summaryrefslogtreecommitdiff
path: root/source/slang/ir-legalize-types.cpp
diff options
context:
space:
mode:
authorTim Foley <tfoleyNV@users.noreply.github.com>2017-12-18 15:14:59 -0800
committerGitHub <noreply@github.com>2017-12-18 15:14:59 -0800
commit393e25fd2e2b8c5ff82ff4c6b14a9d7152d37a5e (patch)
treea3b0617e7ce5a5bfcf43454893f6c2962b7ec382 /source/slang/ir-legalize-types.cpp
parent46b68ed41daecfaf1761e299cf040156e0f65ac0 (diff)
Work on getting rewriter + IR playing nice together. (#314)
* Work on getting rewriter + IR playing nice together. There are a few different changes here, with the goal of improving the interaction between the "rewriter" code generation approach and the new IR and type legalization code. The main changes are: - Add a new pass that occurs before the AST legalization pass, which walks the (used) AST declarations and tries to discover (1) which declarations need to be specialized/lowered via the IR, and (2) which declarations need to be included in the resulting AST module. - AST-based legalization now uses the generated list when in "rewriter" mode, so that we should be working around issues that users were seeing with types not getting emitted. - TODO: we still need an equivalent fixup in the case of non-"rewriter" emit, so this may still be a problem for `.slang` files. - IR type legalization now precedes AST legalization, so that we can record information on how any IR global values got legalized (e.g., if they got split). Then AST legalization includes logic to reconstruct suitable tuple expressions to reference a split global. - When emitting using IR + AST, we walk all of the declarations that we decided belonged to the IR, but which were subsequently referenced in the AST, to make sure they get output (this would include `struct` types that are declared in a file compiled via IR, but never used in IR-based code). The rewriter+IR use case still doesn't *quite* work, but the logic for walking the AST in a pre-pass ends up being needed/useful to fix some pure rewriter bugs, so I'm getting this checked in sooner rather than later. * Fixup: walk arguments to generic declaration reference The gotcha here is that the code for walking the AST would walk a line of code like: SomeType a; and know to traverse the declaration of `SomeType`, but if it saw a line of code like: ParameterBlock<SomeType> b; it would traverse the declaration of `ParameterBlock`, but fail to visit that of `SomeType`.
Diffstat (limited to 'source/slang/ir-legalize-types.cpp')
-rw-r--r--source/slang/ir-legalize-types.cpp164
1 files changed, 66 insertions, 98 deletions
diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp
index fedec4f87..5db3b4d33 100644
--- a/source/slang/ir-legalize-types.cpp
+++ b/source/slang/ir-legalize-types.cpp
@@ -17,78 +17,6 @@
namespace Slang
{
-
-
-struct LegalValImpl : RefObject
-{
-};
-struct TuplePseudoVal;
-struct PairPseudoVal;
-
-struct LegalVal
-{
- enum class Flavor
- {
- none,
- simple,
- implicitDeref,
- tuple,
- pair,
- };
-
- Flavor flavor = Flavor::none;
- RefPtr<RefObject> obj;
- IRValue* irValue = nullptr;
-
- static LegalVal simple(IRValue* irValue)
- {
- LegalVal result;
- result.flavor = Flavor::simple;
- result.irValue = irValue;
- return result;
- }
-
- IRValue* getSimple()
- {
- assert(flavor == Flavor::simple);
- return irValue;
- }
-
- static LegalVal tuple(RefPtr<TuplePseudoVal> tupleVal);
-
- RefPtr<TuplePseudoVal> getTuple()
- {
- assert(flavor == Flavor::tuple);
- return obj.As<TuplePseudoVal>();
- }
-
- static LegalVal implicitDeref(LegalVal const& val);
- LegalVal getImplicitDeref();
-
- static LegalVal pair(RefPtr<PairPseudoVal> pairInfo);
- static LegalVal pair(
- LegalVal const& ordinaryVal,
- LegalVal const& specialVal,
- RefPtr<PairInfo> pairInfo);
-
- RefPtr<PairPseudoVal> getPair()
- {
- assert(flavor == Flavor::pair);
- return obj.As<PairPseudoVal>();
- }
-};
-
-struct TuplePseudoVal : LegalValImpl
-{
- struct Element
- {
- DeclRef<VarDeclBase> fieldDeclRef;
- LegalVal val;
- };
-
- List<Element> elements;
-};
-
LegalVal LegalVal::tuple(RefPtr<TuplePseudoVal> tupleVal)
{
LegalVal result;
@@ -97,16 +25,6 @@ LegalVal LegalVal::tuple(RefPtr<TuplePseudoVal> tupleVal)
return result;
}
-struct PairPseudoVal : LegalValImpl
-{
- LegalVal ordinaryVal;
- LegalVal specialVal;
-
- // The info to tell us which fields
- // are on which side(s)
- RefPtr<PairInfo> pairInfo;
-};
-
LegalVal LegalVal::pair(RefPtr<PairPseudoVal> pairInfo)
{
LegalVal result;
@@ -135,11 +53,6 @@ LegalVal LegalVal::pair(
return LegalVal::pair(obj);
}
-struct ImplicitDerefVal : LegalValImpl
-{
- LegalVal val;
-};
-
LegalVal LegalVal::implicitDeref(LegalVal const& val)
{
RefPtr<ImplicitDerefVal> implicitDerefVal = new ImplicitDerefVal();
@@ -189,12 +102,37 @@ static void registerLegalizedValue(
context->mapValToLegalVal.Add(irValue, legalVal);
}
+static void maybeRegisterLegalizedGlobal(
+ IRTypeLegalizationContext* context,
+ IRGlobalVar* irGlobalVar,
+ LegalVal const& legalVal)
+{
+ // Check the mangled name of the symbol and don't register
+ // symbols that don't have an external name (currently
+ // indicated by them having an empty name string).
+ String mangledName = irGlobalVar->mangledName;
+ if (mangledName.Length() == 0)
+ return;
+
+ // Otherwise, register the legalized value for this symbol
+ // under its mangled name, so that other code can still
+ // find the right value(s) to use after legalization.
+ context->typeLegalizationContext->mapMangledNameToLegalIRValue.AddIfNotExists(mangledName, legalVal);
+}
+
+struct IRGlobalNameInfo
+{
+ IRGlobalVar* globalVar;
+ UInt counter;
+};
+
static LegalVal declareVars(
IRTypeLegalizationContext* context,
IROp op,
LegalType type,
TypeLayout* typeLayout,
- LegalVarChain* varChain);
+ LegalVarChain* varChain,
+ IRGlobalNameInfo* globalNameInfo);
static LegalType legalizeType(
IRTypeLegalizationContext* context,
@@ -608,7 +546,7 @@ static LegalVal legalizeLocalVar(
varChain = &varChainStorage;
}
- LegalVal newVal = declareVars(context, kIROp_Var, legalValueType, typeLayout, varChain);
+ LegalVal newVal = declareVars(context, kIROp_Var, legalValueType, typeLayout, varChain, nullptr);
// Remove the old local var.
irLocalVar->removeFromParent();
@@ -761,7 +699,7 @@ static void legalizeFunc(
context->insertBeforeParam = pp;
context->builder->curBlock = nullptr;
- auto paramVal = declareVars(context, kIROp_Param, legalParamType, nullptr, nullptr);
+ auto paramVal = declareVars(context, kIROp_Param, legalParamType, nullptr, nullptr, nullptr);
paramVals.Add(paramVal);
if (pp == bb->getFirstParam())
{
@@ -807,7 +745,8 @@ static LegalVal declareSimpleVar(
IROp op,
Type* type,
TypeLayout* typeLayout,
- LegalVarChain* varChain)
+ LegalVarChain* varChain,
+ IRGlobalNameInfo* globalNameInfo)
{
RefPtr<VarLayout> varLayout = createVarLayout(varChain, typeLayout);
@@ -830,6 +769,25 @@ static LegalVal declareSimpleVar(
globalVar->removeFromParent();
globalVar->insertBefore(context->insertBeforeGlobal, builder->getModule());
+ // The legalization of a global variable with linkage (one that has
+ // a mangled name), must also have an exported name, so that code
+ // can link against it.
+ //
+ // For now we do something *really* simplistic, and just append
+ // a counter to each leaf variable generated from the original
+ if (globalNameInfo)
+ {
+ String mangledName = globalNameInfo->globalVar->mangledName;
+ if (mangledName.Length() != 0)
+ {
+ mangledName.append("L");
+ mangledName.append(globalNameInfo->counter++);
+ globalVar->mangledName = mangledName;
+ }
+ }
+
+
+
irVar = globalVar;
legalVarVal = LegalVal::simple(irVar);
}
@@ -887,7 +845,8 @@ static LegalVal declareVars(
IROp op,
LegalType type,
TypeLayout* typeLayout,
- LegalVarChain* varChain)
+ LegalVarChain* varChain,
+ IRGlobalNameInfo* globalNameInfo)
{
switch (type.flavor)
{
@@ -895,7 +854,7 @@ static LegalVal declareVars(
return LegalVal();
case LegalType::Flavor::simple:
- return declareSimpleVar(context, op, type.getSimple(), typeLayout, varChain);
+ return declareSimpleVar(context, op, type.getSimple(), typeLayout, varChain, globalNameInfo);
break;
case LegalType::Flavor::implicitDeref:
@@ -908,7 +867,8 @@ static LegalVal declareVars(
op,
type.getImplicitDeref()->valueType,
getDerefTypeLayout(typeLayout),
- varChain);
+ varChain,
+ globalNameInfo);
return LegalVal::implicitDeref(val);
}
break;
@@ -916,8 +876,8 @@ static LegalVal declareVars(
case LegalType::Flavor::pair:
{
auto pairType = type.getPair();
- auto ordinaryVal = declareVars(context, op, pairType->ordinaryType, typeLayout, varChain);
- auto specialVal = declareVars(context, op, pairType->specialType, typeLayout, varChain);
+ auto ordinaryVal = declareVars(context, op, pairType->ordinaryType, typeLayout, varChain, globalNameInfo);
+ auto specialVal = declareVars(context, op, pairType->specialType, typeLayout, varChain, globalNameInfo);
return LegalVal::pair(ordinaryVal, specialVal, pairType->pairInfo);
}
@@ -951,7 +911,8 @@ static LegalVal declareVars(
op,
ee.type,
fieldTypeLayout,
- newVarChain);
+ newVarChain,
+ globalNameInfo);
TuplePseudoVal::Element element;
element.fieldDeclRef = ee.fieldDeclRef;
@@ -1003,11 +964,18 @@ static void legalizeGlobalVar(
varChain = &varChainStorage;
}
- LegalVal newVal = declareVars(context, kIROp_global_var, legalValueType, typeLayout, varChain);
+ IRGlobalNameInfo globalNameInfo;
+ globalNameInfo.globalVar = irGlobalVar;
+ globalNameInfo.counter = 0;
+
+ LegalVal newVal = declareVars(context, kIROp_global_var, legalValueType, typeLayout, varChain, &globalNameInfo);
// Register the new value as the replacement for the old
registerLegalizedValue(context, irGlobalVar, newVal);
+ // Also register the variable according to its mangled name, if any.
+ maybeRegisterLegalizedGlobal(context, irGlobalVar, newVal);
+
// Remove the old global from the module.
irGlobalVar->removeFromParent();
// TODO: actually clean up the global!