Skip to content

Commit 73417c5

Browse files
committed
[HLSL][clang][Driver] Support validator version command line option.
The DXIL validator version option(/validator-version) decide the validator version when compile hlsl. The format is major.minor like 1.0. In normal case, the value of validator version should be got from DXIL validator. Before we got DXIL validator ready for llvm/main, DXIL validator version option is added first to set validator version. It will affect code generation for DXIL, so it is treated as a code gen option. A new member std::string DxilValidatorVersion is added to clang::CodeGenOptions. Then CGHLSLRuntime is added to clang::CodeGenModule. It is used to translate clang::CodeGenOptions::DxilValidatorVersion into a ModuleFlag under key "dx.valver" at end of clang code generation. Reviewed By: beanz Differential Revision: https://reviews.llvm.org/D123884
1 parent 6918a15 commit 73417c5

File tree

13 files changed

+336
-32
lines changed

13 files changed

+336
-32
lines changed

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -667,4 +667,13 @@ def err_drv_target_variant_invalid : Error<
667667
def err_drv_invalid_directx_shader_module : Error<
668668
"invalid profile : %0">;
669669

670+
def err_drv_invalid_range_dxil_validator_version : Error<
671+
"invalid validator version : %0\n"
672+
"Validator version must be less than or equal to current internal version.">;
673+
def err_drv_invalid_format_dxil_validator_version : Error<
674+
"invalid validator version : %0\n"
675+
"Format of validator version is \"<major>.<minor>\" (ex:\"1.4\").">;
676+
def err_drv_invalid_empty_dxil_validator_version : Error<
677+
"invalid validator version : %0\n"
678+
"If validator major version is 0, minor version must also be 0.">;
670679
}

clang/include/clang/Basic/TargetOptions.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,11 @@ class TargetOptions {
110110
/// The version of the darwin target variant SDK which was used during the
111111
/// compilation.
112112
llvm::VersionTuple DarwinTargetVariantSDKVersion;
113+
114+
/// The validator version for dxil.
115+
std::string DxilValidatorVersion;
113116
};
114117

115-
} // end namespace clang
118+
} // end namespace clang
116119

117120
#endif

clang/include/clang/Driver/Options.td

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6736,20 +6736,21 @@ def _SLASH_ZW : CLJoined<"ZW">;
67366736

67376737
def dxc_Group : OptionGroup<"<clang-dxc options>">, Flags<[DXCOption]>,
67386738
HelpText<"dxc compatibility options">;
6739-
67406739
class DXCJoinedOrSeparate<string name> : Option<["/", "-"], name,
67416740
KIND_JOINED_OR_SEPARATE>, Group<dxc_Group>, Flags<[DXCOption, NoXarchOption]>;
67426741

67436742
def dxc_help : Option<["/", "-", "--"], "help", KIND_JOINED>,
67446743
Group<dxc_Group>, Flags<[DXCOption, NoXarchOption]>, Alias<help>,
67456744
HelpText<"Display available options">;
6746-
6747-
67486745
def Fo : DXCJoinedOrSeparate<"Fo">, Alias<o>,
6749-
HelpText<"Output object file.">;
6750-
6746+
HelpText<"Output object file">;
6747+
def dxil_validator_version : Option<["/", "-"], "validator-version", KIND_SEPARATE>,
6748+
Group<dxc_Group>, Flags<[DXCOption, NoXarchOption, CC1Option, HelpHidden]>,
6749+
HelpText<"Override validator version for module. Format: <major.minor>;"
6750+
"Default: DXIL.dll version or current internal version">,
6751+
MarshallingInfoString<TargetOpts<"DxilValidatorVersion">>;
67516752
def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"<profile>">,
6752-
HelpText<"Set target profile.">,
6753+
HelpText<"Set target profile">,
67536754
Values<"ps_6_0, ps_6_1, ps_6_2, ps_6_3, ps_6_4, ps_6_5, ps_6_6, ps_6_7,"
67546755
"vs_6_0, vs_6_1, vs_6_2, vs_6_3, vs_6_4, vs_6_5, vs_6_6, vs_6_7,"
67556756
"gs_6_0, gs_6_1, gs_6_2, gs_6_3, gs_6_4, gs_6_5, gs_6_6, gs_6_7,"

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//===----- CGHLSLRuntime.cpp - Interface to HLSL Runtimes -----------------===//
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+
// This provides an abstract class for HLSL code generation. Concrete
10+
// subclasses of this implement code generation for specific HLSL
11+
// runtime libraries.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "CGHLSLRuntime.h"
16+
#include "CodeGenModule.h"
17+
#include "clang/Basic/TargetOptions.h"
18+
#include "llvm/IR/Metadata.h"
19+
#include "llvm/IR/Module.h"
20+
21+
using namespace clang;
22+
using namespace CodeGen;
23+
using namespace llvm;
24+
25+
namespace {
26+
void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) {
27+
// The validation of ValVersionStr is done at HLSLToolChain::TranslateArgs.
28+
// Assume ValVersionStr is legal here.
29+
VersionTuple Version;
30+
if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
31+
Version.getSubminor() || !Version.getMinor()) {
32+
return;
33+
}
34+
35+
uint64_t Major = Version.getMajor();
36+
uint64_t Minor = Version.getMinor().getValue();
37+
38+
auto &Ctx = M.getContext();
39+
IRBuilder<> B(M.getContext());
40+
MDNode *Val = MDNode::get(Ctx, {ConstantAsMetadata::get(B.getInt32(Major)),
41+
ConstantAsMetadata::get(B.getInt32(Minor))});
42+
StringRef DxilValKey = "dx.valver";
43+
M.addModuleFlag(llvm::Module::ModFlagBehavior::AppendUnique, DxilValKey, Val);
44+
}
45+
} // namespace
46+
47+
void CGHLSLRuntime::finishCodeGen() {
48+
auto &TargetOpts = CGM.getTarget().getTargetOpts();
49+
50+
llvm::Module &M = CGM.getModule();
51+
addDxilValVersion(TargetOpts.DxilValidatorVersion, M);
52+
}

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===----- CGHLSLRuntime.h - Interface to HLSL Runtimes -----*- 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+
// This provides an abstract class for HLSL code generation. Concrete
10+
// subclasses of this implement code generation for specific HLSL
11+
// runtime libraries.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
16+
#define LLVM_CLANG_LIB_CODEGEN_CGHLSLRUNTIME_H
17+
18+
namespace clang {
19+
20+
namespace CodeGen {
21+
22+
class CodeGenModule;
23+
24+
class CGHLSLRuntime {
25+
protected:
26+
CodeGenModule &CGM;
27+
28+
public:
29+
CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
30+
virtual ~CGHLSLRuntime() {}
31+
32+
void finishCodeGen();
33+
};
34+
35+
} // namespace CodeGen
36+
} // namespace clang
37+
38+
#endif

clang/lib/CodeGen/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ add_clang_library(clangCodeGen
5151
CGExprConstant.cpp
5252
CGExprScalar.cpp
5353
CGGPUBuiltin.cpp
54+
CGHLSLRuntime.cpp
5455
CGLoopInfo.cpp
5556
CGNonTrivialStruct.cpp
5657
CGObjC.cpp

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "CGCXXABI.h"
1717
#include "CGCall.h"
1818
#include "CGDebugInfo.h"
19+
#include "CGHLSLRuntime.h"
1920
#include "CGObjCRuntime.h"
2021
#include "CGOpenCLRuntime.h"
2122
#include "CGOpenMPRuntime.h"
@@ -146,6 +147,8 @@ CodeGenModule::CodeGenModule(ASTContext &C, const HeaderSearchOptions &HSO,
146147
createOpenMPRuntime();
147148
if (LangOpts.CUDA)
148149
createCUDARuntime();
150+
if (LangOpts.HLSL)
151+
createHLSLRuntime();
149152

150153
// Enable TBAA unless it's suppressed. ThreadSanitizer needs TBAA even at O0.
151154
if (LangOpts.Sanitize.has(SanitizerKind::Thread) ||
@@ -262,6 +265,10 @@ void CodeGenModule::createCUDARuntime() {
262265
CUDARuntime.reset(CreateNVCUDARuntime(*this));
263266
}
264267

268+
void CodeGenModule::createHLSLRuntime() {
269+
HLSLRuntime.reset(new CGHLSLRuntime(*this));
270+
}
271+
265272
void CodeGenModule::addReplacement(StringRef Name, llvm::Constant *C) {
266273
Replacements[Name] = C;
267274
}
@@ -832,6 +839,10 @@ void CodeGenModule::Release() {
832839
}
833840
}
834841

842+
// HLSL related end of code gen work items.
843+
if (LangOpts.HLSL)
844+
getHLSLRuntime().finishCodeGen();
845+
835846
if (uint32_t PLevel = Context.getLangOpts().PICLevel) {
836847
assert(PLevel < 3 && "Invalid PIC Level");
837848
getModule().setPICLevel(static_cast<llvm::PICLevel::Level>(PLevel));

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class CGObjCRuntime;
8585
class CGOpenCLRuntime;
8686
class CGOpenMPRuntime;
8787
class CGCUDARuntime;
88+
class CGHLSLRuntime;
8889
class CoverageMappingModuleGen;
8990
class TargetCodeGenInfo;
9091

@@ -319,6 +320,7 @@ class CodeGenModule : public CodeGenTypeCache {
319320
std::unique_ptr<CGOpenCLRuntime> OpenCLRuntime;
320321
std::unique_ptr<CGOpenMPRuntime> OpenMPRuntime;
321322
std::unique_ptr<CGCUDARuntime> CUDARuntime;
323+
std::unique_ptr<CGHLSLRuntime> HLSLRuntime;
322324
std::unique_ptr<CGDebugInfo> DebugInfo;
323325
std::unique_ptr<ObjCEntrypoints> ObjCData;
324326
llvm::MDNode *NoObjCARCExceptionsMetadata = nullptr;
@@ -512,6 +514,7 @@ class CodeGenModule : public CodeGenTypeCache {
512514
void createOpenCLRuntime();
513515
void createOpenMPRuntime();
514516
void createCUDARuntime();
517+
void createHLSLRuntime();
515518

516519
bool isTriviallyRecursive(const FunctionDecl *F);
517520
bool shouldEmitFunction(GlobalDecl GD);
@@ -610,6 +613,12 @@ class CodeGenModule : public CodeGenTypeCache {
610613
return *CUDARuntime;
611614
}
612615

616+
/// Return a reference to the configured HLSL runtime.
617+
CGHLSLRuntime &getHLSLRuntime() {
618+
assert(HLSLRuntime != nullptr);
619+
return *HLSLRuntime;
620+
}
621+
613622
ObjCEntrypoints &getObjCEntrypoints() const {
614623
assert(ObjCData != nullptr);
615624
return *ObjCData;

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3468,6 +3468,15 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
34683468
}
34693469
}
34703470

3471+
static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
3472+
types::ID InputType) {
3473+
const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version};
3474+
3475+
for (const auto &Arg : ForwardedArguments)
3476+
if (const auto *A = Args.getLastArg(Arg))
3477+
A->renderAsInput(Args, CmdArgs);
3478+
}
3479+
34713480
static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
34723481
ArgStringList &CmdArgs) {
34733482
bool ARCMTEnabled = false;
@@ -6227,6 +6236,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
62276236
// Forward -cl options to -cc1
62286237
RenderOpenCLOptions(Args, CmdArgs, InputType);
62296238

6239+
// Forward hlsl options to -cc1
6240+
if (C.getDriver().IsDXCMode())
6241+
RenderHLSLOptions(Args, CmdArgs, InputType);
6242+
62306243
if (IsHIP) {
62316244
if (Args.hasFlag(options::OPT_fhip_new_launch_api,
62326245
options::OPT_fno_hip_new_launch_api, true))

clang/lib/Driver/ToolChains/HLSL.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,29 @@ std::string tryParseProfile(StringRef Profile) {
108108
return "";
109109
}
110110

111+
bool isLegalValidatorVersion(StringRef ValVersionStr, const Driver &D) {
112+
VersionTuple Version;
113+
if (Version.tryParse(ValVersionStr) || Version.getBuild() ||
114+
Version.getSubminor() || !Version.getMinor()) {
115+
D.Diag(diag::err_drv_invalid_format_dxil_validator_version)
116+
<< ValVersionStr;
117+
return false;
118+
}
119+
120+
uint64_t Major = Version.getMajor();
121+
uint64_t Minor = Version.getMinor().getValue();
122+
if (Major == 0 && Minor != 0) {
123+
D.Diag(diag::err_drv_invalid_empty_dxil_validator_version) << ValVersionStr;
124+
return false;
125+
}
126+
VersionTuple MinVer(1, 0);
127+
if (Version < MinVer) {
128+
D.Diag(diag::err_drv_invalid_range_dxil_validator_version) << ValVersionStr;
129+
return false;
130+
}
131+
return true;
132+
}
133+
111134
} // namespace
112135

113136
/// DirectX Toolchain
@@ -131,3 +154,30 @@ HLSLToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
131154
return ToolChain::ComputeEffectiveClangTriple(Args, InputType);
132155
}
133156
}
157+
158+
DerivedArgList *
159+
HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
160+
Action::OffloadKind DeviceOffloadKind) const {
161+
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
162+
163+
const OptTable &Opts = getDriver().getOpts();
164+
165+
for (Arg *A : Args) {
166+
if (A->getOption().getID() == options::OPT_dxil_validator_version) {
167+
StringRef ValVerStr = A->getValue();
168+
std::string ErrorMsg;
169+
if (!isLegalValidatorVersion(ValVerStr, getDriver()))
170+
continue;
171+
}
172+
DAL->append(A);
173+
}
174+
// Add default validator version if not set.
175+
// TODO: remove this once read validator version from validator.
176+
if (!DAL->hasArg(options::OPT_dxil_validator_version)) {
177+
const StringRef DefaultValidatorVer = "1.7";
178+
DAL->AddSeparateArg(nullptr,
179+
Opts.getOption(options::OPT_dxil_validator_version),
180+
DefaultValidatorVer);
181+
}
182+
return DAL;
183+
}

0 commit comments

Comments
 (0)