Skip to content

Commit 321154e

Browse files
committed
Test for link time constants
This test exercises link time constants used by modules that are precompiled to SPIR-V. Work on shader-slang#6524
1 parent 8b0484e commit 321154e

8 files changed

+142
-20
lines changed

source/slang/slang-compiler-tu.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnos
147147
// of function name to IRInst* for later reference. After linking is done, we'll scan
148148
// the linked result to see which functions survived the pruning and are included in the
149149
// precompiled blob.
150+
// Tenatively mark all imported variables as downstream imported to resolve potential
151+
// issues with unresolved symbols in the downstream IR.
150152
Dictionary<String, IRInst*> nameToFunction;
151153
bool hasAtLeastOneFunction = false;
152154
for (auto inst : module->getGlobalInsts())
@@ -157,6 +159,12 @@ Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnos
157159
builder.addDecoration(inst, kIROp_DownstreamModuleExportDecoration);
158160
nameToFunction[inst->findDecoration<IRExportDecoration>()->getMangledName()] = inst;
159161
}
162+
163+
//if (inst->findDecoration<IRImportDecoration>())
164+
// {
165+
// inst->dump();
166+
// builder.addDecoration(inst, kIROp_DownstreamModuleImportDecoration);
167+
// }
160168
}
161169

162170
// Bail if there are no functions to export. That's not treated as an error
@@ -170,6 +178,12 @@ Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnos
170178
SlangResult res = codeGenContext.emitPrecompiledDownstreamIR(outArtifact);
171179

172180
sink.getBlobIfNeeded(outDiagnostics);
181+
182+
// print diagnostics
183+
if (outDiagnostics && *outDiagnostics)
184+
{
185+
fprintf(stderr, "%s", (const char*)outDiagnostics);
186+
}
173187
if (res != SLANG_OK)
174188
{
175189
return res;
@@ -212,6 +226,9 @@ Module::precompileForTarget(SlangCompileTarget target, slang::IBlob** outDiagnos
212226
builder.setInsertInto(module);
213227

214228
builder.emitEmbeddedDownstreamIR(targetReq->getTarget(), blob);
229+
230+
module->getModuleInst()->dump();
231+
215232
return SLANG_OK;
216233
}
217234

source/slang/slang-emit-spirv.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -1907,6 +1907,9 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
19071907
case kIROp_IndicesType:
19081908
case kIROp_PrimitivesType:
19091909
return nullptr;
1910+
case kIROp_GlobalConstant:
1911+
//return emitGlobalConstant(as<IRGlobalConstant>(inst));
1912+
return nullptr;
19101913
default:
19111914
{
19121915
if (as<IRSPIRVAsmOperand>(inst))
@@ -3435,6 +3438,7 @@ struct SPIRVEmitContext : public SourceEmitterBase, public SPIRVEmitSharedContex
34353438
/// Emit an instruction that is local to the body of the given `parent`.
34363439
SpvInst* emitLocalInst(SpvInstParent* parent, IRInst* inst)
34373440
{
3441+
inst->dump();
34383442
SpvInst* result = nullptr;
34393443
switch (inst->getOp())
34403444
{

source/slang/slang-emit.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -638,9 +638,14 @@ Result linkAndOptimizeIR(
638638
// modules, and also select between the definitions of
639639
// any "profile-overloaded" symbols.
640640
//
641+
if (codeGenContext->getSink()->getErrorCount() != 0)
642+
return SLANG_FAIL;
643+
641644
outLinkedIR = linkIR(codeGenContext);
642645
auto irModule = outLinkedIR.module;
643646
auto irEntryPoints = outLinkedIR.entryPoints;
647+
if (codeGenContext->getSink()->getErrorCount() != 0)
648+
return SLANG_FAIL;
644649

645650
#if 0
646651
dumpIRIfEnabled(codeGenContext, irModule, "LINKED");
@@ -812,6 +817,8 @@ Result linkAndOptimizeIR(
812817

813818
// Lower all the LValue implict casts (used for out/inout/ref scenarios)
814819
lowerLValueCast(targetProgram, irModule);
820+
if (codeGenContext->getSink()->getErrorCount() != 0)
821+
return SLANG_FAIL;
815822

816823
IRSimplificationOptions defaultIRSimplificationOptions =
817824
IRSimplificationOptions::getDefault(targetProgram);
@@ -832,6 +839,8 @@ Result linkAndOptimizeIR(
832839
if (sink->getErrorCount() != 0)
833840
return SLANG_FAIL;
834841
}
842+
if (codeGenContext->getSink()->getErrorCount() != 0)
843+
return SLANG_FAIL;
835844

836845
// Fill in default matrix layout into matrix types that left layout unspecified.
837846
specializeMatrixLayout(targetProgram, irModule);
@@ -883,6 +892,8 @@ Result linkAndOptimizeIR(
883892
//
884893
// Specialization passes and auto-diff passes runs in an iterative loop
885894
// since each pass can enable the other pass to progress further.
895+
if (codeGenContext->getSink()->getErrorCount() != 0)
896+
return SLANG_FAIL;
886897
for (;;)
887898
{
888899
bool changed = false;

source/slang/slang-ir-link.cpp

+47-20
Original file line numberDiff line numberDiff line change
@@ -1716,6 +1716,8 @@ static bool doesTargetAllowUnresolvedFuncSymbol(TargetRequest* req)
17161716
}
17171717
}
17181718

1719+
1720+
17191721
static void diagnoseUnresolvedSymbols(TargetRequest* req, DiagnosticSink* sink, IRModule* module)
17201722
{
17211723
for (auto globalSym : module->getGlobalInsts())
@@ -1727,10 +1729,17 @@ static void diagnoseUnresolvedSymbols(TargetRequest* req, DiagnosticSink* sink,
17271729
if (auto constant = as<IRGlobalConstant>(globalSym))
17281730
{
17291731
if (constant->getOperandCount() == 0)
1732+
{
1733+
if (globalSym->findDecoration<IRDownstreamModuleImportDecoration>())
1734+
{
1735+
break;
1736+
}
1737+
17301738
sink->diagnose(
1731-
globalSym->sourceLoc,
1732-
Diagnostics::unresolvedSymbol,
1733-
globalSym);
1739+
globalSym->sourceLoc,
1740+
Diagnostics::unresolvedSymbol,
1741+
globalSym);
1742+
}
17341743
}
17351744
else if (auto genericSym = as<IRGeneric>(globalSym))
17361745
{
@@ -2017,14 +2026,16 @@ void cloneUsedWitnessTableEntries(IRSpecContext* context)
20172026
LinkedIR linkIR(CodeGenContext* codeGenContext)
20182027
{
20192028
SLANG_PROFILE;
2020-
2029+
if (codeGenContext->getSink()->getErrorCount() != 0)
2030+
printf("Failed to link IR\n");
20212031
auto linkage = codeGenContext->getLinkage();
20222032
auto program = codeGenContext->getProgram();
20232033
auto session = codeGenContext->getSession();
20242034
auto target = codeGenContext->getTargetFormat();
20252035
auto targetProgram = codeGenContext->getTargetProgram();
20262036
auto targetReq = codeGenContext->getTargetReq();
2027-
2037+
if (codeGenContext->getSink()->getErrorCount() != 0)
2038+
printf("Failed to link IR\n");
20282039
// TODO: We need to make sure that the program we are being asked
20292040
// to compile has been "resolved" so that it has no outstanding
20302041
// unsatisfied requirements.
@@ -2035,10 +2046,12 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
20352046
state->target = target;
20362047
state->targetReq = targetReq;
20372048
auto& irModules = stateStorage.contextStorage.irModules;
2038-
2049+
if (codeGenContext->getSink()->getErrorCount() != 0)
2050+
printf("Failed to link IR\n");
20392051
auto sharedContext = state->getSharedContext();
20402052
initializeSharedSpecContext(sharedContext, session, nullptr, target, targetReq);
2041-
2053+
if (codeGenContext->getSink()->getErrorCount() != 0)
2054+
printf("Failed to link IR\n");
20422055
state->irModule = sharedContext->module;
20432056

20442057
// We need to be able to look up IR definitions for any symbols in
@@ -2050,7 +2063,8 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
20502063
List<IRModule*> builtinModules;
20512064
for (auto& m : globalSession->coreModules)
20522065
builtinModules.add(m->getIRModule());
2053-
2066+
if (codeGenContext->getSink()->getErrorCount() != 0)
2067+
printf("Failed to link IR\n");
20542068
// Link modules in the program.
20552069
program->enumerateIRModules(
20562070
[&](IRModule* module)
@@ -2060,7 +2074,8 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
20602074
else
20612075
irModules.add(module);
20622076
});
2063-
2077+
if (codeGenContext->getSink()->getErrorCount() != 0)
2078+
printf("Failed to link IR\n");
20642079
// We will also consider the IR global symbols from the IR module
20652080
// attached to the `TargetProgram`, since this module is
20662081
// responsible for associating layout information to those
@@ -2073,7 +2088,8 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
20732088
Index userModuleCount = irModules.getCount();
20742089
irModules.addRange(builtinModules);
20752090
ArrayView<IRModule*> userModules = irModules.getArrayView(0, userModuleCount);
2076-
2091+
if (codeGenContext->getSink()->getErrorCount() != 0)
2092+
printf("Failed to link IR\n");
20772093
// Check if any user module uses auto-diff, if so we will need to link
20782094
// additional witnesses and decorations.
20792095
for (IRModule* irModule : userModules)
@@ -2094,14 +2110,17 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
20942110
}
20952111
addGlobalHashedStringLiterals(pool, state->irModule);
20962112
}
2097-
2113+
if (codeGenContext->getSink()->getErrorCount() != 0)
2114+
printf("Failed to link IR\n");
2115+
20982116
// Set up shared and builder insert point
20992117

21002118
context->shared = sharedContext;
21012119
context->builder = &sharedContext->builderStorage;
21022120

21032121
context->builder->setInsertInto(context->getModule()->getModuleInst());
2104-
2122+
if (codeGenContext->getSink()->getErrorCount() != 0)
2123+
printf("Failed to link IR\n");
21052124
// Next, we make sure to clone the global value for
21062125
// the entry point function itself, and rely on
21072126
// this step to recursively copy over anything else
@@ -2126,7 +2145,8 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
21262145
entryPoint,
21272146
nameOverride.getUnownedSlice()));
21282147
}
2129-
2148+
if (codeGenContext->getSink()->getErrorCount() != 0)
2149+
printf("Failed to link IR\n");
21302150
// Layout information for global shader parameters is also required,
21312151
// and in particular every global parameter that is part of the layout
21322152
// should be present in the initial IR module so that steps that
@@ -2143,7 +2163,8 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
21432163
cast<IRVarLayout>(cloneValue(context, irOriginalGlobalScopeVarLayout));
21442164
}
21452165
}
2146-
2166+
if (codeGenContext->getSink()->getErrorCount() != 0)
2167+
printf("Failed to link IR\n");
21472168
// Bindings for global generic parameters are currently represented
21482169
// as stand-alone global-scope instructions in the IR module for
21492170
// `SpecializedComponentType`s. These instructions are required for
@@ -2167,7 +2188,8 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
21672188
}
21682189
}
21692190
}
2170-
2191+
if (codeGenContext->getSink()->getErrorCount() != 0)
2192+
printf("Failed to link IR\n");
21712193
bool shouldCopyGlobalParams =
21722194
linkage->m_optionSet.getBoolOption(CompilerOptionName::PreserveParameters);
21732195

@@ -2190,7 +2212,8 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
21902212
}
21912213
}
21922214
}
2193-
2215+
if (codeGenContext->getSink()->getErrorCount() != 0)
2216+
printf("Failed to link IR\n");
21942217
// In previous steps, we have skipped cloning the witness table entries, and
21952218
// registered any used witness table entry keys to context->deferredWitnessTableEntryKeys
21962219
// for on-demand cloning. Now we will use the deferred keys to clone the witness table
@@ -2234,21 +2257,25 @@ LinkedIR linkIR(CodeGenContext* codeGenContext)
22342257
}
22352258
}
22362259
}
2237-
2260+
if (codeGenContext->getSink()->getErrorCount() != 0)
2261+
printf("Failed to link IR\n");
22382262
// Specialize target_switch branches to use the best branch for the target.
22392263
specializeTargetSwitch(targetReq, state->irModule, codeGenContext->getSink());
2240-
2264+
if (codeGenContext->getSink()->getErrorCount() != 0)
2265+
printf("Failed to link IR\n");
22412266
// Diagnose on unresolved symbols if we are compiling into a target that does
22422267
// not allow incomplete symbols.
22432268
// At this point, we should not see any [import] symbols that does not have a
22442269
// definition.
22452270
diagnoseUnresolvedSymbols(targetReq, codeGenContext->getSink(), state->irModule);
2246-
2271+
if (codeGenContext->getSink()->getErrorCount() != 0)
2272+
printf("Failed to link IR\n");
22472273
// type-use reformatter of GLSL types (only if compiler is set to AllowGLSL mode)
22482274
// which are not supported by SPIRV->Vulkan but is supported by GLSL->Vulkan through
22492275
// compiler magic tricks
22502276
GLSLReplaceAtomicUint(context, targetProgram, state->irModule);
2251-
2277+
if (codeGenContext->getSink()->getErrorCount() != 0)
2278+
printf("Failed to link IR\n");
22522279
// TODO: *technically* we should consider the case where
22532280
// we have global variables with initializers, since
22542281
// these should get run whether or not the entry point

source/slang/slang-ir.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -8671,6 +8671,10 @@ bool isDefinition(IRInst* inVal)
86718671
return val->getFirstChild() != nullptr;
86728672

86738673
case kIROp_GlobalConstant:
8674+
if (cast<IRGlobalConstant>(val)->getValue() == nullptr)
8675+
{
8676+
printf("Has no value\n");
8677+
}
86748678
return cast<IRGlobalConstant>(val)->getValue() != nullptr;
86758679

86768680
default:

source/slang/slang.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -1429,7 +1429,24 @@ Linkage::loadModule(const char* moduleName, slang::IBlob** outDiagnostics)
14291429
auto name = getNamePool()->getName(moduleName);
14301430

14311431
auto module = findOrImportModule(name, SourceLoc(), &sink);
1432+
14321433
sink.getBlobIfNeeded(outDiagnostics);
1434+
1435+
if (false && module->getInterface(slang::IModulePrecompileService_Experimental::getTypeGuid()))
1436+
{
1437+
auto interface = static_cast<slang::IModulePrecompileService_Experimental*>(module);
1438+
auto res = interface->precompileForTarget(SLANG_SPIRV, outDiagnostics);
1439+
// diagnose if needed
1440+
if (outDiagnostics)
1441+
{
1442+
sink.diagnoseRaw(Severity::Error, "Failed to precompile module for SPIRV");
1443+
}
1444+
if (SLANG_FAILED(res))
1445+
{
1446+
return nullptr;
1447+
}
1448+
1449+
}
14331450

14341451
return asExternal(module);
14351452
}
@@ -3667,6 +3684,27 @@ void EndToEndCompileRequest::init()
36673684
m_frontEndReq = new FrontEndCompileRequest(getLinkage(), m_writers, getSink());
36683685
}
36693686

3687+
static void dumpIRIfEnabled(
3688+
CodeGenContext* codeGenContext,
3689+
IRModule* irModule,
3690+
char const* label = nullptr)
3691+
{
3692+
if (codeGenContext->shouldDumpIR())
3693+
{
3694+
DiagnosticSinkWriter writer(codeGenContext->getSink());
3695+
// FILE* f = nullptr;
3696+
// fopen_s(&f, (String("dump-") + label + ".txt").getBuffer(), "wt");
3697+
// FileWriter writer(f, 0);
3698+
dumpIR(
3699+
irModule,
3700+
codeGenContext->getIRDumpOptions(),
3701+
label,
3702+
codeGenContext->getSourceManager(),
3703+
&writer);
3704+
// fclose(f);
3705+
}
3706+
}
3707+
36703708
SlangResult EndToEndCompileRequest::executeActionsInner()
36713709
{
36723710
SLANG_PROFILE_SECTION(endToEndActions);
@@ -3749,6 +3787,8 @@ SlangResult EndToEndCompileRequest::executeActionsInner()
37493787
}
37503788
}
37513789
}
3790+
3791+
37523792

37533793
// If codegen is enabled, we need to move along to
37543794
// apply any generic specialization that the user asked for.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// TEST_IGNORE_FILE
2+
3+
// export-library-global.slang
4+
5+
export static int myGlobalVar = 42;
6+
7+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//TEST:COMPILE: tests/library/precompiled-spirv-global.slang -o tests/library/precompiled-spirv-global.slang-module -target spirv -embed-downstream-ir
2+
3+
//import "export-library-global.slang"; //This would make the test pass
4+
5+
extern int myGlobalVar; //This makes the test fail
6+
7+
layout(location = 0) out float4 fragColor;
8+
9+
[shader("fragment")]
10+
void main() {
11+
fragColor = float4(myGlobalVar);
12+
}

0 commit comments

Comments
 (0)