summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-02-26 17:00:31 -0800
committerGitHub <noreply@github.com>2024-02-26 17:00:31 -0800
commit39522159c245e32a99cfdc47f03236f7028f5c61 (patch)
tree4ae93fb32f267f7caa5ce55a6a52aac9f1f33bdd /source/slang
parent1d8e93cd434f0c7acbb6db747b32c3a3720c5c2e (diff)
Allow default values for `extern` symbols. (#3632)
* Allow default values for `extern` symbols. * Fix. * Fix test.
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/slang-ast-decl.h1
-rw-r--r--source/slang/slang-check-conformance.cpp12
-rw-r--r--source/slang/slang-check-decl.cpp17
-rw-r--r--source/slang/slang-check-impl.h2
-rw-r--r--source/slang/slang-diagnostic-defs.h2
-rw-r--r--source/slang/slang-ir-inst-defs.h3
-rw-r--r--source/slang/slang-ir-insts.h11
-rw-r--r--source/slang/slang-ir-link.cpp100
-rw-r--r--source/slang/slang-ir-peephole.cpp11
-rw-r--r--source/slang/slang-ir-peephole.h13
-rw-r--r--source/slang/slang-ir-ssa-simplification.cpp2
-rw-r--r--source/slang/slang-ir-ssa-simplification.h3
-rw-r--r--source/slang/slang-ir.cpp8
-rw-r--r--source/slang/slang-ir.h2
-rw-r--r--source/slang/slang-lower-to-ir.cpp71
-rw-r--r--source/slang/slang-options.cpp3
-rw-r--r--source/slang/slang-parser.cpp3
-rw-r--r--source/slang/slang-serialize-container.cpp2
-rw-r--r--source/slang/slang.cpp3
19 files changed, 199 insertions, 70 deletions
diff --git a/source/slang/slang-ast-decl.h b/source/slang/slang-ast-decl.h
index c516b15c7..61e1b751f 100644
--- a/source/slang/slang-ast-decl.h
+++ b/source/slang/slang-ast-decl.h
@@ -146,6 +146,7 @@ class AggTypeDecl : public AggTypeDeclBase
// Used if this type declaration is a wrapper, i.e. struct FooWrapper:IFoo = Foo;
TypeExp wrappedType;
+ bool hasBody = true;
void unionTagsWith(TypeTag other);
void addTag(TypeTag tag);
diff --git a/source/slang/slang-check-conformance.cpp b/source/slang/slang-check-conformance.cpp
index 726572d08..e73c0723b 100644
--- a/source/slang/slang-check-conformance.cpp
+++ b/source/slang/slang-check-conformance.cpp
@@ -279,18 +279,16 @@ namespace Slang
}
- Type* SemanticsVisitor::getBufferElementType(Type* type)
+ Type* SemanticsVisitor::getConstantBufferElementType(Type* type)
{
if (auto arrType = as<ArrayExpressionType>(type))
- return getBufferElementType(arrType->getElementType());
+ return getConstantBufferElementType(arrType->getElementType());
if (auto modifiedType = as<ModifiedType>(type))
- return getBufferElementType(modifiedType->getBase());
+ return getConstantBufferElementType(modifiedType->getBase());
if (auto constantBuffer = as<ConstantBufferType>(type))
return constantBuffer->getElementType();
- if (auto structuredBuffer = as<HLSLStructuredBufferTypeBase>(type))
- return structuredBuffer->getElementType();
- if (auto storageBuffer = as<GLSLShaderStorageBufferType>(type))
- return storageBuffer->getElementType();
+ if (auto parameterBlock = as<ParameterBlockType>(type))
+ return parameterBlock->getElementType();
return nullptr;
}
diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp
index 25f535825..5a9559ce6 100644
--- a/source/slang/slang-check-decl.cpp
+++ b/source/slang/slang-check-decl.cpp
@@ -1478,11 +1478,6 @@ namespace Slang
}
else
{
- if (varDecl->hasModifier<ExternModifier>())
- {
- getSink()->diagnose(initExpr, Diagnostics::externValueCannotHaveInitializer);
- }
-
initExpr = CheckExpr(initExpr);
// TODO: We might need some additional steps here to ensure
@@ -1850,7 +1845,7 @@ namespace Slang
varDecl->initExpr = CompleteOverloadCandidate(overloadContext, *overloadContext.bestCandidate);
}
}
- if (auto elementType = getBufferElementType(varDecl->getType()))
+ if (auto elementType = getConstantBufferElementType(varDecl->getType()))
{
if (doesTypeHaveTag(elementType, TypeTag::Incomplete))
{
@@ -5166,6 +5161,13 @@ namespace Slang
return false;
}
+ static bool _doesTypeDeclHaveDefinition(ContainerDecl* decl)
+ {
+ if (auto aggTypeDecl = as<AggTypeDecl>(decl))
+ return aggTypeDecl->hasBody;
+ return false;
+ }
+
bool SemanticsVisitor::checkConformance(
Type* subType,
InheritanceDecl* inheritanceDecl,
@@ -5244,7 +5246,8 @@ namespace Slang
witnessTable = new WitnessTable();
witnessTable->baseType = superType;
witnessTable->witnessedType = subType;
- witnessTable->isExtern = parentDecl->hasModifier<ExternModifier>();
+ witnessTable->isExtern = (!_doesTypeDeclHaveDefinition(parentDecl)
+ && parentDecl->hasModifier<ExternModifier>());
inheritanceDecl->witnessTable = witnessTable;
}
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index 8abf06d6f..d91bbb75b 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -1978,7 +1978,7 @@ namespace Slang
TypeTag getTypeTags(Type* type);
- Type* getBufferElementType(Type* type);
+ Type* getConstantBufferElementType(Type* type);
/// Check whether `subType` is a sub-type of `superTypeDeclRef`,
/// and return a witness to the sub-type relationship if it holds
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index c90dc12e8..d638f7be6 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -484,7 +484,6 @@ DIAGNOSTIC(30504, Error, cannotUseInitializerListForType, "cannot use initialize
// 3062x: variables
DIAGNOSTIC(30620, Error, varWithoutTypeMustHaveInitializer, "a variable declaration without an initial-value expression must be given an explicit type")
-DIAGNOSTIC(30621, Error, externValueCannotHaveInitializer, "an 'extern' variable declaration cannot have a value.")
DIAGNOSTIC(30622, Error, ambiguousDefaultInitializerForType, "more than one default initializer was found for type '$0'")
// 307xx: parameters
@@ -713,6 +712,7 @@ DIAGNOSTIC(41904, Error, unableToAlignOf, "alignof could not be performed for ty
DIAGNOSTIC(42001, Error, invalidUseOfTorchTensorTypeInDeviceFunc, "invalid use of TorchTensor type in device/kernel functions. use `TensorView` instead.")
+DIAGNOSTIC(45001, Error, unresolvedSymbol, "unresolved external symbol '$0'.")
//
// 5xxxx - Target code generation.
//
diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h
index 0c962b7a4..cb89b265b 100644
--- a/source/slang/slang-ir-inst-defs.h
+++ b/source/slang/slang-ir-inst-defs.h
@@ -787,6 +787,9 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0)
INST(ExportDecoration, export, 1, 0)
INST_RANGE(LinkageDecoration, ImportDecoration, ExportDecoration)
+ /// Marks an inst as coming from an `extern` symbol defined in the user code.
+ INST(UserExternDecoration, UserExtern, 0, 0)
+
/// An extern_cpp decoration marks the inst to emit its name without mangling for C++ interop.
INST(ExternCppDecoration, externCpp, 1, 0)
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 82d891459..f1160c9a6 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -526,6 +526,12 @@ struct IRLinkageDecoration : IRDecoration
}
};
+struct IRUserExternDecoration : IRDecoration
+{
+ enum { kOp = kIROp_UserExternDecoration };
+ IR_LEAF_ISA(UserExternDecoration)
+};
+
struct IRImportDecoration : IRLinkageDecoration
{
enum { kOp = kIROp_ImportDecoration };
@@ -4346,6 +4352,11 @@ public:
addDecoration(value, kIROp_ExportDecoration, getStringValue(mangledName));
}
+ void addUserExternDecoration(IRInst* value)
+ {
+ addDecoration(value, kIROp_UserExternDecoration);
+ }
+
void addExternCppDecoration(IRInst* value, UnownedStringSlice const& mangledName)
{
addDecoration(value, kIROp_ExternCppDecoration, getStringValue(mangledName));
diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp
index be0b87b60..e81eddab7 100644
--- a/source/slang/slang-ir-link.cpp
+++ b/source/slang/slang-ir-link.cpp
@@ -1425,6 +1425,100 @@ static bool _isHLSLExported(IRInst* inst)
return false;
}
+static bool doesFuncHaveDefinition(IRFunc* func)
+{
+ if (func->getFirstBlock() != nullptr)
+ return true;
+ for (auto decor : func->getDecorations())
+ {
+ switch (decor->getOp())
+ {
+ case kIROp_IntrinsicOpDecoration:
+ case kIROp_TargetIntrinsicDecoration:
+ return true;
+ default:
+ continue;
+ }
+ }
+ return false;
+}
+
+static bool doesWitnessTableHaveDefinition(IRWitnessTable* wt)
+{
+ auto interfaceType = as<IRInterfaceType>(wt->getConformanceType());
+ if (!interfaceType)
+ return true;
+ auto interfaceRequirementCount = interfaceType->getRequirementCount();
+ if (interfaceRequirementCount == 0)
+ return true;
+ for (auto entry : wt->getChildren())
+ {
+ if (as<IRWitnessTableEntry>(entry))
+ return true;
+ }
+ return false;
+}
+
+static bool doesTargetAllowUnresolvedFuncSymbol(TargetRequest* req)
+{
+ switch (req->getTarget())
+ {
+ case CodeGenTarget::HLSL:
+ case CodeGenTarget::DXIL:
+ case CodeGenTarget::DXILAssembly:
+ case CodeGenTarget::HostCPPSource:
+ case CodeGenTarget::PyTorchCppBinding:
+ case CodeGenTarget::ShaderHostCallable:
+ case CodeGenTarget::ShaderSharedLibrary:
+ case CodeGenTarget::HostHostCallable:
+ case CodeGenTarget::CPPSource:
+ case CodeGenTarget::CUDASource:
+ case CodeGenTarget::SPIRV:
+ if (req->getOptionSet().getBoolOption(CompilerOptionName::IncompleteLibrary))
+ return true;
+ default:
+ return false;
+ }
+}
+
+static void diagnoseUnresolvedSymbols(TargetRequest* req, DiagnosticSink* sink, IRModule* module)
+{
+ for (auto globalSym : module->getGlobalInsts())
+ {
+ if (globalSym->findDecoration<IRImportDecoration>())
+ {
+ for (;;)
+ {
+ if (auto constant = as<IRGlobalConstant>(globalSym))
+ {
+ if (constant->getOperandCount() == 0)
+ sink->diagnose(globalSym->sourceLoc, Diagnostics::unresolvedSymbol, globalSym);
+ }
+ else if (auto genericSym = as<IRGeneric>(globalSym))
+ {
+ globalSym = findGenericReturnVal(genericSym);
+ continue;
+ }
+ else if (auto funcSym = as<IRFunc>(globalSym))
+ {
+ if (!doesFuncHaveDefinition(funcSym) && !doesTargetAllowUnresolvedFuncSymbol(req))
+ sink->diagnose(globalSym->sourceLoc, Diagnostics::unresolvedSymbol, globalSym);
+ }
+ else if (auto witnessSym = as<IRWitnessTable>(globalSym))
+ {
+ if (!doesWitnessTableHaveDefinition(witnessSym))
+ {
+ sink->diagnose(globalSym->sourceLoc, Diagnostics::unresolvedSymbol, witnessSym);
+ if (auto concreteType = witnessSym->getConcreteType())
+ sink->diagnose(concreteType->sourceLoc, Diagnostics::seeDeclarationOf, concreteType);
+ }
+ }
+ break;
+ }
+ }
+ }
+}
+
LinkedIR linkIR(
CodeGenContext* codeGenContext)
{
@@ -1627,6 +1721,12 @@ LinkedIR linkIR(
// Specialize target_switch branches to use the best branch for the target.
specializeTargetSwitch(targetReq, state->irModule);
+ // Diagnose on unresolved symbols if we are compiling into a target that does
+ // not allow incomplete symbols.
+ // At this point, we should not see any [import] symbols that does not have a
+ // definition.
+ diagnoseUnresolvedSymbols(targetReq, codeGenContext->getSink(), state->irModule);
+
// TODO: *technically* we should consider the case where
// we have global variables with initializers, since
// these should get run whether or not the entry point
diff --git a/source/slang/slang-ir-peephole.cpp b/source/slang/slang-ir-peephole.cpp
index f9fca35e3..d8327a580 100644
--- a/source/slang/slang-ir-peephole.cpp
+++ b/source/slang/slang-ir-peephole.cpp
@@ -17,6 +17,7 @@ struct PeepholeContext : InstPassBase
FloatingPointMode floatingPointMode = FloatingPointMode::Precise;
bool removeOldInst = true;
bool isInGeneric = false;
+ bool isPrelinking = false;
TargetProgram* targetProgram;
@@ -695,6 +696,13 @@ struct PeepholeContext : InstPassBase
{
if (inst->getOperand(0)->getOp() == kIROp_WitnessTable)
{
+ // Don't fold witness lookups prelinking if the witness table is `extern`.
+ // These witness tables provides `default`s in case they are not
+ // explicitly specialized via other linked modules, therefore we don't want
+ // to resolve them too soon before linking.
+ if (isPrelinking && inst->getOperand(0)->findDecoration<IRUserExternDecoration>())
+ break;
+
auto wt = as<IRWitnessTable>(inst->getOperand(0));
auto key = inst->getOperand(1);
for (auto item : wt->getChildren())
@@ -1069,10 +1077,11 @@ struct PeepholeContext : InstPassBase
}
};
-bool peepholeOptimize(TargetProgram* target, IRModule* module)
+bool peepholeOptimize(TargetProgram* target, IRModule* module, PeepholeOptimizationOptions options)
{
PeepholeContext context = PeepholeContext(module);
context.targetProgram = target;
+ context.isPrelinking = options.isPrelinking;
return context.processModule();
}
diff --git a/source/slang/slang-ir-peephole.h b/source/slang/slang-ir-peephole.h
index 9aa2d6164..411267072 100644
--- a/source/slang/slang-ir-peephole.h
+++ b/source/slang/slang-ir-peephole.h
@@ -8,8 +8,19 @@ namespace Slang
struct IRInst;
class TargetProgram;
+ struct PeepholeOptimizationOptions
+ {
+ bool isPrelinking = false;
+ static PeepholeOptimizationOptions getPrelinking()
+ {
+ PeepholeOptimizationOptions result;
+ result.isPrelinking = true;
+ return result;
+ }
+ };
+
/// Apply peephole optimizations.
- bool peepholeOptimize(TargetProgram* target, IRModule* module);
+ bool peepholeOptimize(TargetProgram* target, IRModule* module, PeepholeOptimizationOptions options);
bool peepholeOptimize(TargetProgram* target, IRInst* func);
bool peepholeOptimizeGlobalScope(TargetProgram* target, IRModule* module);
bool tryReplaceInstUsesWithSimplifiedValue(TargetProgram* target, IRModule* module, IRInst* inst);
diff --git a/source/slang/slang-ir-ssa-simplification.cpp b/source/slang/slang-ir-ssa-simplification.cpp
index 77cad9f6c..6a0fb620e 100644
--- a/source/slang/slang-ir-ssa-simplification.cpp
+++ b/source/slang/slang-ir-ssa-simplification.cpp
@@ -76,7 +76,7 @@ namespace Slang
while (changed && iterationCounter < kMaxIterations)
{
changed = false;
- changed |= peepholeOptimize(target, module);
+ changed |= peepholeOptimize(target, module, options.peepholeOptions);
changed |= removeRedundancy(module);
changed |= simplifyCFG(module, options.cfgOptions);
diff --git a/source/slang/slang-ir-ssa-simplification.h b/source/slang/slang-ir-ssa-simplification.h
index c15ffc822..4ae8e8e6e 100644
--- a/source/slang/slang-ir-ssa-simplification.h
+++ b/source/slang/slang-ir-ssa-simplification.h
@@ -2,6 +2,7 @@
#pragma once
#include "slang-ir-simplify-cfg.h"
+#include "slang-ir-peephole.h"
namespace Slang
{
@@ -13,6 +14,8 @@ namespace Slang
struct IRSimplificationOptions
{
CFGSimplificationOptions cfgOptions;
+ PeepholeOptimizationOptions peepholeOptions;
+
static IRSimplificationOptions getDefault()
{
IRSimplificationOptions result;
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index 035b2aade..a016679e7 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -32,7 +32,15 @@ namespace Slang
if (!irObject)
return;
if (auto nameHint = irObject->findDecoration<IRNameHintDecoration>())
+ {
sb << nameHint->getName();
+ return;
+ }
+ if (auto linkage = irObject->findDecoration<IRLinkageDecoration>())
+ {
+ sb << linkage->getMangledName();
+ return;
+ }
}
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h
index bbb9dfeeb..3a459a501 100644
--- a/source/slang/slang-ir.h
+++ b/source/slang/slang-ir.h
@@ -1878,6 +1878,8 @@ struct IRInterfaceRequirementEntry : IRInst
struct IRInterfaceType : IRType
{
IR_LEAF_ISA(InterfaceType)
+
+ UInt getRequirementCount() { return getOperandCount(); }
};
struct IRConjunctionType : IRType
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index 9d010ec1c..8b9a3c377 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -654,47 +654,30 @@ bool isFromStdLib(Decl* decl)
return false;
}
-bool isImportedDecl(IRGenContext* context, Decl* decl)
+bool isImportedDecl(IRGenContext* context, Decl* decl, bool& outIsExplicitExtern)
{
// If the declaration has the extern attribute then it must be imported
// from another module.
// Note that `extern` declarations will have a mangled name that does not
// include the module name so the linking step can resolve them correctly.
//
+ outIsExplicitExtern = false;
if (decl->findModifier<ExternAttribute>() || decl->findModifier<ExternModifier>())
{
+ outIsExplicitExtern = true;
return true;
}
- ModuleDecl* moduleDecl = findModuleDecl(decl);
- if (!moduleDecl)
- return false;
-
-#if 0
- // HACK: don't treat standard library code as
- // being imported for right now, just because
- // we don't load its IR in the same way as
- // for other imports.
- //
- // TODO: Fix this the right way, by having standard
- // library declarations have IR modules that we link
- // in via the normal means.
- if (isFromStdLib(decl))
- return false;
-#endif
-
- if (moduleDecl != context->getMainModuleDecl())
- return true;
-
- return false;
-}
-
- /// Is `decl` a function that should be force-inlined early in compilation (before linking)?
-static bool isForceInlineEarly(Decl* decl)
-{
- if(decl->hasModifier<UnsafeForceInlineEarlyAttribute>())
- return true;
-
+ for (auto parent = decl; parent; parent = parent->parentDecl)
+ {
+ if (as<ModuleDecl>(parent) && parent != context->getMainModuleDecl())
+ return true;
+ if (parent->findModifier<ExternAttribute>() || parent->findModifier<ExternModifier>())
+ {
+ outIsExplicitExtern = true;
+ return true;
+ }
+ }
return false;
}
@@ -1325,9 +1308,12 @@ static void addLinkageDecoration(
inst = outerGeneric;
}
- if (isImportedDecl(context, decl))
+ bool explicitExtern = false;
+ if (isImportedDecl(context, decl, explicitExtern))
{
builder->addImportDecoration(inst, mangledName);
+ if (explicitExtern)
+ builder->addUserExternDecoration(inst);
}
else
{
@@ -7597,12 +7583,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// the underlying storage.
context->setGlobalValue(decl, globalVal);
- if (isImportedDecl(decl))
- {
- // Always emit imported declarations as declarations,
- // and not definitions.
- }
- else if( auto initExpr = decl->initExpr )
+ if( auto initExpr = decl->initExpr )
{
IRBuilder subBuilderStorage = *getBuilder();
IRBuilder* subBuilder = &subBuilderStorage;
@@ -8410,11 +8391,6 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
return LoweredValInfo::simple(irFieldKey);
}
- bool isImportedDecl(Decl* decl)
- {
- return Slang::isImportedDecl(context, decl);
- }
-
IRType* maybeGetConstExprType(IRType* type, Decl* decl)
{
return Slang::maybeGetConstExprType(getBuilder(), type, decl);
@@ -9105,12 +9081,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
// pre-generated IR for the module that defines it (or do some kind
// of minimal linking to bring in the inline functions).
//
- if (isImportedDecl(decl) && !isForceInlineEarly(decl))
- {
- // Always emit imported declarations as declarations,
- // and not definitions.
- }
- else if (!decl->body)
+ if (!decl->body)
{
// This is a function declaration without a body.
// In Slang we currently try not to support forward declarations
@@ -10374,7 +10345,7 @@ RefPtr<IRModule> generateIRForTranslationUnit(
constructSSA(module);
simplifyCFG(module, CFGSimplificationOptions::getDefault());
applySparseConditionalConstantPropagation(module, compileRequest->getSink());
- peepholeOptimize(nullptr, module);
+ peepholeOptimize(nullptr, module, PeepholeOptimizationOptions::getPrelinking());
for (auto inst : module->getGlobalInsts())
{
@@ -10423,7 +10394,7 @@ RefPtr<IRModule> generateIRForTranslationUnit(
changed |= constructSSA(module);
simplifyCFG(module, CFGSimplificationOptions::getDefault());
changed |= applySparseConditionalConstantPropagation(module, compileRequest->getSink());
- changed |= peepholeOptimize(nullptr, module);
+ changed |= peepholeOptimize(nullptr, module, PeepholeOptimizationOptions::getPrelinking());
for (auto inst : module->getGlobalInsts())
{
if (auto func = as<IRGlobalValueWithCode>(inst))
diff --git a/source/slang/slang-options.cpp b/source/slang/slang-options.cpp
index 39578a1ea..f8231210c 100644
--- a/source/slang/slang-options.cpp
+++ b/source/slang/slang-options.cpp
@@ -417,6 +417,8 @@ void initCommandOptions(CommandOptions& options)
"Generate SPIR-V output direclty rather than by compiling generated GLSL with glslang" },
{ OptionKind::SPIRVCoreGrammarJSON, "-spirv-core-grammar", nullptr,
"A path to a specific spirv.core.grammar.json to use when generating SPIR-V output" },
+ { OptionKind::IncompleteLibrary, "-incomplete-library", nullptr,
+ "Allow generating code from incomplete libraries with unresolved external functions" },
#endif
};
@@ -1681,6 +1683,7 @@ SlangResult OptionsParser::_parse(
case OptionKind::OutputIncludes:
case OptionKind::PreprocessorOutput:
case OptionKind::DumpAst:
+ case OptionKind::IncompleteLibrary:
linkage->m_optionSet.set(optionKind, true); break;
break;
case OptionKind::NoCodeGen:
diff --git a/source/slang/slang-parser.cpp b/source/slang/slang-parser.cpp
index 7ce710469..5555647f4 100644
--- a/source/slang/slang-parser.cpp
+++ b/source/slang/slang-parser.cpp
@@ -4744,7 +4744,10 @@ namespace Slang
return rs;
}
if (AdvanceIf(this, TokenType::Semicolon))
+ {
+ rs->hasBody = false;
return rs;
+ }
parseDeclBody(this, rs);
return rs;
});
diff --git a/source/slang/slang-serialize-container.cpp b/source/slang/slang-serialize-container.cpp
index 0622c2bd4..5b382f03d 100644
--- a/source/slang/slang-serialize-container.cpp
+++ b/source/slang/slang-serialize-container.cpp
@@ -81,6 +81,8 @@ namespace Slang {
SLANG_ASSERT(dstModule.irModule);
}
DigestBuilder<SHA1> digestBuilder;
+ auto version = String(getBuildTagString());
+ digestBuilder.append(version);
module->getOptionSet().buildHash(digestBuilder);
auto fileDependencies = module->getFileDependencies();
String canonicalModulePath, moduleDir;
diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp
index bc91622f0..9a653aded 100644
--- a/source/slang/slang.cpp
+++ b/source/slang/slang.cpp
@@ -2907,7 +2907,6 @@ SlangResult EndToEndCompileRequest::executeActionsInner()
//
for (auto targetReq : getLinkage()->targets)
{
- targetReq->getOptionSet().inheritFrom(getLinkage()->m_optionSet);
auto targetProgram = m_specializedGlobalAndEntryPointsComponentType->getTargetProgram(targetReq);
targetProgram->getOrCreateLayout(getSink());
}
@@ -3559,6 +3558,8 @@ bool Linkage::isBinaryModuleUpToDate(String fromPath, RiffContainer* container)
auto& moduleHeader = containerData.modules[0];
DigestBuilder<SHA1> digestBuilder;
+ auto version = String(getBuildTagString());
+ digestBuilder.append(version);
m_optionSet.buildHash(digestBuilder);
for (auto file : moduleHeader.dependentFiles)
{