Skip to content

Commit 2f573e4

Browse files
author
Xiang Li
committed
Add option for validator-version.
The information will saved into ModuleFlags with key "dx.valver".
1 parent 51aebd2 commit 2f573e4

File tree

13 files changed

+318
-1
lines changed

13 files changed

+318
-1
lines changed

clang/include/clang/Basic/CodeGenOptions.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
190190
/// debug info.
191191
std::string DIBugsReportFilePath;
192192

193+
/// The validator version for dxil.
194+
std::string DxilValidatorVersion;
195+
193196
/// The floating-point denormal mode to use.
194197
llvm::DenormalMode FPDenormalMode = llvm::DenormalMode::getIEEE();
195198

clang/include/clang/Basic/DiagnosticDriverKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,4 +657,6 @@ def err_drv_target_variant_invalid : Error<
657657
def err_drv_invalid_directx_shader_module : Error<
658658
"invalid profile : %0">;
659659

660+
def err_drv_invalid_dxil_validator_version : Error<
661+
"invalid validator version : %0\n%1">;
660662
}

clang/include/clang/Driver/Options.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6653,6 +6653,7 @@ def _SLASH_ZW : CLJoined<"ZW">;
66536653
def dxc_Group : OptionGroup<"<clang-dxc options>">, Flags<[DXCOption]>,
66546654
HelpText<"dxc compatibility options">;
66556655

6656+
66566657
class DXCJoinedOrSeparate<string name> : Option<["/", "-"], name,
66576658
KIND_JOINED_OR_SEPARATE>, Group<dxc_Group>, Flags<[DXCOption, NoXarchOption]>;
66586659

@@ -6664,6 +6665,11 @@ def dxc_help : Option<["/", "-", "--"], "help", KIND_JOINED>,
66646665
def Fo : DXCJoinedOrSeparate<"Fo">, Alias<o>,
66656666
HelpText<"Output object file.">;
66666667

6668+
def dxil_validator_version : Option<["/", "-"], "validator-version", KIND_SEPARATE>,
6669+
Group<dxc_Group>, Flags<[DXCOption, NoXarchOption, CC1Option, HelpHidden]>,
6670+
HelpText<"Override validator version for module. Format: <major.minor> ;Default: DXIL.dll version or current internal version.">,
6671+
MarshallingInfoString<CodeGenOpts<"DxilValidatorVersion">>;
6672+
66676673
def target_profile : DXCJoinedOrSeparate<"T">, MetaVarName<"<profile>">,
66686674
HelpText<"Set target profile.">,
66696675
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,"

clang/lib/CodeGen/CGHLSLRuntime.cpp

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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/CodeGenOptions.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+
auto VerPair = ValVersionStr.split(".");
30+
llvm::APInt APMajor, APMinor;
31+
32+
if (VerPair.first.getAsInteger(0, APMajor) ||
33+
VerPair.second.getAsInteger(0, APMinor)) {
34+
return;
35+
}
36+
uint64_t Major = APMajor.getLimitedValue();
37+
uint64_t Minor = APMinor.getLimitedValue();
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+
CGHLSLRuntime::CGHLSLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
48+
49+
CGHLSLRuntime::~CGHLSLRuntime() {}
50+
51+
void CGHLSLRuntime::finishCodeGen() {
52+
auto &CGOpts = CGM.getCodeGenOpts();
53+
llvm::Module &M = CGM.getModule();
54+
addDxilValVersion(CGOpts.DxilValidatorVersion, M);
55+
}

clang/lib/CodeGen/CGHLSLRuntime.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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+
#pragma once
16+
17+
namespace clang {
18+
19+
namespace CodeGen {
20+
21+
class CodeGenModule;
22+
23+
class CGHLSLRuntime {
24+
protected:
25+
CodeGenModule &CGM;
26+
27+
public:
28+
CGHLSLRuntime(CodeGenModule &CGM);
29+
virtual ~CGHLSLRuntime();
30+
void finishCodeGen();
31+
32+
};
33+
34+
}
35+
}

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: 12 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
}
@@ -805,6 +812,11 @@ void CodeGenModule::Release() {
805812
}
806813
}
807814

815+
// HLSL related end of code gen work items.
816+
if (LangOpts.HLSL) {
817+
getHLSLRuntime().finishCodeGen();
818+
}
819+
808820
if (uint32_t PLevel = Context.getLangOpts().PICLevel) {
809821
assert(PLevel < 3 && "Invalid PIC Level");
810822
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;
@@ -511,6 +513,7 @@ class CodeGenModule : public CodeGenTypeCache {
511513
void createOpenCLRuntime();
512514
void createOpenMPRuntime();
513515
void createCUDARuntime();
516+
void createHLSLRuntime();
514517

515518
bool isTriviallyRecursive(const FunctionDecl *F);
516519
bool shouldEmitFunction(GlobalDecl GD);
@@ -609,6 +612,12 @@ class CodeGenModule : public CodeGenTypeCache {
609612
return *CUDARuntime;
610613
}
611614

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

clang/lib/Driver/ToolChains/Clang.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3454,6 +3454,16 @@ static void RenderOpenCLOptions(const ArgList &Args, ArgStringList &CmdArgs,
34543454
}
34553455
}
34563456

3457+
static void RenderHLSLOptions(const ArgList &Args, ArgStringList &CmdArgs,
3458+
types::ID InputType) {
3459+
const unsigned ForwardedArguments[] = {options::OPT_dxil_validator_version};
3460+
3461+
for (const auto &Arg : ForwardedArguments)
3462+
if (const auto *A = Args.getLastArg(Arg)) {
3463+
A->renderAsInput(Args, CmdArgs);
3464+
}
3465+
}
3466+
34573467
static void RenderARCMigrateToolOptions(const Driver &D, const ArgList &Args,
34583468
ArgStringList &CmdArgs) {
34593469
bool ARCMTEnabled = false;
@@ -6232,6 +6242,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
62326242
// Forward -cl options to -cc1
62336243
RenderOpenCLOptions(Args, CmdArgs, InputType);
62346244

6245+
if (C.getDriver().IsDXCMode()) {
6246+
// Forward hlsl options to -cc1
6247+
RenderHLSLOptions(Args, CmdArgs, InputType);
6248+
}
6249+
62356250
if (IsHIP) {
62366251
if (Args.hasFlag(options::OPT_fhip_new_launch_api,
62376252
options::OPT_fno_hip_new_launch_api, true))

clang/lib/Driver/ToolChains/HLSL.cpp

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,11 @@ using namespace llvm;
2222
namespace {
2323

2424
const unsigned OfflineLibMinor = 0xF;
25-
const unsigned MaxShaderModel6Minor = 7;
25+
const unsigned MaxDXILMajor = 1;
26+
const unsigned MaxDXILMinor = 7;
27+
const unsigned MaxShaderModel6Minor = MaxDXILMinor;
28+
// TODO:get default validator version from validator.
29+
const StringRef DefaultValidatorVer = "1.7";
2630

2731
bool isLegalVersion(VersionTuple Version, unsigned Major, unsigned MinMinor,
2832
unsigned MaxMinor) {
@@ -122,6 +126,30 @@ std::string tryParseProfile(StringRef Profile) {
122126
return "";
123127
}
124128

129+
bool isLegalValidatorVersion(StringRef ValVersionStr, std::string &ErrorMsg) {
130+
auto VerPair = ValVersionStr.split(".");
131+
llvm::APInt APMajor, APMinor;
132+
133+
if (VerPair.first.getAsInteger(0, APMajor) ||
134+
VerPair.second.getAsInteger(0, APMinor)) {
135+
ErrorMsg =
136+
"Format of validator version is \"<major>.<minor>\" (ex:\"1.4\").";
137+
return false;
138+
}
139+
uint64_t Major = APMajor.getLimitedValue();
140+
uint64_t Minor = APMinor.getLimitedValue();
141+
if (Major > MaxDXILMajor || (Major == MaxDXILMajor && Minor > MaxDXILMinor)) {
142+
ErrorMsg = "Validator version must be less than or equal to current "
143+
"internal version.";
144+
return false;
145+
}
146+
if (Major == 0 && Minor != 0) {
147+
ErrorMsg = "If validator major version is 0, minor version must also be 0.";
148+
return false;
149+
}
150+
return true;
151+
}
152+
125153
} // namespace
126154

127155
/// DirectX Toolchain
@@ -145,3 +173,33 @@ HLSLToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
145173
return ToolChain::ComputeEffectiveClangTriple(Args, InputType);
146174
}
147175
}
176+
177+
DerivedArgList *
178+
HLSLToolChain::TranslateArgs(const DerivedArgList &Args, StringRef BoundArch,
179+
Action::OffloadKind DeviceOffloadKind) const {
180+
DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
181+
182+
const OptTable &Opts = getDriver().getOpts();
183+
184+
for (Arg *A : Args) {
185+
if (A->getOption().getID() == options::OPT_dxil_validator_version) {
186+
StringRef ValVerStr = A->getValue();
187+
std::string ErrorMsg;
188+
if (!isLegalValidatorVersion(ValVerStr, ErrorMsg)) {
189+
getDriver().Diag(diag::err_drv_invalid_dxil_validator_version)
190+
<< ValVerStr << ErrorMsg;
191+
192+
continue;
193+
}
194+
}
195+
DAL->append(A);
196+
}
197+
// Add default validator version if not set.
198+
// TODO: remove this once read validator version from validator.
199+
if (!DAL->hasArg(options::OPT_dxil_validator_version)) {
200+
DAL->AddSeparateArg(nullptr,
201+
Opts.getOption(options::OPT_dxil_validator_version),
202+
DefaultValidatorVer);
203+
}
204+
return DAL;
205+
}

0 commit comments

Comments
 (0)