//===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "HLSL.h" #include "CommonArgs.h" #include "clang/Driver/DriverDiagnostic.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Triple.h" using namespace clang::driver; using namespace clang::driver::tools; using namespace clang::driver::toolchains; using namespace clang; using namespace llvm::opt; using namespace llvm; namespace { const unsigned OfflineLibMinor = 0xF; bool isLegalShaderModel(Triple &T) { if (T.getOS() != Triple::OSType::ShaderModel) return false; auto Version = T.getOSVersion(); if (Version.getBuild()) return false; if (Version.getSubminor()) return false; auto Kind = T.getEnvironment(); switch (Kind) { default: return false; case Triple::EnvironmentType::Vertex: case Triple::EnvironmentType::Hull: case Triple::EnvironmentType::Domain: case Triple::EnvironmentType::Geometry: case Triple::EnvironmentType::Pixel: case Triple::EnvironmentType::Compute: { VersionTuple MinVer(4, 0); return MinVer <= Version; } break; case Triple::EnvironmentType::Library: { VersionTuple SM6x(6, OfflineLibMinor); if (Version == SM6x) return true; VersionTuple MinVer(6, 3); return MinVer <= Version; } break; case Triple::EnvironmentType::Amplification: case Triple::EnvironmentType::Mesh: { VersionTuple MinVer(6, 5); return MinVer <= Version; } break; } return false; } std::string tryParseProfile(StringRef Profile) { // [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor] SmallVector Parts; Profile.split(Parts, "_"); if (Parts.size() != 3) return ""; Triple::EnvironmentType Kind = StringSwitch(Parts[0]) .Case("ps", Triple::EnvironmentType::Pixel) .Case("vs", Triple::EnvironmentType::Vertex) .Case("gs", Triple::EnvironmentType::Geometry) .Case("hs", Triple::EnvironmentType::Hull) .Case("ds", Triple::EnvironmentType::Domain) .Case("cs", Triple::EnvironmentType::Compute) .Case("lib", Triple::EnvironmentType::Library) .Case("ms", Triple::EnvironmentType::Mesh) .Case("as", Triple::EnvironmentType::Amplification) .Default(Triple::EnvironmentType::UnknownEnvironment); if (Kind == Triple::EnvironmentType::UnknownEnvironment) return ""; unsigned long long Major = 0; if (llvm::getAsUnsignedInteger(Parts[1], 0, Major)) return ""; unsigned long long Minor = 0; if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library) Minor = OfflineLibMinor; else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor)) return ""; // dxil-unknown-shadermodel-hull llvm::Triple T; T.setArch(Triple::ArchType::dxil); T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() + VersionTuple(Major, Minor).getAsString()); T.setEnvironment(Kind); if (isLegalShaderModel(T)) return T.getTriple(); else return ""; } } // namespace /// DirectX Toolchain HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args) {} std::string HLSLToolChain::ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const { if (Arg *A = Args.getLastArg(options::OPT_target_profile)) { StringRef Profile = A->getValue(); std::string Triple = tryParseProfile(Profile); if (Triple == "") { getDriver().Diag(diag::err_drv_invalid_directx_shader_module) << Profile; Triple = ToolChain::ComputeEffectiveClangTriple(Args, InputType); } A->claim(); return Triple; } else { return ToolChain::ComputeEffectiveClangTriple(Args, InputType); } }