diff options
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/core.meta.slang | 4 | ||||
| -rw-r--r-- | source/slang/core.meta.slang.h | 4 | ||||
| -rw-r--r-- | source/slang/slang-ir-link.cpp | 20 | ||||
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 16 | ||||
| -rw-r--r-- | source/slang/slang-modifier-defs.h | 5 |
5 files changed, 45 insertions, 4 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index 3b94c4e05..763bd4a78 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -1318,3 +1318,7 @@ attribute_syntax [format(format : String)] : FormatAttribute; __attributeTarget(Decl) attribute_syntax [allow(diagnostic: String)] : AllowAttribute; +// Linking +__attributeTarget(Decl) +attribute_syntax [__extern] : ExternAttribute; + diff --git a/source/slang/core.meta.slang.h b/source/slang/core.meta.slang.h index cc8b796e0..7cb729722 100644 --- a/source/slang/core.meta.slang.h +++ b/source/slang/core.meta.slang.h @@ -1349,3 +1349,7 @@ SLANG_RAW("\n") SLANG_RAW("__attributeTarget(Decl)\n") SLANG_RAW("attribute_syntax [allow(diagnostic: String)] : AllowAttribute;\n") SLANG_RAW("\n") +SLANG_RAW("// Linking\n") +SLANG_RAW("__attributeTarget(Decl)\n") +SLANG_RAW("attribute_syntax [__extern] : ExternAttribute;\n") +SLANG_RAW("\n") diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp index 2d497158d..88f385548 100644 --- a/source/slang/slang-ir-link.cpp +++ b/source/slang/slang-ir-link.cpp @@ -979,6 +979,12 @@ bool isBetterForTarget( IRInst* newVal, IRInst* oldVal) { + // Anything is better than nothing.. + if (oldVal == nullptr) + { + return true; + } + String targetName = getTargetName(context); // For right now every declaration might have zero or more @@ -1000,7 +1006,7 @@ bool isBetterForTarget( // (A and B and C) or (A and D) or (E) or (F and G) ... // // A code generation target would then consist of a - // conjunction of invidual tags: + // conjunction of individual tags: // // (HLSL and SM_4_0 and Vertex and ...) // @@ -1012,6 +1018,7 @@ bool isBetterForTarget( // of the other's. auto newLevel = getTargetSpecialiationLevel(newVal, targetName); + auto oldLevel = getTargetSpecialiationLevel(oldVal, targetName); if(newLevel != oldLevel) return UInt(newLevel) > UInt(oldLevel); @@ -1182,18 +1189,23 @@ IRInst* cloneGlobalValueWithLinkage( // We will try to track the "best" declaration we can find. // - // Generally, one declaration wil lbe better than another if it is + // Generally, one declaration will be better than another if it is // more specialized for the chosen target. Otherwise, we simply favor // definitions over declarations. // - IRInst* bestVal = sym->irGlobalValue; - for( auto ss = sym->nextWithSameName; ss; ss = ss->nextWithSameName ) + IRInst* bestVal = nullptr; + for(IRSpecSymbol* ss = sym; ss; ss = ss->nextWithSameName ) { IRInst* newVal = ss->irGlobalValue; if(isBetterForTarget(context, newVal, bestVal)) bestVal = newVal; } + if (!bestVal) + { + return nullptr; + } + // Check if we've already cloned this value, for the case where // we didn't have an original value (just a name), but we've // now found a representative value. diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index e8e2ff61a..f50bd8be1 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -422,6 +422,22 @@ bool isFromStdLib(Decl* decl) bool isImportedDecl(IRGenContext* context, Decl* decl) { + // If the declaration has the extern attribute then it must be imported + // from another module + // + // The [__extern] attribute is a very special case feature (aka "a hack") that allows a symbol to be declared + // as if it is part of the current module for AST purposes, but then expects to be imported from another IR module. + // For that linkage to work, both the exporting and importing modules must have the same name (which would + // usually indicate that they are the same module). + // + // Note that in practice for matching during linking uses the fully qualified name - including module name. + // Thus using extern __attribute isn't useful for symbols that are imported via `import`, only symbols + // that notionally come from the same module but are split into separate compilations (as can be done with -module-name) + if (decl->FindModifier<ExternAttribute>()) + { + return true; + } + ModuleDecl* moduleDecl = findModuleDecl(decl); if (!moduleDecl) return false; diff --git a/source/slang/slang-modifier-defs.h b/source/slang/slang-modifier-defs.h index 5ac61b991..fb3292e23 100644 --- a/source/slang/slang-modifier-defs.h +++ b/source/slang/slang-modifier-defs.h @@ -460,3 +460,8 @@ END_SYNTAX_CLASS() SYNTAX_CLASS(AllowAttribute, Attribute) FIELD_INIT(DiagnosticInfo const*, diagnostic, nullptr) END_SYNTAX_CLASS() + + +// A `[__extern]` attribute, which indicates that a function/type is defined externally +// +SIMPLE_SYNTAX_CLASS(ExternAttribute, Attribute) |
