Selaa lähdekoodia

Merged PR 111: Integrate master

Merge master to rtmaster, fix missing module shader flags for lib target.
Tex Riddell 7 vuotta sitten
vanhempi
commit
8b4bc1c7c7
100 muutettua tiedostoa jossa 3104 lisäystä ja 1182 poistoa
  1. 78 0
      .travis.yml
  2. 1 1
      CMakeLists.txt
  3. 3 0
      README.md
  4. 148 0
      docs/DxcOnUnix.rst
  5. 29 9
      docs/SPIR-V.rst
  6. 1 1
      external/SPIRV-Headers
  7. 1 1
      external/SPIRV-Tools
  8. 0 2
      include/dxc/Support/Global.h
  9. 2 0
      include/dxc/Support/HLSLOptions.h
  10. 3 1
      include/dxc/Support/HLSLOptions.td
  11. 19 0
      include/dxc/Support/Unicode.h
  12. 472 6
      include/dxc/Support/WinAdapter.h
  13. 70 0
      include/dxc/Support/WinFunctions.h
  14. 56 0
      include/dxc/Support/WinIncludes.h
  15. 25 20
      include/dxc/Support/dxcapi.use.h
  16. 62 10
      include/dxc/dxcapi.h
  17. 13 3
      include/dxc/dxcisense.h
  18. 8 1
      include/dxc/dxctools.h
  19. 8 0
      include/llvm/Analysis/TargetLibraryInfo.def
  20. 4 1
      include/llvm/PassRegistry.h
  21. 8 0
      include/llvm/Support/MSFileSystem.h
  22. 3 3
      include/llvm/Support/Mutex.h
  23. 4 4
      lib/Analysis/TargetLibraryInfo.cpp
  24. 2 0
      lib/DxcSupport/CMakeLists.txt
  25. 14 16
      lib/DxcSupport/FileIOHelper.cpp
  26. 21 0
      lib/DxcSupport/HLSLOptions.cpp
  27. 82 0
      lib/DxcSupport/Unicode.cpp
  28. 59 0
      lib/DxcSupport/WinAdapter.cpp
  29. 337 0
      lib/DxcSupport/WinFunctions.cpp
  30. 8 1
      lib/DxcSupport/dxcapi.use.cpp
  31. 8 13
      lib/DxcSupport/dxcmem.cpp
  32. 4 4
      lib/HLSL/DxilContainerAssembler.cpp
  33. 10 0
      lib/HLSL/DxilContainerReflection.cpp
  34. 2 0
      lib/HLSL/DxilLegalizeSampleOffsetPass.cpp
  35. 1 0
      lib/HLSL/DxilMetadataHelper.cpp
  36. 5 6
      lib/HLSL/DxilPreparePasses.cpp
  37. 1 0
      lib/HLSL/DxilRootSignature.cpp
  38. 31 7
      lib/IR/PassRegistry.cpp
  39. 197 0
      lib/MSSupport/MSFileSystemImpl.cpp
  40. 2 1
      lib/Support/CMakeLists.txt
  41. 3 3
      lib/Support/ErrorHandling.cpp
  42. 34 0
      lib/Support/MSFileSystemBasic.cpp
  43. 1 0
      lib/Support/MemoryBuffer.cpp
  44. 93 4
      lib/Support/Unix/Path.inc
  45. 1 1
      lib/Support/Unix/Process.inc
  46. 13 0
      lib/Support/assert.cpp
  47. 4 1
      lib/Support/regerror.c
  48. 3 3
      lib/Support/regex_impl.h
  49. 2 0
      lib/Transforms/IPO/FunctionAttrs.cpp
  50. 7 1
      tools/CMakeLists.txt
  51. 1 0
      tools/clang/include/clang/AST/HlslTypes.h
  52. 6 0
      tools/clang/include/clang/Basic/Attr.td
  53. 1 0
      tools/clang/include/clang/Basic/TokenKinds.def
  54. 12 0
      tools/clang/include/clang/Basic/TokenKinds.h
  55. 2 0
      tools/clang/include/clang/Frontend/FrontendActions.h
  56. 2 1
      tools/clang/include/clang/SPIRV/EmitSPIRVOptions.h
  57. 7 552
      tools/clang/include/clang/SPIRV/InstBuilder.h
  58. 6 0
      tools/clang/include/clang/SPIRV/ModuleBuilder.h
  59. 6 0
      tools/clang/include/clang/SPIRV/Structure.h
  60. 5 2
      tools/clang/include/clang/SPIRV/Type.h
  61. 1 1
      tools/clang/lib/AST/ItaniumMangle.cpp
  62. 8 1
      tools/clang/lib/Frontend/CompilerInvocation.cpp
  63. 1 2
      tools/clang/lib/Frontend/FrontendActions.cpp
  64. 4 0
      tools/clang/lib/Parse/HLSLRootSignature.cpp
  65. 43 6
      tools/clang/lib/Parse/ParseDecl.cpp
  66. 23 5
      tools/clang/lib/Parse/ParseExpr.cpp
  67. 19 0
      tools/clang/lib/Parse/ParseStmt.cpp
  68. 16 3
      tools/clang/lib/Parse/ParseTentative.cpp
  69. 27 6
      tools/clang/lib/SPIRV/DeclResultIdMapper.cpp
  70. 7 3
      tools/clang/lib/SPIRV/DeclResultIdMapper.h
  71. 266 342
      tools/clang/lib/SPIRV/InstBuilderAuto.cpp
  72. 30 1
      tools/clang/lib/SPIRV/InstBuilderManual.cpp
  73. 9 48
      tools/clang/lib/SPIRV/ModuleBuilder.cpp
  74. 138 37
      tools/clang/lib/SPIRV/SPIRVEmitter.cpp
  75. 14 3
      tools/clang/lib/SPIRV/SPIRVEmitter.h
  76. 38 1
      tools/clang/lib/SPIRV/Structure.cpp
  77. 7 5
      tools/clang/lib/SPIRV/Type.cpp
  78. 102 20
      tools/clang/lib/SPIRV/TypeTranslator.cpp
  79. 8 1
      tools/clang/lib/SPIRV/TypeTranslator.h
  80. 28 0
      tools/clang/lib/Sema/SemaHLSL.cpp
  81. 11 0
      tools/clang/test/CodeGenHLSL/quick-test/center_kwd.hlsl
  82. 13 0
      tools/clang/test/CodeGenHLSL/quick-test/matrix_return_sub2.hlsl
  83. 11 0
      tools/clang/test/CodeGenHLSL/quick-test/min10float.hlsl
  84. 21 0
      tools/clang/test/CodeGenHLSL/quick-test/min10float_to_float.hlsl
  85. 11 0
      tools/clang/test/CodeGenHLSL/quick-test/min12int.hlsl
  86. 21 0
      tools/clang/test/CodeGenHLSL/quick-test/min12int_to_int.hlsl
  87. 12 0
      tools/clang/test/CodeGenHLSL/quick-test/sample-offset-imm-test01.hlsl
  88. 14 0
      tools/clang/test/CodeGenHLSL/quick-test/sample-offset-imm-test02.hlsl
  89. 18 0
      tools/clang/test/CodeGenHLSL/quick-test/sample-offset-imm-test03.hlsl
  90. 12 0
      tools/clang/test/CodeGenHLSL/quick-test/sample-offset-imm-test04.hlsl
  91. 49 0
      tools/clang/test/CodeGenHLSL/quick-test/sample_kwd.hlsl
  92. 0 3
      tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv
  93. 0 3
      tools/clang/test/CodeGenSPIRV/bezier.hull.hlsl2spv
  94. 9 7
      tools/clang/test/CodeGenSPIRV/empty-struct-interface.vs.hlsl2spv
  95. 1 1
      tools/clang/test/CodeGenSPIRV/hs.pcf.primitive-id.1.hlsl
  96. 1 1
      tools/clang/test/CodeGenSPIRV/hs.pcf.view-id.1.hlsl
  97. 19 0
      tools/clang/test/CodeGenSPIRV/intrinsics.interlocked-methods.error.hlsl
  98. 33 0
      tools/clang/test/CodeGenSPIRV/op.buffer.access.hlsl
  99. 29 3
      tools/clang/test/CodeGenSPIRV/op.struct.access.hlsl
  100. 19 0
      tools/clang/test/CodeGenSPIRV/op.texture.access.hlsl

+ 78 - 0
.travis.yml

@@ -0,0 +1,78 @@
+# Linux Build Configuration for Travis
+
+language: cpp
+
+os:
+  - linux
+  - osx
+
+# Use Ubuntu 14.04 LTS (Trusty) as the Linux testing environment.
+sudo: required
+dist: trusty
+
+env:
+  - DXC_BUILD_TYPE=Release
+  - DXC_BUILD_TYPE=Debug
+
+compiler:
+  - clang
+
+matrix:
+  include:
+    - os: linux
+      compiler: gcc
+      addons:
+        apt:
+          sources: ubuntu-toolchain-r-test
+          packages: ninja-build g++-5
+      env: DXC_BUILD_TYPE=Debug
+    - os: linux
+      compiler: gcc
+      addons:
+        apt:
+          sources: ubuntu-toolchain-r-test
+          packages: ninja-build g++-5
+      env: DXC_BUILD_TYPE=Release
+  allow_failures:
+    - os: linux
+    - os: osx
+
+cache:
+  apt: true
+
+git:
+  depth: 1
+
+branches:
+  only:
+    - master
+
+addons:
+  apt:
+    packages:
+      - ninja-build
+
+before_install:
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install ninja; fi
+
+before_script:
+  - git submodule update --init
+  - if [ ${CC} = gcc ]; then CC=gcc-5; CXX=g++-5; fi
+  - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ulimit -Sn 1024; fi
+
+script:
+  - mkdir build && cd build
+  - cmake .. -GNinja
+      $(cat ../utils/cmake-predefined-config-params)
+      -DSPIRV_BUILD_TESTS=ON
+      -DCMAKE_BUILD_TYPE=${DXC_BUILD_TYPE}
+      -DCMAKE_C_COMPILER=${CC} -DCMAKE_CXX_COMPILER=${CXX}
+  - ninja
+  - ./bin/dxc --help
+  - ./bin/dxc -T ps_6_0 ../tools/clang/test/CodeGenSPIRV/passthru-ps.hlsl2spv
+  - ./bin/dxc -T ps_6_0 -Fo passthru-ps.dxil ../tools/clang/test/CodeGenSPIRV/passthru-ps.hlsl2spv
+  - cmp passthru-ps.dxil ../tools/clang/test/CodeGenSPIRV/passthru-ps.${DXC_BUILD_TYPE}.dxil
+  - ./bin/dxc -T ps_6_0 -Fo passthru-ps.spv ../tools/clang/test/CodeGenSPIRV/passthru-ps.hlsl2spv -spirv
+  - cmp passthru-ps.spv ../tools/clang/test/CodeGenSPIRV/passthru-ps.spv
+  - ./bin/clang-spirv-tests --spirv-test-root ../tools/clang/test/CodeGenSPIRV/
+  - ./bin/clang-hlsl-tests --HlslDataDir $PWD/../tools/clang/test/HLSL/

+ 1 - 1
CMakeLists.txt

@@ -103,10 +103,10 @@ option(SPIRV_BUILD_TESTS "Build targets for the SPIR-V unit tests." OFF)
 # Enable SPIR-V CodeGen for Linux by default.
 # Enable SPIR-V CodeGen for Linux by default.
 if(NOT WIN32)
 if(NOT WIN32)
   set(ENABLE_SPIRV_CODEGEN ON)
   set(ENABLE_SPIRV_CODEGEN ON)
-  set(SPIRV_BUILD_TESTS ON)
 endif()
 endif()
 
 
 if (${SPIRV_BUILD_TESTS})
 if (${SPIRV_BUILD_TESTS})
+  enable_testing()
   set(ENABLE_SPIRV_CODEGEN ON)
   set(ENABLE_SPIRV_CODEGEN ON)
 endif()
 endif()
 if (${ENABLE_SPIRV_CODEGEN})
 if (${ENABLE_SPIRV_CODEGEN})

+ 3 - 0
README.md

@@ -1,6 +1,7 @@
 # DirectX Shader Compiler
 # DirectX Shader Compiler
 
 
 [![Build status](https://ci.appveyor.com/api/projects/status/oaf66n7w30xbrg38/branch/master?svg=true)](https://ci.appveyor.com/project/antiagainst/directxshadercompiler/branch/master)
 [![Build status](https://ci.appveyor.com/api/projects/status/oaf66n7w30xbrg38/branch/master?svg=true)](https://ci.appveyor.com/project/antiagainst/directxshadercompiler/branch/master)
+[![Build Status](https://travis-ci.org/Microsoft/DirectXShaderCompiler.svg?branch=master)](https://travis-ci.org/Microsoft/DirectXShaderCompiler)
 
 
 The DirectX Shader Compiler project includes a compiler and related tools used to compile High-Level Shader Language (HLSL) programs into DirectX Intermediate Language (DXIL) representation. Applications that make use of DirectX for graphics, games, and computation can use it to generate shader programs.
 The DirectX Shader Compiler project includes a compiler and related tools used to compile High-Level Shader Language (HLSL) programs into DirectX Intermediate Language (DXIL) representation. Applications that make use of DirectX for graphics, games, and computation can use it to generate shader programs.
 
 
@@ -30,6 +31,8 @@ As an example of community contribution, this project can also target the [SPIR-
 
 
 Note: Instead of building manually, you can download the artifacts built by Appveyor for the latest master branch at [here](https://ci.appveyor.com/project/antiagainst/directxshadercompiler/branch/master/artifacts).
 Note: Instead of building manually, you can download the artifacts built by Appveyor for the latest master branch at [here](https://ci.appveyor.com/project/antiagainst/directxshadercompiler/branch/master/artifacts).
 
 
+Note: If you intend to build from sources on Linux/macOS, follow [these instructions](docs/DxcOnUnix.rst).
+
 Before you build, you will need to have some additional software installed. This is the most straightforward path - see [Building Sources](https://github.com/Microsoft/DirectXShaderCompiler/wiki/Building-Sources) on the Wiki for more options, including Visual Studio 2015 and Ninja support.
 Before you build, you will need to have some additional software installed. This is the most straightforward path - see [Building Sources](https://github.com/Microsoft/DirectXShaderCompiler/wiki/Building-Sources) on the Wiki for more options, including Visual Studio 2015 and Ninja support.
 
 
 * [Git](http://git-scm.com/downloads).
 * [Git](http://git-scm.com/downloads).

+ 148 - 0
docs/DxcOnUnix.rst

@@ -0,0 +1,148 @@
+======================================
+DirectXShaderCompiler on Linux & macOS
+======================================
+
+.. contents::
+   :local:
+   :depth: 3
+
+Introduction
+============
+
+DirectXShaderCompiler (DXC) is based on LLVM/Clang, which is originally
+cross-platform. However, to support HLSL, certain Windows specific techniques
+(like COM, SAL, etc.) are introduced to solve technical issues on the Windows
+platform, which also makes DXC not compilable/runnable on non-Windows platforms.
+
+Upon `several <https://github.com/Microsoft/DirectXShaderCompiler/issues/1082>`_
+`requests <https://github.com/Microsoft/DirectXShaderCompiler/issues/1236>`_
+from the community, we have started the effort to enable compilation and running
+of DXC on non-Windows platforms (Linux and macOS).
+
+Current Status
+==============
+
+Up and Running
+--------------
+We have currently reached the point where we can successfully build and run DXC
+on Linux and macOS. Code generation works for both DXIL and SPIR-V, and we are
+also able to fully run the SPIR-V CodeGen test suite on these platforms.
+
+*Note: This work is currently in experimental phase. How we implement certain
+things for Unix platforms may change without considering backward portability.*
+
+Known Limitations
+-----------------
+
+The following targets are currently disabled for non-Windows platforms and this
+is an area where further contributions can be made:
+
+* d3dcomp
+* dxa
+* dxopt
+* dxl
+* dxr
+* dxv
+* dxlib-sample
+
+Moreover, since the HLSL CodeGen tests were originally written with Windows in
+mind, they require the Windows-specific `TAEF Framework <https://docs.microsoft.com/en-us/windows-hardware/drivers/taef/>`_
+to run. Therefore we are not able to compile/run these tests on non-Windows
+platforms. Note that it is only the testing infrastructure that has this
+limitation, and DXIL CodeGen works as expected by running the DXC executable.
+
+Known Issues
+------------
+- Running the SPIR-V CodeGen tests results in opening a large number of file
+  descriptors, and if the OS limitation on the number of FDs allowed to be opened
+  by a process is low, it will cause test failures. We have not seen this as an
+  issue on Windows and Linux. On macOS we currently increase the allowed limit to
+  get around the problem for the time being.
+
+- The version number of the shared library is currently stuck at 3.7. We need to
+  fix this once a certain versioning scheme is in place.
+
+Building and Using
+==================
+
+Build Requirements
+------------------
+Please make sure you have the following resources before building:
+
+- `Git <https://git-scm.com/downloads>`_
+- `Python <https://www.python.org/downloads/>`_. Version 2.7.x is required, 3.x might work but it's not officially supported. 
+- `Ninja <https://github.com/ninja-build/ninja/releases>`_ (*Optional* CMake generator)
+- Either of gcc/g++ or clang/clang++ compilers. Minimum supported version:
+
+  - `GCC <https://gcc.gnu.org/releases.html>`_ version 5.5 or higher.
+  - `Clang <http://releases.llvm.org/>`_ version 3.8 or higher.
+
+
+Building DXC
+------------
+You can follow these steps to build DXC on Linux/macOS:
+
+.. code:: sh
+
+  cd <dxc-build-dir>
+  cmake <dxc-src-dir> -GNinja -DCMAKE_BUILD_TYPE=Release $(cat <dxc-src-dir>/utils/cmake-predefined-config-params)
+  ninja
+
+Note that ``cmake-predefined-config-params`` file contains several cmake
+configurations that are needed for successful compilation. You can further
+customize your build by adding configurations at the end of the cmake command
+above.
+
+For instance, you can use
+
+``-DCMAKE_C_COMPILER=gcc -DCMAKE_CXX_COMPILER=g++``
+
+or
+
+``-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++``
+
+to choose your desired C/C++ compiler.
+
+You should now have the dxc executable located at ``<dxc-build-dir>/bin/dxc``.
+And you should be able to successfully run commands as you would on Windows, e.g:
+
+.. code:: sh
+
+  ./bin/dxc -help
+  ./bin/dxc -T <target> -E <entry-point-name> <input-hlsl-file>
+
+Note that you cannot use slashes (``/``) for specifying command line options as
+you would on Windows. You should use dashes as per usual Unix style.
+
+Building and Running HLSL CodeGen Tests
+---------------------------------------
+As described in the `Known Limitations`_ section, we can not run these tests on
+non-Windows platforms due to their dependency on TAEF.
+
+Building and Running SPIR-V CodeGen Tests
+-----------------------------------------
+The SPIR-V CodeGen tests were written within the googletest framework, and can
+therefore be built and run on non-Windows platforms.
+
+You can follow these steps to build and run the SPIR-V CodeGen tests:
+
+.. code:: sh
+
+  cd <dxc-build-dir>
+  # Use SPIRV_BUILD_TESTS flag to enable building these tests.
+  cmake <dxc-src-dir> \
+    $(cat <dxc-src-dir>/utils/cmake-predefined-config-params) \
+    -DCMAKE_BUILD_TYPE=Release -DSPIRV_BUILD_TESTS=ON \
+    -GNinja
+  # Build all targets. Includes 'dxc' and tests.
+  ninja
+  # Run all tests
+  ctest
+
+
+As described in the `Known Issues`_ section above, you currently need to
+increase the maximum per-process open files on macOS using
+``ulimit -Sn 1024`` before running the tests on that platform.
+
+TODO: Add more information about Linux implementation details.
+

+ 29 - 9
docs/SPIR-V.rst

@@ -248,6 +248,9 @@ The namespace ``vk`` will be used for all Vulkan attributes:
 - ``push_constant``: For marking a variable as the push constant block. Allowed
 - ``push_constant``: For marking a variable as the push constant block. Allowed
   on global variables of struct type. At most one variable can be marked as
   on global variables of struct type. At most one variable can be marked as
   ``push_constant`` in a shader.
   ``push_constant`` in a shader.
+- ``offset(X)``: For manually layout struct members. Annotating a struct member
+  with this attribute will force the compiler to put the member at offset ``X``
+  w.r.t. the beginning of the struct. Only allowed on struct members.
 - ``constant_id(X)``: For marking a global constant as a specialization constant.
 - ``constant_id(X)``: For marking a global constant as a specialization constant.
   Allowed on global variables of boolean/integer/float types.
   Allowed on global variables of boolean/integer/float types.
 - ``input_attachment_index(X)``: To associate the Xth entry in the input pass
 - ``input_attachment_index(X)``: To associate the Xth entry in the input pass
@@ -713,6 +716,21 @@ We will have the following offsets for each member:
 ``g_float2_2``   160    160    176    112    88    128
 ``g_float2_2``   160    160    176    112    88    128
 ============== ====== ====== ====== ====== ====== ======
 ============== ====== ====== ====== ====== ====== ======
 
 
+If the above layout rules do not satisfy your needs and you want to manually
+control the layout of struct members, you can use either
+
+* The native HLSL ``:packoffset()`` attribute: only available for cbuffers; or
+* The Vulkan-specific ``[[vk::offset()]]`` attribute: applies to all resources.
+
+``[[vk::offset]]`` overrules ``:packoffset``. Attaching ``[[vk::offset]]``
+to a struct memeber affects all variables of the struct type in question. So
+sharing the same struct definition having ``[[vk::offset]]`` annotations means
+also sharing the layout.
+
+These attributes give great flexibility but also responsibility to the
+developer; the compiler will just take in what is specified in the source code
+and emit it to SPIR-V with no error checking.
+
 ``cbuffer`` and ``ConstantBuffer``
 ``cbuffer`` and ``ConstantBuffer``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 
@@ -2262,8 +2280,8 @@ parameter is attached to the instruction as the parameter to the ``Lod`` SPIR-V
 image operands. The ``position`` parameter are used as the coordinate to the
 image operands. The ``position`` parameter are used as the coordinate to the
 instruction directly.
 instruction directly.
 
 
-``.CalculateLevelOfDetail()``
-+++++++++++++++++++++++++++++
+``.CalculateLevelOfDetail()`` and ``.CalculateLevelOfDetailUnclamped()``
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
 
 Not available to ``Texture2DMS`` and ``Texture2DMSArray``.
 Not available to ``Texture2DMS`` and ``Texture2DMSArray``.
 
 
@@ -2272,7 +2290,7 @@ instruction is used for translation. An ``OpSampledImage`` is created based on
 the ``SamplerState`` passed to the function. The resulting sampled image and
 the ``SamplerState`` passed to the function. The resulting sampled image and
 the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
 the coordinate passed to the function are used to invoke ``OpImageQueryLod``.
 The result of ``OpImageQueryLod`` is a ``float2``. The first element contains
 The result of ``OpImageQueryLod`` is a ``float2``. The first element contains
-the mipmap array layer.
+the mipmap array layer. The second element contains the unclamped level of detail.
 
 
 ``Texture1D``
 ``Texture1D``
 ~~~~~~~~~~~~~
 ~~~~~~~~~~~~~
@@ -2698,9 +2716,14 @@ codegen for Vulkan:
 - ``-fvk-use-gl-layout``: Uses strict OpenGL ``std140``/``std430``
 - ``-fvk-use-gl-layout``: Uses strict OpenGL ``std140``/``std430``
   layout rules for resources.
   layout rules for resources.
 - ``-fvk-use-dx-layout``: Uses DirectX layout rules for resources.
 - ``-fvk-use-dx-layout``: Uses DirectX layout rules for resources.
-- ``-fvk-invert-y``: Inverts SV_Position.y before writing to stage output.
-  Used to accommodate the difference between Vulkan's coordinate system and
-  DirectX's. Only allowed in VS/DS/GS.
+- ``-fvk-invert-y``: Negates (additively inverts) SV_Position.y before writing
+  to stage output. Used to accommodate the difference between Vulkan's
+  coordinate system and DirectX's. Only allowed in VS/DS/GS.
+- ``-fvk-use-dx-position-w``: Reciprocates (multiplicatively inverts)
+  SV_Position.w after reading from stage input. Used to accommodate the
+  difference between Vulkan DirectX: the w component of SV_Position in PS is
+  stored as 1/w in Vulkan. Only recognized in PS; applying to other stages
+  is no-op.
 - ``-fvk-stage-io-order={alpha|decl}``: Assigns the stage input/output variable
 - ``-fvk-stage-io-order={alpha|decl}``: Assigns the stage input/output variable
   location number according to alphabetical order or declaration order. See
   location number according to alphabetical order or declaration order. See
   `HLSL semantic and Vulkan Location`_ for more details.
   `HLSL semantic and Vulkan Location`_ for more details.
@@ -2735,9 +2758,6 @@ either because of no Vulkan equivalents at the moment, or because of deprecation
 * ``.GatherCmpGreen()``, ``.GatherCmpBlue()``, ``.GatherCmpAlpha()`` intrinsic
 * ``.GatherCmpGreen()``, ``.GatherCmpBlue()``, ``.GatherCmpAlpha()`` intrinsic
   method: no Vulkan equivalent. (SPIR-V ``OpImageDrefGather`` instruction does
   method: no Vulkan equivalent. (SPIR-V ``OpImageDrefGather`` instruction does
   not take component as input.) The compiler will emit an error.
   not take component as input.) The compiler will emit an error.
-* ``.CalculateLevelOfDetailUnclamped()`` intrinsic method: no Vulkan equivalent.
-  (SPIR-V ``OpImageQueryLod`` returns the clamped LOD in Vulkan.) The compiler
-  will emit an error.
 * Since ``StructuredBuffer``, ``RWStructuredBuffer``, ``ByteAddressBuffer``, and
 * Since ``StructuredBuffer``, ``RWStructuredBuffer``, ``ByteAddressBuffer``, and
   ``RWByteAddressBuffer`` are not represented as image types in SPIR-V, using the
   ``RWByteAddressBuffer`` are not represented as image types in SPIR-V, using the
   output unsigned integer ``status`` argument in their ``Load*`` methods is not
   output unsigned integer ``status`` argument in their ``Load*`` methods is not

+ 1 - 1
external/SPIRV-Headers

@@ -1 +1 @@
-Subproject commit 87a720a5a7ba8fb2ede50fef57e5d936e5e45e97
+Subproject commit ff684ffc6a35d2a58f0f63108877d0064ea33feb

+ 1 - 1
external/SPIRV-Tools

@@ -1 +1 @@
-Subproject commit f80696eaf64298ab60e545086a6a5ab8be2c5ac1
+Subproject commit 208921efe813b457ee909693a270233fbb012987

+ 0 - 2
include/dxc/Support/Global.h

@@ -60,8 +60,6 @@ IMalloc *DxcSwapThreadMallocOrDefault(IMalloc *pMalloc, IMalloc **ppPrior) throw
 
 
 // Used to retrieve the current invocation's allocator or perform an alloc/free/realloc.
 // Used to retrieve the current invocation's allocator or perform an alloc/free/realloc.
 IMalloc *DxcGetThreadMallocNoRef() throw();
 IMalloc *DxcGetThreadMallocNoRef() throw();
-_Ret_maybenull_ _Post_writable_byte_size_(nBytes) void *DxcThreadAlloc(size_t nBytes) throw();
-void DxcThreadFree(void *) throw();
 
 
 struct DxcThreadMalloc {
 struct DxcThreadMalloc {
   DxcThreadMalloc(IMalloc *pMallocOrNull) throw() {
   DxcThreadMalloc(IMalloc *pMallocOrNull) throw() {

+ 2 - 0
include/dxc/Support/HLSLOptions.h

@@ -165,6 +165,7 @@ public:
 #ifdef ENABLE_SPIRV_CODEGEN
 #ifdef ENABLE_SPIRV_CODEGEN
   bool GenSPIRV;                           // OPT_spirv
   bool GenSPIRV;                           // OPT_spirv
   bool VkInvertY;                          // OPT_fvk_invert_y
   bool VkInvertY;                          // OPT_fvk_invert_y
+  bool VkInvertW;                          // OPT_fvk_use_dx_position_w
   bool VkUseGlLayout;                      // OPT_fvk_use_gl_layout
   bool VkUseGlLayout;                      // OPT_fvk_use_gl_layout
   bool VkUseDxLayout;                      // OPT_fvk_use_dx_layout
   bool VkUseDxLayout;                      // OPT_fvk_use_dx_layout
   bool SpvEnableReflect;                   // OPT_fspv_reflect
   bool SpvEnableReflect;                   // OPT_fspv_reflect
@@ -189,6 +190,7 @@ public:
 
 
   MainArgs() = default;
   MainArgs() = default;
   MainArgs(int argc, const wchar_t **argv, int skipArgCount = 1);
   MainArgs(int argc, const wchar_t **argv, int skipArgCount = 1);
+  MainArgs(int argc, const char **argv, int skipArgCount = 1);
   MainArgs(llvm::ArrayRef<llvm::StringRef> args);
   MainArgs(llvm::ArrayRef<llvm::StringRef> args);
   MainArgs& operator=(const MainArgs &other);
   MainArgs& operator=(const MainArgs &other);
   llvm::ArrayRef<const char *> getArrayRef() const {
   llvm::ArrayRef<const char *> getArrayRef() const {

+ 3 - 1
include/dxc/Support/HLSLOptions.td

@@ -253,7 +253,9 @@ def fvk_s_shift : MultiArg<["-"], "fvk-s-shift", 2>, MetaVarName<"<shift> <space
 def fvk_u_shift : MultiArg<["-"], "fvk-u-shift", 2>, MetaVarName<"<shift> <space>">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
 def fvk_u_shift : MultiArg<["-"], "fvk-u-shift", 2>, MetaVarName<"<shift> <space>">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
   HelpText<"Specify Vulkan binding number shift for u-type register">;
   HelpText<"Specify Vulkan binding number shift for u-type register">;
 def fvk_invert_y: Flag<["-"], "fvk-invert-y">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
 def fvk_invert_y: Flag<["-"], "fvk-invert-y">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
-  HelpText<"Invert SV_Position.y in VS/DS/GS to accommodate Vulkan's coordinate system">;
+  HelpText<"Negate SV_Position.y before writing to stage output in VS/DS/GS to accommodate Vulkan's coordinate system">;
+def fvk_use_dx_position_w: Flag<["-"], "fvk-use-dx-position-w">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
+  HelpText<"Reciprocate SV_Position.w after reading from stage input in PS to accommodate the difference between Vulkan and DirectX">;
 def fvk_use_gl_layout: Flag<["-"], "fvk-use-gl-layout">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
 def fvk_use_gl_layout: Flag<["-"], "fvk-use-gl-layout">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
   HelpText<"Use strict OpenGL std140/std430 memory layout for Vulkan resources">;
   HelpText<"Use strict OpenGL std140/std430 memory layout for Vulkan resources">;
 def fvk_use_dx_layout: Flag<["-"], "fvk-use-dx-layout">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,
 def fvk_use_dx_layout: Flag<["-"], "fvk-use-dx-layout">, Group<spirv_Group>, Flags<[CoreOption, DriverOption]>,

+ 19 - 0
include/dxc/Support/Unicode.h

@@ -12,7 +12,26 @@
 #pragma once
 #pragma once
 
 
 #include <string>
 #include <string>
+
+#ifdef _WIN32
 #include <specstrings.h>
 #include <specstrings.h>
+#else
+// MultiByteToWideChar which is a Windows-specific method.
+// This is a very simplistic implementation for non-Windows platforms. This
+// implementation completely ignores CodePage and dwFlags.
+int MultiByteToWideChar(uint32_t CodePage, uint32_t dwFlags,
+                        const char *lpMultiByteStr, int cbMultiByte,
+                        wchar_t *lpWideCharStr, int cchWideChar);
+
+// WideCharToMultiByte is a Windows-specific method.
+// This is a very simplistic implementation for non-Windows platforms. This
+// implementation completely ignores CodePage and dwFlags.
+int WideCharToMultiByte(uint32_t CodePage, uint32_t dwFlags,
+                        const wchar_t *lpWideCharStr, int cchWideChar,
+                        char *lpMultiByteStr, int cbMultiByte,
+                        const char *lpDefaultChar = nullptr,
+                        bool *lpUsedDefaultChar = nullptr);
+#endif // _WIN32
 
 
 namespace Unicode
 namespace Unicode
 {
 {

+ 472 - 6
include/dxc/Support/WinAdapter.h

@@ -32,6 +32,7 @@
 #include <typeinfo>
 #include <typeinfo>
 #include <vector>
 #include <vector>
 #endif // __cplusplus
 #endif // __cplusplus
+#include <execinfo.h>
 
 
 //===----------------------------------------------------------------------===//
 //===----------------------------------------------------------------------===//
 //
 //
@@ -41,11 +42,18 @@
 #define C_ASSERT(expr) static_assert((expr), "")
 #define C_ASSERT(expr) static_assert((expr), "")
 #define ATLASSERT assert
 #define ATLASSERT assert
 
 
+#define CoTaskMemAlloc malloc
+#define CoTaskMemFree free
+
+#define SysFreeString free
+#define SysAllocStringLen(ptr, size) (wchar_t*)realloc(ptr, (size + 1)*sizeof(wchar_t))
+
 #define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
 #define ARRAYSIZE(array) (sizeof(array) / sizeof(array[0]))
 
 
 #define _countof(a) (sizeof(a) / sizeof(*(a)))
 #define _countof(a) (sizeof(a) / sizeof(*(a)))
 
 
 #define __declspec(x)
 #define __declspec(x)
+#define DECLSPEC_SELECTANY
 
 
 #define uuid(id)
 #define uuid(id)
 
 
@@ -94,13 +102,17 @@
 
 
 // Map these errors to equivalent errnos.
 // Map these errors to equivalent errnos.
 #define ERROR_SUCCESS 0L
 #define ERROR_SUCCESS 0L
-#define ERROR_OUT_OF_STRUCTURES ENOMEM
-#define ERROR_UNHANDLED_EXCEPTION EINTR
-#define ERROR_NOT_FOUND ENOTSUP
-#define ERROR_NOT_CAPABLE EPERM
+#define ERROR_ARITHMETIC_OVERFLOW EOVERFLOW
 #define ERROR_FILE_NOT_FOUND ENOENT
 #define ERROR_FILE_NOT_FOUND ENOENT
+#define ERROR_FUNCTION_NOT_CALLED ENOSYS
 #define ERROR_IO_DEVICE EIO
 #define ERROR_IO_DEVICE EIO
+#define ERROR_INSUFFICIENT_BUFFER ENOBUFS
 #define ERROR_INVALID_HANDLE EBADF
 #define ERROR_INVALID_HANDLE EBADF
+#define ERROR_INVALID_PARAMETER EINVAL
+#define ERROR_OUT_OF_STRUCTURES ENOMEM
+#define ERROR_NOT_CAPABLE EPERM
+#define ERROR_NOT_FOUND ENOTSUP
+#define ERROR_UNHANDLED_EXCEPTION EINTR
 
 
 // Used by HRESULT <--> WIN32 error code conversion
 // Used by HRESULT <--> WIN32 error code conversion
 #define SEVERITY_ERROR 1
 #define SEVERITY_ERROR 1
@@ -137,21 +149,47 @@
 #define STREAM_SEEK_CUR 1
 #define STREAM_SEEK_CUR 1
 #define STREAM_SEEK_END 2
 #define STREAM_SEEK_END 2
 
 
-#define HEAP_NO_SERIALIZE 1
+#define HEAP_NO_SERIALIZE 0x1
+#define HEAP_ZERO_MEMORY 0x8
 
 
 #define MB_ERR_INVALID_CHARS 0x00000008 // error for invalid chars
 #define MB_ERR_INVALID_CHARS 0x00000008 // error for invalid chars
 
 
+// File IO
+
+#define CREATE_ALWAYS 2
+#define CREATE_NEW 1
+#define OPEN_ALWAYS 4
+#define OPEN_EXISTING 3
+#define TRUNCATE_EXISTING 5
+
+#define FILE_SHARE_DELETE 0x00000004
+#define FILE_SHARE_READ 0x00000001
+#define FILE_SHARE_WRITE 0x00000002
+
+#define GENERIC_READ 0x80000000
+#define GENERIC_WRITE 0x40000000
+
 #define _atoi64 atoll
 #define _atoi64 atoll
 #define sprintf_s snprintf
 #define sprintf_s snprintf
 #define _strdup strdup
 #define _strdup strdup
+
 #define vsprintf_s vsprintf
 #define vsprintf_s vsprintf
 #define strcat_s strcat
 #define strcat_s strcat
+#define strcpy_s(dst, n, src) strncpy(dst, src, n)
+#define _vscwprintf vwprintf
+#define vswprintf_s vswprintf
+#define swprintf_s swprintf
+
+#define StringCchCopyW(dst, n, src) wcsncpy(dst, src, n)
 
 
 #define OutputDebugStringW(msg) fputws(msg, stderr)
 #define OutputDebugStringW(msg) fputws(msg, stderr)
 
 
 #define OutputDebugStringA(msg) fputs(msg, stderr)
 #define OutputDebugStringA(msg) fputs(msg, stderr)
 #define OutputDebugFormatA(...) fprintf(stderr, __VA_ARGS__)
 #define OutputDebugFormatA(...) fprintf(stderr, __VA_ARGS__)
 
 
+#define CaptureStackBackTrace(FramesToSkip, FramesToCapture, BackTrace, BackTraceHash)\
+  backtrace(BackTrace, FramesToCapture)
+
 // Event Tracing for Windows (ETW) provides application programmers the ability
 // Event Tracing for Windows (ETW) provides application programmers the ability
 // to start and stop event tracing sessions, instrument an application to
 // to start and stop event tracing sessions, instrument an application to
 // provide trace events, and consume trace events.
 // provide trace events, and consume trace events.
@@ -216,6 +254,7 @@
 
 
 #define _Out_
 #define _Out_
 #define _Out_bytecap_(nbytes)
 #define _Out_bytecap_(nbytes)
+#define _Out_writes_to_(a, b)
 #define _Out_writes_to_opt_(a, b)
 #define _Out_writes_to_opt_(a, b)
 #define _Outptr_
 #define _Outptr_
 #define _Outptr_opt_
 #define _Outptr_opt_
@@ -370,6 +409,22 @@ typedef void *HMODULE;
 #define STD_OUTPUT_HANDLE ((DWORD)-11)
 #define STD_OUTPUT_HANDLE ((DWORD)-11)
 #define STD_ERROR_HANDLE ((DWORD)-12)
 #define STD_ERROR_HANDLE ((DWORD)-12)
 
 
+//===--------------------- ID Types and Macros for COM --------------------===//
+
+struct GUID {
+  uint32_t Data1;
+  uint16_t Data2;
+  uint16_t Data3;
+  uint8_t Data4[8];
+};
+typedef GUID CLSID;
+typedef const GUID &REFGUID;
+typedef const void *REFIID;
+typedef const GUID &REFCLSID;
+
+#define IsEqualIID(a, b) a == b
+#define IsEqualCLSID(a, b) !memcmp(&a, &b, sizeof(GUID))
+
 //===--------------------- Struct Types -----------------------------------===//
 //===--------------------- Struct Types -----------------------------------===//
 
 
 typedef struct _FILETIME {
 typedef struct _FILETIME {
@@ -444,7 +499,418 @@ enum tagSTATFLAG {
   STATFLAG_NOOPEN = 2
   STATFLAG_NOOPEN = 2
 };
 };
 
 
-// TODO: More definitions will be added here.
+//===--------------------- UUID Related Macros ----------------------------===//
+
+// The following macros are defined to facilitate the lack of 'uuid' on Linux.
+#define DECLARE_CROSS_PLATFORM_UUIDOF(T)                                       \
+public:                                                                        \
+  static REFIID uuidof() { return static_cast<REFIID>(&T##_ID); }              \
+                                                                               \
+private:                                                                       \
+  static const char T##_ID;
+
+#define DEFINE_CROSS_PLATFORM_UUIDOF(T) const char T::T##_ID = '\0';
+#define __uuidof(T) T::uuidof()
+#define IID_PPV_ARGS(ppType)                                                   \
+  (**(ppType)).uuidof(), reinterpret_cast<void **>(ppType)
+
+//===--------------------- COM Interfaces ---------------------------------===//
+
+struct IUnknown {
+  virtual HRESULT QueryInterface(REFIID riid, void **ppvObject) = 0;
+  virtual ULONG AddRef();
+  virtual ULONG Release();
+  virtual ~IUnknown();
+  template <class Q> HRESULT QueryInterface(Q **pp) {
+    return QueryInterface(__uuidof(Q), (void **)pp);
+  }
+
+private:
+  std::atomic<unsigned long> m_count;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IUnknown)
+};
+
+struct INoMarshal : public IUnknown {
+  DECLARE_CROSS_PLATFORM_UUIDOF(INoMarshal)
+};
+
+struct IMalloc : public IUnknown {
+  virtual void *Alloc(size_t size);
+  virtual void *Realloc(void *ptr, size_t size);
+  virtual void Free(void *ptr);
+  virtual HRESULT QueryInterface(REFIID riid, void **ppvObject);
+};
+
+struct ISequentialStream : public IUnknown {
+  virtual HRESULT Read(void *pv, ULONG cb, ULONG *pcbRead) = 0;
+  virtual HRESULT Write(const void *pv, ULONG cb, ULONG *pcbWritten) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(ISequentialStream)
+};
+
+struct IStream : public ISequentialStream {
+  virtual HRESULT Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin,
+                       ULARGE_INTEGER *plibNewPosition) = 0;
+  virtual HRESULT SetSize(ULARGE_INTEGER libNewSize) = 0;
+  virtual HRESULT CopyTo(IStream *pstm, ULARGE_INTEGER cb,
+                         ULARGE_INTEGER *pcbRead,
+                         ULARGE_INTEGER *pcbWritten) = 0;
+
+  virtual HRESULT Commit(DWORD grfCommitFlags) = 0;
+
+  virtual HRESULT Revert(void) = 0;
+
+  virtual HRESULT LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+                             DWORD dwLockType) = 0;
+
+  virtual HRESULT UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb,
+                               DWORD dwLockType) = 0;
+
+  virtual HRESULT Stat(STATSTG *pstatstg, DWORD grfStatFlag) = 0;
+
+  virtual HRESULT Clone(IStream **ppstm) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IStream)
+};
+
+//===--------------------- COM Pointer Types ------------------------------===//
+
+class CAllocator {
+public:
+  static void *Reallocate(void *p, size_t nBytes) throw();
+  static void *Allocate(size_t nBytes) throw();
+  static void Free(void *p) throw();
+};
+
+template <class T> class CComPtrBase {
+protected:
+  CComPtrBase() throw() { p = nullptr; }
+  CComPtrBase(T *lp) throw() {
+    p = lp;
+    if (p != nullptr)
+      p->AddRef();
+  }
+  void Swap(CComPtrBase &other) {
+    T *pTemp = p;
+    p = other.p;
+    other.p = pTemp;
+  }
+
+public:
+  ~CComPtrBase() throw() {
+    if (p) {
+      p->Release();
+      p = nullptr;
+    }
+  }
+  operator T *() const throw() { return p; }
+  T &operator*() const { return *p; }
+  T *operator->() const { return p; }
+  T **operator&() throw() {
+    assert(p == nullptr);
+    return &p;
+  }
+  bool operator!() const throw() { return (p == nullptr); }
+  bool operator<(T *pT) const throw() { return p < pT; }
+  bool operator!=(T *pT) const { return !operator==(pT); }
+  bool operator==(T *pT) const throw() { return p == pT; }
+
+  // Release the interface and set to nullptr
+  void Release() throw() {
+    T *pTemp = p;
+    if (pTemp) {
+      p = nullptr;
+      pTemp->Release();
+    }
+  }
+
+  // Attach to an existing interface (does not AddRef)
+  void Attach(T *p2) throw() {
+    if (p) {
+      ULONG ref = p->Release();
+      (void)(ref);
+      // Attaching to the same object only works if duplicate references are
+      // being coalesced.  Otherwise re-attaching will cause the pointer to be
+      // released and may cause a crash on a subsequent dereference.
+      assert(ref != 0 || p2 != p);
+    }
+    p = p2;
+  }
+
+  // Detach the interface (does not Release)
+  T *Detach() throw() {
+    T *pt = p;
+    p = nullptr;
+    return pt;
+  }
+
+  HRESULT CopyTo(T **ppT) throw() {
+    assert(ppT != nullptr);
+    if (ppT == nullptr)
+      return E_POINTER;
+    *ppT = p;
+    if (p)
+      p->AddRef();
+    return S_OK;
+  }
+
+  template <class Q> HRESULT QueryInterface(Q **pp) const throw() {
+    assert(pp != nullptr);
+    return p->QueryInterface(__uuidof(Q), (void **)pp);
+  }
+
+  T *p;
+};
+
+template <class T> class CComPtr : public CComPtrBase<T> {
+public:
+  CComPtr() throw() {}
+  CComPtr(T *lp) throw() : CComPtrBase<T>(lp) {}
+  CComPtr(const CComPtr<T> &lp) throw() : CComPtrBase<T>(lp.p) {}
+  T *operator=(T *lp) throw() {
+    if (*this != lp) {
+      CComPtr(lp).Swap(*this);
+    }
+    return *this;
+  }
+
+  inline bool IsEqualObject(IUnknown *pOther) throw() {
+    if (this->p == nullptr && pOther == nullptr)
+      return true; // They are both NULL objects
+
+    if (this->p == nullptr || pOther == nullptr)
+      return false; // One is NULL the other is not
+
+    CComPtr<IUnknown> punk1;
+    CComPtr<IUnknown> punk2;
+    this->p->QueryInterface(__uuidof(IUnknown), (void **)&punk1);
+    pOther->QueryInterface(__uuidof(IUnknown), (void **)&punk2);
+    return punk1 == punk2;
+  }
+
+  void ComPtrAssign(IUnknown **pp, IUnknown *lp, REFIID riid) {
+    IUnknown *pTemp = *pp; // takes ownership
+    if (lp == nullptr || FAILED(lp->QueryInterface(riid, (void **)pp)))
+      *pp = nullptr;
+    if (pTemp)
+      pTemp->Release();
+  }
+
+  template <typename Q> T *operator=(const CComPtr<Q> &lp) throw() {
+    if (!this->IsEqualObject(lp)) {
+      ComPtrAssign((IUnknown **)&this->p, lp, __uuidof(T));
+    }
+    return *this;
+  }
+
+  T *operator=(const CComPtr<T> &lp) throw() {
+    if (*this != lp) {
+      CComPtr(lp).Swap(*this);
+    }
+    return *this;
+  }
+
+  CComPtr(CComPtr<T> &&lp) throw() : CComPtrBase<T>() { lp.Swap(*this); }
+
+  T *operator=(CComPtr<T> &&lp) throw() {
+    if (*this != lp) {
+      CComPtr(static_cast<CComPtr &&>(lp)).Swap(*this);
+    }
+    return *this;
+  }
+};
+
+template <class T> class CSimpleArray : public std::vector<T> {
+public:
+  bool Add(const T &t) {
+    this->push_back(t);
+    return true;
+  }
+  int GetSize() { return this->size(); }
+  T *GetData() { return this->data(); }
+  void RemoveAll() { this->clear(); }
+};
+
+template <class T, class Allocator = CAllocator> class CHeapPtrBase {
+protected:
+  CHeapPtrBase() throw() : m_pData(NULL) {}
+  CHeapPtrBase(CHeapPtrBase<T, Allocator> &p) throw() {
+    m_pData = p.Detach(); // Transfer ownership
+  }
+  explicit CHeapPtrBase(T *pData) throw() : m_pData(pData) {}
+
+public:
+  ~CHeapPtrBase() throw() { Free(); }
+
+protected:
+  CHeapPtrBase<T, Allocator> &operator=(CHeapPtrBase<T, Allocator> &p) throw() {
+    if (m_pData != p.m_pData)
+      Attach(p.Detach()); // Transfer ownership
+    return *this;
+  }
+
+public:
+  operator T *() const throw() { return m_pData; }
+  T *operator->() const throw() {
+    assert(m_pData != NULL);
+    return m_pData;
+  }
+
+  T **operator&() throw() {
+    assert(m_pData == NULL);
+    return &m_pData;
+  }
+
+  // Allocate a buffer with the given number of bytes
+  bool AllocateBytes(size_t nBytes) throw() {
+    assert(m_pData == NULL);
+    m_pData = static_cast<T *>(Allocator::Allocate(nBytes * sizeof(char)));
+    if (m_pData == NULL)
+      return false;
+
+    return true;
+  }
+
+  // Attach to an existing pointer (takes ownership)
+  void Attach(T *pData) throw() {
+    Allocator::Free(m_pData);
+    m_pData = pData;
+  }
+
+  // Detach the pointer (releases ownership)
+  T *Detach() throw() {
+    T *pTemp = m_pData;
+    m_pData = NULL;
+    return pTemp;
+  }
+
+  // Free the memory pointed to, and set the pointer to NULL
+  void Free() throw() {
+    Allocator::Free(m_pData);
+    m_pData = NULL;
+  }
+
+  // Reallocate the buffer to hold a given number of bytes
+  bool ReallocateBytes(size_t nBytes) throw() {
+    T *pNew;
+    pNew =
+        static_cast<T *>(Allocator::Reallocate(m_pData, nBytes * sizeof(char)));
+    if (pNew == NULL)
+      return false;
+    m_pData = pNew;
+
+    return true;
+  }
+
+public:
+  T *m_pData;
+};
+
+template <typename T, class Allocator = CAllocator>
+class CHeapPtr : public CHeapPtrBase<T, Allocator> {
+public:
+  CHeapPtr() throw() {}
+  CHeapPtr(CHeapPtr<T, Allocator> &p) throw() : CHeapPtrBase<T, Allocator>(p) {}
+  explicit CHeapPtr(T *p) throw() : CHeapPtrBase<T, Allocator>(p) {}
+  CHeapPtr<T> &operator=(CHeapPtr<T, Allocator> &p) throw() {
+    CHeapPtrBase<T, Allocator>::operator=(p);
+    return *this;
+  }
+
+  // Allocate a buffer with the given number of elements
+  bool Allocate(size_t nElements = 1) throw() {
+    size_t nBytes = nElements * sizeof(T);
+    return this->AllocateBytes(nBytes);
+  }
+
+  // Reallocate the buffer to hold a given number of elements
+  bool Reallocate(size_t nElements) throw() {
+    size_t nBytes = nElements * sizeof(T);
+    return this->ReallocateBytes(nBytes);
+  }
+};
+
+#define CComHeapPtr CHeapPtr
+
+//===--------------------- UTF-8 Related Types ----------------------------===//
+
+// Code Page
+#define CP_ACP 0
+#define CP_UTF8 65001 // UTF-8 translation.
+
+// The t_nBufferLength parameter is part of the published interface, but not
+// used here.
+template <int t_nBufferLength = 128> class CW2AEX {
+public:
+  CW2AEX(LPCWSTR psz, UINT nCodePage = CP_UTF8) {
+    if (nCodePage != CP_UTF8) {
+      // Current Implementation only supports CP_UTF8
+      assert(false && "CW2AEX implementation for Linux does not handle "
+                      "non-UTF8 code pages");
+      return;
+    }
+
+    if (!psz) {
+      m_psz = NULL;
+      return;
+    }
+
+    int len = (wcslen(psz) + 1) * 4;
+    m_psz = new char[len];
+    std::wcstombs(m_psz, psz, len);
+  }
+
+  ~CW2AEX() { delete[] m_psz; }
+
+  operator LPSTR() const { return m_psz; }
+
+  char *m_psz;
+};
+typedef CW2AEX<> CW2A;
+
+// The t_nBufferLength parameter is part of the published interface, but not
+// used here.
+template <int t_nBufferLength = 128> class CA2WEX {
+public:
+  CA2WEX(LPCSTR psz, UINT nCodePage = CP_UTF8) {
+    if (nCodePage != CP_UTF8) {
+      // Current Implementation only supports CP_UTF8
+      assert(false && "CA2WEX implementation for Linux does not handle "
+                      "non-UTF8 code pages");
+      return;
+    }
+
+    if (!psz) {
+      m_psz = NULL;
+      return;
+    }
+
+    int len = strlen(psz) + 1;
+    m_psz = new wchar_t[len];
+    std::mbstowcs(m_psz, psz, len);
+  }
+
+  ~CA2WEX() { delete[] m_psz; }
+
+  operator LPWSTR() const { return m_psz; }
+
+  wchar_t *m_psz;
+};
+
+typedef CA2WEX<> CA2W;
+
+//===--------- File IO Related Types ----------------===//
+
+class CHandle {
+public:
+  CHandle(HANDLE h);
+  ~CHandle();
+  operator HANDLE() const throw();
+
+private:
+  HANDLE m_h;
+};
 
 
 #endif // __cplusplus
 #endif // __cplusplus
 
 

+ 70 - 0
include/dxc/Support/WinFunctions.h

@@ -0,0 +1,70 @@
+//===-- WinFunctions.h - Windows Functions for other platforms --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines Windows-specific functions used in the codebase for
+// non-Windows platforms.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_WINFUNCTIONS_H
+#define LLVM_SUPPORT_WINFUNCTIONS_H
+
+#ifndef _WIN32
+
+#include "dxc/Support/WinAdapter.h"
+
+HRESULT StringCchCopyEx(LPSTR pszDest, size_t cchDest, LPCSTR pszSrc,
+                        LPSTR *ppszDestEnd, size_t *pcchRemaining, DWORD dwFlags);
+HRESULT StringCchPrintfA(char *dst, size_t dstSize, const char *format, ...);
+HRESULT UIntAdd(UINT uAugend, UINT uAddend, UINT *puResult);
+HRESULT IntToUInt(int in, UINT *out);
+HRESULT SizeTToInt(size_t in, INT *out);
+HRESULT UInt32Mult(UINT a, UINT b, UINT *out);
+int _stricmp(const char *str1, const char *str2);
+int _wcsicmp(const wchar_t *str1, const wchar_t *str2);
+int _wcsnicmp(const wchar_t *str1, const wchar_t *str2, size_t n);
+int wsprintf(wchar_t *wcs, const wchar_t *fmt, ...);
+unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask);
+HRESULT CoGetMalloc(DWORD dwMemContext, IMalloc **ppMalloc);
+
+HANDLE CreateFile2(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess,
+                   _In_ DWORD dwShareMode, _In_ DWORD dwCreationDisposition,
+                   _In_opt_ void *pCreateExParams);
+
+HANDLE CreateFileW(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess,
+                   _In_ DWORD dwShareMode, _In_opt_ void *lpSecurityAttributes,
+                   _In_ DWORD dwCreationDisposition,
+                   _In_ DWORD dwFlagsAndAttributes,
+                   _In_opt_ HANDLE hTemplateFile);
+
+BOOL GetFileSizeEx(_In_ HANDLE hFile, _Out_ PLARGE_INTEGER lpFileSize);
+
+BOOL ReadFile(_In_ HANDLE hFile, _Out_ LPVOID lpBuffer,
+              _In_ DWORD nNumberOfBytesToRead,
+              _Out_opt_ LPDWORD lpNumberOfBytesRead,
+              _Inout_opt_ void *lpOverlapped);
+BOOL WriteFile(_In_ HANDLE hFile, _In_ LPCVOID lpBuffer,
+               _In_ DWORD nNumberOfBytesToWrite,
+               _Out_opt_ LPDWORD lpNumberOfBytesWritten,
+               _Inout_opt_ void *lpOverlapped);
+
+BOOL CloseHandle(_In_ HANDLE hObject);
+
+// Windows-specific heap functions
+HANDLE HeapCreate(DWORD flOptions, SIZE_T dwInitialSize , SIZE_T dwMaximumSize);
+BOOL HeapDestroy(HANDLE heap);
+LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T nBytes);
+LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes);
+BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem);
+SIZE_T HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem);
+HANDLE GetProcessHeap();
+
+#endif // _WIN32
+
+#endif // LLVM_SUPPORT_WINFUNCTIONS_H

+ 56 - 0
include/dxc/Support/WinIncludes.h

@@ -10,6 +10,8 @@
 
 
 #pragma once
 #pragma once
 
 
+#ifdef _MSC_VER
+
 #define NOATOM 1
 #define NOATOM 1
 #define NOGDICAPMASKS 1
 #define NOGDICAPMASKS 1
 #define NOMETAFILE 1
 #define NOMETAFILE 1
@@ -46,3 +48,57 @@ template <class T> void swap(CComHeapPtr<T> &a, CComHeapPtr<T> &b) {
   a.m_pData = b.m_pData;
   a.m_pData = b.m_pData;
   b.m_pData = c;
   b.m_pData = c;
 }
 }
+
+#else // _MSC_VER
+
+#include "dxc/Support/WinAdapter.h"
+
+#ifdef __cplusplus
+// Define operator overloads to enable bit operations on enum values that are
+// used to define flags. Use DEFINE_ENUM_FLAG_OPERATORS(YOUR_TYPE) to enable these
+// operators on YOUR_TYPE.
+extern "C++" {
+    template <size_t S>
+    struct _ENUM_FLAG_INTEGER_FOR_SIZE;
+
+    template <>
+    struct _ENUM_FLAG_INTEGER_FOR_SIZE<1>
+    {
+        typedef int8_t type;
+    };
+
+    template <>
+    struct _ENUM_FLAG_INTEGER_FOR_SIZE<2>
+    {
+        typedef int16_t type;
+    };
+
+    template <>
+    struct _ENUM_FLAG_INTEGER_FOR_SIZE<4>
+    {
+        typedef int32_t type;
+    };
+
+    // used as an approximation of std::underlying_type<T>
+    template <class T>
+    struct _ENUM_FLAG_SIZED_INTEGER
+    {
+        typedef typename _ENUM_FLAG_INTEGER_FOR_SIZE<sizeof(T)>::type type;
+    };
+
+}
+#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) \
+extern "C++" { \
+inline ENUMTYPE operator | (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) | ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
+inline ENUMTYPE &operator |= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) |= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
+inline ENUMTYPE operator & (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) & ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
+inline ENUMTYPE &operator &= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) &= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
+inline ENUMTYPE operator ~ (ENUMTYPE a) { return ENUMTYPE(~((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a)); } \
+inline ENUMTYPE operator ^ (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)a) ^ ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
+inline ENUMTYPE &operator ^= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type &)a) ^= ((_ENUM_FLAG_SIZED_INTEGER<ENUMTYPE>::type)b)); } \
+}
+#else
+#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) // NOP, C allows these operators.
+#endif
+
+#endif // _MSC_VER

+ 25 - 20
include/dxc/Support/dxcapi.use.h

@@ -13,27 +13,27 @@
 #define __DXCAPI_USE_H__
 #define __DXCAPI_USE_H__
 
 
 #include "dxc/dxcapi.h"
 #include "dxc/dxcapi.h"
+#include "llvm/Support/DynamicLibrary.h"
 
 
 namespace dxc {
 namespace dxc {
 
 
 // Helper class to dynamically load the dxcompiler or a compatible libraries.
 // Helper class to dynamically load the dxcompiler or a compatible libraries.
 class DxcDllSupport {
 class DxcDllSupport {
 protected:
 protected:
-  HMODULE m_dll;
+  using DynamicLibrary = llvm::sys::DynamicLibrary;
+  DynamicLibrary m_dll;
   DxcCreateInstanceProc m_createFn;
   DxcCreateInstanceProc m_createFn;
   DxcCreateInstance2Proc m_createFn2;
   DxcCreateInstance2Proc m_createFn2;
 
 
   HRESULT InitializeInternal(LPCWSTR dllName, LPCSTR fnName) {
   HRESULT InitializeInternal(LPCWSTR dllName, LPCSTR fnName) {
-    if (m_dll != nullptr) return S_OK;
-    m_dll = LoadLibraryW(dllName);
-
-    if (m_dll == nullptr) return HRESULT_FROM_WIN32(GetLastError());
-    m_createFn = (DxcCreateInstanceProc)GetProcAddress(m_dll, fnName);
+    if (m_dll.isValid()) return S_OK;
+    m_dll = DynamicLibrary::getPermanentLibrary(CW2A(dllName));
+    if (!m_dll.isValid()) return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
+    m_createFn = (DxcCreateInstanceProc)m_dll.getAddressOfSymbol(fnName);
 
 
     if (m_createFn == nullptr) {
     if (m_createFn == nullptr) {
       HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
       HRESULT hr = HRESULT_FROM_WIN32(GetLastError());
-      FreeLibrary(m_dll);
-      m_dll = nullptr;
+      m_dll = DynamicLibrary();
       return hr;
       return hr;
     }
     }
 
 
@@ -45,18 +45,18 @@ protected:
       memcpy(fnName2, fnName, s);
       memcpy(fnName2, fnName, s);
       fnName2[s] = '2';
       fnName2[s] = '2';
       fnName2[s + 1] = '\0';
       fnName2[s + 1] = '\0';
-      m_createFn2 = (DxcCreateInstance2Proc)GetProcAddress(m_dll, fnName2);
+      m_createFn2 = (DxcCreateInstance2Proc)m_dll.getAddressOfSymbol(fnName2);
     }
     }
 
 
     return S_OK;
     return S_OK;
   }
   }
 
 
 public:
 public:
-  DxcDllSupport() : m_dll(nullptr), m_createFn(nullptr), m_createFn2(nullptr) {
+  DxcDllSupport() : m_dll(), m_createFn(nullptr), m_createFn2(nullptr) {
   }
   }
 
 
   DxcDllSupport(DxcDllSupport&& other) {
   DxcDllSupport(DxcDllSupport&& other) {
-    m_dll = other.m_dll; other.m_dll = nullptr;
+    m_dll = other.m_dll; other.m_dll = DynamicLibrary();
     m_createFn = other.m_createFn; other.m_createFn = nullptr;
     m_createFn = other.m_createFn; other.m_createFn = nullptr;
     m_createFn2 = other.m_createFn2; other.m_createFn2 = nullptr;
     m_createFn2 = other.m_createFn2; other.m_createFn2 = nullptr;
   }
   }
@@ -66,7 +66,13 @@ public:
   }
   }
 
 
   HRESULT Initialize() {
   HRESULT Initialize() {
+    #ifdef _WIN32
     return InitializeInternal(L"dxcompiler.dll", "DxcCreateInstance");
     return InitializeInternal(L"dxcompiler.dll", "DxcCreateInstance");
+    #elif __APPLE__
+    return InitializeInternal(L"libdxcompiler.dylib", "DxcCreateInstance");
+    #else
+    return InitializeInternal(L"libdxcompiler.so", "DxcCreateInstance");
+    #endif
   }
   }
 
 
   HRESULT InitializeForDll(_In_z_ const wchar_t* dll, _In_z_ const char* entryPoint) {
   HRESULT InitializeForDll(_In_z_ const wchar_t* dll, _In_z_ const char* entryPoint) {
@@ -80,7 +86,7 @@ public:
 
 
   HRESULT CreateInstance(REFCLSID clsid, REFIID riid, _Outptr_ IUnknown **pResult) {
   HRESULT CreateInstance(REFCLSID clsid, REFIID riid, _Outptr_ IUnknown **pResult) {
     if (pResult == nullptr) return E_POINTER;
     if (pResult == nullptr) return E_POINTER;
-    if (m_dll == nullptr) return E_FAIL;
+    if (!m_dll.isValid()) return E_FAIL;
     HRESULT hr = m_createFn(clsid, riid, (LPVOID*)pResult);
     HRESULT hr = m_createFn(clsid, riid, (LPVOID*)pResult);
     return hr;
     return hr;
   }
   }
@@ -92,7 +98,7 @@ public:
 
 
   HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, REFIID riid, _Outptr_ IUnknown **pResult) {
   HRESULT CreateInstance2(IMalloc *pMalloc, REFCLSID clsid, REFIID riid, _Outptr_ IUnknown **pResult) {
     if (pResult == nullptr) return E_POINTER;
     if (pResult == nullptr) return E_POINTER;
-    if (m_dll == nullptr) return E_FAIL;
+    if (!m_dll.isValid()) return E_FAIL;
     if (m_createFn2 == nullptr) return E_FAIL;
     if (m_createFn2 == nullptr) return E_FAIL;
     HRESULT hr = m_createFn2(pMalloc, clsid, riid, (LPVOID*)pResult);
     HRESULT hr = m_createFn2(pMalloc, clsid, riid, (LPVOID*)pResult);
     return hr;
     return hr;
@@ -103,21 +109,20 @@ public:
   }
   }
 
 
   bool IsEnabled() const {
   bool IsEnabled() const {
-    return m_dll != nullptr;
+    return m_dll.isValid();
   }
   }
 
 
   void Cleanup() {
   void Cleanup() {
-    if (m_dll != nullptr) {
+    if (m_dll.isValid()) {
       m_createFn = nullptr;
       m_createFn = nullptr;
       m_createFn2 = nullptr;
       m_createFn2 = nullptr;
-      FreeLibrary(m_dll);
-      m_dll = nullptr;
+      m_dll = DynamicLibrary();
     }
     }
   }
   }
 
 
-  HMODULE Detach() {
-    HMODULE module = m_dll;
-    m_dll = nullptr;
+  DynamicLibrary Detach() {
+    DynamicLibrary module = m_dll;
+    m_dll = DynamicLibrary();
     return module;
     return module;
   }
   }
 };
 };

+ 62 - 10
include/dxc/dxcapi.h

@@ -17,11 +17,16 @@
 #define DXC_API_IMPORT __declspec(dllimport)
 #define DXC_API_IMPORT __declspec(dllimport)
 #endif
 #endif
 
 
-#ifndef _WIN32
+#ifdef _WIN32
+#define DECLARE_CROSS_PLATFORM_UUIDOF(T)
+#define DEFINE_CROSS_PLATFORM_UUIDOF(T)
+#else
+#include <dlfcn.h>
 #include "dxc/Support/WinAdapter.h"
 #include "dxc/Support/WinAdapter.h"
 #endif
 #endif
 
 
 struct IMalloc;
 struct IMalloc;
+
 struct IDxcIncludeHandler;
 struct IDxcIncludeHandler;
 
 
 /// <summary>
 /// <summary>
@@ -71,12 +76,19 @@ typedef HRESULT(__stdcall *DxcCreateInstance2Proc)(
 /// <remarks>
 /// <remarks>
 /// While this function is similar to CoCreateInstance, there is no COM involvement.
 /// While this function is similar to CoCreateInstance, there is no COM involvement.
 /// </remarks>
 /// </remarks>
+
+#ifndef _MSC_VER
+extern "C"
+#endif
 DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance(
 DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance(
   _In_ REFCLSID   rclsid,
   _In_ REFCLSID   rclsid,
   _In_ REFIID     riid,
   _In_ REFIID     riid,
   _Out_ LPVOID*   ppv
   _Out_ LPVOID*   ppv
   );
   );
 
 
+#ifndef _MSC_VER
+extern "C"
+#endif
 DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance2(
 DXC_API_IMPORT HRESULT __stdcall DxcCreateInstance2(
   _In_ IMalloc    *pMalloc,
   _In_ IMalloc    *pMalloc,
   _In_ REFCLSID   rclsid,
   _In_ REFCLSID   rclsid,
@@ -91,6 +103,8 @@ IDxcBlob : public IUnknown {
 public:
 public:
   virtual LPVOID STDMETHODCALLTYPE GetBufferPointer(void) = 0;
   virtual LPVOID STDMETHODCALLTYPE GetBufferPointer(void) = 0;
   virtual SIZE_T STDMETHODCALLTYPE GetBufferSize(void) = 0;
   virtual SIZE_T STDMETHODCALLTYPE GetBufferSize(void) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcBlob)
 };
 };
 
 
 struct __declspec(uuid("7241d424-2646-4191-97c0-98e96e42fc68"))
 struct __declspec(uuid("7241d424-2646-4191-97c0-98e96e42fc68"))
@@ -98,6 +112,8 @@ IDxcBlobEncoding : public IDxcBlob {
 public:
 public:
   virtual HRESULT STDMETHODCALLTYPE GetEncoding(_Out_ BOOL *pKnown,
   virtual HRESULT STDMETHODCALLTYPE GetEncoding(_Out_ BOOL *pKnown,
                                                 _Out_ UINT32 *pCodePage) = 0;
                                                 _Out_ UINT32 *pCodePage) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcBlobEncoding)
 };
 };
 
 
 struct __declspec(uuid("e5204dc7-d18c-4c3c-bdfb-851673980fe7"))
 struct __declspec(uuid("e5204dc7-d18c-4c3c-bdfb-851673980fe7"))
@@ -125,6 +141,8 @@ IDxcLibrary : public IUnknown {
       _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;
       _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf16(
   virtual HRESULT STDMETHODCALLTYPE GetBlobAsUtf16(
       _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;
       _In_ IDxcBlob *pBlob, _COM_Outptr_ IDxcBlobEncoding **pBlobEncoding) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcLibrary)
 };
 };
 
 
 struct __declspec(uuid("CEDB484A-D4E9-445A-B991-CA21CA157DC2"))
 struct __declspec(uuid("CEDB484A-D4E9-445A-B991-CA21CA157DC2"))
@@ -132,6 +150,8 @@ IDxcOperationResult : public IUnknown {
   virtual HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetStatus(_Out_ HRESULT *pStatus) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **pResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetResult(_COM_Outptr_result_maybenull_ IDxcBlob **pResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **pErrors) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetErrorBuffer(_COM_Outptr_result_maybenull_ IDxcBlobEncoding **pErrors) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcOperationResult)
 };
 };
 
 
 struct __declspec(uuid("7f61fc7d-950d-467f-b3e3-3c02fb49187c"))
 struct __declspec(uuid("7f61fc7d-950d-467f-b3e3-3c02fb49187c"))
@@ -140,6 +160,8 @@ IDxcIncludeHandler : public IUnknown {
     _In_ LPCWSTR pFilename,                                   // Candidate filename.
     _In_ LPCWSTR pFilename,                                   // Candidate filename.
     _COM_Outptr_result_maybenull_ IDxcBlob **ppIncludeSource  // Resultant source object for included file, nullptr if not found.
     _COM_Outptr_result_maybenull_ IDxcBlob **ppIncludeSource  // Resultant source object for included file, nullptr if not found.
     ) = 0;
     ) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcIncludeHandler)
 };
 };
 
 
 struct DxcDefine {
 struct DxcDefine {
@@ -180,6 +202,8 @@ IDxcCompiler : public IUnknown {
     _In_ IDxcBlob *pSource,                         // Program to disassemble.
     _In_ IDxcBlob *pSource,                         // Program to disassemble.
     _COM_Outptr_ IDxcBlobEncoding **ppDisassembly   // Disassembly text.
     _COM_Outptr_ IDxcBlobEncoding **ppDisassembly   // Disassembly text.
     ) = 0;
     ) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcCompiler)
 };
 };
 
 
 struct __declspec(uuid("A005A9D9-B8BB-4594-B5C9-0E633BEC4D37"))
 struct __declspec(uuid("A005A9D9-B8BB-4594-B5C9-0E633BEC4D37"))
@@ -199,6 +223,8 @@ IDxcCompiler2 : public IDxcCompiler {
     _Outptr_opt_result_z_ LPWSTR *ppDebugBlobName,// Suggested file name for debug blob.
     _Outptr_opt_result_z_ LPWSTR *ppDebugBlobName,// Suggested file name for debug blob.
     _COM_Outptr_opt_ IDxcBlob **ppDebugBlob       // Debug blob
     _COM_Outptr_opt_ IDxcBlob **ppDebugBlob       // Debug blob
   ) = 0;
   ) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcCompiler2)
 };
 };
 
 
 struct __declspec(uuid("F1B5BE2A-62DD-4327-A1C2-42AC1E1E78E6"))
 struct __declspec(uuid("F1B5BE2A-62DD-4327-A1C2-42AC1E1E78E6"))
@@ -224,6 +250,8 @@ public:
       _COM_Outptr_ IDxcOperationResult *
       _COM_Outptr_ IDxcOperationResult *
           *ppResult // Linker output status, buffer, and errors
           *ppResult // Linker output status, buffer, and errors
   ) = 0;
   ) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcLinker)
 };
 };
 
 
 static const UINT32 DxcValidatorFlags_Default = 0;
 static const UINT32 DxcValidatorFlags_Default = 0;
@@ -240,6 +268,8 @@ IDxcValidator : public IUnknown {
     _In_ UINT32 Flags,                            // Validation flags.
     _In_ UINT32 Flags,                            // Validation flags.
     _COM_Outptr_ IDxcOperationResult **ppResult   // Validation output status, buffer, and errors
     _COM_Outptr_ IDxcOperationResult **ppResult   // Validation output status, buffer, and errors
     ) = 0;
     ) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcValidator)
 };
 };
 
 
 struct __declspec(uuid("334b1f50-2292-4b35-99a1-25588d8c17fe"))
 struct __declspec(uuid("334b1f50-2292-4b35-99a1-25588d8c17fe"))
@@ -248,6 +278,8 @@ IDxcContainerBuilder : public IUnknown {
   virtual HRESULT STDMETHODCALLTYPE AddPart(_In_ UINT32 fourCC, _In_ IDxcBlob *pSource) = 0;      // Part to add to the container
   virtual HRESULT STDMETHODCALLTYPE AddPart(_In_ UINT32 fourCC, _In_ IDxcBlob *pSource) = 0;      // Part to add to the container
   virtual HRESULT STDMETHODCALLTYPE RemovePart(_In_ UINT32 fourCC) = 0;                           // Remove the part with fourCC
   virtual HRESULT STDMETHODCALLTYPE RemovePart(_In_ UINT32 fourCC) = 0;                           // Remove the part with fourCC
   virtual HRESULT STDMETHODCALLTYPE SerializeContainer(_Out_ IDxcOperationResult **ppResult) = 0; // Builds a container of the given container builder state
   virtual HRESULT STDMETHODCALLTYPE SerializeContainer(_Out_ IDxcOperationResult **ppResult) = 0; // Builds a container of the given container builder state
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcContainerBuilder)
 };
 };
 
 
 struct __declspec(uuid("091f7a26-1c1f-4948-904b-e6e3a8a771d5"))
 struct __declspec(uuid("091f7a26-1c1f-4948-904b-e6e3a8a771d5"))
@@ -257,6 +289,8 @@ IDxcAssembler : public IUnknown {
     _In_ IDxcBlob *pShader,                       // Shader to assemble.
     _In_ IDxcBlob *pShader,                       // Shader to assemble.
     _COM_Outptr_ IDxcOperationResult **ppResult   // Assembly output status, buffer, and errors
     _COM_Outptr_ IDxcOperationResult **ppResult   // Assembly output status, buffer, and errors
     ) = 0;
     ) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcAssembler)
 };
 };
 
 
 // D3D_SIT_RTACCELERATIONSTRUCTURE is an additional value for D3D_SHADER_INPUT_TYPE,
 // D3D_SIT_RTACCELERATIONSTRUCTURE is an additional value for D3D_SHADER_INPUT_TYPE,
@@ -271,6 +305,8 @@ IDxcContainerReflection : public IUnknown {
   virtual HRESULT STDMETHODCALLTYPE GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlob **ppResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetPartContent(UINT32 idx, _COM_Outptr_ IDxcBlob **ppResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE FindFirstPartKind(UINT32 kind, _Out_ UINT32 *pResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE FindFirstPartKind(UINT32 kind, _Out_ UINT32 *pResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetPartReflection(UINT32 idx, REFIID iid, void **ppvObject) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetPartReflection(UINT32 idx, REFIID iid, void **ppvObject) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcContainerReflection)
 };
 };
 
 
 struct __declspec(uuid("AE2CD79F-CC22-453F-9B6B-B124E7A5204C"))
 struct __declspec(uuid("AE2CD79F-CC22-453F-9B6B-B124E7A5204C"))
@@ -280,6 +316,8 @@ IDxcOptimizerPass : public IUnknown {
   virtual HRESULT STDMETHODCALLTYPE GetOptionArgCount(_Out_ UINT32 *pCount) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetOptionArgCount(_Out_ UINT32 *pCount) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetOptionArgName(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetOptionArgName(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetOptionArgDescription(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetOptionArgDescription(UINT32 argIndex, _COM_Outptr_ LPWSTR *ppResult) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcOptimizerPass)
 };
 };
 
 
 struct __declspec(uuid("25740E2E-9CBA-401B-9119-4FB42F39F270"))
 struct __declspec(uuid("25740E2E-9CBA-401B-9119-4FB42F39F270"))
@@ -290,6 +328,8 @@ IDxcOptimizer : public IUnknown {
     _In_count_(optionCount) LPCWSTR *ppOptions, UINT32 optionCount,
     _In_count_(optionCount) LPCWSTR *ppOptions, UINT32 optionCount,
     _COM_Outptr_ IDxcBlob **pOutputModule,
     _COM_Outptr_ IDxcBlob **pOutputModule,
     _COM_Outptr_opt_ IDxcBlobEncoding **ppOutputText) = 0;
     _COM_Outptr_opt_ IDxcBlobEncoding **ppOutputText) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcOptimizer)
 };
 };
 
 
 static const UINT32 DxcVersionInfoFlags_None = 0;
 static const UINT32 DxcVersionInfoFlags_None = 0;
@@ -300,15 +340,27 @@ struct __declspec(uuid("b04f5b50-2059-4f12-a8ff-a1e0cde1cc7e"))
 IDxcVersionInfo : public IUnknown {
 IDxcVersionInfo : public IUnknown {
   virtual HRESULT STDMETHODCALLTYPE GetVersion(_Out_ UINT32 *pMajor, _Out_ UINT32 *pMinor) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetVersion(_Out_ UINT32 *pMajor, _Out_ UINT32 *pMinor) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetFlags(_Out_ UINT32 *pFlags) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcVersionInfo)
 };
 };
 
 
 struct __declspec(uuid("fb6904c4-42f0-4b62-9c46-983af7da7c83"))
 struct __declspec(uuid("fb6904c4-42f0-4b62-9c46-983af7da7c83"))
 IDxcVersionInfo2 : public IDxcVersionInfo {
 IDxcVersionInfo2 : public IDxcVersionInfo {
   virtual HRESULT STDMETHODCALLTYPE GetCommitInfo(_Out_ UINT32 *pCommitCount, _Out_ char **pCommitHash) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetCommitInfo(_Out_ UINT32 *pCommitCount, _Out_ char **pCommitHash) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcVersionInfo2)
 };
 };
 
 
+// Note: __declspec(selectany) requires 'extern'
+// On Linux __declspec(selectany) is removed and using 'extern' results in link error.
+#ifdef _MSC_VER
+#define EXTERN extern
+#else
+#define EXTERN
+#endif
+
 // {73e22d93-e6ce-47f3-b5bf-f0664f39c1b0}
 // {73e22d93-e6ce-47f3-b5bf-f0664f39c1b0}
-__declspec(selectany) extern const CLSID CLSID_DxcCompiler = {
+__declspec(selectany) EXTERN const CLSID CLSID_DxcCompiler = {
   0x73e22d93,
   0x73e22d93,
   0xe6ce,
   0xe6ce,
   0x47f3,
   0x47f3,
@@ -316,7 +368,7 @@ __declspec(selectany) extern const CLSID CLSID_DxcCompiler = {
 };
 };
 
 
 // {EF6A8087-B0EA-4D56-9E45-D07E1A8B7806}
 // {EF6A8087-B0EA-4D56-9E45-D07E1A8B7806}
-__declspec(selectany) extern const GUID CLSID_DxcLinker = {
+__declspec(selectany) EXTERN const GUID CLSID_DxcLinker = {
     0xef6a8087,
     0xef6a8087,
     0xb0ea,
     0xb0ea,
     0x4d56,
     0x4d56,
@@ -324,7 +376,7 @@ __declspec(selectany) extern const GUID CLSID_DxcLinker = {
 };
 };
 
 
 // {CD1F6B73-2AB0-484D-8EDC-EBE7A43CA09F}
 // {CD1F6B73-2AB0-484D-8EDC-EBE7A43CA09F}
-__declspec(selectany) extern const CLSID CLSID_DxcDiaDataSource = {
+__declspec(selectany) EXTERN const CLSID CLSID_DxcDiaDataSource = {
   0xcd1f6b73,
   0xcd1f6b73,
   0x2ab0,
   0x2ab0,
   0x484d,
   0x484d,
@@ -332,7 +384,7 @@ __declspec(selectany) extern const CLSID CLSID_DxcDiaDataSource = {
 };
 };
 
 
 // {6245D6AF-66E0-48FD-80B4-4D271796748C}
 // {6245D6AF-66E0-48FD-80B4-4D271796748C}
-__declspec(selectany) extern const GUID CLSID_DxcLibrary = {
+__declspec(selectany) EXTERN const GUID CLSID_DxcLibrary = {
   0x6245d6af,
   0x6245d6af,
   0x66e0,
   0x66e0,
   0x48fd,
   0x48fd,
@@ -340,7 +392,7 @@ __declspec(selectany) extern const GUID CLSID_DxcLibrary = {
 };
 };
 
 
 // {8CA3E215-F728-4CF3-8CDD-88AF917587A1}
 // {8CA3E215-F728-4CF3-8CDD-88AF917587A1}
-__declspec(selectany) extern const GUID CLSID_DxcValidator = {
+__declspec(selectany) EXTERN const GUID CLSID_DxcValidator = {
   0x8ca3e215,
   0x8ca3e215,
   0xf728,
   0xf728,
   0x4cf3,
   0x4cf3,
@@ -348,7 +400,7 @@ __declspec(selectany) extern const GUID CLSID_DxcValidator = {
 };
 };
 
 
 // {D728DB68-F903-4F80-94CD-DCCF76EC7151}
 // {D728DB68-F903-4F80-94CD-DCCF76EC7151}
-__declspec(selectany) extern const GUID CLSID_DxcAssembler = {
+__declspec(selectany) EXTERN const GUID CLSID_DxcAssembler = {
   0xd728db68,
   0xd728db68,
   0xf903,
   0xf903,
   0x4f80,
   0x4f80,
@@ -356,7 +408,7 @@ __declspec(selectany) extern const GUID CLSID_DxcAssembler = {
 };
 };
 
 
 // {b9f54489-55b8-400c-ba3a-1675e4728b91}
 // {b9f54489-55b8-400c-ba3a-1675e4728b91}
-__declspec(selectany) extern const GUID CLSID_DxcContainerReflection = {
+__declspec(selectany) EXTERN const GUID CLSID_DxcContainerReflection = {
   0xb9f54489,
   0xb9f54489,
   0x55b8,
   0x55b8,
   0x400c,
   0x400c,
@@ -364,7 +416,7 @@ __declspec(selectany) extern const GUID CLSID_DxcContainerReflection = {
 };
 };
 
 
 // {AE2CD79F-CC22-453F-9B6B-B124E7A5204C}
 // {AE2CD79F-CC22-453F-9B6B-B124E7A5204C}
-__declspec(selectany) extern const GUID CLSID_DxcOptimizer = {
+__declspec(selectany) EXTERN const GUID CLSID_DxcOptimizer = {
     0xae2cd79f,
     0xae2cd79f,
     0xcc22,
     0xcc22,
     0x453f,
     0x453f,
@@ -372,7 +424,7 @@ __declspec(selectany) extern const GUID CLSID_DxcOptimizer = {
 };
 };
 
 
 // {94134294-411f-4574-b4d0-8741e25240d2}
 // {94134294-411f-4574-b4d0-8741e25240d2}
-__declspec(selectany) extern const GUID CLSID_DxcContainerBuilder = {
+__declspec(selectany) EXTERN const GUID CLSID_DxcContainerBuilder = {
   0x94134294,
   0x94134294,
   0x411f,
   0x411f,
   0x4574,  
   0x4574,  

+ 13 - 3
include/dxc/dxcisense.h

@@ -12,6 +12,7 @@
 #ifndef __DXC_ISENSE__
 #ifndef __DXC_ISENSE__
 #define __DXC_ISENSE__
 #define __DXC_ISENSE__
 
 
+#include "dxc/dxcapi.h"
 #include "dxc/Support/WinAdapter.h"
 #include "dxc/Support/WinAdapter.h"
 
 
 typedef enum DxcGlobalOptions
 typedef enum DxcGlobalOptions
@@ -134,8 +135,8 @@ typedef enum DxcDiagnosticDisplayOptions
   // Display the category name associated with this diagnostic, if any.
   // Display the category name associated with this diagnostic, if any.
   DxcDiagnostic_DisplayCategoryName = 0x20,
   DxcDiagnostic_DisplayCategoryName = 0x20,
 
 
-	// Display the severity of the diagnostic message.
-	DxcDiagnostic_DisplaySeverity = 0x200
+  // Display the severity of the diagnostic message.
+  DxcDiagnostic_DisplaySeverity = 0x200
 } DxcDiagnosticDisplayOptions;
 } DxcDiagnosticDisplayOptions;
 
 
 typedef enum DxcTranslationUnitFlags
 typedef enum DxcTranslationUnitFlags
@@ -663,6 +664,8 @@ IDxcIntelliSense : public IUnknown
     _Out_ DxcDiagnosticDisplayOptions* pValue) = 0;
     _Out_ DxcDiagnosticDisplayOptions* pValue) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetDefaultEditingTUOptions(_Out_ DxcTranslationUnitFlags* pValue) = 0;
   virtual HRESULT STDMETHODCALLTYPE GetDefaultEditingTUOptions(_Out_ DxcTranslationUnitFlags* pValue) = 0;
   virtual HRESULT STDMETHODCALLTYPE CreateUnsavedFile(_In_ LPCSTR fileName, _In_ LPCSTR contents, unsigned contentLength, _Outptr_result_nullonfailure_ IDxcUnsavedFile** pResult) = 0;
   virtual HRESULT STDMETHODCALLTYPE CreateUnsavedFile(_In_ LPCSTR fileName, _In_ LPCSTR contents, unsigned contentLength, _Outptr_result_nullonfailure_ IDxcUnsavedFile** pResult) = 0;
+
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcIntelliSense)
 };
 };
 
 
 struct __declspec(uuid("937824a0-7f5a-4815-9ba7-7fc0424f4173"))
 struct __declspec(uuid("937824a0-7f5a-4815-9ba7-7fc0424f4173"))
@@ -762,8 +765,15 @@ IDxcUnsavedFile : public IUnknown
 // Fun fact: 'extern' is required because const is by default static in C++, so
 // Fun fact: 'extern' is required because const is by default static in C++, so
 // CLSID_DxcIntelliSense is not visible externally (this is OK in C, since const is
 // CLSID_DxcIntelliSense is not visible externally (this is OK in C, since const is
 // not by default static in C)
 // not by default static in C)
+
+#ifdef _MSC_VER
+#define EXTERN extern
+#else
+#define EXTERN
+#endif
+
 __declspec(selectany)
 __declspec(selectany)
-extern const CLSID CLSID_DxcIntelliSense = { /* 3047833c-d1c0-4b8e-9d40-102878605985 */
+EXTERN const CLSID CLSID_DxcIntelliSense = { /* 3047833c-d1c0-4b8e-9d40-102878605985 */
     0x3047833c,
     0x3047833c,
     0xd1c0,
     0xd1c0,
     0x4b8e,
     0x4b8e,

+ 8 - 1
include/dxc/dxctools.h

@@ -47,10 +47,17 @@ IDxcRewriter : public IUnknown {
                                                      _In_ UINT32  rewriteOption,
                                                      _In_ UINT32  rewriteOption,
                                                      _COM_Outptr_ IDxcOperationResult **ppResult) = 0;
                                                      _COM_Outptr_ IDxcOperationResult **ppResult) = 0;
 
 
+  DECLARE_CROSS_PLATFORM_UUIDOF(IDxcRewriter)
 };
 };
 
 
+#ifdef _MSC_VER
+#define EXTERN extern
+#else
+#define EXTERN
+#endif
+
 __declspec(selectany)
 __declspec(selectany)
-extern const CLSID CLSID_DxcRewriter = { /* b489b951-e07f-40b3-968d-93e124734da4 */
+EXTERN const CLSID CLSID_DxcRewriter = { /* b489b951-e07f-40b3-968d-93e124734da4 */
   0xb489b951,
   0xb489b951,
   0xe07f,
   0xe07f,
   0x40b3,
   0x40b3,

+ 8 - 0
include/llvm/Analysis/TargetLibraryInfo.def

@@ -431,9 +431,11 @@ TLI_DEFINE_STRING_INTERNAL("fmodl")
 /// FILE *fopen(const char *filename, const char *mode);
 /// FILE *fopen(const char *filename, const char *mode);
 TLI_DEFINE_ENUM_INTERNAL(fopen)
 TLI_DEFINE_ENUM_INTERNAL(fopen)
 TLI_DEFINE_STRING_INTERNAL("fopen")
 TLI_DEFINE_STRING_INTERNAL("fopen")
+#if 0 // HLSL Change Starts - Exclude potentially duplicate 64bit versions
 /// FILE *fopen64(const char *filename, const char *opentype)
 /// FILE *fopen64(const char *filename, const char *opentype)
 TLI_DEFINE_ENUM_INTERNAL(fopen64)
 TLI_DEFINE_ENUM_INTERNAL(fopen64)
 TLI_DEFINE_STRING_INTERNAL("fopen64")
 TLI_DEFINE_STRING_INTERNAL("fopen64")
+#endif // HLSL Change Ends
 /// int fprintf(FILE *stream, const char *format, ...);
 /// int fprintf(FILE *stream, const char *format, ...);
 TLI_DEFINE_ENUM_INTERNAL(fprintf)
 TLI_DEFINE_ENUM_INTERNAL(fprintf)
 TLI_DEFINE_STRING_INTERNAL("fprintf")
 TLI_DEFINE_STRING_INTERNAL("fprintf")
@@ -467,9 +469,11 @@ TLI_DEFINE_STRING_INTERNAL("fseek")
 /// int fseeko(FILE *stream, off_t offset, int whence);
 /// int fseeko(FILE *stream, off_t offset, int whence);
 TLI_DEFINE_ENUM_INTERNAL(fseeko)
 TLI_DEFINE_ENUM_INTERNAL(fseeko)
 TLI_DEFINE_STRING_INTERNAL("fseeko")
 TLI_DEFINE_STRING_INTERNAL("fseeko")
+#if 0 // HLSL Change Starts - Exclude potentially duplicate 64bit versions
 /// int fseeko64(FILE *stream, off64_t offset, int whence)
 /// int fseeko64(FILE *stream, off64_t offset, int whence)
 TLI_DEFINE_ENUM_INTERNAL(fseeko64)
 TLI_DEFINE_ENUM_INTERNAL(fseeko64)
 TLI_DEFINE_STRING_INTERNAL("fseeko64")
 TLI_DEFINE_STRING_INTERNAL("fseeko64")
+#endif // HLSL Change Ends
 /// int fsetpos(FILE *stream, const fpos_t *pos);
 /// int fsetpos(FILE *stream, const fpos_t *pos);
 TLI_DEFINE_ENUM_INTERNAL(fsetpos)
 TLI_DEFINE_ENUM_INTERNAL(fsetpos)
 TLI_DEFINE_STRING_INTERNAL("fsetpos")
 TLI_DEFINE_STRING_INTERNAL("fsetpos")
@@ -491,9 +495,11 @@ TLI_DEFINE_STRING_INTERNAL("ftell")
 /// off_t ftello(FILE *stream);
 /// off_t ftello(FILE *stream);
 TLI_DEFINE_ENUM_INTERNAL(ftello)
 TLI_DEFINE_ENUM_INTERNAL(ftello)
 TLI_DEFINE_STRING_INTERNAL("ftello")
 TLI_DEFINE_STRING_INTERNAL("ftello")
+#if 0 // HLSL Change Starts - Exclude potentially duplicate 64bit versions
 /// off64_t ftello64(FILE *stream)
 /// off64_t ftello64(FILE *stream)
 TLI_DEFINE_ENUM_INTERNAL(ftello64)
 TLI_DEFINE_ENUM_INTERNAL(ftello64)
 TLI_DEFINE_STRING_INTERNAL("ftello64")
 TLI_DEFINE_STRING_INTERNAL("ftello64")
+#endif // HLSL Change Ends
 /// int ftrylockfile(FILE *file);
 /// int ftrylockfile(FILE *file);
 TLI_DEFINE_ENUM_INTERNAL(ftrylockfile)
 TLI_DEFINE_ENUM_INTERNAL(ftrylockfile)
 TLI_DEFINE_STRING_INTERNAL("ftrylockfile")
 TLI_DEFINE_STRING_INTERNAL("ftrylockfile")
@@ -955,9 +961,11 @@ TLI_DEFINE_STRING_INTERNAL("times")
 /// FILE *tmpfile(void);
 /// FILE *tmpfile(void);
 TLI_DEFINE_ENUM_INTERNAL(tmpfile)
 TLI_DEFINE_ENUM_INTERNAL(tmpfile)
 TLI_DEFINE_STRING_INTERNAL("tmpfile")
 TLI_DEFINE_STRING_INTERNAL("tmpfile")
+#if 0 // HLSL Change Starts - Exclude potentially duplicate 64bit versions
 /// FILE *tmpfile64(void)
 /// FILE *tmpfile64(void)
 TLI_DEFINE_ENUM_INTERNAL(tmpfile64)
 TLI_DEFINE_ENUM_INTERNAL(tmpfile64)
 TLI_DEFINE_STRING_INTERNAL("tmpfile64")
 TLI_DEFINE_STRING_INTERNAL("tmpfile64")
+#endif // HLSL Change Ends
 /// int toascii(int c);
 /// int toascii(int c);
 TLI_DEFINE_ENUM_INTERNAL(toascii)
 TLI_DEFINE_ENUM_INTERNAL(toascii)
 TLI_DEFINE_STRING_INTERNAL("toascii")
 TLI_DEFINE_STRING_INTERNAL("toascii")

+ 4 - 1
include/llvm/PassRegistry.h

@@ -39,7 +39,10 @@ struct PassRegistrationListener;
 /// threads simultaneously, you will need to use a separate PassRegistry on
 /// threads simultaneously, you will need to use a separate PassRegistry on
 /// each thread.
 /// each thread.
 class PassRegistry {
 class PassRegistry {
-  //mutable sys::SmartRWMutex<true> Lock; // HLSL Change - no lock needed
+  #ifndef LLVM_ON_WIN32
+  // HLSL Change - no lock needed for Windows, as it will use its own mechanism defined in PassRegistry.cpp.
+  mutable sys::SmartRWMutex<true> Lock;
+  #endif
 
 
   /// PassInfoMap - Keep track of the PassInfo object for each registered pass.
   /// PassInfoMap - Keep track of the PassInfo object for each registered pass.
   typedef DenseMap<const void *, const PassInfo *> MapType;
   typedef DenseMap<const void *, const PassInfo *> MapType;

+ 8 - 0
include/llvm/Support/MSFileSystem.h

@@ -14,6 +14,7 @@
 
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 // MSFileSystem interface.
 // MSFileSystem interface.
+struct stat;
 
 
 namespace llvm {
 namespace llvm {
 namespace sys  {
 namespace sys  {
@@ -86,6 +87,13 @@ public:
   virtual errno_t resize_file(_In_ LPCWSTR path, uint64_t size) throw() = 0; // A number of C calls.
   virtual errno_t resize_file(_In_ LPCWSTR path, uint64_t size) throw() = 0; // A number of C calls.
   virtual int Read(int fd, _Out_bytecap_(count) void* buffer, unsigned int count) throw() = 0;
   virtual int Read(int fd, _Out_bytecap_(count) void* buffer, unsigned int count) throw() = 0;
   virtual int Write(int fd, _In_bytecount_(count) const void* buffer, unsigned int count) throw() = 0;
   virtual int Write(int fd, _In_bytecount_(count) const void* buffer, unsigned int count) throw() = 0;
+
+  // Unix interface
+#ifndef _WIN32
+  virtual int Open(const char *lpFileName, int flags, mode_t mode = 0) throw() = 0;
+  virtual int Stat(const char *lpFileName, struct stat *Status) throw() = 0;
+  virtual int Fstat(int FD, struct stat *Status) throw() = 0;
+#endif
 };
 };
 
 
 
 

+ 3 - 3
include/llvm/Support/Mutex.h

@@ -71,10 +71,10 @@ namespace llvm
     /// @{
     /// @{
     private:
     private:
 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
 #if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0
-#if 0 // HLSL Change
-      void* data_; ///< We don't know what the data will be
-#else
+#if LLVM_ON_WIN32 // HLSL Change
       char data_[sizeof(void*) == 8 ? 40 : 24]; // C_ASSERT this is CRITICAL_SECTION-sized
       char data_[sizeof(void*) == 8 ? 40 : 24]; // C_ASSERT this is CRITICAL_SECTION-sized
+#else
+      void* data_; ///< We don't know what the data will be
 #endif // HLSL Change
 #endif // HLSL Change
 #endif
 #endif
 
 

+ 4 - 4
lib/Analysis/TargetLibraryInfo.cpp

@@ -350,16 +350,16 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T,
     TLI.setUnavailable(LibFunc::under_IO_getc);
     TLI.setUnavailable(LibFunc::under_IO_getc);
     TLI.setUnavailable(LibFunc::under_IO_putc);
     TLI.setUnavailable(LibFunc::under_IO_putc);
     TLI.setUnavailable(LibFunc::memalign);
     TLI.setUnavailable(LibFunc::memalign);
-    TLI.setUnavailable(LibFunc::fopen64);
-    TLI.setUnavailable(LibFunc::fseeko64);
+    //TLI.setUnavailable(LibFunc::fopen64); // HLSL Change - duplicate 64bit versions
+    //TLI.setUnavailable(LibFunc::fseeko64); // HLSL Change - duplicate 64bit versions
     TLI.setUnavailable(LibFunc::fstat64);
     TLI.setUnavailable(LibFunc::fstat64);
     TLI.setUnavailable(LibFunc::fstatvfs64);
     TLI.setUnavailable(LibFunc::fstatvfs64);
-    TLI.setUnavailable(LibFunc::ftello64);
+    //TLI.setUnavailable(LibFunc::ftello64); // HLSL Change - duplicate 64bit versions
     TLI.setUnavailable(LibFunc::lstat64);
     TLI.setUnavailable(LibFunc::lstat64);
     TLI.setUnavailable(LibFunc::open64);
     TLI.setUnavailable(LibFunc::open64);
     TLI.setUnavailable(LibFunc::stat64);
     TLI.setUnavailable(LibFunc::stat64);
     TLI.setUnavailable(LibFunc::statvfs64);
     TLI.setUnavailable(LibFunc::statvfs64);
-    TLI.setUnavailable(LibFunc::tmpfile64);
+    //TLI.setUnavailable(LibFunc::tmpfile64); // HLSL Change - duplicate 64bit versions
   }
   }
 
 
   TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary);
   TLI.addVectorizableFunctionsFromVecLib(ClVectorLibrary);

+ 2 - 0
lib/DxcSupport/CMakeLists.txt

@@ -7,6 +7,8 @@ add_llvm_library(LLVMDxcSupport
   Global.cpp
   Global.cpp
   HLSLOptions.cpp
   HLSLOptions.cpp
   Unicode.cpp
   Unicode.cpp
+  WinAdapter.cpp
+  WinFunctions.cpp
   )
   )
 
 
 add_dependencies(LLVMDxcSupport TablegenHLSLOptions)
 add_dependencies(LLVMDxcSupport TablegenHLSLOptions)

+ 14 - 16
lib/DxcSupport/FileIOHelper.cpp

@@ -14,43 +14,43 @@
 #include "dxc/Support/microcom.h"
 #include "dxc/Support/microcom.h"
 #include "dxc/Support/Unicode.h"
 #include "dxc/Support/Unicode.h"
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/Support/FileIOHelper.h"
+#include "dxc/Support/WinFunctions.h"
 #include "dxc/dxcapi.h"
 #include "dxc/dxcapi.h"
 
 
 #include <algorithm>
 #include <algorithm>
 #include <memory>
 #include <memory>
+
+#ifdef _WIN32
 #include <intsafe.h>
 #include <intsafe.h>
+#endif
 
 
 #define CP_UTF16 1200
 #define CP_UTF16 1200
 
 
 struct HeapMalloc : public IMalloc {
 struct HeapMalloc : public IMalloc {
 public:
 public:
-  ULONG STDMETHODCALLTYPE AddRef() {
-    return 1;
-  }
-  ULONG STDMETHODCALLTYPE Release() {
-    return 1;
-  }
+  ULONG STDMETHODCALLTYPE AddRef() override { return 1; }
+  ULONG STDMETHODCALLTYPE Release() override { return 1; }
   STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override {
   STDMETHODIMP QueryInterface(REFIID iid, void** ppvObject) override {
     return DoBasicQueryInterface<IMalloc>(this, iid, ppvObject);
     return DoBasicQueryInterface<IMalloc>(this, iid, ppvObject);
   }
   }
-  virtual void *STDMETHODCALLTYPE Alloc(
+  virtual void *STDMETHODCALLTYPE Alloc (
     /* [annotation][in] */
     /* [annotation][in] */
-    _In_  SIZE_T cb) {
+    _In_  SIZE_T cb) override {
     return HeapAlloc(GetProcessHeap(), 0, cb);
     return HeapAlloc(GetProcessHeap(), 0, cb);
   }
   }
 
 
-  virtual void *STDMETHODCALLTYPE Realloc(
+  virtual void *STDMETHODCALLTYPE Realloc (
     /* [annotation][in] */
     /* [annotation][in] */
     _In_opt_  void *pv,
     _In_opt_  void *pv,
     /* [annotation][in] */
     /* [annotation][in] */
-    _In_  SIZE_T cb)
+    _In_  SIZE_T cb) override
   {
   {
     return HeapReAlloc(GetProcessHeap(), 0, pv, cb);
     return HeapReAlloc(GetProcessHeap(), 0, pv, cb);
   }
   }
 
 
-  virtual void STDMETHODCALLTYPE Free(
+  virtual void STDMETHODCALLTYPE Free (
     /* [annotation][in] */
     /* [annotation][in] */
-    _In_opt_  void *pv)
+    _In_opt_  void *pv) override
   {
   {
     HeapFree(GetProcessHeap(), 0, pv);
     HeapFree(GetProcessHeap(), 0, pv);
   }
   }
@@ -71,9 +71,7 @@ public:
   }
   }
 
 
 
 
-  virtual void STDMETHODCALLTYPE HeapMinimize(void)
-  {
-  }
+  virtual void STDMETHODCALLTYPE HeapMinimize(void) {}
 };
 };
 
 
 static HeapMalloc g_HeapMalloc;
 static HeapMalloc g_HeapMalloc;
@@ -311,9 +309,9 @@ static HRESULT CodePageBufferToUtf16(UINT32 codePage, LPCVOID bufferPointer,
   int numActuallyConvertedUTF16 =
   int numActuallyConvertedUTF16 =
       MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS, (LPCSTR)bufferPointer,
       MultiByteToWideChar(codePage, MB_ERR_INVALID_CHARS, (LPCSTR)bufferPointer,
                           bufferSize, utf16NewCopy, buffSizeUTF16);
                           bufferSize, utf16NewCopy, buffSizeUTF16);
+
   if (numActuallyConvertedUTF16 == 0)
   if (numActuallyConvertedUTF16 == 0)
     return HRESULT_FROM_WIN32(GetLastError());
     return HRESULT_FROM_WIN32(GetLastError());
-
   ((LPWSTR)utf16NewCopy)[numActuallyConvertedUTF16] = L'\0';
   ((LPWSTR)utf16NewCopy)[numActuallyConvertedUTF16] = L'\0';
   *pConvertedCharCount = numActuallyConvertedUTF16;
   *pConvertedCharCount = numActuallyConvertedUTF16;
 
 

+ 21 - 0
lib/DxcSupport/HLSLOptions.cpp

@@ -49,6 +49,10 @@ namespace {
 
 
 static HlslOptTable *g_HlslOptTable;
 static HlslOptTable *g_HlslOptTable;
 
 
+#ifndef _WIN32
+#pragma GCC visibility push(hidden)
+#endif
+
 std::error_code hlsl::options::initHlslOptTable() {
 std::error_code hlsl::options::initHlslOptTable() {
   DXASSERT(g_HlslOptTable == nullptr, "else double-init");
   DXASSERT(g_HlslOptTable == nullptr, "else double-init");
   g_HlslOptTable = new (std::nothrow) HlslOptTable();
   g_HlslOptTable = new (std::nothrow) HlslOptTable();
@@ -66,6 +70,10 @@ const OptTable * hlsl::options::getHlslOptTable() {
   return g_HlslOptTable;
   return g_HlslOptTable;
 }
 }
 
 
+#ifndef _WIN32
+#pragma GCC visibility pop
+#endif
+
 void DxcDefines::push_back(llvm::StringRef value) {
 void DxcDefines::push_back(llvm::StringRef value) {
   // Skip empty defines.
   // Skip empty defines.
   if (value.size() > 0) {
   if (value.size() > 0) {
@@ -147,6 +155,17 @@ MainArgs::MainArgs(int argc, const wchar_t **argv, int skipArgCount) {
   }
   }
 }
 }
 
 
+MainArgs::MainArgs(int argc, const char **argv, int skipArgCount) {
+  if (argc > skipArgCount) {
+    Utf8StringVector.reserve(argc - skipArgCount);
+    Utf8CharPtrVector.reserve(argc - skipArgCount);
+    for (int i = skipArgCount; i < argc; ++i) {
+      Utf8StringVector.emplace_back(argv[i]);
+      Utf8CharPtrVector.push_back(Utf8StringVector.back().data());
+    }
+  }
+}
+
 MainArgs::MainArgs(llvm::ArrayRef<llvm::StringRef> args) {
 MainArgs::MainArgs(llvm::ArrayRef<llvm::StringRef> args) {
   Utf8StringVector.reserve(args.size());
   Utf8StringVector.reserve(args.size());
   Utf8CharPtrVector.reserve(args.size());
   Utf8CharPtrVector.reserve(args.size());
@@ -525,6 +544,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
 #ifdef ENABLE_SPIRV_CODEGEN
 #ifdef ENABLE_SPIRV_CODEGEN
   const bool genSpirv = opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);
   const bool genSpirv = opts.GenSPIRV = Args.hasFlag(OPT_spirv, OPT_INVALID, false);
   opts.VkInvertY = Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false);
   opts.VkInvertY = Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false);
+  opts.VkInvertW = Args.hasFlag(OPT_fvk_use_dx_position_w, OPT_INVALID, false);
   opts.VkUseGlLayout = Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false);
   opts.VkUseGlLayout = Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false);
   opts.VkUseDxLayout = Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false);
   opts.VkUseDxLayout = Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false);
   opts.SpvEnableReflect = Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false);
   opts.SpvEnableReflect = Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false);
@@ -590,6 +610,7 @@ int ReadDxcOpts(const OptTable *optionTable, unsigned flagsToInclude,
 #else
 #else
   if (Args.hasFlag(OPT_spirv, OPT_INVALID, false) ||
   if (Args.hasFlag(OPT_spirv, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fvk_invert_y, OPT_INVALID, false) ||
+      Args.hasFlag(OPT_fvk_use_dx_position_w, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fvk_use_gl_layout, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fvk_use_dx_layout, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false) ||
       Args.hasFlag(OPT_fspv_reflect, OPT_INVALID, false) ||

+ 82 - 0
lib/DxcSupport/Unicode.cpp

@@ -17,6 +17,88 @@
 #include "dxc/Support/Unicode.h"
 #include "dxc/Support/Unicode.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
 
 
+#ifndef _WIN32
+// MultiByteToWideChar which is a Windows-specific method.
+// This is a very simplistic implementation for non-Windows platforms. This
+// implementation completely ignores CodePage and dwFlags.
+int MultiByteToWideChar(uint32_t /*CodePage*/, uint32_t /*dwFlags*/,
+                        const char *lpMultiByteStr, int cbMultiByte,
+                        wchar_t *lpWideCharStr, int cchWideChar) {
+
+  if (cbMultiByte == 0) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return 0;
+  }
+
+  // if cbMultiByte is -1, it indicates that lpMultiByteStr is null-terminated
+  // and the entire string should be processed.
+  if (cbMultiByte == -1) {
+    for (cbMultiByte = 0; lpMultiByteStr[cbMultiByte] != '\0'; ++cbMultiByte)
+      ;
+    // Add 1 for the null-terminating character.
+    ++cbMultiByte;
+  }
+  // if zero is given as the destination size, this function should
+  // return the required size (including the null-terminating character).
+  if (cchWideChar == 0) {
+    wchar_t *tempStr = (wchar_t *)malloc(cbMultiByte * sizeof(wchar_t));
+    size_t requiredSize = mbstowcs(tempStr, lpMultiByteStr, cbMultiByte);
+    free(tempStr);
+    if (requiredSize == (size_t)cbMultiByte) return requiredSize;
+    return requiredSize + 1;
+  }
+
+  if (cchWideChar < cbMultiByte) {
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return 0;
+  }
+
+  size_t rv = mbstowcs(lpWideCharStr, lpMultiByteStr, cbMultiByte);
+  if (rv == (size_t)cbMultiByte) return rv;
+  return rv + 1; // mbstowcs excludes the terminating character
+}
+
+// WideCharToMultiByte is a Windows-specific method.
+// This is a very simplistic implementation for non-Windows platforms. This
+// implementation completely ignores CodePage and dwFlags.
+int WideCharToMultiByte(uint32_t /*CodePage*/, uint32_t /*dwFlags*/,
+                        const wchar_t *lpWideCharStr, int cchWideChar,
+                        char *lpMultiByteStr, int cbMultiByte,
+                        const char * /*lpDefaultChar*/,
+                        bool * /*lpUsedDefaultChar*/) {
+  // if cchWideChar is -1, it indicates that lpWideCharStr is null-terminated
+  // and the entire string should be processed.
+  if (cchWideChar == 0) {
+    SetLastError(ERROR_INVALID_PARAMETER);
+    return 0;
+  }
+  if (cchWideChar == -1) {
+    for (cchWideChar = 0; lpWideCharStr[cchWideChar] != '\0'; ++cchWideChar)
+      ;
+    // Add 1 for the null-terminating character.
+    ++cchWideChar;
+  }
+  // if zero is given as the destination size, this function should
+  // return the required size (including the null-terminating character).
+  if (cbMultiByte == 0) {
+    char *tempStr = (char *)malloc(cchWideChar * sizeof(char));
+    size_t requiredSize = wcstombs(tempStr, lpWideCharStr, cchWideChar);
+    free(tempStr);
+    if (requiredSize == (size_t)cchWideChar) return requiredSize;
+    return requiredSize + 1;
+  }
+
+  if (cbMultiByte < cchWideChar) {
+    SetLastError(ERROR_INSUFFICIENT_BUFFER);
+    return 0;
+  }
+
+  size_t rv = wcstombs(lpMultiByteStr, lpWideCharStr, cchWideChar);
+  if (rv == (size_t)cchWideChar) return rv;
+  return rv + 1; // mbstowcs excludes the terminating character
+}
+#endif // _WIN32
+
 namespace Unicode {
 namespace Unicode {
 
 
 _Success_(return != false)
 _Success_(return != false)

+ 59 - 0
lib/DxcSupport/WinAdapter.cpp

@@ -0,0 +1,59 @@
+//===-- WinAdapter.cpp - Windows Adapter for other platforms ----*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _WIN32
+
+#include "dxc/Support/WinAdapter.h"
+#include "dxc/Support/WinFunctions.h"
+
+DEFINE_CROSS_PLATFORM_UUIDOF(IUnknown)
+DEFINE_CROSS_PLATFORM_UUIDOF(INoMarshal)
+DEFINE_CROSS_PLATFORM_UUIDOF(IStream)
+DEFINE_CROSS_PLATFORM_UUIDOF(ISequentialStream)
+
+//===--------------------------- IUnknown ---------------------------------===//
+
+ULONG IUnknown::AddRef() {
+  ++m_count;
+  return m_count;
+}
+ULONG IUnknown::Release() {
+  ULONG result = --m_count;
+  if (m_count == 0) {
+    delete this;
+  }
+  return result;
+}
+IUnknown::~IUnknown() {}
+
+//===--------------------------- IMalloc ----------------------------------===//
+
+void *IMalloc::Alloc(size_t size) { return malloc(size); }
+void *IMalloc::Realloc(void *ptr, size_t size) { return realloc(ptr, size); }
+void IMalloc::Free(void *ptr) { free(ptr); }
+HRESULT IMalloc::QueryInterface(REFIID riid, void **ppvObject) {
+  assert(false && "QueryInterface not implemented for IMalloc.");
+  return E_NOINTERFACE;
+}
+
+//===--------------------------- CAllocator -------------------------------===//
+
+void *CAllocator::Reallocate(void *p, size_t nBytes) throw() {
+  return realloc(p, nBytes);
+}
+void *CAllocator::Allocate(size_t nBytes) throw() { return malloc(nBytes); }
+void CAllocator::Free(void *p) throw() { free(p); }
+
+//===--------------------------- CHandle -------------------------------===//
+
+CHandle::CHandle(HANDLE h) { m_h = h; }
+CHandle::~CHandle() { CloseHandle(m_h); }
+CHandle::operator HANDLE() const throw() { return m_h; }
+
+#endif

+ 337 - 0
lib/DxcSupport/WinFunctions.cpp

@@ -0,0 +1,337 @@
+//===-- WinFunctions.cpp - Windows Functions for other platforms --*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines Windows-specific functions used in the codebase for
+// non-Windows platforms.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _WIN32
+#include <fcntl.h>
+#include <map>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "dxc/Support/WinFunctions.h"
+
+HRESULT StringCchCopyEx(LPSTR pszDest, size_t cchDest, LPCSTR pszSrc,
+                        LPSTR *ppszDestEnd, size_t *pcchRemaining, DWORD dwFlags) {
+  assert(dwFlags == 0 && "dwFlag values not supported in StringCchCopyEx");
+  char *zPtr = 0;
+
+  zPtr = stpncpy(pszDest, pszSrc, cchDest);
+
+  if (ppszDestEnd)
+    *ppszDestEnd = zPtr;
+
+  if (pcchRemaining)
+    *pcchRemaining = cchDest - (zPtr - pszDest);
+
+  return S_OK;
+}
+
+
+HRESULT StringCchPrintfA(char *dst, size_t dstSize, const char *format, ...) {
+  va_list args;
+  va_start(args, format);
+  va_list argscopy;
+  va_copy(argscopy, args);
+  // C++11 snprintf can return the size of the resulting string if it was to be
+  // constructed.
+  size_t size = vsnprintf(nullptr, 0, format, argscopy) + 1; // Extra space for '\0'
+  if (size > dstSize) {
+    *dst = '\0';
+  } else {
+    vsnprintf(dst, size, format, args);
+  }
+  va_end(argscopy);
+  va_end(args);
+  return S_OK;
+}
+HRESULT UIntAdd(UINT uAugend, UINT uAddend, UINT *puResult) {
+  HRESULT hr;
+  if ((uAugend + uAddend) >= uAugend) {
+    *puResult = (uAugend + uAddend);
+    hr = S_OK;
+  } else {
+    *puResult = 0xffffffff;
+    hr = ERROR_ARITHMETIC_OVERFLOW;
+  }
+  return hr;
+}
+HRESULT IntToUInt(int in, UINT *out) {
+  HRESULT hr;
+  if (in >= 0) {
+    *out = (UINT)in;
+    hr = S_OK;
+  } else {
+    *out = 0xffffffff;
+    hr = ERROR_ARITHMETIC_OVERFLOW;
+  }
+  return hr;
+}
+HRESULT SizeTToInt(size_t in, int *out) {
+  HRESULT hr;
+  if(in <= INT_MAX) {
+    *out = (int)in;
+    hr = S_OK;
+  }
+  else {
+    *out = 0xffffffff;
+    hr = ERROR_ARITHMETIC_OVERFLOW;
+  }
+  return hr;
+}
+HRESULT UInt32Mult(UINT a, UINT b, UINT *out) {
+  uint64_t result = (uint64_t)a * (uint64_t)b;
+  if (result > uint64_t(UINT_MAX))
+    return ERROR_ARITHMETIC_OVERFLOW;
+
+  *out = (uint32_t)result;
+  return S_OK;
+}
+
+int _stricmp(const char *str1, const char *str2) {
+  size_t i = 0;
+  for (; str1[i] && str2[i]; ++i) {
+    int d = std::tolower(str1[i]) - std::tolower(str2[i]);
+    if (d != 0)
+      return d;
+  }
+  return str1[i] - str2[i];
+}
+
+int _wcsicmp(const wchar_t *str1, const wchar_t *str2) {
+  size_t i = 0;
+  for (; str1[i] && str2[i]; ++i) {
+    int d = std::towlower(str1[i]) - std::towlower(str2[i]);
+    if (d != 0)
+      return d;
+  }
+  return str1[i] - str2[i];
+}
+
+int _wcsnicmp(const wchar_t *str1, const wchar_t *str2, size_t n) {
+  size_t i = 0;
+  for (; i < n && str1[i] && str2[i]; ++i) {
+    int d = std::towlower(str1[i]) - std::towlower(str2[i]);
+    if (d != 0)
+      return d;
+  }
+  if (i >= n) return 0;
+  return str1[i] - str2[i];
+}
+
+unsigned char _BitScanForward(unsigned long * Index, unsigned long Mask) {
+  unsigned long l;
+  if (!Mask) return 0;
+  for (l=0; !(Mask&1); l++) Mask >>= 1;
+  *Index = l;
+  return 1;
+}
+
+HRESULT CoGetMalloc(DWORD dwMemContext, IMalloc **ppMalloc) {
+  *ppMalloc = new IMalloc;
+  (*ppMalloc)->AddRef();
+  return S_OK;
+}
+
+HANDLE CreateFile2(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess,
+                   _In_ DWORD dwShareMode, _In_ DWORD dwCreationDisposition,
+                   _In_opt_ void *pCreateExParams) {
+  return CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, pCreateExParams,
+                     dwCreationDisposition, FILE_ATTRIBUTE_NORMAL, nullptr);
+}
+
+HANDLE CreateFileW(_In_ LPCWSTR lpFileName, _In_ DWORD dwDesiredAccess,
+                   _In_ DWORD dwShareMode, _In_opt_ void *lpSecurityAttributes,
+                   _In_ DWORD dwCreationDisposition,
+                   _In_ DWORD dwFlagsAndAttributes,
+                   _In_opt_ HANDLE hTemplateFile) {
+  CW2A pUtf8FileName(lpFileName);
+  size_t fd = -1;
+  int flags = 0;
+
+  if (dwDesiredAccess & GENERIC_WRITE)
+    if (dwDesiredAccess & GENERIC_READ)
+      flags |= O_RDWR;
+    else
+      flags |= O_WRONLY;
+  else // dwDesiredAccess may be 0, but open() demands something here. This is mostly harmless
+    flags |= O_RDONLY;
+
+  if (dwCreationDisposition == CREATE_ALWAYS)
+    flags |= (O_CREAT | O_TRUNC);
+  if (dwCreationDisposition == OPEN_ALWAYS)
+    flags |= O_CREAT;
+  else if (dwCreationDisposition == CREATE_NEW)
+    flags |= (O_CREAT | O_EXCL);
+  else if (dwCreationDisposition == TRUNCATE_EXISTING)
+    flags |= O_TRUNC;
+  // OPEN_EXISTING represents default open() behavior
+
+  // Catch Implementation limitations.
+  assert(!lpSecurityAttributes && "security attributes not supported in CreateFileW yet");
+  assert(!hTemplateFile && "template file not supported in CreateFileW yet");
+  assert(dwFlagsAndAttributes == FILE_ATTRIBUTE_NORMAL &&
+         "Attributes other than NORMAL not supported in CreateFileW yet");
+
+  while ((int)(fd = open(pUtf8FileName, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)) < 0) {
+    if (errno != EINTR)
+      return INVALID_HANDLE_VALUE;
+  }
+
+  return (HANDLE)fd;
+}
+
+BOOL GetFileSizeEx(_In_ HANDLE hFile, _Out_ PLARGE_INTEGER lpFileSize) {
+  int fd = (size_t)hFile;
+  struct stat fdstat;
+  int rv = fstat(fd, &fdstat);
+  if (!rv) {
+    lpFileSize->QuadPart = (LONGLONG)fdstat.st_size;
+    return true;
+  }
+  return false;
+}
+
+BOOL ReadFile(_In_ HANDLE hFile, _Out_ LPVOID lpBuffer,
+              _In_ DWORD nNumberOfBytesToRead,
+              _Out_opt_ LPDWORD lpNumberOfBytesRead,
+              _Inout_opt_ void *lpOverlapped) {
+  size_t fd = (size_t)hFile;
+  ssize_t rv = -1;
+
+  // Implementation limitation
+  assert(!lpOverlapped && "Overlapping not supported in ReadFile yet.");
+
+  rv = read(fd, lpBuffer, nNumberOfBytesToRead);
+  if (rv < 0)
+    return false;
+  *lpNumberOfBytesRead = rv;
+  return true;
+}
+
+BOOL WriteFile(_In_ HANDLE hFile, _In_ LPCVOID lpBuffer,
+               _In_ DWORD nNumberOfBytesToWrite,
+               _Out_opt_ LPDWORD lpNumberOfBytesWritten,
+               _Inout_opt_ void *lpOverlapped) {
+  size_t fd = (size_t)hFile;
+  ssize_t rv = -1;
+
+  // Implementation limitation
+  assert(!lpOverlapped && "Overlapping not supported in WriteFile yet.");
+
+  rv = write(fd, lpBuffer, nNumberOfBytesToWrite);
+  if (rv < 0)
+    return false;
+  *lpNumberOfBytesWritten = rv;
+  return true;
+}
+
+BOOL CloseHandle(_In_ HANDLE hObject) {
+  int fd = (size_t)hObject;
+  return !close(fd);
+}
+
+// Half-hearted implementation of a heap structure
+// Enables size queries, maximum allocation limit, and collective free at heap destruction
+// Does not perform any preallocation or allocation organization.
+// Does not respect any flags except for HEAP_ZERO_MEMORY
+struct SimpleAllocation {
+  LPVOID ptr;
+  SIZE_T size;
+};
+
+struct SimpleHeap {
+  std::map<LPCVOID, SimpleAllocation> allocs;
+  SIZE_T maxSize, curSize;
+};
+
+HANDLE HeapCreate(DWORD flOptions, SIZE_T dwInitialSize , SIZE_T dwMaximumSize) {
+  SimpleHeap *simpHeap = new SimpleHeap;
+  simpHeap->maxSize = dwMaximumSize;
+  simpHeap->curSize = 0;
+  return (HANDLE)simpHeap;
+}
+
+BOOL HeapDestroy(HANDLE hHeap) {
+  SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
+
+  for (auto it = simpHeap->allocs.begin(), e = simpHeap->allocs.end(); it != e; it++)
+    free(it->second.ptr);
+
+  delete simpHeap;
+  return true;
+}
+
+LPVOID HeapAlloc(HANDLE hHeap, DWORD dwFlags, SIZE_T dwBytes) {
+  LPVOID ptr = nullptr;
+  SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
+
+  if (simpHeap->maxSize && simpHeap->curSize + dwBytes > simpHeap->maxSize)
+    return nullptr;
+
+  if (dwFlags == HEAP_ZERO_MEMORY)
+    ptr = calloc(1, dwBytes);
+  else
+    ptr = malloc(dwBytes);
+
+  simpHeap->allocs[ptr] = {ptr, dwBytes};
+  simpHeap->curSize += dwBytes;
+
+  return ptr;
+}
+
+LPVOID HeapReAlloc(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem, SIZE_T dwBytes) {
+  LPVOID ptr = nullptr;
+  SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
+  SIZE_T oSize = simpHeap->allocs[lpMem].size;
+
+  if (simpHeap->maxSize && simpHeap->curSize - oSize + dwBytes > simpHeap->maxSize)
+    return nullptr;
+
+  ptr = realloc(lpMem, dwBytes);
+  if (dwFlags == HEAP_ZERO_MEMORY && oSize < dwBytes)
+    memset((char*)ptr + oSize, 0, dwBytes - oSize);
+
+  simpHeap->allocs.erase(lpMem);
+  simpHeap->curSize -= oSize;
+
+  simpHeap->allocs[ptr] = {ptr, dwBytes};
+  simpHeap->curSize += dwBytes;
+
+  return ptr;
+}
+
+BOOL HeapFree(HANDLE hHeap, DWORD dwFlags, LPVOID lpMem) {
+  SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
+  SIZE_T oSize = simpHeap->allocs[lpMem].size;
+
+  free(lpMem);
+
+  simpHeap->allocs.erase(lpMem);
+  simpHeap->curSize -= oSize;
+
+  return true;
+}
+
+SIZE_T HeapSize(HANDLE hHeap, DWORD dwFlags, LPCVOID lpMem) {
+  SimpleHeap *simpHeap = (SimpleHeap*)hHeap;
+  return simpHeap->allocs[lpMem].size;
+}
+
+static SimpleHeap g_processHeap;
+
+HANDLE GetProcessHeap() {
+  return (HANDLE)&g_processHeap;
+}
+
+#endif // _WIN32

+ 8 - 1
lib/DxcSupport/dxcapi.use.cpp

@@ -13,6 +13,7 @@
 #include "dxc/Support/dxcapi.use.h"
 #include "dxc/Support/dxcapi.use.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/Unicode.h"
 #include "dxc/Support/Unicode.h"
+#include "dxc/Support/WinFunctions.h"
 
 
 namespace dxc {
 namespace dxc {
 
 
@@ -37,6 +38,12 @@ static std::string GetWin32ErrorMessage(DWORD err) {
   }
   }
   return std::string();
   return std::string();
 }
 }
+#else
+static std::string GetWin32ErrorMessage(DWORD err) {
+  // Since we use errno for handling messages, we use strerror to get the error
+  // message.
+  return std::string(std::strerror(err));
+}
 #endif // _WIN32
 #endif // _WIN32
 
 
 void IFT_Data(HRESULT hr, LPCWSTR data) {
 void IFT_Data(HRESULT hr, LPCWSTR data) {
@@ -160,7 +167,7 @@ void WriteUtf8ToConsoleSizeT(_In_opt_count_(charCount) const char *pText,
     return;
     return;
   }
   }
 
 
-  int charCountInt;
+  int charCountInt = 0;
   IFT(SizeTToInt(charCount, &charCountInt));
   IFT(SizeTToInt(charCount, &charCountInt));
   WriteUtf8ToConsole(pText, charCountInt, streamType);
   WriteUtf8ToConsole(pText, charCountInt, streamType);
 }
 }

+ 8 - 13
lib/DxcSupport/dxcmem.cpp

@@ -15,25 +15,16 @@
 #endif
 #endif
 
 
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
+#include "dxc/Support/WinFunctions.h"
 #include "llvm/Support/ThreadLocal.h"
 #include "llvm/Support/ThreadLocal.h"
 #include <memory>
 #include <memory>
 
 
 static llvm::sys::ThreadLocal<IMalloc> *g_ThreadMallocTls;
 static llvm::sys::ThreadLocal<IMalloc> *g_ThreadMallocTls;
 static IMalloc *g_pDefaultMalloc;
 static IMalloc *g_pDefaultMalloc;
 
 
-// Used by DllMain to set up and tear down per-thread tracking.
-HRESULT DxcInitThreadMalloc() throw();
-void DxcCleanupThreadMalloc() throw();
-
-// Used by APIs that are entry points to set up per-thread/invocation allocator.
-void DxcSetThreadMalloc(IMalloc *pMalloc) throw();
-void DxcSetThreadMallocOrDefault(IMalloc *pMalloc) throw(); 
-void DxcClearThreadMalloc() throw();
-
-// Used to retrieve the current invocation's allocator or perform an alloc/free/realloc.
-IMalloc *DxcGetThreadMallocNoRef() throw();
-_Ret_maybenull_ _Post_writable_byte_size_(nBytes) void *DxcThreadAlloc(size_t nBytes) throw();
-void DxcThreadFree(void *) throw();
+#ifndef _WIN32
+#pragma GCC visibility push(hidden)
+#endif
 
 
 HRESULT DxcInitThreadMalloc() throw() {
 HRESULT DxcInitThreadMalloc() throw() {
   DXASSERT(g_pDefaultMalloc == nullptr, "else InitThreadMalloc already called");
   DXASSERT(g_pDefaultMalloc == nullptr, "else InitThreadMalloc already called");
@@ -96,3 +87,7 @@ IMalloc *DxcSwapThreadMalloc(IMalloc *pMalloc, IMalloc **ppPrior) throw() {
 IMalloc *DxcSwapThreadMallocOrDefault(IMalloc *pMallocOrNull, IMalloc **ppPrior) throw() {
 IMalloc *DxcSwapThreadMallocOrDefault(IMalloc *pMallocOrNull, IMalloc **ppPrior) throw() {
   return DxcSwapThreadMalloc(pMallocOrNull ? pMallocOrNull : g_pDefaultMalloc, ppPrior);
   return DxcSwapThreadMalloc(pMallocOrNull ? pMallocOrNull : g_pDefaultMalloc, ppPrior);
 }
 }
+
+#ifndef _WIN32
+#pragma GCC visibility pop
+#endif

+ 4 - 4
lib/HLSL/DxilContainerAssembler.cpp

@@ -1431,6 +1431,10 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
 
 
   // If we have debug information present, serialize it to a debug part, then use the stripped version as the canonical program version.
   // If we have debug information present, serialize it to a debug part, then use the stripped version as the canonical program version.
   CComPtr<AbstractMemoryStream> pProgramStream = pInputProgramStream;
   CComPtr<AbstractMemoryStream> pProgramStream = pInputProgramStream;
+  const uint32_t DebugInfoNameHashLen = 32;   // 32 chars of MD5
+  const uint32_t DebugInfoNameSuffix = 4;     // '.lld'
+  const uint32_t DebugInfoNameNullAndPad = 4; // '\0\0\0\0'
+  CComPtr<AbstractMemoryStream> pHashStream;
   if (HasDebugInfo(*pModule->GetModule())) {
   if (HasDebugInfo(*pModule->GetModule())) {
     uint32_t debugInUInt32, debugPaddingBytes;
     uint32_t debugInUInt32, debugPaddingBytes;
     GetPaddedProgramPartSize(pInputProgramStream, debugInUInt32, debugPaddingBytes);
     GetPaddedProgramPartSize(pInputProgramStream, debugInUInt32, debugPaddingBytes);
@@ -1450,16 +1454,12 @@ void hlsl::SerializeDxilContainerForModule(DxilModule *pModule,
     WriteBitcodeToFile(pModule->GetModule(), outStream, true);
     WriteBitcodeToFile(pModule->GetModule(), outStream, true);
 
 
     if (Flags & SerializeDxilFlags::IncludeDebugNamePart) {
     if (Flags & SerializeDxilFlags::IncludeDebugNamePart) {
-      CComPtr<AbstractMemoryStream> pHashStream;
       // If the debug name should be specific to the sources, base the name on the debug
       // If the debug name should be specific to the sources, base the name on the debug
       // bitcode, which will include the source references, line numbers, etc. Otherwise,
       // bitcode, which will include the source references, line numbers, etc. Otherwise,
       // do it exclusively on the target shader bitcode.
       // do it exclusively on the target shader bitcode.
       pHashStream = (int)(Flags & SerializeDxilFlags::DebugNameDependOnSource)
       pHashStream = (int)(Flags & SerializeDxilFlags::DebugNameDependOnSource)
                         ? CComPtr<AbstractMemoryStream>(pModuleBitcode)
                         ? CComPtr<AbstractMemoryStream>(pModuleBitcode)
                         : CComPtr<AbstractMemoryStream>(pProgramStream);
                         : CComPtr<AbstractMemoryStream>(pProgramStream);
-      const uint32_t DebugInfoNameHashLen = 32;   // 32 chars of MD5
-      const uint32_t DebugInfoNameSuffix = 4;     // '.lld'
-      const uint32_t DebugInfoNameNullAndPad = 4; // '\0\0\0\0'
       const uint32_t DebugInfoContentLen =
       const uint32_t DebugInfoContentLen =
           sizeof(DxilShaderDebugName) + DebugInfoNameHashLen +
           sizeof(DxilShaderDebugName) + DebugInfoNameHashLen +
           DebugInfoNameSuffix + DebugInfoNameNullAndPad;
           DebugInfoNameSuffix + DebugInfoNameNullAndPad;

+ 10 - 0
lib/HLSL/DxilContainerReflection.cpp

@@ -30,8 +30,10 @@
 
 
 #include "dxc/dxcapi.h"
 #include "dxc/dxcapi.h"
 
 
+#ifdef LLVM_ON_WIN32
 #include "d3d12shader.h" // for compatibility
 #include "d3d12shader.h" // for compatibility
 #include "d3d11shader.h" // for compatibility
 #include "d3d11shader.h" // for compatibility
+
 const GUID IID_ID3D11ShaderReflection_43 = {
 const GUID IID_ID3D11ShaderReflection_43 = {
     0x0a233719,
     0x0a233719,
     0x3960,
     0x3960,
@@ -2340,3 +2342,11 @@ ID3D12FunctionReflection *DxilLibraryReflection::GetFunctionByIndex(INT Function
 
 
 // DxilRuntimeReflection implementation
 // DxilRuntimeReflection implementation
 #include "dxc/HLSL/DxilRuntimeReflection.inl"
 #include "dxc/HLSL/DxilRuntimeReflection.inl"
+
+#else
+void hlsl::CreateDxcContainerReflection(IDxcContainerReflection **ppResult) {
+  *ppResult = nullptr;
+}
+
+DEFINE_CROSS_PLATFORM_UUIDOF(IDxcContainerReflection)
+#endif // LLVM_ON_WIN32

+ 2 - 0
lib/HLSL/DxilLegalizeSampleOffsetPass.cpp

@@ -153,6 +153,8 @@ void DxilLegalizeSampleOffsetPass::FinalCheck(
 void DxilLegalizeSampleOffsetPass::TryUnrollLoop(
 void DxilLegalizeSampleOffsetPass::TryUnrollLoop(
     std::vector<Instruction *> &illegalOffsets, Function &F) {
     std::vector<Instruction *> &illegalOffsets, Function &F) {
   legacy::FunctionPassManager PM(F.getParent());
   legacy::FunctionPassManager PM(F.getParent());
+  // Scalarize aggregates as mem2reg only applies on scalars.
+  PM.add(createSROAPass());
   // Always need mem2reg for simplify illegal offsets.
   // Always need mem2reg for simplify illegal offsets.
   PM.add(createPromoteMemoryToRegisterPass());
   PM.add(createPromoteMemoryToRegisterPass());
 
 

+ 1 - 0
lib/HLSL/DxilMetadataHelper.cpp

@@ -31,6 +31,7 @@
 #include <algorithm>
 #include <algorithm>
 
 
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
+#include "dxc/Support/WinFunctions.h"
 
 
 using namespace llvm;
 using namespace llvm;
 using std::string;
 using std::string;

+ 5 - 6
lib/HLSL/DxilPreparePasses.cpp

@@ -330,12 +330,11 @@ public:
       // Strip parameters of entry function.
       // Strip parameters of entry function.
       StripEntryParameters(M, DM, IsLib);
       StripEntryParameters(M, DM, IsLib);
 
 
-      // Skip shader flag for library.
-      if (!IsLib) {
-        DM.CollectShaderFlagsForModule(); // Update flags to reflect any changes.
-                                 // Update Validator Version
-        DM.UpgradeToMinValidatorVersion();
-      }
+      // Update flags to reflect any changes.
+      DM.CollectShaderFlagsForModule();
+
+      // Update Validator Version
+      DM.UpgradeToMinValidatorVersion();
 
 
       return true;
       return true;
     }
     }

+ 1 - 0
lib/HLSL/DxilRootSignature.cpp

@@ -14,6 +14,7 @@
 #include "dxc/HLSL/DxilPipelineStateValidation.h"
 #include "dxc/HLSL/DxilPipelineStateValidation.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
+#include "dxc/Support/WinFunctions.h"
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/Support/FileIOHelper.h"
 #include "dxc/dxcapi.h"
 #include "dxc/dxcapi.h"
 
 

+ 31 - 7
lib/IR/PassRegistry.cpp

@@ -22,6 +22,7 @@
 
 
 using namespace llvm;
 using namespace llvm;
 
 
+#ifdef LLVM_ON_WIN32
 // HLSL Change Starts - managed statics are tied to DLL lifetime
 // HLSL Change Starts - managed statics are tied to DLL lifetime
 // Passes exist only in dxcompiler.dll or in a tool like opt that is updated.
 // Passes exist only in dxcompiler.dll or in a tool like opt that is updated.
 //
 //
@@ -43,6 +44,7 @@ static void CheckThreadId() {
       "else updating PassRegistry from incorrect thread");
       "else updating PassRegistry from incorrect thread");
 }
 }
 // HLSL Change Ends
 // HLSL Change Ends
+#endif
 
 
 // FIXME: We use ManagedStatic to erase the pass registrar on shutdown.
 // FIXME: We use ManagedStatic to erase the pass registrar on shutdown.
 // Unfortunately, passes are registered with static ctors, and having
 // Unfortunately, passes are registered with static ctors, and having
@@ -61,13 +63,17 @@ PassRegistry *PassRegistry::getPassRegistry() {
 PassRegistry::~PassRegistry() {}
 PassRegistry::~PassRegistry() {}
 
 
 const PassInfo *PassRegistry::getPassInfo(const void *TI) const {
 const PassInfo *PassRegistry::getPassInfo(const void *TI) const {
-  // sys::SmartScopedReader<true> Guard(Lock); // HLSL Change
+  #ifndef LLVM_ON_WIN32  // HLSL Change
+  sys::SmartScopedReader<true> Guard(Lock);
+  #endif
   MapType::const_iterator I = PassInfoMap.find(TI);
   MapType::const_iterator I = PassInfoMap.find(TI);
   return I != PassInfoMap.end() ? I->second : nullptr;
   return I != PassInfoMap.end() ? I->second : nullptr;
 }
 }
 
 
 const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const {
 const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const {
-  // sys::SmartScopedReader<true> Guard(Lock); // HLSL Change
+  #ifndef LLVM_ON_WIN32  // HLSL Change
+  sys::SmartScopedReader<true> Guard(Lock);
+  #endif
   StringMapType::const_iterator I = PassInfoStringMap.find(Arg);
   StringMapType::const_iterator I = PassInfoStringMap.find(Arg);
   return I != PassInfoStringMap.end() ? I->second : nullptr;
   return I != PassInfoStringMap.end() ? I->second : nullptr;
 }
 }
@@ -77,7 +83,11 @@ const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const {
 //
 //
 
 
 void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) {
 void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) {
-  CheckThreadId(); // sys::SmartScopedReader<true> Guard(Lock); // HLSL Change
+  #ifdef LLVM_ON_WIN32  // HLSL Change
+  CheckThreadId();
+  #else
+  sys::SmartScopedReader<true> Guard(Lock);
+  #endif
   bool Inserted =
   bool Inserted =
       PassInfoMap.insert(std::make_pair(PI.getTypeInfo(), &PI)).second;
       PassInfoMap.insert(std::make_pair(PI.getTypeInfo(), &PI)).second;
   assert(Inserted && "Pass registered multiple times!");
   assert(Inserted && "Pass registered multiple times!");
@@ -93,7 +103,9 @@ void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) {
 }
 }
 
 
 void PassRegistry::enumerateWith(PassRegistrationListener *L) {
 void PassRegistry::enumerateWith(PassRegistrationListener *L) {
-  // sys::SmartScopedReader<true> Guard(Lock); // HLSL Change
+  #ifndef LLVM_ON_WIN32  // HLSL Change
+  sys::SmartScopedReader<true> Guard(Lock);
+  #endif
   for (auto PassInfoPair : PassInfoMap)
   for (auto PassInfoPair : PassInfoMap)
     L->passEnumerate(PassInfoPair.second);
     L->passEnumerate(PassInfoPair.second);
 }
 }
@@ -117,7 +129,11 @@ void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
     assert(ImplementationInfo &&
     assert(ImplementationInfo &&
            "Must register pass before adding to AnalysisGroup!");
            "Must register pass before adding to AnalysisGroup!");
 
 
-    CheckThreadId(); // sys::SmartScopedReader<true> Guard(Lock); // HLSL Change
+    #ifdef LLVM_ON_WIN32  // HLSL Change
+    CheckThreadId();
+    #else
+    sys::SmartScopedReader<true> Guard(Lock);
+    #endif
 
 
     // Make sure we keep track of the fact that the implementation implements
     // Make sure we keep track of the fact that the implementation implements
     // the interface.
     // the interface.
@@ -140,12 +156,20 @@ void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
 }
 }
 
 
 void PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
 void PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
-  CheckThreadId(); // sys::SmartScopedReader<true> Guard(Lock); // HLSL Change
+  #ifdef LLVM_ON_WIN32  // HLSL Change
+  CheckThreadId();
+  #else
+  sys::SmartScopedReader<true> Guard(Lock);
+  #endif
   Listeners.push_back(L);
   Listeners.push_back(L);
 }
 }
 
 
 void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
 void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
-  CheckThreadId(); // sys::SmartScopedReader<true> Guard(Lock); // HLSL Change
+  #ifdef LLVM_ON_WIN32  // HLSL Change
+  CheckThreadId();
+  #else
+  sys::SmartScopedReader<true> Guard(Lock);
+  #endif
 
 
   auto I = std::find(Listeners.begin(), Listeners.end(), L);
   auto I = std::find(Listeners.begin(), Listeners.end(), L);
   Listeners.erase(I);
   Listeners.erase(I);

+ 197 - 0
lib/MSSupport/MSFileSystemImpl.cpp

@@ -89,105 +89,187 @@ public:
   virtual errno_t resize_file(_In_ LPCWSTR path, uint64_t size) throw() override;
   virtual errno_t resize_file(_In_ LPCWSTR path, uint64_t size) throw() override;
   virtual int Read(int fd, _Out_bytecap_(count) void* buffer, unsigned int count) throw() override;
   virtual int Read(int fd, _Out_bytecap_(count) void* buffer, unsigned int count) throw() override;
   virtual int Write(int fd, _In_bytecount_(count) const void* buffer, unsigned int count) throw() override;
   virtual int Write(int fd, _In_bytecount_(count) const void* buffer, unsigned int count) throw() override;
+#ifndef _WIN32
+  virtual int Open(const char *lpFileName, int flags, mode_t mode) throw() override;
+  virtual int Stat(const char *lpFileName, struct stat *Status) throw() override;
+  virtual int Fstat(int FD, struct stat *Status) throw() override;
+#endif
 };
 };
 
 
 MSFileSystemForDisk::MSFileSystemForDisk()
 MSFileSystemForDisk::MSFileSystemForDisk()
 {
 {
+  #ifdef _WIN32
   _defaultAttributes = GetConsoleOutputTextAttributes();
   _defaultAttributes = GetConsoleOutputTextAttributes();
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) throw()
 BOOL MSFileSystemForDisk::FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData) throw()
 {
 {
+  #ifdef _WIN32
   return ::FindNextFileW(hFindFile, lpFindFileData);
   return ::FindNextFileW(hFindFile, lpFindFileData);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 HANDLE MSFileSystemForDisk::FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) throw()
 HANDLE MSFileSystemForDisk::FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData) throw()
 {
 {
+  #ifdef _WIN32
   return ::FindFirstFileW(lpFileName, lpFindFileData);
   return ::FindFirstFileW(lpFileName, lpFindFileData);
+  #else
+  assert(false && "Not implemented for Unix");
+  return nullptr;
+  #endif
 }
 }
 
 
 void MSFileSystemForDisk::FindClose(HANDLE findHandle) throw()
 void MSFileSystemForDisk::FindClose(HANDLE findHandle) throw()
 {
 {
+  #ifdef _WIN32
   ::FindClose(findHandle);
   ::FindClose(findHandle);
+  #else
+  assert(false && "Not implemented for Unix");
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 HANDLE MSFileSystemForDisk::CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes) throw()
 HANDLE MSFileSystemForDisk::CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes) throw()
 {
 {
+  #ifdef _WIN32
   return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, nullptr, dwCreationDisposition, dwFlagsAndAttributes, nullptr);
   return ::CreateFileW(lpFileName, dwDesiredAccess, dwShareMode, nullptr, dwCreationDisposition, dwFlagsAndAttributes, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return nullptr;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::SetFileTime(HANDLE hFile, _In_opt_ const FILETIME *lpCreationTime, _In_opt_ const FILETIME *lpLastAccessTime, _In_opt_ const FILETIME *lpLastWriteTime) throw()
 BOOL MSFileSystemForDisk::SetFileTime(HANDLE hFile, _In_opt_ const FILETIME *lpCreationTime, _In_opt_ const FILETIME *lpLastAccessTime, _In_opt_ const FILETIME *lpLastWriteTime) throw()
 {
 {
+  #ifdef _WIN32
   return ::SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
   return ::SetFileTime(hFile, lpCreationTime, lpLastAccessTime, lpLastWriteTime);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation) throw()
 BOOL MSFileSystemForDisk::GetFileInformationByHandle(HANDLE hFile, LPBY_HANDLE_FILE_INFORMATION lpFileInformation) throw()
 {
 {
+  #ifdef _WIN32
   return ::GetFileInformationByHandle(hFile, lpFileInformation);
   return ::GetFileInformationByHandle(hFile, lpFileInformation);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetFileType(HANDLE hFile) throw()
 DWORD MSFileSystemForDisk::GetFileType(HANDLE hFile) throw()
 {
 {
+  #ifdef _WIN32
   return ::GetFileType(hFile);
   return ::GetFileType(hFile);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::CreateHardLinkW(LPCWSTR lpFileName, LPCWSTR lpExistingFileName) throw()
 BOOL MSFileSystemForDisk::CreateHardLinkW(LPCWSTR lpFileName, LPCWSTR lpExistingFileName) throw()
 {
 {
+  #ifdef _WIN32
   return ::CreateHardLinkW(lpFileName, lpExistingFileName, nullptr);
   return ::CreateHardLinkW(lpFileName, lpExistingFileName, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags) throw()
 BOOL MSFileSystemForDisk::MoveFileExW(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, DWORD dwFlags) throw()
 {
 {
+  #ifdef _WIN32
   return ::MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags);
   return ::MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetFileAttributesW(LPCWSTR lpFileName) throw()
 DWORD MSFileSystemForDisk::GetFileAttributesW(LPCWSTR lpFileName) throw()
 {
 {
+  #ifdef _WIN32
   return ::GetFileAttributesW(lpFileName);
   return ::GetFileAttributesW(lpFileName);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::CloseHandle(HANDLE hObject) throw()
 BOOL MSFileSystemForDisk::CloseHandle(HANDLE hObject) throw()
 {
 {
+  #ifdef _WIN32
   return ::CloseHandle(hObject);
   return ::CloseHandle(hObject);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::DeleteFileW(LPCWSTR lpFileName) throw()
 BOOL MSFileSystemForDisk::DeleteFileW(LPCWSTR lpFileName) throw()
 {
 {
+  #ifdef _WIN32
   return ::DeleteFileW(lpFileName);
   return ::DeleteFileW(lpFileName);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::RemoveDirectoryW(LPCWSTR lpFileName) throw()
 BOOL MSFileSystemForDisk::RemoveDirectoryW(LPCWSTR lpFileName) throw()
 {
 {
+  #ifdef _WIN32
   return ::RemoveDirectoryW(lpFileName);
   return ::RemoveDirectoryW(lpFileName);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::CreateDirectoryW(LPCWSTR lpPathName) throw()
 BOOL MSFileSystemForDisk::CreateDirectoryW(LPCWSTR lpPathName) throw()
 {
 {
+  #ifdef _WIN32
   return ::CreateDirectoryW(lpPathName, nullptr);
   return ::CreateDirectoryW(lpPathName, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetCurrentDirectoryW(DWORD nBufferLength,  LPWSTR lpBuffer) throw()
 DWORD MSFileSystemForDisk::GetCurrentDirectoryW(DWORD nBufferLength,  LPWSTR lpBuffer) throw()
 {
 {
+  #ifdef _WIN32
   return ::GetCurrentDirectoryW(nBufferLength, lpBuffer);
   return ::GetCurrentDirectoryW(nBufferLength, lpBuffer);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetMainModuleFileNameW(LPWSTR lpFilename, DWORD nSize) throw()
 DWORD MSFileSystemForDisk::GetMainModuleFileNameW(LPWSTR lpFilename, DWORD nSize) throw()
 {
 {
+  #ifdef _WIN32
   // Add some code to ensure that the result is null terminated.
   // Add some code to ensure that the result is null terminated.
   if (nSize <= 1)
   if (nSize <= 1)
   {
   {
@@ -199,14 +281,24 @@ DWORD MSFileSystemForDisk::GetMainModuleFileNameW(LPWSTR lpFilename, DWORD nSize
   if (result == 0) return result;
   if (result == 0) return result;
   lpFilename[result] = L'\0';
   lpFilename[result] = L'\0';
   return result;
   return result;
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 DWORD MSFileSystemForDisk::GetTempPathW(DWORD nBufferLength, LPWSTR lpBuffer) throw()
 DWORD MSFileSystemForDisk::GetTempPathW(DWORD nBufferLength, LPWSTR lpBuffer) throw()
 {
 {
+  #ifdef _WIN32
   return ::GetTempPathW(nBufferLength, lpBuffer);
   return ::GetTempPathW(nBufferLength, lpBuffer);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
+#ifdef _WIN32
 namespace {
 namespace {
   typedef BOOLEAN(WINAPI *PtrCreateSymbolicLinkW)(
   typedef BOOLEAN(WINAPI *PtrCreateSymbolicLinkW)(
     /*__in*/ LPCWSTR lpSymlinkFileName,
     /*__in*/ LPCWSTR lpSymlinkFileName,
@@ -217,103 +309,181 @@ namespace {
     PtrCreateSymbolicLinkW(::GetProcAddress(
     PtrCreateSymbolicLinkW(::GetProcAddress(
     ::GetModuleHandleW(L"Kernel32.dll"), "CreateSymbolicLinkW"));
     ::GetModuleHandleW(L"Kernel32.dll"), "CreateSymbolicLinkW"));
 }
 }
+#endif
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOLEAN MSFileSystemForDisk::CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName, LPCWSTR lpTargetFileName, DWORD dwFlags) throw()
 BOOLEAN MSFileSystemForDisk::CreateSymbolicLinkW(LPCWSTR lpSymlinkFileName, LPCWSTR lpTargetFileName, DWORD dwFlags) throw()
 {
 {
+  #ifdef _WIN32
   return create_symbolic_link_api(lpSymlinkFileName, lpTargetFileName, dwFlags);
   return create_symbolic_link_api(lpSymlinkFileName, lpTargetFileName, dwFlags);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 bool MSFileSystemForDisk::SupportsCreateSymbolicLink() throw()
 bool MSFileSystemForDisk::SupportsCreateSymbolicLink() throw()
 {
 {
+  #ifdef _WIN32
   return create_symbolic_link_api != nullptr;
   return create_symbolic_link_api != nullptr;
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, _Out_opt_ LPDWORD lpNumberOfBytesRead) throw()
 BOOL MSFileSystemForDisk::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, _Out_opt_ LPDWORD lpNumberOfBytesRead) throw()
 {
 {
+  #ifdef _WIN32
   return ::ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, nullptr);
   return ::ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 HANDLE MSFileSystemForDisk::CreateFileMappingW(HANDLE hFile, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow) throw()
 HANDLE MSFileSystemForDisk::CreateFileMappingW(HANDLE hFile, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow) throw()
 {
 {
+  #ifdef _WIN32
   return ::CreateFileMappingW(hFile, nullptr, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, nullptr);
   return ::CreateFileMappingW(hFile, nullptr, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, nullptr);
+  #else
+  assert(false && "Not implemented for Unix");
+  return nullptr;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 LPVOID MSFileSystemForDisk::MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) throw()
 LPVOID MSFileSystemForDisk::MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) throw()
 {
 {
+  #ifdef _WIN32
   return ::MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap);
   return ::MapViewOfFile(hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap);
+  #else
+  assert(false && "Not implemented for Unix");
+  return nullptr;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 BOOL MSFileSystemForDisk::UnmapViewOfFile(LPCVOID lpBaseAddress) throw()
 BOOL MSFileSystemForDisk::UnmapViewOfFile(LPCVOID lpBaseAddress) throw()
 {
 {
+  #ifdef _WIN32
   return ::UnmapViewOfFile(lpBaseAddress);
   return ::UnmapViewOfFile(lpBaseAddress);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 bool MSFileSystemForDisk::FileDescriptorIsDisplayed(int fd) throw()
 bool MSFileSystemForDisk::FileDescriptorIsDisplayed(int fd) throw()
 {
 {
+  #ifdef _WIN32
   DWORD Mode;  // Unused
   DWORD Mode;  // Unused
   return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
   return (GetConsoleMode((HANDLE)_get_osfhandle(fd), &Mode) != 0);
+  #else
+  assert(false && "Not implemented for Unix");
+  return false;
+  #endif
 }
 }
 
 
 unsigned MSFileSystemForDisk::GetColumnCount(DWORD nStdHandle) throw()
 unsigned MSFileSystemForDisk::GetColumnCount(DWORD nStdHandle) throw()
 {
 {
+  #ifdef _WIN32
   unsigned Columns = 0;
   unsigned Columns = 0;
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   if (::GetConsoleScreenBufferInfo(GetStdHandle(nStdHandle), &csbi))
   if (::GetConsoleScreenBufferInfo(GetStdHandle(nStdHandle), &csbi))
     Columns = csbi.dwSize.X;
     Columns = csbi.dwSize.X;
   return Columns;
   return Columns;
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 unsigned MSFileSystemForDisk::GetConsoleOutputTextAttributes() throw()
 unsigned MSFileSystemForDisk::GetConsoleOutputTextAttributes() throw()
 {
 {
+  #ifdef _WIN32
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   CONSOLE_SCREEN_BUFFER_INFO csbi;
   if (::GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
   if (::GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
     return csbi.wAttributes;
     return csbi.wAttributes;
   return 0;
   return 0;
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 void MSFileSystemForDisk::SetConsoleOutputTextAttributes(unsigned attributes) throw()
 void MSFileSystemForDisk::SetConsoleOutputTextAttributes(unsigned attributes) throw()
 {
 {
+  #ifdef _WIN32
   ::SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attributes);
   ::SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attributes);
+  #else
+  assert(false && "Not implemented for Unix");
+  #endif
 }
 }
 
 
 void MSFileSystemForDisk::ResetConsoleOutputTextAttributes() throw()
 void MSFileSystemForDisk::ResetConsoleOutputTextAttributes() throw()
 {
 {
+  #ifdef _WIN32
   ::SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _defaultAttributes);
   ::SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), _defaultAttributes);
+  #else
+  assert(false && "Not implemented for Unix");
+  #endif
 }
 }
 
 
 int MSFileSystemForDisk::open_osfhandle(intptr_t osfhandle, int flags) throw()
 int MSFileSystemForDisk::open_osfhandle(intptr_t osfhandle, int flags) throw()
 {
 {
+  #ifdef _WIN32
   return ::_open_osfhandle(osfhandle, flags);
   return ::_open_osfhandle(osfhandle, flags);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 intptr_t MSFileSystemForDisk::get_osfhandle(int fd) throw()
 intptr_t MSFileSystemForDisk::get_osfhandle(int fd) throw()
 {
 {
+  #ifdef _WIN32
   return ::_get_osfhandle(fd);
   return ::_get_osfhandle(fd);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 int MSFileSystemForDisk::close(int fd) throw()
 int MSFileSystemForDisk::close(int fd) throw()
 {
 {
+  #ifdef _WIN32
   return ::_close(fd);
   return ::_close(fd);
+  #else
+  return ::close(fd);
+  #endif
 }
 }
 
 
 long MSFileSystemForDisk::lseek(int fd, long offset, int origin) throw()
 long MSFileSystemForDisk::lseek(int fd, long offset, int origin) throw()
 {
 {
+  #ifdef _WIN32
   return ::_lseek(fd, offset, origin);
   return ::_lseek(fd, offset, origin);
+  #else
+  return ::lseek(fd, offset, origin);
+  #endif
 }
 }
 
 
 int MSFileSystemForDisk::setmode(int fd, int mode) throw()
 int MSFileSystemForDisk::setmode(int fd, int mode) throw()
 {
 {
+  #ifdef _WIN32
   return ::_setmode(fd, mode);
   return ::_setmode(fd, mode);
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 errno_t MSFileSystemForDisk::resize_file(LPCWSTR path, uint64_t size) throw()
 errno_t MSFileSystemForDisk::resize_file(LPCWSTR path, uint64_t size) throw()
 {
 {
+  #ifdef _WIN32
   int fd = ::_wopen(path, O_BINARY | _O_RDWR, S_IWRITE);
   int fd = ::_wopen(path, O_BINARY | _O_RDWR, S_IWRITE);
   if (fd == -1)
   if (fd == -1)
     return errno;
     return errno;
@@ -324,20 +494,47 @@ errno_t MSFileSystemForDisk::resize_file(LPCWSTR path, uint64_t size) throw()
 #endif
 #endif
   ::_close(fd);
   ::_close(fd);
   return error;
   return error;
+
+  #else
+  assert(false && "Not implemented for Unix");
+  return 0;
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 int MSFileSystemForDisk::Read(int fd, void* buffer, unsigned int count) throw()
 int MSFileSystemForDisk::Read(int fd, void* buffer, unsigned int count) throw()
 {
 {
+  #ifdef _WIN32
   return ::_read(fd, buffer, count);
   return ::_read(fd, buffer, count);
+  #else
+  return ::read(fd, buffer, count);
+  #endif
 }
 }
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
 int MSFileSystemForDisk::Write(int fd, const void* buffer, unsigned int count) throw()
 int MSFileSystemForDisk::Write(int fd, const void* buffer, unsigned int count) throw()
 {
 {
+  #ifdef _WIN32
   return ::_write(fd, buffer, count);
   return ::_write(fd, buffer, count);
+  #else
+  return ::write(fd, buffer, count);
+  #endif
+}
+
+#ifndef _WIN32
+int MSFileSystemForDisk::Open(const char *lpFileName, int flags, mode_t mode) throw() {
+  return ::open(lpFileName, flags, mode);
 }
 }
 
 
+int MSFileSystemForDisk::Stat(const char *lpFileName, struct stat *Status) throw() {
+  return ::stat(lpFileName, Status);
+}
+
+int MSFileSystemForDisk::Fstat(int FD, struct stat *Status) throw() {
+  return ::fstat(FD, Status);
+}
+#endif
+
 } // end namespace fs
 } // end namespace fs
 } // end namespace sys
 } // end namespace sys
 } // end namespace llvm
 } // end namespace llvm

+ 2 - 1
lib/Support/CMakeLists.txt

@@ -28,7 +28,7 @@ if( NOT MSVC )
 endif( NOT MSVC )
 endif( NOT MSVC )
 
 
 # HLSL Change - add ignored sources
 # HLSL Change - add ignored sources
-set(HLSL_IGNORE_SOURCES DynamicLibrary.cpp PluginLoader.cpp)
+set(HLSL_IGNORE_SOURCES PluginLoader.cpp)
 
 
 add_llvm_library(LLVMSupport
 add_llvm_library(LLVMSupport
   APFloat.cpp
   APFloat.cpp
@@ -52,6 +52,7 @@ add_llvm_library(LLVMSupport
   DeltaAlgorithm.cpp
   DeltaAlgorithm.cpp
   DAGDeltaAlgorithm.cpp
   DAGDeltaAlgorithm.cpp
   Dwarf.cpp
   Dwarf.cpp
+  DynamicLibrary.cpp
   ErrorHandling.cpp
   ErrorHandling.cpp
   FileUtilities.cpp
   FileUtilities.cpp
   FileOutputBuffer.cpp
   FileOutputBuffer.cpp

+ 3 - 3
lib/Support/ErrorHandling.cpp

@@ -87,7 +87,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
     handlerData = ErrorHandlerUserData;
     handlerData = ErrorHandlerUserData;
   }
   }
 
 
-#if 0 // HLSL Change - unwind if necessary, but don't terminate the process
+#ifndef LLVM_ON_WIN32 // HLSL Change - unwind if necessary, but don't terminate the process
   if (handler) {
   if (handler) {
     handler(handlerData, Reason.str(), GenCrashDiag);
     handler(handlerData, Reason.str(), GenCrashDiag);
   } else {
   } else {
@@ -98,7 +98,7 @@ void llvm::report_fatal_error(const Twine &Reason, bool GenCrashDiag) {
     raw_svector_ostream OS(Buffer);
     raw_svector_ostream OS(Buffer);
     OS << "LLVM ERROR: " << Reason << "\n";
     OS << "LLVM ERROR: " << Reason << "\n";
     StringRef MessageStr = OS.str();
     StringRef MessageStr = OS.str();
-    ssize_t written = ::_write(2, MessageStr.data(), MessageStr.size());
+    ssize_t written = ::write(2, MessageStr.data(), MessageStr.size());
     (void)written; // If something went wrong, we deliberately just give up.
     (void)written; // If something went wrong, we deliberately just give up.
   }
   }
 
 
@@ -127,7 +127,7 @@ void llvm::llvm_unreachable_internal(const char *msg, const char *file,
   if (file)
   if (file)
     dbgs() << " at " << file << ":" << line;
     dbgs() << " at " << file << ":" << line;
   dbgs() << "!\n";
   dbgs() << "!\n";
-#if 0 // HLSL Change - unwind if necessary, but don't terminate the process
+#ifndef LLVM_ON_WIN32 // HLSL Change - unwind if necessary, but don't terminate the process
   abort();
   abort();
 #else
 #else
   RaiseException(STATUS_LLVM_UNREACHABLE, 0, 0, 0);
   RaiseException(STATUS_LLVM_UNREACHABLE, 0, 0, 0);

+ 34 - 0
lib/Support/MSFileSystemBasic.cpp

@@ -222,6 +222,11 @@ public:
   virtual errno_t resize_file(_In_ LPCWSTR path, uint64_t size) throw() override;
   virtual errno_t resize_file(_In_ LPCWSTR path, uint64_t size) throw() override;
   virtual int Read(int fd, _Out_bytecap_(count) void* buffer, unsigned int count) throw() override;
   virtual int Read(int fd, _Out_bytecap_(count) void* buffer, unsigned int count) throw() override;
   virtual int Write(int fd, _In_bytecount_(count) const void* buffer, unsigned int count) throw() override;
   virtual int Write(int fd, _In_bytecount_(count) const void* buffer, unsigned int count) throw() override;
+#ifndef _WIN32
+  virtual int Open(const char *lpFileName, int flags, mode_t mode) throw() override;
+  virtual int Stat(const char *lpFileName, struct stat *Status) throw() override;
+  virtual int Fstat(int FD, struct stat *Status) throw() override;
+#endif
 };
 };
 
 
 _Use_decl_annotations_
 _Use_decl_annotations_
@@ -942,6 +947,23 @@ Cleanup:
   return (int)cbWritten;
   return (int)cbWritten;
 }
 }
 
 
+#ifndef _WIN32
+int MSFileSystemForIface::Open(const char *lpFileName, int flags, mode_t mode) throw() {
+  SetLastError(ERROR_FUNCTION_NOT_CALLED);
+  return FALSE;
+}
+
+int MSFileSystemForIface::Stat(const char *lpFileName, struct stat *Status) throw() {
+  SetLastError(ERROR_FUNCTION_NOT_CALLED);
+  return FALSE;
+}
+
+int MSFileSystemForIface::Fstat(int FD, struct stat *Status) throw() {
+  SetLastError(ERROR_FUNCTION_NOT_CALLED);
+  return FALSE;
+}
+#endif
+
 } // end namespace fs
 } // end namespace fs
 } // end namespace sys
 } // end namespace sys
 } // end namespace llvm
 } // end namespace llvm
@@ -1099,6 +1121,18 @@ public:
   virtual int Write(int fd, const void* buffer, unsigned int count) throw() override
   virtual int Write(int fd, const void* buffer, unsigned int count) throw() override
   { return MSFileSystemBlockedErrno(); }
   { return MSFileSystemBlockedErrno(); }
 
 
+  // Unix interface
+#ifndef _WIN32
+  virtual int Open(const char *lpFileName, int flags, mode_t mode) throw() override
+  { return MSFileSystemBlockedErrno(); }
+
+  virtual int Stat(const char *lpFileName, struct stat *Status) throw() override
+  { return MSFileSystemBlockedErrno(); }
+
+  virtual int Fstat(int FD, struct stat *Status) throw() override
+  { return MSFileSystemBlockedErrno(); }
+#endif
+
 };
 };
 
 
 MSFileSystemBlocked::MSFileSystemBlocked()
 MSFileSystemBlocked::MSFileSystemBlocked()

+ 1 - 0
lib/Support/MemoryBuffer.cpp

@@ -377,6 +377,7 @@ getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
   char *BufPtr = const_cast<char *>(Buf->getBufferStart());
   char *BufPtr = const_cast<char *>(Buf->getBufferStart());
 
 
   size_t BytesLeft = MapSize;
   size_t BytesLeft = MapSize;
+#undef HAVE_PREAD // HLSL Change - pread bypasses needed layers
 #ifndef HAVE_PREAD
 #ifndef HAVE_PREAD
   if (llvm::sys::fs::msf_lseek(FD, Offset, SEEK_SET) == -1)  // HLSL Change - use msf_lseek
   if (llvm::sys::fs::msf_lseek(FD, Offset, SEEK_SET) == -1)  // HLSL Change - use msf_lseek
     return std::error_code(errno, std::generic_category());
     return std::error_code(errno, std::generic_category());

+ 93 - 4
lib/Support/Unix/Path.inc

@@ -60,6 +60,8 @@
 # define PATH_MAX 4096
 # define PATH_MAX 4096
 #endif
 #endif
 
 
+#include "llvm/Support/MSFileSystem.h" // HLSL change
+
 using namespace llvm;
 using namespace llvm;
 
 
 namespace llvm {
 namespace llvm {
@@ -379,13 +381,15 @@ std::error_code status(const Twine &Path, file_status &Result) {
   StringRef P = Path.toNullTerminatedStringRef(PathStorage);
   StringRef P = Path.toNullTerminatedStringRef(PathStorage);
 
 
   struct stat Status;
   struct stat Status;
-  int StatRet = ::stat(P.begin(), &Status);
+  MSFileSystem* fsr = GetCurrentThreadFileSystem(); // HLSL Change
+  int StatRet = fsr->Stat(P.begin(), &Status); // HLSL Change - FS abstraction
   return fillStatus(StatRet, Status, Result);
   return fillStatus(StatRet, Status, Result);
 }
 }
 
 
 std::error_code status(int FD, file_status &Result) {
 std::error_code status(int FD, file_status &Result) {
   struct stat Status;
   struct stat Status;
-  int StatRet = ::fstat(FD, &Status);
+  MSFileSystem* fsr = GetCurrentThreadFileSystem(); // HLSL Change
+  int StatRet = fsr->Fstat(FD, &Status); // HLSL Change - FS abstraction
   return fillStatus(StatRet, Status, Result);
   return fillStatus(StatRet, Status, Result);
 }
 }
 
 
@@ -504,7 +508,8 @@ std::error_code detail::directory_iterator_increment(detail::DirIterState &it) {
 std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
 std::error_code openFileForRead(const Twine &Name, int &ResultFD) {
   SmallString<128> Storage;
   SmallString<128> Storage;
   StringRef P = Name.toNullTerminatedStringRef(Storage);
   StringRef P = Name.toNullTerminatedStringRef(Storage);
-  while ((ResultFD = open(P.begin(), O_RDONLY)) < 0) {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem(); // HLSL Change
+  while ((ResultFD = fsr->Open(P.begin(), O_RDONLY)) < 0) { // HLSL Change - FS abstraction
     if (errno != EINTR)
     if (errno != EINTR)
       return std::error_code(errno, std::generic_category());
       return std::error_code(errno, std::generic_category());
   }
   }
@@ -534,7 +539,8 @@ std::error_code openFileForWrite(const Twine &Name, int &ResultFD,
 
 
   SmallString<128> Storage;
   SmallString<128> Storage;
   StringRef P = Name.toNullTerminatedStringRef(Storage);
   StringRef P = Name.toNullTerminatedStringRef(Storage);
-  while ((ResultFD = open(P.begin(), OpenFlags, Mode)) < 0) {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem(); // HLSL Change
+  while ((ResultFD = fsr->Open(P.begin(), OpenFlags, Mode)) < 0) { // HLSL Change - FS abstraction
     if (errno != EINTR)
     if (errno != EINTR)
       return std::error_code(errno, std::generic_category());
       return std::error_code(errno, std::generic_category());
   }
   }
@@ -619,3 +625,86 @@ void system_temp_directory(bool ErasedOnReboot, SmallVectorImpl<char> &Result) {
 
 
 } // end namespace sys
 } // end namespace sys
 } // end namespace llvm
 } // end namespace llvm
+
+
+// The following is implementation of MSFileSystem for Unix.
+// This will make usages of MSFileSystem throughout DirectXShaderCompiler
+// compatible with Unix.
+namespace llvm {
+namespace sys  {
+namespace fs {
+
+thread_local MSFileSystem* threadFS = nullptr;
+
+std::error_code SetupPerThreadFileSystem() throw() {
+  // This method is now a no-op since we are using thread_local.
+  return std::error_code();
+}
+void CleanupPerThreadFileSystem() throw() {
+  // This method is now a no-op since we are using thread_local.
+}
+
+MSFileSystem* GetCurrentThreadFileSystem() throw() {
+  return threadFS;
+}
+
+std::error_code SetCurrentThreadFileSystem(MSFileSystem* value) throw() {
+  // For now, disallow reentrancy in APIs (i.e., replace the current instance with another one).
+  if (value != nullptr) {
+    MSFileSystem* current = GetCurrentThreadFileSystem();
+    if (current != nullptr) {
+      return std::error_code(1131L, std::system_category());
+    }
+  }
+  threadFS = value;
+  return std::error_code();
+}
+
+int msf_read(int fd, void* buffer, unsigned int count) throw() {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->Read(fd, buffer, count);
+}
+
+int msf_write(int fd, const void* buffer, unsigned int count) throw() {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->Write(fd, buffer, count);
+}
+
+int msf_close(int fd) throw() {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->close(fd);
+}
+
+long msf_lseek(int fd, long offset, int origin) {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->lseek(fd, offset, origin);
+}
+
+int msf_setmode(int fd, int mode) throw() {
+  MSFileSystem* fsr = GetCurrentThreadFileSystem();
+  if (fsr == nullptr) {
+    errno = EBADF;
+    return -1;
+  }
+  return fsr->setmode(fd, mode);
+}
+
+} // namespace fs
+} // namespace sys
+} // namespace llvm

+ 1 - 1
lib/Support/Unix/Process.inc

@@ -262,7 +262,7 @@ std::error_code Process::SafelyCloseFileDescriptor(int FD) {
   // We need to save the error, if one occurs, because our subsequent call to
   // We need to save the error, if one occurs, because our subsequent call to
   // pthread_sigmask might tamper with errno.
   // pthread_sigmask might tamper with errno.
   int ErrnoFromClose = 0;
   int ErrnoFromClose = 0;
-  if (::close(FD) < 0)
+  if (fs::msf_close(FD) < 0)
     ErrnoFromClose = errno;
     ErrnoFromClose = errno;
   // Restore the signal mask back to what we saved earlier.
   // Restore the signal mask back to what we saved earlier.
   int EC = 0;
   int EC = 0;

+ 13 - 0
lib/Support/assert.cpp

@@ -8,6 +8,9 @@
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
 
 #include "assert.h"
 #include "assert.h"
+
+#ifdef _WIN32
+
 #include "windows.h"
 #include "windows.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/Global.h"
 
 
@@ -18,3 +21,13 @@ void llvm_assert(_In_z_ const char *_Message,
   OutputDebugFormatA("Error: assert(%s)\nFile:\n%s(%d)\nFunc:\t%s\n", _Message, _File, _Line, _Function);
   OutputDebugFormatA("Error: assert(%s)\nFile:\n%s(%d)\nFunc:\t%s\n", _Message, _File, _Line, _Function);
   RaiseException(STATUS_LLVM_ASSERT, 0, 0, 0);
   RaiseException(STATUS_LLVM_ASSERT, 0, 0, 0);
 }
 }
+
+#else
+
+#include <assert.h>
+
+void llvm_assert(const char* message, const char*, unsigned) {
+  assert(false && message);
+}
+
+#endif

+ 4 - 1
lib/Support/regerror.c

@@ -108,12 +108,15 @@ llvm_regerror(int errcode, const llvm_regex_t *preg, _Out_writes_all_(errbuf_siz
 				assert(strlen(r->name) < sizeof(convbuf));
 				assert(strlen(r->name) < sizeof(convbuf));
 				(void) llvm_strlcpy(convbuf, r->name, sizeof convbuf);
 				(void) llvm_strlcpy(convbuf, r->name, sizeof convbuf);
 			} else
 			} else
+                          // Begin HLSL Change
 #ifdef _WIN32
 #ifdef _WIN32
 				(void)_snprintf_s(convbuf, _countof(convbuf), _countof(convbuf),
 				(void)_snprintf_s(convbuf, _countof(convbuf), _countof(convbuf),
+				    "REG_0x%x", target);
 #else
 #else
 				(void)snprintf(convbuf, sizeof convbuf,
 				(void)snprintf(convbuf, sizeof convbuf,
-#endif // WIN32
 				    "REG_0x%x", target);
 				    "REG_0x%x", target);
+#endif // WIN32
+                          // End HLSL Change
 			s = convbuf;
 			s = convbuf;
 		} else
 		} else
 			s = r->explain;
 			s = r->explain;

+ 3 - 3
lib/Support/regex_impl.h

@@ -35,8 +35,8 @@
  *	@(#)regex.h	8.1 (Berkeley) 6/2/93
  *	@(#)regex.h	8.1 (Berkeley) 6/2/93
  */
  */
 
 
-#ifndef _REGEX_H_
-#define	_REGEX_H_
+#ifndef _REGEX_IMPL_H_ // HLSL Change
+#define _REGEX_IMPL_H_ // HLSL Change
 
 
 #include "dxc/Support/WinAdapter.h" // HLSL Change
 #include "dxc/Support/WinAdapter.h" // HLSL Change
 #include <sys/types.h>
 #include <sys/types.h>
@@ -119,4 +119,4 @@ size_t  llvm_strlcpy(
 }
 }
 #endif
 #endif
 
 
-#endif /* !_REGEX_H_ */
+#endif /* !_REGEX_IMPL_H_ */ // HLSL Change

+ 2 - 0
lib/Transforms/IPO/FunctionAttrs.cpp

@@ -1627,6 +1627,7 @@ bool FunctionAttrs::inferPrototypeAttributes(Function &F) {
     setOnlyReadsMemory(F, 1);
     setOnlyReadsMemory(F, 1);
     setOnlyReadsMemory(F, 2);
     setOnlyReadsMemory(F, 2);
     break;
     break;
+#if 0 // HLSL Change Starts - Exclude potentially duplicate 64bit versions
   case LibFunc::fopen64:
   case LibFunc::fopen64:
     if (FTy->getNumParams() != 2 ||
     if (FTy->getNumParams() != 2 ||
         !FTy->getReturnType()->isPointerTy() ||
         !FTy->getReturnType()->isPointerTy() ||
@@ -1653,6 +1654,7 @@ bool FunctionAttrs::inferPrototypeAttributes(Function &F) {
     setDoesNotThrow(F);
     setDoesNotThrow(F);
     setDoesNotAlias(F, 0);
     setDoesNotAlias(F, 0);
     break;
     break;
+#endif // HLSL Change Ends - Exclude potentially duplicate 64bit versions
   case LibFunc::fstat64:
   case LibFunc::fstat64:
   case LibFunc::fstatvfs64:
   case LibFunc::fstatvfs64:
     if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())
     if (FTy->getNumParams() != 2 || !FTy->getParamType(1)->isPointerTy())

+ 7 - 1
tools/CMakeLists.txt

@@ -17,7 +17,13 @@ endif()
 # add_llvm_tool_subdirectory(llvm-as) # HLSL Change
 # add_llvm_tool_subdirectory(llvm-as) # HLSL Change
 # add_llvm_tool_subdirectory(llvm-dis) # HLSL Change
 # add_llvm_tool_subdirectory(llvm-dis) # HLSL Change
 # add_llvm_tool_subdirectory(llvm-mc) # HLSL Change
 # add_llvm_tool_subdirectory(llvm-mc) # HLSL Change
-add_llvm_tool_subdirectory(dxexp) # HLSL Change
+
+# HLSL Change Begins
+if (WIN32)
+# This target can currently only be built on Windows.
+add_llvm_tool_subdirectory(dxexp)
+endif (WIN32)
+# HLSL Change ends
 
 
 # add_llvm_tool_subdirectory(llc) # HLSL Change
 # add_llvm_tool_subdirectory(llc) # HLSL Change
 # add_llvm_tool_subdirectory(llvm-ar) # HLSL Change
 # add_llvm_tool_subdirectory(llvm-ar) # HLSL Change

+ 1 - 0
tools/clang/include/clang/AST/HlslTypes.h

@@ -34,6 +34,7 @@ namespace clang {
   class FunctionTemplateDecl;
   class FunctionTemplateDecl;
   class InheritableAttr;
   class InheritableAttr;
   class NamedDecl;
   class NamedDecl;
+  class Sema;
   class TypeSourceInfo;
   class TypeSourceInfo;
   class TypedefDecl;
   class TypedefDecl;
 }
 }

+ 6 - 0
tools/clang/include/clang/Basic/Attr.td

@@ -754,6 +754,12 @@ def HLSLLinear : InheritableAttr {
   let Documentation = [Undocumented];
   let Documentation = [Undocumented];
 }
 }
 
 
+def HLSLCenter : InheritableAttr {
+  let Spellings = [CXX11<"", "center", 2015>];
+  let Subjects = SubjectList<[Function, ParmVar, Field]>;
+  let Documentation = [Undocumented];
+}
+
 def HLSLNoPerspective : InheritableAttr {
 def HLSLNoPerspective : InheritableAttr {
   let Spellings = [CXX11<"", "noperspective", 2015>];
   let Spellings = [CXX11<"", "noperspective", 2015>];
   let Subjects = SubjectList<[Function, ParmVar, Field]>;
   let Subjects = SubjectList<[Function, ParmVar, Field]>;

+ 1 - 0
tools/clang/include/clang/Basic/TokenKinds.def

@@ -498,6 +498,7 @@ KEYWORD(out                         , KEYHLSL)
 KEYWORD(inout                       , KEYHLSL)
 KEYWORD(inout                       , KEYHLSL)
 KEYWORD(uniform                     , KEYHLSL)
 KEYWORD(uniform                     , KEYHLSL)
 KEYWORD(precise                     , KEYHLSL)
 KEYWORD(precise                     , KEYHLSL)
+KEYWORD(center                      , KEYHLSL)
 KEYWORD(shared                      , KEYHLSL)
 KEYWORD(shared                      , KEYHLSL)
 KEYWORD(groupshared                 , KEYHLSL)
 KEYWORD(groupshared                 , KEYHLSL)
 KEYWORD(discard                     , KEYHLSL)
 KEYWORD(discard                     , KEYHLSL)

+ 12 - 0
tools/clang/include/clang/Basic/TokenKinds.h

@@ -100,6 +100,18 @@ inline bool isAnnotation(TokenKind K) {
   return false;
   return false;
 }
 }
 
 
+// HLSL Change Starts
+/// \brief Return true if this is a punctuator token.
+inline bool isPunctuator(TokenKind K) {
+#define PUNCTUATOR(NAME, SYMBOL) \
+  if (K == tok::NAME) \
+    return true;
+#include "clang/Basic/TokenKinds.def"
+#undef PUNCTUATOR
+  return false;
+}
+// HLSL Change Ends
+
 }  // end namespace tok
 }  // end namespace tok
 }  // end namespace clang
 }  // end namespace clang
 
 

+ 2 - 0
tools/clang/include/clang/Frontend/FrontendActions.h

@@ -137,6 +137,7 @@ public:
   bool hasCodeCompletionSupport() const override { return true; }
   bool hasCodeCompletionSupport() const override { return true; }
 };
 };
 
 
+#if 0 // HLSL change - no support for modules or PCH
 /// \brief Dump information about the given module file, to be used for
 /// \brief Dump information about the given module file, to be used for
 /// basic debugging and discovery.
 /// basic debugging and discovery.
 class DumpModuleInfoAction : public ASTFrontendAction {
 class DumpModuleInfoAction : public ASTFrontendAction {
@@ -162,6 +163,7 @@ protected:
 public:
 public:
   bool hasCodeCompletionSupport() const override { return false; }
   bool hasCodeCompletionSupport() const override { return false; }
 };
 };
+#endif // HLSL changes
 
 
 /**
 /**
  * \brief Frontend action adaptor that merges ASTs together.
  * \brief Frontend action adaptor that merges ASTs together.

+ 2 - 1
tools/clang/include/clang/SPIRV/EmitSPIRVOptions.h

@@ -32,7 +32,8 @@ struct EmitSPIRVOptions {
   bool codeGenHighLevel;
   bool codeGenHighLevel;
   bool defaultRowMajor;
   bool defaultRowMajor;
   bool disableValidation;
   bool disableValidation;
-  bool invertY;
+  bool invertY; // Additive inverse
+  bool invertW; // Multiplicative inverse
   bool useGlLayout;
   bool useGlLayout;
   bool useDxLayout;
   bool useDxLayout;
   bool enable16BitTypes;
   bool enable16BitTypes;

+ 7 - 552
tools/clang/include/clang/SPIRV/InstBuilder.h

@@ -23,6 +23,7 @@
 #include "spirv/unified1/spirv.hpp11"
 #include "spirv/unified1/spirv.hpp11"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
 
 
 namespace clang {
 namespace clang {
 namespace spirv {
 namespace spirv {
@@ -93,10 +94,10 @@ public:
   // Instruction building methods.
   // Instruction building methods.
   InstBuilder &opNop();
   InstBuilder &opNop();
   InstBuilder &opUndef(uint32_t result_type, uint32_t result_id);
   InstBuilder &opUndef(uint32_t result_type, uint32_t result_id);
-  InstBuilder &opSourceContinued(std::string continued_source);
+  InstBuilder &opSourceContinued(llvm::StringRef continued_source);
   InstBuilder &opSource(spv::SourceLanguage source_language, uint32_t version,
   InstBuilder &opSource(spv::SourceLanguage source_language, uint32_t version,
                         llvm::Optional<uint32_t> file,
                         llvm::Optional<uint32_t> file,
-                        llvm::Optional<std::string> source);
+                        llvm::Optional<llvm::StringRef> source);
   InstBuilder &opSourceExtension(std::string extension);
   InstBuilder &opSourceExtension(std::string extension);
   InstBuilder &opName(uint32_t target, std::string name);
   InstBuilder &opName(uint32_t target, std::string name);
   InstBuilder &opMemberName(uint32_t type, uint32_t member, std::string name);
   InstBuilder &opMemberName(uint32_t type, uint32_t member, std::string name);
@@ -307,179 +308,9 @@ public:
                                   uint32_t image);
                                   uint32_t image);
   InstBuilder &opImageQuerySamples(uint32_t result_type, uint32_t result_id,
   InstBuilder &opImageQuerySamples(uint32_t result_type, uint32_t result_id,
                                    uint32_t image);
                                    uint32_t image);
-  InstBuilder &opConvertFToU(uint32_t result_type, uint32_t result_id,
-                             uint32_t float_value);
-  InstBuilder &opConvertFToS(uint32_t result_type, uint32_t result_id,
-                             uint32_t float_value);
-  InstBuilder &opConvertSToF(uint32_t result_type, uint32_t result_id,
-                             uint32_t signed_value);
-  InstBuilder &opConvertUToF(uint32_t result_type, uint32_t result_id,
-                             uint32_t unsigned_value);
-  InstBuilder &opUConvert(uint32_t result_type, uint32_t result_id,
-                          uint32_t unsigned_value);
-  InstBuilder &opSConvert(uint32_t result_type, uint32_t result_id,
-                          uint32_t signed_value);
-  InstBuilder &opFConvert(uint32_t result_type, uint32_t result_id,
-                          uint32_t float_value);
-  InstBuilder &opQuantizeToF16(uint32_t result_type, uint32_t result_id,
-                               uint32_t value);
-  InstBuilder &opConvertPtrToU(uint32_t result_type, uint32_t result_id,
-                               uint32_t pointer);
-  InstBuilder &opSatConvertSToU(uint32_t result_type, uint32_t result_id,
-                                uint32_t signed_value);
-  InstBuilder &opSatConvertUToS(uint32_t result_type, uint32_t result_id,
-                                uint32_t unsigned_value);
-  InstBuilder &opConvertUToPtr(uint32_t result_type, uint32_t result_id,
-                               uint32_t integer_value);
-  InstBuilder &opPtrCastToGeneric(uint32_t result_type, uint32_t result_id,
-                                  uint32_t pointer);
-  InstBuilder &opGenericCastToPtr(uint32_t result_type, uint32_t result_id,
-                                  uint32_t pointer);
-  InstBuilder &opGenericCastToPtrExplicit(uint32_t result_type,
-                                          uint32_t result_id, uint32_t pointer,
-                                          spv::StorageClass storage);
-  InstBuilder &opBitcast(uint32_t result_type, uint32_t result_id,
-                         uint32_t operand);
-  InstBuilder &opSNegate(uint32_t result_type, uint32_t result_id,
-                         uint32_t operand);
-  InstBuilder &opFNegate(uint32_t result_type, uint32_t result_id,
-                         uint32_t operand);
-  InstBuilder &opIAdd(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFAdd(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opISub(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFSub(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opIMul(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFMul(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opUDiv(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opSDiv(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFDiv(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opUMod(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opSRem(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opSMod(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFRem(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFMod(uint32_t result_type, uint32_t result_id,
-                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opVectorTimesScalar(uint32_t result_type, uint32_t result_id,
-                                   uint32_t vector, uint32_t scalar);
-  InstBuilder &opMatrixTimesScalar(uint32_t result_type, uint32_t result_id,
-                                   uint32_t matrix, uint32_t scalar);
-  InstBuilder &opVectorTimesMatrix(uint32_t result_type, uint32_t result_id,
-                                   uint32_t vector, uint32_t matrix);
-  InstBuilder &opMatrixTimesVector(uint32_t result_type, uint32_t result_id,
-                                   uint32_t matrix, uint32_t vector);
-  InstBuilder &opMatrixTimesMatrix(uint32_t result_type, uint32_t result_id,
-                                   uint32_t left_matrix, uint32_t right_matrix);
-  InstBuilder &opOuterProduct(uint32_t result_type, uint32_t result_id,
-                              uint32_t vector_1, uint32_t vector_2);
-  InstBuilder &opDot(uint32_t result_type, uint32_t result_id,
-                     uint32_t vector_1, uint32_t vector_2);
-  InstBuilder &opIAddCarry(uint32_t result_type, uint32_t result_id,
-                           uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opISubBorrow(uint32_t result_type, uint32_t result_id,
-                            uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opUMulExtended(uint32_t result_type, uint32_t result_id,
-                              uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opSMulExtended(uint32_t result_type, uint32_t result_id,
-                              uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opAny(uint32_t result_type, uint32_t result_id, uint32_t vector);
-  InstBuilder &opAll(uint32_t result_type, uint32_t result_id, uint32_t vector);
-  InstBuilder &opIsNan(uint32_t result_type, uint32_t result_id, uint32_t x);
-  InstBuilder &opIsInf(uint32_t result_type, uint32_t result_id, uint32_t x);
-  InstBuilder &opIsFinite(uint32_t result_type, uint32_t result_id, uint32_t x);
-  InstBuilder &opIsNormal(uint32_t result_type, uint32_t result_id, uint32_t x);
-  InstBuilder &opSignBitSet(uint32_t result_type, uint32_t result_id,
-                            uint32_t x);
-  InstBuilder &opLessOrGreater(uint32_t result_type, uint32_t result_id,
-                               uint32_t x, uint32_t y);
-  InstBuilder &opOrdered(uint32_t result_type, uint32_t result_id, uint32_t x,
-                         uint32_t y);
-  InstBuilder &opUnordered(uint32_t result_type, uint32_t result_id, uint32_t x,
-                           uint32_t y);
-  InstBuilder &opLogicalEqual(uint32_t result_type, uint32_t result_id,
-                              uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opLogicalNotEqual(uint32_t result_type, uint32_t result_id,
-                                 uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opLogicalOr(uint32_t result_type, uint32_t result_id,
-                           uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opLogicalAnd(uint32_t result_type, uint32_t result_id,
-                            uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opLogicalNot(uint32_t result_type, uint32_t result_id,
-                            uint32_t operand);
   InstBuilder &opSelect(uint32_t result_type, uint32_t result_id,
   InstBuilder &opSelect(uint32_t result_type, uint32_t result_id,
                         uint32_t condition, uint32_t object_1,
                         uint32_t condition, uint32_t object_1,
                         uint32_t object_2);
                         uint32_t object_2);
-  InstBuilder &opIEqual(uint32_t result_type, uint32_t result_id,
-                        uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opINotEqual(uint32_t result_type, uint32_t result_id,
-                           uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opUGreaterThan(uint32_t result_type, uint32_t result_id,
-                              uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opSGreaterThan(uint32_t result_type, uint32_t result_id,
-                              uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opUGreaterThanEqual(uint32_t result_type, uint32_t result_id,
-                                   uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opSGreaterThanEqual(uint32_t result_type, uint32_t result_id,
-                                   uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opULessThan(uint32_t result_type, uint32_t result_id,
-                           uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opSLessThan(uint32_t result_type, uint32_t result_id,
-                           uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opULessThanEqual(uint32_t result_type, uint32_t result_id,
-                                uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opSLessThanEqual(uint32_t result_type, uint32_t result_id,
-                                uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFOrdEqual(uint32_t result_type, uint32_t result_id,
-                           uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFUnordEqual(uint32_t result_type, uint32_t result_id,
-                             uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFOrdNotEqual(uint32_t result_type, uint32_t result_id,
-                              uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFUnordNotEqual(uint32_t result_type, uint32_t result_id,
-                                uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFOrdLessThan(uint32_t result_type, uint32_t result_id,
-                              uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFUnordLessThan(uint32_t result_type, uint32_t result_id,
-                                uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFOrdGreaterThan(uint32_t result_type, uint32_t result_id,
-                                 uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFUnordGreaterThan(uint32_t result_type, uint32_t result_id,
-                                   uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFOrdLessThanEqual(uint32_t result_type, uint32_t result_id,
-                                   uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFUnordLessThanEqual(uint32_t result_type, uint32_t result_id,
-                                     uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFOrdGreaterThanEqual(uint32_t result_type, uint32_t result_id,
-                                      uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opFUnordGreaterThanEqual(uint32_t result_type,
-                                        uint32_t result_id, uint32_t operand_1,
-                                        uint32_t operand_2);
-  InstBuilder &opShiftRightLogical(uint32_t result_type, uint32_t result_id,
-                                   uint32_t base, uint32_t shift);
-  InstBuilder &opShiftRightArithmetic(uint32_t result_type, uint32_t result_id,
-                                      uint32_t base, uint32_t shift);
-  InstBuilder &opShiftLeftLogical(uint32_t result_type, uint32_t result_id,
-                                  uint32_t base, uint32_t shift);
-  InstBuilder &opBitwiseOr(uint32_t result_type, uint32_t result_id,
-                           uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opBitwiseXor(uint32_t result_type, uint32_t result_id,
-                            uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opBitwiseAnd(uint32_t result_type, uint32_t result_id,
-                            uint32_t operand_1, uint32_t operand_2);
-  InstBuilder &opNot(uint32_t result_type, uint32_t result_id,
-                     uint32_t operand);
   InstBuilder &opBitFieldInsert(uint32_t result_type, uint32_t result_id,
   InstBuilder &opBitFieldInsert(uint32_t result_type, uint32_t result_id,
                                 uint32_t base, uint32_t insert, uint32_t offset,
                                 uint32_t base, uint32_t insert, uint32_t offset,
                                 uint32_t count);
                                 uint32_t count);
@@ -536,33 +367,6 @@ public:
   InstBuilder &opAtomicIDecrement(uint32_t result_type, uint32_t result_id,
   InstBuilder &opAtomicIDecrement(uint32_t result_type, uint32_t result_id,
                                   uint32_t pointer, uint32_t scope,
                                   uint32_t pointer, uint32_t scope,
                                   uint32_t semantics);
                                   uint32_t semantics);
-  InstBuilder &opAtomicIAdd(uint32_t result_type, uint32_t result_id,
-                            uint32_t pointer, uint32_t scope,
-                            uint32_t semantics, uint32_t value);
-  InstBuilder &opAtomicISub(uint32_t result_type, uint32_t result_id,
-                            uint32_t pointer, uint32_t scope,
-                            uint32_t semantics, uint32_t value);
-  InstBuilder &opAtomicSMin(uint32_t result_type, uint32_t result_id,
-                            uint32_t pointer, uint32_t scope,
-                            uint32_t semantics, uint32_t value);
-  InstBuilder &opAtomicUMin(uint32_t result_type, uint32_t result_id,
-                            uint32_t pointer, uint32_t scope,
-                            uint32_t semantics, uint32_t value);
-  InstBuilder &opAtomicSMax(uint32_t result_type, uint32_t result_id,
-                            uint32_t pointer, uint32_t scope,
-                            uint32_t semantics, uint32_t value);
-  InstBuilder &opAtomicUMax(uint32_t result_type, uint32_t result_id,
-                            uint32_t pointer, uint32_t scope,
-                            uint32_t semantics, uint32_t value);
-  InstBuilder &opAtomicAnd(uint32_t result_type, uint32_t result_id,
-                           uint32_t pointer, uint32_t scope, uint32_t semantics,
-                           uint32_t value);
-  InstBuilder &opAtomicOr(uint32_t result_type, uint32_t result_id,
-                          uint32_t pointer, uint32_t scope, uint32_t semantics,
-                          uint32_t value);
-  InstBuilder &opAtomicXor(uint32_t result_type, uint32_t result_id,
-                           uint32_t pointer, uint32_t scope, uint32_t semantics,
-                           uint32_t value);
   InstBuilder &
   InstBuilder &
   opPhi(uint32_t result_type, uint32_t result_id,
   opPhi(uint32_t result_type, uint32_t result_id,
         llvm::ArrayRef<std::pair<uint32_t, uint32_t>> variable_parent_);
         llvm::ArrayRef<std::pair<uint32_t, uint32_t>> variable_parent_);
@@ -581,145 +385,6 @@ public:
   InstBuilder &opReturn();
   InstBuilder &opReturn();
   InstBuilder &opReturnValue(uint32_t value);
   InstBuilder &opReturnValue(uint32_t value);
   InstBuilder &opUnreachable();
   InstBuilder &opUnreachable();
-  InstBuilder &opLifetimeStart(uint32_t pointer, uint32_t size);
-  InstBuilder &opLifetimeStop(uint32_t pointer, uint32_t size);
-  InstBuilder &opGroupAsyncCopy(uint32_t result_type, uint32_t result_id,
-                                uint32_t execution, uint32_t destination,
-                                uint32_t source, uint32_t num_elements,
-                                uint32_t stride, uint32_t event);
-  InstBuilder &opGroupWaitEvents(uint32_t execution, uint32_t num_events,
-                                 uint32_t events_list);
-  InstBuilder &opGroupAll(uint32_t result_type, uint32_t result_id,
-                          uint32_t execution, uint32_t predicate);
-  InstBuilder &opGroupAny(uint32_t result_type, uint32_t result_id,
-                          uint32_t execution, uint32_t predicate);
-  InstBuilder &opGroupBroadcast(uint32_t result_type, uint32_t result_id,
-                                uint32_t execution, uint32_t value,
-                                uint32_t local_id);
-  InstBuilder &opGroupIAdd(uint32_t result_type, uint32_t result_id,
-                           uint32_t execution, spv::GroupOperation operation,
-                           uint32_t x);
-  InstBuilder &opGroupFAdd(uint32_t result_type, uint32_t result_id,
-                           uint32_t execution, spv::GroupOperation operation,
-                           uint32_t x);
-  InstBuilder &opGroupFMin(uint32_t result_type, uint32_t result_id,
-                           uint32_t execution, spv::GroupOperation operation,
-                           uint32_t x);
-  InstBuilder &opGroupUMin(uint32_t result_type, uint32_t result_id,
-                           uint32_t execution, spv::GroupOperation operation,
-                           uint32_t x);
-  InstBuilder &opGroupSMin(uint32_t result_type, uint32_t result_id,
-                           uint32_t execution, spv::GroupOperation operation,
-                           uint32_t x);
-  InstBuilder &opGroupFMax(uint32_t result_type, uint32_t result_id,
-                           uint32_t execution, spv::GroupOperation operation,
-                           uint32_t x);
-  InstBuilder &opGroupUMax(uint32_t result_type, uint32_t result_id,
-                           uint32_t execution, spv::GroupOperation operation,
-                           uint32_t x);
-  InstBuilder &opGroupSMax(uint32_t result_type, uint32_t result_id,
-                           uint32_t execution, spv::GroupOperation operation,
-                           uint32_t x);
-  InstBuilder &opReadPipe(uint32_t result_type, uint32_t result_id,
-                          uint32_t pipe, uint32_t pointer, uint32_t packet_size,
-                          uint32_t packet_alignment);
-  InstBuilder &opWritePipe(uint32_t result_type, uint32_t result_id,
-                           uint32_t pipe, uint32_t pointer,
-                           uint32_t packet_size, uint32_t packet_alignment);
-  InstBuilder &opReservedReadPipe(uint32_t result_type, uint32_t result_id,
-                                  uint32_t pipe, uint32_t reserve_id,
-                                  uint32_t index, uint32_t pointer,
-                                  uint32_t packet_size,
-                                  uint32_t packet_alignment);
-  InstBuilder &opReservedWritePipe(uint32_t result_type, uint32_t result_id,
-                                   uint32_t pipe, uint32_t reserve_id,
-                                   uint32_t index, uint32_t pointer,
-                                   uint32_t packet_size,
-                                   uint32_t packet_alignment);
-  InstBuilder &opReserveReadPipePackets(uint32_t result_type,
-                                        uint32_t result_id, uint32_t pipe,
-                                        uint32_t num_packets,
-                                        uint32_t packet_size,
-                                        uint32_t packet_alignment);
-  InstBuilder &opReserveWritePipePackets(uint32_t result_type,
-                                         uint32_t result_id, uint32_t pipe,
-                                         uint32_t num_packets,
-                                         uint32_t packet_size,
-                                         uint32_t packet_alignment);
-  InstBuilder &opCommitReadPipe(uint32_t pipe, uint32_t reserve_id,
-                                uint32_t packet_size,
-                                uint32_t packet_alignment);
-  InstBuilder &opCommitWritePipe(uint32_t pipe, uint32_t reserve_id,
-                                 uint32_t packet_size,
-                                 uint32_t packet_alignment);
-  InstBuilder &opIsValidReserveId(uint32_t result_type, uint32_t result_id,
-                                  uint32_t reserve_id);
-  InstBuilder &opGetNumPipePackets(uint32_t result_type, uint32_t result_id,
-                                   uint32_t pipe, uint32_t packet_size,
-                                   uint32_t packet_alignment);
-  InstBuilder &opGetMaxPipePackets(uint32_t result_type, uint32_t result_id,
-                                   uint32_t pipe, uint32_t packet_size,
-                                   uint32_t packet_alignment);
-  InstBuilder &opGroupReserveReadPipePackets(uint32_t result_type,
-                                             uint32_t result_id,
-                                             uint32_t execution, uint32_t pipe,
-                                             uint32_t num_packets,
-                                             uint32_t packet_size,
-                                             uint32_t packet_alignment);
-  InstBuilder &opGroupReserveWritePipePackets(uint32_t result_type,
-                                              uint32_t result_id,
-                                              uint32_t execution, uint32_t pipe,
-                                              uint32_t num_packets,
-                                              uint32_t packet_size,
-                                              uint32_t packet_alignment);
-  InstBuilder &opGroupCommitReadPipe(uint32_t execution, uint32_t pipe,
-                                     uint32_t reserve_id, uint32_t packet_size,
-                                     uint32_t packet_alignment);
-  InstBuilder &opGroupCommitWritePipe(uint32_t execution, uint32_t pipe,
-                                      uint32_t reserve_id, uint32_t packet_size,
-                                      uint32_t packet_alignment);
-  InstBuilder &opEnqueueMarker(uint32_t result_type, uint32_t result_id,
-                               uint32_t queue, uint32_t num_events,
-                               uint32_t wait_events, uint32_t ret_event);
-  InstBuilder &opEnqueueKernel(uint32_t result_type, uint32_t result_id,
-                               uint32_t queue, uint32_t flags,
-                               uint32_t nd_range, uint32_t num_events,
-                               uint32_t wait_events, uint32_t ret_event,
-                               uint32_t invoke, uint32_t param,
-                               uint32_t param_size, uint32_t param_align,
-                               llvm::ArrayRef<uint32_t> local_size);
-  InstBuilder &opGetKernelNDrangeSubGroupCount(uint32_t result_type,
-                                               uint32_t result_id,
-                                               uint32_t nd_range,
-                                               uint32_t invoke, uint32_t param,
-                                               uint32_t param_size,
-                                               uint32_t param_align);
-  InstBuilder &
-  opGetKernelNDrangeMaxSubGroupSize(uint32_t result_type, uint32_t result_id,
-                                    uint32_t nd_range, uint32_t invoke,
-                                    uint32_t param, uint32_t param_size,
-                                    uint32_t param_align);
-  InstBuilder &opGetKernelWorkGroupSize(uint32_t result_type,
-                                        uint32_t result_id, uint32_t invoke,
-                                        uint32_t param, uint32_t param_size,
-                                        uint32_t param_align);
-  InstBuilder &opGetKernelPreferredWorkGroupSizeMultiple(
-      uint32_t result_type, uint32_t result_id, uint32_t invoke, uint32_t param,
-      uint32_t param_size, uint32_t param_align);
-  InstBuilder &opRetainEvent(uint32_t event);
-  InstBuilder &opReleaseEvent(uint32_t event);
-  InstBuilder &opCreateUserEvent(uint32_t result_type, uint32_t result_id);
-  InstBuilder &opIsValidEvent(uint32_t result_type, uint32_t result_id,
-                              uint32_t event);
-  InstBuilder &opSetUserEventStatus(uint32_t event, uint32_t status);
-  InstBuilder &opCaptureEventProfilingInfo(uint32_t event,
-                                           uint32_t profiling_info,
-                                           uint32_t value);
-  InstBuilder &opGetDefaultQueue(uint32_t result_type, uint32_t result_id);
-  InstBuilder &opBuildNDRange(uint32_t result_type, uint32_t result_id,
-                              uint32_t global_work_size,
-                              uint32_t local_work_size,
-                              uint32_t global_work_offset);
   InstBuilder &opImageSparseSampleImplicitLod(
   InstBuilder &opImageSparseSampleImplicitLod(
       uint32_t result_type, uint32_t result_id, uint32_t sampled_image,
       uint32_t result_type, uint32_t result_id, uint32_t sampled_image,
       uint32_t coordinate,
       uint32_t coordinate,
@@ -806,219 +471,6 @@ public:
   InstBuilder &opModuleProcessed(std::string process);
   InstBuilder &opModuleProcessed(std::string process);
   InstBuilder &opExecutionModeId(uint32_t entry_point, spv::ExecutionMode mode);
   InstBuilder &opExecutionModeId(uint32_t entry_point, spv::ExecutionMode mode);
   InstBuilder &opDecorateId(uint32_t target, spv::Decoration decoration);
   InstBuilder &opDecorateId(uint32_t target, spv::Decoration decoration);
-  InstBuilder &opGroupNonUniformElect(uint32_t result_type, uint32_t result_id,
-                                      uint32_t execution);
-  InstBuilder &opGroupNonUniformAll(uint32_t result_type, uint32_t result_id,
-                                    uint32_t execution, uint32_t predicate);
-  InstBuilder &opGroupNonUniformAny(uint32_t result_type, uint32_t result_id,
-                                    uint32_t execution, uint32_t predicate);
-  InstBuilder &opGroupNonUniformAllEqual(uint32_t result_type,
-                                         uint32_t result_id, uint32_t execution,
-                                         uint32_t value);
-  InstBuilder &opGroupNonUniformBroadcast(uint32_t result_type,
-                                          uint32_t result_id,
-                                          uint32_t execution, uint32_t value,
-                                          uint32_t id);
-  InstBuilder &opGroupNonUniformBroadcastFirst(uint32_t result_type,
-                                               uint32_t result_id,
-                                               uint32_t execution,
-                                               uint32_t value);
-  InstBuilder &opGroupNonUniformBallot(uint32_t result_type, uint32_t result_id,
-                                       uint32_t execution, uint32_t predicate);
-  InstBuilder &opGroupNonUniformInverseBallot(uint32_t result_type,
-                                              uint32_t result_id,
-                                              uint32_t execution,
-                                              uint32_t value);
-  InstBuilder &opGroupNonUniformBallotBitExtract(uint32_t result_type,
-                                                 uint32_t result_id,
-                                                 uint32_t execution,
-                                                 uint32_t value,
-                                                 uint32_t index);
-  InstBuilder &opGroupNonUniformBallotBitCount(uint32_t result_type,
-                                               uint32_t result_id,
-                                               uint32_t execution,
-                                               spv::GroupOperation operation,
-                                               uint32_t value);
-  InstBuilder &opGroupNonUniformBallotFindLSB(uint32_t result_type,
-                                              uint32_t result_id,
-                                              uint32_t execution,
-                                              uint32_t value);
-  InstBuilder &opGroupNonUniformBallotFindMSB(uint32_t result_type,
-                                              uint32_t result_id,
-                                              uint32_t execution,
-                                              uint32_t value);
-  InstBuilder &opGroupNonUniformShuffle(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        uint32_t value, uint32_t id);
-  InstBuilder &opGroupNonUniformShuffleXor(uint32_t result_type,
-                                           uint32_t result_id,
-                                           uint32_t execution, uint32_t value,
-                                           uint32_t mask);
-  InstBuilder &opGroupNonUniformShuffleUp(uint32_t result_type,
-                                          uint32_t result_id,
-                                          uint32_t execution, uint32_t value,
-                                          uint32_t delta);
-  InstBuilder &opGroupNonUniformShuffleDown(uint32_t result_type,
-                                            uint32_t result_id,
-                                            uint32_t execution, uint32_t value,
-                                            uint32_t delta);
-  InstBuilder &opGroupNonUniformIAdd(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformFAdd(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformIMul(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformFMul(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformSMin(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformUMin(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformFMin(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformSMax(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformUMax(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformFMax(uint32_t result_type, uint32_t result_id,
-                                     uint32_t execution,
-                                     spv::GroupOperation operation,
-                                     uint32_t value,
-                                     llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &
-  opGroupNonUniformBitwiseAnd(uint32_t result_type, uint32_t result_id,
-                              uint32_t execution, spv::GroupOperation operation,
-                              uint32_t value,
-                              llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &
-  opGroupNonUniformBitwiseOr(uint32_t result_type, uint32_t result_id,
-                             uint32_t execution, spv::GroupOperation operation,
-                             uint32_t value,
-                             llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &
-  opGroupNonUniformBitwiseXor(uint32_t result_type, uint32_t result_id,
-                              uint32_t execution, spv::GroupOperation operation,
-                              uint32_t value,
-                              llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &
-  opGroupNonUniformLogicalAnd(uint32_t result_type, uint32_t result_id,
-                              uint32_t execution, spv::GroupOperation operation,
-                              uint32_t value,
-                              llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &
-  opGroupNonUniformLogicalOr(uint32_t result_type, uint32_t result_id,
-                             uint32_t execution, spv::GroupOperation operation,
-                             uint32_t value,
-                             llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &
-  opGroupNonUniformLogicalXor(uint32_t result_type, uint32_t result_id,
-                              uint32_t execution, spv::GroupOperation operation,
-                              uint32_t value,
-                              llvm::Optional<uint32_t> cluster_size);
-  InstBuilder &opGroupNonUniformQuadBroadcast(uint32_t result_type,
-                                              uint32_t result_id,
-                                              uint32_t execution,
-                                              uint32_t value, uint32_t index);
-  InstBuilder &opGroupNonUniformQuadSwap(uint32_t result_type,
-                                         uint32_t result_id, uint32_t execution,
-                                         uint32_t value, uint32_t direction);
-  InstBuilder &opSubgroupBallotKHR(uint32_t result_type, uint32_t result_id,
-                                   uint32_t predicate);
-  InstBuilder &opSubgroupFirstInvocationKHR(uint32_t result_type,
-                                            uint32_t result_id, uint32_t value);
-  InstBuilder &opSubgroupAllKHR(uint32_t result_type, uint32_t result_id,
-                                uint32_t predicate);
-  InstBuilder &opSubgroupAnyKHR(uint32_t result_type, uint32_t result_id,
-                                uint32_t predicate);
-  InstBuilder &opSubgroupAllEqualKHR(uint32_t result_type, uint32_t result_id,
-                                     uint32_t predicate);
-  InstBuilder &opSubgroupReadInvocationKHR(uint32_t result_type,
-                                           uint32_t result_id, uint32_t value,
-                                           uint32_t index);
-  InstBuilder &opGroupIAddNonUniformAMD(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        spv::GroupOperation operation,
-                                        uint32_t x);
-  InstBuilder &opGroupFAddNonUniformAMD(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        spv::GroupOperation operation,
-                                        uint32_t x);
-  InstBuilder &opGroupFMinNonUniformAMD(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        spv::GroupOperation operation,
-                                        uint32_t x);
-  InstBuilder &opGroupUMinNonUniformAMD(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        spv::GroupOperation operation,
-                                        uint32_t x);
-  InstBuilder &opGroupSMinNonUniformAMD(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        spv::GroupOperation operation,
-                                        uint32_t x);
-  InstBuilder &opGroupFMaxNonUniformAMD(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        spv::GroupOperation operation,
-                                        uint32_t x);
-  InstBuilder &opGroupUMaxNonUniformAMD(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        spv::GroupOperation operation,
-                                        uint32_t x);
-  InstBuilder &opGroupSMaxNonUniformAMD(uint32_t result_type,
-                                        uint32_t result_id, uint32_t execution,
-                                        spv::GroupOperation operation,
-                                        uint32_t x);
-  InstBuilder &opFragmentMaskFetchAMD(uint32_t result_type, uint32_t result_id,
-                                      uint32_t image, uint32_t coordinate);
-  InstBuilder &opFragmentFetchAMD(uint32_t result_type, uint32_t result_id,
-                                  uint32_t image, uint32_t coordinate,
-                                  uint32_t fragment_index);
-  InstBuilder &opSubgroupShuffleINTEL(uint32_t result_type, uint32_t result_id,
-                                      uint32_t data, uint32_t invocation_id);
-  InstBuilder &opSubgroupShuffleDownINTEL(uint32_t result_type,
-                                          uint32_t result_id, uint32_t current,
-                                          uint32_t next, uint32_t delta);
-  InstBuilder &opSubgroupShuffleUpINTEL(uint32_t result_type,
-                                        uint32_t result_id, uint32_t previous,
-                                        uint32_t current, uint32_t delta);
-  InstBuilder &opSubgroupShuffleXorINTEL(uint32_t result_type,
-                                         uint32_t result_id, uint32_t data,
-                                         uint32_t value);
-  InstBuilder &opSubgroupBlockReadINTEL(uint32_t result_type,
-                                        uint32_t result_id, uint32_t ptr);
-  InstBuilder &opSubgroupBlockWriteINTEL(uint32_t ptr, uint32_t data);
-  InstBuilder &opSubgroupImageBlockReadINTEL(uint32_t result_type,
-                                             uint32_t result_id, uint32_t image,
-                                             uint32_t coordinate);
-  InstBuilder &opSubgroupImageBlockWriteINTEL(uint32_t image,
-                                              uint32_t coordinate,
-                                              uint32_t data);
   InstBuilder &opDecorateStringGOOGLE(uint32_t target,
   InstBuilder &opDecorateStringGOOGLE(uint32_t target,
                                       spv::Decoration decoration);
                                       spv::Decoration decoration);
   InstBuilder &opMemberDecorateStringGOOGLE(uint32_t struct_type,
   InstBuilder &opMemberDecorateStringGOOGLE(uint32_t struct_type,
@@ -1033,6 +485,9 @@ public:
   InstBuilder &specConstantBinaryOp(spv::Op op, uint32_t result_type,
   InstBuilder &specConstantBinaryOp(spv::Op op, uint32_t result_type,
                                     uint32_t result_id, uint32_t lhs,
                                     uint32_t result_id, uint32_t lhs,
                                     uint32_t rhs);
                                     uint32_t rhs);
+  InstBuilder &atomicOp(spv::Op op, uint32_t result_type, uint32_t result_id,
+                        uint32_t pointer, uint32_t scope, uint32_t semantics,
+                        uint32_t value);
 
 
   // All-in-one methods for creating OpGroupNonUniform* operations.
   // All-in-one methods for creating OpGroupNonUniform* operations.
   InstBuilder &groupNonUniformOp(spv::Op op, uint32_t result_type,
   InstBuilder &groupNonUniformOp(spv::Op op, uint32_t result_type,
@@ -1092,7 +547,7 @@ private:
   void encodeMemoryAccess(spv::MemoryAccessMask value);
   void encodeMemoryAccess(spv::MemoryAccessMask value);
   void encodeExecutionMode(spv::ExecutionMode value);
   void encodeExecutionMode(spv::ExecutionMode value);
   void encodeDecoration(spv::Decoration value);
   void encodeDecoration(spv::Decoration value);
-  void encodeString(std::string value);
+  void encodeString(llvm::StringRef value);
 
 
   WordConsumer TheConsumer;
   WordConsumer TheConsumer;
   std::vector<uint32_t> TheInst;       ///< The instruction under construction.
   std::vector<uint32_t> TheInst;       ///< The instruction under construction.

+ 6 - 0
tools/clang/include/clang/SPIRV/ModuleBuilder.h

@@ -341,6 +341,8 @@ public:
   /// \brief Sets the source file name and the <result-id> for the OpString for
   /// \brief Sets the source file name and the <result-id> for the OpString for
   /// the file name.
   /// the file name.
   inline void setSourceFileName(uint32_t id, std::string name);
   inline void setSourceFileName(uint32_t id, std::string name);
+  /// \brief Sets the main source file content.
+  inline void setSourceFileContent(llvm::StringRef content);
 
 
   /// \brief Adds an execution mode to the module under construction.
   /// \brief Adds an execution mode to the module under construction.
   void addExecutionMode(uint32_t entryPointId, spv::ExecutionMode em,
   void addExecutionMode(uint32_t entryPointId, spv::ExecutionMode em,
@@ -553,6 +555,10 @@ void ModuleBuilder::setSourceFileName(uint32_t id, std::string name) {
   theModule.setSourceFileName(id, std::move(name));
   theModule.setSourceFileName(id, std::move(name));
 }
 }
 
 
+void ModuleBuilder::setSourceFileContent(llvm::StringRef content) {
+  theModule.setSourceFileContent(content);
+}
+
 } // end namespace spirv
 } // end namespace spirv
 } // end namespace clang
 } // end namespace clang
 
 

+ 6 - 0
tools/clang/include/clang/SPIRV/Structure.h

@@ -308,6 +308,7 @@ public:
   inline void addExecutionMode(Instruction &&);
   inline void addExecutionMode(Instruction &&);
   inline void setShaderModelVersion(uint32_t);
   inline void setShaderModelVersion(uint32_t);
   inline void setSourceFileName(uint32_t id, std::string name);
   inline void setSourceFileName(uint32_t id, std::string name);
+  inline void setSourceFileContent(llvm::StringRef content);
   // TODO: source code debug information
   // TODO: source code debug information
   inline void addDebugName(uint32_t targetId, llvm::StringRef name,
   inline void addDebugName(uint32_t targetId, llvm::StringRef name,
                            llvm::Optional<uint32_t> memberIndex = llvm::None);
                            llvm::Optional<uint32_t> memberIndex = llvm::None);
@@ -341,6 +342,7 @@ private:
   uint32_t shaderModelVersion;
   uint32_t shaderModelVersion;
   uint32_t sourceFileNameId; // The <result-id> for the OpString for file name
   uint32_t sourceFileNameId; // The <result-id> for the OpString for file name
   std::string sourceFileName;
   std::string sourceFileName;
+  llvm::StringRef sourceFileContent;
   // TODO: source code debug information
   // TODO: source code debug information
   std::set<DebugName> debugNames;
   std::set<DebugName> debugNames;
   llvm::SetVector<std::pair<uint32_t, const Decoration *>> decorations;
   llvm::SetVector<std::pair<uint32_t, const Decoration *>> decorations;
@@ -503,6 +505,10 @@ void SPIRVModule::setSourceFileName(uint32_t id, std::string name) {
   sourceFileName = std::move(name);
   sourceFileName = std::move(name);
 }
 }
 
 
+void SPIRVModule::setSourceFileContent(llvm::StringRef content) {
+  sourceFileContent = content;
+}
+
 void SPIRVModule::addDebugName(uint32_t targetId, llvm::StringRef name,
 void SPIRVModule::addDebugName(uint32_t targetId, llvm::StringRef name,
                                llvm::Optional<uint32_t> memberIndex) {
                                llvm::Optional<uint32_t> memberIndex) {
 
 

+ 5 - 2
tools/clang/include/clang/SPIRV/Type.h

@@ -18,6 +18,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/StringRef.h"
 
 
 namespace clang {
 namespace clang {
 namespace spirv {
 namespace spirv {
@@ -95,7 +96,7 @@ public:
                                      DecorationSet decs = {});
                                      DecorationSet decs = {});
   static const Type *getStruct(SPIRVContext &ctx,
   static const Type *getStruct(SPIRVContext &ctx,
                                llvm::ArrayRef<uint32_t> members,
                                llvm::ArrayRef<uint32_t> members,
-                               DecorationSet d = {});
+                               llvm::StringRef name = {}, DecorationSet d = {});
   static const Type *getPointer(SPIRVContext &ctx,
   static const Type *getPointer(SPIRVContext &ctx,
                                 spv::StorageClass storage_class, uint32_t type,
                                 spv::StorageClass storage_class, uint32_t type,
                                 DecorationSet decs = {});
                                 DecorationSet decs = {});
@@ -109,7 +110,8 @@ public:
 
 
 private:
 private:
   /// \brief Private constructor.
   /// \brief Private constructor.
-  Type(spv::Op op, std::vector<uint32_t> arg = {}, DecorationSet dec = {});
+  Type(spv::Op op, std::vector<uint32_t> arg = {}, DecorationSet dec = {},
+       llvm::StringRef name = {});
 
 
   /// \brief Returns the unique Type pointer within the given context.
   /// \brief Returns the unique Type pointer within the given context.
   static const Type *getUniqueType(SPIRVContext &, const Type &);
   static const Type *getUniqueType(SPIRVContext &, const Type &);
@@ -117,6 +119,7 @@ private:
 private:
 private:
   spv::Op opcode;             ///< OpCode of the Type defined in SPIR-V Spec
   spv::Op opcode;             ///< OpCode of the Type defined in SPIR-V Spec
   std::vector<uint32_t> args; ///< Arguments needed to define the type
   std::vector<uint32_t> args; ///< Arguments needed to define the type
+  std::string name;           ///< Source code name of this type
 
 
   /// The decorations that are applied to a type.
   /// The decorations that are applied to a type.
   /// Note: we use a SetVector because:
   /// Note: we use a SetVector because:

+ 1 - 1
tools/clang/lib/AST/ItaniumMangle.cpp

@@ -2040,7 +2040,7 @@ void CXXNameMangler::mangleType(const BuiltinType *T) {
   case BuiltinType::OCLSampler: Out << "11ocl_sampler"; break;
   case BuiltinType::OCLSampler: Out << "11ocl_sampler"; break;
   case BuiltinType::OCLEvent: Out << "9ocl_event"; break;
   case BuiltinType::OCLEvent: Out << "9ocl_event"; break;
     // HLSL Change starts
     // HLSL Change starts
-  case BuiltinType::Min12Int: Out << "min21_int"; break;
+  case BuiltinType::Min12Int: Out << "min12_int"; break;
   case BuiltinType::LitInt: Out << "lit_int"; break;
   case BuiltinType::LitInt: Out << "lit_int"; break;
   case BuiltinType::LitFloat: Out << "lit_float"; break;
   case BuiltinType::LitFloat: Out << "lit_float"; break;
   case BuiltinType::Min10Float: Out << "min10_float"; break;
   case BuiltinType::Min10Float: Out << "min10_float"; break;

+ 8 - 1
tools/clang/lib/Frontend/CompilerInvocation.cpp

@@ -1910,10 +1910,17 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
   // where we have a dxc-based command-line. We choose to accept additional
   // where we have a dxc-based command-line. We choose to accept additional
   // options even if they don't get applied.
   // options even if they don't get applied.
   const unsigned IncludedFlagsBitmask = 0;
   const unsigned IncludedFlagsBitmask = 0;
+#ifdef _WIN32
+  const unsigned ExcludedFlagsBitmask = 0;
+#else
+  // Exception: Exclude cl.exe like arguments that can trip up Unix systems
+  const unsigned ExcludedFlagsBitmask = options::CLOption;
+#endif
+  // End HLSL Change
   unsigned MissingArgIndex, MissingArgCount;
   unsigned MissingArgIndex, MissingArgCount;
   InputArgList Args =
   InputArgList Args =
       Opts->ParseArgs(llvm::makeArrayRef(ArgBegin, ArgEnd), MissingArgIndex,
       Opts->ParseArgs(llvm::makeArrayRef(ArgBegin, ArgEnd), MissingArgIndex,
-                      MissingArgCount, IncludedFlagsBitmask);
+                      MissingArgCount, IncludedFlagsBitmask, ExcludedFlagsBitmask);
 
 
   // Check for missing argument error.
   // Check for missing argument error.
   if (MissingArgCount) {
   if (MissingArgCount) {

+ 1 - 2
tools/clang/lib/Frontend/FrontendActions.cpp

@@ -408,6 +408,7 @@ SyntaxOnlyAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
   return llvm::make_unique<ASTConsumer>();
   return llvm::make_unique<ASTConsumer>();
 }
 }
 
 
+#if 0 // HLSL Change Starts - no support for modules or PCH
 std::unique_ptr<ASTConsumer>
 std::unique_ptr<ASTConsumer>
 DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
 DumpModuleInfoAction::CreateASTConsumer(CompilerInstance &CI,
                                         StringRef InFile) {
                                         StringRef InFile) {
@@ -419,8 +420,6 @@ VerifyPCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
   return llvm::make_unique<ASTConsumer>();
   return llvm::make_unique<ASTConsumer>();
 }
 }
 
 
-#if 0 // HLSL Change Starts - no support for modules or PCH
-
 void VerifyPCHAction::ExecuteAction() {
 void VerifyPCHAction::ExecuteAction() {
   CompilerInstance &CI = getCompilerInstance();
   CompilerInstance &CI = getCompilerInstance();
   bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;
   bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0;

+ 4 - 0
tools/clang/lib/Parse/HLSLRootSignature.cpp

@@ -17,7 +17,11 @@
 #include "clang/Parse/ParseDiagnostic.h"
 #include "clang/Parse/ParseDiagnostic.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/Global.h"
 #include "dxc/Support/WinIncludes.h"
 #include "dxc/Support/WinIncludes.h"
+#include "dxc/Support/WinFunctions.h"
 #include "HLSLRootSignature.h"
 #include "HLSLRootSignature.h"
+
+#include <float.h>
+
 using namespace llvm;
 using namespace llvm;
 using namespace hlsl;
 using namespace hlsl;
 
 

+ 43 - 6
tools/clang/lib/Parse/ParseDecl.cpp

@@ -229,12 +229,14 @@ static void ParseRegisterNumberForHLSL(_In_z_ const char *name,
   // It's valid to omit the register name.
   // It's valid to omit the register name.
   if (*name) {
   if (*name) {
     char *nameEnd;
     char *nameEnd;
+    unsigned long num;
     errno = 0;
     errno = 0;
-    *registerNumber = strtoul(name, &nameEnd, 10);
-    if (*nameEnd != '\0' || errno == ERANGE) {
+    num = strtoul(name, &nameEnd, 10);
+    if (*nameEnd != '\0' || errno == ERANGE || num > UINT32_MAX) {
       *diagId = diag::err_hlsl_unsupported_register_number;
       *diagId = diag::err_hlsl_unsupported_register_number;
       return;
       return;
     }
     }
+    *registerNumber = num;
   } else {
   } else {
     *registerNumber = 0;
     *registerNumber = 0;
   }
   }
@@ -721,6 +723,7 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
     //case AttributeList::AT_HLSLIn:
     //case AttributeList::AT_HLSLIn:
     //case AttributeList::AT_HLSLInOut:
     //case AttributeList::AT_HLSLInOut:
     //case AttributeList::AT_HLSLLinear:
     //case AttributeList::AT_HLSLLinear:
+    //case AttributeList::AT_HLSLCenter:
     //case AttributeList::AT_HLSLNoInterpolation:
     //case AttributeList::AT_HLSLNoInterpolation:
     //case AttributeList::AT_HLSLNoPerspective:
     //case AttributeList::AT_HLSLNoPerspective:
     //case AttributeList::AT_HLSLOut:
     //case AttributeList::AT_HLSLOut:
@@ -3715,10 +3718,8 @@ HLSLReservedKeyword:
       isStorageClass = true;
       isStorageClass = true;
       break;
       break;
     // HLSL Change Starts
     // HLSL Change Starts
-    case tok::kw_precise:
     case tok::kw_shared:
     case tok::kw_shared:
     case tok::kw_groupshared:
     case tok::kw_groupshared:
-    case tok::kw_globallycoherent:
     case tok::kw_uniform:
     case tok::kw_uniform:
     case tok::kw_in:
     case tok::kw_in:
     case tok::kw_out:
     case tok::kw_out:
@@ -3726,7 +3727,6 @@ HLSLReservedKeyword:
     case tok::kw_linear:
     case tok::kw_linear:
     case tok::kw_nointerpolation:
     case tok::kw_nointerpolation:
     case tok::kw_noperspective:
     case tok::kw_noperspective:
-    case tok::kw_sample:
     case tok::kw_centroid:
     case tok::kw_centroid:
     case tok::kw_column_major:
     case tok::kw_column_major:
     case tok::kw_row_major:
     case tok::kw_row_major:
@@ -3747,7 +3747,22 @@ HLSLReservedKeyword:
         }
         }
       }
       }
       break;
       break;
-    // HLSL Change Ends
+    case tok::kw_precise:
+    case tok::kw_sample:
+    case tok::kw_globallycoherent:
+    case tok::kw_center:
+      // Back-compat: 'precise', 'globallycoherent', 'center' and 'sample' are keywords when used as an interpolation 
+      // modifiers, but in FXC they can also be used an identifiers. If the decl type has already been specified
+      // we need to update the token to be handled as an identifier.
+      if (getLangOpts().HLSL) {
+        if (DS.getTypeSpecType() != DeclSpec::TST_unspecified) {
+          Tok.setKind(tok::identifier);
+          continue;
+        }
+        DS.getAttributes().addNew(Tok.getIdentifierInfo(), Tok.getLocation(), 0, SourceLocation(), 0, 0, AttributeList::AS_CXX11);
+      }
+      break;
+      // HLSL Change Ends
     case tok::kw_auto:
     case tok::kw_auto:
       if (getLangOpts().HLSL) { goto HLSLReservedKeyword; } // HLSL Change - auto is reserved for HLSL
       if (getLangOpts().HLSL) { goto HLSLReservedKeyword; } // HLSL Change - auto is reserved for HLSL
       if (getLangOpts().CPlusPlus11) {
       if (getLangOpts().CPlusPlus11) {
@@ -5163,6 +5178,7 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
 
 
   // HLSL Change Starts
   // HLSL Change Starts
   case tok::kw_precise:
   case tok::kw_precise:
+  case tok::kw_center:
   case tok::kw_shared:
   case tok::kw_shared:
   case tok::kw_groupshared:
   case tok::kw_groupshared:
   case tok::kw_globallycoherent:
   case tok::kw_globallycoherent:
@@ -5949,6 +5965,27 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
       // the l_paren token.
       // the l_paren token.
     }
     }
 
 
+    // HLSL Change Starts
+    // FXC compatiblity: these are keywords when used as modifiers, but in
+    // FXC they can also be used an identifiers. If the next token is a
+    // punctuator, then we are using them as identifers. Need to change
+    // the token type to tok::identifier and fall through to the next case.
+    // E.g., <type> left, center, right;
+    if (getLangOpts().HLSL) {
+      switch (Tok.getKind()) {
+      case tok::kw_center:
+      case tok::kw_globallycoherent:
+      case tok::kw_precise:
+      case tok::kw_sample:
+        if (tok::isPunctuator(NextToken().getKind()))
+          Tok.setKind(tok::identifier);
+        break;
+      default:
+        break;
+      }
+    }
+    // HLSL Change Ends
+
     if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,
     if (Tok.isOneOf(tok::identifier, tok::kw_operator, tok::annot_template_id,
                     tok::tilde)) {
                     tok::tilde)) {
       // We found something that indicates the start of an unqualified-id.
       // We found something that indicates the start of an unqualified-id.

+ 23 - 5
tools/clang/lib/Parse/ParseExpr.cpp

@@ -788,7 +788,18 @@ HLSLReservedKeyword:
       return ExprError();
       return ExprError();
     assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));
     assert(Tok.isNot(tok::kw_decltype) && Tok.isNot(tok::kw___super));
     return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
     return ParseCastExpression(isUnaryExpression, isAddressOfOperand);
-      
+
+    // HLSL Change Starts
+  case tok::kw_precise:
+  case tok::kw_sample:
+  case tok::kw_globallycoherent:
+  case tok::kw_center:
+    // Back-compat: 'precise', 'globallycoherent', 'center' and 'sample' are keywords when used as an interpolation 
+    // modifiers, but in FXC they can also be used an identifiers. No interpolation modifiers are expected here
+    // so we need to change the token type to tok::identifier and fall through to the next case.
+    Tok.setKind(tok::identifier);
+    __fallthrough;
+    // HLSL Change Ends
   case tok::identifier: {      // primary-expression: identifier
   case tok::identifier: {      // primary-expression: identifier
                                // unqualified-id: identifier
                                // unqualified-id: identifier
                                // constant: enumeration-constant
                                // constant: enumeration-constant
@@ -1702,13 +1713,20 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) {
       }
       }
 
 
       // HLSL Change Starts
       // HLSL Change Starts
-      // 'sample' is a keyword when used as an interpolation modifier, but it is
-      // also a built-in field of some types. By the time we're considering a
+      // 'sample' and others are keywords when used as modifiers, but they are
+      // also built-in field of some types. By the time we're considering a
       // field access, update the token if necessary to reflect this.
       // field access, update the token if necessary to reflect this.
       if (getLangOpts().HLSL) {
       if (getLangOpts().HLSL) {
-        if (Tok.is(tok::kw_sample)) {
+        switch (auto tk = Tok.getKind()) {
+        case tok::kw_center:
+        case tok::kw_globallycoherent:
+        case tok::kw_precise:
+        case tok::kw_sample:
           Tok.setKind(tok::identifier);
           Tok.setKind(tok::identifier);
-          Tok.setIdentifierInfo(PP.getIdentifierInfo(StringRef("sample")));
+          Tok.setIdentifierInfo(PP.getIdentifierInfo(getKeywordSpelling(tk)));
+          break;
+        default:
+          break;
         }
         }
       }
       }
       // HLSL Change Ends
       // HLSL Change Ends

+ 19 - 0
tools/clang/lib/Parse/ParseStmt.cpp

@@ -175,6 +175,25 @@ Retry:
     cutOffParsing();
     cutOffParsing();
     return StmtError();
     return StmtError();
 
 
+    // HLSL Change Starts
+  case tok::kw_precise:
+  case tok::kw_sample:
+  case tok::kw_globallycoherent:
+  case tok::kw_center: {
+    // FXC compatiblity: these are keywords when used as modifiers, but in
+    // FXC they can also be used an identifiers. If the next token is a
+    // punctuator, then we are using them as identifers. Need to change
+    // the token type to tok::identifier and fall through to the next case.
+    // E.g., center = <RHS>.
+    if (tok::isPunctuator(NextToken().getKind())) {
+      Tok.setKind(tok::identifier);
+      __fallthrough;
+    } else {
+      goto tok_default_case;
+    }
+  }
+    // HLSL Change Ends
+
   case tok::identifier: {
   case tok::identifier: {
     Token Next = NextToken();
     Token Next = NextToken();
     if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement
     if (Next.is(tok::colon)) { // C99 6.8.1: labeled-statement

+ 16 - 3
tools/clang/lib/Parse/ParseTentative.cpp

@@ -1271,6 +1271,22 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
     return TPResult::True;
     return TPResult::True;
 
 
   // HLSL Change Starts
   // HLSL Change Starts
+  case tok::kw_sample:
+  case tok::kw_precise:
+  case tok::kw_center:
+  case tok::kw_globallycoherent:
+    // FXC compatiblity: these are keywords when used as modifiers, but in
+    // FXC they can also be used an identifiers. If the next token is a
+    // punctuator, then we are using them as identifers. Need to change
+    // the token type to tok::identifier and return false.
+    // E.g., return (center);
+    if (tok::isPunctuator(NextToken().getKind())) {
+      Tok.setKind(tok::identifier);
+      return TPResult::False;
+    } else {
+      return TPResult::True;
+    }
+
   case tok::kw_in:
   case tok::kw_in:
   case tok::kw_inout:
   case tok::kw_inout:
   case tok::kw_out:
   case tok::kw_out:
@@ -1278,11 +1294,8 @@ Parser::isCXXDeclarationSpecifier(Parser::TPResult BracedCastResult,
   case tok::kw_centroid:
   case tok::kw_centroid:
   case tok::kw_nointerpolation:
   case tok::kw_nointerpolation:
   case tok::kw_noperspective:
   case tok::kw_noperspective:
-  case tok::kw_sample:
-  case tok::kw_precise:
   case tok::kw_shared:
   case tok::kw_shared:
   case tok::kw_groupshared:
   case tok::kw_groupshared:
-  case tok::kw_globallycoherent:
   case tok::kw_uniform:
   case tok::kw_uniform:
   case tok::kw_row_major:
   case tok::kw_row_major:
   case tok::kw_column_major:
   case tok::kw_column_major:

+ 27 - 6
tools/clang/lib/SPIRV/DeclResultIdMapper.cpp

@@ -214,13 +214,17 @@ bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,
 
 
   SemanticInfo inheritSemantic = {};
   SemanticInfo inheritSemantic = {};
 
 
+  // If storedValue is 0, it means this parameter in the original source code is
+  // not used at all. Avoid writing back.
+  //
+  // Write back of stage output variables in GS is manually controlled by
+  // .Append() intrinsic method, implemented in writeBackOutputStream(). So
+  // ignoreValue should be set to true for GS.
+  const bool noWriteBack = storedValue == 0 || shaderModel.IsGS();
+
   return createStageVars(sigPoint, decl, /*asInput=*/false, type,
   return createStageVars(sigPoint, decl, /*asInput=*/false, type,
                          /*arraySize=*/0, "out.var", llvm::None, &storedValue,
                          /*arraySize=*/0, "out.var", llvm::None, &storedValue,
-                         // Write back of stage output variables in GS is
-                         // manually controlled by .Append() intrinsic method,
-                         // implemented in writeBackOutputStream(). So
-                         // noWriteBack should be set to true for GS.
-                         shaderModel.IsGS(), &inheritSemantic);
+                         noWriteBack, &inheritSemantic);
 }
 }
 
 
 bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,
 bool DeclResultIdMapper::createStageOutputVar(const DeclaratorDecl *decl,
@@ -1494,12 +1498,16 @@ bool DeclResultIdMapper::createStageVars(const hlsl::SigPoint *sigPoint,
               theBuilder.getVecType(srcVecElemTypeId, 2), *value, *value,
               theBuilder.getVecType(srcVecElemTypeId, 2), *value, *value,
               {0, 1});
               {0, 1});
       }
       }
+
+      // Reciprocate SV_Position.w if requested
+      if (semanticKind == hlsl::Semantic::Kind::Position)
+        *value = invertWIfRequested(*value);
     } else {
     } else {
       if (noWriteBack)
       if (noWriteBack)
         return true;
         return true;
 
 
       // Negate SV_Position.y if requested
       // Negate SV_Position.y if requested
-      if (semanticToUse->semantic->GetKind() == hlsl::Semantic::Kind::Position)
+      if (semanticKind == hlsl::Semantic::Kind::Position)
         *value = invertYIfRequested(*value);
         *value = invertYIfRequested(*value);
 
 
       uint32_t ptr = varId;
       uint32_t ptr = varId;
@@ -1786,6 +1794,19 @@ uint32_t DeclResultIdMapper::invertYIfRequested(uint32_t position) {
   return position;
   return position;
 }
 }
 
 
+uint32_t DeclResultIdMapper::invertWIfRequested(uint32_t position) {
+  // Reciprocate SV_Position.w if requested
+  if (spirvOptions.invertW && shaderModel.IsPS()) {
+    const auto f32Type = theBuilder.getFloat32Type();
+    const auto v4f32Type = theBuilder.getVecType(f32Type, 4);
+    const auto oldW = theBuilder.createCompositeExtract(f32Type, position, {3});
+    const auto newW = theBuilder.createBinaryOp(
+        spv::Op::OpFDiv, f32Type, theBuilder.getConstantFloat32(1), oldW);
+    position = theBuilder.createCompositeInsert(v4f32Type, position, {3}, newW);
+  }
+  return position;
+}
+
 void DeclResultIdMapper::decoratePSInterpolationMode(const NamedDecl *decl,
 void DeclResultIdMapper::decoratePSInterpolationMode(const NamedDecl *decl,
                                                      QualType type,
                                                      QualType type,
                                                      uint32_t varId) {
                                                      uint32_t varId) {

+ 7 - 3
tools/clang/lib/SPIRV/DeclResultIdMapper.h

@@ -433,9 +433,13 @@ public:
   bool writeBackOutputStream(const NamedDecl *decl, QualType type,
   bool writeBackOutputStream(const NamedDecl *decl, QualType type,
                              uint32_t value);
                              uint32_t value);
 
 
-  /// \brief Inverts SV_Position.y is requested.
+  /// \brief Negates to get the additive inverse of SV_Position.y if requested.
   uint32_t invertYIfRequested(uint32_t position);
   uint32_t invertYIfRequested(uint32_t position);
 
 
+  /// \brief Reciprocates to get the multiplicative inverse of SV_Position.w
+  /// if requested.
+  uint32_t invertWIfRequested(uint32_t position);
+
   /// \brief Decorates all stage input and output variables with proper
   /// \brief Decorates all stage input and output variables with proper
   /// location and returns true on success.
   /// location and returns true on success.
   ///
   ///
@@ -744,8 +748,8 @@ DeclResultIdMapper::DeclResultIdMapper(const hlsl::ShaderModel &model,
                                        const EmitSPIRVOptions &options)
                                        const EmitSPIRVOptions &options)
     : shaderModel(model), theBuilder(builder), spirvOptions(options),
     : shaderModel(model), theBuilder(builder), spirvOptions(options),
       astContext(context), diags(context.getDiagnostics()),
       astContext(context), diags(context.getDiagnostics()),
-      typeTranslator(translator), entryFunctionId(0),
-      laneCountBuiltinId(0), laneIndexBuiltinId(0), needsLegalization(false),
+      typeTranslator(translator), entryFunctionId(0), laneCountBuiltinId(0),
+      laneIndexBuiltinId(0), needsLegalization(false),
       glPerVertex(model, context, builder, typeTranslator) {}
       glPerVertex(model, context, builder, typeTranslator) {}
 
 
 bool DeclResultIdMapper::decorateStageIOLocations() {
 bool DeclResultIdMapper::decorateStageIOLocations() {

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 266 - 342
tools/clang/lib/SPIRV/InstBuilderAuto.cpp


+ 30 - 1
tools/clang/lib/SPIRV/InstBuilderManual.cpp

@@ -84,6 +84,35 @@ InstBuilder &InstBuilder::specConstantBinaryOp(spv::Op op, uint32_t result_type,
   return *this;
   return *this;
 }
 }
 
 
+InstBuilder &InstBuilder::atomicOp(spv::Op op, uint32_t result_type,
+                                   uint32_t result_id, uint32_t pointer,
+                                   uint32_t scope, uint32_t semantics,
+                                   uint32_t value) {
+  if (!TheInst.empty()) {
+    TheStatus = Status::NestedInst;
+    return *this;
+  }
+  if (result_type == 0) {
+    TheStatus = Status::ZeroResultType;
+    return *this;
+  }
+  if (result_id == 0) {
+    TheStatus = Status::ZeroResultId;
+    return *this;
+  }
+
+  TheInst.reserve(7);
+  TheInst.emplace_back(static_cast<uint32_t>(op));
+  TheInst.emplace_back(result_type);
+  TheInst.emplace_back(result_id);
+  TheInst.emplace_back(pointer);
+  TheInst.emplace_back(scope);
+  TheInst.emplace_back(semantics);
+  TheInst.emplace_back(value);
+
+  return *this;
+}
+
 InstBuilder &InstBuilder::groupNonUniformOp(spv::Op op, uint32_t result_type,
 InstBuilder &InstBuilder::groupNonUniformOp(spv::Op op, uint32_t result_type,
                                             uint32_t result_id,
                                             uint32_t result_id,
                                             uint32_t exec_scope) {
                                             uint32_t exec_scope) {
@@ -234,7 +263,7 @@ InstBuilder &InstBuilder::opSpecConstant(uint32_t resultType, uint32_t resultId,
   return *this;
   return *this;
 }
 }
 
 
-void InstBuilder::encodeString(std::string value) {
+void InstBuilder::encodeString(llvm::StringRef value) {
   const auto &words = string::encodeSPIRVString(value);
   const auto &words = string::encodeSPIRVString(value);
   TheInst.insert(TheInst.end(), words.begin(), words.end());
   TheInst.insert(TheInst.end(), words.begin(), words.end());
 }
 }

+ 9 - 48
tools/clang/lib/SPIRV/ModuleBuilder.cpp

@@ -301,51 +301,10 @@ uint32_t ModuleBuilder::createAtomicOp(spv::Op opcode, uint32_t resultType,
                                        uint32_t valueToOp) {
                                        uint32_t valueToOp) {
   assert(insertPoint && "null insert point");
   assert(insertPoint && "null insert point");
   const uint32_t id = theContext.takeNextId();
   const uint32_t id = theContext.takeNextId();
-  switch (opcode) {
-  case spv::Op::OpAtomicIAdd:
-    instBuilder.opAtomicIAdd(resultType, id, orignalValuePtr, scopeId,
-                             memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicISub:
-    instBuilder.opAtomicISub(resultType, id, orignalValuePtr, scopeId,
-                             memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicAnd:
-    instBuilder.opAtomicAnd(resultType, id, orignalValuePtr, scopeId,
-                            memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicOr:
-    instBuilder.opAtomicOr(resultType, id, orignalValuePtr, scopeId,
-                           memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicXor:
-    instBuilder.opAtomicXor(resultType, id, orignalValuePtr, scopeId,
-                            memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicUMax:
-    instBuilder.opAtomicUMax(resultType, id, orignalValuePtr, scopeId,
-                             memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicUMin:
-    instBuilder.opAtomicUMin(resultType, id, orignalValuePtr, scopeId,
-                             memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicSMax:
-    instBuilder.opAtomicSMax(resultType, id, orignalValuePtr, scopeId,
-                             memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicSMin:
-    instBuilder.opAtomicSMin(resultType, id, orignalValuePtr, scopeId,
-                             memorySemanticsId, valueToOp);
-    break;
-  case spv::Op::OpAtomicExchange:
-    instBuilder.opAtomicExchange(resultType, id, orignalValuePtr, scopeId,
-                                 memorySemanticsId, valueToOp);
-    break;
-  default:
-    assert(false && "unimplemented atomic opcode");
-  }
-  instBuilder.x();
+  instBuilder
+      .atomicOp(opcode, resultType, id, orignalValuePtr, scopeId,
+                memorySemanticsId, valueToOp)
+      .x();
   insertPoint->appendInstruction(std::move(constructSite));
   insertPoint->appendInstruction(std::move(constructSite));
   return id;
   return id;
 }
 }
@@ -1026,7 +985,8 @@ ModuleBuilder::getStructType(llvm::ArrayRef<uint32_t> fieldTypes,
                              llvm::StringRef structName,
                              llvm::StringRef structName,
                              llvm::ArrayRef<llvm::StringRef> fieldNames,
                              llvm::ArrayRef<llvm::StringRef> fieldNames,
                              Type::DecorationSet decorations) {
                              Type::DecorationSet decorations) {
-  const Type *type = Type::getStruct(theContext, fieldTypes, decorations);
+  const Type *type =
+      Type::getStruct(theContext, fieldTypes, structName, decorations);
   bool isRegistered = false;
   bool isRegistered = false;
   const uint32_t typeId = theContext.getResultIdForType(type, &isRegistered);
   const uint32_t typeId = theContext.getResultIdForType(type, &isRegistered);
   theModule.addType(type, typeId);
   theModule.addType(type, typeId);
@@ -1112,7 +1072,8 @@ uint32_t ModuleBuilder::getImageType(uint32_t sampledType, spv::Dim dim,
     requireCapability(spv::Capability::StorageImageExtendedFormats);
     requireCapability(spv::Capability::StorageImageExtendedFormats);
     break;
     break;
   default:
   default:
-    // Only image formats requiring extended formats are relevant. The rest just pass through.
+    // Only image formats requiring extended formats are relevant. The rest just
+    // pass through.
     break;
     break;
   }
   }
 
 
@@ -1204,7 +1165,7 @@ uint32_t ModuleBuilder::getByteAddressBufferType(bool isRW) {
   if (!isRW)
   if (!isRW)
     typeDecs.push_back(Decoration::getNonWritable(theContext, 0));
     typeDecs.push_back(Decoration::getNonWritable(theContext, 0));
 
 
-  const Type *type = Type::getStruct(theContext, {raTypeId}, typeDecs);
+  const Type *type = Type::getStruct(theContext, {raTypeId}, "", typeDecs);
   const uint32_t typeId = theContext.getResultIdForType(type);
   const uint32_t typeId = theContext.getResultIdForType(type);
   theModule.addType(type, typeId);
   theModule.addType(type, typeId);
   theModule.addDebugName(typeId, isRW ? "type.RWByteAddressBuffer"
   theModule.addDebugName(typeId, isRW ? "type.RWByteAddressBuffer"

+ 138 - 37
tools/clang/lib/SPIRV/SPIRVEmitter.cpp

@@ -230,7 +230,8 @@ bool spirvToolsOptimize(spv_target_env env, std::vector<uint32_t> *module,
 }
 }
 
 
 bool spirvToolsValidate(spv_target_env env, std::vector<uint32_t> *module,
 bool spirvToolsValidate(spv_target_env env, std::vector<uint32_t> *module,
-                        std::string *messages, bool relaxLogicalPointer) {
+                        std::string *messages, bool relaxLogicalPointer,
+                        bool glLayout, bool dxLayout) {
   spvtools::SpirvTools tools(env);
   spvtools::SpirvTools tools(env);
 
 
   tools.SetMessageConsumer(
   tools.SetMessageConsumer(
@@ -240,6 +241,11 @@ bool spirvToolsValidate(spv_target_env env, std::vector<uint32_t> *module,
 
 
   spvtools::ValidatorOptions options;
   spvtools::ValidatorOptions options;
   options.SetRelaxLogicalPointer(relaxLogicalPointer);
   options.SetRelaxLogicalPointer(relaxLogicalPointer);
+  // GL: strict block layout rules
+  // VK: relaxed block layout rules
+  // DX: Skip block layout rules
+  options.SetRelaxBlockLayout(!glLayout && !dxLayout);
+  options.SetSkipBlockLayout(dxLayout);
 
 
   return tools.Validate(module->data(), module->size(), options);
   return tools.Validate(module->data(), module->size(), options);
 }
 }
@@ -604,9 +610,18 @@ SPIRVEmitter::SPIRVEmitter(CompilerInstance &ci, EmitSPIRVOptions &options)
 
 
   // Set debug info
   // Set debug info
   const auto &inputFiles = ci.getFrontendOpts().Inputs;
   const auto &inputFiles = ci.getFrontendOpts().Inputs;
-  if (options.enableDebugInfo && !inputFiles.empty())
+  if (options.enableDebugInfo && !inputFiles.empty()) {
+    // File name
     theBuilder.setSourceFileName(theContext.takeNextId(),
     theBuilder.setSourceFileName(theContext.takeNextId(),
                                  inputFiles.front().getFile().str());
                                  inputFiles.front().getFile().str());
+
+    // Source code
+    const auto &sm = ci.getSourceManager();
+    const llvm::MemoryBuffer *mainFile =
+        sm.getBuffer(sm.getMainFileID(), SourceLocation());
+    theBuilder.setSourceFileContent(
+        StringRef(mainFile->getBufferStart(), mainFile->getBufferSize()));
+  }
 }
 }
 
 
 void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
 void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
@@ -692,8 +707,9 @@ void SPIRVEmitter::HandleTranslationUnit(ASTContext &context) {
   // Validate the generated SPIR-V code
   // Validate the generated SPIR-V code
   if (!spirvOptions.disableValidation) {
   if (!spirvOptions.disableValidation) {
     std::string messages;
     std::string messages;
-    if (!spirvToolsValidate(targetEnv, &m, &messages,
-                            declIdMapper.requiresLegalization())) {
+    if (!spirvToolsValidate(
+            targetEnv, &m, &messages, declIdMapper.requiresLegalization(),
+            spirvOptions.useGlLayout, spirvOptions.useDxLayout)) {
       emitFatalError("generated SPIR-V is invalid: %0", {}) << messages;
       emitFatalError("generated SPIR-V is invalid: %0", {}) << messages;
       emitNote("please file a bug report on "
       emitNote("please file a bug report on "
                "https://github.com/Microsoft/DirectXShaderCompiler/issues "
                "https://github.com/Microsoft/DirectXShaderCompiler/issues "
@@ -1937,7 +1953,7 @@ SPIRVEmitter::doArraySubscriptExpr(const ArraySubscriptExpr *expr) {
   }
   }
 
 
   if (!indices.empty()) {
   if (!indices.empty()) {
-    (void)turnIntoElementPtr(info, expr->getType(), indices);
+    (void)turnIntoElementPtr(base->getType(), info, expr->getType(), indices);
   }
   }
 
 
   return info;
   return info;
@@ -2430,7 +2446,8 @@ SpirvEvalInfo SPIRVEmitter::doCastExpr(const CastExpr *expr) {
       baseIndices[i] = theBuilder.getConstantUint32(baseIndices[i]);
       baseIndices[i] = theBuilder.getConstantUint32(baseIndices[i]);
 
 
     auto derivedInfo = doExpr(subExpr);
     auto derivedInfo = doExpr(subExpr);
-    return turnIntoElementPtr(derivedInfo, expr->getType(), baseIndices);
+    return turnIntoElementPtr(subExpr->getType(), derivedInfo, expr->getType(),
+                              baseIndices);
   }
   }
   default:
   default:
     emitError("implicit cast kind '%0' unimplemented", expr->getExprLoc())
     emitError("implicit cast kind '%0' unimplemented", expr->getExprLoc())
@@ -2929,7 +2946,8 @@ SPIRVEmitter::processBufferTextureGetDimensions(const CXXMemberCallExpr *expr) {
 }
 }
 
 
 uint32_t
 uint32_t
-SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr) {
+SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr,
+                                          bool unclamped) {
   // Possible signatures are as follows:
   // Possible signatures are as follows:
   // Texture1D(Array).CalculateLevelOfDetail(SamplerState S, float x);
   // Texture1D(Array).CalculateLevelOfDetail(SamplerState S, float x);
   // Texture2D(Array).CalculateLevelOfDetail(SamplerState S, float2 xy);
   // Texture2D(Array).CalculateLevelOfDetail(SamplerState S, float2 xy);
@@ -2957,9 +2975,11 @@ SPIRVEmitter::processTextureLevelOfDetail(const CXXMemberCallExpr *expr) {
       theBuilder.getVecType(theBuilder.getFloat32Type(), 2u);
       theBuilder.getVecType(theBuilder.getFloat32Type(), 2u);
   const uint32_t query = theBuilder.createBinaryOp(
   const uint32_t query = theBuilder.createBinaryOp(
       spv::Op::OpImageQueryLod, queryResultType, sampledImage, coordinate);
       spv::Op::OpImageQueryLod, queryResultType, sampledImage, coordinate);
+
   // The first component of the float2 contains the mipmap array layer.
   // The first component of the float2 contains the mipmap array layer.
+  // The second component of the float2 represents the unclamped lod.
   return theBuilder.createCompositeExtract(theBuilder.getFloat32Type(), query,
   return theBuilder.createCompositeExtract(theBuilder.getFloat32Type(), query,
-                                           {0});
+                                           unclamped ? 1 : 0);
 }
 }
 
 
 uint32_t SPIRVEmitter::processTextureGatherRGBACmpRGBA(
 uint32_t SPIRVEmitter::processTextureGatherRGBACmpRGBA(
@@ -3148,7 +3168,21 @@ SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(
   QualType elemType = sampledType;
   QualType elemType = sampledType;
   uint32_t elemCount = 1;
   uint32_t elemCount = 1;
   uint32_t elemTypeId = 0;
   uint32_t elemTypeId = 0;
-  (void)TypeTranslator::isVectorType(sampledType, &elemType, &elemCount);
+  bool isTemplateOverStruct = false;
+
+  // Check whether the template type is a vector type or struct type.
+  if (!TypeTranslator::isVectorType(sampledType, &elemType, &elemCount)) {
+    if (sampledType->getAsStructureType()) {
+      isTemplateOverStruct = true;
+      // For struct type, we need to make sure it can fit into a 4-component
+      // vector. Detailed failing reasons will be emitted by the function so
+      // we don't need to emit errors here.
+      if (!typeTranslator.canFitIntoOneRegister(sampledType, &elemType,
+                                                &elemCount))
+        return 0;
+    }
+  }
+
   if (elemType->isFloatingType()) {
   if (elemType->isFloatingType()) {
     elemTypeId = theBuilder.getFloat32Type();
     elemTypeId = theBuilder.getFloat32Type();
   } else if (elemType->isSignedIntegerType()) {
   } else if (elemType->isSignedIntegerType()) {
@@ -3156,7 +3190,7 @@ SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(
   } else if (elemType->isUnsignedIntegerType()) {
   } else if (elemType->isUnsignedIntegerType()) {
     elemTypeId = theBuilder.getUint32Type();
     elemTypeId = theBuilder.getUint32Type();
   } else {
   } else {
-    emitError("buffer/texture type unimplemented", object->getExprLoc());
+    emitError("loading %0 value unsupported", object->getExprLoc()) << type;
     return 0;
     return 0;
   }
   }
 
 
@@ -3169,6 +3203,10 @@ SpirvEvalInfo SPIRVEmitter::processBufferTextureLoad(
   // If the result type is a vec1, vec2, or vec3, some extra processing
   // If the result type is a vec1, vec2, or vec3, some extra processing
   // (extraction) is required.
   // (extraction) is required.
   uint32_t retVal = extractVecFromVec4(texel, elemCount, elemTypeId);
   uint32_t retVal = extractVecFromVec4(texel, elemCount, elemTypeId);
+  if (isTemplateOverStruct) {
+    // Convert to the struct so that we are consistent with types in the AST.
+    retVal = convertVectorToStruct(sampledType, elemTypeId, retVal);
+  }
   return SpirvEvalInfo(retVal).setRValue();
   return SpirvEvalInfo(retVal).setRValue();
 }
 }
 
 
@@ -3277,7 +3315,7 @@ SPIRVEmitter::processStructuredBufferLoad(const CXXMemberCallExpr *expr) {
   const uint32_t zero = theBuilder.getConstantInt32(0);
   const uint32_t zero = theBuilder.getConstantInt32(0);
   const uint32_t index = doExpr(expr->getArg(0));
   const uint32_t index = doExpr(expr->getArg(0));
 
 
-  return turnIntoElementPtr(info, structType, {zero, index});
+  return turnIntoElementPtr(buffer->getType(), info, structType, {zero, index});
 }
 }
 
 
 uint32_t SPIRVEmitter::incDecRWACSBufferCounter(const CXXMemberCallExpr *expr,
 uint32_t SPIRVEmitter::incDecRWACSBufferCounter(const CXXMemberCallExpr *expr,
@@ -3471,7 +3509,8 @@ SPIRVEmitter::processACSBufferAppendConsume(const CXXMemberCallExpr *expr) {
 
 
   const auto bufferElemTy = hlsl::GetHLSLResourceResultType(object->getType());
   const auto bufferElemTy = hlsl::GetHLSLResourceResultType(object->getType());
 
 
-  (void)turnIntoElementPtr(bufferInfo, bufferElemTy, {zero, index});
+  (void)turnIntoElementPtr(object->getType(), bufferInfo, bufferElemTy,
+                           {zero, index});
 
 
   if (isAppend) {
   if (isAppend) {
     // Write out the value
     // Write out the value
@@ -3820,7 +3859,9 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
     retVal = processGetDimensions(expr);
     retVal = processGetDimensions(expr);
     break;
     break;
   case IntrinsicOp::MOP_CalculateLevelOfDetail:
   case IntrinsicOp::MOP_CalculateLevelOfDetail:
-    retVal = processTextureLevelOfDetail(expr);
+    retVal = processTextureLevelOfDetail(expr, /* unclamped */ false);
+  case IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped:
+    retVal = processTextureLevelOfDetail(expr, /* unclamped */ true);
     break;
     break;
   case IntrinsicOp::MOP_IncrementCounter:
   case IntrinsicOp::MOP_IncrementCounter:
     retVal = theBuilder.createUnaryOp(
     retVal = theBuilder.createUnaryOp(
@@ -3865,7 +3906,6 @@ SPIRVEmitter::processIntrinsicMemberCall(const CXXMemberCallExpr *expr,
   case IntrinsicOp::MOP_GatherCmpGreen:
   case IntrinsicOp::MOP_GatherCmpGreen:
   case IntrinsicOp::MOP_GatherCmpBlue:
   case IntrinsicOp::MOP_GatherCmpBlue:
   case IntrinsicOp::MOP_GatherCmpAlpha:
   case IntrinsicOp::MOP_GatherCmpAlpha:
-  case IntrinsicOp::MOP_CalculateLevelOfDetailUnclamped:
     emitError("no equivalent for %0 intrinsic method in Vulkan",
     emitError("no equivalent for %0 intrinsic method in Vulkan",
               expr->getCallee()->getExprLoc())
               expr->getCallee()->getExprLoc())
         << expr->getMethodDecl()->getName();
         << expr->getMethodDecl()->getName();
@@ -4394,7 +4434,8 @@ SPIRVEmitter::doCXXOperatorCallExpr(const CXXOperatorCallExpr *expr) {
     base = createTemporaryVar(baseExpr->getType(), "vector", base);
     base = createTemporaryVar(baseExpr->getType(), "vector", base);
   }
   }
 
 
-  return turnIntoElementPtr(base, expr->getType(), indices);
+  return turnIntoElementPtr(baseExpr->getType(), base, expr->getType(),
+                            indices);
 }
 }
 
 
 SpirvEvalInfo
 SpirvEvalInfo
@@ -4579,19 +4620,7 @@ SpirvEvalInfo SPIRVEmitter::doMemberExpr(const MemberExpr *expr) {
   auto info = loadIfAliasVarRef(base);
   auto info = loadIfAliasVarRef(base);
 
 
   if (!indices.empty()) {
   if (!indices.empty()) {
-    // Sometime we are accessing the member of a rvalue, e.g.,
-    // <some-function-returing-a-struct>().<some-field>
-    // Create a temporary variable to hold the rvalue so that we can use access
-    // chain to index into it.
-    if (info.isRValue()) {
-      SpirvEvalInfo tempVar = createTemporaryVar(
-          base->getType(), TypeTranslator::getName(base->getType()), info);
-      (void)turnIntoElementPtr(tempVar, expr->getType(), indices);
-      info.setResultId(theBuilder.createLoad(
-          typeTranslator.translateType(expr->getType()), tempVar));
-    } else {
-      (void)turnIntoElementPtr(info, expr->getType(), indices);
-    }
+    (void)turnIntoElementPtr(base->getType(), info, expr->getType(), indices);
   }
   }
 
 
   return info;
   return info;
@@ -5453,6 +5482,38 @@ void SPIRVEmitter::splitVecLastElement(QualType vecType, uint32_t vec,
       theBuilder.createCompositeExtract(elemTypeId, vec, {count - 1});
       theBuilder.createCompositeExtract(elemTypeId, vec, {count - 1});
 }
 }
 
 
+uint32_t SPIRVEmitter::convertVectorToStruct(QualType structType,
+                                             uint32_t elemTypeId,
+                                             uint32_t vector) {
+  assert(structType->isStructureType());
+
+  const auto *structDecl = structType->getAsStructureType()->getDecl();
+  uint32_t vectorIndex = 0;
+  uint32_t elemCount = 1;
+  llvm::SmallVector<uint32_t, 4> members;
+
+  for (const auto *field : structDecl->fields()) {
+    if (TypeTranslator::isScalarType(field->getType())) {
+      members.push_back(theBuilder.createCompositeExtract(elemTypeId, vector,
+                                                          {vectorIndex++}));
+    } else if (TypeTranslator::isVectorType(field->getType(), nullptr,
+                                            &elemCount)) {
+      llvm::SmallVector<uint32_t, 4> indices;
+      for (uint32_t i = 0; i < elemCount; ++i)
+        indices.push_back(vectorIndex++);
+
+      const uint32_t type = theBuilder.getVecType(elemTypeId, elemCount);
+      members.push_back(
+          theBuilder.createVectorShuffle(type, vector, vector, indices));
+    } else {
+      assert(false && "unhandled type");
+    }
+  }
+
+  return theBuilder.createCompositeConstruct(
+      typeTranslator.translateType(structType), members);
+}
+
 SpirvEvalInfo
 SpirvEvalInfo
 SPIRVEmitter::tryToGenFloatVectorScale(const BinaryOperator *expr) {
 SPIRVEmitter::tryToGenFloatVectorScale(const BinaryOperator *expr) {
   const QualType type = expr->getType();
   const QualType type = expr->getType();
@@ -5630,7 +5691,7 @@ SPIRVEmitter::tryToAssignToVectorElements(const Expr *lhs,
       const auto result = tryToAssignToRWBufferRWTexture(base, newVec);
       const auto result = tryToAssignToRWBufferRWTexture(base, newVec);
       assert(result); // Definitely RWBuffer/RWTexture assignment
       assert(result); // Definitely RWBuffer/RWTexture assignment
       (void)result;
       (void)result;
-      return rhs;     // TODO: incorrect for compound assignments
+      return rhs; // TODO: incorrect for compound assignments
     } else {
     } else {
       // Assigning to one normal vector component. Nothing special, just fall
       // Assigning to one normal vector component. Nothing special, just fall
       // back to the normal CodeGen path.
       // back to the normal CodeGen path.
@@ -6029,13 +6090,40 @@ const Expr *SPIRVEmitter::collectArrayStructIndices(
 }
 }
 
 
 SpirvEvalInfo &SPIRVEmitter::turnIntoElementPtr(
 SpirvEvalInfo &SPIRVEmitter::turnIntoElementPtr(
-    SpirvEvalInfo &info, QualType elemType,
+    QualType baseType, SpirvEvalInfo &base, QualType elemType,
     const llvm::SmallVector<uint32_t, 4> &indices) {
     const llvm::SmallVector<uint32_t, 4> &indices) {
-  assert(!info.isRValue());
-  const uint32_t ptrType = theBuilder.getPointerType(
-      typeTranslator.translateType(elemType, info.getLayoutRule()),
-      info.getStorageClass());
-  return info.setResultId(theBuilder.createAccessChain(ptrType, info, indices));
+  // If this is a rvalue, we need a temporary object to hold it
+  // so that we can get access chain from it.
+  const bool needTempVar = base.isRValue();
+
+  if (needTempVar) {
+    auto varName = TypeTranslator::getName(baseType);
+    const auto var = createTemporaryVar(baseType, varName, base);
+    base.setResultId(var)
+        .setLayoutRule(LayoutRule::Void)
+        .setStorageClass(spv::StorageClass::Function);
+  }
+
+  const uint32_t elemTypeId =
+      typeTranslator.translateType(elemType, base.getLayoutRule());
+  const uint32_t ptrType =
+      theBuilder.getPointerType(elemTypeId, base.getStorageClass());
+  base.setResultId(theBuilder.createAccessChain(ptrType, base, indices));
+
+  // Okay, this part seems weird, but it is intended:
+  // If the base is originally a rvalue, the whole AST involving the base
+  // is consistently set up to handle rvalues. By copying the base into
+  // a temporary variable and grab an access chain from it, we are breaking
+  // the consistency by turning the base from rvalue into lvalue. Keep in
+  // mind that there will be no LValueToRValue casts in the AST for us
+  // to rely on to load the access chain if a rvalue is expected. Therefore,
+  // we must do the load here. Otherwise, it's up to the consumer of this
+  // access chain to do the load, and that can be everywhere.
+  if (needTempVar) {
+    base.setResultId(theBuilder.createLoad(elemTypeId, base));
+  }
+
+  return base;
 }
 }
 
 
 uint32_t SPIRVEmitter::castToBool(const uint32_t fromVal, QualType fromType,
 uint32_t SPIRVEmitter::castToBool(const uint32_t fromVal, QualType fromType,
@@ -6663,6 +6751,13 @@ SPIRVEmitter::processIntrinsicInterlockedMethod(const CallExpr *expr,
   const uint32_t scope = theBuilder.getConstantUint32(1); // Device
   const uint32_t scope = theBuilder.getConstantUint32(1); // Device
   const auto *dest = expr->getArg(0);
   const auto *dest = expr->getArg(0);
   const auto baseType = dest->getType();
   const auto baseType = dest->getType();
+
+  if (!baseType->isIntegerType()) {
+    emitError("can only perform atomic operations on scalar integer values",
+              dest->getLocStart());
+    return 0;
+  }
+
   const uint32_t baseTypeId = typeTranslator.translateType(baseType);
   const uint32_t baseTypeId = typeTranslator.translateType(baseType);
 
 
   const auto doArg = [baseType, this](const CallExpr *callExpr,
   const auto doArg = [baseType, this](const CallExpr *callExpr,
@@ -9378,7 +9473,10 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
       if (!declIdMapper.createStageInputVar(param, &loadedValue, false))
       if (!declIdMapper.createStageInputVar(param, &loadedValue, false))
         return false;
         return false;
 
 
-      theBuilder.createStore(tempVar, loadedValue);
+      // Only initialize the temporary variable if the parameter is indeed used.
+      if (param->isUsed()) {
+        theBuilder.createStore(tempVar, loadedValue);
+      }
 
 
       // Record the temporary variable holding SV_OutputControlPointID,
       // Record the temporary variable holding SV_OutputControlPointID,
       // SV_PrimitiveID, and SV_ViewID. It may be used later in the patch
       // SV_PrimitiveID, and SV_ViewID. It may be used later in the patch
@@ -9427,10 +9525,13 @@ bool SPIRVEmitter::emitEntryFunctionWrapper(const FunctionDecl *decl,
       const uint32_t typeId = typeTranslator.translateType(param->getType());
       const uint32_t typeId = typeTranslator.translateType(param->getType());
       uint32_t loadedParam = 0;
       uint32_t loadedParam = 0;
 
 
+      // No need to write back the value if the parameter is not used at all in
+      // the original entry function.
+      //
       // Write back of stage output variables in GS is manually controlled by
       // Write back of stage output variables in GS is manually controlled by
       // .Append() intrinsic method. No need to load the parameter since we
       // .Append() intrinsic method. No need to load the parameter since we
       // won't need to write back here.
       // won't need to write back here.
-      if (!shaderModel.IsGS())
+      if (param->isUsed() && !shaderModel.IsGS())
         loadedParam = theBuilder.createLoad(typeId, params[i]);
         loadedParam = theBuilder.createLoad(typeId, params[i]);
 
 
       if (!declIdMapper.createStageOutputVar(param, loadedParam, false))
       if (!declIdMapper.createStageOutputVar(param, loadedParam, false))

+ 14 - 3
tools/clang/lib/SPIRV/SPIRVEmitter.h

@@ -222,6 +222,14 @@ private:
   void splitVecLastElement(QualType vecType, uint32_t vec, uint32_t *residual,
   void splitVecLastElement(QualType vecType, uint32_t vec, uint32_t *residual,
                            uint32_t *lastElement);
                            uint32_t *lastElement);
 
 
+  /// Converts a vector value into the given struct type with its element type's
+  /// <result-id> as elemTypeId.
+  ///
+  /// Assumes the vector and the struct have matching number of elements. Panics
+  /// otherwise.
+  uint32_t convertVectorToStruct(QualType structType, uint32_t elemTypeId,
+                                 uint32_t vector);
+
   /// Translates a floatN * float multiplication into SPIR-V instructions and
   /// Translates a floatN * float multiplication into SPIR-V instructions and
   /// returns the <result-id>. Returns 0 if the given binary operation is not
   /// returns the <result-id>. Returns 0 if the given binary operation is not
   /// floatN * float.
   /// floatN * float.
@@ -288,7 +296,7 @@ private:
   /// Creates an access chain to index into the given SPIR-V evaluation result
   /// Creates an access chain to index into the given SPIR-V evaluation result
   /// and overwrites and returns the new SPIR-V evaluation result.
   /// and overwrites and returns the new SPIR-V evaluation result.
   SpirvEvalInfo &
   SpirvEvalInfo &
-  turnIntoElementPtr(SpirvEvalInfo &info, QualType elemType,
+  turnIntoElementPtr(QualType baseType, SpirvEvalInfo &base, QualType elemType,
                      const llvm::SmallVector<uint32_t, 4> &indices);
                      const llvm::SmallVector<uint32_t, 4> &indices);
 
 
 private:
 private:
@@ -747,8 +755,11 @@ private:
   uint32_t processTextureGatherCmp(const CXXMemberCallExpr *expr);
   uint32_t processTextureGatherCmp(const CXXMemberCallExpr *expr);
 
 
   /// \brief Returns the calculated level-of-detail (a single float value) for
   /// \brief Returns the calculated level-of-detail (a single float value) for
-  /// the given texture. Handles intrinsic HLSL CalculateLevelOfDetail function.
-  uint32_t processTextureLevelOfDetail(const CXXMemberCallExpr *expr);
+  /// the given texture. Handles intrinsic HLSL CalculateLevelOfDetail or
+  /// CalculateLevelOfDetailUnclamped function depending on the given unclamped
+  /// parameter.
+  uint32_t processTextureLevelOfDetail(const CXXMemberCallExpr *expr,
+                                       bool unclamped);
 
 
   /// \brief Processes the .GetDimensions() call on supported objects.
   /// \brief Processes the .GetDimensions() call on supported objects.
   uint32_t processGetDimensions(const CXXMemberCallExpr *);
   uint32_t processGetDimensions(const CXXMemberCallExpr *);

+ 38 - 1
tools/clang/lib/SPIRV/Structure.cpp

@@ -17,6 +17,32 @@ namespace spirv {
 namespace {
 namespace {
 constexpr uint32_t kGeneratorNumber = 14;
 constexpr uint32_t kGeneratorNumber = 14;
 constexpr uint32_t kToolVersion = 0;
 constexpr uint32_t kToolVersion = 0;
+
+/// Chops the given original string into multiple smaller ones to make sure they
+/// can be encoded in a sequence of OpSourceContinued instructions following an
+/// OpSource instruction.
+void chopString(llvm::StringRef original,
+                llvm::SmallVectorImpl<llvm::StringRef> *chopped) {
+  const uint32_t maxCharInOpSource = 0xFFFFu - 5u; // Minus operands and nul
+  const uint32_t maxCharInContinue = 0xFFFFu - 2u; // Minus opcode and nul
+
+  chopped->clear();
+  if (original.size() > maxCharInOpSource) {
+    chopped->push_back(llvm::StringRef(original.data(), maxCharInOpSource));
+    original = llvm::StringRef(original.data() + maxCharInOpSource,
+                               original.size() - maxCharInOpSource);
+    while (original.size() > maxCharInContinue) {
+      chopped->push_back(llvm::StringRef(original.data(), maxCharInContinue));
+      original = llvm::StringRef(original.data() + maxCharInContinue,
+                                 original.size() - maxCharInContinue);
+    }
+    if (!original.empty()) {
+      chopped->push_back(original);
+    }
+  } else if (!original.empty()) {
+    chopped->push_back(original);
+  }
+}
 } // namespace
 } // namespace
 
 
 // === Instruction implementations ===
 // === Instruction implementations ===
@@ -289,10 +315,21 @@ void SPIRVModule::take(InstBuilder *builder) {
       fileName = sourceFileNameId;
       fileName = sourceFileNameId;
     }
     }
 
 
+    llvm::SmallVector<llvm::StringRef, 2> choppedSrcCode;
+    llvm::Optional<llvm::StringRef> firstSnippet;
+    chopString(sourceFileContent, &choppedSrcCode);
+    if (!choppedSrcCode.empty()) {
+      firstSnippet = llvm::Optional<llvm::StringRef>(choppedSrcCode.front());
+    }
+
     builder
     builder
         ->opSource(spv::SourceLanguage::HLSL, shaderModelVersion, fileName,
         ->opSource(spv::SourceLanguage::HLSL, shaderModelVersion, fileName,
-                   llvm::None)
+                   firstSnippet)
         .x();
         .x();
+
+    for (uint32_t i = 1; i < choppedSrcCode.size(); ++i) {
+      builder->opSourceContinued(choppedSrcCode[i]).x();
+    }
   }
   }
 
 
   // BasicBlock debug names should be emitted only for blocks that are
   // BasicBlock debug names should be emitted only for blocks that are

+ 7 - 5
tools/clang/lib/SPIRV/Type.cpp

@@ -14,8 +14,9 @@
 namespace clang {
 namespace clang {
 namespace spirv {
 namespace spirv {
 
 
-Type::Type(spv::Op op, std::vector<uint32_t> arg, DecorationSet decs)
-    : opcode(op), args(std::move(arg)) {
+Type::Type(spv::Op op, std::vector<uint32_t> arg, DecorationSet decs,
+           llvm::StringRef n)
+    : opcode(op), args(std::move(arg)), name(n.str()) {
   decorations = llvm::SetVector<const Decoration *>(decs.begin(), decs.end());
   decorations = llvm::SetVector<const Decoration *>(decs.begin(), decs.end());
 }
 }
 
 
@@ -126,8 +127,9 @@ const Type *Type::getRuntimeArray(SPIRVContext &context,
   return getUniqueType(context, t);
   return getUniqueType(context, t);
 }
 }
 const Type *Type::getStruct(SPIRVContext &context,
 const Type *Type::getStruct(SPIRVContext &context,
-                            llvm::ArrayRef<uint32_t> members, DecorationSet d) {
-  Type t = Type(spv::Op::OpTypeStruct, std::vector<uint32_t>(members), d);
+                            llvm::ArrayRef<uint32_t> members,
+                            llvm::StringRef name, DecorationSet d) {
+  Type t = Type(spv::Op::OpTypeStruct, std::vector<uint32_t>(members), d, name);
   return getUniqueType(context, t);
   return getUniqueType(context, t);
 }
 }
 const Type *Type::getPointer(SPIRVContext &context,
 const Type *Type::getPointer(SPIRVContext &context,
@@ -148,7 +150,7 @@ const Type *Type::getFunction(SPIRVContext &context, uint32_t return_type,
 
 
 bool Type::operator==(const Type &other) const {
 bool Type::operator==(const Type &other) const {
   if (opcode == other.opcode && args == other.args &&
   if (opcode == other.opcode && args == other.args &&
-      decorations.size() == other.decorations.size()) {
+      decorations.size() == other.decorations.size() && name == other.name) {
     // If two types have the same decorations, but in different order,
     // If two types have the same decorations, but in different order,
     // they are in fact the same type.
     // they are in fact the same type.
     for (const Decoration *dec : decorations) {
     for (const Decoration *dec : decorations) {

+ 102 - 20
tools/clang/lib/SPIRV/TypeTranslator.cpp

@@ -1045,7 +1045,8 @@ bool TypeTranslator::isOrContainsNonFpColMajorMatrix(QualType type,
                                                      const Decl *decl) const {
                                                      const Decl *decl) const {
   const auto isColMajorDecl = [this](const Decl *decl) {
   const auto isColMajorDecl = [this](const Decl *decl) {
     return decl->hasAttr<HLSLColumnMajorAttr>() ||
     return decl->hasAttr<HLSLColumnMajorAttr>() ||
-           (!decl->hasAttr<HLSLRowMajorAttr>() && !spirvOptions.defaultRowMajor);
+           (!decl->hasAttr<HLSLRowMajorAttr>() &&
+            !spirvOptions.defaultRowMajor);
   };
   };
 
 
   QualType elemType = {};
   QualType elemType = {};
@@ -1190,13 +1191,21 @@ bool TypeTranslator::isSameType(QualType type1, QualType type2) {
 QualType TypeTranslator::getElementType(QualType type) {
 QualType TypeTranslator::getElementType(QualType type) {
   QualType elemType = {};
   QualType elemType = {};
   if (isScalarType(type, &elemType) || isVectorType(type, &elemType) ||
   if (isScalarType(type, &elemType) || isVectorType(type, &elemType) ||
-      isMxNMatrix(type, &elemType)) {
-  } else if (const auto *arrType = astContext.getAsConstantArrayType(type)) {
-    elemType = arrType->getElementType();
-  } else {
-    assert(false && "unhandled type");
+      isMxNMatrix(type, &elemType) || canFitIntoOneRegister(type, &elemType)) {
+    return elemType;
   }
   }
-  return elemType;
+
+  if (const auto *arrType = astContext.getAsConstantArrayType(type)) {
+    return arrType->getElementType();
+  }
+
+  emitError("unsupported resource type parameter %0") << type;
+  // Note: We are returning the original type instead of a null QualType here
+  // to keep the translation going and avoid hitting asserts trying to query
+  // info from null QualType in other places of the compiler. Although we are
+  // likely generating invalid code here, it should be fine since the error
+  // reported will prevent the CodeGen from actually outputing.
+  return type;
 }
 }
 
 
 uint32_t TypeTranslator::getComponentVectorType(QualType matrixType) {
 uint32_t TypeTranslator::getComponentVectorType(QualType matrixType) {
@@ -1296,11 +1305,12 @@ llvm::SmallVector<const Decoration *, 4> TypeTranslator::getLayoutDecorations(
 
 
     if (rule == LayoutRule::RelaxedGLSLStd140 ||
     if (rule == LayoutRule::RelaxedGLSLStd140 ||
         rule == LayoutRule::RelaxedGLSLStd430 ||
         rule == LayoutRule::RelaxedGLSLStd430 ||
-        rule == LayoutRule::FxcCTBuffer)
-      alignUsingHLSLRelaxedLayout(fieldType, memberSize, &memberAlignment,
+        rule == LayoutRule::FxcCTBuffer) {
+      alignUsingHLSLRelaxedLayout(fieldType, memberSize, memberAlignment,
                                   &offset);
                                   &offset);
-    else
+    } else {
       offset = roundToPow2(offset, memberAlignment);
       offset = roundToPow2(offset, memberAlignment);
+    }
 
 
     // The vk::offset attribute takes precedence over all.
     // The vk::offset attribute takes precedence over all.
     if (const auto *offsetAttr = decl->getAttr<VKOffsetAttr>()) {
     if (const auto *offsetAttr = decl->getAttr<VKOffsetAttr>()) {
@@ -1533,6 +1543,16 @@ uint32_t TypeTranslator::translateResourceType(QualType type, LayoutRule rule) {
   if (name == "Buffer" || name == "RWBuffer") {
   if (name == "Buffer" || name == "RWBuffer") {
     theBuilder.requireCapability(spv::Capability::SampledBuffer);
     theBuilder.requireCapability(spv::Capability::SampledBuffer);
     const auto sampledType = hlsl::GetHLSLResourceResultType(type);
     const auto sampledType = hlsl::GetHLSLResourceResultType(type);
+    if (sampledType->isStructureType() && name.startswith("RW")) {
+      // Note: actually fxc supports RWBuffer over struct types. However, the
+      // struct member must fit into a 4-component vector and writing to a
+      // RWBuffer element must write all components. This is a feature that are
+      // rarely used by developers. We just emit an error saying not supported
+      // for now.
+      emitError("cannot instantiate RWBuffer with struct type %0")
+          << sampledType;
+      return 0;
+    }
     const auto format = translateSampledTypeToImageFormat(sampledType);
     const auto format = translateSampledTypeToImageFormat(sampledType);
     return theBuilder.getImageType(
     return theBuilder.getImageType(
         translateType(getElementType(sampledType)), spv::Dim::Buffer,
         translateType(getElementType(sampledType)), spv::Dim::Buffer,
@@ -1578,7 +1598,8 @@ TypeTranslator::translateSampledTypeToImageFormat(QualType sampledType) {
   uint32_t elemCount = 1;
   uint32_t elemCount = 1;
   QualType ty = {};
   QualType ty = {};
   if (isScalarType(sampledType, &ty) ||
   if (isScalarType(sampledType, &ty) ||
-      isVectorType(sampledType, &ty, &elemCount)) {
+      isVectorType(sampledType, &ty, &elemCount) ||
+      canFitIntoOneRegister(sampledType, &ty, &elemCount)) {
     if (const auto *builtinType = ty->getAs<BuiltinType>()) {
     if (const auto *builtinType = ty->getAs<BuiltinType>()) {
       switch (builtinType->getKind()) {
       switch (builtinType->getKind()) {
       case BuiltinType::Int:
       case BuiltinType::Int:
@@ -1599,13 +1620,65 @@ TypeTranslator::translateSampledTypeToImageFormat(QualType sampledType) {
       }
       }
     }
     }
   }
   }
-  emitError("resource type %0 unimplemented") << sampledType.getAsString();
+  emitError(
+      "cannot translate resource type parameter %0 to proper image format")
+      << sampledType;
   return spv::ImageFormat::Unknown;
   return spv::ImageFormat::Unknown;
 }
 }
 
 
+bool TypeTranslator::canFitIntoOneRegister(QualType structType,
+                                           QualType *elemType,
+                                           uint32_t *elemCount) {
+  if (structType->getAsStructureType() == nullptr)
+    return false;
+
+  const auto *structDecl = structType->getAsStructureType()->getDecl();
+  QualType firstElemType;
+  uint32_t totalCount = 0;
+
+  for (const auto *field : structDecl->fields()) {
+    QualType type;
+    uint32_t count = 1;
+
+    if (isScalarType(field->getType(), &type) ||
+        isVectorType(field->getType(), &type, &count)) {
+      if (firstElemType.isNull()) {
+        firstElemType = type;
+      } else {
+        if (!canTreatAsSameScalarType(firstElemType, type)) {
+          emitError("all struct members should have the same element type for "
+                    "resource template instantiation",
+                    structDecl->getLocation());
+          return false;
+        }
+      }
+      totalCount += count;
+    } else {
+      emitError("unsupported struct element type for resource template "
+                "instantiation",
+                structDecl->getLocation());
+      return false;
+    }
+  }
+
+  if (totalCount > 4) {
+    emitError(
+        "resource template element type %0 cannot fit into four 32-bit scalars",
+        structDecl->getLocation())
+        << structType;
+    return false;
+  }
+
+  if (elemType)
+    *elemType = firstElemType;
+  if (elemCount)
+    *elemCount = totalCount;
+  return true;
+}
+
 void TypeTranslator::alignUsingHLSLRelaxedLayout(QualType fieldType,
 void TypeTranslator::alignUsingHLSLRelaxedLayout(QualType fieldType,
                                                  uint32_t fieldSize,
                                                  uint32_t fieldSize,
-                                                 uint32_t *fieldAlignment,
+                                                 uint32_t fieldAlignment,
                                                  uint32_t *currentOffset) {
                                                  uint32_t *currentOffset) {
   QualType vecElemType = {};
   QualType vecElemType = {};
   const bool fieldIsVecType = isVectorType(fieldType, &vecElemType);
   const bool fieldIsVecType = isVectorType(fieldType, &vecElemType);
@@ -1618,17 +1691,17 @@ void TypeTranslator::alignUsingHLSLRelaxedLayout(QualType fieldType,
     std::tie(scalarAlignment, std::ignore) =
     std::tie(scalarAlignment, std::ignore) =
         getAlignmentAndSize(vecElemType, LayoutRule::Void, nullptr);
         getAlignmentAndSize(vecElemType, LayoutRule::Void, nullptr);
     if (scalarAlignment <= 4)
     if (scalarAlignment <= 4)
-      *fieldAlignment = scalarAlignment;
+      fieldAlignment = scalarAlignment;
   }
   }
 
 
-  *currentOffset = roundToPow2(*currentOffset, *fieldAlignment);
+  *currentOffset = roundToPow2(*currentOffset, fieldAlignment);
 
 
   // Adjust according to HLSL relaxed layout rules.
   // Adjust according to HLSL relaxed layout rules.
   // Bump to 4-component vector alignment if there is a bad straddle
   // Bump to 4-component vector alignment if there is a bad straddle
   if (fieldIsVecType &&
   if (fieldIsVecType &&
       improperStraddle(fieldType, fieldSize, *currentOffset)) {
       improperStraddle(fieldType, fieldSize, *currentOffset)) {
-    *fieldAlignment = kStd140Vec4Alignment;
-    *currentOffset = roundToPow2(*currentOffset, *fieldAlignment);
+    fieldAlignment = kStd140Vec4Alignment;
+    *currentOffset = roundToPow2(*currentOffset, fieldAlignment);
   }
   }
 }
 }
 
 
@@ -1811,11 +1884,20 @@ TypeTranslator::getAlignmentAndSize(QualType type, LayoutRule rule,
 
 
       if (rule == LayoutRule::RelaxedGLSLStd140 ||
       if (rule == LayoutRule::RelaxedGLSLStd140 ||
           rule == LayoutRule::RelaxedGLSLStd430 ||
           rule == LayoutRule::RelaxedGLSLStd430 ||
-          rule == LayoutRule::FxcCTBuffer)
+          rule == LayoutRule::FxcCTBuffer) {
         alignUsingHLSLRelaxedLayout(field->getType(), memberSize,
         alignUsingHLSLRelaxedLayout(field->getType(), memberSize,
-                                    &memberAlignment, &structSize);
-      else
+                                    memberAlignment, &structSize);
+      } else {
         structSize = roundToPow2(structSize, memberAlignment);
         structSize = roundToPow2(structSize, memberAlignment);
+      }
+
+      // Reset the current offset to the one specified in the source code
+      // if exists. It's debatable whether we should do sanity check here.
+      // If the developers want manually control the layout, we leave
+      // everything to them.
+      if (const auto *offsetAttr = field->getAttr<VKOffsetAttr>()) {
+        structSize = offsetAttr->getOffset();
+      }
 
 
       // The base alignment of the structure is N, where N is the largest
       // The base alignment of the structure is N, where N is the largest
       // base alignment value of any of its members...
       // base alignment value of any of its members...

+ 8 - 1
tools/clang/lib/SPIRV/TypeTranslator.h

@@ -233,6 +233,13 @@ public:
   /// matrix type.
   /// matrix type.
   uint32_t getComponentVectorType(QualType matrixType);
   uint32_t getComponentVectorType(QualType matrixType);
 
 
+  /// \brief Returns true if all members in structType are of the same element
+  /// type and can be fit into a 4-component vector. Writes element type and
+  /// count to *elemType and *elemCount if not nullptr. Otherwise, emit errors
+  /// explaining why not.
+  bool canFitIntoOneRegister(QualType structType, QualType *elemType = nullptr,
+                             uint32_t *elemCount = nullptr);
+
   /// \brief Returns the capability required for the given storage image type.
   /// \brief Returns the capability required for the given storage image type.
   /// Returns Capability::Max to mean no capability requirements.
   /// Returns Capability::Max to mean no capability requirements.
   static spv::Capability getCapabilityForStorageImageReadWrite(QualType type);
   static spv::Capability getCapabilityForStorageImageReadWrite(QualType type);
@@ -302,7 +309,7 @@ private:
   /// fieldSize and fieldAlignment are the original size and alignment
   /// fieldSize and fieldAlignment are the original size and alignment
   /// calculated without considering the HLSL vector relaxed rule.
   /// calculated without considering the HLSL vector relaxed rule.
   void alignUsingHLSLRelaxedLayout(QualType fieldType, uint32_t fieldSize,
   void alignUsingHLSLRelaxedLayout(QualType fieldType, uint32_t fieldSize,
-                                   uint32_t *fieldAlignment,
+                                   uint32_t fieldAlignment,
                                    uint32_t *currentOffset);
                                    uint32_t *currentOffset);
 
 
 public:
 public:

+ 28 - 0
tools/clang/lib/Sema/SemaHLSL.cpp

@@ -3736,6 +3736,11 @@ public:
     DXASSERT_VALIDBASICKIND(componentType);
     DXASSERT_VALIDBASICKIND(componentType);
 
 
     QualType pType;  // The type to return.
     QualType pType;  // The type to return.
+    if (componentType < AR_BASIC_COUNT) {
+      // If basic numeric, call LookupScalarTypeDef to ensure on-demand
+      // initialization
+      LookupScalarTypeDef(ScalarTypeForBasic(componentType));
+    }
     QualType pEltType = GetBasicKindType(componentType);
     QualType pEltType = GetBasicKindType(componentType);
     DXASSERT(!pEltType.isNull(), "otherwise caller is specifying an incorrect basic kind type");
     DXASSERT(!pEltType.isNull(), "otherwise caller is specifying an incorrect basic kind type");
 
 
@@ -10494,6 +10499,7 @@ void hlsl::HandleDeclAttributeForHLSL(Sema &S, Decl *D, const AttributeList &A,
       A.getAttributeSpellingListIndex());
       A.getAttributeSpellingListIndex());
     break;
     break;
   case AttributeList::AT_HLSLLinear:
   case AttributeList::AT_HLSLLinear:
+  case AttributeList::AT_HLSLCenter:
     declAttr = ::new (S.Context) HLSLLinearAttr(A.getRange(), S.Context,
     declAttr = ::new (S.Context) HLSLLinearAttr(A.getRange(), S.Context,
       A.getAttributeSpellingListIndex());
       A.getAttributeSpellingListIndex());
     break;
     break;
@@ -11183,6 +11189,7 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC,
     *pNoPerspective = nullptr,
     *pNoPerspective = nullptr,
     *pSample = nullptr,
     *pSample = nullptr,
     *pCentroid = nullptr,
     *pCentroid = nullptr,
+    *pCenter = nullptr,
     *pAnyLinear = nullptr,                   // first linear attribute found
     *pAnyLinear = nullptr,                   // first linear attribute found
     *pTopology = nullptr;
     *pTopology = nullptr;
   bool usageIn = false;
   bool usageIn = false;
@@ -11274,6 +11281,7 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC,
       break;
       break;
 
 
     case AttributeList::AT_HLSLLinear:
     case AttributeList::AT_HLSLLinear:
+    case AttributeList::AT_HLSLCenter:
     case AttributeList::AT_HLSLNoPerspective:
     case AttributeList::AT_HLSLNoPerspective:
     case AttributeList::AT_HLSLSample:
     case AttributeList::AT_HLSLSample:
     case AttributeList::AT_HLSLCentroid:
     case AttributeList::AT_HLSLCentroid:
@@ -11294,6 +11302,13 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC,
         }
         }
         pLinear = pAttr;
         pLinear = pAttr;
         break;
         break;
+      case AttributeList::AT_HLSLCenter:
+        if (pCenter) {
+          Diag(pAttr->getLoc(), diag::warn_hlsl_duplicate_specifier)
+            << pAttr->getName() << pAttr->getRange();
+        }
+        pCenter = pAttr;
+        break;
       case AttributeList::AT_HLSLNoPerspective:
       case AttributeList::AT_HLSLNoPerspective:
         if (pNoPerspective) {
         if (pNoPerspective) {
           Diag(pAttr->getLoc(), diag::warn_hlsl_duplicate_specifier)
           Diag(pAttr->getLoc(), diag::warn_hlsl_duplicate_specifier)
@@ -11361,6 +11376,14 @@ bool Sema::DiagnoseHLSLDecl(Declarator &D, DeclContext *DC,
     Diag(pCentroid->getLoc(), diag::warn_hlsl_specifier_overridden)
     Diag(pCentroid->getLoc(), diag::warn_hlsl_specifier_overridden)
         << pCentroid->getName() << pSample->getName() << pCentroid->getRange();
         << pCentroid->getName() << pSample->getName() << pCentroid->getRange();
   }
   }
+  if (pCenter && pCentroid) {
+    Diag(pCenter->getLoc(), diag::warn_hlsl_specifier_overridden)
+      << pCenter->getName() << pCentroid->getName() << pCenter->getRange();
+  }
+  if (pSample && pCenter) {
+    Diag(pCenter->getLoc(), diag::warn_hlsl_specifier_overridden)
+      << pCenter->getName() << pSample->getName() << pCenter->getRange();
+  }
   clang::AttributeList *pNonUniformAttr = pAnyLinear ? pAnyLinear : (
   clang::AttributeList *pNonUniformAttr = pAnyLinear ? pAnyLinear : (
     pNoInterpolation ? pNoInterpolation : pTopology);
     pNoInterpolation ? pNoInterpolation : pTopology);
   if (pUniform && pNonUniformAttr) {
   if (pUniform && pNonUniformAttr) {
@@ -11648,6 +11671,10 @@ void hlsl::CustomPrintHLSLAttr(const clang::Attr *A, llvm::raw_ostream &Out, con
     Out << "linear ";
     Out << "linear ";
     break;
     break;
 
 
+  case clang::attr::HLSLCenter:
+    Out << "center ";
+    break;
+
   case clang::attr::HLSLCentroid:
   case clang::attr::HLSLCentroid:
     Out << "centroid ";
     Out << "centroid ";
     break;
     break;
@@ -11924,6 +11951,7 @@ bool hlsl::IsHLSLAttr(clang::attr::Kind AttrKind) {
   case clang::attr::HLSLInOut:
   case clang::attr::HLSLInOut:
   case clang::attr::HLSLInstance:
   case clang::attr::HLSLInstance:
   case clang::attr::HLSLLinear:
   case clang::attr::HLSLLinear:
+  case clang::attr::HLSLCenter:
   case clang::attr::HLSLLoop:
   case clang::attr::HLSLLoop:
   case clang::attr::HLSLMaxTessFactor:
   case clang::attr::HLSLMaxTessFactor:
   case clang::attr::HLSLNoInterpolation:
   case clang::attr::HLSLNoInterpolation:

+ 11 - 0
tools/clang/test/CodeGenHLSL/quick-test/center_kwd.hlsl

@@ -0,0 +1,11 @@
+// RUN: %dxc -T ps_6_0 -Od -E main %s | FileCheck %s 
+
+// CHECK: %center = alloca float, align 4
+
+// make sure 'center' is allowed as an interpolation modifier
+float main(center float t : T) : SV_TARGET
+{
+    // and also as an identifier
+    float center = 10.0f;
+    return center * 2;
+}

+ 13 - 0
tools/clang/test/CodeGenHLSL/quick-test/matrix_return_sub2.hlsl

@@ -0,0 +1,13 @@
+// RUN: %dxc -E main -T ps_6_0 %s | FileCheck %s
+
+// Make sure this works on function that returns matrix
+// CHECK: call %dx.types.CBufRet.f32 @dx.op.cbufferLoad
+
+float4x4 m;
+float4x4 GetMat() {
+  return m;
+}
+
+float main() : SV_Target {
+  return GetMat()._m01;
+}

+ 11 - 0
tools/clang/test/CodeGenHLSL/quick-test/min10float.hlsl

@@ -0,0 +1,11 @@
+// RUN: %dxc -E main -T ps_6_0 -Zi %s | FileCheck %s
+
+// CHECK: warning: min10float is promoted to min16float
+// CHECK: define void @main
+// CHECK: ret void
+
+[RootSignature("")]
+min10float main( min10float mf:P ) : SV_Target
+{
+    return  mf * 2;
+}

+ 21 - 0
tools/clang/test/CodeGenHLSL/quick-test/min10float_to_float.hlsl

@@ -0,0 +1,21 @@
+// RUN: %dxc -E main -T ps_6_0 -Zi %s | FileCheck %s
+
+// CHECK: warning: min10float is promoted to min16float
+// CHECK: define void @main
+// CHECK: ret void
+
+[RootSignature("")]
+float2 main( min10float mf:P , int s:Q) : SV_Target
+{
+    if(s > 1)
+    {
+        min10float new_mf = mf * mf;
+        new_mf = new_mf / 2.0;
+        float f = float(new_mf);
+        f = (f * 4.0) / 3.3;
+        min10float new_mf1 = min10float(f);
+        new_mf1 = new_mf1 + new_mf;
+        return float2(new_mf1, new_mf1);
+    }
+    return float2(1.0, 1.0);
+}

+ 11 - 0
tools/clang/test/CodeGenHLSL/quick-test/min12int.hlsl

@@ -0,0 +1,11 @@
+// RUN: %dxc -E main -T ps_6_0 -Zi %s | FileCheck %s
+
+// CHECK: warning: min12int is promoted to min16int
+// CHECK: define void @main
+// CHECK: ret void
+
+[RootSignature("")]
+min12int main( min12int mi:P ) : SV_Target
+{
+    return  mi * 2;
+}

+ 21 - 0
tools/clang/test/CodeGenHLSL/quick-test/min12int_to_int.hlsl

@@ -0,0 +1,21 @@
+// RUN: %dxc -E main -T ps_6_0 -Zi %s | FileCheck %s
+
+// CHECK: warning: min12int is promoted to min16int
+// CHECK: define void @main
+// CHECK: ret void
+
+[RootSignature("")]
+int2 main( min12int mi:P , int s:Q) : SV_Target
+{
+    if(s > 1)
+    {
+        min12int new_mi = mi * mi;
+        new_mi = min12int(new_mi * 2);
+        int f = int(new_mi);
+        f = (f * 4) / 3;
+        min12int new_mi1 = min12int(f);
+        new_mi1 = new_mi1 + new_mi;
+        return int2(new_mi1, new_mi1);
+    }
+    return int2(1, 1);
+}

+ 12 - 0
tools/clang/test/CodeGenHLSL/quick-test/sample-offset-imm-test01.hlsl

@@ -0,0 +1,12 @@
+// RUN: %dxc /O0 /Tps_6_0 /Emain > %s | FileCheck %s
+// CHECK: define void @main()
+// CHECK: entry
+Texture2D g_Tex;
+SamplerState g_Sampler;
+void unused() { }
+float4 main(float4 pos : SV_Position, float4 user : USER, bool b : B) : SV_Target {
+	unused();
+	int2 offset = int2(0,-1);
+	if (b) user = g_Tex.SampleLevel(g_Sampler, pos.xy, 0.0, offset.xy);
+	return user * pos;
+}

+ 14 - 0
tools/clang/test/CodeGenHLSL/quick-test/sample-offset-imm-test02.hlsl

@@ -0,0 +1,14 @@
+// RUN: %dxc /O0 /Tps_6_0 /Emain > %s | FileCheck %s
+// CHECK: define void @main()
+// CHECK: entry
+Texture2D g_Tex;
+SamplerState g_Sampler;
+void unused() { }
+float4 main(float4 pos : SV_Position, float4 user : USER, bool b : B) : SV_Target {
+	unused();
+	int2 offset = int2(0,-1);
+	float4 g_Buffer = {-1.0, 1.0, -2.0, 2.0};
+	float4 shift = float4(g_Buffer[offset.x], g_Buffer[offset.x], g_Buffer[offset.x], g_Buffer[offset.y]);
+	if (b) user = g_Tex.SampleLevel(g_Sampler, pos.xy, 0.0, offset.xy);
+	return user * (pos * shift);
+}

+ 18 - 0
tools/clang/test/CodeGenHLSL/quick-test/sample-offset-imm-test03.hlsl

@@ -0,0 +1,18 @@
+// RUN: %dxc /O0 /Od /Tps_6_0 /Emain > %s | FileCheck %s
+// CHECK: define void @main()
+// CHECK: entry
+Texture2D g_Tex;
+SamplerState g_Sampler;
+void unused() { }
+float4 main(float4 pos : SV_Position, float4 user : USER, bool b : B) : SV_Target {
+	unused();
+	int2 offset = int2(0,1);
+	float2x4 g_Buffer =
+	{
+	-1.0, 1.0, -2.0, 2.0,
+	-1.0, -1.0, 2.0, -2.0,
+	};
+	float4 shift = float4(g_Buffer[offset.x][offset.x], g_Buffer[offset.y][offset.x], g_Buffer[offset.x][offset.y], g_Buffer[offset.y][offset.y]);
+	if (b) user = g_Tex.SampleLevel(g_Sampler, pos.xy, 0.0, offset.xy);
+	return user * (pos * shift);
+}

+ 12 - 0
tools/clang/test/CodeGenHLSL/quick-test/sample-offset-imm-test04.hlsl

@@ -0,0 +1,12 @@
+// RUN: %dxc /O0 /Od /Tps_6_0 /Emain > %s | FileCheck %s
+// CHECK: define void @main()
+// CHECK: entry
+Texture2D g_Tex;
+SamplerState g_Sampler;
+void unused() { }
+float4 main(float4 pos : SV_Position, float4 user : USER, bool b : B) : SV_Target {
+	unused();
+	int2 offset[2] = { int2(0,1), int2(1,0) };
+	if (b) user = g_Tex.SampleLevel(g_Sampler, pos.xy, 0.0, int2(offset[1].x, offset[0].y));
+	return user * pos;
+}

+ 49 - 0
tools/clang/test/CodeGenHLSL/quick-test/sample_kwd.hlsl

@@ -0,0 +1,49 @@
+// RUN: %dxc -T ps_6_0 -Od -E main %s | FileCheck %s
+
+// CHECK: %precise = alloca float, align 4
+// CHECK: %globallycoherent = alloca i32, align 4
+// CHECK: %sample = alloca float, align 4
+// CHECK: %center = alloca float, align 4
+
+// CHECK: call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %MyBuffer_UAV_structbuf, i32 0, i32 0)
+// CHECK: call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %MyBuffer_UAV_structbuf, i32 0, i32 16)
+// CHECK: call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %MyBuffer_UAV_structbuf, i32 0, i32 32)
+// CHECK: call %dx.types.ResRet.f32 @dx.op.bufferLoad.f32(i32 68, %dx.types.Handle %MyBuffer_UAV_structbuf, i32 0, i32 48)
+
+// Check function parameters are accepted
+float3 foo(float3 sample) {
+    return sample;
+}
+
+// Check member fields are accepted
+struct S {
+  float4 center;
+  float4 precise;
+  float4 sample;
+  float4 globallycoherent;
+};
+
+RWStructuredBuffer<S> MyBuffer;
+
+float4 main(float4 input : SV_POSITION) : SV_TARGET
+{
+    // Check declarations are accepted
+    float precise = 1.0f;
+    int globallycoherent = 1;
+    float sample;
+
+    // Check assignments are accepted
+    sample = 1.0f;
+    globallycoherent += 10;
+
+    // Check declaration group is accepted
+    float left, center = 1.0, right;
+
+    // Check parentheses are accepted
+    // (they go through the path for type cast in frontend)
+    float w = (center).x;
+
+    return float4(foo(float3(precise, globallycoherent, sample)), w) +
+           MyBuffer[0].center + MyBuffer[0].precise +
+           MyBuffer[0].sample + MyBuffer[0].globallycoherent;
+}

+ 0 - 3
tools/clang/test/CodeGenSPIRV/bezier.domain.hlsl2spv

@@ -167,10 +167,8 @@ DS_OUTPUT BezierEvalDS( HS_CONSTANT_DATA_OUTPUT input,
 // %35 = OpLoad %_arr_v3float_uint_4 %in_var_TANVCORNER
 // %35 = OpLoad %_arr_v3float_uint_4 %in_var_TANVCORNER
 // %38 = OpLoad %v4float %in_var_TANWEIGHTS
 // %38 = OpLoad %v4float %in_var_TANWEIGHTS
 // %39 = OpCompositeConstruct %HS_CONSTANT_DATA_OUTPUT %22 %25 %28 %31 %33 %35 %38
 // %39 = OpCompositeConstruct %HS_CONSTANT_DATA_OUTPUT %22 %25 %28 %31 %33 %35 %38
-// OpStore %param_var_input %39
 // %44 = OpLoad %v3float %gl_TessCoord
 // %44 = OpLoad %v3float %gl_TessCoord
 // %45 = OpVectorShuffle %v2float %44 %44 0 1
 // %45 = OpVectorShuffle %v2float %44 %44 0 1
-// OpStore %param_var_UV %45
 // %51 = OpLoad %_arr_v3float_uint_4 %in_var_BEZIERPOS
 // %51 = OpLoad %_arr_v3float_uint_4 %in_var_BEZIERPOS
 // %52 = OpCompositeExtract %v3float %51 0
 // %52 = OpCompositeExtract %v3float %51 0
 // %53 = OpCompositeConstruct %BEZIER_CONTROL_POINT %52
 // %53 = OpCompositeConstruct %BEZIER_CONTROL_POINT %52
@@ -181,7 +179,6 @@ DS_OUTPUT BezierEvalDS( HS_CONSTANT_DATA_OUTPUT input,
 // %58 = OpCompositeExtract %v3float %51 3
 // %58 = OpCompositeExtract %v3float %51 3
 // %59 = OpCompositeConstruct %BEZIER_CONTROL_POINT %58
 // %59 = OpCompositeConstruct %BEZIER_CONTROL_POINT %58
 // %60 = OpCompositeConstruct %_arr_BEZIER_CONTROL_POINT_uint_4 %53 %55 %57 %59
 // %60 = OpCompositeConstruct %_arr_BEZIER_CONTROL_POINT_uint_4 %53 %55 %57 %59
-// OpStore %param_var_bezpatch %60
 // %62 = OpFunctionCall %DS_OUTPUT %src_BezierEvalDS %param_var_input %param_var_UV %param_var_bezpatch
 // %62 = OpFunctionCall %DS_OUTPUT %src_BezierEvalDS %param_var_input %param_var_UV %param_var_bezpatch
 // %63 = OpCompositeExtract %v3float %62 0
 // %63 = OpCompositeExtract %v3float %62 0
 // OpStore %out_var_NORMAL %63
 // OpStore %out_var_NORMAL %63

+ 0 - 3
tools/clang/test/CodeGenSPIRV/bezier.hull.hlsl2spv

@@ -212,11 +212,8 @@ BEZIER_CONTROL_POINT SubDToBezierHS(InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POIN
 // %35 = OpCompositeExtract %v3float %24 2
 // %35 = OpCompositeExtract %v3float %24 2
 // %36 = OpCompositeConstruct %VS_CONTROL_POINT_OUTPUT %33 %34 %35
 // %36 = OpCompositeConstruct %VS_CONTROL_POINT_OUTPUT %33 %34 %35
 // %37 = OpCompositeConstruct %_arr_VS_CONTROL_POINT_OUTPUT_uint_3 %28 %32 %36
 // %37 = OpCompositeConstruct %_arr_VS_CONTROL_POINT_OUTPUT_uint_3 %28 %32 %36
-// OpStore %param_var_ip %37
 // %42 = OpLoad %uint %gl_InvocationID
 // %42 = OpLoad %uint %gl_InvocationID
-// OpStore %param_var_cpid %42
 // %45 = OpLoad %uint %gl_PrimitiveID
 // %45 = OpLoad %uint %gl_PrimitiveID
-// OpStore %param_var_PatchID %45
 // %47 = OpFunctionCall %BEZIER_CONTROL_POINT %src_SubDToBezierHS %param_var_ip %param_var_cpid %param_var_PatchID
 // %47 = OpFunctionCall %BEZIER_CONTROL_POINT %src_SubDToBezierHS %param_var_ip %param_var_cpid %param_var_PatchID
 // %48 = OpCompositeExtract %v3float %47 0
 // %48 = OpCompositeExtract %v3float %47 0
 // %52 = OpAccessChain %_ptr_Output_v3float %out_var_BEZIERPOS %42
 // %52 = OpAccessChain %_ptr_Output_v3float %out_var_BEZIERPOS %42

+ 9 - 7
tools/clang/test/CodeGenSPIRV/empty-struct-interface.vs.hlsl2spv

@@ -22,25 +22,27 @@ VSOut main(VSIn input)
 // OpName %main "main"
 // OpName %main "main"
 // OpName %VSIn "VSIn"
 // OpName %VSIn "VSIn"
 // OpName %param_var_input "param.var.input"
 // OpName %param_var_input "param.var.input"
+// OpName %VSOut "VSOut"
 // OpName %input "input"
 // OpName %input "input"
 // OpName %result "result"
 // OpName %result "result"
 // %void = OpTypeVoid
 // %void = OpTypeVoid
 // %3 = OpTypeFunction %void
 // %3 = OpTypeFunction %void
 // %VSIn = OpTypeStruct
 // %VSIn = OpTypeStruct
 // %_ptr_Function_VSIn = OpTypePointer Function %VSIn
 // %_ptr_Function_VSIn = OpTypePointer Function %VSIn
-// %11 = OpTypeFunction %VSIn %_ptr_Function_VSIn
+// %VSOut = OpTypeStruct
+// %12 = OpTypeFunction %VSOut %_ptr_Function_VSIn
+// %_ptr_Function_VSOut = OpTypePointer Function %VSOut
 // %main = OpFunction %void None %3
 // %main = OpFunction %void None %3
 // %5 = OpLabel
 // %5 = OpLabel
 // %param_var_input = OpVariable %_ptr_Function_VSIn Function
 // %param_var_input = OpVariable %_ptr_Function_VSIn Function
 // %9 = OpCompositeConstruct %VSIn
 // %9 = OpCompositeConstruct %VSIn
-// OpStore %param_var_input %9
-// %10 = OpFunctionCall %VSIn %src_main %param_var_input
+// %11 = OpFunctionCall %VSOut %src_main %param_var_input
 // OpReturn
 // OpReturn
 // OpFunctionEnd
 // OpFunctionEnd
-// %src_main = OpFunction %VSIn None %11
+// %src_main = OpFunction %VSOut None %12
 // %input = OpFunctionParameter %_ptr_Function_VSIn
 // %input = OpFunctionParameter %_ptr_Function_VSIn
 // %bb_entry = OpLabel
 // %bb_entry = OpLabel
-// %result = OpVariable %_ptr_Function_VSIn Function
-// %15 = OpLoad %VSIn %result
-// OpReturnValue %15
+// %result = OpVariable %_ptr_Function_VSOut Function
+// %17 = OpLoad %VSOut %result
+// OpReturnValue %17
 // OpFunctionEnd
 // OpFunctionEnd

+ 1 - 1
tools/clang/test/CodeGenSPIRV/hs.pcf.primitive-id.1.hlsl

@@ -45,6 +45,6 @@ HS_CONSTANT_DATA_OUTPUT PCF(uint PatchID : SV_PrimitiveID) {
 BEZIER_CONTROL_POINT main(InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POINTS> ip, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID) {
 BEZIER_CONTROL_POINT main(InputPatch<VS_CONTROL_POINT_OUTPUT, MAX_POINTS> ip, uint i : SV_OutputControlPointID, uint PatchID : SV_PrimitiveID) {
   VS_CONTROL_POINT_OUTPUT vsOutput;
   VS_CONTROL_POINT_OUTPUT vsOutput;
   BEZIER_CONTROL_POINT result;
   BEZIER_CONTROL_POINT result;
-  result.vPosition = vsOutput.vPosition;
+  result.vPosition = vsOutput.vPosition + PatchID;
   return result;
   return result;
 }
 }

+ 1 - 1
tools/clang/test/CodeGenSPIRV/hs.pcf.view-id.1.hlsl

@@ -44,7 +44,7 @@ HsCpOut main(InputPatch<HsCpIn, NumOutPoints> patch,
              uint id : SV_OutputControlPointID,
              uint id : SV_OutputControlPointID,
              uint viewid : SV_ViewID) {
              uint viewid : SV_ViewID) {
     HsCpOut output;
     HsCpOut output;
-    output = (HsCpOut)0;
+    output.bar = viewid;
     return output;
     return output;
 // CHECK:             %main = OpFunction %void None {{%\d+}}
 // CHECK:             %main = OpFunction %void None {{%\d+}}
 // CHECK: %param_var_viewid = OpVariable %_ptr_Function_uint Function
 // CHECK: %param_var_viewid = OpVariable %_ptr_Function_uint Function

+ 19 - 0
tools/clang/test/CodeGenSPIRV/intrinsics.interlocked-methods.error.hlsl

@@ -0,0 +1,19 @@
+// Run: %dxc -T cs_6_0 -E main
+
+groupshared float MyFloat;
+RWBuffer<float> MyBuffer;
+
+typedef int MyIntegerType;
+RWStructuredBuffer<MyIntegerType> MySBuffer;
+
+[numthreads(1, 1, 1)]
+void main()
+{
+  InterlockedAdd(MyFloat, 1);
+  InterlockedCompareStore(MyBuffer[0], MySBuffer[0], MySBuffer[1]);
+  InterlockedXor(MySBuffer[2], 5);
+}
+
+// CHECK:     :12:18: error: can only perform atomic operations on scalar integer values
+// CHECK:     :13:27: error: can only perform atomic operations on scalar integer values
+// CHECK-NOT:         error: can only perform atomic operations on scalar integer values

+ 33 - 0
tools/clang/test/CodeGenSPIRV/op.buffer.access.hlsl

@@ -15,6 +15,14 @@ RWBuffer<int4> int4buf;
 RWBuffer<uint4> uint4buf;
 RWBuffer<uint4> uint4buf;
 RWBuffer<float4> float4buf;
 RWBuffer<float4> float4buf;
 
 
+struct S {
+  float  a;
+  float2 b;
+  float1 c;
+};
+
+  Buffer<S> sBuf;
+
 void main() {
 void main() {
   int address;
   int address;
 
 
@@ -102,4 +110,29 @@ void main() {
 // CHECK-NEXT:     [[b:%\d+]] = OpLoad %float [[ac14]]
 // CHECK-NEXT:     [[b:%\d+]] = OpLoad %float [[ac14]]
 // CHECK-NEXT:                  OpStore %b [[b]]
 // CHECK-NEXT:                  OpStore %b [[b]]
   float b = float4buf[address][2];
   float b = float4buf[address][2];
+
+// CHECK:        [[img:%\d+]] = OpLoad %type_buffer_image_7 %sBuf
+// CHECK-NEXT: [[fetch:%\d+]] = OpImageFetch %v4float [[img]] %uint_0 None
+// CHECK-NEXT:   [[s_a:%\d+]] = OpCompositeExtract %float [[fetch]] 0
+// CHECK-NEXT:   [[s_b:%\d+]] = OpVectorShuffle %v2float [[fetch]] [[fetch]] 1 2
+// CHECK-NEXT:   [[s_c:%\d+]] = OpCompositeExtract %float [[fetch]] 3
+// CHECK-NEXT:     [[s:%\d+]] = OpCompositeConstruct %S [[s_a]] [[s_b]] [[s_c]]
+// CHECK-NEXT:                  OpStore %temp_var_S [[s]]
+// CHECK-NEXT:   [[ptr:%\d+]] = OpAccessChain %_ptr_Function_float %temp_var_S %int_0
+// CHECK-NEXT:     [[c:%\d+]] = OpLoad %float [[ptr]]
+// CHECK-NEXT:                  OpStore %c [[c]]
+  float c = sBuf[0].a;
+
+// CHECK:        [[img:%\d+]] = OpLoad %type_buffer_image_7 %sBuf
+// CHECK-NEXT: [[fetch:%\d+]] = OpImageFetch %v4float [[img]] %uint_1 None
+// CHECK-NEXT:   [[s_a:%\d+]] = OpCompositeExtract %float [[fetch]] 0
+// CHECK-NEXT:   [[s_b:%\d+]] = OpVectorShuffle %v2float [[fetch]] [[fetch]] 1 2
+// CHECK-NEXT:   [[s_c:%\d+]] = OpCompositeExtract %float [[fetch]] 3
+// CHECK-NEXT:     [[s:%\d+]] = OpCompositeConstruct %S [[s_a]] [[s_b]] [[s_c]]
+// CHECK-NEXT:                  OpStore %temp_var_S_0 [[s]]
+// CHECK-NEXT:   [[ptr:%\d+]] = OpAccessChain %_ptr_Function_v2float %temp_var_S_0 %int_1
+// CHECK-NEXT:   [[val:%\d+]] = OpLoad %v2float [[ptr]]
+// CHECK-NEXT:     [[d:%\d+]] = OpCompositeExtract %float [[val]] 1
+// CHECK-NEXT:                  OpStore %d [[d]]
+  float d = sBuf[1].b.y;
 }
 }

+ 29 - 3
tools/clang/test/CodeGenSPIRV/op.struct.access.hlsl

@@ -1,10 +1,13 @@
 // Run: %dxc -T ps_6_0 -E main
 // Run: %dxc -T ps_6_0 -E main
 
 
 struct S {
 struct S {
-    bool a;
-    uint2 b;
+    bool     a;
+    uint2    b;
     float2x3 c;
     float2x3 c;
-    float4 d;
+    float4   d;
+    float4   e[1];
+    float    f[4];
+    int      g;
 };
 };
 
 
 struct T {
 struct T {
@@ -17,6 +20,17 @@ T foo() {
     return ret;
     return ret;
 }
 }
 
 
+S bar() {
+    S ret = (S)0;
+    return ret;
+}
+
+ConstantBuffer<S> MyBuffer;
+
+S baz() {
+    return MyBuffer;
+}
+
 float4 main() : SV_Target {
 float4 main() : SV_Target {
     T t;
     T t;
 
 
@@ -75,6 +89,18 @@ float4 main() : SV_Target {
 // CHECK-NEXT: OpStore [[c0]] {{%\d+}}
 // CHECK-NEXT: OpStore [[c0]] {{%\d+}}
     t.i.c[0] = v6;
     t.i.c[0] = v6;
 
 
+// CHECK:       [[baz:%\d+]] = OpFunctionCall %S %baz
+// CHECK-NEXT:                 OpStore %temp_var_S [[baz]]
+// CHECK-NEXT:                 OpAccessChain %_ptr_Function_v4float %temp_var_S %int_4 %int_0
+// CHECK:       [[bar:%\d+]] = OpFunctionCall %S %bar
+// CHECK-NEXT:                 OpStore %temp_var_S_0 [[bar]]
+// CHECK-NEXT:                 OpAccessChain %_ptr_Function_float %temp_var_S_0 %int_5 %int_1
+    float4 val1 = bar().f[1] * baz().e[0];
+
+// CHECK:        [[ac:%\d+]] = OpAccessChain %_ptr_Function_int %temp_var_S_1 %int_6
+// CHECK-NEXT:                 OpLoad %int [[ac]]
+    bool val2 = bar().g; // Need cast on rvalue function return
+
 // CHECK:      [[ret:%\d+]] = OpFunctionCall %T %foo
 // CHECK:      [[ret:%\d+]] = OpFunctionCall %T %foo
 // CHECK-NEXT: OpStore %temp_var_T [[ret]]
 // CHECK-NEXT: OpStore %temp_var_T [[ret]]
 // CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Function_v4float %temp_var_T %int_1 %int_3
 // CHECK-NEXT: [[ptr:%\d+]] = OpAccessChain %_ptr_Function_v4float %temp_var_T %int_1 %int_3

+ 19 - 0
tools/clang/test/CodeGenSPIRV/op.texture.access.hlsl

@@ -10,6 +10,13 @@ Texture2DArray   <int3>   t6;
 // There is no operator[] for TextureCubeArray in HLSL reference.
 // There is no operator[] for TextureCubeArray in HLSL reference.
 // There is no operator[] for Texture2DMSArray in HLSL reference.
 // There is no operator[] for Texture2DMSArray in HLSL reference.
 
 
+struct S {
+  float  a;
+  float2 b;
+  float1 c;
+};
+
+Texture2D <S> tStruct;
 
 
 // CHECK:  [[cu12:%\d+]] = OpConstantComposite %v2uint %uint_1 %uint_2
 // CHECK:  [[cu12:%\d+]] = OpConstantComposite %v2uint %uint_1 %uint_2
 // CHECK: [[cu123:%\d+]] = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
 // CHECK: [[cu123:%\d+]] = OpConstantComposite %v3uint %uint_1 %uint_2 %uint_3
@@ -55,4 +62,16 @@ void main() {
 // CHECK-NEXT: [[result6:%\d+]] = OpVectorShuffle %v3int [[f6]] [[f6]] 0 1 2
 // CHECK-NEXT: [[result6:%\d+]] = OpVectorShuffle %v3int [[f6]] [[f6]] 0 1 2
 // CHECK-NEXT: OpStore %a6 [[result6]]
 // CHECK-NEXT: OpStore %a6 [[result6]]
   int3   a6 = t6[uint3(1,2,3)];
   int3   a6 = t6[uint3(1,2,3)];
+
+// CHECK:        [[tex:%\d+]] = OpLoad %type_2d_image_1 %tStruct
+// CHECK-NEXT: [[fetch:%\d+]] = OpImageFetch %v4float [[tex]] {{%\d+}} Lod %uint_0
+// CHECK-NEXT:     [[a:%\d+]] = OpCompositeExtract %float [[fetch]] 0
+// CHECK-NEXT:     [[b:%\d+]] = OpVectorShuffle %v2float [[fetch]] [[fetch]] 1 2
+// CHECK-NEXT:     [[c:%\d+]] = OpCompositeExtract %float [[fetch]] 3
+// CHECK-NEXT:     [[s:%\d+]] = OpCompositeConstruct %S [[a]] [[b]] [[c]]
+// CHECK-NEXT:                  OpStore %temp_var_S [[s]]
+// CHECK-NEXT:   [[ptr:%\d+]] = OpAccessChain %_ptr_Function_float %temp_var_S %int_2
+// CHECK-NEXT:   [[val:%\d+]] = OpLoad %float [[ptr]]
+// CHECK-NEXT:                  OpStore %a7 [[val]]
+  float  a7 = tStruct[uint2(1, 2)].c;
 }
 }

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä