diff options
| author | Tim Foley <tfoleyNV@users.noreply.github.com> | 2018-01-21 18:05:39 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2018-01-21 18:05:39 -0800 |
| commit | 41311209af4963f44acf34942d42828590d4b156 (patch) | |
| tree | 97318b544324b26f056fc824f22ba91e821c6330 /source/slang | |
| parent | 8196dc4a684a75344e507697273e2123af97b979 (diff) | |
Fix legalization of generic types (#377)
Previously, all legalizations of a generic type would use the name of the original decl for the "ordinary" part of things, and this would lead to collisions because the names didn't include the mangled generic arguments.
This is now fixed by storing the mangled name of the original inside of `struct` declarations created for legalization, and using those names instead.
Also adds support for `getElementPtr` instructions when doing IR type legalization.
Also tries to make a `DeclRefType` convert to a string using the underlying `DeclRef`. This doesn't help because `DeclRef::toString` doesn't actually include generic arguments either.
Diffstat (limited to 'source/slang')
| -rw-r--r-- | source/slang/ir-legalize-types.cpp | 111 | ||||
| -rw-r--r-- | source/slang/legalize-types.cpp | 10 | ||||
| -rw-r--r-- | source/slang/mangle.cpp | 7 | ||||
| -rw-r--r-- | source/slang/modifier-defs.h | 4 | ||||
| -rw-r--r-- | source/slang/syntax.cpp | 2 |
5 files changed, 130 insertions, 4 deletions
diff --git a/source/slang/ir-legalize-types.cpp b/source/slang/ir-legalize-types.cpp index 5db3b4d33..d4f6d2a64 100644 --- a/source/slang/ir-legalize-types.cpp +++ b/source/slang/ir-legalize-types.cpp @@ -470,6 +470,114 @@ static LegalVal legalizeFieldAddress( fieldDeclRef); } +static LegalVal legalizeGetElementPtr( + IRTypeLegalizationContext* context, + LegalType type, + LegalVal legalPtrOperand, + IRValue* indexOperand) +{ + auto builder = context->builder; + + switch (legalPtrOperand.flavor) + { + case LegalVal::Flavor::simple: + return LegalVal::simple( + builder->emitElementAddress( + type.getSimple(), + legalPtrOperand.getSimple(), + indexOperand)); + + case LegalVal::Flavor::pair: + { + // There are two sides, the ordinary and the special, + // and we basically just dispatch to both of them. + auto pairVal = legalPtrOperand.getPair(); + auto pairInfo = pairVal->pairInfo; + + LegalType ordinaryType = type; + LegalType specialType = type; + if (type.flavor == LegalType::Flavor::pair) + { + auto pairType = type.getPair(); + ordinaryType = pairType->ordinaryType; + specialType = pairType->specialType; + } + + LegalVal ordinaryVal = legalizeGetElementPtr( + context, + ordinaryType, + pairVal->ordinaryVal, + indexOperand); + + LegalVal specialVal = legalizeGetElementPtr( + context, + specialType, + pairVal->specialVal, + indexOperand); + + return LegalVal::pair(ordinaryVal, specialVal, pairInfo); + } + break; + + case LegalVal::Flavor::tuple: + { + // The operand is a tuple of pointer-like + // values, we want to extract the element + // corresponding to a field. We will handle + // this by simply returning the corresponding + // element from the operand. + auto ptrTupleInfo = legalPtrOperand.getTuple(); + + RefPtr<TuplePseudoVal> resTupleInfo = new TuplePseudoVal(); + + auto tupleType = type.getTuple(); + assert(tupleType); + + auto elemCount = ptrTupleInfo->elements.Count(); + assert(elemCount == tupleType->elements.Count()); + + for(UInt ee = 0; ee < elemCount; ++ee) + { + auto ptrElem = ptrTupleInfo->elements[ee]; + auto elemType = tupleType->elements[ee].type; + + TuplePseudoVal::Element resElem; + resElem.fieldDeclRef = ptrElem.fieldDeclRef; + resElem.val = legalizeGetElementPtr( + context, + elemType, + ptrElem.val, + indexOperand); + + resTupleInfo->elements.Add(resElem); + } + + return LegalVal::tuple(resTupleInfo); + } + + default: + SLANG_UNEXPECTED("unhandled"); + UNREACHABLE_RETURN(LegalVal()); + } +} + +static LegalVal legalizeGetElementPtr( + IRTypeLegalizationContext* context, + LegalType type, + LegalVal legalPtrOperand, + LegalVal legalIndexOperand) +{ + // We don't expect any legalization to affect + // the "index" argument. + auto indexOperand = legalIndexOperand.getSimple(); + + return legalizeGetElementPtr( + context, + type, + legalPtrOperand, + indexOperand); +} + static LegalVal legalizeInst( IRTypeLegalizationContext* context, IRInst* inst, @@ -484,6 +592,9 @@ static LegalVal legalizeInst( case kIROp_FieldAddress: return legalizeFieldAddress(context, type, args[0], args[1]); + case kIROp_getElementPtr: + return legalizeGetElementPtr(context, type, args[0], args[1]); + case kIROp_Store: return legalizeStore(context, args[0], args[1]); diff --git a/source/slang/legalize-types.cpp b/source/slang/legalize-types.cpp index d1cef4dac..76fda18e3 100644 --- a/source/slang/legalize-types.cpp +++ b/source/slang/legalize-types.cpp @@ -1,6 +1,8 @@ // legalize-types.cpp #include "legalize-types.h" +#include "mangle.h" + namespace Slang { @@ -335,7 +337,9 @@ struct TupleTypeBuilder ordinaryStructDecl->loc = typeDeclRef.getDecl()->loc; ordinaryStructDecl->nameAndLoc = typeDeclRef.getDecl()->nameAndLoc; - addModifier(ordinaryStructDecl, new LegalizedModifier()); + auto typeLegalizedModifier = new LegalizedModifier(); + typeLegalizedModifier->originalMangledName = getMangledName(typeDeclRef); + addModifier(ordinaryStructDecl, typeLegalizedModifier); // We will do something a bit unsavory here, by setting the logical // parent of the new `struct` type to be the same as the orignal type @@ -408,7 +412,9 @@ struct TupleTypeBuilder pairElements[elementIndex].ordinaryFieldDeclRef = makeDeclRef(fieldDecl.Ptr()); - addModifier(fieldDecl, new LegalizedModifier()); + auto fieldLegalizedModifier = new LegalizedModifier(); + fieldLegalizedModifier->originalMangledName = getMangledName(ee.fieldDeclRef); + addModifier(fieldDecl, fieldLegalizedModifier); } RefPtr<Type> ordinaryStructType = DeclRefType::Create( diff --git a/source/slang/mangle.cpp b/source/slang/mangle.cpp index 29446d942..f2bf279a2 100644 --- a/source/slang/mangle.cpp +++ b/source/slang/mangle.cpp @@ -373,6 +373,13 @@ namespace Slang String getMangledName(DeclRef<Decl> const& declRef) { + // Special case: if a declaration is the result of a type legalization + // transformation, then it should just get the mangled name of the + // original declaration, and not the one that would be computed + // for it otherwise. + if(auto legalizedModifier = declRef.getDecl()->FindModifier<LegalizedModifier>()) + return legalizedModifier->originalMangledName; + ManglingContext context; mangleName(&context, declRef); return context.sb.ProduceString(); diff --git a/source/slang/modifier-defs.h b/source/slang/modifier-defs.h index 124dd2882..3750f3373 100644 --- a/source/slang/modifier-defs.h +++ b/source/slang/modifier-defs.h @@ -343,5 +343,7 @@ END_SYNTAX_CLASS() // A marker modifier used to indicate that a declaration was created as // part of type legalization. -SIMPLE_SYNTAX_CLASS(LegalizedModifier, Modifier) +SYNTAX_CLASS(LegalizedModifier, Modifier) + FIELD(String, originalMangledName) +END_SYNTAX_CLASS() diff --git a/source/slang/syntax.cpp b/source/slang/syntax.cpp index 3bccf51ce..0428246db 100644 --- a/source/slang/syntax.cpp +++ b/source/slang/syntax.cpp @@ -433,7 +433,7 @@ void Type::accept(IValVisitor* visitor, void* extra) String DeclRefType::ToString() { - return getText(declRef.GetName()); + return declRef.toString(); } int DeclRefType::GetHashCode() |
