1414#include " llvm/ADT/StringRef.h"
1515#include < iostream>
1616
17- static bool CheckNeedsValidationFromCompileArgs (LPCWSTR *pArgs,
18- UINT32 argCount) {
17+ static bool NeedsValidationFromCompileArgs (LPCWSTR *pArgs, UINT32 argCount) {
1918 std::vector<std::wstring> Args (pArgs, pArgs + argCount);
2019
2120 // validation will normally take place upon a compilation unless
@@ -126,7 +125,6 @@ class ExternalValidationHelper : public IDxcCompiler, public IDxcCompiler3 {
126125
127126 *ppvObject = nullptr ;
128127
129- // Windows: use built-in __uuidof
130128 if (IsEqualIID (iid, __uuidof (IUnknown))) {
131129 AddRef ();
132130 *ppvObject = static_cast <IDxcCompiler3 *>(this );
@@ -158,11 +156,10 @@ class ExternalValidationHelper : public IDxcCompiler, public IDxcCompiler3 {
158156 IDxcOperationResult **ppResult) override {
159157
160158 // if validation will not be needed, compile as normal
161- if (!CheckNeedsValidationFromCompileArgs (pArguments, argCount)) {
159+ if (!NeedsValidationFromCompileArgs (pArguments, argCount))
162160 return m_pCompiler->Compile (
163161 pSource, pSourceName, pEntryPoint, pTargetProfile, pArguments,
164162 argCount, pDefines, defineCount, pIncludeHandler, ppResult);
165- }
166163
167164 // Otherwise, first, add the external validation compilation args
168165 std::vector<std::wstring> newArgs = AddExtValCompilationArgs (
@@ -181,14 +178,14 @@ class ExternalValidationHelper : public IDxcCompiler, public IDxcCompiler3 {
181178 if (DXC_FAILED (CompHR))
182179 return CompHR;
183180
184- HRESULT status ;
185- (*ppResult)->GetStatus (&status );
181+ HRESULT Status ;
182+ (*ppResult)->GetStatus (&Status );
186183
187184 // Then validate, only if compilation succeeded.
188185 // The caller is responsible for handling compilation errors,
189186 // but this function should return whether there was a critical
190187 // failure in compilation or not at this point
191- if (DXC_FAILED (status ))
188+ if (DXC_FAILED (Status ))
192189 return CompHR;
193190
194191 CComPtr<IDxcBlob> pProgram;
@@ -241,21 +238,67 @@ class ExternalValidationHelper : public IDxcCompiler, public IDxcCompiler3 {
241238 LPCWSTR *pArguments, UINT32 argCount,
242239 IDxcIncludeHandler *pIncludeHandler,
243240 REFIID riid, LPVOID *ppResult) override {
244- // First, add -Vd to the compilation args, to disable the
245- // internal validator
241+ // if validation will not be needed, compile as normal
242+ if (!NeedsValidationFromCompileArgs (pArguments, argCount))
243+ return m_pCompiler3->Compile (pSource, pArguments, argCount,
244+ pIncludeHandler, riid, ppResult);
245+
246+ // Otherwise, first, add the external validation compilation args
246247 std::vector<std::wstring> newArgs = AddExtValCompilationArgs (
247248 argCount, pArguments, ValidatorVersionMajor, ValidatorVersionMinor);
248249
249- // Build raw LPCWSTR* array from owned wstrings
250- std::vector<LPCWSTR> argPtrs;
251- argPtrs.reserve (newArgs.size ());
252- for (auto &s : newArgs) {
253- argPtrs.push_back (s.c_str ());
250+ // Now build an array of LPCWSTRs for the API call:
251+ std::vector<LPCWSTR> rawArgs;
252+ rawArgs.reserve (newArgs.size ());
253+ for (auto &a : newArgs) {
254+ rawArgs.push_back (a.c_str ());
255+ }
256+ HRESULT CompHR = m_pCompiler3->Compile (pSource, pArguments, argCount,
257+ pIncludeHandler, riid, ppResult);
258+ if (DXC_FAILED (CompHR))
259+ return CompHR;
260+
261+ HRESULT Status;
262+ CComPtr<IDxcOperationResult> pDxcOperationResult;
263+ IFT (((IUnknown *)*ppResult)
264+ ->QueryInterface (IID_PPV_ARGS (&pDxcOperationResult)));
265+ pDxcOperationResult->GetStatus (&Status);
266+
267+ // Then validate, only if compilation succeeded.
268+ // The caller is responsible for handling compilation errors,
269+ // but this function should return whether there was a critical
270+ // failure in compilation or not at this point
271+ if (DXC_FAILED (Status))
272+ return CompHR;
273+
274+ CComPtr<IDxcBlob> pProgram;
275+ CComPtr<IDxcOperationResult> pValResult;
276+
277+ IFT (pDxcOperationResult->GetResult (&pProgram));
278+
279+ // This checks the validator ran without any critical failures,
280+ // not that the program was valid.
281+ IFT (m_pValidator->Validate (pProgram, DxcValidatorFlags_InPlaceEdit,
282+ &pValResult));
283+ CComPtr<IDxcResult> pResult;
284+ HRESULT ValHR;
285+ IFT (pValResult->GetStatus (&ValHR));
286+ if (FAILED (ValHR)) {
287+ // emulate having a diagnostic context, but leave
288+ // the rest of the error print out to the caller
289+ fwprintf (stderr, L" error: validation errors\r\n " );
290+ }
291+
292+ // regardless if there were errors or not, we want to replace
293+ // the output blob with the result of the validator
294+ if (pDxcOperationResult) {
295+ pDxcOperationResult.Release ();
296+ pDxcOperationResult = nullptr ;
254297 }
255298
256- return m_pCompiler3-> Compile (pSource, argPtrs. data (),
257- static_cast <UINT32>(argPtrs. size ()),
258- pIncludeHandler, riid, ppResult) ;
299+ *ppResult = pValResult. Detach (); // Transfers ownership to caller
300+
301+ return S_OK ;
259302 }
260303
261304 HRESULT STDMETHODCALLTYPE Disassemble (const DxcBuffer *pObject, REFIID riid,
0 commit comments