From b8702dfb6d0e41515fa0f9f899d86b7935dfc3fd Mon Sep 17 00:00:00 2001 From: Yong He Date: Tue, 25 Aug 2020 21:55:05 -0700 Subject: Export witness table and RTTI objects in compiled libraries. (#1514) * Export witness table objects in compiled code. - Ensure that witness tables are preceeded with `extern "C"` modifier in the generated C++ code. - RTTI objects use the mangled name of the type directly, so that can be queried using the type's mangled name directly from the resulting DLL. - Expose `Linkage::getTypeConformanceWitnessMangledName` to return the mangled name of witness tables to the host. - Ensure that all witness tables (including those for associated types) have proper mangled name. * Fix GCC error in Slang generated code. --- source/slang/slang-ast-support-types.h | 3 +++ source/slang/slang-check-decl.cpp | 2 ++ source/slang/slang-compiler.h | 4 ++++ source/slang/slang-emit-cpp.cpp | 10 ++++++++-- source/slang/slang-ir-generics-lowering-context.cpp | 2 +- source/slang/slang-lower-to-ir.cpp | 6 +++++- source/slang/slang.cpp | 11 +++++++++++ 7 files changed, 34 insertions(+), 4 deletions(-) (limited to 'source') diff --git a/source/slang/slang-ast-support-types.h b/source/slang/slang-ast-support-types.h index b8923643c..f667c5fc3 100644 --- a/source/slang/slang-ast-support-types.h +++ b/source/slang/slang-ast-support-types.h @@ -1318,6 +1318,9 @@ namespace Slang // The type that the witness table witnesses conformance to (e.g. an Interface) Type* baseType; + + // The type witnessesd by the witness table (a concrete type). + Type* witnessedType; }; typedef Dictionary AttributeArgumentValueDict; diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index f9a514d23..4fa5fff17 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -2450,6 +2450,7 @@ namespace Slang { witnessTable = new WitnessTable(); witnessTable->baseType = DeclRefType::create(m_astBuilder, interfaceDeclRef); + witnessTable->witnessedType = type; } context->mapInterfaceToWitnessTable.Add(interfaceDeclRef, witnessTable); @@ -3021,6 +3022,7 @@ namespace Slang // RefPtr witnessTable = new WitnessTable(); witnessTable->baseType = enumConformanceDecl->base.type; + witnessTable->witnessedType = enumTypeType; enumConformanceDecl->witnessTable = witnessTable; Name* tagAssociatedTypeName = getSession()->getNameObj("__Tag"); diff --git a/source/slang/slang-compiler.h b/source/slang/slang-compiler.h index 8996f5512..ac22270f8 100755 --- a/source/slang/slang-compiler.h +++ b/source/slang/slang-compiler.h @@ -1205,6 +1205,10 @@ namespace Slang SlangInt targetIndex = 0, slang::LayoutRules rules = slang::LayoutRules::Default, ISlangBlob** outDiagnostics = nullptr) override; + SLANG_NO_THROW SlangResult SLANG_MCALL getTypeConformanceWitnessMangledName( + slang::TypeReflection* type, + slang::TypeReflection* interfaceType, + ISlangBlob** outNameBlob) override; SLANG_NO_THROW SlangResult SLANG_MCALL createCompileRequest( SlangCompileRequest** outCompileRequest) override; diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index 0c2b4cd93..e7c90f657 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -1611,7 +1611,7 @@ void CPPSourceEmitter::emitWitnessTable(IRWitnessTable* witnessTable) _maybeEmitWitnessTableTypeDefinition(interfaceType); // Define a global variable for the witness table. - m_writer->emit("extern "); + m_writer->emit("extern \"C\" "); emitSimpleType(interfaceType); m_writer->emit(" "); m_writer->emit(getName(witnessTable)); @@ -1692,7 +1692,13 @@ void CPPSourceEmitter::emitInterface(IRInterfaceType* interfaceType) void CPPSourceEmitter::emitRTTIObject(IRRTTIObject* rttiObject) { - m_writer->emit("static TypeInfo "); + // Declare the type info object as `extern "C"` first. + m_writer->emit("extern \"C\" TypeInfo "); + m_writer->emit(getName(rttiObject)); + m_writer->emit(";\n"); + + // Now actually define the object. + m_writer->emit("TypeInfo "); m_writer->emit(getName(rttiObject)); m_writer->emit(" = {"); auto typeSizeDecoration = rttiObject->findDecoration(); diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp index 67f376153..317532e8c 100644 --- a/source/slang/slang-ir-generics-lowering-context.cpp +++ b/source/slang/slang-ir-generics-lowering-context.cpp @@ -72,7 +72,7 @@ namespace Slang // Give a name to the rtti object. if (auto exportDecoration = typeInst->findDecoration()) { - String rttiObjName = String(exportDecoration->getMangledName()) + "_rtti"; + String rttiObjName = exportDecoration->getMangledName(); builder->addExportDecoration(result, rttiObjName.getUnownedSlice()); } mapTypeToRTTIObject[typeInst] = result; diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index f87b6bd69..f756cf28a 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -5170,7 +5170,11 @@ struct DeclLoweringVisitor : DeclVisitor // Need to construct a sub-witness-table auto irWitnessTableBaseType = lowerType(subContext, astReqWitnessTable->baseType); irSatisfyingWitnessTable = subBuilder->createWitnessTable(irWitnessTableBaseType); - + auto mangledName = getMangledNameForConformanceWitness( + subContext->astBuilder, + astReqWitnessTable->witnessedType, + astReqWitnessTable->baseType); + subBuilder->addExportDecoration(irSatisfyingWitnessTable, mangledName.getUnownedSlice()); // Recursively lower the sub-table. lowerWitnessTable( subContext, diff --git a/source/slang/slang.cpp b/source/slang/slang.cpp index 6bffa0f65..074c71f21 100644 --- a/source/slang/slang.cpp +++ b/source/slang/slang.cpp @@ -623,6 +623,17 @@ SLANG_NO_THROW slang::TypeLayoutReflection* SLANG_MCALL Linkage::getTypeLayout( return asExternal(typeLayout); } +SLANG_NO_THROW SlangResult SLANG_MCALL Linkage::getTypeConformanceWitnessMangledName( + slang::TypeReflection* type, slang::TypeReflection* interfaceType, ISlangBlob** outNameBlob) +{ + auto subType = asInternal(type); + auto supType = asInternal(interfaceType); + auto name = getMangledNameForConformanceWitness(subType->getASTBuilder(), subType, supType); + Slang::ComPtr blob = Slang::StringUtil::createStringBlob(name); + *outNameBlob = blob.detach(); + return SLANG_OK; +} + SLANG_NO_THROW SlangResult SLANG_MCALL Linkage::createCompileRequest( SlangCompileRequest** outCompileRequest) { -- cgit v1.2.3