Skip to content

Commit 37df7af

Browse files
committed
Fixed review comments
Also added new interface to retrieve disassembled spirv
1 parent 0e675ac commit 37df7af

10 files changed

+121
-166
lines changed

source/compiler-core/slang-downstream-compiler.h

+15
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,10 @@ class IDownstreamCompiler : public ICastable
340340
/// Disassemble and print to stdout
341341
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
342342
disassemble(const uint32_t* contents, int contentsSize) = 0;
343+
344+
/// Disassemble and return the result as a string
345+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
346+
disassembleWithResult(const uint32_t* contents, int contentsSize, String& outString) = 0;
343347

344348
/// True if underlying compiler uses file system to communicate source
345349
virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() = 0;
@@ -384,6 +388,17 @@ class DownstreamCompilerBase : public ComBaseObject, public IDownstreamCompiler
384388
SLANG_UNUSED(contentsSize);
385389
return SLANG_FAIL;
386390
}
391+
392+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
393+
disassembleWithResult(const uint32_t* contents, int contentsSize, String& outString) SLANG_OVERRIDE
394+
{
395+
SLANG_UNUSED(contents);
396+
SLANG_UNUSED(contentsSize);
397+
SLANG_UNUSED(outString);
398+
return SLANG_FAIL;
399+
}
400+
401+
virtual SLANG_NO_THROW bool SLANG_MCALL isFileBased() SLANG_OVERRIDE { return true; }
387402

388403
DownstreamCompilerBase(const Desc& desc)
389404
: m_desc(desc)

source/compiler-core/slang-glslang-compiler.cpp

+24
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ class GlslangDownstreamCompiler : public DownstreamCompilerBase
4949
validate(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE;
5050
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
5151
disassemble(const uint32_t* contents, int contentsSize) SLANG_OVERRIDE;
52+
virtual SLANG_NO_THROW SlangResult SLANG_MCALL
53+
disassembleWithResult(const uint32_t* contents, int contentsSize, String& outString) SLANG_OVERRIDE;
5254

5355
/// Must be called before use
5456
SlangResult init(ISlangSharedLibrary* library);
@@ -66,6 +68,7 @@ class GlslangDownstreamCompiler : public DownstreamCompilerBase
6668
glslang_CompileFunc_1_2 m_compile_1_2 = nullptr;
6769
glslang_ValidateSPIRVFunc m_validate = nullptr;
6870
glslang_DisassembleSPIRVFunc m_disassemble = nullptr;
71+
glslang_DisassembleSPIRVWithResultFunc m_disassembleWithResult = nullptr;
6972

7073
ComPtr<ISlangSharedLibrary> m_sharedLibrary;
7174

@@ -80,6 +83,8 @@ SlangResult GlslangDownstreamCompiler::init(ISlangSharedLibrary* library)
8083
m_validate = (glslang_ValidateSPIRVFunc)library->findFuncByName("glslang_validateSPIRV");
8184
m_disassemble =
8285
(glslang_DisassembleSPIRVFunc)library->findFuncByName("glslang_disassembleSPIRV");
86+
m_disassembleWithResult =
87+
(glslang_DisassembleSPIRVWithResultFunc)library->findFuncByName("glslang_disassembleSPIRVWithResult");
8388

8489
if (m_compile_1_0 == nullptr && m_compile_1_1 == nullptr && m_compile_1_2 == nullptr)
8590
{
@@ -323,6 +328,25 @@ SlangResult GlslangDownstreamCompiler::disassemble(const uint32_t* contents, int
323328
return SLANG_FAIL;
324329
}
325330

331+
SlangResult GlslangDownstreamCompiler::disassembleWithResult(const uint32_t* contents, int contentsSize, String& outString)
332+
{
333+
if (m_disassembleWithResult == nullptr)
334+
{
335+
return SLANG_FAIL;
336+
}
337+
338+
char* resultString = nullptr;
339+
if (m_disassembleWithResult(contents, contentsSize, &resultString))
340+
{
341+
if (resultString)
342+
{
343+
outString = String(resultString);
344+
return SLANG_OK;
345+
}
346+
}
347+
return SLANG_FAIL;
348+
}
349+
326350
bool GlslangDownstreamCompiler::canConvert(const ArtifactDesc& from, const ArtifactDesc& to)
327351
{
328352
// Can only disassemble blobs that are SPIR-V

source/slang-glslang/slang-glslang.cpp

+38-5
Original file line numberDiff line numberDiff line change
@@ -184,36 +184,69 @@ extern "C"
184184
return tools.Validate(contents, contentsSize, options);
185185
}
186186

187-
// Disassemble the given SPIRV-ASM instructions.
187+
// Forward declaration for the disassembly function
188+
extern "C"
189+
#ifdef _MSC_VER
190+
_declspec(dllexport)
191+
#else
192+
__attribute__((__visibility__("default")))
193+
#endif
194+
bool glslang_disassembleSPIRVWithResult(const uint32_t* contents, int contentsSize, char** outString);
195+
196+
// Disassemble the given SPIRV-ASM instructions
188197
extern "C"
189198
#ifdef _MSC_VER
190199
_declspec(dllexport)
191200
#else
192201
__attribute__((__visibility__("default")))
193202
#endif
194203
bool glslang_disassembleSPIRV(const uint32_t* contents, int contentsSize)
204+
{
205+
return glslang_disassembleSPIRVWithResult(contents, contentsSize, nullptr);
206+
}
207+
208+
// Disassemble the given SPIRV-ASM instructions and return the result as a string.
209+
extern "C"
210+
#ifdef _MSC_VER
211+
_declspec(dllexport)
212+
#else
213+
__attribute__((__visibility__("default")))
214+
#endif
215+
bool glslang_disassembleSPIRVWithResult(const uint32_t* contents, int contentsSize, char** outString)
195216
{
196217
static const auto kDefaultEnvironment = SPV_ENV_UNIVERSAL_1_5;
218+
spv_text text;
197219

198220
uint32_t options = SPV_BINARY_TO_TEXT_OPTION_NONE;
199221
options |= SPV_BINARY_TO_TEXT_OPTION_COMMENT;
200-
options |= SPV_BINARY_TO_TEXT_OPTION_PRINT;
201-
options |= SPV_BINARY_TO_TEXT_OPTION_COLOR;
202222
options |= SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES;
223+
options |= SPV_BINARY_TO_TEXT_OPTION_INDENT;
203224

204225
spv_diagnostic diagnostic = nullptr;
205226
spv_context context = spvContextCreate(kDefaultEnvironment);
206227
spv_result_t error =
207-
spvBinaryToText(context, contents, contentsSize, options, nullptr, &diagnostic);
228+
spvBinaryToText(context, contents, contentsSize, options, &text, &diagnostic);
208229
spvContextDestroy(context);
209230
if (error)
210231
{
211232
spvDiagnosticPrint(diagnostic);
212233
spvDiagnosticDestroy(diagnostic);
213234
return false;
214235
}
236+
else
237+
{
238+
if (outString)
239+
{
240+
// Allocate memory for the output string and copy the result
241+
size_t len = text->length + 1; // +1 for null terminator
242+
*outString = new char[len];
243+
memcpy(*outString, text->str, text->length);
244+
(*outString)[text->length] = '\0'; // Ensure null termination
245+
}
215246

216-
return true;
247+
spvTextDestroy(text);
248+
return true;
249+
}
217250
}
218251

219252
// Apply the SPIRV-Tools optimizer to generated SPIR-V based on the desired optimization level

source/slang-glslang/slang-glslang.h

+1
Original file line numberDiff line numberDiff line change
@@ -166,5 +166,6 @@ typedef int (*glslang_CompileFunc_1_1)(glslang_CompileRequest_1_1* request);
166166
typedef int (*glslang_CompileFunc_1_2)(glslang_CompileRequest_1_2* request);
167167
typedef bool (*glslang_ValidateSPIRVFunc)(const uint32_t* contents, int contentsSize);
168168
typedef bool (*glslang_DisassembleSPIRVFunc)(const uint32_t* contents, int contentsSize);
169+
typedef bool (*glslang_DisassembleSPIRVWithResultFunc)(const uint32_t* contents, int contentsSize, char** outString);
169170
typedef bool (*glslang_LinkSPIRVFunc)(glslang_LinkRequest* request);
170171
#endif

source/slang/CMakeLists.txt

-1
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,6 @@ set(slang_link_args
230230
slang-reflect-headers
231231
slang-lookup-tables
232232
SPIRV-Headers
233-
SPIRV-Tools
234233
)
235234
set(slang_interface_args INCLUDE_DIRECTORIES_PUBLIC ${slang_SOURCE_DIR}/include)
236235
set(slang_public_lib_args

source/slang/slang-compiler-tu.cpp

-30
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,6 @@
1010

1111
namespace Slang
1212
{
13-
static void dumpIRIfEnabled(
14-
CodeGenContext* codeGenContext,
15-
IRModule* irModule,
16-
char const* label = nullptr)
17-
{
18-
if (codeGenContext->shouldDumpIR())
19-
{
20-
DiagnosticSinkWriter writer(codeGenContext->getSink());
21-
dumpIR(
22-
irModule,
23-
codeGenContext->getIRDumpOptions(),
24-
label,
25-
codeGenContext->getSourceManager(),
26-
&writer);
27-
}
28-
}
29-
3013
// Only attempt to precompile functions:
3114
// 1) With function bodies (not just empty decls)
3215
// 2) Not marked with unsafeForceInlineDecoration
@@ -120,10 +103,6 @@ Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnos
120103
applySettingsToDiagnosticSink(&sink, &sink, linkage->m_optionSet);
121104
applySettingsToDiagnosticSink(&sink, &sink, m_optionSet);
122105

123-
// Configure diagnostic writer to write directly to stderr
124-
static FileWriter stdError(stderr, WriterFlag::IsStatic | WriterFlag::IsUnowned);
125-
sink.writer = &stdError;
126-
127106
RefPtr<TargetRequest> targetReq = new TargetRequest(linkage, targetEnum);
128107

129108
List<RefPtr<ComponentType>> allComponentTypes;
@@ -164,9 +143,6 @@ Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnos
164143
CodeGenContext::Shared sharedCodeGenContext(&tp, entryPointIndices, &sink, nullptr);
165144
CodeGenContext codeGenContext(&sharedCodeGenContext);
166145

167-
// Dump initial IR before precompilation
168-
dumpIRIfEnabled(&codeGenContext, module, "PRECOMPILE_FOR_TARGET");
169-
170146
// Mark all public functions as exported, ensure there's at least one. Store a mapping
171147
// of function name to IRInst* for later reference. After linking is done, we'll scan
172148
// the linked result to see which functions survived the pruning and are included in the
@@ -205,9 +181,6 @@ Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnos
205181
return SLANG_E_NOT_AVAILABLE;
206182
}
207183

208-
// Dump IR after precompilation but before applying decorations
209-
dumpIRIfEnabled(&codeGenContext, module, "PRECOMPILE_FOR_TARGET_BEFORE_DECORATIONS");
210-
211184
for (const auto& mangledName : metadata->getExportedFunctionMangledNames())
212185
{
213186
auto moduleInst = nameToFunction[mangledName];
@@ -239,9 +212,6 @@ Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnos
239212
builder.setInsertInto(module);
240213

241214
builder.emitEmbeddedDownstreamIR(targetReq->getTarget(), blob);
242-
243-
// Dump final IR after all transformations
244-
dumpIRIfEnabled(&codeGenContext, module, "PRECOMPILE_FOR_TARGET_COMPLETE_ALL");
245215
return SLANG_OK;
246216
}
247217

source/slang/slang-ir.cpp

+21-27
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@
88
#include "slang-ir-util.h"
99
#include "slang-mangle.h"
1010

11-
#include "spirv-tools/libspirv.h"
12-
1311
namespace Slang
1412
{
1513
struct IRSpecContext;
@@ -7167,37 +7165,33 @@ static void dumpInstExpr(IRDumpContext* context, IRInst* inst)
71677165
const uint32_t* spirvCode = (const uint32_t*)blob.begin();
71687166
const size_t spirvWordCount = blob.getLength() / sizeof(uint32_t);
71697167

7170-
// Create SPIR-V tools context
7171-
spv_context spvContext = spvContextCreate(SPV_ENV_UNIVERSAL_1_0);
7172-
spv_text text = nullptr;
7173-
spv_diagnostic diagnostic = nullptr;
7174-
7175-
// Disassemble with friendly names and comments
7176-
spv_result_t result = spvBinaryToText(
7177-
spvContext,
7178-
spirvCode,
7179-
spirvWordCount,
7180-
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | SPV_BINARY_TO_TEXT_OPTION_INDENT,
7181-
&text,
7182-
&diagnostic);
7183-
7184-
if (result == SPV_SUCCESS && text)
7168+
// Get the compiler from the session through the module
7169+
auto module = inst->getModule();
7170+
auto session = module->getSession();
7171+
IDownstreamCompiler* compiler = session->getOrLoadDownstreamCompiler(
7172+
PassThroughMode::SpirvDis,
7173+
nullptr);
7174+
7175+
if (compiler)
71857176
{
7186-
dump(context, "\n");
7187-
dumpIndent(context);
7188-
dump(context, text->str);
7177+
// Use glslang interface to disassemble with string output
7178+
String disassemblyOutput;
7179+
if (SLANG_SUCCEEDED(compiler->disassembleWithResult(spirvCode, int(spirvWordCount), disassemblyOutput)))
7180+
{
7181+
// Dump the captured disassembly
7182+
dump(context, "\n");
7183+
dumpIndent(context);
7184+
dump(context, disassemblyOutput);
7185+
}
7186+
else
7187+
{
7188+
dump(context, "<disassembly failed>");
7189+
}
71897190
}
71907191
else
71917192
{
71927193
dump(context, "<invalid SPIR-V>");
71937194
}
7194-
7195-
// Cleanup
7196-
if (diagnostic)
7197-
spvDiagnosticDestroy(diagnostic);
7198-
if (text)
7199-
spvTextDestroy(text);
7200-
spvContextDestroy(spvContext);
72017195
}
72027196
else
72037197
{

source/slang/slang.cpp

+12
Original file line numberDiff line numberDiff line change
@@ -3746,6 +3746,18 @@ SlangResult EndToEndCompileRequest::executeActionsInner()
37463746
{
37473747
SLANG_RETURN_ON_FAIL(
37483748
translationUnit->getModule()->precompileForTarget(targetEnum, nullptr));
3749+
3750+
if (frontEndReq->optionSet.shouldDumpIR())
3751+
{
3752+
DiagnosticSinkWriter writer(frontEndReq->getSink());
3753+
3754+
dumpIR(
3755+
translationUnit->getModule()->getIRModule(),
3756+
frontEndReq->m_irDumpOptions,
3757+
"PRECOMPILE_FOR_TARGET_COMPLETE_ALL",
3758+
frontEndReq->getSourceManager(),
3759+
&writer);
3760+
}
37493761
}
37503762
}
37513763
}

0 commit comments

Comments
 (0)