Path: blob/main/contrib/llvm-project/clang/lib/Driver/ToolChains/HLSL.cpp
35266 views
//===--- HLSL.cpp - HLSL ToolChain Implementations --------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "HLSL.h"9#include "CommonArgs.h"10#include "clang/Driver/Compilation.h"11#include "clang/Driver/DriverDiagnostic.h"12#include "clang/Driver/Job.h"13#include "llvm/ADT/StringSwitch.h"14#include "llvm/TargetParser/Triple.h"1516using namespace clang::driver;17using namespace clang::driver::tools;18using namespace clang::driver::toolchains;19using namespace clang;20using namespace llvm::opt;21using namespace llvm;2223namespace {2425const unsigned OfflineLibMinor = 0xF;2627bool isLegalShaderModel(Triple &T) {28if (T.getOS() != Triple::OSType::ShaderModel)29return false;3031auto Version = T.getOSVersion();32if (Version.getBuild())33return false;34if (Version.getSubminor())35return false;3637auto Kind = T.getEnvironment();3839switch (Kind) {40default:41return false;42case Triple::EnvironmentType::Vertex:43case Triple::EnvironmentType::Hull:44case Triple::EnvironmentType::Domain:45case Triple::EnvironmentType::Geometry:46case Triple::EnvironmentType::Pixel:47case Triple::EnvironmentType::Compute: {48VersionTuple MinVer(4, 0);49return MinVer <= Version;50} break;51case Triple::EnvironmentType::Library: {52VersionTuple SM6x(6, OfflineLibMinor);53if (Version == SM6x)54return true;5556VersionTuple MinVer(6, 3);57return MinVer <= Version;58} break;59case Triple::EnvironmentType::Amplification:60case Triple::EnvironmentType::Mesh: {61VersionTuple MinVer(6, 5);62return MinVer <= Version;63} break;64}65return false;66}6768std::optional<std::string> tryParseProfile(StringRef Profile) {69// [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor]70SmallVector<StringRef, 3> Parts;71Profile.split(Parts, "_");72if (Parts.size() != 3)73return std::nullopt;7475Triple::EnvironmentType Kind =76StringSwitch<Triple::EnvironmentType>(Parts[0])77.Case("ps", Triple::EnvironmentType::Pixel)78.Case("vs", Triple::EnvironmentType::Vertex)79.Case("gs", Triple::EnvironmentType::Geometry)80.Case("hs", Triple::EnvironmentType::Hull)81.Case("ds", Triple::EnvironmentType::Domain)82.Case("cs", Triple::EnvironmentType::Compute)83.Case("lib", Triple::EnvironmentType::Library)84.Case("ms", Triple::EnvironmentType::Mesh)85.Case("as", Triple::EnvironmentType::Amplification)86.Default(Triple::EnvironmentType::UnknownEnvironment);87if (Kind == Triple::EnvironmentType::UnknownEnvironment)88return std::nullopt;8990unsigned long long Major = 0;91if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))92return std::nullopt;9394unsigned long long Minor = 0;95if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library)96Minor = OfflineLibMinor;97else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))98return std::nullopt;99100// Determine DXIL version using the minor version number of Shader101// Model version specified in target profile. Prior to decoupling DXIL version102// numbering from that of Shader Model DXIL version 1.Y corresponds to SM 6.Y.103// E.g., dxilv1.Y-unknown-shadermodelX.Y-hull104llvm::Triple T;105Triple::SubArchType SubArch = llvm::Triple::NoSubArch;106switch (Minor) {107case 0:108SubArch = llvm::Triple::DXILSubArch_v1_0;109break;110case 1:111SubArch = llvm::Triple::DXILSubArch_v1_1;112break;113case 2:114SubArch = llvm::Triple::DXILSubArch_v1_2;115break;116case 3:117SubArch = llvm::Triple::DXILSubArch_v1_3;118break;119case 4:120SubArch = llvm::Triple::DXILSubArch_v1_4;121break;122case 5:123SubArch = llvm::Triple::DXILSubArch_v1_5;124break;125case 6:126SubArch = llvm::Triple::DXILSubArch_v1_6;127break;128case 7:129SubArch = llvm::Triple::DXILSubArch_v1_7;130break;131case 8:132SubArch = llvm::Triple::DXILSubArch_v1_8;133break;134case OfflineLibMinor:135// Always consider minor version x as the latest supported DXIL version136SubArch = llvm::Triple::LatestDXILSubArch;137break;138default:139// No DXIL Version corresponding to specified Shader Model version found140return std::nullopt;141}142T.setArch(Triple::ArchType::dxil, SubArch);143T.setOSName(Triple::getOSTypeName(Triple::OSType::ShaderModel).str() +144VersionTuple(Major, Minor).getAsString());145T.setEnvironment(Kind);146if (isLegalShaderModel(T))147return T.getTriple();148else149return std::nullopt;150}151152bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {153VersionTuple Version;154if (Version.tryParse(ValVersionStr) || Version.getBuild() ||155Version.getSubminor() || !Version.getMinor()) {156D.Diag(diag::err_drv_invalid_format_dxil_validator_version)157<< ValVersionStr;158return false;159}160161uint64_t Major = Version.getMajor();162uint64_t Minor = *Version.getMinor();163if (Major == 0 && Minor != 0) {164D.Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr;165return false;166}167VersionTuple MinVer(1, 0);168if (Version < MinVer) {169D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;170return false;171}172return true;173}174175} // namespace176177void tools::hlsl::Validator::ConstructJob(Compilation &C, const JobAction &JA,178const InputInfo &Output,179const InputInfoList &Inputs,180const ArgList &Args,181const char *LinkingOutput) const {182std::string DxvPath = getToolChain().GetProgramPath("dxv");183assert(DxvPath != "dxv" && "cannot find dxv");184185ArgStringList CmdArgs;186assert(Inputs.size() == 1 && "Unable to handle multiple inputs.");187const InputInfo &Input = Inputs[0];188assert(Input.isFilename() && "Unexpected verify input");189// Grabbing the output of the earlier cc1 run.190CmdArgs.push_back(Input.getFilename());191// Use the same name as output.192CmdArgs.push_back("-o");193CmdArgs.push_back(Input.getFilename());194195const char *Exec = Args.MakeArgString(DxvPath);196C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),197Exec, CmdArgs, Inputs, Input));198}199200/// DirectX Toolchain201HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,202const ArgList &Args)203: ToolChain(D, Triple, Args) {204if (Args.hasArg(options::OPT_dxc_validator_path_EQ))205getProgramPaths().push_back(206Args.getLastArgValue(options::OPT_dxc_validator_path_EQ).str());207}208209Tool *clang::driver::toolchains::HLSLToolChain::getTool(210Action::ActionClass AC) const {211switch (AC) {212case Action::BinaryAnalyzeJobClass:213if (!Validator)214Validator.reset(new tools::hlsl::Validator(*this));215return Validator.get();216default:217return ToolChain::getTool(AC);218}219}220221std::optional<std::string>222clang::driver::toolchains::HLSLToolChain::parseTargetProfile(223StringRef TargetProfile) {224return tryParseProfile(TargetProfile);225}226227DerivedArgList *228HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,229Action::OffloadKind DeviceOffloadKind) const {230DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());231232const OptTable &Opts = getDriver().getOpts();233234for (Arg *A : Args) {235if (A->getOption().getID() == options::OPT_dxil_validator_version) {236StringRef ValVerStr = A->getValue();237std::string ErrorMsg;238if (!isLegalValidatorVersion(ValVerStr, getDriver()))239continue;240}241if (A->getOption().getID() == options::OPT_dxc_entrypoint) {242DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_hlsl_entrypoint),243A->getValue());244A->claim();245continue;246}247if (A->getOption().getID() == options::OPT__SLASH_O) {248StringRef OStr = A->getValue();249if (OStr == "d") {250DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_O0));251A->claim();252continue;253} else {254DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), OStr);255A->claim();256continue;257}258}259if (A->getOption().getID() == options::OPT_emit_pristine_llvm) {260// Translate -fcgl into -emit-llvm and -disable-llvm-passes.261DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_emit_llvm));262DAL->AddFlagArg(nullptr,263Opts.getOption(options::OPT_disable_llvm_passes));264A->claim();265continue;266}267if (A->getOption().getID() == options::OPT_dxc_hlsl_version) {268// Translate -HV into -std for llvm269// depending on the value given270LangStandard::Kind LangStd = LangStandard::getHLSLLangKind(A->getValue());271if (LangStd != LangStandard::lang_unspecified) {272LangStandard l = LangStandard::getLangStandardForKind(LangStd);273DAL->AddSeparateArg(nullptr, Opts.getOption(options::OPT_std_EQ),274l.getName());275} else {276getDriver().Diag(diag::err_drv_invalid_value) << "HV" << A->getValue();277}278279A->claim();280continue;281}282DAL->append(A);283}284285// Add default validator version if not set.286// TODO: remove this once read validator version from validator.287if (!DAL->hasArg(options::OPT_dxil_validator_version)) {288const StringRef DefaultValidatorVer = "1.7";289DAL->AddSeparateArg(nullptr,290Opts.getOption(options::OPT_dxil_validator_version),291DefaultValidatorVer);292}293if (!DAL->hasArg(options::OPT_O_Group)) {294DAL->AddJoinedArg(nullptr, Opts.getOption(options::OPT_O), "3");295}296297return DAL;298}299300bool HLSLToolChain::requiresValidation(DerivedArgList &Args) const {301if (Args.getLastArg(options::OPT_dxc_disable_validation))302return false;303304std::string DxvPath = GetProgramPath("dxv");305if (DxvPath != "dxv")306return true;307308getDriver().Diag(diag::warn_drv_dxc_missing_dxv);309return false;310}311312313