HLSL supports half type. When enable-16bit-types is not set, half will be treated as float. When enable-16bit-types is set, half will be treated like real 16bit float type and map to llvm half type. Also change CXXABI to Microsoft to match dxc behavior. The mangle name for half is "$f16@" when half is treat as native half type and "$halff@" when treat as float. In AST, half is still half. The special thing is done at clang codeGen, when NativeHalfType is false, half will translated into float. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D124790
184 lines
5.8 KiB
C++
184 lines
5.8 KiB
C++
//===--- 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;
|
|
}
|
|
|
|
llvm::Optional<std::string> tryParseProfile(StringRef Profile) {
|
|
// [ps|vs|gs|hs|ds|cs|ms|as]_[major]_[minor]
|
|
SmallVector<StringRef, 3> Parts;
|
|
Profile.split(Parts, "_");
|
|
if (Parts.size() != 3)
|
|
return NoneType();
|
|
|
|
Triple::EnvironmentType Kind =
|
|
StringSwitch<Triple::EnvironmentType>(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 NoneType();
|
|
|
|
unsigned long long Major = 0;
|
|
if (llvm::getAsUnsignedInteger(Parts[1], 0, Major))
|
|
return NoneType();
|
|
|
|
unsigned long long Minor = 0;
|
|
if (Parts[2] == "x" && Kind == Triple::EnvironmentType::Library)
|
|
Minor = OfflineLibMinor;
|
|
else if (llvm::getAsUnsignedInteger(Parts[2], 0, Minor))
|
|
return NoneType();
|
|
|
|
// 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 NoneType();
|
|
}
|
|
|
|
bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
|
|
VersionTuple Version;
|
|
if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
|
|
Version.getSubminor() || !Version.getMinor()) {
|
|
D.Diag(diag::err_drv_invalid_format_dxil_validator_version)
|
|
<< ValVersionStr;
|
|
return false;
|
|
}
|
|
|
|
uint64_t Major = Version.getMajor();
|
|
uint64_t Minor = *Version.getMinor();
|
|
if (Major == 0 && Minor != 0) {
|
|
D.Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr;
|
|
return false;
|
|
}
|
|
VersionTuple MinVer(1, 0);
|
|
if (Version < MinVer) {
|
|
D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
/// DirectX Toolchain
|
|
HLSLToolChain::HLSLToolChain(const Driver &D, const llvm::Triple &Triple,
|
|
const ArgList &Args)
|
|
: ToolChain(D, Triple, Args) {}
|
|
|
|
llvm::Optional<std::string>
|
|
clang::driver::toolchains::HLSLToolChain::parseTargetProfile(
|
|
StringRef TargetProfile) {
|
|
return tryParseProfile(TargetProfile);
|
|
}
|
|
|
|
DerivedArgList *
|
|
HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
|
|
Action::OffloadKind DeviceOffloadKind) const {
|
|
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
|
|
|
|
const OptTable &Opts = getDriver().getOpts();
|
|
|
|
for (Arg *A : Args) {
|
|
if (A->getOption().getID() == options::OPT_dxil_validator_version) {
|
|
StringRef ValVerStr = A->getValue();
|
|
std::string ErrorMsg;
|
|
if (!isLegalValidatorVersion(ValVerStr, getDriver()))
|
|
continue;
|
|
}
|
|
if (A->getOption().getID() == options::OPT_emit_pristine_llvm) {
|
|
// Translate fcgl into -S -emit-llvm and -disable-llvm-passes.
|
|
DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_S));
|
|
DAL->AddFlagArg(nullptr, Opts.getOption(options::OPT_emit_llvm));
|
|
DAL->AddFlagArg(nullptr,
|
|
Opts.getOption(options::OPT_disable_llvm_passes));
|
|
A->claim();
|
|
continue;
|
|
}
|
|
DAL->append(A);
|
|
}
|
|
// Add default validator version if not set.
|
|
// TODO: remove this once read validator version from validator.
|
|
if (!DAL->hasArg(options::OPT_dxil_validator_version)) {
|
|
const StringRef DefaultValidatorVer = "1.7";
|
|
DAL->AddSeparateArg(nullptr,
|
|
Opts.getOption(options::OPT_dxil_validator_version),
|
|
DefaultValidatorVer);
|
|
}
|
|
// FIXME: add validation for enable_16bit_types should be after HLSL 2018 and
|
|
// shader model 6.2.
|
|
return DAL;
|
|
}
|