Skip to content

Commit 8652894

Browse files
authored
[Validator] Remove the pModule input for RunInternalValidator (microsoft#6845)
This change ensures that data validation occurs within the container itself, rather than relying on the module—especially since the module may be modified during container assembly. Furthermore, simplifying the validator’s interface would be an added benefit.
1 parent cc6c665 commit 8652894

File tree

9 files changed

+73
-157
lines changed

9 files changed

+73
-157
lines changed

include/dxc/HLSL/DxilValidation.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,7 @@ HRESULT ValidateDxilContainer(const void *pContainer, uint32_t ContainerSize,
8787

8888
// Full container validation, including ValidateDxilModule, with debug module
8989
HRESULT ValidateDxilContainer(const void *pContainer, uint32_t ContainerSize,
90-
const void *pOptDebugBitcode,
91-
uint32_t OptDebugBitcodeSize,
90+
llvm::Module *pDebugModule,
9291
llvm::raw_ostream &DiagStream);
9392

9493
class PrintDiagnosticContext {

lib/HLSL/DxilValidation.cpp

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,32 @@ namespace {
7575
// Utility class for setting and restoring the diagnostic context so we may
7676
// capture errors/warnings
7777
struct DiagRestore {
78-
LLVMContext &Ctx;
78+
LLVMContext *Ctx = nullptr;
7979
void *OrigDiagContext;
8080
LLVMContext::DiagnosticHandlerTy OrigHandler;
8181

82-
DiagRestore(llvm::LLVMContext &Ctx, void *DiagContext) : Ctx(Ctx) {
83-
OrigHandler = Ctx.getDiagnosticHandler();
84-
OrigDiagContext = Ctx.getDiagnosticContext();
85-
Ctx.setDiagnosticHandler(
82+
DiagRestore(llvm::LLVMContext &InputCtx, void *DiagContext) : Ctx(&InputCtx) {
83+
init(DiagContext);
84+
}
85+
DiagRestore(Module *M, void *DiagContext) {
86+
if (!M)
87+
return;
88+
Ctx = &M->getContext();
89+
init(DiagContext);
90+
}
91+
~DiagRestore() {
92+
if (!Ctx)
93+
return;
94+
Ctx->setDiagnosticHandler(OrigHandler, OrigDiagContext);
95+
}
96+
97+
private:
98+
void init(void *DiagContext) {
99+
OrigHandler = Ctx->getDiagnosticHandler();
100+
OrigDiagContext = Ctx->getDiagnosticContext();
101+
Ctx->setDiagnosticHandler(
86102
hlsl::PrintDiagnosticContext::PrintDiagnosticHandler, DiagContext);
87103
}
88-
~DiagRestore() { Ctx.setDiagnosticHandler(OrigHandler, OrigDiagContext); }
89104
};
90105

91106
static void emitDxilDiag(LLVMContext &Ctx, const char *str) {
@@ -6984,11 +6999,10 @@ HRESULT ValidateLoadModuleFromContainerLazy(
69846999
}
69857000

69867001
HRESULT ValidateDxilContainer(const void *pContainer, uint32_t ContainerSize,
6987-
const void *pOptDebugBitcode,
6988-
uint32_t OptDebugBitcodeSize,
7002+
llvm::Module *pDebugModule,
69897003
llvm::raw_ostream &DiagStream) {
69907004
LLVMContext Ctx, DbgCtx;
6991-
std::unique_ptr<llvm::Module> pModule, pDebugModule;
7005+
std::unique_ptr<llvm::Module> pModule, pDebugModuleInContainer;
69927006

69937007
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
69947008
PrintDiagnosticContext DiagContext(DiagPrinter);
@@ -6997,31 +7011,29 @@ HRESULT ValidateDxilContainer(const void *pContainer, uint32_t ContainerSize,
69977011
DbgCtx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler,
69987012
&DiagContext, true);
69997013

7014+
DiagRestore DR(pDebugModule, &DiagContext);
7015+
70007016
IFR(ValidateLoadModuleFromContainer(pContainer, ContainerSize, pModule,
7001-
pDebugModule, Ctx, DbgCtx, DiagStream));
7017+
pDebugModuleInContainer, Ctx, DbgCtx,
7018+
DiagStream));
70027019

7003-
if (!pDebugModule && pOptDebugBitcode) {
7004-
// TODO: lazy load for perf
7005-
IFR(ValidateLoadModule((const char *)pOptDebugBitcode, OptDebugBitcodeSize,
7006-
pDebugModule, DbgCtx, DiagStream,
7007-
/*bLazyLoad*/ false));
7008-
}
7020+
if (pDebugModuleInContainer)
7021+
pDebugModule = pDebugModuleInContainer.get();
70097022

70107023
// Validate DXIL Module
7011-
IFR(ValidateDxilModule(pModule.get(), pDebugModule.get()));
7024+
IFR(ValidateDxilModule(pModule.get(), pDebugModule));
70127025

70137026
if (DiagContext.HasErrors() || DiagContext.HasWarnings()) {
70147027
return DXC_E_IR_VERIFICATION_FAILED;
70157028
}
70167029

70177030
return ValidateDxilContainerParts(
7018-
pModule.get(), pDebugModule.get(),
7031+
pModule.get(), pDebugModule,
70197032
IsDxilContainerLike(pContainer, ContainerSize), ContainerSize);
70207033
}
70217034

70227035
HRESULT ValidateDxilContainer(const void *pContainer, uint32_t ContainerSize,
70237036
llvm::raw_ostream &DiagStream) {
7024-
return ValidateDxilContainer(pContainer, ContainerSize, nullptr, 0,
7025-
DiagStream);
7037+
return ValidateDxilContainer(pContainer, ContainerSize, nullptr, DiagStream);
70267038
}
70277039
} // namespace hlsl

tools/clang/tools/dxcompiler/dxcompilerobj.cpp

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,17 +77,6 @@ using namespace clang;
7777
using namespace hlsl;
7878
using std::string;
7979

80-
// This declaration is used for the locally-linked validator.
81-
HRESULT CreateDxcValidator(REFIID riid, LPVOID *ppv);
82-
83-
// This internal call allows the validator to avoid having to re-deserialize
84-
// the module. It trusts that the caller didn't make any changes and is
85-
// kept internal because the layout of the module class may change based
86-
// on changes across modules, or picking a different compiler version or CRT.
87-
HRESULT RunInternalValidator(IDxcValidator *pValidator, llvm::Module *pModule,
88-
llvm::Module *pDebugModule, IDxcBlob *pShader,
89-
UINT32 Flags, IDxcOperationResult **ppResult);
90-
9180
static bool ShouldBeCopiedIntoPDB(UINT32 FourCC) {
9281
switch (FourCC) {
9382
case hlsl::DFCC_ShaderDebugName:

tools/clang/tools/dxcompiler/dxcutil.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ HRESULT CreateDxcValidator(REFIID riid, LPVOID *ppv);
4242
// the module. It trusts that the caller didn't make any changes and is
4343
// kept internal because the layout of the module class may change based
4444
// on changes across modules, or picking a different compiler version or CRT.
45-
HRESULT RunInternalValidator(IDxcValidator *pValidator, llvm::Module *pModule,
45+
HRESULT RunInternalValidator(IDxcValidator *pValidator,
4646
llvm::Module *pDebugModule, IDxcBlob *pShader,
4747
UINT32 Flags, IDxcOperationResult **ppResult);
4848

@@ -223,8 +223,7 @@ HRESULT ValidateAndAssembleToContainer(AssembleInputs &inputs) {
223223
// Important: in-place edit is required so the blob is reused and thus
224224
// dxil.dll can be released.
225225
if (bInternalValidator) {
226-
IFT(RunInternalValidator(pValidator, inputs.pM.get(),
227-
llvmModuleWithDebugInfo.get(),
226+
IFT(RunInternalValidator(pValidator, llvmModuleWithDebugInfo.get(),
228227
inputs.pOutputContainerBlob,
229228
DxcValidatorFlags_InPlaceEdit, &pValResult));
230229
} else {

tools/clang/tools/dxcompiler/dxcvalidator.cpp

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,9 @@ class DxcValidator : public IDxcValidator2,
4545
}
4646

4747
// For internal use only.
48-
HRESULT ValidateWithOptModules(
48+
HRESULT ValidateWithOptDebugModule(
4949
IDxcBlob *pShader, // Shader to validate.
5050
UINT32 Flags, // Validation flags.
51-
llvm::Module *pModule, // Module to validate, if available.
5251
llvm::Module *pDebugModule, // Debug module to validate, if available
5352
IDxcOperationResult *
5453
*ppResult // Validation output status, buffer, and errors
@@ -90,7 +89,7 @@ HRESULT STDMETHODCALLTYPE DxcValidator::Validate(
9089
IDxcOperationResult *
9190
*ppResult // Validation output status, buffer, and errors
9291
) {
93-
return hlsl::validate(pShader, Flags, ppResult);
92+
return hlsl::validateWithDebug(pShader, Flags, nullptr, ppResult);
9493
}
9594

9695
HRESULT STDMETHODCALLTYPE DxcValidator::ValidateWithDebug(
@@ -104,16 +103,15 @@ HRESULT STDMETHODCALLTYPE DxcValidator::ValidateWithDebug(
104103
return hlsl::validateWithDebug(pShader, Flags, pOptDebugBitcode, ppResult);
105104
}
106105

107-
HRESULT DxcValidator::ValidateWithOptModules(
106+
HRESULT DxcValidator::ValidateWithOptDebugModule(
108107
IDxcBlob *pShader, // Shader to validate.
109108
UINT32 Flags, // Validation flags.
110-
llvm::Module *pModule, // Module to validate, if available.
111109
llvm::Module *pDebugModule, // Debug module to validate, if available
112110
IDxcOperationResult *
113111
*ppResult // Validation output status, buffer, and errors
114112
) {
115-
return hlsl::validateWithOptModules(pShader, Flags, pModule, pDebugModule,
116-
ppResult);
113+
return hlsl::validateWithOptDebugModule(pShader, Flags, pDebugModule,
114+
ppResult);
117115
}
118116

119117
HRESULT STDMETHODCALLTYPE DxcValidator::GetVersion(UINT32 *pMajor,
@@ -153,17 +151,16 @@ HRESULT STDMETHODCALLTYPE DxcValidator::GetFlags(UINT32 *pFlags) {
153151

154152
///////////////////////////////////////////////////////////////////////////////
155153

156-
HRESULT RunInternalValidator(IDxcValidator *pValidator, llvm::Module *pModule,
154+
HRESULT RunInternalValidator(IDxcValidator *pValidator,
157155
llvm::Module *pDebugModule, IDxcBlob *pShader,
158156
UINT32 Flags, IDxcOperationResult **ppResult) {
159157
DXASSERT_NOMSG(pValidator != nullptr);
160-
DXASSERT_NOMSG(pModule != nullptr);
161158
DXASSERT_NOMSG(pShader != nullptr);
162159
DXASSERT_NOMSG(ppResult != nullptr);
163160

164161
DxcValidator *pInternalValidator = (DxcValidator *)pValidator;
165-
return pInternalValidator->ValidateWithOptModules(pShader, Flags, pModule,
166-
pDebugModule, ppResult);
162+
return pInternalValidator->ValidateWithOptDebugModule(pShader, Flags,
163+
pDebugModule, ppResult);
167164
}
168165

169166
HRESULT CreateDxcValidator(REFIID riid, LPVOID *ppv) {

tools/clang/tools/dxcvalidator/dxcvalidator.cpp

Lines changed: 18 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -31,79 +31,21 @@
3131
using namespace llvm;
3232
using namespace hlsl;
3333

34-
// Utility class for setting and restoring the diagnostic context so we may
35-
// capture errors/warnings
36-
struct DiagRestore {
37-
LLVMContext &Ctx;
38-
void *OrigDiagContext;
39-
LLVMContext::DiagnosticHandlerTy OrigHandler;
40-
41-
DiagRestore(llvm::LLVMContext &Ctx, void *DiagContext) : Ctx(Ctx) {
42-
OrigHandler = Ctx.getDiagnosticHandler();
43-
OrigDiagContext = Ctx.getDiagnosticContext();
44-
Ctx.setDiagnosticHandler(PrintDiagnosticContext::PrintDiagnosticHandler,
45-
DiagContext);
46-
}
47-
~DiagRestore() { Ctx.setDiagnosticHandler(OrigHandler, OrigDiagContext); }
48-
};
49-
5034
static uint32_t runValidation(
5135
IDxcBlob *Shader,
5236
uint32_t Flags, // Validation flags.
53-
llvm::Module *Module, // Module to validate, if available.
5437
llvm::Module *DebugModule, // Debug module to validate, if available
5538
AbstractMemoryStream *DiagMemStream) {
56-
5739
// Run validation may throw, but that indicates an inability to validate,
5840
// not that the validation failed (eg out of memory). That is indicated
5941
// by a failing HRESULT, and possibly error messages in the diagnostics
6042
// stream.
6143

6244
raw_stream_ostream DiagStream(DiagMemStream);
6345

64-
if (Flags & DxcValidatorFlags_ModuleOnly) {
65-
if (IsDxilContainerLike(Shader->GetBufferPointer(),
66-
Shader->GetBufferSize()))
67-
return E_INVALIDARG;
68-
} else {
69-
if (!IsDxilContainerLike(Shader->GetBufferPointer(),
70-
Shader->GetBufferSize()))
71-
return DXC_E_CONTAINER_INVALID;
72-
}
73-
74-
if (!Module) {
75-
DXASSERT_NOMSG(DebugModule == nullptr);
76-
if (Flags & DxcValidatorFlags_ModuleOnly) {
77-
return ValidateDxilBitcode((const char *)Shader->GetBufferPointer(),
78-
(uint32_t)Shader->GetBufferSize(), DiagStream);
79-
} else {
80-
return ValidateDxilContainer(Shader->GetBufferPointer(),
81-
Shader->GetBufferSize(), DiagStream);
82-
}
83-
}
84-
85-
llvm::DiagnosticPrinterRawOStream DiagPrinter(DiagStream);
86-
PrintDiagnosticContext DiagContext(DiagPrinter);
87-
DiagRestore DR(Module->getContext(), &DiagContext);
88-
89-
HRESULT hr = hlsl::ValidateDxilModule(Module, DebugModule);
90-
if (FAILED(hr))
91-
return hr;
92-
if (!(Flags & DxcValidatorFlags_ModuleOnly)) {
93-
hr = ValidateDxilContainerParts(
94-
Module, DebugModule,
95-
IsDxilContainerLike(Shader->GetBufferPointer(),
96-
Shader->GetBufferSize()),
97-
(uint32_t)Shader->GetBufferSize());
98-
if (FAILED(hr))
99-
return hr;
100-
}
101-
102-
if (DiagContext.HasErrors() || DiagContext.HasWarnings()) {
103-
return DXC_E_IR_VERIFICATION_FAILED;
104-
}
105-
106-
return S_OK;
46+
return ValidateDxilContainer(Shader->GetBufferPointer(),
47+
Shader->GetBufferSize(), DebugModule,
48+
DiagStream);
10749
}
10850

10951
static uint32_t
@@ -151,23 +93,14 @@ runRootSignatureValidation(IDxcBlob *Shader,
15193
return S_OK;
15294
}
15395

154-
// Compile a single entry point to the target shader model
155-
uint32_t hlsl::validate(
156-
IDxcBlob *Shader, // Shader to validate.
157-
uint32_t Flags, // Validation flags.
158-
IDxcOperationResult **Result // Validation output status, buffer, and errors
159-
) {
160-
DxcThreadMalloc TM(DxcGetThreadMallocNoRef());
161-
if (Result == nullptr)
162-
return false;
163-
*Result = nullptr;
164-
if (Shader == nullptr || Flags & ~DxcValidatorFlags_ValidMask)
165-
return false;
166-
if ((Flags & DxcValidatorFlags_ModuleOnly) &&
167-
(Flags &
168-
(DxcValidatorFlags_InPlaceEdit | DxcValidatorFlags_RootSignatureOnly)))
169-
return false;
170-
return validateWithOptModules(Shader, Flags, nullptr, nullptr, Result);
96+
static uint32_t runDxilModuleValidation(IDxcBlob *Shader, // Shader to validate.
97+
AbstractMemoryStream *DiagMemStream) {
98+
if (IsDxilContainerLike(Shader->GetBufferPointer(), Shader->GetBufferSize()))
99+
return E_INVALIDARG;
100+
101+
raw_stream_ostream DiagStream(DiagMemStream);
102+
return ValidateDxilBitcode((const char *)Shader->GetBufferPointer(),
103+
(uint32_t)Shader->GetBufferSize(), DiagStream);
171104
}
172105

173106
uint32_t hlsl::validateWithDebug(
@@ -212,17 +145,15 @@ uint32_t hlsl::validateWithDebug(
212145
if (FAILED(hr))
213146
throw hlsl::Exception(hr);
214147
}
215-
return validateWithOptModules(Shader, Flags, nullptr, DebugModule.get(),
216-
Result);
148+
return validateWithOptDebugModule(Shader, Flags, DebugModule.get(), Result);
217149
}
218150
CATCH_CPP_ASSIGN_HRESULT();
219151
return hr;
220152
}
221153

222-
uint32_t hlsl::validateWithOptModules(
154+
uint32_t hlsl::validateWithOptDebugModule(
223155
IDxcBlob *Shader, // Shader to validate.
224156
uint32_t Flags, // Validation flags.
225-
llvm::Module *Module, // Module to validate, if available.
226157
llvm::Module *DebugModule, // Debug module to validate, if available
227158
IDxcOperationResult **Result // Validation output status, buffer, and errors
228159
) {
@@ -238,12 +169,12 @@ uint32_t hlsl::validateWithOptModules(
238169
throw hlsl::Exception(hr);
239170
// Run validation may throw, but that indicates an inability to validate,
240171
// not that the validation failed (eg out of memory).
241-
if (Flags & DxcValidatorFlags_RootSignatureOnly) {
172+
if (Flags & DxcValidatorFlags_RootSignatureOnly)
242173
validationStatus = runRootSignatureValidation(Shader, DiagStream);
243-
} else {
244-
validationStatus =
245-
runValidation(Shader, Flags, Module, DebugModule, DiagStream);
246-
}
174+
else if (Flags & DxcValidatorFlags_ModuleOnly)
175+
validationStatus = runDxilModuleValidation(Shader, DiagStream);
176+
else
177+
validationStatus = runValidation(Shader, Flags, DebugModule, DiagStream);
247178
if (FAILED(validationStatus)) {
248179
std::string msg("Validation failed.\n");
249180
ULONG cbWritten;

tools/clang/tools/dxcvalidator/dxcvalidator.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,22 +24,15 @@ class LLVMContext;
2424
} // namespace llvm
2525

2626
namespace hlsl {
27+
2728
// For internal use only.
28-
uint32_t validateWithOptModules(
29+
uint32_t validateWithOptDebugModule(
2930
IDxcBlob *Shader, // Shader to validate.
3031
uint32_t Flags, // Validation flags.
31-
llvm::Module *Module, // Module to validate, if available.
3232
llvm::Module *DebugModule, // Debug module to validate, if available
3333
IDxcOperationResult **Result // Validation output status, buffer, and errors
3434
);
3535

36-
// IDxcValidator
37-
uint32_t validate(
38-
IDxcBlob *Shader, // Shader to validate.
39-
uint32_t Flags, // Validation flags.
40-
IDxcOperationResult **Result // Validation output status, buffer, and errors
41-
);
42-
4336
// IDxcValidator2
4437
uint32_t validateWithDebug(
4538
IDxcBlob *Shader, // Shader to validate.

tools/clang/tools/dxrfallbackcompiler/dxcutil.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ HRESULT CreateDxcValidator(REFIID riid, LPVOID *ppv);
4040
// the module. It trusts that the caller didn't make any changes and is
4141
// kept internal because the layout of the module class may change based
4242
// on changes across modules, or picking a different compiler version or CRT.
43-
HRESULT RunInternalValidator(IDxcValidator *pValidator, llvm::Module *pModule,
43+
HRESULT RunInternalValidator(IDxcValidator *pValidator,
4444
llvm::Module *pDebugModule, IDxcBlob *pShader,
4545
UINT32 Flags, IDxcOperationResult **ppResult);
4646

@@ -190,8 +190,7 @@ HRESULT ValidateAndAssembleToContainer(AssembleInputs &inputs) {
190190
// Important: in-place edit is required so the blob is reused and thus
191191
// dxil.dll can be released.
192192
if (bInternalValidator) {
193-
IFT(RunInternalValidator(pValidator, inputs.pM.get(),
194-
llvmModuleWithDebugInfo.get(),
193+
IFT(RunInternalValidator(pValidator, llvmModuleWithDebugInfo.get(),
195194
inputs.pOutputContainerBlob,
196195
DxcValidatorFlags_InPlaceEdit, &pValResult));
197196
} else {

0 commit comments

Comments
 (0)