1*81ad6265SDimitry Andric //===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===// 2*81ad6265SDimitry Andric // 3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*81ad6265SDimitry Andric // 7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===// 8*81ad6265SDimitry Andric 9*81ad6265SDimitry Andric #include "HLSL.h" 10*81ad6265SDimitry Andric #include "CommonArgs.h" 11*81ad6265SDimitry Andric #include "clang/Driver/DriverDiagnostic.h" 12*81ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h" 13*81ad6265SDimitry Andric #include "llvm/ADT/Triple.h" 14*81ad6265SDimitry Andric 15*81ad6265SDimitry Andric using namespace clang::driver; 16*81ad6265SDimitry Andric using namespace clang::driver::tools; 17*81ad6265SDimitry Andric using namespace clang::driver::toolchains; 18*81ad6265SDimitry Andric using namespace clang; 19*81ad6265SDimitry Andric using namespace llvm::opt; 20*81ad6265SDimitry Andric using namespace llvm; 21*81ad6265SDimitry Andric 22*81ad6265SDimitry Andric namespace { 23*81ad6265SDimitry Andric 24*81ad6265SDimitry Andric const unsigned OfflineLibMinor = 0xF; 25*81ad6265SDimitry Andric 26*81ad6265SDimitry Andric bool isLegalShaderModel(Triple &T) { 27*81ad6265SDimitry Andric if (T.getOS() != Triple::OSType::ShaderModel) 28*81ad6265SDimitry Andric return false; 29*81ad6265SDimitry Andric 30*81ad6265SDimitry Andric auto Version = T.getOSVersion(); 31*81ad6265SDimitry Andric if (Version.getBuild()) 32*81ad6265SDimitry Andric return false; 33*81ad6265SDimitry Andric if (Version.getSubminor()) 34*81ad6265SDimitry Andric return false; 35*81ad6265SDimitry Andric 36*81ad6265SDimitry Andric auto Kind = T.getEnvironment(); 37*81ad6265SDimitry Andric 38*81ad6265SDimitry Andric switch (Kind) { 39*81ad6265SDimitry Andric default: 40*81ad6265SDimitry Andric return false; 41*81ad6265SDimitry Andric case Triple::EnvironmentType::Vertex: 42*81ad6265SDimitry Andric case Triple::EnvironmentType::Hull: 43*81ad6265SDimitry Andric case Triple::EnvironmentType::Domain: 44*81ad6265SDimitry Andric case Triple::EnvironmentType::Geometry: 45*81ad6265SDimitry Andric case Triple::EnvironmentType::Pixel: 46*81ad6265SDimitry Andric case Triple::EnvironmentType::Compute: { 47*81ad6265SDimitry Andric VersionTuple MinVer(4, 0); 48*81ad6265SDimitry Andric return MinVer <= Version; 49*81ad6265SDimitry Andric } break; 50*81ad6265SDimitry Andric case Triple::EnvironmentType::Library: { 51*81ad6265SDimitry Andric VersionTuple SM6x(6, OfflineLibMinor); 52*81ad6265SDimitry Andric if (Version == SM6x) 53*81ad6265SDimitry Andric return true; 54*81ad6265SDimitry Andric 55*81ad6265SDimitry Andric VersionTuple MinVer(6, 3); 56*81ad6265SDimitry Andric return MinVer <= Version; 57*81ad6265SDimitry Andric } break; 58*81ad6265SDimitry Andric case Triple::EnvironmentType::Amplification: 59*81ad6265SDimitry Andric case Triple::EnvironmentType::Mesh: { 60*81ad6265SDimitry Andric VersionTuple MinVer(6, 5); 61*81ad6265SDimitry Andric return MinVer <= Version; 62*81ad6265SDimitry Andric } break; 63*81ad6265SDimitry Andric } 64*81ad6265SDimitry Andric return false; 65*81ad6265SDimitry Andric } 66*81ad6265SDimitry Andric 67*81ad6265SDimitry Andric llvm::Optional<std::string> tryParseProfile(StringRef Profile) { 68*81ad6265SDimitry Andric // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor] 69*81ad6265SDimitry Andric SmallVector<StringRef, 3> Parts; 70*81ad6265SDimitry Andric Profile.split(Parts, "_"); 71*81ad6265SDimitry Andric if (Parts.size() != 3) 72*81ad6265SDimitry Andric return NoneType(); 73*81ad6265SDimitry Andric 74*81ad6265SDimitry Andric Triple::EnvironmentType Kind = 75*81ad6265SDimitry Andric StringSwitch<Triple::EnvironmentType>(Parts[0]) 76*81ad6265SDimitry Andric .Case("ps", Triple::EnvironmentType::Pixel) 77*81ad6265SDimitry Andric .Case("vs", Triple::EnvironmentType::Vertex) 78*81ad6265SDimitry Andric .Case("gs", Triple::EnvironmentType::Geometry) 79*81ad6265SDimitry Andric .Case("hs", Triple::EnvironmentType::Hull) 80*81ad6265SDimitry Andric .Case("ds", Triple::EnvironmentType::Domain) 81*81ad6265SDimitry Andric .Case("cs", Triple::EnvironmentType::Compute) 82*81ad6265SDimitry Andric .Case("lib", Triple::EnvironmentType::Library) 83*81ad6265SDimitry Andric .Case("ms", Triple::EnvironmentType::Mesh) 84*81ad6265SDimitry Andric .Case("as", Triple::EnvironmentType::Amplification) 85*81ad6265SDimitry Andric .Default(Triple::EnvironmentType::UnknownEnvironment); 86*81ad6265SDimitry Andric if (Kind == Triple::EnvironmentType::UnknownEnvironment) 87*81ad6265SDimitry Andric return NoneType(); 88*81ad6265SDimitry Andric 89*81ad6265SDimitry Andric unsigned long long Major = 0; 90*81ad6265SDimitry Andric if (llvm::getAsUnsignedInteger(Parts[1], 0, Major)) 91*81ad6265SDimitry Andric return NoneType(); 92*81ad6265SDimitry Andric 93*81ad6265SDimitry Andric unsigned long long Minor = 0; 94*81ad6265SDimitry Andric if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library) 95*81ad6265SDimitry Andric Minor = OfflineLibMinor; 96*81ad6265SDimitry Andric else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor)) 97*81ad6265SDimitry Andric return NoneType(); 98*81ad6265SDimitry Andric 99*81ad6265SDimitry Andric // dxil-unknown-shadermodel-hull 100*81ad6265SDimitry Andric llvm::Triple T; 101*81ad6265SDimitry Andric T.setArch(Triple::ArchType::dxil); 102*81ad6265SDimitry Andric T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() + 103*81ad6265SDimitry Andric VersionTuple(Major, Minor).getAsString()); 104*81ad6265SDimitry Andric T.setEnvironment(Kind); 105*81ad6265SDimitry Andric if (isLegalShaderModel(T)) 106*81ad6265SDimitry Andric return T.getTriple(); 107*81ad6265SDimitry Andric else 108*81ad6265SDimitry Andric return NoneType(); 109*81ad6265SDimitry Andric } 110*81ad6265SDimitry Andric 111*81ad6265SDimitry Andric bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) { 112*81ad6265SDimitry Andric VersionTuple Version; 113*81ad6265SDimitry Andric if (Version.tryParse(ValVersionStr) || Version.getBuild() || 114*81ad6265SDimitry Andric Version.getSubminor() || !Version.getMinor()) { 115*81ad6265SDimitry Andric D.Diag(diag::err_drv_invalid_format_dxil_validator_version) 116*81ad6265SDimitry Andric << ValVersionStr; 117*81ad6265SDimitry Andric return false; 118*81ad6265SDimitry Andric } 119*81ad6265SDimitry Andric 120*81ad6265SDimitry Andric uint64_t Major = Version.getMajor(); 121*81ad6265SDimitry Andric uint64_t Minor = *Version.getMinor(); 122*81ad6265SDimitry Andric if (Major == 0 && Minor != 0) { 123*81ad6265SDimitry Andric D.Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr; 124*81ad6265SDimitry Andric return false; 125*81ad6265SDimitry Andric } 126*81ad6265SDimitry Andric VersionTuple MinVer(1, 0); 127*81ad6265SDimitry Andric if (Version < MinVer) { 128*81ad6265SDimitry Andric D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr; 129*81ad6265SDimitry Andric return false; 130*81ad6265SDimitry Andric } 131*81ad6265SDimitry Andric return true; 132*81ad6265SDimitry Andric } 133*81ad6265SDimitry Andric 134*81ad6265SDimitry Andric } // namespace 135*81ad6265SDimitry Andric 136*81ad6265SDimitry Andric /// DirectX Toolchain 137*81ad6265SDimitry Andric HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple, 138*81ad6265SDimitry Andric const ArgList &Args) 139*81ad6265SDimitry Andric : ToolChain(D, Triple, Args) {} 140*81ad6265SDimitry Andric 141*81ad6265SDimitry Andric llvm::Optional<std::string> 142*81ad6265SDimitry Andric clang::driver::toolchains::HLSLToolChain::parseTargetProfile( 143*81ad6265SDimitry Andric StringRef TargetProfile) { 144*81ad6265SDimitry Andric return tryParseProfile(TargetProfile); 145*81ad6265SDimitry Andric } 146*81ad6265SDimitry Andric 147*81ad6265SDimitry Andric DerivedArgList * 148*81ad6265SDimitry Andric HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch, 149*81ad6265SDimitry Andric Action::OffloadKind DeviceOffloadKind) const { 150*81ad6265SDimitry Andric DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 151*81ad6265SDimitry Andric 152*81ad6265SDimitry Andric const OptTable &Opts = getDriver().getOpts(); 153*81ad6265SDimitry Andric 154*81ad6265SDimitry Andric for (Arg *A : Args) { 155*81ad6265SDimitry Andric if (A->getOption().getID() == options::OPT_dxil_validator_version) { 156*81ad6265SDimitry Andric StringRef ValVerStr = A->getValue(); 157*81ad6265SDimitry Andric std::string ErrorMsg; 158*81ad6265SDimitry Andric if (!isLegalValidatorVersion(ValVerStr, getDriver())) 159*81ad6265SDimitry Andric continue; 160*81ad6265SDimitry Andric } 161*81ad6265SDimitry Andric if (A->getOption().getID() == options::OPT_emit_pristine_llvm) { 162*81ad6265SDimitry Andric // Translate fcgl into -S -emit-llvm and -disable-llvm-passes. 163*81ad6265SDimitry Andric DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_S)); 164*81ad6265SDimitry Andric DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_emit_llvm)); 165*81ad6265SDimitry Andric DAL->AddFlagArg(nullptr, 166*81ad6265SDimitry Andric Opts.getOption(options::OPT_disable_llvm_passes)); 167*81ad6265SDimitry Andric A->claim(); 168*81ad6265SDimitry Andric continue; 169*81ad6265SDimitry Andric } 170*81ad6265SDimitry Andric DAL->append(A); 171*81ad6265SDimitry Andric } 172*81ad6265SDimitry Andric // Add default validator version if not set. 173*81ad6265SDimitry Andric // TODO: remove this once read validator version from validator. 174*81ad6265SDimitry Andric if (!DAL->hasArg(options::OPT_dxil_validator_version)) { 175*81ad6265SDimitry Andric const StringRef DefaultValidatorVer = "1.7"; 176*81ad6265SDimitry Andric DAL->AddSeparateArg(nullptr, 177*81ad6265SDimitry Andric Opts.getOption(options::OPT_dxil_validator_version), 178*81ad6265SDimitry Andric DefaultValidatorVer); 179*81ad6265SDimitry Andric } 180*81ad6265SDimitry Andric // FIXME: add validation for enable_16bit_types should be after HLSL 2018 and 181*81ad6265SDimitry Andric // shader model 6.2. 182*81ad6265SDimitry Andric return DAL; 183*81ad6265SDimitry Andric } 184