summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang4
-rw-r--r--source/slang/core.meta.slang.h4
-rw-r--r--source/slang/slang-ir-link.cpp20
-rw-r--r--source/slang/slang-lower-to-ir.cpp16
-rw-r--r--source/slang/slang-modifier-defs.h5
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)