diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -665,6 +665,9 @@ return nullptr; return std::make_unique(Triple, Opts); } + case llvm::Triple::spirv: { + return std::make_unique(Triple, Opts); + } case llvm::Triple::spirv32: { if (os != llvm::Triple::UnknownOS || Triple.getEnvironment() != llvm::Triple::UnknownEnvironment) diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h --- a/clang/lib/Basic/Targets/SPIR.h +++ b/clang/lib/Basic/Targets/SPIR.h @@ -93,10 +93,6 @@ : TargetInfo(Triple) { assert((Triple.isSPIR() || Triple.isSPIRV()) && "Invalid architecture for SPIR or SPIR-V."); - assert(getTriple().getOS() == llvm::Triple::UnknownOS && - "SPIR(-V) target must use unknown OS"); - assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && - "SPIR(-V) target must use unknown environment type"); TLSSupported = false; VLASupported = false; LongWidth = LongAlign = 64; @@ -284,31 +280,53 @@ MacroBuilder &Builder) const override; }; -class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRTargetInfo { +class LLVM_LIBRARY_VISIBILITY BaseSPIRVTargetInfo : public BaseSPIRTargetInfo { public: - SPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + BaseSPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) : BaseSPIRTargetInfo(Triple, Opts) { assert(Triple.isSPIRV() && "Invalid architecture for SPIR-V."); - assert(getTriple().getOS() == llvm::Triple::UnknownOS && - "SPIR-V target must use unknown OS"); - assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && - "SPIR-V target must use unknown environment type"); + } + + bool hasFeature(StringRef Feature) const override { + return Feature == "spirv"; } void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const override; +}; - bool hasFeature(StringRef Feature) const override { - return Feature == "spirv"; +class LLVM_LIBRARY_VISIBILITY SPIRVTargetInfo : public BaseSPIRVTargetInfo { +public: + SPIRVTargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) + : BaseSPIRVTargetInfo(Triple, Opts) { + assert(Triple.getArch() == llvm::Triple::spirv && + "Invalid architecture for Logical SPIR-V."); + assert(Triple.getOS() == llvm::Triple::ShaderModel && + "Logical SPIR-V requires a valid ShaderModel."); + assert(Triple.getEnvironment() >= llvm::Triple::Pixel && + Triple.getEnvironment() <= llvm::Triple::Amplification && + "Logical SPIR-V environment must be a valid shader stage."); + + // SPIR-V IDs are represented with a single 32-bit word. + SizeType = TargetInfo::UnsignedInt; + resetDataLayout("e-i64:64-v16:16-v24:32-v32:32-v48:64-" + "v96:128-v192:256-v256:256-v512:512-v1024:1024"); } + + void getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const override; }; -class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public SPIRVTargetInfo { +class LLVM_LIBRARY_VISIBILITY SPIRV32TargetInfo : public BaseSPIRVTargetInfo { public: SPIRV32TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : SPIRVTargetInfo(Triple, Opts) { + : BaseSPIRVTargetInfo(Triple, Opts) { assert(Triple.getArch() == llvm::Triple::spirv32 && "Invalid architecture for 32-bit SPIR-V."); + assert(getTriple().getOS() == llvm::Triple::UnknownOS && + "32-bit SPIR-V target must use unknown OS"); + assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && + "32-bit SPIR-V target must use unknown environment type"); PointerWidth = PointerAlign = 32; SizeType = TargetInfo::UnsignedInt; PtrDiffType = IntPtrType = TargetInfo::SignedInt; @@ -320,12 +338,16 @@ MacroBuilder &Builder) const override; }; -class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public SPIRVTargetInfo { +class LLVM_LIBRARY_VISIBILITY SPIRV64TargetInfo : public BaseSPIRVTargetInfo { public: SPIRV64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) - : SPIRVTargetInfo(Triple, Opts) { + : BaseSPIRVTargetInfo(Triple, Opts) { assert(Triple.getArch() == llvm::Triple::spirv64 && "Invalid architecture for 64-bit SPIR-V."); + assert(getTriple().getOS() == llvm::Triple::UnknownOS && + "64-bit SPIR-V target must use unknown OS"); + assert(getTriple().getEnvironment() == llvm::Triple::UnknownEnvironment && + "64-bit SPIR-V target must use unknown environment type"); PointerWidth = PointerAlign = 64; SizeType = TargetInfo::UnsignedLong; PtrDiffType = IntPtrType = TargetInfo::SignedLong; diff --git a/clang/lib/Basic/Targets/SPIR.cpp b/clang/lib/Basic/Targets/SPIR.cpp --- a/clang/lib/Basic/Targets/SPIR.cpp +++ b/clang/lib/Basic/Targets/SPIR.cpp @@ -33,19 +33,24 @@ DefineStd(Builder, "SPIR64", Opts); } +void BaseSPIRVTargetInfo::getTargetDefines(const LangOptions &Opts, + MacroBuilder &Builder) const { + DefineStd(Builder, "SPIRV", Opts); +} + void SPIRVTargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { - DefineStd(Builder, "SPIRV", Opts); + BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); } void SPIRV32TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { - SPIRVTargetInfo::getTargetDefines(Opts, Builder); + BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); DefineStd(Builder, "SPIRV32", Opts); } void SPIRV64TargetInfo::getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const { - SPIRVTargetInfo::getTargetDefines(Opts, Builder); + BaseSPIRVTargetInfo::getTargetDefines(Opts, Builder); DefineStd(Builder, "SPIRV64", Opts); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -4049,7 +4049,8 @@ // Validate options for HLSL if (Opts.HLSL) { - bool SupportedTarget = T.getArch() == llvm::Triple::dxil && + bool SupportedTarget = (T.getArch() == llvm::Triple::dxil || + T.getArch() == llvm::Triple::spirv) && T.getOS() == llvm::Triple::ShaderModel; if (!SupportedTarget) Diags.Report(diag::err_drv_hlsl_unsupported_target) << T.str(); diff --git a/llvm/include/llvm/TargetParser/Triple.h b/llvm/include/llvm/TargetParser/Triple.h --- a/llvm/include/llvm/TargetParser/Triple.h +++ b/llvm/include/llvm/TargetParser/Triple.h @@ -96,6 +96,7 @@ hsail64, // AMD HSAIL with 64-bit pointers spir, // SPIR: standard portable IR for OpenCL 32-bit version spir64, // SPIR: standard portable IR for OpenCL 64-bit version + spirv, // SPIR-V with logical memory layout. spirv32, // SPIR-V with 32-bit pointers spirv64, // SPIR-V with 64-bit pointers kalimba, // Kalimba: generic kalimba @@ -760,9 +761,10 @@ return getArch() == Triple::spir || getArch() == Triple::spir64; } - /// Tests whether the target is SPIR-V (32/64-bit). + /// Tests whether the target is SPIR-V (32/64-bit/Logical). bool isSPIRV() const { - return getArch() == Triple::spirv32 || getArch() == Triple::spirv64; + return getArch() == Triple::spirv32 || getArch() == Triple::spirv64 || + getArch() == Triple::spirv; } /// Tests whether the target is NVPTX (32- or 64-bit). diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -70,6 +70,7 @@ case sparcv9: return "sparcv9"; case spir64: return "spir64"; case spir: return "spir"; + case spirv: return "spirv"; case spirv32: return "spirv32"; case spirv64: return "spirv64"; case systemz: return "s390x"; @@ -154,6 +155,7 @@ case spir: case spir64: return "spir"; + case spirv: case spirv32: case spirv64: return "spirv"; @@ -376,6 +378,7 @@ .Case("hsail64", hsail64) .Case("spir", spir) .Case("spir64", spir64) + .Case("spirv", spirv) .Case("spirv32", spirv32) .Case("spirv64", spirv64) .Case("kalimba", kalimba) @@ -516,6 +519,8 @@ .Case("hsail64", Triple::hsail64) .Case("spir", Triple::spir) .Case("spir64", Triple::spir64) + .Cases("spirv", "spirv1.0", "spirv1.1", "spirv1.2", + "spirv1.3", "spirv1.4", "spirv1.5", Triple::spirv) .Cases("spirv32", "spirv32v1.0", "spirv32v1.1", "spirv32v1.2", "spirv32v1.3", "spirv32v1.4", "spirv32v1.5", Triple::spirv32) .Cases("spirv64", "spirv64v1.0", "spirv64v1.1", "spirv64v1.2", @@ -859,6 +864,7 @@ case Triple::wasm64: return Triple::Wasm; + case Triple::spirv: case Triple::spirv32: case Triple::spirv64: return Triple::SPIRV; @@ -1442,6 +1448,7 @@ case llvm::Triple::renderscript64: case llvm::Triple::riscv64: case llvm::Triple::sparcv9: + case llvm::Triple::spirv: case llvm::Triple::spir64: case llvm::Triple::spirv64: case llvm::Triple::systemz: @@ -1536,6 +1543,7 @@ case Triple::riscv64: T.setArch(Triple::riscv32); break; case Triple::sparcv9: T.setArch(Triple::sparc); break; case Triple::spir64: T.setArch(Triple::spir); break; + case Triple::spirv: case Triple::spirv64: T.setArch(Triple::spirv32, getSubArch()); break; @@ -1614,6 +1622,7 @@ case Triple::riscv32: T.setArch(Triple::riscv64); break; case Triple::sparc: T.setArch(Triple::sparcv9); break; case Triple::spir: T.setArch(Triple::spir64); break; + case Triple::spirv: case Triple::spirv32: T.setArch(Triple::spirv64, getSubArch()); break; @@ -1656,6 +1665,7 @@ case Triple::shave: case Triple::spir64: case Triple::spir: + case Triple::spirv: case Triple::spirv32: case Triple::spirv64: case Triple::wasm32: @@ -1765,6 +1775,7 @@ case Triple::sparcel: case Triple::spir64: case Triple::spir: + case Triple::spirv: case Triple::spirv32: case Triple::spirv64: case Triple::tcele: diff --git a/llvm/unittests/TargetParser/TripleTest.cpp b/llvm/unittests/TargetParser/TripleTest.cpp --- a/llvm/unittests/TargetParser/TripleTest.cpp +++ b/llvm/unittests/TargetParser/TripleTest.cpp @@ -319,6 +319,132 @@ EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); EXPECT_EQ(Triple::UnknownOS, T.getOS()); + T = Triple("spirv-unknown-shadermodel-pixel"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Pixel, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-vertex"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Vertex, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-geometry"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Geometry, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-library"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Library, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-raygeneration"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::RayGeneration, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-intersection"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Intersection, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-anyhit"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::AnyHit, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-closesthit"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::ClosestHit, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-miss"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Miss, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-callable"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Callable, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-mesh"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Mesh, T.getEnvironment()); + + T = Triple("spirv-unknown-shadermodel-amplification"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::NoSubArch, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Amplification, T.getEnvironment()); + + T = Triple("spirv1.0-unknown-shadermodel-compute"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::SPIRVSubArch_v10, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Compute, T.getEnvironment()); + + T = Triple("spirv1.1-unknown-shadermodel-compute"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::SPIRVSubArch_v11, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Compute, T.getEnvironment()); + + T = Triple("spirv1.2-unknown-shadermodel-compute"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::SPIRVSubArch_v12, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Compute, T.getEnvironment()); + + T = Triple("spirv1.3-unknown-shadermodel-compute"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::SPIRVSubArch_v13, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Compute, T.getEnvironment()); + + T = Triple("spirv1.4-unknown-shadermodel-compute"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::SPIRVSubArch_v14, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Compute, T.getEnvironment()); + + T = Triple("spirv1.5-unknown-shadermodel-compute"); + EXPECT_EQ(Triple::spirv, T.getArch()); + EXPECT_EQ(Triple::SPIRVSubArch_v15, T.getSubArch()); + EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); + EXPECT_EQ(Triple::ShaderModel, T.getOS()); + EXPECT_EQ(Triple::Compute, T.getEnvironment()); + T = Triple("x86_64-unknown-fuchsia"); EXPECT_EQ(Triple::x86_64, T.getArch()); EXPECT_EQ(Triple::UnknownVendor, T.getVendor()); @@ -1155,6 +1281,12 @@ EXPECT_FALSE(T.isArch32Bit()); EXPECT_TRUE(T.isArch64Bit()); + T.setArch(Triple::spirv); + EXPECT_FALSE(T.isArch16Bit()); + EXPECT_FALSE(T.isArch32Bit()); + EXPECT_TRUE(T.isArch64Bit()); + EXPECT_TRUE(T.isSPIRV()); + T.setArch(Triple::spirv32); EXPECT_FALSE(T.isArch16Bit()); EXPECT_TRUE(T.isArch32Bit()); @@ -1359,6 +1491,10 @@ EXPECT_EQ(Triple::spir, T.get32BitArchVariant().getArch()); EXPECT_EQ(Triple::spir64, T.get64BitArchVariant().getArch()); + T.setArch(Triple::spirv); + EXPECT_EQ(Triple::spirv32, T.get32BitArchVariant().getArch()); + EXPECT_EQ(Triple::spirv64, T.get64BitArchVariant().getArch()); + T.setArch(Triple::spirv32); EXPECT_EQ(Triple::spirv32, T.get32BitArchVariant().getArch()); EXPECT_EQ(Triple::spirv64, T.get64BitArchVariant().getArch()); @@ -1844,6 +1980,7 @@ EXPECT_EQ(Triple::ELF, Triple("csky-unknown-unknown").getObjectFormat()); EXPECT_EQ(Triple::ELF, Triple("csky-unknown-linux").getObjectFormat()); + EXPECT_EQ(Triple::SPIRV, Triple("spirv-unknown-unknown").getObjectFormat()); EXPECT_EQ(Triple::SPIRV, Triple("spirv32-unknown-unknown").getObjectFormat()); EXPECT_EQ(Triple::SPIRV, Triple("spirv64-unknown-unknown").getObjectFormat());