Repository: HansKristian-Work/dxil-spirv
Branch: master
Commit: 62dbb07f7715
Files: 2195
Total size: 9.0 MB
Directory structure:
gitextract_06b8vcw_/
├── .clang-format
├── .gitattributes
├── .gitignore
├── .gitmodules
├── CMakeLists.txt
├── DESCRIPTORS.md
├── LICENSE.MIT
├── README.md
├── bc/
│ ├── CMakeLists.txt
│ ├── cast.hpp
│ ├── context.cpp
│ ├── context.hpp
│ ├── data_structures.hpp
│ ├── disassembler.cpp
│ ├── function.cpp
│ ├── function.hpp
│ ├── instruction.cpp
│ ├── instruction.hpp
│ ├── iterator.hpp
│ ├── metadata.cpp
│ ├── metadata.hpp
│ ├── module.cpp
│ ├── module.hpp
│ ├── module_dxbc_ir.cpp
│ ├── type.cpp
│ ├── type.hpp
│ ├── value.cpp
│ └── value.hpp
├── build_dxc.sh
├── cfg_structurizer.cpp
├── cfg_structurizer.hpp
├── checkout_dxc.sh
├── checkout_llvm.sh
├── copy_reference_shaders.py
├── debug/
│ ├── logging.cpp
│ └── logging.hpp
├── descriptor_qa.cpp
├── descriptor_qa.hpp
├── dxbc_spirv_sandbox.cpp
├── dxil-disasm.py
├── dxil.hpp
├── dxil_converter.cpp
├── dxil_converter.hpp
├── dxil_extract.cpp
├── dxil_parser.cpp
├── dxil_parser.hpp
├── dxil_spirv.cpp
├── dxil_spirv_c.cpp
├── dxil_spirv_c.h
├── external/
│ └── CMakeLists.txt
├── format_all.sh
├── ir.hpp
├── link.T
├── llvm_bitcode_parser.cpp
├── llvm_bitcode_parser.hpp
├── memory_stream.cpp
├── memory_stream.hpp
├── meson.build
├── misc/
│ └── structurize_test.cpp
├── node.cpp
├── node.hpp
├── node_pool.cpp
├── node_pool.hpp
├── opcodes/
│ ├── converter_impl.hpp
│ ├── dxil/
│ │ ├── dxil_ags.cpp
│ │ ├── dxil_ags.hpp
│ │ ├── dxil_arithmetic.cpp
│ │ ├── dxil_arithmetic.hpp
│ │ ├── dxil_buffer.cpp
│ │ ├── dxil_buffer.hpp
│ │ ├── dxil_common.cpp
│ │ ├── dxil_common.hpp
│ │ ├── dxil_compute.cpp
│ │ ├── dxil_compute.hpp
│ │ ├── dxil_geometry.cpp
│ │ ├── dxil_geometry.hpp
│ │ ├── dxil_mesh.cpp
│ │ ├── dxil_mesh.hpp
│ │ ├── dxil_nvapi.cpp
│ │ ├── dxil_nvapi.hpp
│ │ ├── dxil_pixel_ops.cpp
│ │ ├── dxil_pixel_ops.hpp
│ │ ├── dxil_ray_tracing.cpp
│ │ ├── dxil_ray_tracing.hpp
│ │ ├── dxil_resources.cpp
│ │ ├── dxil_resources.hpp
│ │ ├── dxil_sampling.cpp
│ │ ├── dxil_sampling.hpp
│ │ ├── dxil_tessellation.cpp
│ │ ├── dxil_tessellation.hpp
│ │ ├── dxil_waveops.cpp
│ │ ├── dxil_waveops.hpp
│ │ ├── dxil_workgraph.cpp
│ │ └── dxil_workgraph.hpp
│ ├── opcodes.hpp
│ ├── opcodes_dxil_builtins.cpp
│ ├── opcodes_dxil_builtins.hpp
│ ├── opcodes_llvm_builtins.cpp
│ └── opcodes_llvm_builtins.hpp
├── pkg-config/
│ └── dxil-spirv-c-shared.pc.in
├── reference/
│ └── shaders/
│ ├── ags/
│ │ ├── ags.ssbo.comp
│ │ ├── cs_constexpr_wmma_gep.sm66.full-wmma.ssbo.comp
│ │ ├── cs_constexpr_wmma_gep.sm66.ssbo.comp
│ │ ├── cs_wmma_alloca.sm66.ssbo.comp
│ │ ├── cs_wmma_copy_transpose_fp16.sm66.ssbo.comp
│ │ ├── cs_wmma_copy_transpose_fp16.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_extract_insert.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16_at.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16_bt.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16_ct.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16_ot.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_fp8.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8_quant_f16.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8_quant_f16_strided.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8_quant_f16_strided_transpose.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8_quant_f32.sm66.ssbo.comp
│ │ ├── cs_wmma_fp16_fp8_conversions.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_fp32_fp16_conversions.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_fp32_fp8_conversions.sm66.ssbo.nv-coopmat2.comp
│ │ ├── cs_wmma_fp8_fp32_conversions.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_lds_transpose.sm66.ssbo.comp
│ │ ├── cs_wmma_matrix_length.sm66.ssbo.comp
│ │ ├── cs_wmma_store_phi.full-wmma.sm66.ssbo.comp
│ │ └── cs_wmma_store_phi.sm66.ssbo.comp
│ ├── alloca-opts/
│ │ ├── bad-stride.frag
│ │ ├── double-array-load.frag
│ │ ├── float4-array-load.bindless.frag
│ │ ├── float4-array-load.bindless.root-constants.frag
│ │ ├── float4-array-load.frag
│ │ ├── float4-array-load.root-constant.frag
│ │ ├── float4-array-load.root-descriptor.frag
│ │ ├── float4-array-load.root-descriptor.root-constants.frag
│ │ ├── load-different.frag
│ │ ├── local-root-constants.local-root-signature.rgen
│ │ ├── matrix-load.frag
│ │ ├── missing-first.frag
│ │ ├── missing-last-element.frag
│ │ ├── out-of-order-load.frag
│ │ ├── store-after-load.frag
│ │ └── uint4-array-load.frag
│ ├── asm/
│ │ ├── bfi.bc.dxil
│ │ ├── cbv.no-legacy-cbuf-layout.sm66-heaps-single-alias.bc.dxil
│ │ ├── cbv.no-legacy-cbuf-layout.sm66-heaps.bc.dxil
│ │ ├── constant-struct-aggregate.bc.dxil
│ │ ├── control-flow-multi-break-with-non-idom-loop-header.dxil
│ │ ├── ibfe.bc.dxil
│ │ └── ubfe.bc.dxil
│ ├── auto-barrier/
│ │ ├── complex-loop.auto-group-shared-barrier.comp
│ │ ├── inner-to-inner.auto-group-shared-barrier.comp
│ │ ├── inner-to-outer.auto-group-shared-barrier.comp
│ │ ├── outer-to-inner.auto-group-shared-barrier.comp
│ │ ├── single-block-loop.auto-group-shared-barrier.comp
│ │ └── single-block.auto-group-shared-barrier.comp
│ ├── control-flow/
│ │ ├── branch-return-2.comp
│ │ ├── branch-return.comp
│ │ ├── branch.comp
│ │ ├── conditional-break-into-if-else-if-ladder-2.comp
│ │ ├── conditional-break-into-if-else-if-ladder.comp
│ │ ├── dual-inner-loop-early-return.comp
│ │ ├── if-else-if-into-continue.comp
│ │ ├── inner-loop-early-return.comp
│ │ ├── interleaved-unrolled-loop-breaks.comp
│ │ ├── loop-break-2.comp
│ │ ├── loop-break.comp
│ │ ├── loop-continue-2.comp
│ │ ├── loop-continue-3.comp
│ │ ├── loop-continue.comp
│ │ ├── loop-inside-infinite-loop-2.frag
│ │ ├── loop-inside-infinite-loop.frag
│ │ ├── loop-return.comp
│ │ ├── loop.comp
│ │ ├── nested-loop-break-2.comp
│ │ ├── nested-loop-break.comp
│ │ ├── nested-loop.comp
│ │ ├── selection-merge-split-post-domination.frag
│ │ ├── switch-continue.frag
│ │ ├── switch-merge-into-other-merge.comp
│ │ ├── switch-shared-header-with-loop.comp
│ │ └── wave-size-dependent-loop-unroll.comp
│ ├── descriptor_qa/
│ │ ├── acceleration-structure.bindless.descriptor-qa.rgen
│ │ ├── acceleration-structure.bindless.descriptor-qa.sm66.rgen
│ │ ├── acceleration-structure.bindless.ssbo-rtas.local-root-signature.descriptor-qa.rgen
│ │ ├── descriptor_qa.bindless.cbv-as-ssbo.descriptor-qa.comp
│ │ ├── descriptor_qa.bindless.descriptor-qa.comp
│ │ ├── descriptor_qa.bindless.descriptor-qa.sm66.comp
│ │ ├── descriptor_qa.bindless.ssbo.descriptor-qa.comp
│ │ ├── early-2.bindless.descriptor-qa.frag
│ │ ├── early-3.bindless.descriptor-qa.frag
│ │ ├── early-4.bindless.descriptor-qa.frag
│ │ ├── early-5.bindless.descriptor-qa.frag
│ │ ├── early-heap.descriptor-qa.sm66.frag
│ │ └── early.bindless.descriptor-qa.frag
│ ├── dxil-builtin/
│ │ ├── accept-hit-and-end-search-ignore-hit.rany
│ │ ├── acos.frag
│ │ ├── asin.frag
│ │ ├── atan.frag
│ │ ├── atomic-bin-op.bindless.root-constant.frag
│ │ ├── atomic-bin-op.frag
│ │ ├── atomic-bin-op.root-descriptor.comp
│ │ ├── atomic-bin-op.ssbo.frag
│ │ ├── atomic-compare-exchange.frag
│ │ ├── atomic-compare-exchange.root-descriptor.comp
│ │ ├── atomic-compare-exchange.ssbo.frag
│ │ ├── attributes.denorm-ftz.comp
│ │ ├── attributes.denorm-preserve.comp
│ │ ├── barrier.comp
│ │ ├── barycentrics-2.frag
│ │ ├── barycentrics.frag
│ │ ├── bfrev.frag
│ │ ├── bitcount-bitrev-sizes.ssbo.comp
│ │ ├── buffer-load-feedback.frag
│ │ ├── buffer-load-signed-feedback.frag
│ │ ├── buffer-load-signed.frag
│ │ ├── buffer-load.frag
│ │ ├── buffer-load.ssbo.frag
│ │ ├── buffer-store-signed.frag
│ │ ├── buffer-store.frag
│ │ ├── buffer-store.ssbo.frag
│ │ ├── buffer-update-counter.frag
│ │ ├── calculate-lod.frag
│ │ ├── call-shader.rgen
│ │ ├── clip.demote-to-helper.frag
│ │ ├── clip.frag
│ │ ├── compute-shader-derivatives-cube-array.noderivs.sm66.ssbo.comp
│ │ ├── compute-shader-derivatives-cube.noderivs.sm66.ssbo.comp
│ │ ├── compute-shader-derivatives-single-thread.sm66.ssbo.comp
│ │ ├── compute-shader-derivatives.noderivs.sm66.ssbo.comp
│ │ ├── cos.frag
│ │ ├── countbits.frag
│ │ ├── coverage.frag
│ │ ├── derivative.frag
│ │ ├── derivative.sm60.frag
│ │ ├── derivative.sm60.native-fp16.frag
│ │ ├── derivatives.sm66.comp
│ │ ├── discard.demote-to-helper.frag
│ │ ├── discard.frag
│ │ ├── dispatch-rays-dimensions.rgen
│ │ ├── dispatch-rays-index.rgen
│ │ ├── dot2.frag
│ │ ├── dot3.frag
│ │ ├── dot4.frag
│ │ ├── eval-centroid.frag
│ │ ├── eval-sample-index.frag
│ │ ├── eval-snapped.frag
│ │ ├── exp.frag
│ │ ├── f16-to-f32.frag
│ │ ├── f32-to-f16.frag
│ │ ├── fabs.frag
│ │ ├── firstbithi-16.sm62.frag
│ │ ├── firstbithi-64.frag
│ │ ├── firstbithi.frag
│ │ ├── firstbitlo-16.sm62.frag
│ │ ├── firstbitlo-64.frag
│ │ ├── firstbitlo.frag
│ │ ├── firstbitshi-16.sm62.frag
│ │ ├── firstbitshi-64.frag
│ │ ├── firstbitshi.frag
│ │ ├── flattened_thread_id_in_group.comp
│ │ ├── fma.frag
│ │ ├── fmad-precise.frag
│ │ ├── fmad.frag
│ │ ├── fmax.frag
│ │ ├── fmin.frag
│ │ ├── frc.frag
│ │ ├── get-dimensions-w-only.frag
│ │ ├── get-dimensions-xyz-only.frag
│ │ ├── get-dimensions.bindless.root-constant.frag
│ │ ├── get-dimensions.bindless.root-constant.ssbo.frag
│ │ ├── get-dimensions.frag
│ │ ├── get-dimensions.ssbo.frag
│ │ ├── group_id.comp
│ │ ├── hcos.frag
│ │ ├── hsin.frag
│ │ ├── htan.frag
│ │ ├── imad.frag
│ │ ├── imax.frag
│ │ ├── imin.frag
│ │ ├── instance-id.vert
│ │ ├── is-helper-lane-2.demote-to-helper.sm66.frag
│ │ ├── is-helper-lane-2.sm66.frag
│ │ ├── is-helper-lane.demote-to-helper.sm66.frag
│ │ ├── is-helper-lane.sm66.frag
│ │ ├── isfinite.frag
│ │ ├── isinf.frag
│ │ ├── isnan.frag
│ │ ├── log.frag
│ │ ├── make-double.frag
│ │ ├── msaa-uav.sm67.comp
│ │ ├── msad.comp
│ │ ├── object-ray-direction.rany
│ │ ├── object-ray-origin.rany
│ │ ├── object-to-world-3x4.rany
│ │ ├── object-to-world-4x3.rany
│ │ ├── pack-unpack.ssbo.sm66.comp
│ │ ├── quad-all-any.sm67.comp
│ │ ├── quad-all-any.sm67.quad-maximal-reconvergence.noglsl.comp
│ │ ├── quad-read-at-2d.comp
│ │ ├── quad-read-at-2d.sm66.comp
│ │ ├── quad-read-at.comp
│ │ ├── quad-read-at.frag
│ │ ├── quad-swap.comp
│ │ ├── quad-swap.frag
│ │ ├── raw-gather-offset-sparse.sm67.ssbo.comp
│ │ ├── raw-gather-offset.sm67.ssbo.comp
│ │ ├── raw-gather-sparse.sm67.ssbo.comp
│ │ ├── raw-gather.sm67.ssbo.comp
│ │ ├── ray-query-phi-multi.invalid.sm66.comp
│ │ ├── ray-query-phi-simple.sm66.comp
│ │ ├── ray-query-select-multi.invalid.sm66.comp
│ │ ├── ray-query-select-simple.sm66.comp
│ │ ├── ray-query-store-multi.invalid.sm66.comp
│ │ ├── ray-query-store-simple.sm66.comp
│ │ ├── ray-query.comp
│ │ ├── ray-t-current.rany
│ │ ├── ray-t-min.rany
│ │ ├── render-target-sample-count.frag
│ │ ├── render-target-sample-position.frag
│ │ ├── report-hit.rint
│ │ ├── round-ne.frag
│ │ ├── round-ni.frag
│ │ ├── round-pi.frag
│ │ ├── round-z.frag
│ │ ├── rsqrt.frag
│ │ ├── rt-geometry-index.rany
│ │ ├── rt-hit-kind.rany
│ │ ├── rt-instance-id.rany
│ │ ├── rt-instance-index.rany
│ │ ├── rt-primitive-index.rany
│ │ ├── rt-ray-flags.rany
│ │ ├── sample-bias-feedback.frag
│ │ ├── sample-bias-offset.frag
│ │ ├── sample-bias.frag
│ │ ├── sample-cmp-bias-feedback.frag
│ │ ├── sample-cmp-bias-offset.frag
│ │ ├── sample-cmp-bias.frag
│ │ ├── sample-cmp-feedback.frag
│ │ ├── sample-cmp-grad-offset-feedback.frag
│ │ ├── sample-cmp-grad-offset.frag
│ │ ├── sample-cmp-grad.frag
│ │ ├── sample-cmp-level.sm67.noglsl.frag
│ │ ├── sample-cmp-levelzero.frag
│ │ ├── sample-cmp-offset-levelzero-feedback.frag
│ │ ├── sample-cmp-offset-levelzero.frag
│ │ ├── sample-cmp-offset.frag
│ │ ├── sample-cmp.frag
│ │ ├── sample-grad-offset-dynamic.noglsl.invalid.sm67.frag
│ │ ├── sample-grad-offset-feedback.frag
│ │ ├── sample-grad-offset.frag
│ │ ├── sample-grad.frag
│ │ ├── sample-id.frag
│ │ ├── sample-level-offset-feedback.frag
│ │ ├── sample-level-offset.frag
│ │ ├── sample-level.frag
│ │ ├── sample-offset-dynamic.noglsl.invalid.sm67.frag
│ │ ├── sample-offset.frag
│ │ ├── sample.frag
│ │ ├── saturate.frag
│ │ ├── sin.frag
│ │ ├── sm64-packed-arithmetic.ssbo.comp
│ │ ├── sm64-packed-arithmetic.ssbo.i8dot.noglsl.comp
│ │ ├── sm64-packed-arithmetic.ssbo.mixed-float-dot-product.noglsl.comp
│ │ ├── split-double.frag
│ │ ├── sqrt.frag
│ │ ├── tan.frag
│ │ ├── texture-gather-4offset.frag
│ │ ├── texture-gather-cmp-offset-feedback.frag
│ │ ├── texture-gather-cmp-offset.frag
│ │ ├── texture-gather-cmp.frag
│ │ ├── texture-gather-offset.frag
│ │ ├── texture-gather-signed-feedback.frag
│ │ ├── texture-gather-signed.frag
│ │ ├── texture-gather.frag
│ │ ├── texture-load-feedback.frag
│ │ ├── texture-load-offset-dynamic.sm67.frag
│ │ ├── texture-load-offset.frag
│ │ ├── texture-load-signed.frag
│ │ ├── texture-load.frag
│ │ ├── texture-store-signed.frag
│ │ ├── texture-store.frag
│ │ ├── texture2dms-sample-position.frag
│ │ ├── thread_id.comp
│ │ ├── thread_id_in_group.comp
│ │ ├── trace-ray-flags-2.rgen
│ │ ├── trace-ray-flags.rgen
│ │ ├── trace-ray.rgen
│ │ ├── umad.frag
│ │ ├── umax.frag
│ │ ├── umin.frag
│ │ ├── vertex-id.vert
│ │ ├── wave-active-all-true.comp
│ │ ├── wave-active-all-true.frag
│ │ ├── wave-active-any-true.comp
│ │ ├── wave-active-any-true.frag
│ │ ├── wave-active-ballot-discard.demote-to-helper.frag
│ │ ├── wave-active-ballot-discard.frag
│ │ ├── wave-active-ballot.comp
│ │ ├── wave-active-ballot.demote-to-helper.frag
│ │ ├── wave-active-ballot.frag
│ │ ├── wave-active-count-bits.comp
│ │ ├── wave-active-count-bits.frag
│ │ ├── wave-all-equal.comp
│ │ ├── wave-all-equal.frag
│ │ ├── wave-get-lane-count.comp
│ │ ├── wave-get-lane-index.comp
│ │ ├── wave-is-first-lane.comp
│ │ ├── wave-is-first-lane.frag
│ │ ├── wave-match.comp
│ │ ├── wave-match.frag
│ │ ├── wave-match.partitioned.noglsl.comp
│ │ ├── wave-match.partitioned.noglsl.frag
│ │ ├── wave-multi-prefix-count-bits.comp
│ │ ├── wave-multi-prefix-count-bits.frag
│ │ ├── wave-multi-prefix-op.comp
│ │ ├── wave-multi-prefix-op.frag
│ │ ├── wave-multi-prefix-op.partitioned.noglsl.comp
│ │ ├── wave-multi-prefix-op.partitioned.noglsl.frag
│ │ ├── wave-prefix.comp
│ │ ├── wave-prefix.frag
│ │ ├── wave-read-lane-at-optimizations.comp
│ │ ├── wave-read-lane-at.comp
│ │ ├── wave-read-lane-first.comp
│ │ ├── wave-read-lane-first.frag
│ │ ├── wave-reduce-helpers.sm67.frag
│ │ ├── wave-reduce-helpers.sm67.quad-maximal-reconvergence.frag
│ │ ├── wave-reduce.comp
│ │ ├── wave-reduce.frag
│ │ ├── wave-size.sm66.comp
│ │ ├── world-ray-direction.rany
│ │ ├── world-ray-origin.rany
│ │ ├── world-to-object-3x4.rany
│ │ └── world-to-object-4x3.rany
│ ├── fp16/
│ │ ├── saturate.frag
│ │ ├── saturate.sm60.frag
│ │ └── saturate.sm60.native-fp16.frag
│ ├── heap-robustness/
│ │ ├── misc.bindless.heap-raw-va-cbv.sm66.ssbo.comp
│ │ ├── misc.bindless.heap-robustness.heap-robustness-cbv.sm66.ssbo.comp
│ │ ├── misc.bindless.heap-robustness.sm66.ssbo.comp
│ │ ├── misc.bindless.sm66.ssbo.comp
│ │ └── misc.heap-robustness.bindless.heap-robustness-cbv.heap-raw-va-cbv.sm66.ssbo.comp
│ ├── instrumentation/
│ │ ├── atomics-raw.bindless.bda-instrumentation.ssbo.comp
│ │ ├── atomics-raw.root-descriptor.bda-instrumentation.ssbo.comp
│ │ ├── atomics-structured-counter.bindless.bda-instrumentation.ssbo.comp
│ │ ├── atomics-structured.bindless.bda-instrumentation.ssbo.comp
│ │ ├── atomics-structured.root-descriptor.bda-instrumentation.ssbo.comp
│ │ ├── atomics-typed.bindless.bda-instrumentation.ssbo.comp
│ │ ├── cbv.bindless.bda-instrumentation.comp
│ │ ├── cbv.root-descriptor.bda-instrumentation.comp
│ │ ├── raw.bindless.bda-instrumentation.ssbo.comp
│ │ ├── raw.root-descriptor.bda-instrumentation.ssbo.comp
│ │ ├── structured.bindless.bda-instrumentation.comp
│ │ ├── structured.bindless.bda-instrumentation.ssbo.comp
│ │ ├── structured.root-descriptor.bda-instrumentation.ssbo.comp
│ │ └── typed.bindless.bda-instrumentation.comp
│ ├── llvm-builtin/
│ │ ├── alloca-robustness-cases.extended-robustness.vert
│ │ ├── alloca.frag
│ │ ├── atomic-bin-op.comp
│ │ ├── atomic-compare-exchange.comp
│ │ ├── atomic-compare-exchange.sm66.ssbo.comp
│ │ ├── bool-to-fp.frag
│ │ ├── constant-expression-cast.comp
│ │ ├── constant-expression-gep.comp
│ │ ├── fadd.frag
│ │ ├── fast-mul-div-pair.comp
│ │ ├── fcmp_eq.frag
│ │ ├── fcmp_ge.frag
│ │ ├── fcmp_gt.frag
│ │ ├── fcmp_le.frag
│ │ ├── fcmp_lt.frag
│ │ ├── fcmp_ne.frag
│ │ ├── fdiv.frag
│ │ ├── fmul.frag
│ │ ├── frem.frag
│ │ ├── fsub.frag
│ │ ├── glitched-integer-width.comp
│ │ ├── groupshared.comp
│ │ ├── icmp_eq.frag
│ │ ├── icmp_ne.frag
│ │ ├── icmp_sge.frag
│ │ ├── icmp_sgt.frag
│ │ ├── icmp_sle.frag
│ │ ├── icmp_slt.frag
│ │ ├── icmp_uge.frag
│ │ ├── icmp_ugt.frag
│ │ ├── icmp_ule.frag
│ │ ├── icmp_ult.frag
│ │ ├── logical-and.frag
│ │ ├── logical-equal.frag
│ │ ├── logical-not-equal.frag
│ │ ├── logical-or.frag
│ │ ├── lut.frag
│ │ ├── min16-phi.sm60.comp
│ │ ├── precise_math.frag
│ │ └── zext-bool.frag
│ ├── memory-model/
│ │ ├── uav-coherent-promotion.bindless.ssbo.comp
│ │ ├── uav-coherent-promotion.root-descriptor.ssbo.comp
│ │ ├── uav-coherent-promotion.sm66.bindless.ssbo.comp
│ │ ├── uav-coherent-promotion.sm66.ssbo.comp
│ │ ├── uav-coherent-promotion.ssbo.comp
│ │ ├── uav-coherent.root-descriptor.ssbo.comp
│ │ ├── uav-coherent.sm66.ssbo.comp
│ │ └── uav-coherent.ssbo.comp
│ ├── nvapi/
│ │ ├── bringup.nvapi.ssbo.rgen
│ │ ├── get-special-global-timer.nvapi.ssbo.rgen
│ │ ├── hit-object.local-root-signature.noglsl.nvapi.ssbo.rgen
│ │ ├── ray-query-cluster-id.nvapi.comp
│ │ ├── rt-cluster-id.nvapi.rany
│ │ └── shuffle.nvapi.ssbo.comp
│ ├── opts/
│ │ ├── fp16-fp32-fp16-1.ssbo.comp
│ │ ├── sabs.frag
│ │ ├── sneg.frag
│ │ ├── wave-read-lane-first-heap.sm66.comp
│ │ ├── wave-read-lane-first.bindless.local-root-signature.rmiss
│ │ ├── wave-read-lane-first.comp
│ │ ├── wave-read-lane-first.no-legacy-cbuf-layout.comp
│ │ ├── wave-read-lane-first.no-legacy-cbuf-layout.sm60.comp
│ │ ├── wave-read-lane-first.sm60.comp
│ │ ├── wave-read-lane-first.sm66.comp
│ │ ├── wave-read-lane-first.ssbo.comp
│ │ ├── wave-read-lane-first.ssbo.rgen
│ │ ├── wave-read-lane-first.ssbo.sm60.comp
│ │ ├── wave-read-lane-first.ssbo.sm66.comp
│ │ └── wave-read-lane-first.ssbo.sm66.rgen
│ ├── raw-access/
│ │ ├── bab-double1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-double2.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-double3.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-double4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float2.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float3.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float4x4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float2.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float3.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float4x4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-half1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-min16float1.raw-access-chains.noglsl.ssbo.sm60.comp
│ │ ├── structured-min16float1.raw-access-chains.noglsl.ssbo.sm60.native-fp16.comp
│ │ ├── structured-min16uint1.raw-access-chains.noglsl.ssbo.sm60.comp
│ │ ├── structured-min16uint1.raw-access-chains.noglsl.ssbo.sm60.native-fp16.comp
│ │ ├── structured-uint1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-uint2.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-uint3.raw-access-chains.noglsl.ssbo.comp
│ │ └── structured-uint4.raw-access-chains.noglsl.ssbo.comp
│ ├── resources/
│ │ ├── acceleration-structure.bindless.rgen
│ │ ├── acceleration-structure.bindless.ssbo-rtas.local-root-signature.raw-va-stride-offset.rgen
│ │ ├── acceleration-structure.bindless.ssbo-rtas.local-root-signature.rgen
│ │ ├── acceleration-structure.local-root-signature.root-descriptor.rgen
│ │ ├── basic.input-attachment.frag
│ │ ├── buffer-16bit.ssbo.bindless.comp
│ │ ├── buffer-16bit.ssbo.bindless.ssbo-align.comp
│ │ ├── buffer-16bit.ssbo.comp
│ │ ├── buffer-64bit.ssbo.bindless.ssbo-align.comp
│ │ ├── buffer-64bit.ssbo.comp
│ │ ├── buffer-alignment-fixup.bindless.root-constant.offset-layout.typed-buffer-offset.comp
│ │ ├── buffer-alignment-fixup.ssbo.ssbo-align.bindless.root-constant.comp
│ │ ├── buffer-alignment-fixup.ssbo.ssbo-align.bindless.root-constant.offset-layout.typed-buffer-offset.comp
│ │ ├── cbuf.root-constant.min16float.sm60.frag
│ │ ├── cbuf.root-constant.min16float.sm60.native-fp16.frag
│ │ ├── cbuf.root-constant.min16int.sm60.frag
│ │ ├── cbuf.root-constant.min16int.sm60.native-fp16.frag
│ │ ├── cbv-array-nonuniform.frag
│ │ ├── cbv-array.frag
│ │ ├── cbv-dynamic.no-legacy-cbuf-layout.local-root-signature.rmiss
│ │ ├── cbv-indexing.frag
│ │ ├── cbv-indexing.sm66.frag
│ │ ├── cbv-legacy-fp16-fp64.frag
│ │ ├── cbv-legacy-fp16-fp64.root-descriptor.frag
│ │ ├── cbv-legacy-fp16-fp64.root-descriptor.sm60.frag
│ │ ├── cbv-legacy-fp16-fp64.root-descriptor.sm60.native-fp16.frag
│ │ ├── cbv-legacy-fp16-fp64.sm60.frag
│ │ ├── cbv-legacy-fp16-fp64.sm60.native-fp16.frag
│ │ ├── cbv.bindless.root-constant.cbv-as-ssbo.frag
│ │ ├── cbv.bindless.root-constant.frag
│ │ ├── cbv.frag
│ │ ├── cbv.no-legacy-cbuf-layout.bindless.frag
│ │ ├── cbv.no-legacy-cbuf-layout.index-divider.frag
│ │ ├── cbv.no-legacy-cbuf-layout.local-root-signature.rmiss
│ │ ├── cbv.no-legacy-cbuf-layout.native-fp16.sm60.frag
│ │ ├── cbv.no-legacy-cbuf-layout.root-constant.frag
│ │ ├── cbv.root-constant.frag
│ │ ├── cbv.root-descriptor.no-legacy-cbuf-layout.frag
│ │ ├── combined-image-sampler-reuse.frag
│ │ ├── dynamic-root-constant.root-constant.bindless.root-descriptor.comp
│ │ ├── min16-alloca-groupshared.sm60.comp
│ │ ├── min16float-ssbo-dxr.ssbo.rgen
│ │ ├── raw-buffer-addressing.comp
│ │ ├── raw-buffer-addressing.ssbo.comp
│ │ ├── root-bda.root-descriptor.comp
│ │ ├── root-bda.root-descriptor.sm60.comp
│ │ ├── root-constant-with-bda.root-descriptor.root-constant.comp
│ │ ├── rt-resources.bindless.local-root-signature.rmiss
│ │ ├── rt-resources.bindless.rmiss
│ │ ├── rt-resources.rmiss
│ │ ├── sampler-array.frag
│ │ ├── sampler-indexing.frag
│ │ ├── sampler-indexing.sm66.frag
│ │ ├── sampler.bindless.root-constant.frag
│ │ ├── sm66/
│ │ │ ├── atomics-64bit-groupshared.ssbo.sm66.comp
│ │ │ ├── atomics-64bit.root-descriptor.sm66.comp
│ │ │ ├── atomics-64bit.ssbo.sm66.comp
│ │ │ ├── atomics-component-alias.sm66.comp
│ │ │ ├── atomics-typed-64bit-heap.sm66.comp
│ │ │ ├── atomics-typed-64bit.bindless.sm66.comp
│ │ │ ├── atomics-typed-64bit.sm66.comp
│ │ │ ├── binding-range-selection.bindless.sm66.comp
│ │ │ ├── binding-range-selection.sm66.comp
│ │ │ ├── buffer-64bit-double.ssbo.sm66.comp
│ │ │ ├── buffer-64bit.ssbo.sm66.comp
│ │ │ ├── buffer-64bit.ssbo.ssbo-align.sm66.comp
│ │ │ ├── cbuffer-heap.sm66.frag
│ │ │ ├── cbv.no-legacy-cbuf-layout.bindless.sm66.frag
│ │ │ ├── cbv.no-legacy-cbuf-layout.sm66.frag
│ │ │ ├── raw-buffer-heap.sm66.frag
│ │ │ ├── raw-buffer-heap.ssbo.sm66.frag
│ │ │ ├── raw-buffer-heap.typed-buffer-offset.sm66.frag
│ │ │ ├── raw-buffers-binding.ssbo.bindless.sm66.frag
│ │ │ ├── raw-buffers-binding.ssbo.bindless.ssbo-align.sm66.frag
│ │ │ ├── raw-buffers-binding.ssbo.sm66.frag
│ │ │ ├── raygen-heap.sm66.rgen
│ │ │ ├── raygen-heap.ssbo-rtas.raw-va-stride-offset.sm66.rgen
│ │ │ ├── raygen-heap.ssbo-rtas.sm66.rgen
│ │ │ ├── raygen.sm66.rgen
│ │ │ ├── raygen.ssbo-rtas.bindless.raw-va-stride-offset.sm66.rgen
│ │ │ ├── raygen.ssbo-rtas.bindless.sm66.rgen
│ │ │ ├── rw-typed-binding.sm66.frag
│ │ │ ├── rw-typed-heap.sm66.frag
│ │ │ ├── sampled-types-binding.sm66.frag
│ │ │ ├── sampled-types.sm66.frag
│ │ │ ├── sampler-binding.sm66.frag
│ │ │ ├── sampler-heap.sm66.frag
│ │ │ ├── structured-16bit-heap.ssbo.sm66.frag
│ │ │ ├── structured-16bit-heap.ssbo.ssbo-align.sm66.frag
│ │ │ ├── structured-buffer-heap.sm66.frag
│ │ │ ├── structured-buffer-heap.ssbo.sm66.frag
│ │ │ ├── structured-buffer-heap.ssbo.ssbo-align.sm66.frag
│ │ │ └── structured-buffer-heap.typed-buffer-offset.sm66.frag
│ │ ├── srv-array-raw-buffer-nonuniform.frag
│ │ ├── srv-array-raw-buffer.frag
│ │ ├── srv-array-structured-buffer-nonuniform.frag
│ │ ├── srv-array-structured-buffer.frag
│ │ ├── srv-array-texture-nonuniform.frag
│ │ ├── srv-array-texture.frag
│ │ ├── srv-array-typed-buffer-nonuniform.frag
│ │ ├── srv-array-typed-buffer.frag
│ │ ├── srv-indexing.frag
│ │ ├── srv-indexing.sm66.frag
│ │ ├── srv-raw-buffer.bindless.root-constant.frag
│ │ ├── srv-raw-buffer.bindless.root-constant.ssbo.frag
│ │ ├── srv-raw-buffer.ssbo.frag
│ │ ├── srv-structured-buffer.bindless.root-constant.frag
│ │ ├── srv-structured-buffer.bindless.root-constant.ssbo.frag
│ │ ├── srv-structured-buffer.ssbo.frag
│ │ ├── srv-texture.bindless.root-constant.frag
│ │ ├── srv-texture.bindless.root-constant.inline-ubo.frag
│ │ ├── srv-typed-buffer.bindless.root-constant.frag
│ │ ├── srv-uav-raw.typed-buffer-offset.comp
│ │ ├── srv-uav.typed-buffer-offset.comp
│ │ ├── ssbo-minprecision.sm60.native-fp16.frag
│ │ ├── ssbo-minprecision.sm60.ssbo.frag
│ │ ├── ssbo-minprecision.sm60.ssbo.native-fp16.frag
│ │ ├── ssbo-minprecision.sm60.ssbo.native-fp16.root-descriptor.frag
│ │ ├── ssbo-minprecision.sm60.ssbo.root-descriptor.frag
│ │ ├── subobject-parsing.rgen
│ │ ├── typed-resources-16bit-sparse.frag
│ │ ├── typed-resources-16bit.bindless.frag
│ │ ├── typed-resources-16bit.frag
│ │ ├── typed-resources-16bit.sm60.bindless.frag
│ │ ├── typed-resources-16bit.sm60.frag
│ │ ├── typed-resources-16bit.sm60.native-fp16.bindless.frag
│ │ ├── typed-resources-16bit.sm60.native-fp16.frag
│ │ ├── uav-array-raw-buffer-nonuniform.frag
│ │ ├── uav-array-raw-buffer.frag
│ │ ├── uav-array-structured-buffer-nonuniform.frag
│ │ ├── uav-array-structured-buffer-nonuniform.ssbo.bindless.root-constant.frag
│ │ ├── uav-array-structured-buffer-nonuniform.ssbo.frag
│ │ ├── uav-array-structured-buffer.frag
│ │ ├── uav-array-texture-nonuniform.frag
│ │ ├── uav-array-texture.frag
│ │ ├── uav-array-typed-buffer-nonuniform.frag
│ │ ├── uav-array-typed-buffer.frag
│ │ ├── uav-counter-array.ssbo.frag
│ │ ├── uav-counter-array.ssbo.sm66.frag
│ │ ├── uav-counter-array.ssbo.sm66.uav-counter-ssbo.frag
│ │ ├── uav-counter-array.ssbo.uav-counter-ssbo.frag
│ │ ├── uav-counter-heap.sm66.bindless.ssbo.frag
│ │ ├── uav-counter-heap.sm66.uav-counter-ssbo.bindless.ssbo.frag
│ │ ├── uav-counter-heap.sm66.uav-counter-texel-buffer.bindless.ssbo.frag
│ │ ├── uav-counter.bindless.nobda.root-constant.comp
│ │ ├── uav-counter.bindless.nobda.root-constant.raw-va-stride-offset.comp
│ │ ├── uav-counter.bindless.root-constant.comp
│ │ ├── uav-counter.bindless.root-constant.raw-va-stride-offset.comp
│ │ ├── uav-counter.bindless.root-constant.raw-va-stride-offset.heap-raw-va-cbv.comp
│ │ ├── uav-counter.bindless.root-constant.uav-counter-ssbo.comp
│ │ ├── uav-counter.ssbo.comp
│ │ ├── uav-counter.ssbo.raw-va-stride-offset.comp
│ │ ├── uav-counter.ssbo.uav-counter-ssbo.comp
│ │ ├── uav-indexing.frag
│ │ ├── uav-indexing.sm66.frag
│ │ ├── uav-raw-buffer.bindless.root-constant.frag
│ │ ├── uav-raw-buffer.ssbo.frag
│ │ ├── uav-structured-buffer.bindless.root-constant.frag
│ │ ├── uav-typed-buffer.bindless.root-constant.frag
│ │ └── uav-typed.typed-uav-without-format.comp
│ ├── rov/
│ │ ├── rov-bab.bindless.frag
│ │ ├── rov-bab.frag
│ │ ├── rov-bab.ssbo.bindless.frag
│ │ ├── rov-bab.ssbo.frag
│ │ ├── rov-bab.ssbo.root-descriptor.frag
│ │ ├── rov-branch-early-return.frag
│ │ ├── rov-branch.frag
│ │ ├── rov-buffer.frag
│ │ ├── rov-inloop-2.frag
│ │ ├── rov-inloop.frag
│ │ ├── rov-per-sample.sm66.frag
│ │ ├── rov-postloop.frag
│ │ ├── rov-structured.bindless.frag
│ │ ├── rov-structured.frag
│ │ ├── rov-structured.ssbo.bindless.frag
│ │ ├── rov-structured.ssbo.frag
│ │ ├── rov-structured.ssbo.root-descriptor.frag
│ │ ├── rov-tex1d.bindless.frag
│ │ ├── rov-tex1d.frag
│ │ ├── rov-tex1darray.bindless.frag
│ │ ├── rov-tex1darray.frag
│ │ ├── rov-tex2d.bindless.frag
│ │ ├── rov-tex2d.frag
│ │ ├── rov-tex2darray.bindless.frag
│ │ ├── rov-tex2darray.frag
│ │ ├── rov-tex3d.bindless.frag
│ │ ├── rov-tex3d.frag
│ │ ├── rov-undef.frag
│ │ └── rov.sm66.frag
│ ├── sampler-feedback/
│ │ ├── sampler-feedback.frag
│ │ └── sampler-feedback.sm66.frag
│ ├── semantics/
│ │ ├── clip-cull-distance.vert
│ │ ├── clip-cull.frag
│ │ ├── clip-distance-cols.frag
│ │ ├── clip-distance-cols.vert
│ │ ├── clip-distance-flatten.frag
│ │ ├── clip-distance-flatten.vert
│ │ ├── clip-distance-rows.frag
│ │ ├── clip-distance-rows.vert
│ │ ├── clip-distance-single.vert
│ │ ├── coverage.frag
│ │ ├── depth-greater-equal.frag
│ │ ├── depth-less-equal.frag
│ │ ├── depth.frag
│ │ ├── early-depth-stencil.frag
│ │ ├── inner-coverage.noglsl.frag
│ │ ├── is-front-face.frag
│ │ ├── position-short.frag
│ │ ├── position-short.vert
│ │ ├── position.frag
│ │ ├── primitive-id.frag
│ │ ├── primitive-id.geom
│ │ ├── render-target-array-index.frag
│ │ ├── render-target-array-index.geom
│ │ ├── sample-rate-pos.frag
│ │ ├── stencil-ref.frag
│ │ ├── sv-shading-rate.noglsl.frag
│ │ ├── sv-shading-rate.noglsl.vert
│ │ ├── view-id.frag
│ │ ├── view-id.vert
│ │ ├── viewport-array-index.frag
│ │ └── viewport-array-index.geom
│ ├── stages/
│ │ ├── boolean-io.vert
│ │ ├── callable-chain.rcall
│ │ ├── callable.rcall
│ │ ├── closesthit.rclosest
│ │ ├── domain-clip-cull.tese
│ │ ├── domain-patch-input-integer-io.tese
│ │ ├── domain.tese
│ │ ├── extra_output.dual-source-blending.frag
│ │ ├── extra_output_reordered.dual-source-blending.frag
│ │ ├── geometry-clip-cull.geom
│ │ ├── geometry-input-line.geom
│ │ ├── geometry-input-lineadj.geom
│ │ ├── geometry-input-point.geom
│ │ ├── geometry-input-triangle.geom
│ │ ├── geometry-input-triangleadj.geom
│ │ ├── geometry-instancing.geom
│ │ ├── geometry-output-line.geom
│ │ ├── geometry-output-point.geom
│ │ ├── geometry-streams.geom
│ │ ├── hull-arrays.tesc
│ │ ├── hull-clip-cull.tesc
│ │ ├── hull-patch-output-integer-io.tesc
│ │ ├── hull-single-cp.tesc
│ │ ├── hull.tesc
│ │ ├── mesh-basic-line.mesh
│ │ ├── mesh-basic.mesh
│ │ ├── mesh-clip-cull.mesh
│ │ ├── raygen-complex-storage-class.rgen
│ │ ├── raygen-skip-inactive-resources.rgen
│ │ ├── raygen.rgen
│ │ ├── raymiss-chain.rmiss
│ │ ├── raymiss.rmiss
│ │ ├── simple.dual-source-blending.frag
│ │ ├── simple.invariant.vert
│ │ ├── stage-input-output.16bit-io.frag
│ │ ├── stage-input-output.frag
│ │ ├── stream-out.stream-out.vert
│ │ ├── swizzle.rt-swizzle.frag
│ │ ├── task-basic.task
│ │ ├── vertex-array-input.vert
│ │ ├── vertex-array-output.vert
│ │ └── vertex-input-remapping.vert
│ ├── vectorization/
│ │ ├── copy-byte-address.ssbo.comp
│ │ ├── copy-composite-2.ssbo.comp
│ │ ├── copy-composite.ssbo.comp
│ │ ├── copy-composite.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-double2.ssbo.comp
│ │ ├── copy-double2.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-double3.ssbo.comp
│ │ ├── copy-double3.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-double4.ssbo.comp
│ │ ├── copy-float2.ssbo.comp
│ │ ├── copy-float2.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-float2x2.ssbo.comp
│ │ ├── copy-float3.ssbo.comp
│ │ ├── copy-float3.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-float4x4.ssbo.comp
│ │ ├── copy-half2.ssbo.comp
│ │ ├── copy-half2.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-half3.ssbo.comp
│ │ ├── copy-half3.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-half4.ssbo.comp
│ │ └── copy-half4.ssbo.ssbo-align.bindless.comp
│ ├── view-instancing/
│ │ ├── geom/
│ │ │ ├── basic.view-instancing.last-pre-raster.geom
│ │ │ ├── basic.view-instancing.last-pre-raster.view-instance-mask.geom
│ │ │ ├── basic.view-instancing.view-instancing-multiview.last-pre-raster.geom
│ │ │ ├── basic.view-instancing.view-instancing-multiview.view-instancing-viewport-offset.last-pre-raster.geom
│ │ │ └── basic.view-instancing.view-instancing-viewport-offset.last-pre-raster.geom
│ │ ├── mesh/
│ │ │ ├── basic-export-viewport-layer.view-instancing.last-pre-raster.mesh
│ │ │ ├── basic-export-viewport-layer.view-instancing.last-pre-raster.view-instancing-viewport-offset.mesh
│ │ │ ├── basic-few-thread.view-instancing.last-pre-raster.mesh
│ │ │ ├── basic-many-thread.view-instancing.last-pre-raster.mesh
│ │ │ ├── basic.view-instancing.last-pre-raster.mesh
│ │ │ ├── basic.view-instancing.last-pre-raster.view-instance-mask.mesh
│ │ │ ├── basic.view-instancing.last-pre-raster.view-instancing-viewport-offset.mesh
│ │ │ └── basic.view-instancing.mesh
│ │ ├── tesc/
│ │ │ ├── basic.view-instancing.tesc
│ │ │ └── basic.view-instancing.view-instancing-multiview.tesc
│ │ ├── tese/
│ │ │ ├── domain-export-layer-viewport.view-instancing.view-instancing-multiview.last-pre-raster.tese
│ │ │ ├── domain-export-layer-viewport.view-instancing.view-instancing-multiview.tese
│ │ │ ├── domain.view-instancing.last-pre-raster.tese
│ │ │ ├── domain.view-instancing.tese
│ │ │ ├── domain.view-instancing.view-instancing-multiview.last-pre-raster.tese
│ │ │ ├── domain.view-instancing.view-instancing-multiview.tese
│ │ │ ├── domain.view-instancing.view-instancing-viewport-offset.last-pre-raster.tese
│ │ │ └── domain.view-instancing.view-instancing-viewport-offset.tese
│ │ └── vert/
│ │ ├── basic.view-instancing.export-layer-viewport.last-pre-raster.vert
│ │ ├── basic.view-instancing.export-layer-viewport.vert
│ │ ├── basic.view-instancing.export-layer-viewport.view-instancing-multiview.vert
│ │ ├── basic.view-instancing.export-layer-viewport.view-instancing-viewport-offset.vert
│ │ ├── basic.view-instancing.export-layer.last-pre-raster.vert
│ │ ├── basic.view-instancing.export-layer.vert
│ │ ├── basic.view-instancing.export-layer.view-instancing-multiview.vert
│ │ ├── basic.view-instancing.export-layer.view-instancing-viewport-offset.vert
│ │ ├── basic.view-instancing.export-viewport.last-pre-raster.vert
│ │ ├── basic.view-instancing.export-viewport.vert
│ │ ├── basic.view-instancing.export-viewport.view-instancing-multiview.vert
│ │ ├── basic.view-instancing.export-viewport.view-instancing-viewport-offset.vert
│ │ ├── basic.view-instancing.last-pre-raster.vert
│ │ ├── basic.view-instancing.vert
│ │ ├── basic.view-instancing.view-instance-mask.last-pre-raster.vert
│ │ ├── basic.view-instancing.view-instance-mask.vert
│ │ ├── basic.view-instancing.view-instancing-multiview.vert
│ │ └── basic.view-instancing.view-instancing-viewport-offset.vert
│ └── vkmm/
│ ├── coopmat.sm66.ssbo.vkmm.comp
│ ├── cross_group_sharing.vkmm.node.inline-ubo.comp
│ ├── descriptor_qa.bindless.descriptor-qa.vkmm.comp
│ ├── groupshared.vkmm.comp
│ ├── hull.vkmm.tesc
│ ├── image-load-store.vkmm.comp
│ ├── image-load-store.vkmm.sm66.comp
│ ├── memory-model/
│ │ ├── uav-coherent-promotion.bindless.ssbo.vkmm.comp
│ │ ├── uav-coherent-promotion.root-descriptor.ssbo.vkmm.comp
│ │ ├── uav-coherent-promotion.sm66.bindless.ssbo.vkmm.comp
│ │ ├── uav-coherent-promotion.sm66.ssbo.vkmm.comp
│ │ ├── uav-coherent-promotion.ssbo.vkmm.comp
│ │ ├── uav-coherent.root-descriptor.ssbo.vkmm.comp
│ │ ├── uav-coherent.sm66.ssbo.vkmm.comp
│ │ └── uav-coherent.ssbo.vkmm.comp
│ ├── report-hit.vkmm.rint
│ ├── rov-structured.vkmm.frag
│ └── rov-tex2d.vkmm.frag
├── reference-dxbc/
│ ├── test_arithmetic_bool.asm
│ ├── test_arithmetic_bool.glsl
│ ├── test_arithmetic_fp16_compare.asm
│ ├── test_arithmetic_fp16_compare.glsl
│ ├── test_arithmetic_fp16_packing.asm
│ ├── test_arithmetic_fp16_packing.glsl
│ ├── test_arithmetic_fp16_packing_legacy.asm
│ ├── test_arithmetic_fp16_packing_legacy.glsl
│ ├── test_arithmetic_fp16_scalar.asm
│ ├── test_arithmetic_fp16_scalar.glsl
│ ├── test_arithmetic_fp16_vector.asm
│ ├── test_arithmetic_fp16_vector.glsl
│ ├── test_arithmetic_fp32.asm
│ ├── test_arithmetic_fp32.glsl
│ ├── test_arithmetic_fp32_compare.asm
│ ├── test_arithmetic_fp32_compare.glsl
│ ├── test_arithmetic_fp32_precise.asm
│ ├── test_arithmetic_fp32_precise.glsl
│ ├── test_arithmetic_fp32_special.asm
│ ├── test_arithmetic_fp32_special.glsl
│ ├── test_arithmetic_fp64.asm
│ ├── test_arithmetic_fp64.glsl
│ ├── test_arithmetic_fp64_compare.asm
│ ├── test_arithmetic_fp64_compare.glsl
│ ├── test_arithmetic_fp64_packing.asm
│ ├── test_arithmetic_fp64_packing.glsl
│ ├── test_arithmetic_int_extended.asm
│ ├── test_arithmetic_int_extended.glsl
│ ├── test_arithmetic_sint16_compare.asm
│ ├── test_arithmetic_sint16_compare.glsl
│ ├── test_arithmetic_sint16_scalar.asm
│ ├── test_arithmetic_sint16_scalar.glsl
│ ├── test_arithmetic_sint16_vector.asm
│ ├── test_arithmetic_sint16_vector.glsl
│ ├── test_arithmetic_sint32.asm
│ ├── test_arithmetic_sint32.glsl
│ ├── test_arithmetic_sint32_compare.asm
│ ├── test_arithmetic_sint32_compare.glsl
│ ├── test_arithmetic_uint16_compare.asm
│ ├── test_arithmetic_uint16_compare.glsl
│ ├── test_arithmetic_uint16_scalar.asm
│ ├── test_arithmetic_uint16_scalar.glsl
│ ├── test_arithmetic_uint16_vector.asm
│ ├── test_arithmetic_uint16_vector.glsl
│ ├── test_arithmetic_uint32.asm
│ ├── test_arithmetic_uint32.glsl
│ ├── test_arithmetic_uint32_compare.asm
│ ├── test_arithmetic_uint32_compare.glsl
│ ├── test_cfg_if.asm
│ ├── test_cfg_if.glsl
│ ├── test_cfg_if_else.asm
│ ├── test_cfg_if_else.glsl
│ ├── test_cfg_loop_infinite.asm
│ ├── test_cfg_loop_infinite.glsl
│ ├── test_cfg_loop_once.asm
│ ├── test_cfg_loop_once.glsl
│ ├── test_cfg_switch_complex.asm
│ ├── test_cfg_switch_complex.glsl
│ ├── test_cfg_switch_simple.asm
│ ├── test_cfg_switch_simple.glsl
│ ├── test_convert_f_to_f.asm
│ ├── test_convert_f_to_f.glsl
│ ├── test_convert_f_to_i.asm
│ ├── test_convert_f_to_i.glsl
│ ├── test_convert_i_to_f.asm
│ ├── test_convert_i_to_f.glsl
│ ├── test_convert_i_to_i.asm
│ ├── test_convert_i_to_i.glsl
│ ├── test_io_cs_builtins.asm
│ ├── test_io_cs_builtins.glsl
│ ├── test_io_ds_isoline.asm
│ ├── test_io_ds_isoline.glsl
│ ├── test_io_ds_quad.asm
│ ├── test_io_ds_quad.glsl
│ ├── test_io_ds_triangle.asm
│ ├── test_io_ds_triangle.glsl
│ ├── test_io_gs_basic_line.asm
│ ├── test_io_gs_basic_line.glsl
│ ├── test_io_gs_basic_line_adj.asm
│ ├── test_io_gs_basic_line_adj.glsl
│ ├── test_io_gs_basic_point.asm
│ ├── test_io_gs_basic_point.glsl
│ ├── test_io_gs_basic_triangle.asm
│ ├── test_io_gs_basic_triangle.glsl
│ ├── test_io_gs_basic_triangle_adj.asm
│ ├── test_io_gs_basic_triangle_adj.glsl
│ ├── test_io_gs_instanced.asm
│ ├── test_io_gs_instanced.glsl
│ ├── test_io_gs_multi_stream_xfb_raster_0.asm
│ ├── test_io_gs_multi_stream_xfb_raster_0.glsl
│ ├── test_io_gs_multi_stream_xfb_raster_1.asm
│ ├── test_io_gs_multi_stream_xfb_raster_1.glsl
│ ├── test_io_gs_xfb.asm
│ ├── test_io_gs_xfb.glsl
│ ├── test_io_hs_line.asm
│ ├── test_io_hs_line.glsl
│ ├── test_io_hs_point.asm
│ ├── test_io_hs_point.glsl
│ ├── test_io_hs_triangle_ccw.asm
│ ├── test_io_hs_triangle_ccw.glsl
│ ├── test_io_hs_triangle_cw.asm
│ ├── test_io_hs_triangle_cw.glsl
│ ├── test_io_ps_builtins.asm
│ ├── test_io_ps_builtins.glsl
│ ├── test_io_ps_export_depth.asm
│ ├── test_io_ps_export_depth.glsl
│ ├── test_io_ps_export_depth_greater.asm
│ ├── test_io_ps_export_depth_greater.glsl
│ ├── test_io_ps_export_depth_less.asm
│ ├── test_io_ps_export_depth_less.glsl
│ ├── test_io_ps_export_stencil.asm
│ ├── test_io_ps_export_stencil.glsl
│ ├── test_io_ps_fully_covered.asm
│ ├── test_io_ps_fully_covered.glsl
│ ├── test_io_ps_interpolate_centroid.asm
│ ├── test_io_ps_interpolate_centroid.glsl
│ ├── test_io_ps_interpolate_offset.asm
│ ├── test_io_ps_interpolate_offset.glsl
│ ├── test_io_ps_interpolate_sample.asm
│ ├── test_io_ps_interpolate_sample.glsl
│ ├── test_io_vs.asm
│ ├── test_io_vs.glsl
│ ├── test_io_vs_clip_cull_dist.asm
│ ├── test_io_vs_clip_cull_dist.glsl
│ ├── test_io_vs_clip_dist.asm
│ ├── test_io_vs_clip_dist.glsl
│ ├── test_io_vs_cull_dist.asm
│ ├── test_io_vs_cull_dist.glsl
│ ├── test_io_vs_instance_id.asm
│ ├── test_io_vs_instance_id.glsl
│ ├── test_io_vs_layer.asm
│ ├── test_io_vs_layer.glsl
│ ├── test_io_vs_vertex_id.asm
│ ├── test_io_vs_vertex_id.glsl
│ ├── test_io_vs_viewport.asm
│ ├── test_io_vs_viewport.glsl
│ ├── test_misc_constant_load.asm
│ ├── test_misc_constant_load.glsl
│ ├── test_misc_function.asm
│ ├── test_misc_function.glsl
│ ├── test_misc_function_with_args.asm
│ ├── test_misc_function_with_args.glsl
│ ├── test_misc_function_with_return.asm
│ ├── test_misc_function_with_return.glsl
│ ├── test_misc_function_with_undef.asm
│ ├── test_misc_function_with_undef.glsl
│ ├── test_misc_lds.asm
│ ├── test_misc_lds.glsl
│ ├── test_misc_lds_atomic.asm
│ ├── test_misc_lds_atomic.glsl
│ ├── test_misc_ps_demote.asm
│ ├── test_misc_ps_demote.glsl
│ ├── test_misc_ps_early_z.asm
│ ├── test_misc_ps_early_z.glsl
│ ├── test_misc_scratch.asm
│ ├── test_misc_scratch.glsl
│ ├── test_resource_rov.asm
│ ├── test_resource_rov.glsl
│ ├── test_resource_srv_buffer_load_sparse_feedback.asm
│ ├── test_resource_srv_buffer_load_sparse_feedback.glsl
│ ├── test_resource_srv_image_1d_array_load.asm
│ ├── test_resource_srv_image_1d_array_load.glsl
│ ├── test_resource_srv_image_1d_array_query.asm
│ ├── test_resource_srv_image_1d_array_query.glsl
│ ├── test_resource_srv_image_1d_array_sample.asm
│ ├── test_resource_srv_image_1d_array_sample.glsl
│ ├── test_resource_srv_image_1d_load.asm
│ ├── test_resource_srv_image_1d_load.glsl
│ ├── test_resource_srv_image_1d_query.asm
│ ├── test_resource_srv_image_1d_query.glsl
│ ├── test_resource_srv_image_1d_sample.asm
│ ├── test_resource_srv_image_1d_sample.glsl
│ ├── test_resource_srv_image_2d_array_gather.asm
│ ├── test_resource_srv_image_2d_array_gather.glsl
│ ├── test_resource_srv_image_2d_array_gather_depth.asm
│ ├── test_resource_srv_image_2d_array_gather_depth.glsl
│ ├── test_resource_srv_image_2d_array_load.asm
│ ├── test_resource_srv_image_2d_array_load.glsl
│ ├── test_resource_srv_image_2d_array_query.asm
│ ├── test_resource_srv_image_2d_array_query.glsl
│ ├── test_resource_srv_image_2d_array_sample.asm
│ ├── test_resource_srv_image_2d_array_sample.glsl
│ ├── test_resource_srv_image_2d_array_sample_depth.asm
│ ├── test_resource_srv_image_2d_array_sample_depth.glsl
│ ├── test_resource_srv_image_2d_gather.asm
│ ├── test_resource_srv_image_2d_gather.glsl
│ ├── test_resource_srv_image_2d_gather_depth.asm
│ ├── test_resource_srv_image_2d_gather_depth.glsl
│ ├── test_resource_srv_image_2d_load.asm
│ ├── test_resource_srv_image_2d_load.glsl
│ ├── test_resource_srv_image_2d_ms_array_load.asm
│ ├── test_resource_srv_image_2d_ms_array_load.glsl
│ ├── test_resource_srv_image_2d_ms_array_query.asm
│ ├── test_resource_srv_image_2d_ms_array_query.glsl
│ ├── test_resource_srv_image_2d_ms_load.asm
│ ├── test_resource_srv_image_2d_ms_load.glsl
│ ├── test_resource_srv_image_2d_ms_query.asm
│ ├── test_resource_srv_image_2d_ms_query.glsl
│ ├── test_resource_srv_image_2d_query.asm
│ ├── test_resource_srv_image_2d_query.glsl
│ ├── test_resource_srv_image_2d_sample.asm
│ ├── test_resource_srv_image_2d_sample.glsl
│ ├── test_resource_srv_image_2d_sample_depth.asm
│ ├── test_resource_srv_image_2d_sample_depth.glsl
│ ├── test_resource_srv_image_3d_load.asm
│ ├── test_resource_srv_image_3d_load.glsl
│ ├── test_resource_srv_image_3d_query.asm
│ ├── test_resource_srv_image_3d_query.glsl
│ ├── test_resource_srv_image_3d_sample.asm
│ ├── test_resource_srv_image_3d_sample.glsl
│ ├── test_resource_srv_image_cube_array_gather.asm
│ ├── test_resource_srv_image_cube_array_gather.glsl
│ ├── test_resource_srv_image_cube_array_gather_depth.asm
│ ├── test_resource_srv_image_cube_array_gather_depth.glsl
│ ├── test_resource_srv_image_cube_array_query.asm
│ ├── test_resource_srv_image_cube_array_query.glsl
│ ├── test_resource_srv_image_cube_array_sample.asm
│ ├── test_resource_srv_image_cube_array_sample.glsl
│ ├── test_resource_srv_image_cube_array_sample_depth.asm
│ ├── test_resource_srv_image_cube_array_sample_depth.glsl
│ ├── test_resource_srv_image_cube_gather.asm
│ ├── test_resource_srv_image_cube_gather.glsl
│ ├── test_resource_srv_image_cube_gather_depth.asm
│ ├── test_resource_srv_image_cube_gather_depth.glsl
│ ├── test_resource_srv_image_cube_query.asm
│ ├── test_resource_srv_image_cube_query.glsl
│ ├── test_resource_srv_image_cube_sample.asm
│ ├── test_resource_srv_image_cube_sample.glsl
│ ├── test_resource_srv_image_cube_sample_depth.asm
│ ├── test_resource_srv_image_cube_sample_depth.glsl
│ ├── test_resource_srv_image_gather_depth_sparse_feedback.asm
│ ├── test_resource_srv_image_gather_depth_sparse_feedback.glsl
│ ├── test_resource_srv_image_gather_sparse_feedback.asm
│ ├── test_resource_srv_image_gather_sparse_feedback.glsl
│ ├── test_resource_srv_image_load_sparse_feedback.asm
│ ├── test_resource_srv_image_load_sparse_feedback.glsl
│ ├── test_resource_srv_image_sample_depth_sparse_feedback.asm
│ ├── test_resource_srv_image_sample_depth_sparse_feedback.glsl
│ ├── test_resource_srv_image_sample_sparse_feedback.asm
│ ├── test_resource_srv_image_sample_sparse_feedback.glsl
│ ├── test_resource_srv_indexed_image_1d_array_load.asm
│ ├── test_resource_srv_indexed_image_1d_array_load.glsl
│ ├── test_resource_srv_indexed_image_1d_array_query.asm
│ ├── test_resource_srv_indexed_image_1d_array_query.glsl
│ ├── test_resource_srv_indexed_image_1d_array_sample.asm
│ ├── test_resource_srv_indexed_image_1d_array_sample.glsl
│ ├── test_resource_srv_indexed_image_1d_load.asm
│ ├── test_resource_srv_indexed_image_1d_load.glsl
│ ├── test_resource_srv_indexed_image_1d_query.asm
│ ├── test_resource_srv_indexed_image_1d_query.glsl
│ ├── test_resource_srv_indexed_image_1d_sample.asm
│ ├── test_resource_srv_indexed_image_1d_sample.glsl
│ ├── test_resource_srv_indexed_image_2d_array_gather.asm
│ ├── test_resource_srv_indexed_image_2d_array_gather.glsl
│ ├── test_resource_srv_indexed_image_2d_array_gather_depth.asm
│ ├── test_resource_srv_indexed_image_2d_array_gather_depth.glsl
│ ├── test_resource_srv_indexed_image_2d_array_load.asm
│ ├── test_resource_srv_indexed_image_2d_array_load.glsl
│ ├── test_resource_srv_indexed_image_2d_array_query.asm
│ ├── test_resource_srv_indexed_image_2d_array_query.glsl
│ ├── test_resource_srv_indexed_image_2d_array_sample.asm
│ ├── test_resource_srv_indexed_image_2d_array_sample.glsl
│ ├── test_resource_srv_indexed_image_2d_array_sample_depth.asm
│ ├── test_resource_srv_indexed_image_2d_array_sample_depth.glsl
│ ├── test_resource_srv_indexed_image_2d_gather.asm
│ ├── test_resource_srv_indexed_image_2d_gather.glsl
│ ├── test_resource_srv_indexed_image_2d_gather_depth.asm
│ ├── test_resource_srv_indexed_image_2d_gather_depth.glsl
│ ├── test_resource_srv_indexed_image_2d_load.asm
│ ├── test_resource_srv_indexed_image_2d_load.glsl
│ ├── test_resource_srv_indexed_image_2d_ms_array_load.asm
│ ├── test_resource_srv_indexed_image_2d_ms_array_load.glsl
│ ├── test_resource_srv_indexed_image_2d_ms_array_query.asm
│ ├── test_resource_srv_indexed_image_2d_ms_array_query.glsl
│ ├── test_resource_srv_indexed_image_2d_ms_load.asm
│ ├── test_resource_srv_indexed_image_2d_ms_load.glsl
│ ├── test_resource_srv_indexed_image_2d_ms_query.asm
│ ├── test_resource_srv_indexed_image_2d_ms_query.glsl
│ ├── test_resource_srv_indexed_image_2d_query.asm
│ ├── test_resource_srv_indexed_image_2d_query.glsl
│ ├── test_resource_srv_indexed_image_2d_sample.asm
│ ├── test_resource_srv_indexed_image_2d_sample.glsl
│ ├── test_resource_srv_indexed_image_2d_sample_depth.asm
│ ├── test_resource_srv_indexed_image_2d_sample_depth.glsl
│ ├── test_resource_srv_indexed_image_3d_load.asm
│ ├── test_resource_srv_indexed_image_3d_load.glsl
│ ├── test_resource_srv_indexed_image_3d_query.asm
│ ├── test_resource_srv_indexed_image_3d_query.glsl
│ ├── test_resource_srv_indexed_image_3d_sample.asm
│ ├── test_resource_srv_indexed_image_3d_sample.glsl
│ ├── test_resource_srv_indexed_image_cube_array_gather.asm
│ ├── test_resource_srv_indexed_image_cube_array_gather.glsl
│ ├── test_resource_srv_indexed_image_cube_array_gather_depth.asm
│ ├── test_resource_srv_indexed_image_cube_array_gather_depth.glsl
│ ├── test_resource_srv_indexed_image_cube_array_query.asm
│ ├── test_resource_srv_indexed_image_cube_array_query.glsl
│ ├── test_resource_srv_indexed_image_cube_array_sample.asm
│ ├── test_resource_srv_indexed_image_cube_array_sample.glsl
│ ├── test_resource_srv_indexed_image_cube_array_sample_depth.asm
│ ├── test_resource_srv_indexed_image_cube_array_sample_depth.glsl
│ ├── test_resource_srv_indexed_image_cube_gather.asm
│ ├── test_resource_srv_indexed_image_cube_gather.glsl
│ ├── test_resource_srv_indexed_image_cube_gather_depth.asm
│ ├── test_resource_srv_indexed_image_cube_gather_depth.glsl
│ ├── test_resource_srv_indexed_image_cube_query.asm
│ ├── test_resource_srv_indexed_image_cube_query.glsl
│ ├── test_resource_srv_indexed_image_cube_sample.asm
│ ├── test_resource_srv_indexed_image_cube_sample.glsl
│ ├── test_resource_srv_indexed_image_cube_sample_depth.asm
│ ├── test_resource_srv_indexed_image_cube_sample_depth.glsl
│ ├── test_resource_uav_buffer_load_sparse_feedback.asm
│ ├── test_resource_uav_buffer_load_sparse_feedback.glsl
│ ├── test_resource_uav_counter.asm
│ ├── test_resource_uav_counter.glsl
│ ├── test_resource_uav_counter_indexed.asm
│ ├── test_resource_uav_counter_indexed.glsl
│ ├── test_resource_uav_image_1d_array_atomic.asm
│ ├── test_resource_uav_image_1d_array_atomic.glsl
│ ├── test_resource_uav_image_1d_array_load.asm
│ ├── test_resource_uav_image_1d_array_load.glsl
│ ├── test_resource_uav_image_1d_array_query.asm
│ ├── test_resource_uav_image_1d_array_query.glsl
│ ├── test_resource_uav_image_1d_array_store.asm
│ ├── test_resource_uav_image_1d_array_store.glsl
│ ├── test_resource_uav_image_1d_atomic.asm
│ ├── test_resource_uav_image_1d_atomic.glsl
│ ├── test_resource_uav_image_1d_load.asm
│ ├── test_resource_uav_image_1d_load.glsl
│ ├── test_resource_uav_image_1d_query.asm
│ ├── test_resource_uav_image_1d_query.glsl
│ ├── test_resource_uav_image_1d_store.asm
│ ├── test_resource_uav_image_1d_store.glsl
│ ├── test_resource_uav_image_2d_array_atomic.asm
│ ├── test_resource_uav_image_2d_array_atomic.glsl
│ ├── test_resource_uav_image_2d_array_load.asm
│ ├── test_resource_uav_image_2d_array_load.glsl
│ ├── test_resource_uav_image_2d_array_query.asm
│ ├── test_resource_uav_image_2d_array_query.glsl
│ ├── test_resource_uav_image_2d_array_store.asm
│ ├── test_resource_uav_image_2d_array_store.glsl
│ ├── test_resource_uav_image_2d_atomic.asm
│ ├── test_resource_uav_image_2d_atomic.glsl
│ ├── test_resource_uav_image_2d_load.asm
│ ├── test_resource_uav_image_2d_load.glsl
│ ├── test_resource_uav_image_2d_load_precise.asm
│ ├── test_resource_uav_image_2d_load_precise.glsl
│ ├── test_resource_uav_image_2d_query.asm
│ ├── test_resource_uav_image_2d_query.glsl
│ ├── test_resource_uav_image_2d_store.asm
│ ├── test_resource_uav_image_2d_store.glsl
│ ├── test_resource_uav_image_3d_atomic.asm
│ ├── test_resource_uav_image_3d_atomic.glsl
│ ├── test_resource_uav_image_3d_load.asm
│ ├── test_resource_uav_image_3d_load.glsl
│ ├── test_resource_uav_image_3d_query.asm
│ ├── test_resource_uav_image_3d_query.glsl
│ ├── test_resource_uav_image_3d_store.asm
│ ├── test_resource_uav_image_3d_store.glsl
│ ├── test_resource_uav_image_load_sparse_feedback.asm
│ ├── test_resource_uav_image_load_sparse_feedback.glsl
│ ├── test_resource_uav_indexed_image_1d_array_atomic.asm
│ ├── test_resource_uav_indexed_image_1d_array_atomic.glsl
│ ├── test_resource_uav_indexed_image_1d_array_load.asm
│ ├── test_resource_uav_indexed_image_1d_array_load.glsl
│ ├── test_resource_uav_indexed_image_1d_array_query.asm
│ ├── test_resource_uav_indexed_image_1d_array_query.glsl
│ ├── test_resource_uav_indexed_image_1d_array_store.asm
│ ├── test_resource_uav_indexed_image_1d_array_store.glsl
│ ├── test_resource_uav_indexed_image_1d_atomic.asm
│ ├── test_resource_uav_indexed_image_1d_atomic.glsl
│ ├── test_resource_uav_indexed_image_1d_load.asm
│ ├── test_resource_uav_indexed_image_1d_load.glsl
│ ├── test_resource_uav_indexed_image_1d_query.asm
│ ├── test_resource_uav_indexed_image_1d_query.glsl
│ ├── test_resource_uav_indexed_image_1d_store.asm
│ ├── test_resource_uav_indexed_image_1d_store.glsl
│ ├── test_resource_uav_indexed_image_2d_array_atomic.asm
│ ├── test_resource_uav_indexed_image_2d_array_atomic.glsl
│ ├── test_resource_uav_indexed_image_2d_array_load.asm
│ ├── test_resource_uav_indexed_image_2d_array_load.glsl
│ ├── test_resource_uav_indexed_image_2d_array_query.asm
│ ├── test_resource_uav_indexed_image_2d_array_query.glsl
│ ├── test_resource_uav_indexed_image_2d_array_store.asm
│ ├── test_resource_uav_indexed_image_2d_array_store.glsl
│ ├── test_resource_uav_indexed_image_2d_atomic.asm
│ ├── test_resource_uav_indexed_image_2d_atomic.glsl
│ ├── test_resource_uav_indexed_image_2d_load.asm
│ ├── test_resource_uav_indexed_image_2d_load.glsl
│ ├── test_resource_uav_indexed_image_2d_query.asm
│ ├── test_resource_uav_indexed_image_2d_query.glsl
│ ├── test_resource_uav_indexed_image_2d_store.asm
│ ├── test_resource_uav_indexed_image_2d_store.glsl
│ ├── test_resource_uav_indexed_image_3d_atomic.asm
│ ├── test_resource_uav_indexed_image_3d_atomic.glsl
│ ├── test_resource_uav_indexed_image_3d_load.asm
│ ├── test_resource_uav_indexed_image_3d_load.glsl
│ ├── test_resource_uav_indexed_image_3d_query.asm
│ ├── test_resource_uav_indexed_image_3d_query.glsl
│ ├── test_resource_uav_indexed_image_3d_store.asm
│ ├── test_resource_uav_indexed_image_3d_store.glsl
│ ├── test_resources_cbv.asm
│ ├── test_resources_cbv.glsl
│ ├── test_resources_cbv_dynamic.asm
│ ├── test_resources_cbv_dynamic.glsl
│ ├── test_resources_cbv_indexed.asm
│ ├── test_resources_cbv_indexed.glsl
│ ├── test_resources_cbv_indexed_nonuniform.asm
│ ├── test_resources_cbv_indexed_nonuniform.glsl
│ ├── test_resources_srv_buffer_raw_load.asm
│ ├── test_resources_srv_buffer_raw_load.glsl
│ ├── test_resources_srv_buffer_raw_query.asm
│ ├── test_resources_srv_buffer_raw_query.glsl
│ ├── test_resources_srv_buffer_structured_load.asm
│ ├── test_resources_srv_buffer_structured_load.glsl
│ ├── test_resources_srv_buffer_structured_query.asm
│ ├── test_resources_srv_buffer_structured_query.glsl
│ ├── test_resources_srv_buffer_typed_load.asm
│ ├── test_resources_srv_buffer_typed_load.glsl
│ ├── test_resources_srv_buffer_typed_query.asm
│ ├── test_resources_srv_buffer_typed_query.glsl
│ ├── test_resources_srv_indexed_buffer_raw_load.asm
│ ├── test_resources_srv_indexed_buffer_raw_load.glsl
│ ├── test_resources_srv_indexed_buffer_raw_query.asm
│ ├── test_resources_srv_indexed_buffer_raw_query.glsl
│ ├── test_resources_srv_indexed_buffer_structured_load.asm
│ ├── test_resources_srv_indexed_buffer_structured_load.glsl
│ ├── test_resources_srv_indexed_buffer_structured_query.asm
│ ├── test_resources_srv_indexed_buffer_structured_query.glsl
│ ├── test_resources_srv_indexed_buffer_typed_load.asm
│ ├── test_resources_srv_indexed_buffer_typed_load.glsl
│ ├── test_resources_srv_indexed_buffer_typed_query.asm
│ ├── test_resources_srv_indexed_buffer_typed_query.glsl
│ ├── test_resources_uav_buffer_raw_atomic.asm
│ ├── test_resources_uav_buffer_raw_atomic.glsl
│ ├── test_resources_uav_buffer_raw_load.asm
│ ├── test_resources_uav_buffer_raw_load.glsl
│ ├── test_resources_uav_buffer_raw_load_precise.asm
│ ├── test_resources_uav_buffer_raw_load_precise.glsl
│ ├── test_resources_uav_buffer_raw_query.asm
│ ├── test_resources_uav_buffer_raw_query.glsl
│ ├── test_resources_uav_buffer_raw_store.asm
│ ├── test_resources_uav_buffer_raw_store.glsl
│ ├── test_resources_uav_buffer_structured_atomic.asm
│ ├── test_resources_uav_buffer_structured_atomic.glsl
│ ├── test_resources_uav_buffer_structured_load.asm
│ ├── test_resources_uav_buffer_structured_load.glsl
│ ├── test_resources_uav_buffer_structured_load_precise.asm
│ ├── test_resources_uav_buffer_structured_load_precise.glsl
│ ├── test_resources_uav_buffer_structured_query.asm
│ ├── test_resources_uav_buffer_structured_query.glsl
│ ├── test_resources_uav_buffer_structured_store.asm
│ ├── test_resources_uav_buffer_structured_store.glsl
│ ├── test_resources_uav_buffer_typed_atomic.asm
│ ├── test_resources_uav_buffer_typed_atomic.glsl
│ ├── test_resources_uav_buffer_typed_load.asm
│ ├── test_resources_uav_buffer_typed_load.glsl
│ ├── test_resources_uav_buffer_typed_load_precise.asm
│ ├── test_resources_uav_buffer_typed_load_precise.glsl
│ ├── test_resources_uav_buffer_typed_query.asm
│ ├── test_resources_uav_buffer_typed_query.glsl
│ ├── test_resources_uav_buffer_typed_store.asm
│ ├── test_resources_uav_buffer_typed_store.glsl
│ ├── test_resources_uav_indexed_buffer_raw_atomic.asm
│ ├── test_resources_uav_indexed_buffer_raw_atomic.glsl
│ ├── test_resources_uav_indexed_buffer_raw_load.asm
│ ├── test_resources_uav_indexed_buffer_raw_load.glsl
│ ├── test_resources_uav_indexed_buffer_raw_query.asm
│ ├── test_resources_uav_indexed_buffer_raw_query.glsl
│ ├── test_resources_uav_indexed_buffer_raw_store.asm
│ ├── test_resources_uav_indexed_buffer_raw_store.glsl
│ ├── test_resources_uav_indexed_buffer_structured_atomic.asm
│ ├── test_resources_uav_indexed_buffer_structured_atomic.glsl
│ ├── test_resources_uav_indexed_buffer_structured_load.asm
│ ├── test_resources_uav_indexed_buffer_structured_load.glsl
│ ├── test_resources_uav_indexed_buffer_structured_query.asm
│ ├── test_resources_uav_indexed_buffer_structured_query.glsl
│ ├── test_resources_uav_indexed_buffer_structured_store.asm
│ ├── test_resources_uav_indexed_buffer_structured_store.glsl
│ ├── test_resources_uav_indexed_buffer_typed_atomic.asm
│ ├── test_resources_uav_indexed_buffer_typed_atomic.glsl
│ ├── test_resources_uav_indexed_buffer_typed_load.asm
│ ├── test_resources_uav_indexed_buffer_typed_load.glsl
│ ├── test_resources_uav_indexed_buffer_typed_query.asm
│ ├── test_resources_uav_indexed_buffer_typed_query.glsl
│ ├── test_resources_uav_indexed_buffer_typed_store.asm
│ └── test_resources_uav_indexed_buffer_typed_store.glsl
├── roundtrip_shaders.py
├── scratch_pool.hpp
├── shaders/
│ ├── ags/
│ │ ├── ags.ssbo.comp
│ │ ├── ags_shader_intrinsics_dx12.inc
│ │ ├── cs_constexpr_wmma_gep.sm66.full-wmma.ssbo.comp
│ │ ├── cs_constexpr_wmma_gep.sm66.ssbo.comp
│ │ ├── cs_wmma_alloca.sm66.ssbo.comp
│ │ ├── cs_wmma_copy_transpose_fp16.sm66.ssbo.comp
│ │ ├── cs_wmma_copy_transpose_fp16.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_extract_insert.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16_at.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16_bt.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16_ct.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_f16_ot.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_f16_quant_fp8.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8_quant_f16.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8_quant_f16_strided.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8_quant_f16_strided_transpose.sm66.ssbo.comp
│ │ ├── cs_wmma_f32_16x16x16_fp8_quant_f32.sm66.ssbo.comp
│ │ ├── cs_wmma_fp16_fp8_conversions.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_fp32_fp16_conversions.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_fp32_fp8_conversions.sm66.ssbo.nv-coopmat2.comp
│ │ ├── cs_wmma_fp8_fp32_conversions.sm66.ssbo.full-wmma.comp
│ │ ├── cs_wmma_lds_transpose.sm66.ssbo.comp
│ │ ├── cs_wmma_matrix_length.sm66.ssbo.comp
│ │ ├── cs_wmma_store_phi.full-wmma.sm66.ssbo.comp
│ │ ├── cs_wmma_store_phi.sm66.ssbo.comp
│ │ └── wmma_ags.h
│ ├── alloca-opts/
│ │ ├── bad-stride.frag
│ │ ├── double-array-load.frag
│ │ ├── float4-array-load.bindless.frag
│ │ ├── float4-array-load.bindless.root-constants.frag
│ │ ├── float4-array-load.frag
│ │ ├── float4-array-load.root-constant.frag
│ │ ├── float4-array-load.root-descriptor.frag
│ │ ├── float4-array-load.root-descriptor.root-constants.frag
│ │ ├── load-different.frag
│ │ ├── local-root-constants.local-root-signature.rgen
│ │ ├── matrix-load.frag
│ │ ├── missing-first.frag
│ │ ├── missing-last-element.frag
│ │ ├── out-of-order-load.frag
│ │ ├── store-after-load.frag
│ │ └── uint4-array-load.frag
│ ├── asm/
│ │ ├── bfi.bc.dxil
│ │ ├── cbv.no-legacy-cbuf-layout.sm66-heaps-single-alias.bc.dxil
│ │ ├── cbv.no-legacy-cbuf-layout.sm66-heaps.bc.dxil
│ │ ├── constant-struct-aggregate.bc.dxil
│ │ ├── control-flow-multi-break-with-non-idom-loop-header.dxil
│ │ ├── ibfe.bc.dxil
│ │ └── ubfe.bc.dxil
│ ├── auto-barrier/
│ │ ├── complex-loop.auto-group-shared-barrier.comp
│ │ ├── inner-to-inner.auto-group-shared-barrier.comp
│ │ ├── inner-to-outer.auto-group-shared-barrier.comp
│ │ ├── outer-to-inner.auto-group-shared-barrier.comp
│ │ ├── single-block-loop.auto-group-shared-barrier.comp
│ │ └── single-block.auto-group-shared-barrier.comp
│ ├── control-flow/
│ │ ├── branch-return-2.comp
│ │ ├── branch-return.comp
│ │ ├── branch.comp
│ │ ├── conditional-break-into-if-else-if-ladder-2.comp
│ │ ├── conditional-break-into-if-else-if-ladder.comp
│ │ ├── dual-inner-loop-early-return.comp
│ │ ├── if-else-if-into-continue.comp
│ │ ├── inner-loop-early-return.comp
│ │ ├── interleaved-unrolled-loop-breaks.comp
│ │ ├── loop-break-2.comp
│ │ ├── loop-break.comp
│ │ ├── loop-continue-2.comp
│ │ ├── loop-continue-3.comp
│ │ ├── loop-continue.comp
│ │ ├── loop-inside-infinite-loop-2.frag
│ │ ├── loop-inside-infinite-loop.frag
│ │ ├── loop-return.comp
│ │ ├── loop.comp
│ │ ├── nested-loop-break-2.comp
│ │ ├── nested-loop-break.comp
│ │ ├── nested-loop.comp
│ │ ├── selection-merge-split-post-domination.frag
│ │ ├── switch-continue.frag
│ │ ├── switch-merge-into-other-merge.comp
│ │ ├── switch-shared-header-with-loop.comp
│ │ └── wave-size-dependent-loop-unroll.comp
│ ├── descriptor_qa/
│ │ ├── acceleration-structure.bindless.descriptor-qa.rgen
│ │ ├── acceleration-structure.bindless.descriptor-qa.sm66.rgen
│ │ ├── acceleration-structure.bindless.ssbo-rtas.local-root-signature.descriptor-qa.rgen
│ │ ├── descriptor_qa.bindless.cbv-as-ssbo.descriptor-qa.comp
│ │ ├── descriptor_qa.bindless.descriptor-qa.comp
│ │ ├── descriptor_qa.bindless.descriptor-qa.sm66.comp
│ │ ├── descriptor_qa.bindless.ssbo.descriptor-qa.comp
│ │ ├── early-2.bindless.descriptor-qa.frag
│ │ ├── early-3.bindless.descriptor-qa.frag
│ │ ├── early-4.bindless.descriptor-qa.frag
│ │ ├── early-5.bindless.descriptor-qa.frag
│ │ ├── early-heap.descriptor-qa.sm66.frag
│ │ └── early.bindless.descriptor-qa.frag
│ ├── dxil-builtin/
│ │ ├── accept-hit-and-end-search-ignore-hit.rany
│ │ ├── acos.frag
│ │ ├── asin.frag
│ │ ├── atan.frag
│ │ ├── atomic-bin-op.bindless.root-constant.frag
│ │ ├── atomic-bin-op.frag
│ │ ├── atomic-bin-op.root-descriptor.comp
│ │ ├── atomic-bin-op.ssbo.frag
│ │ ├── atomic-compare-exchange.frag
│ │ ├── atomic-compare-exchange.root-descriptor.comp
│ │ ├── atomic-compare-exchange.ssbo.frag
│ │ ├── attributes.denorm-ftz.comp
│ │ ├── attributes.denorm-preserve.comp
│ │ ├── barrier.comp
│ │ ├── barycentrics-2.frag
│ │ ├── barycentrics.frag
│ │ ├── bfrev.frag
│ │ ├── bitcount-bitrev-sizes.ssbo.comp
│ │ ├── buffer-load-feedback.frag
│ │ ├── buffer-load-signed-feedback.frag
│ │ ├── buffer-load-signed.frag
│ │ ├── buffer-load.frag
│ │ ├── buffer-load.ssbo.frag
│ │ ├── buffer-store-signed.frag
│ │ ├── buffer-store.frag
│ │ ├── buffer-store.ssbo.frag
│ │ ├── buffer-update-counter.frag
│ │ ├── calculate-lod.frag
│ │ ├── call-shader.rgen
│ │ ├── clip.demote-to-helper.frag
│ │ ├── clip.frag
│ │ ├── compute-shader-derivatives-cube-array.noderivs.sm66.ssbo.comp
│ │ ├── compute-shader-derivatives-cube.noderivs.sm66.ssbo.comp
│ │ ├── compute-shader-derivatives-single-thread.sm66.ssbo.comp
│ │ ├── compute-shader-derivatives.noderivs.sm66.ssbo.comp
│ │ ├── cos.frag
│ │ ├── countbits.frag
│ │ ├── coverage.frag
│ │ ├── derivative.frag
│ │ ├── derivative.sm60.frag
│ │ ├── derivative.sm60.native-fp16.frag
│ │ ├── derivatives.sm66.comp
│ │ ├── discard.demote-to-helper.frag
│ │ ├── discard.frag
│ │ ├── dispatch-rays-dimensions.rgen
│ │ ├── dispatch-rays-index.rgen
│ │ ├── dot2.frag
│ │ ├── dot3.frag
│ │ ├── dot4.frag
│ │ ├── eval-centroid.frag
│ │ ├── eval-sample-index.frag
│ │ ├── eval-snapped.frag
│ │ ├── exp.frag
│ │ ├── f16-to-f32.frag
│ │ ├── f32-to-f16.frag
│ │ ├── fabs.frag
│ │ ├── firstbithi-16.sm62.frag
│ │ ├── firstbithi-64.frag
│ │ ├── firstbithi.frag
│ │ ├── firstbitlo-16.sm62.frag
│ │ ├── firstbitlo-64.frag
│ │ ├── firstbitlo.frag
│ │ ├── firstbitshi-16.sm62.frag
│ │ ├── firstbitshi-64.frag
│ │ ├── firstbitshi.frag
│ │ ├── flattened_thread_id_in_group.comp
│ │ ├── fma.frag
│ │ ├── fmad-precise.frag
│ │ ├── fmad.frag
│ │ ├── fmax.frag
│ │ ├── fmin.frag
│ │ ├── frc.frag
│ │ ├── get-dimensions-w-only.frag
│ │ ├── get-dimensions-xyz-only.frag
│ │ ├── get-dimensions.bindless.root-constant.frag
│ │ ├── get-dimensions.bindless.root-constant.ssbo.frag
│ │ ├── get-dimensions.frag
│ │ ├── get-dimensions.ssbo.frag
│ │ ├── group_id.comp
│ │ ├── hcos.frag
│ │ ├── hsin.frag
│ │ ├── htan.frag
│ │ ├── imad.frag
│ │ ├── imax.frag
│ │ ├── imin.frag
│ │ ├── instance-id.vert
│ │ ├── is-helper-lane-2.demote-to-helper.sm66.frag
│ │ ├── is-helper-lane-2.sm66.frag
│ │ ├── is-helper-lane.demote-to-helper.sm66.frag
│ │ ├── is-helper-lane.sm66.frag
│ │ ├── isfinite.frag
│ │ ├── isinf.frag
│ │ ├── isnan.frag
│ │ ├── log.frag
│ │ ├── make-double.frag
│ │ ├── msaa-uav.sm67.comp
│ │ ├── msad.comp
│ │ ├── object-ray-direction.rany
│ │ ├── object-ray-origin.rany
│ │ ├── object-to-world-3x4.rany
│ │ ├── object-to-world-4x3.rany
│ │ ├── pack-unpack.ssbo.sm66.comp
│ │ ├── quad-all-any.sm67.comp
│ │ ├── quad-all-any.sm67.quad-maximal-reconvergence.noglsl.comp
│ │ ├── quad-read-at-2d.comp
│ │ ├── quad-read-at-2d.sm66.comp
│ │ ├── quad-read-at.comp
│ │ ├── quad-read-at.frag
│ │ ├── quad-swap.comp
│ │ ├── quad-swap.frag
│ │ ├── raw-gather-offset-sparse.sm67.ssbo.comp
│ │ ├── raw-gather-offset.sm67.ssbo.comp
│ │ ├── raw-gather-sparse.sm67.ssbo.comp
│ │ ├── raw-gather.sm67.ssbo.comp
│ │ ├── ray-query-phi-multi.invalid.sm66.comp
│ │ ├── ray-query-phi-simple.sm66.comp
│ │ ├── ray-query-select-multi.invalid.sm66.comp
│ │ ├── ray-query-select-simple.sm66.comp
│ │ ├── ray-query-store-multi.invalid.sm66.comp
│ │ ├── ray-query-store-simple.sm66.comp
│ │ ├── ray-query.comp
│ │ ├── ray-t-current.rany
│ │ ├── ray-t-min.rany
│ │ ├── render-target-sample-count.frag
│ │ ├── render-target-sample-position.frag
│ │ ├── report-hit.rint
│ │ ├── round-ne.frag
│ │ ├── round-ni.frag
│ │ ├── round-pi.frag
│ │ ├── round-z.frag
│ │ ├── rsqrt.frag
│ │ ├── rt-geometry-index.rany
│ │ ├── rt-hit-kind.rany
│ │ ├── rt-instance-id.rany
│ │ ├── rt-instance-index.rany
│ │ ├── rt-primitive-index.rany
│ │ ├── rt-ray-flags.rany
│ │ ├── sample-bias-feedback.frag
│ │ ├── sample-bias-offset.frag
│ │ ├── sample-bias.frag
│ │ ├── sample-cmp-bias-feedback.frag
│ │ ├── sample-cmp-bias-offset.frag
│ │ ├── sample-cmp-bias.frag
│ │ ├── sample-cmp-feedback.frag
│ │ ├── sample-cmp-grad-offset-feedback.frag
│ │ ├── sample-cmp-grad-offset.frag
│ │ ├── sample-cmp-grad.frag
│ │ ├── sample-cmp-level.sm67.noglsl.frag
│ │ ├── sample-cmp-levelzero.frag
│ │ ├── sample-cmp-offset-levelzero-feedback.frag
│ │ ├── sample-cmp-offset-levelzero.frag
│ │ ├── sample-cmp-offset.frag
│ │ ├── sample-cmp.frag
│ │ ├── sample-grad-offset-dynamic.noglsl.invalid.sm67.frag
│ │ ├── sample-grad-offset-feedback.frag
│ │ ├── sample-grad-offset.frag
│ │ ├── sample-grad.frag
│ │ ├── sample-id.frag
│ │ ├── sample-level-offset-feedback.frag
│ │ ├── sample-level-offset.frag
│ │ ├── sample-level.frag
│ │ ├── sample-offset-dynamic.noglsl.invalid.sm67.frag
│ │ ├── sample-offset.frag
│ │ ├── sample.frag
│ │ ├── saturate.frag
│ │ ├── sin.frag
│ │ ├── sm64-packed-arithmetic.ssbo.comp
│ │ ├── sm64-packed-arithmetic.ssbo.i8dot.noglsl.comp
│ │ ├── sm64-packed-arithmetic.ssbo.mixed-float-dot-product.noglsl.comp
│ │ ├── split-double.frag
│ │ ├── sqrt.frag
│ │ ├── tan.frag
│ │ ├── texture-gather-4offset.frag
│ │ ├── texture-gather-cmp-offset-feedback.frag
│ │ ├── texture-gather-cmp-offset.frag
│ │ ├── texture-gather-cmp.frag
│ │ ├── texture-gather-offset.frag
│ │ ├── texture-gather-signed-feedback.frag
│ │ ├── texture-gather-signed.frag
│ │ ├── texture-gather.frag
│ │ ├── texture-load-feedback.frag
│ │ ├── texture-load-offset-dynamic.sm67.frag
│ │ ├── texture-load-offset.frag
│ │ ├── texture-load-signed.frag
│ │ ├── texture-load.frag
│ │ ├── texture-store-signed.frag
│ │ ├── texture-store.frag
│ │ ├── texture2dms-sample-position.frag
│ │ ├── thread_id.comp
│ │ ├── thread_id_in_group.comp
│ │ ├── trace-ray-flags-2.rgen
│ │ ├── trace-ray-flags.rgen
│ │ ├── trace-ray.rgen
│ │ ├── umad.frag
│ │ ├── umax.frag
│ │ ├── umin.frag
│ │ ├── vertex-id.vert
│ │ ├── wave-active-all-true.comp
│ │ ├── wave-active-all-true.frag
│ │ ├── wave-active-any-true.comp
│ │ ├── wave-active-any-true.frag
│ │ ├── wave-active-ballot-discard.demote-to-helper.frag
│ │ ├── wave-active-ballot-discard.frag
│ │ ├── wave-active-ballot.comp
│ │ ├── wave-active-ballot.demote-to-helper.frag
│ │ ├── wave-active-ballot.frag
│ │ ├── wave-active-count-bits.comp
│ │ ├── wave-active-count-bits.frag
│ │ ├── wave-all-equal.comp
│ │ ├── wave-all-equal.frag
│ │ ├── wave-get-lane-count.comp
│ │ ├── wave-get-lane-index.comp
│ │ ├── wave-is-first-lane.comp
│ │ ├── wave-is-first-lane.frag
│ │ ├── wave-match.comp
│ │ ├── wave-match.frag
│ │ ├── wave-match.partitioned.noglsl.comp
│ │ ├── wave-match.partitioned.noglsl.frag
│ │ ├── wave-multi-prefix-count-bits.comp
│ │ ├── wave-multi-prefix-count-bits.frag
│ │ ├── wave-multi-prefix-op.comp
│ │ ├── wave-multi-prefix-op.frag
│ │ ├── wave-multi-prefix-op.partitioned.noglsl.comp
│ │ ├── wave-multi-prefix-op.partitioned.noglsl.frag
│ │ ├── wave-prefix.comp
│ │ ├── wave-prefix.frag
│ │ ├── wave-read-lane-at-optimizations.comp
│ │ ├── wave-read-lane-at.comp
│ │ ├── wave-read-lane-first.comp
│ │ ├── wave-read-lane-first.frag
│ │ ├── wave-reduce-helpers.sm67.frag
│ │ ├── wave-reduce-helpers.sm67.quad-maximal-reconvergence.frag
│ │ ├── wave-reduce.comp
│ │ ├── wave-reduce.frag
│ │ ├── wave-size.sm66.comp
│ │ ├── world-ray-direction.rany
│ │ ├── world-ray-origin.rany
│ │ ├── world-to-object-3x4.rany
│ │ └── world-to-object-4x3.rany
│ ├── fp16/
│ │ ├── saturate.frag
│ │ ├── saturate.sm60.frag
│ │ └── saturate.sm60.native-fp16.frag
│ ├── heap-robustness/
│ │ ├── misc.bindless.heap-raw-va-cbv.sm66.ssbo.comp
│ │ ├── misc.bindless.heap-robustness.heap-robustness-cbv.sm66.ssbo.comp
│ │ ├── misc.bindless.heap-robustness.sm66.ssbo.comp
│ │ ├── misc.bindless.sm66.ssbo.comp
│ │ └── misc.heap-robustness.bindless.heap-robustness-cbv.heap-raw-va-cbv.sm66.ssbo.comp
│ ├── instrumentation/
│ │ ├── atomics-raw.bindless.bda-instrumentation.ssbo.comp
│ │ ├── atomics-raw.root-descriptor.bda-instrumentation.ssbo.comp
│ │ ├── atomics-structured-counter.bindless.bda-instrumentation.ssbo.comp
│ │ ├── atomics-structured.bindless.bda-instrumentation.ssbo.comp
│ │ ├── atomics-structured.root-descriptor.bda-instrumentation.ssbo.comp
│ │ ├── atomics-typed.bindless.bda-instrumentation.ssbo.comp
│ │ ├── cbv.bindless.bda-instrumentation.comp
│ │ ├── cbv.root-descriptor.bda-instrumentation.comp
│ │ ├── raw.bindless.bda-instrumentation.ssbo.comp
│ │ ├── raw.root-descriptor.bda-instrumentation.ssbo.comp
│ │ ├── structured.bindless.bda-instrumentation.comp
│ │ ├── structured.bindless.bda-instrumentation.ssbo.comp
│ │ ├── structured.root-descriptor.bda-instrumentation.ssbo.comp
│ │ └── typed.bindless.bda-instrumentation.comp
│ ├── llvm-builtin/
│ │ ├── alloca-robustness-cases.extended-robustness.vert
│ │ ├── alloca.frag
│ │ ├── atomic-bin-op.comp
│ │ ├── atomic-compare-exchange.comp
│ │ ├── atomic-compare-exchange.sm66.ssbo.comp
│ │ ├── bool-to-fp.frag
│ │ ├── constant-expression-cast.comp
│ │ ├── constant-expression-gep.comp
│ │ ├── fadd.frag
│ │ ├── fast-mul-div-pair.comp
│ │ ├── fcmp_eq.frag
│ │ ├── fcmp_ge.frag
│ │ ├── fcmp_gt.frag
│ │ ├── fcmp_le.frag
│ │ ├── fcmp_lt.frag
│ │ ├── fcmp_ne.frag
│ │ ├── fdiv.frag
│ │ ├── fmul.frag
│ │ ├── frem.frag
│ │ ├── fsub.frag
│ │ ├── glitched-integer-width.comp
│ │ ├── groupshared.comp
│ │ ├── icmp_eq.frag
│ │ ├── icmp_ne.frag
│ │ ├── icmp_sge.frag
│ │ ├── icmp_sgt.frag
│ │ ├── icmp_sle.frag
│ │ ├── icmp_slt.frag
│ │ ├── icmp_uge.frag
│ │ ├── icmp_ugt.frag
│ │ ├── icmp_ule.frag
│ │ ├── icmp_ult.frag
│ │ ├── logical-and.frag
│ │ ├── logical-equal.frag
│ │ ├── logical-not-equal.frag
│ │ ├── logical-or.frag
│ │ ├── lut.frag
│ │ ├── min16-phi.sm60.comp
│ │ ├── precise_math.frag
│ │ └── zext-bool.frag
│ ├── memory-model/
│ │ ├── uav-coherent-promotion.bindless.ssbo.comp
│ │ ├── uav-coherent-promotion.root-descriptor.ssbo.comp
│ │ ├── uav-coherent-promotion.sm66.bindless.ssbo.comp
│ │ ├── uav-coherent-promotion.sm66.ssbo.comp
│ │ ├── uav-coherent-promotion.ssbo.comp
│ │ ├── uav-coherent.root-descriptor.ssbo.comp
│ │ ├── uav-coherent.sm66.ssbo.comp
│ │ └── uav-coherent.ssbo.comp
│ ├── nvapi/
│ │ ├── bringup.nvapi.ssbo.rgen
│ │ ├── get-special-global-timer.nvapi.ssbo.rgen
│ │ ├── hit-object.local-root-signature.noglsl.nvapi.ssbo.rgen
│ │ ├── nvHLSLExtns.h
│ │ ├── nvHLSLExtnsInternal.h
│ │ ├── nvShaderExtnEnums.h
│ │ ├── ray-query-cluster-id.nvapi.comp
│ │ ├── rt-cluster-id.nvapi.rany
│ │ └── shuffle.nvapi.ssbo.comp
│ ├── opts/
│ │ ├── fp16-fp32-fp16-1.ssbo.comp
│ │ ├── sabs.frag
│ │ ├── sneg.frag
│ │ ├── wave-read-lane-first-heap.sm66.comp
│ │ ├── wave-read-lane-first.bindless.local-root-signature.rmiss
│ │ ├── wave-read-lane-first.comp
│ │ ├── wave-read-lane-first.no-legacy-cbuf-layout.comp
│ │ ├── wave-read-lane-first.no-legacy-cbuf-layout.sm60.comp
│ │ ├── wave-read-lane-first.sm60.comp
│ │ ├── wave-read-lane-first.sm66.comp
│ │ ├── wave-read-lane-first.ssbo.comp
│ │ ├── wave-read-lane-first.ssbo.rgen
│ │ ├── wave-read-lane-first.ssbo.sm60.comp
│ │ ├── wave-read-lane-first.ssbo.sm66.comp
│ │ └── wave-read-lane-first.ssbo.sm66.rgen
│ ├── raw-access/
│ │ ├── bab-double1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-double2.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-double3.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-double4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float2.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float3.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── bab-float4x4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float2.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float3.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-float4x4.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-half1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-min16float1.raw-access-chains.noglsl.ssbo.sm60.comp
│ │ ├── structured-min16float1.raw-access-chains.noglsl.ssbo.sm60.native-fp16.comp
│ │ ├── structured-min16uint1.raw-access-chains.noglsl.ssbo.sm60.comp
│ │ ├── structured-min16uint1.raw-access-chains.noglsl.ssbo.sm60.native-fp16.comp
│ │ ├── structured-uint1.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-uint2.raw-access-chains.noglsl.ssbo.comp
│ │ ├── structured-uint3.raw-access-chains.noglsl.ssbo.comp
│ │ └── structured-uint4.raw-access-chains.noglsl.ssbo.comp
│ ├── resources/
│ │ ├── acceleration-structure.bindless.rgen
│ │ ├── acceleration-structure.bindless.ssbo-rtas.local-root-signature.raw-va-stride-offset.rgen
│ │ ├── acceleration-structure.bindless.ssbo-rtas.local-root-signature.rgen
│ │ ├── acceleration-structure.local-root-signature.root-descriptor.rgen
│ │ ├── basic.input-attachment.frag
│ │ ├── buffer-16bit.ssbo.bindless.comp
│ │ ├── buffer-16bit.ssbo.bindless.ssbo-align.comp
│ │ ├── buffer-16bit.ssbo.comp
│ │ ├── buffer-64bit.ssbo.bindless.ssbo-align.comp
│ │ ├── buffer-64bit.ssbo.comp
│ │ ├── buffer-alignment-fixup.bindless.root-constant.offset-layout.typed-buffer-offset.comp
│ │ ├── buffer-alignment-fixup.ssbo.ssbo-align.bindless.root-constant.comp
│ │ ├── buffer-alignment-fixup.ssbo.ssbo-align.bindless.root-constant.offset-layout.typed-buffer-offset.comp
│ │ ├── cbuf.root-constant.min16float.sm60.frag
│ │ ├── cbuf.root-constant.min16float.sm60.native-fp16.frag
│ │ ├── cbuf.root-constant.min16int.sm60.frag
│ │ ├── cbuf.root-constant.min16int.sm60.native-fp16.frag
│ │ ├── cbv-array-nonuniform.frag
│ │ ├── cbv-array.frag
│ │ ├── cbv-dynamic.no-legacy-cbuf-layout.local-root-signature.rmiss
│ │ ├── cbv-indexing.frag
│ │ ├── cbv-indexing.sm66.frag
│ │ ├── cbv-legacy-fp16-fp64.frag
│ │ ├── cbv-legacy-fp16-fp64.root-descriptor.frag
│ │ ├── cbv-legacy-fp16-fp64.root-descriptor.sm60.frag
│ │ ├── cbv-legacy-fp16-fp64.root-descriptor.sm60.native-fp16.frag
│ │ ├── cbv-legacy-fp16-fp64.sm60.frag
│ │ ├── cbv-legacy-fp16-fp64.sm60.native-fp16.frag
│ │ ├── cbv.bindless.root-constant.cbv-as-ssbo.frag
│ │ ├── cbv.bindless.root-constant.frag
│ │ ├── cbv.frag
│ │ ├── cbv.no-legacy-cbuf-layout.bindless.frag
│ │ ├── cbv.no-legacy-cbuf-layout.index-divider.frag
│ │ ├── cbv.no-legacy-cbuf-layout.local-root-signature.rmiss
│ │ ├── cbv.no-legacy-cbuf-layout.native-fp16.sm60.frag
│ │ ├── cbv.no-legacy-cbuf-layout.root-constant.frag
│ │ ├── cbv.root-constant.frag
│ │ ├── cbv.root-descriptor.no-legacy-cbuf-layout.frag
│ │ ├── combined-image-sampler-reuse.frag
│ │ ├── dynamic-root-constant.root-constant.bindless.root-descriptor.comp
│ │ ├── min16-alloca-groupshared.sm60.comp
│ │ ├── min16float-ssbo-dxr.ssbo.rgen
│ │ ├── raw-buffer-addressing.comp
│ │ ├── raw-buffer-addressing.ssbo.comp
│ │ ├── root-bda.root-descriptor.comp
│ │ ├── root-bda.root-descriptor.sm60.comp
│ │ ├── root-constant-with-bda.root-descriptor.root-constant.comp
│ │ ├── rt-resources.bindless.local-root-signature.rmiss
│ │ ├── rt-resources.bindless.rmiss
│ │ ├── rt-resources.rmiss
│ │ ├── sampler-array.frag
│ │ ├── sampler-indexing.frag
│ │ ├── sampler-indexing.sm66.frag
│ │ ├── sampler.bindless.root-constant.frag
│ │ ├── sm66/
│ │ │ ├── atomics-64bit-groupshared.ssbo.sm66.comp
│ │ │ ├── atomics-64bit.root-descriptor.sm66.comp
│ │ │ ├── atomics-64bit.ssbo.sm66.comp
│ │ │ ├── atomics-component-alias.sm66.comp
│ │ │ ├── atomics-typed-64bit-heap.sm66.comp
│ │ │ ├── atomics-typed-64bit.bindless.sm66.comp
│ │ │ ├── atomics-typed-64bit.sm66.comp
│ │ │ ├── binding-range-selection.bindless.sm66.comp
│ │ │ ├── binding-range-selection.sm66.comp
│ │ │ ├── buffer-64bit-double.ssbo.sm66.comp
│ │ │ ├── buffer-64bit.ssbo.sm66.comp
│ │ │ ├── buffer-64bit.ssbo.ssbo-align.sm66.comp
│ │ │ ├── cbuffer-heap.sm66.frag
│ │ │ ├── cbv.no-legacy-cbuf-layout.bindless.sm66.frag
│ │ │ ├── cbv.no-legacy-cbuf-layout.sm66.frag
│ │ │ ├── raw-buffer-heap.sm66.frag
│ │ │ ├── raw-buffer-heap.ssbo.sm66.frag
│ │ │ ├── raw-buffer-heap.typed-buffer-offset.sm66.frag
│ │ │ ├── raw-buffers-binding.ssbo.bindless.sm66.frag
│ │ │ ├── raw-buffers-binding.ssbo.bindless.ssbo-align.sm66.frag
│ │ │ ├── raygen-heap.sm66.rgen
│ │ │ ├── raygen-heap.ssbo-rtas.raw-va-stride-offset.sm66.rgen
│ │ │ ├── raygen-heap.ssbo-rtas.sm66.rgen
│ │ │ ├── raygen.sm66.rgen
│ │ │ ├── raygen.ssbo-rtas.bindless.raw-va-stride-offset.sm66.rgen
│ │ │ ├── raygen.ssbo-rtas.bindless.sm66.rgen
│ │ │ ├── rw-typed-binding.sm66.frag
│ │ │ ├── rw-typed-heap.sm66.frag
│ │ │ ├── sampled-types-binding.sm66.frag
│ │ │ ├── sampled-types.sm66.frag
│ │ │ ├── sampler-binding.sm66.frag
│ │ │ ├── sampler-heap.sm66.frag
│ │ │ ├── structured-16bit-heap.ssbo.sm66.frag
│ │ │ ├── structured-16bit-heap.ssbo.ssbo-align.sm66.frag
│ │ │ ├── structured-buffer-heap.sm66.frag
│ │ │ ├── structured-buffer-heap.ssbo.sm66.frag
│ │ │ ├── structured-buffer-heap.ssbo.ssbo-align.sm66.frag
│ │ │ └── structured-buffer-heap.typed-buffer-offset.sm66.frag
│ │ ├── srv-array-raw-buffer-nonuniform.frag
│ │ ├── srv-array-raw-buffer.frag
│ │ ├── srv-array-structured-buffer-nonuniform.frag
│ │ ├── srv-array-structured-buffer.frag
│ │ ├── srv-array-texture-nonuniform.frag
│ │ ├── srv-array-texture.frag
│ │ ├── srv-array-typed-buffer-nonuniform.frag
│ │ ├── srv-array-typed-buffer.frag
│ │ ├── srv-indexing.frag
│ │ ├── srv-indexing.sm66.frag
│ │ ├── srv-raw-buffer.bindless.root-constant.frag
│ │ ├── srv-raw-buffer.bindless.root-constant.ssbo.frag
│ │ ├── srv-raw-buffer.ssbo.frag
│ │ ├── srv-structured-buffer.bindless.root-constant.frag
│ │ ├── srv-structured-buffer.bindless.root-constant.ssbo.frag
│ │ ├── srv-structured-buffer.ssbo.frag
│ │ ├── srv-texture.bindless.root-constant.frag
│ │ ├── srv-texture.bindless.root-constant.inline-ubo.frag
│ │ ├── srv-typed-buffer.bindless.root-constant.frag
│ │ ├── srv-uav-raw.typed-buffer-offset.comp
│ │ ├── srv-uav.typed-buffer-offset.comp
│ │ ├── ssbo-minprecision.sm60.native-fp16.frag
│ │ ├── ssbo-minprecision.sm60.ssbo.frag
│ │ ├── ssbo-minprecision.sm60.ssbo.native-fp16.frag
│ │ ├── ssbo-minprecision.sm60.ssbo.native-fp16.root-descriptor.frag
│ │ ├── ssbo-minprecision.sm60.ssbo.root-descriptor.frag
│ │ ├── subobject-parsing.rgen
│ │ ├── typed-resources-16bit-sparse.frag
│ │ ├── typed-resources-16bit.bindless.frag
│ │ ├── typed-resources-16bit.frag
│ │ ├── typed-resources-16bit.sm60.bindless.frag
│ │ ├── typed-resources-16bit.sm60.frag
│ │ ├── typed-resources-16bit.sm60.native-fp16.bindless.frag
│ │ ├── typed-resources-16bit.sm60.native-fp16.frag
│ │ ├── uav-array-raw-buffer-nonuniform.frag
│ │ ├── uav-array-raw-buffer.frag
│ │ ├── uav-array-structured-buffer-nonuniform.frag
│ │ ├── uav-array-structured-buffer-nonuniform.ssbo.bindless.root-constant.frag
│ │ ├── uav-array-structured-buffer-nonuniform.ssbo.frag
│ │ ├── uav-array-structured-buffer.frag
│ │ ├── uav-array-texture-nonuniform.frag
│ │ ├── uav-array-texture.frag
│ │ ├── uav-array-typed-buffer-nonuniform.frag
│ │ ├── uav-array-typed-buffer.frag
│ │ ├── uav-counter-array.ssbo.frag
│ │ ├── uav-counter-array.ssbo.sm66.frag
│ │ ├── uav-counter-array.ssbo.sm66.uav-counter-ssbo.frag
│ │ ├── uav-counter-array.ssbo.uav-counter-ssbo.frag
│ │ ├── uav-counter-heap.sm66.bindless.ssbo.frag
│ │ ├── uav-counter-heap.sm66.uav-counter-ssbo.bindless.ssbo.frag
│ │ ├── uav-counter-heap.sm66.uav-counter-texel-buffer.bindless.ssbo.frag
│ │ ├── uav-counter.bindless.nobda.root-constant.comp
│ │ ├── uav-counter.bindless.nobda.root-constant.raw-va-stride-offset.comp
│ │ ├── uav-counter.bindless.root-constant.comp
│ │ ├── uav-counter.bindless.root-constant.raw-va-stride-offset.comp
│ │ ├── uav-counter.bindless.root-constant.raw-va-stride-offset.heap-raw-va-cbv.comp
│ │ ├── uav-counter.bindless.root-constant.uav-counter-ssbo.comp
│ │ ├── uav-counter.ssbo.comp
│ │ ├── uav-counter.ssbo.raw-va-stride-offset.comp
│ │ ├── uav-counter.ssbo.uav-counter-ssbo.comp
│ │ ├── uav-indexing.frag
│ │ ├── uav-indexing.sm66.frag
│ │ ├── uav-raw-buffer.bindless.root-constant.frag
│ │ ├── uav-raw-buffer.ssbo.frag
│ │ ├── uav-structured-buffer.bindless.root-constant.frag
│ │ ├── uav-typed-buffer.bindless.root-constant.frag
│ │ └── uav-typed.typed-uav-without-format.comp
│ ├── rov/
│ │ ├── rov-bab.bindless.frag
│ │ ├── rov-bab.frag
│ │ ├── rov-bab.ssbo.bindless.frag
│ │ ├── rov-bab.ssbo.frag
│ │ ├── rov-bab.ssbo.root-descriptor.frag
│ │ ├── rov-branch-early-return.frag
│ │ ├── rov-branch.frag
│ │ ├── rov-buffer.frag
│ │ ├── rov-inloop-2.frag
│ │ ├── rov-inloop.frag
│ │ ├── rov-per-sample.sm66.frag
│ │ ├── rov-postloop.frag
│ │ ├── rov-structured.bindless.frag
│ │ ├── rov-structured.frag
│ │ ├── rov-structured.ssbo.bindless.frag
│ │ ├── rov-structured.ssbo.frag
│ │ ├── rov-structured.ssbo.root-descriptor.frag
│ │ ├── rov-tex1d.bindless.frag
│ │ ├── rov-tex1d.frag
│ │ ├── rov-tex1darray.bindless.frag
│ │ ├── rov-tex1darray.frag
│ │ ├── rov-tex2d.bindless.frag
│ │ ├── rov-tex2d.frag
│ │ ├── rov-tex2darray.bindless.frag
│ │ ├── rov-tex2darray.frag
│ │ ├── rov-tex3d.bindless.frag
│ │ ├── rov-tex3d.frag
│ │ ├── rov-undef.frag
│ │ └── rov.sm66.frag
│ ├── sampler-feedback/
│ │ ├── sampler-feedback.frag
│ │ └── sampler-feedback.sm66.frag
│ ├── semantics/
│ │ ├── clip-cull-distance.vert
│ │ ├── clip-cull.frag
│ │ ├── clip-distance-cols.frag
│ │ ├── clip-distance-cols.vert
│ │ ├── clip-distance-flatten.frag
│ │ ├── clip-distance-flatten.vert
│ │ ├── clip-distance-rows.frag
│ │ ├── clip-distance-rows.vert
│ │ ├── clip-distance-single.vert
│ │ ├── coverage.frag
│ │ ├── depth-greater-equal.frag
│ │ ├── depth-less-equal.frag
│ │ ├── depth.frag
│ │ ├── early-depth-stencil.frag
│ │ ├── inner-coverage.noglsl.frag
│ │ ├── is-front-face.frag
│ │ ├── position.frag
│ │ ├── primitive-id.frag
│ │ ├── primitive-id.geom
│ │ ├── render-target-array-index.frag
│ │ ├── render-target-array-index.geom
│ │ ├── sample-rate-pos.frag
│ │ ├── stencil-ref.frag
│ │ ├── sv-shading-rate.noglsl.frag
│ │ ├── sv-shading-rate.noglsl.vert
│ │ ├── view-id.frag
│ │ ├── view-id.vert
│ │ ├── viewport-array-index.frag
│ │ └── viewport-array-index.geom
│ ├── stages/
│ │ ├── boolean-io.vert
│ │ ├── callable-chain.rcall
│ │ ├── callable.rcall
│ │ ├── closesthit.rclosest
│ │ ├── domain-clip-cull.tese
│ │ ├── domain-patch-input-integer-io.tese
│ │ ├── domain.tese
│ │ ├── extra_output.dual-source-blending.frag
│ │ ├── extra_output_reordered.dual-source-blending.frag
│ │ ├── geometry-clip-cull.geom
│ │ ├── geometry-input-line.geom
│ │ ├── geometry-input-lineadj.geom
│ │ ├── geometry-input-point.geom
│ │ ├── geometry-input-triangle.geom
│ │ ├── geometry-input-triangleadj.geom
│ │ ├── geometry-instancing.geom
│ │ ├── geometry-output-line.geom
│ │ ├── geometry-output-point.geom
│ │ ├── geometry-streams.geom
│ │ ├── hull-arrays.tesc
│ │ ├── hull-clip-cull.tesc
│ │ ├── hull-patch-output-integer-io.tesc
│ │ ├── hull-single-cp.tesc
│ │ ├── hull.tesc
│ │ ├── mesh-basic-line.mesh
│ │ ├── mesh-basic.mesh
│ │ ├── mesh-clip-cull.mesh
│ │ ├── raygen-complex-storage-class.rgen
│ │ ├── raygen-skip-inactive-resources.rgen
│ │ ├── raygen.rgen
│ │ ├── raymiss-chain.rmiss
│ │ ├── raymiss.rmiss
│ │ ├── simple.dual-source-blending.frag
│ │ ├── simple.invariant.vert
│ │ ├── stage-input-output.16bit-io.frag
│ │ ├── stage-input-output.frag
│ │ ├── stream-out.stream-out.vert
│ │ ├── swizzle.rt-swizzle.frag
│ │ ├── task-basic.task
│ │ ├── vertex-array-input.vert
│ │ ├── vertex-array-output.vert
│ │ └── vertex-input-remapping.vert
│ ├── vectorization/
│ │ ├── copy-byte-address.ssbo.comp
│ │ ├── copy-composite-2.ssbo.comp
│ │ ├── copy-composite.ssbo.comp
│ │ ├── copy-composite.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-double2.ssbo.comp
│ │ ├── copy-double2.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-double3.ssbo.comp
│ │ ├── copy-double3.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-double4.ssbo.comp
│ │ ├── copy-float2.ssbo.comp
│ │ ├── copy-float2.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-float2x2.ssbo.comp
│ │ ├── copy-float3.ssbo.comp
│ │ ├── copy-float3.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-float4x4.ssbo.comp
│ │ ├── copy-half2.ssbo.comp
│ │ ├── copy-half2.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-half3.ssbo.comp
│ │ ├── copy-half3.ssbo.ssbo-align.bindless.comp
│ │ ├── copy-half4.ssbo.comp
│ │ └── copy-half4.ssbo.ssbo-align.bindless.comp
│ ├── view-instancing/
│ │ ├── geom/
│ │ │ ├── basic.view-instancing.last-pre-raster.geom
│ │ │ ├── basic.view-instancing.last-pre-raster.view-instance-mask.geom
│ │ │ ├── basic.view-instancing.view-instancing-multiview.last-pre-raster.geom
│ │ │ ├── basic.view-instancing.view-instancing-multiview.view-instancing-viewport-offset.last-pre-raster.geom
│ │ │ └── basic.view-instancing.view-instancing-viewport-offset.last-pre-raster.geom
│ │ ├── mesh/
│ │ │ ├── basic-export-viewport-layer.view-instancing.last-pre-raster.mesh
│ │ │ ├── basic-export-viewport-layer.view-instancing.last-pre-raster.view-instancing-viewport-offset.mesh
│ │ │ ├── basic-few-thread.view-instancing.last-pre-raster.mesh
│ │ │ ├── basic-many-thread.view-instancing.last-pre-raster.mesh
│ │ │ ├── basic.view-instancing.last-pre-raster.mesh
│ │ │ ├── basic.view-instancing.last-pre-raster.view-instance-mask.mesh
│ │ │ ├── basic.view-instancing.last-pre-raster.view-instancing-viewport-offset.mesh
│ │ │ └── basic.view-instancing.mesh
│ │ ├── tesc/
│ │ │ ├── basic.view-instancing.tesc
│ │ │ └── basic.view-instancing.view-instancing-multiview.tesc
│ │ ├── tese/
│ │ │ ├── domain-export-layer-viewport.view-instancing.view-instancing-multiview.last-pre-raster.tese
│ │ │ ├── domain-export-layer-viewport.view-instancing.view-instancing-multiview.tese
│ │ │ ├── domain.view-instancing.last-pre-raster.tese
│ │ │ ├── domain.view-instancing.tese
│ │ │ ├── domain.view-instancing.view-instancing-multiview.last-pre-raster.tese
│ │ │ ├── domain.view-instancing.view-instancing-multiview.tese
│ │ │ ├── domain.view-instancing.view-instancing-viewport-offset.last-pre-raster.tese
│ │ │ └── domain.view-instancing.view-instancing-viewport-offset.tese
│ │ └── vert/
│ │ ├── basic.view-instancing.export-layer-viewport.last-pre-raster.vert
│ │ ├── basic.view-instancing.export-layer-viewport.vert
│ │ ├── basic.view-instancing.export-layer-viewport.view-instancing-multiview.vert
│ │ ├── basic.view-instancing.export-layer-viewport.view-instancing-viewport-offset.vert
│ │ ├── basic.view-instancing.export-layer.last-pre-raster.vert
│ │ ├── basic.view-instancing.export-layer.vert
│ │ ├── basic.view-instancing.export-layer.view-instancing-multiview.vert
│ │ ├── basic.view-instancing.export-layer.view-instancing-viewport-offset.vert
│ │ ├── basic.view-instancing.export-viewport.last-pre-raster.vert
│ │ ├── basic.view-instancing.export-viewport.vert
│ │ ├── basic.view-instancing.export-viewport.view-instancing-multiview.vert
│ │ ├── basic.view-instancing.export-viewport.view-instancing-viewport-offset.vert
│ │ ├── basic.view-instancing.last-pre-raster.vert
│ │ ├── basic.view-instancing.vert
│ │ ├── basic.view-instancing.view-instance-mask.last-pre-raster.vert
│ │ ├── basic.view-instancing.view-instance-mask.vert
│ │ ├── basic.view-instancing.view-instancing-multiview.vert
│ │ └── basic.view-instancing.view-instancing-viewport-offset.vert
│ └── vkmm/
│ ├── coopmat.sm66.ssbo.vkmm.comp
│ ├── cross_group_sharing.vkmm.node.inline-ubo.comp
│ ├── descriptor_qa.bindless.descriptor-qa.vkmm.comp
│ ├── groupshared.vkmm.comp
│ ├── hull.vkmm.tesc
│ ├── image-load-store.vkmm.comp
│ ├── image-load-store.vkmm.sm66.comp
│ ├── memory-model/
│ │ ├── uav-coherent-promotion.bindless.ssbo.vkmm.comp
│ │ ├── uav-coherent-promotion.root-descriptor.ssbo.vkmm.comp
│ │ ├── uav-coherent-promotion.sm66.bindless.ssbo.vkmm.comp
│ │ ├── uav-coherent-promotion.sm66.ssbo.vkmm.comp
│ │ ├── uav-coherent-promotion.ssbo.vkmm.comp
│ │ ├── uav-coherent.root-descriptor.ssbo.vkmm.comp
│ │ ├── uav-coherent.sm66.ssbo.vkmm.comp
│ │ └── uav-coherent.ssbo.vkmm.comp
│ ├── report-hit.vkmm.rint
│ ├── rov-structured.vkmm.frag
│ ├── rov-tex2d.vkmm.frag
│ └── wmma_ags.h
├── show_graph.py
├── spirv_module.cpp
├── spirv_module.hpp
├── spirv_module_instrumentation.cpp
├── spirv_module_instrumentation.hpp
├── test_shaders.py
├── third_party/
│ ├── CMakeLists.txt
│ ├── bc-decoder/
│ │ ├── llvm_bitreader.h
│ │ ├── llvm_decoder.cpp
│ │ └── llvm_decoder.h
│ ├── cli_parser/
│ │ ├── cli_parser.cpp
│ │ └── cli_parser.hpp
│ └── glslang-spirv/
│ ├── InReadableOrder.cpp
│ ├── Logger.cpp
│ ├── Logger.h
│ ├── SpvBuilder.cpp
│ ├── SpvBuilder.h
│ └── spvIR.h
└── util/
├── thread_local_allocator.cpp
└── thread_local_allocator.hpp
================================================
FILE CONTENTS
================================================
================================================
FILE: .clang-format
================================================
# The style used for all options not specifically set in the configuration.
BasedOnStyle: LLVM
# The extra indent or outdent of access modifiers, e.g. public:.
AccessModifierOffset: -4
# If true, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column.
AlignEscapedNewlinesLeft: true
# If true, aligns trailing comments.
AlignTrailingComments: false
# Allow putting all parameters of a function declaration onto the next line even if BinPackParameters is false.
AllowAllParametersOfDeclarationOnNextLine: false
# Allows contracting simple braced statements to a single line.
AllowShortBlocksOnASingleLine: false
# If true, short case labels will be contracted to a single line.
AllowShortCaseLabelsOnASingleLine: false
# Dependent on the value, int f() { return 0; } can be put on a single line. Possible values: None, Inline, All.
AllowShortFunctionsOnASingleLine: None
# If true, if (a) return; can be put on a single line.
AllowShortIfStatementsOnASingleLine: false
# If true, while (true) continue; can be put on a single line.
AllowShortLoopsOnASingleLine: false
# If true, always break after function definition return types.
AlwaysBreakAfterDefinitionReturnType: false
# If true, always break before multiline string literals.
AlwaysBreakBeforeMultilineStrings: false
# If true, always break after the template<...> of a template declaration.
AlwaysBreakTemplateDeclarations: true
# If false, a function call's arguments will either be all on the same line or will have one line each.
BinPackArguments: true
# If false, a function declaration's or function definition's parameters will either all be on the same line
# or will have one line each.
BinPackParameters: true
# The way to wrap binary operators. Possible values: None, NonAssignment, All.
BreakBeforeBinaryOperators: None
# The brace breaking style to use. Possible values: Attach, Linux, Stroustrup, Allman, GNU.
BreakBeforeBraces: Allman
# If true, ternary operators will be placed after line breaks.
BreakBeforeTernaryOperators: false
# Always break constructor initializers before commas and align the commas with the colon.
BreakConstructorInitializersBeforeComma: true
# The column limit. A column limit of 0 means that there is no column limit.
ColumnLimit: 120
# A regular expression that describes comments with special meaning, which should not be split into lines or otherwise changed.
CommentPragmas: '^ *'
# If the constructor initializers don't fit on a line, put each initializer on its own line.
ConstructorInitializerAllOnOneLineOrOnePerLine: false
# The number of characters to use for indentation of constructor initializer lists.
ConstructorInitializerIndentWidth: 4
# Indent width for line continuations.
ContinuationIndentWidth: 4
# If true, format braced lists as best suited for C++11 braced lists.
Cpp11BracedListStyle: false
# Disables formatting at all.
DisableFormat: false
# A vector of macros that should be interpreted as foreach loops instead of as function calls.
#ForEachMacros: ''
# Indent case labels one level from the switch statement.
# When false, use the same indentation level as for the switch statement.
# Switch statement body is always indented one level more than case labels.
IndentCaseLabels: false
# The number of columns to use for indentation.
IndentWidth: 4
# Indent if a function definition or declaration is wrapped after the type.
IndentWrappedFunctionNames: false
# If true, empty lines at the start of blocks are kept.
KeepEmptyLinesAtTheStartOfBlocks: true
# Language, this format style is targeted at. Possible values: None, Cpp, Java, JavaScript, Proto.
Language: Cpp
# The maximum number of consecutive empty lines to keep.
MaxEmptyLinesToKeep: 1
# The indentation used for namespaces. Possible values: None, Inner, All.
NamespaceIndentation: None
# The penalty for breaking a function call after "call(".
PenaltyBreakBeforeFirstCallParameter: 19
# The penalty for each line break introduced inside a comment.
PenaltyBreakComment: 300
# The penalty for breaking before the first <<.
PenaltyBreakFirstLessLess: 120
# The penalty for each line break introduced inside a string literal.
PenaltyBreakString: 1000
# The penalty for each character outside of the column limit.
PenaltyExcessCharacter: 1000000
# Penalty for putting the return type of a function onto its own line.
PenaltyReturnTypeOnItsOwnLine: 1000000000
# Pointer and reference alignment style. Possible values: Left, Right, Middle.
PointerAlignment: Right
# If true, a space may be inserted after C style casts.
SpaceAfterCStyleCast: false
# If false, spaces will be removed before assignment operators.
SpaceBeforeAssignmentOperators: true
# Defines in which cases to put a space before opening parentheses. Possible values: Never, ControlStatements, Always.
SpaceBeforeParens: ControlStatements
# If true, spaces may be inserted into '()'.
SpaceInEmptyParentheses: false
# The number of spaces before trailing line comments (// - comments).
SpacesBeforeTrailingComments: 1
# If true, spaces will be inserted after '<' and before '>' in template argument lists.
SpacesInAngles: false
# If true, spaces may be inserted into C style casts.
SpacesInCStyleCastParentheses: false
# If true, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals).
SpacesInContainerLiterals: false
# If true, spaces will be inserted after '(' and before ')'.
SpacesInParentheses: false
# If true, spaces will be inserted after '[' and befor']'.
SpacesInSquareBrackets: false
# Format compatible with this standard, e.g. use A > instead of A> for LS_Cpp03. Possible values: Cpp03, Cpp11, Auto.
Standard: Cpp11
# The number of columns used for tab stops.
TabWidth: 4
# The way to use tab characters in the resulting file. Possible values: Never, ForIndentation, Always.
UseTab: ForIndentation
# Do not reflow comments
ReflowComments: false
================================================
FILE: .gitattributes
================================================
shaders/**/* linguist-language=GLSL
reference/**/* linguist-generated
================================================
FILE: .gitignore
================================================
/cmake-build-debug
/cmake-build-release
*.iml
/.idea
/.vs
/.vscode
/external/dxc*
/external/DirectXShaderCompiler
/external/llvm
/shaders-dxil
/shaders-dxbc
/reference/shaders-dxil
/reference/shaders-dxbc
/build
/out/build
================================================
FILE: .gitmodules
================================================
[submodule "third_party/spirv-headers"]
path = third_party/spirv-headers
url = https://github.com/KhronosGroup/SPIRV-Headers
[submodule "third_party/SPIRV-Tools"]
path = third_party/SPIRV-Tools
url = https://github.com/KhronosGroup/SPIRV-Tools
[submodule "third_party/SPIRV-Cross"]
path = third_party/SPIRV-Cross
url = https://github.com/KhronosGroup/SPIRV-Cross
[submodule "third_party/dxbc-spirv"]
path = subprojects/dxbc-spirv
url = https://github.com/doitsujin/dxbc-spirv
================================================
FILE: CMakeLists.txt
================================================
#
# Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
#
# SPDX-License-Identifier: MIT
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_C_STANDARD 99)
project(dxil-spirv LANGUAGES CXX C)
add_library(dxil-debug STATIC debug/logging.hpp debug/logging.cpp)
target_include_directories(dxil-debug PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/debug)
set_target_properties(dxil-debug PROPERTIES POSITION_INDEPENDENT_CODE ON)
option(DXIL_SPIRV_CLI "Enable CLI support." ON)
option(DXIL_SPIRV_NATIVE_LLVM "Enable native LLVM support." OFF)
include(GNUInstallDirs)
if (CMAKE_COMPILER_IS_GNUCXX OR (${CMAKE_CXX_COMPILER_ID} MATCHES "Clang"))
set(DXIL_SPV_CXX_FLAGS -Wall -Wextra -Wno-missing-field-initializers -Wno-empty-body -Wno-unused-parameter -fno-exceptions -fno-rtti -fvisibility=hidden)
elseif (MSVC)
set(DXIL_SPV_CXX_FLAGS /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4244 /wd4267 /wd4244 /wd4309 /wd4005 /MP /DNOMINMAX)
endif()
add_library(dxil-utils STATIC util/thread_local_allocator.hpp util/thread_local_allocator.cpp)
target_include_directories(dxil-utils PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/util)
target_compile_options(dxil-utils PRIVATE ${DXIL_SPV_CXX_FLAGS})
set_target_properties(dxil-utils PROPERTIES POSITION_INDEPENDENT_CODE ON)
add_subdirectory(third_party EXCLUDE_FROM_ALL)
add_subdirectory(bc EXCLUDE_FROM_ALL)
add_subdirectory(external EXCLUDE_FROM_ALL)
add_library(spirv-module STATIC
ir.hpp
descriptor_qa.cpp descriptor_qa.hpp
spirv_module.hpp spirv_module.cpp
spirv_module_instrumentation.hpp spirv_module_instrumentation.cpp)
set_target_properties(spirv-module PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(spirv-module PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(spirv-module PUBLIC glslang-spirv-builder dxil-spirv-headers)
target_link_libraries(spirv-module PRIVATE dxil-utils dxil-debug)
target_compile_options(spirv-module PRIVATE ${DXIL_SPV_CXX_FLAGS})
add_library(dxil-converter STATIC
memory_stream.hpp memory_stream.cpp
llvm_bitcode_parser.hpp llvm_bitcode_parser.cpp
dxil.hpp
dxil_converter.hpp dxil_converter.cpp
cfg_structurizer.hpp cfg_structurizer.cpp
node_pool.hpp node_pool.cpp
node.hpp node.cpp
dxil_parser.hpp dxil_parser.cpp
scratch_pool.hpp
opcodes/converter_impl.hpp
opcodes/opcodes.hpp
opcodes/dxil/dxil_common.hpp opcodes/dxil/dxil_common.cpp
opcodes/dxil/dxil_resources.hpp opcodes/dxil/dxil_resources.cpp
opcodes/dxil/dxil_compute.hpp opcodes/dxil/dxil_compute.cpp
opcodes/dxil/dxil_arithmetic.hpp opcodes/dxil/dxil_arithmetic.cpp
opcodes/dxil/dxil_pixel_ops.hpp opcodes/dxil/dxil_pixel_ops.cpp
opcodes/dxil/dxil_geometry.hpp opcodes/dxil/dxil_geometry.cpp
opcodes/dxil/dxil_tessellation.hpp opcodes/dxil/dxil_tessellation.cpp
opcodes/dxil/dxil_waveops.hpp opcodes/dxil/dxil_waveops.cpp
opcodes/dxil/dxil_sampling.hpp opcodes/dxil/dxil_sampling.cpp
opcodes/dxil/dxil_buffer.hpp opcodes/dxil/dxil_buffer.cpp
opcodes/dxil/dxil_ray_tracing.hpp opcodes/dxil/dxil_ray_tracing.cpp
opcodes/dxil/dxil_mesh.hpp opcodes/dxil/dxil_mesh.cpp
opcodes/dxil/dxil_workgraph.hpp opcodes/dxil/dxil_workgraph.cpp
opcodes/dxil/dxil_ags.hpp opcodes/dxil/dxil_ags.cpp
opcodes/dxil/dxil_nvapi.hpp opcodes/dxil/dxil_nvapi.cpp
opcodes/opcodes_llvm_builtins.hpp opcodes/opcodes_llvm_builtins.cpp
opcodes/opcodes_dxil_builtins.hpp opcodes/opcodes_dxil_builtins.cpp)
set_target_properties(dxil-converter PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_include_directories(dxil-converter PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
target_compile_options(dxil-converter PRIVATE ${DXIL_SPV_CXX_FLAGS})
target_link_libraries(dxil-converter PRIVATE dxil-debug external::llvm dxil-utils)
target_link_libraries(dxil-converter PUBLIC spirv-module)
add_library(dxil-spirv-c-shared SHARED dxil_spirv_c.h dxil_spirv_c.cpp)
target_include_directories(dxil-spirv-c-shared
PUBLIC
$
$)
target_link_libraries(dxil-spirv-c-shared PRIVATE dxil-debug dxil-converter external::llvm dxil-utils)
target_compile_options(dxil-spirv-c-shared PRIVATE ${DXIL_SPV_CXX_FLAGS})
target_compile_definitions(dxil-spirv-c-shared PRIVATE DXIL_SPV_EXPORT_SYMBOLS)
set_target_properties(dxil-spirv-c-shared PROPERTIES PUBLIC_HEADERS dxil_spirv_c.h)
if (WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
target_link_libraries(dxil-spirv-c-shared PRIVATE -static gcc stdc++ winpthread)
endif()
# If we're linking in full LLVM statically, ensure we don't export all LLVM symbols.
if (NOT MSVC AND DXIL_SPIRV_NATIVE_LLVM)
set_target_properties(dxil-spirv-c-shared PROPERTIES LINK_FLAGS "-Wl,--version-script ${CMAKE_CURRENT_SOURCE_DIR}/link.T")
endif()
add_library(dxil-spirv-c-static STATIC dxil_spirv_c.h dxil_spirv_c.cpp)
target_include_directories(dxil-spirv-c-static
PUBLIC
$
$)
target_link_libraries(dxil-spirv-c-static PRIVATE dxil-debug dxil-converter external::llvm dxil-utils)
target_compile_options(dxil-spirv-c-static PRIVATE ${DXIL_SPV_CXX_FLAGS})
set_target_properties(dxil-spirv-c-static PROPERTIES PUBLIC_HEADERS dxil_spirv_c.h)
set_target_properties(dxil-spirv-c-static PROPERTIES POSITION_INDEPENDENT_CODE ON)
if (DXIL_SPIRV_CLI)
add_library(cli-parser STATIC
third_party/cli_parser/cli_parser.hpp
third_party/cli_parser/cli_parser.cpp)
target_include_directories(cli-parser PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/third_party/cli_parser)
target_link_libraries(cli-parser PUBLIC dxil-debug)
target_compile_options(cli-parser PRIVATE ${DXIL_SPV_CXX_FLAGS})
add_executable(dxil-spirv dxil_spirv.cpp)
add_executable(dxil-extract dxil_extract.cpp)
target_link_libraries(dxil-spirv PRIVATE dxil-spirv-c-shared cli-parser SPIRV-Tools-static spirv-cross-c dxil-debug)
target_compile_options(dxil-spirv PRIVATE ${DXIL_SPV_CXX_FLAGS})
target_link_libraries(dxil-extract PRIVATE dxil-spirv-c-shared cli-parser external::llvm)
target_compile_options(dxil-extract PRIVATE ${DXIL_SPV_CXX_FLAGS})
if (WIN32 AND CMAKE_COMPILER_IS_GNUCXX)
target_link_libraries(dxil-spirv PRIVATE -static gcc stdc++ winpthread)
target_link_libraries(dxil-extract PRIVATE -static gcc stdc++ winpthread)
endif()
if (NOT DXIL_SPV_NATIVE_LLVM)
add_executable(dxbc-spirv-sandbox dxbc_spirv_sandbox.cpp)
target_link_libraries(dxbc-spirv-sandbox PRIVATE
dxil-utils dxil-debug llvm-bc dxil-converter
dxbc-spirv dxbc-spirv-test
spirv-cross-c SPIRV-Tools-static)
endif()
endif()
set(DXIL_SPV_VERSION_MAJOR 2)
set(DXIL_SPV_VERSION_MINOR 66)
set(DXIL_SPV_VERSION_PATCH 0)
set(DXIL_SPV_VERSION ${DXIL_SPV_VERSION_MAJOR}.${DXIL_SPV_VERSION_MINOR}.${DXIL_SPV_VERSION_PATCH})
set_target_properties(dxil-spirv-c-shared PROPERTIES
VERSION ${DXIL_SPV_VERSION}
SOVERSION ${DXIL_SPV_VERSION_MAJOR})
set(DXIL_SPV_INSTALL_LIB_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR})
set(DXIL_SPV_INSTALL_INC_DIR ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/dxil-spirv)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/pkg-config/dxil-spirv-c-shared.pc.in
${CMAKE_CURRENT_BINARY_DIR}/dxil-spirv-c-shared.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/dxil-spirv-c-shared.pc DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
if (DXIL_SPIRV_CLI)
install(TARGETS dxil-spirv RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
install(TARGETS dxil-extract RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif()
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dxil_spirv_c.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dxil-spirv)
install(TARGETS dxil-spirv-c-shared
EXPORT dxil_spirv_c_sharedConfig
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/dxil-spirv)
install(EXPORT dxil_spirv_c_sharedConfig DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/dxil_spirv_c_shared/cmake)
option(DXIL_SPV_MISC_CLI "Enable misc CLI apps." OFF)
if (DXIL_SPV_MISC_CLI)
add_executable(structurize-test misc/structurize_test.cpp)
target_link_libraries(structurize-test PRIVATE dxil-converter SPIRV-Tools-static spirv-cross-c dxil-debug dxil-utils)
target_compile_options(structurize-test PRIVATE ${DXIL_SPV_CXX_FLAGS})
endif()
================================================
FILE: DESCRIPTORS.md
================================================
# Full SM 6.0+ descriptor compatibility in Vulkan
In this document, I aim to rethink how we implement descriptors.
The goal is to efficiently implement descriptors even in bindless scenarios, i.e. SM 5.1/6.0+.
## Descriptor heaps in D3D12
The API lets you allocate a descriptor heap with N elements. Each element can be a SRV, UAV or CBV or any arbitrary type.
The API exposes some kind of "stride" here, which implies that max(sizeof(SRV), sizeof(UAV), sizeof(CBV)) is some value, i.e. 32 on drivers I've tested.
## Root signatures
Here we can specify up to 64 DWORDs (256 bytes) which gets passed to the shader.
- Descriptor table pointer: 1 DWORD, (not two? interesting ...)
- Root descriptor (UAV/CBV), apparently not bounds checked? (2 DWORD)
- Root constants (1 DWORD each)
First thought that comes to mind is that a descriptor table pointer can correlate to a descriptor set, but this will not work.
We only have 8 descriptor sets available. (4 is technically min-spec, but only some mobile chips expose that. I think it's fair to rely on 8.)
### Descriptor table pointer as an offset
A weird design of D3D12 is SetDescriptorHeaps which lets you bind only two heaps, one SRV/CBV/UAV heap and one SAMPLER heap, and all descriptor table pointers
must refer to one of these.
Looking at the descriptor table pointer only taking 1 DWORD this starts making sense. We should just encode offsets here into the two heaps.
SetDesciptorHeaps now becomes vkCmdBindDescriptorSets directly. The root signature becomes push constants (for 256 byte implementations),
or spills into a versioned uniform buffer (for 128 byte implementations and root sig > 128 bytes, which should be rare).
### Descriptor types
While descriptor types are kind of irrelevant in D3D12 inside heaps, we have very particular types in Vulkan.
`SAMPLED_IMAGE`, `UNIFORM_TEXEL_BUFFER`, `STORAGE_TEXEL_BUFFER`, `UNIFORM_BUFFER` and friends. Ideally, we'd have a "GENERAL" descriptor type which could be anything and we'd save on a lot of bloat in this scenario.
With a descriptor heap, we do not know the root signature yet, so we have two choices on how to allocate the descriptors, either with `VARIABLE_COUNT` or not.
With `VARIABLE_COUNT` we can declare descriptor set layouts which have the maximum number of bindings we expect to support (At least 1M according to Tier2),
and then allocating the descriptor pools we can allocate just the right amount of descriptors. This seems like the correct approach.
Two effects of this is that each descriptor type must live in their own descriptor sets, as only one descriptor binding can have VARYING count.
So far, we thus have 6 descriptor set layouts which will be common across all pipelines. Each set contains one binding, with VARYING size array of that type.
- Set0: `SAMPLED_IMAGE` - Texture
- Set1: `UNIFORM_TEXEL_BUFFER` - TypedBuffer, StructuredBuffer, ByteAddressBuffer
- Set2: `STORAGE_TEXEL_BUFFER` - RWTypedBuffer, RWStructuredBuffer, RWByteAddressBuffer. Descriptors come in pairs of two, the odd indices can deal with UAV counters.
- Set3: `STORAGE_IMAGE`
- Set4: `UNIFORM_BUFFER`
- Set5: `SAMPLER`
This leaves three sets which can be derived from a root signature directly. These include:
- Set6: Immutable samplers. It's useful to keep these in their own set since we don't have to deal with push descriptor restrictions of having to push immutable samplers
(and thus having to keep track of them as well).
- Set4 (reuse `UNIFORM_BUFFER` set): Virtualized bindings. These are bindings we have to repack from descriptor heaps to support implementations with few CBVs (like older Nvidia cards).
Due to RS 1.0 volatile descriptor behavior (descriptor needs only be valid in GPU timeline and can change anytime)
we need to defer the actual vkUpdateDescriptorSet calls to QueueSubmit() time. Using a descriptor update template here would be nice!
Virtualized bindings is currently the *only* path used by vkd3d and it crumbles down for any interesting uses of SM 5.1 and up, i.e. larger arrays of resources.
If we use virtualized descriptors, we can pilfer the set used for uniform buffers as that's the descriptor type we're going to virtualize anyways.
- Set7 (reuse `UNIFORM_BUFFER` set): Versioned push descriptor set. Here we can place:
- Root constants which spill outside maxPushConstantSize
- Root descriptors
For implementations which don't support push descriptors, we can fallback to a versioned descriptor set instead, just like vkd3d does.
#### Why not `STORAGE_BUFFER` for buffer UAVs?
Alignment is a big issue for SSBOs, especially on Nvidia. StructuredBuffers can be bound at very awkward alignments and only `STORAGE_TEXEL_BUFFER` of R32UI can express those.
This might lead us into an awkward path when dealing with 16-bit load/store in SM 6.2. Using physical storage buffers (PSB) for untyped buffers would be great, but we need to consider out-of-bounds behavior, which PSB does not support. Also, if we go the PSB route, we will have another indirection to consider. Since rather than going:
- Load UAV descriptor
- Load/Store data
we end up with:
- Load CBV/UAV descriptor
- Load PSB pointer
- Load/store data
## Sample shader
```
layout(push_constant) uniform RootConstants
{
uint descriptor_table_offset0;
uint descriptor_table_offset1;
uint descriptor_table_offset2;
uint descriptor_table_offset3;
uint root_constant0;
uint root_constant1;
uint root_constant2;
uint root_constant3;
} root;
// We can alias descriptors.
layout(set = 0, binding = 0) uniform texture2D Tex2D[];
layout(set = 0, binding = 0) uniform texture3D Tex3D[];
layout(set = 1, binding = 0) textureBuffer TypedBuffers[];
layout(set = 1, binding = 0) textureBuffer StructuredBuffers[];
layout(set = 1, binding = 0) textureBuffer ByteAddressBuffers[];
layout(set = 2, binding = 0) imageBuffer RWTypedBuffers[];
layout(set = 2, binding = 1, r32ui) uimageBuffer RWStructureBuffers[];
layout(set = 2, binding = 2, r32ui) uimageBuffer RWByteAddressBuffers[];
layout(set = 3, binding = 0) uniform image2D RWTex2D[];
layout(set = 3, binding = 0) uniform image3D RWTex3D[];
#if SUPPORTS_MANY_CBVS
layout(set = 4, binding = 0, std140) uniform UBOs
{
vec4 data[MAX_SIZE];
} CBV[];
#else
// Versioned descriptors.
layout(set = 4, binding = 0, std140) uniform UBO0
{
vec4 data[MAX_SIZE];
} ubo0;
layout(set = 4, binding = 1, std140) uniform UBO0
{
vec4 data[MAX_SIZE];
} ubo0;
#endif
layout(set = 5, binding = 0) uniform sampler DynamicSamplers[];
layout(set = 6, binding = 0) uniform sampler ImmutableSampler0;
layout(set = 6, binding = 1) uniform sampler ImmutableSampler1;
layout(set = 6, binding = 2) uniform sampler ImmutableSampler2;
// Root descriptors.
layout(set = 7, binding = 0) uniform RootCBV0
{
vec4 data[MAX_SIZE];
} root_cbv0;
layout(set = 7, binding = 1) uniform RootCBV1
{
vec4 data[MAX_SIZE];
} root_cbv1;
void main()
{
const uint OffsetIntoRootTable = 42; // This is deduced from D3D12_DESCRIPTOR_RANGE.
// descriptor_table_offset is offset into a SetDescriptorHeaps, which we can find by looking at
// SetGraphicsRootDescriptor table compared to SetDescriptorHeaps.
// Tack on nonuniformEXT as required by IL.
texelFetch(Tex2D[OffsetIntoRootTable + root.descriptor_table_offset1]);
}
================================================
FILE: LICENSE.MIT
================================================
Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
SPDX-License-Identifier: MIT
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
For third_party/bc-decoder:
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2020 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
For third_party/glslang-spirv (glslang):
--------------------------------------------------------------------------------
The MIT License
--------------------------------------------------------------------------------
Copyright 2020 The Khronos Group Inc
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# dxil-spirv
This project aims to provide translation of DXIL (SM 6.x) shaders to SPIR-V which can be used in the vkd3d project,
which implements D3D12 on top of Vulkan.
Using [dxbc-spirv](https://github.com/doitsujin/dxbc-spirv) it also handles legacy DXBC shaders.
## Building
### Dependencies
Check out submodules first with `git submodule update --init --recursive`.
No external dependencies apart from the submodules are required to build.
This project implements a "small" LLVM C++ API subset which acts as a drop-in replacement for the full LLVM.
It is possible to build against the true LLVM C++ API if llvm is checked out in `external/llvm` and `-DDXIL_SPIRV_NATIVE_LLVM=ON` CMake option is used.
See `checkout_llvm.sh` script.
### Build
Standard CMake build.
```shell
mkdir build
cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
cmake --build . --config Release
```
## Linking against dxil-spirv
Only the C API is installed and is expected to be kept ABI/API stable when it releases.
### pkg-config
```shell
pkg-config dxil-spirv-c-shared --cflags --libs
```
### CMake module
Something like:
```
find_package(dxil_spirv_c_shared)
if (dxil_spirv_c_shared_FOUND)
message("Found dxil-spirv! Enabling DXIL support.")
target_link_libraries(vkd3d-shader PRIVATE dxil-spirv-c-shared)
target_compile_definitions(vkd3d-shader PRIVATE HAVE_DXIL_SPV)
target_sources(vkd3d-shader PRIVATE vkd3d/libs/vkd3d-shader/dxil.c)
else()
message("Did not find dxil-spirv :( Disabling DXIL support.")
endif()
```
## Testing
The primary method of testing dxil-spirv and avoiding regressions is through a reference shader suite.
### Build DXC
First, build DXC. To keep output consistent, we must use a fixed version of DXC.
Currently, this only works on Linux, the Windows build of DXC does not seem to support CMake properly.
```shell
./checkout_dxc.sh
./build_dxc.sh
```
The test suite accepts an arbitrary path to DXC, so if you have a standalone binary somewhere, that can work as well.
### Run test suite
When adding new tests, place the HLSL test in `shaders/` somewhere and run:
```shell
./test_shaders.py shaders --dxc external/dxc-build/bin/dxc --dxil-spirv cmake-build-debug/dxil-spirv
```
If there is any mismatch, the test script will complain. If there are legitimate changes to be made,
add `--update` to the command. The updated files should now be committed alongside the dxil-spirv change.
`--parallel` can (and should) be used to speed up the process.
To update DXBC references, run:
```shell
./cmake-build-debug/dxbc-spirv-sandbox ./reference-dxbc
```
### Running large repro suites
For internal development, we also have an extensive repro suite which cover real-world content.
These cannot be made public for obvious reasons, so the intent is that symlinks are set up during development.
Shaders can be dumped with `VKD3D_SHADER_DUMP_PATH`.
```shell
# The scripts might not work properly if the paths aren't laid out like this.
ln -s ${DXIL_SPIRV_REPO}/shaders shaders-dxil
ln -s ${DXBC_SPIRV_REPO}/shaders shaders-dxbc
ln -s ${DXIL_SPIRV_REPO}/reference/shaders reference/shaders-dxil
ln -s ${DXBC_SPIRV_REPO}/reference/shaders reference/shaders-dxbc
./test_shaders.py shaders-dxil --dxil-spirv cmake-build-release/dxil-spirv --parallel --update
./test_shaders.py shaders-dxbc --dxil-spirv cmake-build-release/dxil-spirv --parallel --update
```
To import shaders into the suite:
```shell
mkdir shaders-dxil/dxilgame
mkdir shaders-dxbc/dxbcgame
# For DXIL
./copy_reference_shaders.py --dxil /tmp/path/to/vkd3d-shader-dump-path --raw --output shaders-dxil/dxilgame
# For DXBC
./copy_reference_shaders.py --dxbc /tmp/path/to/vkd3d-shader-dump-path --raw --output shaders-dxbc/dxbcgame
```
To run an isolated subfolder only, there's `--subfolder`.
## License
dxil-spirv is currently licensed as MIT. See LICENSE.MIT for more details.
```c
/* Copyright (c) 2019-2025 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
```
================================================
FILE: bc/CMakeLists.txt
================================================
add_library(llvm-bc STATIC
cast.hpp iterator.hpp
data_structures.hpp
value.hpp value.cpp
instruction.hpp instruction.cpp
function.hpp function.cpp
context.hpp context.cpp
type.hpp type.cpp
module.hpp module.cpp module_dxbc_ir.cpp
metadata.hpp metadata.cpp
disassembler.cpp)
target_compile_options(llvm-bc PRIVATE ${DXIL_SPV_CXX_FLAGS})
target_compile_definitions(llvm-bc PUBLIC HAVE_LLVMBC)
target_link_libraries(llvm-bc PRIVATE bc-decoder dxil-debug dxil-utils)
target_include_directories(llvm-bc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
set_target_properties(llvm-bc PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(llvm-bc PRIVATE dxbc-spirv)
================================================
FILE: bc/cast.hpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "logging.hpp"
#include "metadata.hpp"
#include "type.hpp"
#include "value.hpp"
#include
namespace LLVMBC
{
struct ModuleParseContext;
template
inline T *cast(Type *type)
{
if (type->getTypeID() != T::get_type_id())
{
LOGE("Invalid type ID in cast.\n");
std::terminate();
}
return static_cast(type);
}
template
inline const T *cast(const Type *type)
{
if (type->getTypeID() != T::get_type_id())
{
LOGE("Invalid type ID in cast.\n");
std::terminate();
}
return static_cast(type);
}
template
inline T *dyn_cast(Type *type)
{
if (!type)
return nullptr;
if (type->getTypeID() != T::get_type_id())
return nullptr;
else
return static_cast(type);
}
template
inline const T *dyn_cast(const Type *type)
{
if (!type)
return nullptr;
if (type->getTypeID() != T::get_type_id())
return nullptr;
else
return static_cast(type);
}
template
inline bool isa(const Type *type)
{
return type->getTypeID() == T::get_type_id();
}
class ValueProxy : public Value
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Proxy;
}
ValueProxy(Type *type, ModuleParseContext &context, uint64_t id);
Value *get_proxy_value() const;
bool resolve();
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
uint64_t id;
ModuleParseContext &context;
Value *proxy = nullptr;
};
namespace Internal
{
inline Value *resolve_proxy(Value *value);
inline const Value *resolve_proxy(const Value *value);
} // namespace Internal
template
inline T *cast(Value *value)
{
if (T::get_value_kind() != ValueKind::Proxy)
value = Internal::resolve_proxy(value);
if (T::is_base_of_value_kind(value->get_value_kind()))
return static_cast(value);
else
{
LOGE("Invalid type ID in cast.\n");
std::terminate();
}
}
template
inline const T *cast(const Value *value)
{
if (T::get_value_kind() != ValueKind::Proxy)
value = Internal::resolve_proxy(value);
if (T::is_base_of_value_kind(value->get_value_kind()))
return static_cast(value);
else
{
LOGE("Invalid type ID in cast.\n");
std::terminate();
}
}
template
inline T *dyn_cast(Value *value)
{
if (!value)
return nullptr;
if (T::get_value_kind() != ValueKind::Proxy)
value = Internal::resolve_proxy(value);
if (T::is_base_of_value_kind(value->get_value_kind()))
return static_cast(value);
else
return nullptr;
}
template
inline const T *dyn_cast(const Value *value)
{
if (!value)
return nullptr;
if (T::get_value_kind() != ValueKind::Proxy)
value = Internal::resolve_proxy(value);
if (T::is_base_of_value_kind(value->get_value_kind()))
return static_cast(value);
else
return nullptr;
}
template
inline bool isa(const Value *value)
{
if (T::get_value_kind() != ValueKind::Proxy)
value = Internal::resolve_proxy(value);
return T::is_base_of_value_kind(value->get_value_kind());
}
namespace Internal
{
inline Value *resolve_proxy(Value *value)
{
while (value && value->get_value_kind() == ValueKind::Proxy)
value = cast(value)->get_proxy_value();
return value;
}
inline const Value *resolve_proxy(const Value *value)
{
while (value && value->get_value_kind() == ValueKind::Proxy)
value = cast(value)->get_proxy_value();
return value;
}
} // namespace Internal
template
inline T *cast(MDOperand &md)
{
if (md.get_metadata_kind() == T::get_metadata_kind())
return static_cast(&md);
else
{
LOGE("Invalid type ID in cast.\n");
std::terminate();
}
}
template
inline T *cast(MDOperand *md)
{
if (md->get_metadata_kind() == T::get_metadata_kind())
return static_cast(md);
else
{
LOGE("Invalid type ID in cast.\n");
std::terminate();
}
}
template
inline const T *cast(const MDOperand &md)
{
if (md.get_metadata_kind() == T::get_metadata_kind())
return static_cast(&md);
else
{
LOGE("Invalid type ID in cast.\n");
std::terminate();
}
}
template
inline const T *cast(const MDOperand *md)
{
if (md->get_metadata_kind() == T::get_metadata_kind())
return static_cast(md);
else
{
LOGE("Invalid type ID in cast.\n");
std::terminate();
}
}
template
inline T *dyn_cast(MDOperand &md)
{
if (md.get_metadata_kind() == T::get_metadata_kind())
return static_cast(&md);
else
return nullptr;
}
template
inline T *dyn_cast(MDOperand *md)
{
if (!md)
return nullptr;
if (md->get_metadata_kind() == T::get_metadata_kind())
return static_cast(md);
else
return nullptr;
}
template
inline const T *dyn_cast(const MDOperand &md)
{
if (md.get_metadata_kind() == T::get_metadata_kind())
return static_cast(&md);
else
return nullptr;
}
template
inline const T *dyn_cast(const MDOperand *md)
{
if (!md)
return nullptr;
if (md->get_metadata_kind() == T::get_metadata_kind())
return static_cast(md);
else
return nullptr;
}
template
inline bool isa(const MDOperand &md)
{
return md.get_metadata_kind() == T::get_metadata_kind();
}
template
inline bool isa(const MDOperand *md)
{
return md->get_metadata_kind() == T::get_metadata_kind();
}
} // namespace LLVMBC
================================================
FILE: bc/context.cpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "context.hpp"
#include
namespace LLVMBC
{
LLVMContext::LLVMContext()
{
}
LLVMContext::~LLVMContext()
{
for (size_t i = typed_allocations.size(); i; i--)
typed_allocations[i - 1]->run();
for (size_t i = raw_allocations.size(); i; i--)
dxil_spv::free_in_thread(raw_allocations[i - 1]);
}
void *LLVMContext::allocate_from_chain(uintptr_t size, uintptr_t align)
{
current_block = (current_block + align - 1) & ~(align - 1);
if (current_block + size <= current_block_end)
{
void *ret = reinterpret_cast(current_block);
current_block += size;
return ret;
}
else
{
current_block = 0;
current_block_end = 0;
return nullptr;
}
}
void LLVMContext::allocate_new_chain(size_t size, size_t align)
{
size_t min_size = size + align;
if (min_size < 64 * 1024)
min_size = 64 * 1024;
void *ptr = dxil_spv::allocate_in_thread(min_size);
if (ptr)
{
raw_allocations.push_back(ptr);
current_block = reinterpret_cast(ptr);
current_block_end = current_block + min_size;
}
else
{
current_block = 0;
current_block_end = 0;
}
}
void *LLVMContext::allocate(size_t size, size_t align)
{
void *ptr = allocate_from_chain(size, align);
if (!ptr)
{
allocate_new_chain(size, align);
ptr = allocate_from_chain(size, align);
}
return ptr;
}
} // namespace LLVMBC
================================================
FILE: bc/context.hpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "data_structures.hpp"
#include
#include
#include
namespace LLVMBC
{
class Type;
class LLVMContext
{
public:
LLVMContext();
~LLVMContext();
void operator=(const LLVMContext &) = delete;
LLVMContext(const LLVMContext &) = delete;
template
T *construct(U &&... u)
{
T *mem = static_cast(allocate(sizeof(T), alignof(T)));
if (!mem)
std::terminate();
T *t = new (mem) T(std::forward(u)...);
if (!std::is_trivially_destructible::value)
append_typed_destructor(t);
return t;
}
template
T *construct_n(size_t n, const U &... u)
{
T *mem = static_cast(allocate(sizeof(T) * n, alignof(T)));
if (!mem)
std::terminate();
for (size_t i = 0; i < n; i++)
{
T *tmp = new (&mem[i]) T(u...);
if (!std::is_trivially_destructible::value)
append_typed_destructor(tmp);
}
return mem;
}
Vector &get_type_cache()
{
return type_cache;
}
private:
void *allocate(size_t size, size_t align);
struct Deleter
{
virtual ~Deleter() = default;
virtual void run() = 0;
};
template
struct TypedDeleter : Deleter
{
explicit TypedDeleter(T *ptr_)
: ptr(ptr_)
{
}
void run() override
{
ptr->~T();
}
T *ptr;
};
uintptr_t current_block = 0;
uintptr_t current_block_end = 0;
void *allocate_from_chain(uintptr_t size, uintptr_t align);
void allocate_new_chain(size_t size, size_t align);
Vector raw_allocations;
Vector typed_allocations;
Vector type_cache;
template
T *construct_trivial(U &&... u)
{
T *mem = static_cast(allocate(sizeof(T), alignof(T)));
if (!mem)
std::terminate();
T *t = new (mem) T(std::forward(u)...);
return t;
}
template
void append_typed_destructor(T *ptr)
{
typed_allocations.push_back(construct_trivial>(ptr));
}
};
} // namespace LLVMBC
================================================
FILE: bc/data_structures.hpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "thread_local_allocator.hpp"
namespace LLVMBC
{
template
using Vector = dxil_spv::Vector;
template
using UnorderedSet = dxil_spv::UnorderedSet;
template
using UnorderedMap = dxil_spv::UnorderedMap;
using String = dxil_spv::String;
using StringStream = dxil_spv::StringStream;
}
================================================
FILE: bc/disassembler.cpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "cast.hpp"
#include "context.hpp"
#include "function.hpp"
#include "instruction.hpp"
#include "metadata.hpp"
#include "module.hpp"
#include "type.hpp"
#include "value.hpp"
#include
#include
#include
namespace LLVMBC
{
struct StreamState
{
StringStream stream;
unsigned indent = 0;
void append(Type *type);
void append(IntegerType *type);
void append(PointerType *type);
void append(ArrayType *type);
void append(StructType *type);
void append(FunctionType *type);
void append(VectorType *type);
void append(const String &str);
void append(Value *value, bool decl = false);
void append(GlobalVariable *value, bool decl = false);
void append(Instruction *value);
void append(Argument *value, bool decl = false);
void append(ShuffleVectorInst *shuf, bool decl = false);
void append(ExtractElementInst *extr, bool decl = false);
void append(InsertElementInst *inst, bool decl = false);
void append(Function *value, bool decl = false);
void append(BinaryOperator *value, bool decl = false);
void append(UnaryOperator *uop, bool decl = false);
void append(CallInst *value, bool decl = false);
void append(BranchInst *value, bool decl = false);
void append(SwitchInst *branch, bool decl = false);
void append(ReturnInst *value, bool decl = false);
void append(UndefValue *value, bool decl = false);
void append(Constant *value, bool decl = false);
void append(ConstantInt *value, bool decl = false);
void append(ConstantFP *value, bool decl = false);
void append(BasicBlock *bb, bool decl = false);
void append(FCmpInst *value, bool decl = false);
void append(ICmpInst *value, bool decl = false);
void append(PHINode *value, bool decl = false);
void append(CastInst *value, bool decl = false);
void append(SelectInst *value, bool decl = false);
void append(ExtractValueInst *value, bool decl = false);
void append(AllocaInst *value, bool decl = false);
void append(GetElementPtrInst *value, bool decl = false);
void append(LoadInst *value, bool decl = false);
void append(StoreInst *value, bool decl = false);
void append(AtomicRMWInst *value, bool decl = false);
void append(AtomicCmpXchgInst *xchg, bool decl = false);
void append(ConstantAggregate *agg, bool decl = false);
void append(ConstantAggregateZero *zero, bool decl = false);
void append(ConstantDataArray *data, bool decl = false);
void append(ConstantDataVector *vec, bool decl = false);
void append(ConstantExpr *expr, bool decl = false);
void append(MDOperand *md);
void append(NamedMDNode *md);
void append(MDNode *md, bool decl = false);
void append(float v);
void append(double v);
void append(bool v);
void append(const char *str);
void newline();
void newline_noindent();
void begin_scope();
void end_scope();
template
void append(T &&t, Ts &&... ts)
{
append(std::forward(t));
append(std::forward(ts)...);
}
// Only want this overload to trigger on various integer types.
template
typename std::enable_if::value, void>::type append(T value)
{
stream << value;
}
// Need this to avoid the generic template to be deduced.
template
void append(char (&str)[N])
{
return append(static_cast(str));
}
};
void StreamState::append(IntegerType *type)
{
append("i", type->getBitWidth());
}
void StreamState::append(StructType *type)
{
append("{ ");
for (unsigned i = 0; i < type->getNumElements(); i++)
{
append(type->getElementType(i));
if (i + 1 < type->getNumElements())
append(", ");
}
append(" }");
}
void StreamState::append(PointerType *type)
{
if (type->getAddressSpace() != 0)
append(type->getElementType(), " addrspace(", type->getAddressSpace(), ")*");
else
append(type->getElementType(), "*");
}
void StreamState::append(ArrayType *type)
{
append("[", type->getArrayNumElements(), " x ", type->getArrayElementType(), "]");
}
void StreamState::append(FunctionType *type)
{
append("(", type->getReturnType(), " (*) (");
for (unsigned i = 0; i < type->getNumParams(); i++)
{
append(type->getParamType(i));
if (i + 1 < type->getNumParams())
append(", ");
}
append("))");
}
void StreamState::append(VectorType *type)
{
append(type->getElementType(), "x", type->getVectorSize());
}
void StreamState::append(bool v)
{
stream << (v ? "true" : "false");
}
void StreamState::append(float v)
{
char buf[1024];
sprintf(buf, "%e", v);
append(buf);
}
void StreamState::append(double v)
{
char buf[1024];
sprintf(buf, "%e", v);
append(buf);
}
void StreamState::newline()
{
stream << "\n";
for (unsigned i = 0; i < indent; i++)
stream << " ";
}
void StreamState::newline_noindent()
{
stream << "\n";
}
void StreamState::append(const char *str)
{
stream << str;
}
void StreamState::append(const String &str)
{
stream << str;
}
void StreamState::begin_scope()
{
append(" {");
indent++;
}
void StreamState::end_scope()
{
assert(indent > 0);
indent--;
newline();
append("}");
}
void StreamState::append(Type *type)
{
switch (type->getTypeID())
{
case Type::TypeID::IntegerTyID:
return append(cast(type));
case Type::TypeID::PointerTyID:
return append(cast(type));
case Type::TypeID::StructTyID:
return append(cast(type));
case Type::TypeID::ArrayTyID:
return append(cast(type));
case Type::TypeID::FunctionTyID:
return append(cast(type));
case Type::TypeID::VectorTyID:
return append(cast(type));
case Type::TypeID::HalfTyID:
return append("half");
case Type::TypeID::FloatTyID:
return append("float");
case Type::TypeID::DoubleTyID:
return append("double");
case Type::TypeID::Unknown:
return append("unknown");
case Type::TypeID::VoidTyID:
return append("void");
case Type::TypeID::OpaqueTyID:
return append("opaque");
default:
break;
}
LOGE("Unknown Type %u.\n", unsigned(type->getTypeID()));
}
void StreamState::append(ShuffleVectorInst *shuf, bool decl)
{
if (decl)
{
append("%", shuf->get_tween_id(), " = shufflevector ", shuf->getType(), " ", shuf->getOperand(0), ", ", shuf->getOperand(1), " <");
auto *vec_type = cast(shuf->getType());
for (unsigned i = 0; i < vec_type->getVectorSize(); i++)
{
append(shuf->getMaskValue(i));
if (i + 1 < vec_type->getVectorSize())
append(", ");
}
append(">");
}
else
append("%", shuf->get_tween_id());
}
void StreamState::append(ExtractElementInst *extr, bool decl)
{
if (decl)
{
append("%", extr->get_tween_id(), " = extractelement ",
extr->getType(), " ", extr->getVectorOperand(), ", ", extr->getIndexOperand());
}
else
append("%", extr->get_tween_id());
}
void StreamState::append(InsertElementInst *inst, bool decl)
{
if (decl)
{
append("%", inst->get_tween_id(), " = insertelement ",
inst->getOperand(0), ", ", inst->getOperand(1), ", ", inst->getOperand(2));
}
else
append("%", inst->get_tween_id());
}
void StreamState::append(Argument *arg, bool decl)
{
append("%arg", arg->getArgNo());
}
void StreamState::append(Function *func, bool decl)
{
if (decl)
{
append("define ", func->getType(), " @", func->getName(), "(");
auto *type = func->getFunctionType();
for (unsigned i = 0; i < type->getNumParams(); i++)
{
append(type->getParamType(i));
if (i + 1 < type->getNumParams())
append(", ");
}
append(")");
if (func->begin() != func->end())
{
begin_scope();
for (auto &bb : *func)
append(&bb, true);
end_scope();
}
}
else
append("@", func->getName());
}
void StreamState::append(GlobalVariable *var, bool decl)
{
if (decl)
{
append("@", var->get_tween_id(), " = ");
if (cast(var->getType())->getAddressSpace() != 0)
append("groupshared ");
else
append(var->isConstant() ? "constant" : "global", " ");
append(var->getType()->getPointerElementType());
if (var->hasInitializer())
append(" ", var->getInitializer());
newline();
}
else
{
append("@", var->get_tween_id());
}
}
static const char *to_string(BinaryOperator::BinaryOps op)
{
switch (op)
{
#define BINOP(op, str) \
case BinaryOperator::BinaryOps::op: \
return str
BINOP(InvalidBinaryOp, "invalid");
BINOP(Add, "add");
BINOP(FAdd, "fadd");
BINOP(Sub, "sub");
BINOP(FSub, "fsub");
BINOP(Mul, "mul");
BINOP(FMul, "fmul");
BINOP(UDiv, "udiv");
BINOP(SDiv, "sdiv");
BINOP(FDiv, "fdiv");
BINOP(URem, "urem");
BINOP(SRem, "srem");
BINOP(FRem, "frem");
BINOP(Shl, "shl");
BINOP(LShr, "lshr");
BINOP(AShr, "ashr");
BINOP(And, "and");
BINOP(Or, "or");
BINOP(Xor, "xor");
}
#undef BINOP
return "???";
}
static const char *to_string(UnaryOperator::UnaryOps op)
{
switch (op)
{
case UnaryOperator::UnaryOps::FNeg:
return "fneg";
default:
return "invalid";
}
}
static const char *to_string(Instruction::Predicate pred)
{
switch (pred)
{
#define PRED(op, str) \
case Instruction::FCMP_##op: \
return str
PRED(FALSE, "false");
PRED(OEQ, "oeq");
PRED(OGT, "ogt");
PRED(OGE, "oge");
PRED(OLT, "olt");
PRED(OLE, "ole");
PRED(ONE, "one");
PRED(ORD, "ord");
PRED(UNO, "uno");
PRED(UEQ, "ueq");
PRED(UGT, "ugt");
PRED(UGE, "uge");
PRED(ULT, "ult");
PRED(ULE, "ule");
PRED(UNE, "une");
PRED(TRUE, "true");
#undef PRED
#define PRED(op, str) \
case Instruction::ICMP_##op: \
return str
PRED(EQ, "eq");
PRED(NE, "ne");
PRED(UGT, "ugt");
PRED(UGE, "uge");
PRED(ULT, "ult");
PRED(ULE, "ule");
PRED(SGT, "sgt");
PRED(SGE, "sge");
PRED(SLT, "slt");
PRED(SLE, "sle");
}
#undef PRED
return "???";
}
static const char *to_string(Instruction::CastOps op)
{
switch (op)
{
#define CAST(op, str) \
case Instruction::op: \
return str
CAST(Trunc, "trunc");
CAST(ZExt, "zext");
CAST(SExt, "sext");
CAST(FPToUI, "fptoui");
CAST(FPToSI, "fptosi");
CAST(UIToFP, "uitofp");
CAST(SIToFP, "sitofp");
CAST(FPTrunc, "fptrunc");
CAST(FPExt, "fpext");
CAST(PtrToInt, "ptrtoint");
CAST(IntToPtr, "inttoptr");
CAST(BitCast, "bitcast");
CAST(AddrSpaceCast, "addrspacecast");
default:
break;
}
#undef CAST
return "???";
}
static const char *to_string(AtomicRMWInst::BinOp op)
{
switch (op)
{
#define RMW(op, str) \
case AtomicRMWInst::BinOp::op: \
return str
RMW(Add, "add");
RMW(Sub, "sub");
RMW(Xchg, "xchg");
RMW(And, "and");
RMW(Xor, "xor");
RMW(Or, "or");
RMW(Nand, "nand");
RMW(Max, "max");
RMW(Min, "min");
RMW(UMax, "umax");
RMW(UMin, "umin");
RMW(FAdd, "fadd");
RMW(FSub, "fsub");
default:
break;
}
#undef RMW
return "???";
}
void StreamState::append(BinaryOperator *binop, bool decl)
{
if (decl)
{
append("%", binop->get_tween_id(), " = ", to_string(binop->getOpcode()), " ", binop->getType(), " ",
binop->getOperand(0), ", ", binop->getOperand(1));
}
else
{
append("%", binop->get_tween_id());
}
}
void StreamState::append(UnaryOperator *uop, bool decl)
{
if (decl)
{
append("%", uop->get_tween_id(), " = ", to_string(uop->getOpcode()), " ", uop->getType(), " ",
uop->getOperand(0), ", ", uop->getOperand(1));
}
else
{
append("%", uop->get_tween_id());
}
}
void StreamState::append(BasicBlock *bb, bool decl)
{
if (decl)
{
newline_noindent();
newline_noindent();
append(bb->get_tween_id(), ":");
for (auto &inst : *bb)
{
newline();
append(&inst);
}
}
else
{
append("label %", bb->get_tween_id());
}
}
void StreamState::append(FCmpInst *value, bool decl)
{
if (decl)
{
append("%", value->get_tween_id(), " = fcmp ", to_string(value->getPredicate()), " ", value->getOperand(0),
", ", value->getOperand(1));
}
else
{
append("%", value->get_tween_id());
}
}
void StreamState::append(ICmpInst *value, bool decl)
{
if (decl)
{
append("%", value->get_tween_id(), " = icmp ", to_string(value->getPredicate()), " ", value->getOperand(0),
", ", value->getOperand(1));
}
else
{
append("%", value->get_tween_id());
}
}
void StreamState::append(BranchInst *br, bool)
{
append("br ");
if (br->getCondition())
append(br->getCondition(), ", ", br->getSuccessor(0), ", ", br->getSuccessor(1));
else
append(br->getSuccessor(0));
}
void StreamState::append(SwitchInst *branch, bool)
{
append("switch ", branch->getCondition(), ", ", branch->getDefaultDest());
begin_scope();
for (auto itr = branch->case_begin(); itr != branch->case_end(); ++itr)
{
newline();
append(itr->getCaseValue(), ", ", itr->getCaseSuccessor());
}
end_scope();
}
void StreamState::append(CallInst *call, bool decl)
{
if (decl)
{
if (call->getType()->getTypeID() != Type::TypeID::VoidTyID)
append("%", call->get_tween_id(), " = ");
append("call ", call->getType(), " @", call->getCalledFunction()->getName(), "(");
for (unsigned i = 0; i < call->getNumOperands(); i++)
{
append(call->getOperand(i));
if (i + 1 < call->getNumOperands())
append(", ");
}
append(")");
for (auto itr = call->metadata_begin(); itr != call->metadata_end(); ++itr)
{
append(" !", itr->first, " ", itr->second);
}
}
else
{
append("%", call->get_tween_id());
}
}
void StreamState::append(CastInst *cast, bool decl)
{
if (decl)
{
append("%", cast->get_tween_id(), " = ", to_string(cast->getOpcode()), " ", cast->getOperand(0), " to ",
cast->getType());
}
else
{
append("%", cast->get_tween_id());
}
}
void StreamState::append(SelectInst *cast, bool decl)
{
if (decl)
{
append("%", cast->get_tween_id(), " = ", "select ", cast->getOperand(0), ", ", cast->getOperand(1), ", ",
cast->getOperand(2));
}
else
{
append("%", cast->get_tween_id());
}
}
void StreamState::append(ExtractValueInst *ext, bool decl)
{
if (decl)
{
append("%", ext->get_tween_id(), " = ", "extractvalue ", ext->getType(), " ", ext->getAggregateOperand());
for (unsigned i = 0; i < ext->getNumIndices(); i++)
{
append(", ");
append(ext->getIndices()[i]);
}
}
else
{
append("%", ext->get_tween_id());
}
}
void StreamState::append(AllocaInst *alloca, bool decl)
{
if (decl)
{
append("%", alloca->get_tween_id(), " = alloca ", cast(alloca->getType())->getElementType());
}
else
{
append("%", alloca->get_tween_id());
}
}
void StreamState::append(GetElementPtrInst *ptr, bool decl)
{
if (decl)
{
append("%", ptr->get_tween_id(), " = getelementptr ", ptr->isInBounds() ? "inbounds " : "", ptr->getType());
for (unsigned i = 0; i < ptr->getNumOperands(); i++)
{
append(", ");
append(ptr->getOperand(i));
}
}
else
{
append("%", ptr->get_tween_id());
}
}
void StreamState::append(LoadInst *ptr, bool decl)
{
if (decl)
append("%", ptr->get_tween_id(), " = load ", ptr->getType(), " ", ptr->getPointerOperand());
else
append("%", ptr->get_tween_id());
}
void StreamState::append(StoreInst *ptr, bool decl)
{
if (decl)
append("store ", ptr->getOperand(0), ", ", ptr->getOperand(1));
else
append("%", ptr->get_tween_id());
}
void StreamState::append(AtomicRMWInst *atomic_op, bool decl)
{
if (decl)
{
append("%", atomic_op->get_tween_id(), " = atomicrmw ", to_string(atomic_op->getOperation()), " ",
atomic_op->getType(), " ", atomic_op->getPointerOperand(), ", ", atomic_op->getValOperand());
}
else
append("%", atomic_op->get_tween_id());
}
void StreamState::append(AtomicCmpXchgInst *xchg, bool decl)
{
if (decl)
{
append("%", xchg->get_tween_id(), " = cmpxchg ", xchg->getType(), " ", xchg->getPointerOperand(), ", ",
xchg->getCompareOperand(), ", ", xchg->getNewValOperand());
}
else
append("%", xchg->get_tween_id());
}
void StreamState::append(ConstantAggregate *agg, bool)
{
append("[");
if (agg->getNumOperands())
append(agg->getOperand(0));
for (unsigned i = 1; i < agg->getNumOperands(); i++)
append(", ", agg->getOperand(i));
append("]");
}
void StreamState::append(ConstantAggregateZero *zero, bool)
{
append("[zeroinitialized]");
}
void StreamState::append(ConstantDataArray *arr, bool)
{
append("[");
for (unsigned i = 0; i < arr->getNumElements(); i++)
{
append(arr->getElementAsConstant(i));
if (i + 1 < arr->getNumElements())
append(", ");
}
append("]");
}
void StreamState::append(ConstantDataVector *vec, bool)
{
append("<");
for (unsigned i = 0; i < vec->getNumElements(); i++)
{
append(vec->getElementAsConstant(i));
if (i + 1 < vec->getNumElements())
append(", ");
}
append(">");
}
void StreamState::append(ConstantExpr *expr, bool decl)
{
if (decl)
{
append("%", expr->get_tween_id(), " = ", expr->getOpcode(), " ", expr->getType());
if (expr->getNumOperands())
append(" ", expr->getOperand(0));
for (unsigned i = 1; i < expr->getNumOperands(); i++)
append(", ", expr->getOperand(i));
}
else
{
append("%", expr->get_tween_id());
}
}
void StreamState::append(PHINode *phi, bool decl)
{
if (decl)
{
append("%", phi->get_tween_id(), " = phi ", phi->getType(), " ");
unsigned count = phi->getNumIncomingValues();
for (unsigned i = 0; i < count; i++)
{
Value *value = phi->getIncomingValue(i);
BasicBlock *bb = phi->getIncomingBlock(i);
append("[ ", value, ", ", bb, " ]");
if (i + 1 < count)
append(", ");
}
}
else
{
append("%", phi->get_tween_id());
}
}
void StreamState::append(ReturnInst *value, bool)
{
if (value->getReturnValue())
append("ret ", value);
else
append("ret void");
}
void StreamState::append(UndefValue *undef, bool decl)
{
append(undef->getType(), " undef");
}
void StreamState::append(ConstantFP *value, bool decl)
{
append(value->getValueAPF().convertToDouble());
}
void StreamState::append(ConstantInt *value, bool decl)
{
append(value->getType(), " ", value->getUniqueInteger().getSExtValue());
}
void StreamState::append(Constant *value, bool decl)
{
append(static_cast(value), decl);
}
void StreamState::append(Instruction *inst)
{
append(static_cast(inst), true);
}
void StreamState::append(MDNode *md, bool decl)
{
if (md)
{
if (decl)
{
append("!", md->get_tween_id(), " = !{");
for (unsigned i = 0; i < md->getNumOperands(); i++)
{
append(&md->getOperand(i));
if (i + 1 < md->getNumOperands())
append(", ");
}
append("}");
}
else
append("!", md->get_tween_id());
}
else
append("null");
}
void StreamState::append(NamedMDNode *md)
{
append("!", md->getName(), " = !{");
for (unsigned i = 0; i < md->getNumOperands(); i++)
{
append(md->getOperand(i), false);
if (i + 1 < md->getNumOperands())
append(", ");
}
append("}");
}
void StreamState::append(MDOperand *md)
{
if (md)
{
switch (md->get_metadata_kind())
{
case MetadataKind::NamedNode:
return append(cast(md));
case MetadataKind::Node:
return append(cast(md), false);
case MetadataKind::Constant:
return append(cast(md)->getValue());
case MetadataKind::String:
return append("\"", cast(md)->getString(), "\"");
case MetadataKind::None:
return append("null");
default:
LOGE("Unknown MetadataKind %u.\n", unsigned(md->get_metadata_kind()));
break;
}
}
else
append("null");
}
void StreamState::append(Value *value, bool decl)
{
switch (value->get_value_kind())
{
case ValueKind::Argument:
return append(cast(value), decl);
case ValueKind::Function:
return append(cast(value), decl);
case ValueKind::BinaryOperator:
return append(cast(value), decl);
case ValueKind::UnaryOperator:
return append(cast(value), decl);
case ValueKind::Call:
return append(cast(value), decl);
case ValueKind::Branch:
return append(cast(value), decl);
case ValueKind::FCmp:
return append(cast(value), decl);
case ValueKind::ICmp:
return append(cast(value), decl);
case ValueKind::Return:
return append(cast(value), decl);
case ValueKind::Undef:
return append(cast(value), decl);
case ValueKind::ConstantInt:
return append(cast(value), decl);
case ValueKind::ConstantFP:
return append(cast(value), decl);
case ValueKind::BasicBlock:
return append(cast(value), decl);
case ValueKind::PHI:
return append(cast(value), decl);
case ValueKind::Cast:
return append(cast(value), decl);
case ValueKind::Select:
return append(cast(value), decl);
case ValueKind::ExtractValue:
return append(cast(value), decl);
case ValueKind::Alloca:
return append(cast(value), decl);
case ValueKind::GetElementPtr:
return append(cast(value), decl);
case ValueKind::Load:
return append(cast(value), decl);
case ValueKind::Store:
return append(cast(value), decl);
case ValueKind::AtomicRMW:
return append(cast(value), decl);
case ValueKind::AtomicCmpXchg:
return append(cast(value), decl);
case ValueKind::Global:
return append(cast(value), decl);
case ValueKind::ConstantAggregate:
return append(cast(value), decl);
case ValueKind::ConstantAggregateZero:
return append(cast(value), decl);
case ValueKind::ConstantDataArray:
return append(cast(value), decl);
case ValueKind::ConstantDataVector:
return append(cast(value), decl);
case ValueKind::ConstantExpr:
return append(cast(value), decl);
case ValueKind::Switch:
return append(cast(value), decl);
case ValueKind::ShuffleVector:
return append(cast(value), decl);
case ValueKind::ExtractElement:
return append(cast(value), decl);
case ValueKind::InsertElement:
return append(cast(value), decl);
default:
break;
}
LOGE("Unknown ValueKind %u.\n", unsigned(value->get_value_kind()));
if (decl)
append("%", value->get_tween_id(), " = unimplemented");
else
append("%", value->get_tween_id());
}
bool disassemble(Module &module, String &str)
{
StreamState state;
for (auto itr = module.global_begin(); itr != module.global_end(); ++itr)
state.append(&*itr, true);
for (auto *func : module)
{
state.newline();
state.append(func, true);
state.newline();
}
state.newline();
for (auto itr = module.named_metadata_begin(); itr != module.named_metadata_end(); ++itr)
{
state.newline();
state.append(itr->second);
}
state.newline();
for (auto itr = module.unnamed_metadata_begin(); itr != module.unnamed_metadata_end(); ++itr)
{
state.newline();
state.append(*itr, true);
}
str = state.stream.str();
return true;
}
} // namespace LLVMBC
================================================
FILE: bc/function.cpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "function.hpp"
#include "context.hpp"
#include "instruction.hpp"
#include "module.hpp"
#include "type.hpp"
#include
#include
namespace LLVMBC
{
Function::Function(FunctionType *function_type_, uint64_t value_id_, Module &module_)
: Constant(function_type_, ValueKind::Function)
, module(module_)
, value_id(value_id_)
, function_type(function_type_)
{
}
const String &Function::getName() const
{
return module.get_value_name(value_id);
}
void Function::set_basic_blocks(Vector basic_blocks_)
{
basic_blocks = std::move(basic_blocks_);
}
FunctionType *Function::getFunctionType() const
{
return function_type;
}
IteratorAdaptor::const_iterator> Function::begin() const
{
return basic_blocks.begin();
}
IteratorAdaptor::const_iterator> Function::end() const
{
return basic_blocks.end();
}
BasicBlock &Function::getEntryBlock() const
{
return *basic_blocks.front();
}
void Function::add_argument(Argument *arg)
{
arguments.push_back(arg);
}
String Attribute::getValueAsString() const
{
// LLVM implementation does this.
if (value)
return *value;
else
return {};
}
Attribute::Attribute(const String *value_)
: value(value_)
{
}
Attribute Function::getFnAttribute(const char *attribute) const
{
for (auto &attr : attributes)
if (attr.first == attribute)
return Attribute(&attr.second);
return Attribute(nullptr);
}
bool Function::hasFnAttribute(const char *attribute) const
{
for (auto &attr : attributes)
if (attr.first == attribute)
return true;
return false;
}
void Function::set_attributes(Vector> attributes_)
{
attributes = std::move(attributes_);
}
void Function::set_structured_control_flow()
{
structured_control_flow = true;
}
bool Function::get_structured_control_flow() const
{
return structured_control_flow;
}
IteratorAdaptor::const_iterator> Function::arg_begin() const
{
return arguments.begin();
}
IteratorAdaptor::const_iterator> Function::arg_end() const
{
return arguments.end();
}
BasicBlock::BasicBlock(LLVMContext &context_)
: Value(Type::getLabelTy(context_), ValueKind::BasicBlock)
{
}
void BasicBlock::add_instruction(Instruction *inst)
{
instructions.push_back(inst);
}
Instruction *BasicBlock::getTerminator() const
{
if (!instructions.empty() && instructions.back()->isTerminator())
return instructions.back();
else
return nullptr;
}
void BasicBlock::add_successor(BasicBlock *succ)
{
if (std::find(succs.begin(), succs.end(), succ) == succs.end())
succs.push_back(succ);
}
BasicBlock::Merge BasicBlock::get_merge() const
{
return merge;
}
BasicBlock *BasicBlock::get_merge_bb() const
{
return merge_bb;
}
BasicBlock *BasicBlock::get_continue_bb() const
{
return continue_bb;
}
void BasicBlock::set_selection_merge(BasicBlock *bb)
{
merge = Merge::Selection;
merge_bb = bb;
}
void BasicBlock::set_loop_merge(BasicBlock *merge_bb_, BasicBlock *continue_bb_)
{
merge = Merge::Loop;
merge_bb = merge_bb_;
continue_bb = continue_bb_;
}
IteratorAdaptor::const_iterator> BasicBlock::begin() const
{
return instructions.begin();
}
IteratorAdaptor::const_iterator> BasicBlock::end() const
{
return instructions.end();
}
Vector::const_iterator BasicBlock::succ_begin() const
{
return succs.begin();
}
Vector::const_iterator BasicBlock::succ_end() const
{
return succs.end();
}
} // namespace LLVMBC
================================================
FILE: bc/function.hpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "iterator.hpp"
#include "value.hpp"
namespace LLVMBC
{
class LLVMContext;
class Instruction;
class Module;
class FunctionType;
class BasicBlock : public Value
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::BasicBlock;
}
explicit BasicBlock(LLVMContext &context);
void add_instruction(Instruction *inst);
Instruction *getTerminator() const;
IteratorAdaptor::const_iterator> begin() const;
IteratorAdaptor::const_iterator> end() const;
void add_successor(BasicBlock *succ);
enum class Merge
{
None,
Selection,
Loop
};
Merge get_merge() const;
void set_selection_merge(BasicBlock *bb);
void set_loop_merge(BasicBlock *merge_bb, BasicBlock *continue_bb);
BasicBlock *get_merge_bb() const;
BasicBlock *get_continue_bb() const;
Vector::const_iterator succ_begin() const;
Vector::const_iterator succ_end() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Vector instructions;
Vector succs;
Merge merge = Merge::None;
BasicBlock *merge_bb = nullptr;
BasicBlock *continue_bb = nullptr;
};
inline Vector::const_iterator succ_begin(const BasicBlock *bb)
{
return bb->succ_begin();
}
inline Vector::const_iterator succ_end(const BasicBlock *bb)
{
return bb->succ_end();
}
class Attribute
{
public:
explicit Attribute(const String *value);
String getValueAsString() const;
private:
const String *value;
};
class Function : public Constant
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Function;
}
explicit Function(FunctionType *function_type, uint64_t value_id, Module &module);
const String &getName() const;
void set_basic_blocks(Vector basic_blocks);
IteratorAdaptor::const_iterator> begin() const;
IteratorAdaptor::const_iterator> end() const;
FunctionType *getFunctionType() const;
BasicBlock &getEntryBlock() const;
void add_argument(Argument *arg);
IteratorAdaptor::const_iterator> arg_begin() const;
IteratorAdaptor::const_iterator> arg_end() const;
// Bare bones implementation, we only need it for fp32-denorm-mode attribute.
Attribute getFnAttribute(const char *attribute) const;
bool hasFnAttribute(const char *attribute) const;
void set_attributes(Vector> attributes);
bool get_structured_control_flow() const;
void set_structured_control_flow();
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Module &module;
uint64_t value_id;
FunctionType *function_type;
Vector basic_blocks;
Vector arguments;
Vector> attributes;
bool structured_control_flow = false;
};
} // namespace LLVMBC
================================================
FILE: bc/instruction.cpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "instruction.hpp"
#include "cast.hpp"
#include
namespace LLVMBC
{
Instruction::Instruction(Type *type, ValueKind kind)
: Value(type, kind)
{
}
void Instruction::set_operands(Vector op)
{
operands = std::move(op);
}
unsigned Instruction::getNumOperands() const
{
return operands.size();
}
Value *Instruction::getOperand(unsigned index) const
{
if (index >= operands.size())
{
LOGE("Operand index is out of range.\n");
return nullptr;
}
return Internal::resolve_proxy(operands[index]);
}
bool Instruction::isTerminator() const
{
return is_terminator;
}
void Instruction::set_terminator()
{
is_terminator = true;
}
bool Instruction::resolve_proxy_values()
{
for (auto &op : operands)
while (op && op->get_value_kind() == ValueKind::Proxy)
op = cast(op)->get_proxy_value();
if (get_value_kind() == ValueKind::PHI)
{
auto *phi = cast(this);
if (!phi->resolve_proxy_values_incoming())
return false;
}
return true;
}
void Instruction::setMetadata(const String &str, MDNode *node)
{
attachments[str] = node;
}
UnorderedMap::const_iterator Instruction::metadata_begin() const
{
return attachments.begin();
}
UnorderedMap::const_iterator Instruction::metadata_end() const
{
return attachments.end();
}
bool Instruction::hasMetadata(const String &str) const
{
return attachments.find(str) != attachments.end();
}
MDNode *Instruction::getMetadata(const String &str) const
{
auto itr = attachments.find(str);
if (itr != attachments.end())
return itr->second;
else
return nullptr;
}
bool Instruction::is_base_of_value_kind(ValueKind kind)
{
switch (kind)
{
case ValueKind::Return:
case ValueKind::Unreachable:
case ValueKind::Call:
case ValueKind::UnaryOperator:
case ValueKind::BinaryOperator:
case ValueKind::Cast:
case ValueKind::Select:
case ValueKind::ExtractValue:
case ValueKind::Alloca:
case ValueKind::GetElementPtr:
case ValueKind::Load:
case ValueKind::Store:
case ValueKind::CompareBase:
case ValueKind::FCmp:
case ValueKind::ICmp:
case ValueKind::Branch:
case ValueKind::Switch:
case ValueKind::PHI:
case ValueKind::AtomicRMW:
case ValueKind::AtomicCmpXchg:
case ValueKind::ShuffleVector:
case ValueKind::ExtractElement:
case ValueKind::InsertElement:
return true;
default:
break;
}
return false;
}
BinaryOperator::BinaryOperator(Value *LHS, Value *RHS, BinaryOps op_)
: Instruction(LHS->getType(), ValueKind::BinaryOperator)
, op(op_)
{
set_operands({ LHS, RHS });
}
BinaryOperator::BinaryOps BinaryOperator::getOpcode() const
{
return op;
}
bool BinaryOperator::isFast() const
{
return fast_math;
}
void BinaryOperator::setFast(bool enabled)
{
fast_math = enabled;
}
UnaryOperator::UnaryOperator(UnaryOps uop, Value *value)
: Instruction(value->getType(), ValueKind::UnaryOperator), op(uop)
{
set_operands({ value });
}
UnaryOperator::UnaryOps UnaryOperator::getOpcode() const
{
return op;
}
ReturnInst::ReturnInst(Value *value_)
: Instruction(value_ ? value_->getType() : nullptr, ValueKind::Return)
, value(value_)
{
set_terminator();
}
UnreachableInst::UnreachableInst()
: Instruction(nullptr, ValueKind::Unreachable)
{
set_terminator();
}
CallInst::CallInst(FunctionType *function_type_, Function *callee_, Vector params)
: Instruction(function_type_->getReturnType(), ValueKind::Call)
, callee(callee_)
{
set_operands(std::move(params));
}
Function *CallInst::getCalledFunction() const
{
return callee;
}
Value *ReturnInst::getReturnValue() const
{
return Internal::resolve_proxy(value);
}
CmpInst::CmpInst(ValueKind kind, Predicate pred_, Value *LHS, Value *RHS)
: Instruction(Type::getInt1Ty(LHS->getType()->getContext()), kind)
, pred(pred_)
{
set_operands({ LHS, RHS });
}
CastInst::CastInst(Type *type, Value *value, Instruction::CastOps op_)
: Instruction(type, ValueKind::Cast)
, op(op_)
{
set_operands({ value });
}
SelectInst::SelectInst(Value *true_value, Value *false_value, Value *cond)
: Instruction(true_value->getType(), ValueKind::Select)
{
set_operands({ cond, true_value, false_value });
}
ExtractValueInst::ExtractValueInst(Type *type, Value *aggregate, Vector indices_)
: Instruction(type, ValueKind::ExtractValue)
, indices(std::move(indices_))
{
set_operands({ aggregate });
}
Value *ExtractValueInst::getAggregateOperand() const
{
return Internal::resolve_proxy(operands[0]);
}
unsigned ExtractValueInst::getNumIndices() const
{
return indices.size();
}
const unsigned *ExtractValueInst::getIndices() const
{
return indices.data();
}
Instruction::CastOps CastInst::getOpcode() const
{
return op;
}
Instruction::Predicate CmpInst::getPredicate() const
{
return pred;
}
bool CmpInst::is_base_of_value_kind(ValueKind kind)
{
return kind == ValueKind::ICmp || kind == ValueKind::FCmp;
}
FCmpInst::FCmpInst(Predicate pred_, Value *LHS, Value *RHS)
: CmpInst(ValueKind::FCmp, pred_, LHS, RHS)
{
set_operands({ LHS, RHS });
}
ICmpInst::ICmpInst(Predicate pred_, Value *LHS, Value *RHS)
: CmpInst(ValueKind::ICmp, pred_, LHS, RHS)
{
set_operands({ LHS, RHS });
}
BranchInst::BranchInst(BasicBlock *true_block, BasicBlock *false_block, Value *cond_)
: Instruction(nullptr, ValueKind::Branch)
, cond(cond_)
{
set_terminator();
num_blocks = 2;
bbs[0] = true_block;
bbs[1] = false_block;
}
BranchInst::BranchInst(BasicBlock *true_block)
: Instruction(nullptr, ValueKind::Branch)
{
set_terminator();
num_blocks = 1;
bbs[0] = true_block;
}
bool BranchInst::isConditional() const
{
return cond != nullptr;
}
Value *BranchInst::getCondition() const
{
return Internal::resolve_proxy(cond);
}
BasicBlock *BranchInst::getSuccessor(unsigned index) const
{
assert(index < num_blocks);
return bbs[index];
}
unsigned BranchInst::getNumSuccessors() const
{
return num_blocks;
}
SwitchInst::SwitchInst(Value *cond_, BasicBlock *default_block_, unsigned num_cases)
: Instruction(Type::getVoidTy(cond_->getType()->getContext()), ValueKind::Switch)
, cond(cond_)
, default_block(default_block_)
{
set_terminator();
cases.reserve(num_cases);
}
void SwitchInst::addCase(Value *case_value, BasicBlock *bb)
{
cases.push_back({ case_value, bb });
}
Vector::const_iterator SwitchInst::case_begin() const
{
return cases.begin();
}
Vector::const_iterator SwitchInst::case_end() const
{
return cases.end();
}
BasicBlock *SwitchInst::getDefaultDest() const
{
return default_block;
}
Value *SwitchInst::getCondition() const
{
return Internal::resolve_proxy(cond);
}
ConstantInt *SwitchInst::Case::getCaseValue() const
{
return cast(value);
}
BasicBlock *SwitchInst::Case::getCaseSuccessor() const
{
return bb;
}
PHINode::PHINode(Type *type, size_t num_edges)
: Instruction(type, ValueKind::PHI)
{
incoming.reserve(num_edges);
}
void PHINode::add_incoming(Value *value, BasicBlock *bb)
{
incoming.push_back({ value, bb });
}
unsigned PHINode::getNumIncomingValues() const
{
return unsigned(incoming.size());
}
AllocaInst::AllocaInst(Type *pointer_type, Type *element_type_, Value *size)
: Instruction(pointer_type, ValueKind::Alloca)
, array_size(size)
{
}
Value *AllocaInst::getArraySize() const
{
return Internal::resolve_proxy(array_size);
}
GetElementPtrInst::GetElementPtrInst(Type *pointer_type, Vector indices, bool inbounds_)
: Instruction(pointer_type, ValueKind::GetElementPtr)
, inbounds(inbounds_)
{
set_operands(std::move(indices));
}
bool GetElementPtrInst::isInBounds() const
{
return inbounds;
}
LoadInst::LoadInst(Type *type, Value *ptr)
: Instruction(type, ValueKind::Load)
{
set_operands({ ptr });
}
Value *LoadInst::getPointerOperand() const
{
return getOperand(0);
}
StoreInst::StoreInst(Value *ptr, Value *value)
: Instruction(Type::getVoidTy(ptr->getType()->getContext()), ValueKind::Store)
{
set_operands({ value, ptr });
}
BasicBlock *PHINode::getIncomingBlock(unsigned index) const
{
if (index >= incoming.size())
return nullptr;
return incoming[index].bb;
}
Value *PHINode::getIncomingValue(unsigned index) const
{
if (index >= incoming.size())
return nullptr;
return Internal::resolve_proxy(incoming[index].value);
}
bool PHINode::resolve_proxy_values_incoming()
{
for (auto &node : incoming)
{
while (node.value && node.value->get_value_kind() == ValueKind::Proxy)
{
node.value = cast(node.value)->get_proxy_value();
if (!node.value)
return false;
}
}
return true;
}
AtomicRMWInst::AtomicRMWInst(Type *type, Value *ptr_, Value *value_, BinOp op_)
: Instruction(type, ValueKind::AtomicRMW)
, ptr(ptr_)
, value(value_)
, op(op_)
{
set_operands({ ptr, value });
}
Value *AtomicRMWInst::getPointerOperand() const
{
return Internal::resolve_proxy(ptr);
}
Value *AtomicRMWInst::getValOperand() const
{
return Internal::resolve_proxy(value);
}
AtomicRMWInst::BinOp AtomicRMWInst::getOperation() const
{
return op;
}
AtomicCmpXchgInst::AtomicCmpXchgInst(Value *ptr_, Value *cmp_, Value *new_value_, Type *type_override)
: Instruction(type_override ?
type_override :
StructType::get(new_value_->getType()->getContext(),
{ new_value_->getType(), Type::getInt1Ty(new_value_->getType()->getContext()) }),
ValueKind::AtomicCmpXchg)
, ptr(ptr_)
, new_value(new_value_)
, cmp_value(cmp_)
{
set_operands({ ptr, new_value, cmp_value });
}
Value *AtomicCmpXchgInst::getPointerOperand() const
{
return Internal::resolve_proxy(ptr);
}
Value *AtomicCmpXchgInst::getCompareOperand() const
{
return Internal::resolve_proxy(cmp_value);
}
Value *AtomicCmpXchgInst::getNewValOperand() const
{
return Internal::resolve_proxy(new_value);
}
ShuffleVectorInst::ShuffleVectorInst(Type *type, Value *a, Value *b, Value *shuf)
: Instruction(type, ValueKind::ShuffleVector)
{
set_operands({ a, b });
auto *masks = cast(shuf);
shuffle_mask.reserve(masks->getNumElements());
for (unsigned i = 0; i < masks->getNumElements(); i++)
shuffle_mask.push_back(cast(masks->getElementAsConstant(i))->getUniqueInteger().getSExtValue());
}
int ShuffleVectorInst::getMaskValue(unsigned index) const
{
assert(index < shuffle_mask.size());
return shuffle_mask[index];
}
ExtractElementInst::ExtractElementInst(Value *vec_, Value *index_)
: Instruction(cast(vec_->getType())->getElementType(), ValueKind::ExtractElement),
vec(vec_), index(index_)
{
set_operands({ vec, index });
}
Value *ExtractElementInst::getVectorOperand() const
{
return Internal::resolve_proxy(vec);
}
Value *ExtractElementInst::getIndexOperand() const
{
return Internal::resolve_proxy(index);
}
InsertElementInst::InsertElementInst(Value *vec, Value *value, Value *index)
: Instruction(vec->getType(), ValueKind::InsertElement)
{
set_operands({ vec, value, index });
}
CompositeConstructInst::CompositeConstructInst(Type *type, Vector constituents)
: Instruction(type, ValueKind::CompositeConstruct)
{
set_operands(std::move(constituents));
}
} // namespace LLVMBC
================================================
FILE: bc/instruction.hpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "value.hpp"
namespace LLVMBC
{
class FunctionType;
class Function;
class BasicBlock;
class MDNode;
class Instruction : public Value
{
public:
Instruction(Type *type, ValueKind kind);
enum Predicate
{
FCMP_FALSE = 0,
FCMP_OEQ = 1,
FCMP_OGT = 2,
FCMP_OGE = 3,
FCMP_OLT = 4,
FCMP_OLE = 5,
FCMP_ONE = 6,
FCMP_ORD = 7,
FCMP_UNO = 8,
FCMP_UEQ = 9,
FCMP_UGT = 10,
FCMP_UGE = 11,
FCMP_ULT = 12,
FCMP_ULE = 13,
FCMP_UNE = 14,
FCMP_TRUE = 15,
ICMP_EQ = 32,
ICMP_NE = 33,
ICMP_UGT = 34,
ICMP_UGE = 35,
ICMP_ULT = 36,
ICMP_ULE = 37,
ICMP_SGT = 38,
ICMP_SGE = 39,
ICMP_SLT = 40,
ICMP_SLE = 41
};
enum CastOps
{
InvalidCastOp = 100,
Trunc,
ZExt,
SExt,
FPToUI,
FPToSI,
UIToFP,
SIToFP,
FPTrunc,
FPExt,
PtrToInt,
IntToPtr,
BitCast,
AddrSpaceCast
};
enum GEPOps
{
GetElementPtr = 200
};
enum BinaryOps
{
InvalidBinaryOp = 300,
Add,
FAdd,
Sub,
FSub,
Mul,
FMul,
UDiv,
SDiv,
FDiv,
URem,
SRem,
FRem,
Shl,
LShr,
AShr,
And,
Or,
Xor
};
bool isTerminator() const;
Value *getOperand(unsigned index) const;
unsigned getNumOperands() const;
bool resolve_proxy_values();
MDNode *getMetadata(const String &str) const;
bool hasMetadata(const String &str) const;
void setMetadata(const String &str, MDNode *node);
UnorderedMap::const_iterator metadata_begin() const;
UnorderedMap::const_iterator metadata_end() const;
static bool is_base_of_value_kind(ValueKind kind);
static constexpr ValueKind get_value_kind()
{
return ValueKind::InstructionBase;
}
protected:
void set_terminator();
bool is_terminator = false;
void set_operands(Vector op);
Vector operands;
UnorderedMap attachments;
};
class ReturnInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Return;
}
explicit ReturnInst(Value *value);
Value *getReturnValue() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Value *value;
};
class UnreachableInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Unreachable;
}
UnreachableInst();
LLVMBC_DEFAULT_VALUE_KIND_IMPL
};
class CallInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Call;
}
CallInst(FunctionType *function_type, Function *callee, Vector params);
Function *getCalledFunction() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Function *callee;
};
class UnaryOperator : public Instruction
{
public:
enum class UnaryOps
{
Invalid,
FNeg,
INeg, // custom extension
};
static constexpr ValueKind get_value_kind()
{
return ValueKind::UnaryOperator;
}
UnaryOperator(UnaryOps uop, Value *value);
UnaryOps getOpcode() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
UnaryOps op;
};
class BinaryOperator : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::BinaryOperator;
}
BinaryOperator(Value *LHS, Value *RHS, BinaryOps op);
BinaryOps getOpcode() const;
void setFast(bool enabled);
bool isFast() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
BinaryOps op;
bool fast_math = false;
};
class CastInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Cast;
}
CastInst(Type *type, Value *value, Instruction::CastOps op);
Instruction::CastOps getOpcode() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Instruction::CastOps op;
};
class SelectInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Select;
}
SelectInst(Value *true_value, Value *false_value, Value *cond);
LLVMBC_DEFAULT_VALUE_KIND_IMPL
};
class ExtractValueInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::ExtractValue;
}
ExtractValueInst(Type *type, Value *aggregate, Vector indices);
Value *getAggregateOperand() const;
unsigned getNumIndices() const;
const unsigned *getIndices() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Vector indices;
};
class AllocaInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Alloca;
}
AllocaInst(Type *pointer_type, Type *element_type, Value *size);
Value *getArraySize() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Value *array_size;
};
class GetElementPtrInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::GetElementPtr;
}
GetElementPtrInst(Type *pointer_type, Vector arguments, bool inbounds);
bool isInBounds() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
bool inbounds;
};
class LoadInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Load;
}
LoadInst(Type *type, Value *ptr);
Value *getPointerOperand() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
};
class StoreInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Store;
}
StoreInst(Value *ptr, Value *value);
LLVMBC_DEFAULT_VALUE_KIND_IMPL
};
class CmpInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::CompareBase;
}
CmpInst(ValueKind kind, Predicate pred, Value *LHS, Value *RHS);
Predicate getPredicate() const;
static bool is_base_of_value_kind(ValueKind kind);
private:
Predicate pred;
};
class FCmpInst : public CmpInst
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::FCmp;
}
FCmpInst(Predicate pred, Value *LHS, Value *RHS);
LLVMBC_DEFAULT_VALUE_KIND_IMPL
};
class ICmpInst : public CmpInst
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::ICmp;
}
ICmpInst(Predicate pred, Value *LHS, Value *RHS);
LLVMBC_DEFAULT_VALUE_KIND_IMPL
};
class BranchInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Branch;
}
BranchInst(BasicBlock *true_block, BasicBlock *false_block, Value *cond);
explicit BranchInst(BasicBlock *true_block);
bool isConditional() const;
Value *getCondition() const;
unsigned getNumSuccessors() const;
BasicBlock *getSuccessor(unsigned index) const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
BasicBlock *bbs[2] = {};
unsigned num_blocks = 0;
Value *cond = nullptr;
};
class SwitchInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::Switch;
}
SwitchInst(Value *cond, BasicBlock *default_block, unsigned num_cases);
void addCase(Value *case_value, BasicBlock *bb);
struct Case
{
Value *value;
BasicBlock *bb;
BasicBlock *getCaseSuccessor() const;
ConstantInt *getCaseValue() const;
};
Vector::const_iterator case_begin() const;
Vector::const_iterator case_end() const;
Value *getCondition() const;
BasicBlock *getDefaultDest() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Value *cond;
BasicBlock *default_block;
Vector cases;
};
class PHINode : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::PHI;
}
PHINode(Type *type, size_t num_edges);
unsigned getNumIncomingValues() const;
Value *getIncomingValue(unsigned index) const;
BasicBlock *getIncomingBlock(unsigned index) const;
void add_incoming(Value *value, BasicBlock *bb);
bool resolve_proxy_values_incoming();
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
struct Incoming
{
Value *value;
BasicBlock *bb;
};
Vector incoming;
};
class AtomicRMWInst : public Instruction
{
public:
enum class BinOp
{
Invalid,
Xchg,
Add,
Sub,
And,
Nand,
Or,
Xor,
Max,
Min,
UMax,
UMin,
FAdd, // wat
FSub
};
static constexpr ValueKind get_value_kind()
{
return ValueKind::AtomicRMW;
}
AtomicRMWInst(Type *type, Value *ptr, Value *value, BinOp op);
Value *getPointerOperand() const;
Value *getValOperand() const;
BinOp getOperation() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Value *ptr;
Value *value;
BinOp op;
};
class AtomicCmpXchgInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::AtomicCmpXchg;
}
AtomicCmpXchgInst(Value *ptr, Value *cmp, Value *new_value, Type *type_override = nullptr);
Value *getPointerOperand() const;
Value *getNewValOperand() const;
Value *getCompareOperand() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Value *ptr;
Value *new_value;
Value *cmp_value;
};
class ShuffleVectorInst : public Instruction
{
public:
ShuffleVectorInst(Type *type, Value *a, Value *b, Value *shuf);
static constexpr ValueKind get_value_kind()
{
return ValueKind::ShuffleVector;
}
int getMaskValue(unsigned index) const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Vector shuffle_mask;
};
class ExtractElementInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::ExtractElement;
}
ExtractElementInst(Value *vec, Value *offset);
Value *getVectorOperand() const;
Value *getIndexOperand() const;
LLVMBC_DEFAULT_VALUE_KIND_IMPL
private:
Value *vec;
Value *index;
};
class InsertElementInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::InsertElement;
}
InsertElementInst(Value *vec, Value *value, Value *index);
LLVMBC_DEFAULT_VALUE_KIND_IMPL
};
// Extension of LLVM to better map to SPIR-V / DXBC-IR
class CompositeConstructInst : public Instruction
{
public:
static constexpr ValueKind get_value_kind()
{
return ValueKind::CompositeConstruct;
}
CompositeConstructInst(Type *type, Vector constituents);
LLVMBC_DEFAULT_VALUE_KIND_IMPL
};
} // namespace LLVMBC
================================================
FILE: bc/iterator.hpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include
namespace LLVMBC
{
// An iterator adaptor which lets us receive reference types instead of pointer types.
template
struct IteratorAdaptor
{
IteratorAdaptor(Iter iter_)
: iter(iter_)
{
}
T &operator*()
{
return **iter;
}
T *operator->()
{
return *iter;
}
IteratorAdaptor operator++()
{
++iter;
return *this;
}
bool operator==(const IteratorAdaptor &other) const
{
return iter == other.iter;
}
bool operator!=(const IteratorAdaptor &other) const
{
return !(*this == other);
}
ptrdiff_t operator-(const IteratorAdaptor &other) const
{
return iter - other.iter;
}
Iter iter;
};
} // namespace LLVMBC
================================================
FILE: bc/metadata.cpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "metadata.hpp"
#include "module.hpp"
#include "value.hpp"
#include
#include
namespace LLVMBC
{
MDOperand::MDOperand(Module *parent_, MetadataKind kind_)
: parent(parent_)
, kind(kind_)
{
}
MDOperand::MDOperand(Module *parent_)
: parent(parent_)
{
}
Module *MDOperand::getParent() const
{
return parent;
}
MetadataKind MDOperand::get_metadata_kind() const
{
return kind;
}
MDNode::MDNode(Module *module, Vector operands_)
: MDOperand(module, MetadataKind::Node)
, operands(std::move(operands_))
{
}
unsigned MDNode::getNumOperands() const
{
return unsigned(operands.size());
}
MDOperand &MDNode::getOperand(unsigned index) const
{
assert(index < operands.size());
return *operands[index];
}
uint64_t MDNode::get_tween_id() const
{
return tween;
}
void MDNode::set_tween_id(uint64_t id)
{
tween = id;
}
NamedMDNode::NamedMDNode(Module *module, String name_, Vector operands_)
: MDOperand(module, MetadataKind::NamedNode)
, name(std::move(name_))
, operands(std::move(operands_))
{
}
unsigned NamedMDNode::getNumOperands() const
{
return unsigned(operands.size());
}
MDNode *NamedMDNode::getOperand(unsigned index) const
{
assert(index < operands.size());
return operands[index];
}
const String &NamedMDNode::getName() const
{
return name;
}
ConstantAsMetadata::ConstantAsMetadata(Module *module, Constant *value_)
: MDOperand(module, MetadataKind::Constant)
, value(value_)
{
}
Constant *ConstantAsMetadata::getValue() const
{
return value;
}
MDString::MDString(LLVMBC::Module *module, String str_)
: MDOperand(module, MetadataKind::String)
, str(std::move(str_))
{
}
const String &MDString::getString() const
{
return str;
}
} // namespace LLVMBC
================================================
FILE: bc/metadata.hpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "data_structures.hpp"
namespace LLVMBC
{
class Value;
class Module;
class Constant;
enum class MetadataKind
{
NamedNode,
Node,
Constant,
String,
None
};
class MDOperand
{
public:
explicit MDOperand(Module *parent);
MDOperand(Module *parent, MetadataKind kind);
Module *getParent() const;
MetadataKind get_metadata_kind() const;
explicit operator bool() const
{
return kind != MetadataKind::None;
}
private:
Module *parent;
MetadataKind kind = MetadataKind::None;
};
class MDNode : public MDOperand
{
public:
static constexpr MetadataKind get_metadata_kind()
{
return MetadataKind::Node;
}
MDNode(Module *module, Vector operands);
MDOperand &getOperand(unsigned index) const;
unsigned getNumOperands() const;
void set_tween_id(uint64_t id);
uint64_t get_tween_id() const;
private:
Vector operands;
uint64_t tween = 0;
};
class NamedMDNode : public MDOperand
{
public:
static constexpr MetadataKind get_metadata_kind()
{
return MetadataKind::NamedNode;
}
NamedMDNode(Module *module, String name, Vector operands);
const String &getName() const;
MDNode *getOperand(unsigned index) const;
unsigned getNumOperands() const;
private:
String name;
Vector operands;
};
class ConstantAsMetadata : public MDOperand
{
public:
static constexpr MetadataKind get_metadata_kind()
{
return MetadataKind::Constant;
}
ConstantAsMetadata(Module *module, Constant *value);
Constant *getValue() const;
private:
Constant *value;
};
class MDString : public MDOperand
{
public:
static constexpr MetadataKind get_metadata_kind()
{
return MetadataKind::String;
}
MDString(Module *module, String str);
const String &getString() const;
private:
String str;
};
} // namespace LLVMBC
================================================
FILE: bc/module.cpp
================================================
/* Copyright (c) 2019-2022 Hans-Kristian Arntzen for Valve Corporation
*
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "module.hpp"
#include "cast.hpp"
#include "context.hpp"
#include "function.hpp"
#include "instruction.hpp"
#include "logging.hpp"
#include "metadata.hpp"
#include "type.hpp"
#include "value.hpp"
#include
#include "llvm_decoder.h"
namespace LLVMBC
{
enum class KnownBlocks : uint32_t
{
BLOCKINFO = 0,
// 1-7 reserved,
MODULE_BLOCK = 8,
PARAMATTR_BLOCK = 9,
PARAMATTR_GROUP_BLOCK = 10,
CONSTANTS_BLOCK = 11,
FUNCTION_BLOCK = 12,
TYPE_SYMTAB_BLOCK = 13,
VALUE_SYMTAB_BLOCK = 14,
METADATA_BLOCK = 15,
METADATA_ATTACHMENT = 16,
TYPE_BLOCK = 17,
};
enum class AttributeRecord : uint32_t
{
NONE = 0,
ALIGNMENT = 1,
BY_VAL = 3,
STACK_ALIGNMENT = 25,
DEREFERENCEABLE = 41,
DEREFERENCEABLE_OR_NULL = 42,
ALLOC_SIZE = 51
};
enum class ModuleRecord : uint32_t
{
VERSION = 1,
TRIPLE = 2,
DATALAYOUT = 3,
GLOBAL_VARIABLE = 7,
FUNCTION = 8,
};
enum class ConstantsRecord : uint32_t
{
SETTYPE = 1,
CONST_NULL = 2,
UNDEF = 3,
INTEGER = 4,
WIDE_INTEGER = 5,
FLOAT = 6,
AGGREGATE = 7,
STRING = 8,
BINOP = 10,
CE_CAST = 11,
GEP = 12,
INBOUNDS_GEP = 20,
DATA = 22,
GEP_WITH_INRANGE_INDEX = 24
};
enum class FunctionRecord : uint32_t
{
DECLAREBLOCKS = 1,
INST_BINOP = 2,
INST_CAST = 3,
INST_GEP_OLD = 4,
INST_SELECT = 5,
INST_EXTRACTELT = 6,
INST_INSERTELT = 7,
INST_SHUFFLEVEC = 8,
INST_CMP = 9,
INST_RET = 10,
INST_BR = 11,
INST_SWITCH = 12,
INST_INVOKE = 13,
INST_UNREACHABLE = 15,
INST_PHI = 16,
INST_ALLOCA = 19,
INST_LOAD = 20,
INST_VAARG = 23,
INST_STORE_OLD = 24,
INST_EXTRACTVAL = 26,
INST_INSERTVAL = 27,
INST_CMP2 = 28,
INST_VSELECT = 29,
INST_INBOUNDS_GEP_OLD = 30,
INST_INDIRECTBR = 31,
DEBUG_LOC_AGAIN = 33,
INST_CALL = 34,
DEBUG_LOC = 35,
INST_FENCE = 36,
INST_CMPXCHG_OLD = 37,
INST_ATOMICRMW = 38,
INST_RESUME = 39,
INST_LANDINGPAD_OLD = 40,
INST_LOADATOMIC = 41,
INST_STOREATOMIC_OLD = 42,
INST_GEP = 43,
INST_STORE = 44,
INST_STOREATOMIC = 45,
INST_CMPXCHG = 46,
INST_LANDINGPAD = 47,
INST_CLEANUPRET = 48,
INST_CATCHRET = 49,
INST_CATCHPAD = 50,
INST_CLEANUPPAD = 51,
INST_CATCHSWITCH = 52,
OPERAND_BUNDLE = 55,
INST_UNOP = 56,
INST_CALLBR = 57,
};
enum class ValueSymtabRecord : uint32_t
{
ENTRY = 1,
BBENTRY = 2,
FNENTRY = 3,
COMBINED_ENTRY = 5,
};
enum class MetaDataRecord : uint32_t
{
STRING_OLD = 1,
VALUE = 2,
NODE = 3,
NAME = 4,
DISTINCT_NODE = 5,
KIND = 6,
LOCATION = 7,
OLD_NODE = 8,
OLD_FN_NODE = 9,
NAMED_NODE = 10,
ATTACHMENT = 11,
GENERIC_DEBUG = 12,
SUBRANGE = 13,
ENUMERATOR = 14,
BASIC_TYPE = 15,
FILE = 16,
DERIVED_TYPE = 17,
COMPOSITE_TYPE = 18,
SUBROUTINE_TYPE = 19,
COMPILE_UNIT = 20,
SUBPROGRAM = 21,
LEXICAL_BLOCK = 22,
LEXICAL_BLOCK_FILE = 23,
NAMESPACE = 24,
TEMPLATE_TYPE = 25,
TEMPLATE_VALUE = 26,
GLOBAL_VAR = 27,
LOCAL_VAR = 28,
EXPRESSION = 29,
OBJC_PROPERTY = 30,
IMPORTED_ENTITY = 31,
MODULE = 32,
MACRO = 33,
MACRO_FILE = 34,
STRINGS = 35,
GLOBAL_DECL_ATTACHMENT = 36,
GLOBAL_VAR_EXPR = 37,
INDEX_OFFSET = 38,
INDEX = 39,
LABEL = 40,
COMMON_BLOCK = 44,
};
enum class AttributeCodes : uint32_t
{
CodeEntryOld = 1,
CodeEntry = 2,
GroupCodeEntry = 3
};
enum class TypeRecord : uint32_t
{
NUMENTRY = 1,
VOID_TYPE = 2,
FLOAT = 3,
DOUBLE = 4,
LABEL = 5,
OPAQUE_TYPE = 6,
INTEGER = 7,
POINTER = 8,
FUNCTION_OLD = 9,
HALF = 10,
ARRAY = 11,
VECTOR = 12,
METADATA = 16,
STRUCT_ANON = 18,
STRUCT_NAME = 19,
STRUCT_NAMED = 20,
FUNCTION = 21,
TOKEN = 22,
};
enum class UnaryOp : uint32_t
{
FNEG = 0
};
enum class BinOp : uint32_t
{
ADD = 0,
SUB = 1,
MUL = 2,
UDIV = 3,
SDIV = 4,
UREM = 5,
SREM = 6,
SHL = 7,
LSHR = 8,
ASHR = 9,
AND = 10,
OR = 11,
XOR = 12
};
enum class AtomicBinOp : uint32_t
{
RMW_XCHG = 0,
RMW_ADD = 1,
RMW_SUB = 2,
RMW_AND = 3,
RMW_NAND = 4,
RMW_OR = 5,
RMW_XOR = 6,
RMW_MAX = 7,
RMW_MIN = 8,
RMW_UMAX = 9,
RMW_UMIN = 10,
RMW_FADD = 11,
RMW_FSUB = 12
};
enum class CastOp : uint32_t
{
TRUNC = 0,
ZEXT = 1,
SEXT = 2,
FPTOUI = 3,
FPTOSI = 4,
UITOFP = 5,
SITOFP = 6,
FPTRUNC = 7,
FPEXT = 8,
PTRTOINT = 9,
INTTOPTR = 10,
BITCAST = 11,
ADDSPACECAST = 12
};
enum CallFlagBits
{
CALL_TAIL_BIT = 1 << 0,
CALL_CCONV_BIT = 1 << 1,
CALL_MUSTTAIL_BIT = 1 << 14,
CALL_EXPLICIT_TYPE_BIT = 1 << 15,
CALL_NOTAIL_BIT = 1 << 16,
CALL_FMF_BIT = 1 << 17
};
enum FastMathFlagBits
{
FAST_MATH_UNSAFE_ALGEBRA_BIT = 1 << 0,
FAST_MATH_ALLOW_CONTRACT_BIT = 1 << 5
};
static int64_t decode_sign_rotated_value(uint64_t v)
{
bool sign = (v & 1) != 0;
v >>= 1;
if (sign)
v = v ? -int64_t(v) : (1ull << 63u);
return int64_t(v);
}
struct ModuleParseContext
{
Function *function = nullptr;
Module *module = nullptr;
LLVMContext *context = nullptr;
Vector basic_blocks;
Vector values;
Vector instructions;
Vector types;
Vector functions_with_bodies;
UnorderedMap metadata;
UnorderedMap metadata_kind_map;
Vector>> attribute_lists;
UnorderedMap>> attribute_groups;
Type *constant_type = nullptr;
String current_metadata_name;
bool parse_function_child_block(const BlockOrRecord &entry);
bool parse_record(const BlockOrRecord &entry);
bool parse_constants_record(const BlockOrRecord &entry);
bool parse_constants_block(const BlockOrRecord &entry);
bool parse_metadata_block(const BlockOrRecord &entry);
bool parse_paramattr_block(const BlockOrRecord &entry);
bool parse_paramattr_group_block(const BlockOrRecord &entry);
bool parse_metadata_attachment_record(const BlockOrRecord &entry);
bool parse_metadata_record(const BlockOrRecord &entry, unsigned index);
Type *get_constant_type();
bool parse_function_body(const BlockOrRecord &entry);
bool parse_types(const BlockOrRecord &entry);
bool parse_value_symtab(const BlockOrRecord &entry);
bool parse_function_record(const BlockOrRecord &entry);
bool parse_global_variable_record(const BlockOrRecord &entry);
bool parse_version_record(const BlockOrRecord &entry);
bool parse_type(const BlockOrRecord &entry);
bool add_instruction(Instruction *inst);
bool add_value(Value *value);
bool add_type(Type *type);
Type *get_type(uint64_t index);
bool finish_basic_block();
bool add_successor(BasicBlock *bb);
BasicBlock *get_basic_block(uint64_t index) const;
BasicBlock *current_bb = nullptr;
unsigned basic_block_index = 0;
Value *get_value(uint64_t op, Type *expected_type = nullptr, bool force_absolute = false);
std::pair get_value_and_type(const Vector &ops, unsigned &index);
Value *get_value(const Vector &ops, unsigned &index, Type *expected_type);
Value *get_value_signed(uint64_t op, Type *expected_type = nullptr);
MDOperand *get_metadata(uint64_t index) const;
const char *get_metadata_kind(uint64_t index) const;
Instruction *get_instruction(uint64_t index) const;
Vector pending_forward_references;
Vector> global_initializations;
bool resolve_forward_references();
bool resolve_global_initializations();
uint64_t tween_id = 1;
uint64_t metadata_tween_id = 1;
bool use_relative_id = true;
bool use_strtab = false;
bool seen_first_function_body = false;
};
ValueProxy::ValueProxy(Type *type, ModuleParseContext &context_, uint64_t id_)
: Value(type, ValueKind::Proxy)
, id(id_)
, context(context_)
{
}
bool ValueProxy::resolve()
{
if (proxy)
return true;
if (id >= context.values.size())
{
LOGE("Value proxy is out of range.\n");
return false;
}
proxy = context.values[id];
while (proxy && proxy->get_value_kind() == ValueKind::Proxy)
{
cast(proxy)->resolve();
proxy = cast(proxy)->get_proxy_value();
}
if (!proxy)
{
LOGE("Failed to resolve proxy value.\n");
return false;
}
return true;
}
Value *ValueProxy::get_proxy_value() const
{
return proxy;
}
bool ModuleParseContext::finish_basic_block()
{
basic_block_index++;
if (basic_block_index >= basic_blocks.size())
current_bb = nullptr;
else
{
current_bb = basic_blocks[basic_block_index];
current_bb->set_tween_id(tween_id++);
}
return true;
}
bool ModuleParseContext::add_successor(BasicBlock *bb)
{
if (!current_bb)
{
LOGE("No basic block is active in add_successor().\n");
return false;
}
current_bb->add_successor(bb);
return true;
}
BasicBlock *ModuleParseContext::get_basic_block(uint64_t index) const
{
if (index >= basic_blocks.size())
{
LOGE("Basic block index is out of bounds!\n");
return nullptr;
}
return basic_blocks[index];
}
Value *ModuleParseContext::get_value(uint64_t op, Type *expected_type, bool force_absolute)
{
if (!force_absolute && use_relative_id)
op = uint32_t(values.size() - op);
if (op >= values.size())
{
if (!expected_type)
{
LOGE("Must have an expected type for forward references!\n");
return nullptr;
}
auto *proxy = context->construct(expected_type, *this, op);
pending_forward_references.push_back(proxy);
return proxy;
}
else
{
// A pointer to function and a constant function do match.
if (auto *ptr_type = dyn_cast(expected_type))
if (ptr_type->getPointerElementType()->getTypeID() == Type::TypeID::FunctionTyID)
expected_type = ptr_type->getPointerElementType();
if (expected_type && expected_type != values[op]->getType())
{
LOGE("Type mismatch.\n");
return nullptr;
}
return values[op];
}
}
Value *ModuleParseContext::get_value(const Vector &ops, unsigned &index, Type *expected_type)
{
if (index >= ops.size())
return nullptr;
return get_value(ops[index++], expected_type);
}
std::pair ModuleParseContext::get_value_and_type(const Vector &ops, unsigned &index)
{
if (index >= ops.size())
return {};
uint64_t op = ops[index++];
if (use_relative_id)
op = uint32_t(values.size() - op);
if (op < values.size())
{
// Normal reference.
return { values[op], values[op]->getType() };
}
else
{
// Forward reference, the type is encoded in the next element.
if (index >= ops.size())
return {};
auto *type = get_type(ops[index++]);
auto *proxy = context->construct(type, *this, op);
pending_forward_references.push_back(proxy);
return { proxy, type };
}
}
Instruction *ModuleParseContext::get_instruction(uint64_t index) const
{
if (index >= instructions.size())
{
LOGE("Instruction index is out of range!\n");
return nullptr;
}
return instructions[index];
}
MDOperand *ModuleParseContext::get_metadata(uint64_t index) const
{
auto itr = metadata.find(index);
if (itr != metadata.end())
return itr->second;
else
{
// Need to return a null-node like this since MDOperand is used as a reference in the LLVM API for some reason.
return context->construct(module);
}
}
const char *ModuleParseContext::get_metadata_kind(uint64_t index) const
{
auto itr = metadata_kind_map.find(index);
if (itr != metadata_kind_map.end())
return itr->second.c_str();
else
return nullptr;
}
Value *ModuleParseContext::get_value_signed(uint64_t op, Type *expected_type)
{
int64_t signed_op = decode_sign_rotated_value(op);
if (use_relative_id)
signed_op = values.size() - signed_op;
op = signed_op;
if (op >= values.size())
{
if (!expected_type)
{
LOGE("Must have an expected type for forward references!\n");
return nullptr;
}
auto *proxy = context->construct(expected_type, *this, op);
pending_forward_references.push_back(proxy);
return proxy;
}
else
return values[op];
}
bool ModuleParseContext::add_instruction(Instruction *inst)
{
instructions.push_back(inst);
if (current_bb)
current_bb->add_instruction(inst);
else
{
LOGE("No basic block is currently set!\n");
return false;
}
if (inst->isTerminator())
return finish_basic_block();
else
return add_value(inst);
}
bool ModuleParseContext::add_value(Value *value)
{
if (value->getType()->getTypeID() != Type::TypeID::VoidTyID)
{
value->set_tween_id(tween_id++);
values.push_back(value);
}
return true;
}
Type *ModuleParseContext::get_constant_type()
{
if (constant_type)
return constant_type;
else
return Type::getInt32Ty(*context);
}
static Type *resolve_gep_element_type(Type *type, const Vector &args)
{
for (unsigned i = 2; i < args.size(); i++)
{
auto *arg = args[i];
if (type->getTypeID() == Type::TypeID::StructTyID)
{
auto *const_int = dyn_cast(arg);
if (!const_int)
{
LOGE("Indexing into a struct without a constant integer.\n");
return nullptr;
}
unsigned index = const_int->getUniqueInteger().getZExtValue();
if (index >= cast(type)->getNumElements())
{
LOGE("Struct element index out of range.\n");
return nullptr;
}
type = cast(type)->getElementType(index);
}
else if (type->getTypeID() == Type::TypeID::ArrayTyID)
{
type = type->getArrayElementType();
}
else if (type->getTypeID() == Type::TypeID::VectorTyID)
{
type = cast(type)->getElementType();
}
else
return nullptr;
}
return type;
}
static BinaryOperator::BinaryOps translate_binop(BinOp op, Type *type)
{
bool is_fp = type->isFloatingPointTy();
switch (op)
{
case BinOp::ADD:
return is_fp ? BinaryOperator::BinaryOps::FAdd : BinaryOperator::BinaryOps::Add;
case BinOp::SUB:
return is_fp ? BinaryOperator::BinaryOps::FSub : BinaryOperator::BinaryOps::Sub;
case BinOp::MUL:
return is_fp ? BinaryOperator::BinaryOps::FMul : BinaryOperator::BinaryOps::Mul;
case BinOp::UDIV:
return is_fp ? BinaryOperator::BinaryOps::InvalidBinaryOp : BinaryOperator::BinaryOps::UDiv;
case BinOp::SDIV:
return is_fp ? BinaryOperator::BinaryOps::FDiv : BinaryOperator::BinaryOps::SDiv;
case BinOp::UREM:
return is_fp ? BinaryOperator::BinaryOps::InvalidBinaryOp : BinaryOperator::BinaryOps::URem;
case BinOp::SREM:
return is_fp ? BinaryOperator::BinaryOps::FRem : BinaryOperator::BinaryOps::SRem;
case BinOp::SHL:
return is_fp ? BinaryOperator::BinaryOps::InvalidBinaryOp : BinaryOperator::BinaryOps::Shl;
case BinOp::LSHR:
return is_fp ? BinaryOperator::BinaryOps::InvalidBinaryOp : BinaryOperator::BinaryOps::LShr;
case BinOp::ASHR:
return is_fp ? BinaryOperator::BinaryOps::InvalidBinaryOp : BinaryOperator::BinaryOps::AShr;
case BinOp::AND:
return is_fp ? BinaryOperator::BinaryOps::InvalidBinaryOp : BinaryOperator::BinaryOps::And;
case BinOp::OR:
return is_fp ? BinaryOperator::BinaryOps::InvalidBinaryOp : BinaryOperator::BinaryOps::Or;
case BinOp::XOR:
return is_fp ? BinaryOperator::BinaryOps::InvalidBinaryOp : BinaryOperator::BinaryOps::Xor;
default:
return BinaryOperator::BinaryOps::InvalidBinaryOp;
}
}
static Instruction::CastOps translate_castop(CastOp op)
{
switch (op)
{
case CastOp::TRUNC:
return Instruction::Trunc;
case CastOp::ZEXT:
return Instruction::ZExt;
case CastOp::SEXT:
return Instruction::SExt;
case CastOp::FPTOUI:
return Instruction::FPToUI;
case CastOp::FPTOSI:
return Instruction::FPToSI;
case CastOp::UITOFP:
return Instruction::UIToFP;
case CastOp::SITOFP:
return Instruction::SIToFP;
case CastOp::FPTRUNC:
return Instruction::FPTrunc;
case CastOp::FPEXT:
return Instruction::FPExt;
case CastOp::PTRTOINT:
return Instruction::PtrToInt;
case CastOp::INTTOPTR:
return Instruction::IntToPtr;
case CastOp::BITCAST:
return Instruction::BitCast;
case CastOp::ADDSPACECAST:
return Instruction::AddrSpaceCast;
}
return Instruction::CastOps::InvalidCastOp;
}
bool ModuleParseContext::parse_constants_record(const BlockOrRecord &entry)
{
if (entry.IsBlock())
return true;
switch (ConstantsRecord(entry.id))
{
case ConstantsRecord::SETTYPE:
if (entry.ops.size() < 1)
return false;
constant_type = get_type(entry.ops[0]);
break;
case ConstantsRecord::CONST_NULL:
{
auto *type = get_constant_type();
Value *value = nullptr;
if (type->isIntegerTy())
value = ConstantInt::get(type, 0);
else if (type->isFloatingPointTy())
value = ConstantFP::get(type, 0);
else if (isa(type) || isa(type) || isa(type))
value = context->construct(type);
else if (isa(type))
value = context->construct(type);
if (!value)
{
LOGE("Unknown type for CONST_NULL.\n");
return false;
}
values.push_back(value);
break;
}
case ConstantsRecord::UNDEF:
{
auto *type = get_constant_type();
values.push_back(UndefValue::get(type));
break;
}
case ConstantsRecord::INTEGER:
{
if (entry.ops.size() < 1)
return false;
auto *type = get_constant_type();
if (!type->isIntegerTy())
{
LOGE("Constant type is not integer.\n");
return false;
}
uint64_t literal = entry.ops[0];
int64_t signed_literal = decode_sign_rotated_value(literal);
ConstantInt *value = ConstantInt::get(type, signed_literal);
values.push_back(value);
break;
}
case ConstantsRecord::WIDE_INTEGER:
LOGE("WIDE_INTEGER unimplemented.\n");
return false;
case ConstantsRecord::FLOAT:
{
if (entry.ops.size() < 1)
return false;
auto *type = get_constant_type();
if (!type->isFloatingPointTy())
{
LOGE("Constant type is not FP.\n");
return false;
}
ConstantFP *value = ConstantFP::get(type, entry.ops[0]);
values.push_back(value);
break;
}
case ConstantsRecord::AGGREGATE:
{
Vector constants;
Value *value;
constants.reserve(entry.ops.size());
if (auto *struct_type = dyn_cast(get_constant_type()))
{
if (entry.ops.size() != struct_type->getStructNumElements())
{
LOGE("Mismatch in struct element counts.\n");
return false;
}
for (unsigned i = 0; i < struct_type->getStructNumElements(); i++)
constants.push_back(get_value(entry.ops[i], struct_type->getStructElementType(i), true));
value = context->construct(get_constant_type(), std::move(constants));
}
else if (isa(get_constant_type()))
{
auto *element_type = get_constant_type()->getArrayElementType();
for (auto &op : entry.ops)
constants.push_back(get_value(op, element_type, true));
value = context->construct(get_constant_type(), std::move(constants));
}
else if (isa(get_constant_type()))
{
auto *element_type = cast(get_constant_type())->getElementType();
for (auto &op : entry.ops)
constants.push_back(get_value(op, element_type, true));
value = context->construct(get_constant_type(), std::move(constants));
}
else
{
value = UndefValue::get(get_constant_type());
}
values.push_back(value);
break;
}
case ConstantsRecord::STRING:
LOGE("STRING unimplemented.\n");
return false;
case ConstantsRecord::BINOP:
{
unsigned index = 0;
auto *type = get_constant_type();
auto op = translate_binop(BinOp(entry.ops[index++]), type);
auto *a = get_value(entry.ops[index++], type, true);
auto *b = get_value(entry.ops[index++], type, true);
auto elements = Vector