1 //===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "HLSL.h" 10 #include "CommonArgs.h" 11 #include "clang/Driver/DriverDiagnostic.h" 12 #include "llvm/ADT/StringSwitch.h" 13 #include "llvm/ADT/Triple.h" 14 15 using namespace clang::driver; 16 using namespace clang::driver::tools; 17 using namespace clang::driver::toolchains; 18 using namespace clang; 19 using namespace llvm::opt; 20 using namespace llvm; 21 22 namespace { 23 24 const unsigned OfflineLibMinor = 0xF; 25 26 bool isLegalShaderModel(Triple &T) { 27 if (T.getOS() != Triple::OSType::ShaderModel) 28 return false; 29 30 auto Version = T.getOSVersion(); 31 if (Version.getBuild()) 32 return false; 33 if (Version.getSubminor()) 34 return false; 35 36 auto Kind = T.getEnvironment(); 37 38 switch (Kind) { 39 default: 40 return false; 41 case Triple::EnvironmentType::Vertex: 42 case Triple::EnvironmentType::Hull: 43 case Triple::EnvironmentType::Domain: 44 case Triple::EnvironmentType::Geometry: 45 case Triple::EnvironmentType::Pixel: 46 case Triple::EnvironmentType::Compute: { 47 VersionTuple MinVer(4, 0); 48 return MinVer <= Version; 49 } break; 50 case Triple::EnvironmentType::Library: { 51 VersionTuple SM6x(6, OfflineLibMinor); 52 if (Version == SM6x) 53 return true; 54 55 VersionTuple MinVer(6, 3); 56 return MinVer <= Version; 57 } break; 58 case Triple::EnvironmentType::Amplification: 59 case Triple::EnvironmentType::Mesh: { 60 VersionTuple MinVer(6, 5); 61 return MinVer <= Version; 62 } break; 63 } 64 return false; 65 } 66 67 std::string tryParseProfile(StringRef Profile) { 68 // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor] 69 SmallVector<StringRef, 3> Parts; 70 Profile.split(Parts, "_"); 71 if (Parts.size() != 3) 72 return ""; 73 74 Triple::EnvironmentType Kind = 75 StringSwitch<Triple::EnvironmentType>(Parts[0]) 76 .Case("ps", Triple::EnvironmentType::Pixel) 77 .Case("vs", Triple::EnvironmentType::Vertex) 78 .Case("gs", Triple::EnvironmentType::Geometry) 79 .Case("hs", Triple::EnvironmentType::Hull) 80 .Case("ds", Triple::EnvironmentType::Domain) 81 .Case("cs", Triple::EnvironmentType::Compute) 82 .Case("lib", Triple::EnvironmentType::Library) 83 .Case("ms", Triple::EnvironmentType::Mesh) 84 .Case("as", Triple::EnvironmentType::Amplification) 85 .Default(Triple::EnvironmentType::UnknownEnvironment); 86 if (Kind == Triple::EnvironmentType::UnknownEnvironment) 87 return ""; 88 89 unsigned long long Major = 0; 90 if (llvm::getAsUnsignedInteger(Parts[1], 0, Major)) 91 return ""; 92 93 unsigned long long Minor = 0; 94 if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library) 95 Minor = OfflineLibMinor; 96 else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor)) 97 return ""; 98 99 // dxil-unknown-shadermodel-hull 100 llvm::Triple T; 101 T.setArch(Triple::ArchType::dxil); 102 T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() + 103 VersionTuple(Major, Minor).getAsString()); 104 T.setEnvironment(Kind); 105 if (isLegalShaderModel(T)) 106 return T.getTriple(); 107 else 108 return ""; 109 } 110 111 } // namespace 112 113 /// DirectX Toolchain 114 HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple, 115 const ArgList &Args) 116 : ToolChain(D, Triple, Args) {} 117 118 std::string 119 HLSLToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 120 types::ID InputType) const { 121 if (Arg *A = Args.getLastArg(options::OPT_target_profile)) { 122 StringRef Profile = A->getValue(); 123 std::string Triple = tryParseProfile(Profile); 124 if (Triple == "") { 125 getDriver().Diag(diag::err_drv_invalid_directx_shader_module) << Profile; 126 Triple = ToolChain::ComputeEffectiveClangTriple(Args, InputType); 127 } 128 A->claim(); 129 return Triple; 130 } else { 131 return ToolChain::ComputeEffectiveClangTriple(Args, InputType); 132 } 133 } 134