diff options
| author | Yong He <yonghe@outlook.com> | 2022-05-10 19:42:48 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-05-10 19:42:48 -0700 |
| commit | 765061a77bcf4fe6300721263cc9e0f25595488d (patch) | |
| tree | 5fe52269a46d8db85a869784f8637022f154c20f /source | |
| parent | dc541cc10783de541d8341b5fccee4c6019b5c6e (diff) | |
Initial support for COM interface in host code. (#2230)
Co-authored-by: Yong He <yhe@nvidia.com>
Co-authored-by: Theresa Foley <10618364+tangent-vector@users.noreply.github.com>
Diffstat (limited to 'source')
25 files changed, 328 insertions, 7 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang index de83eac73..9a09196c5 100644 --- a/source/slang/core.meta.slang +++ b/source/slang/core.meta.slang @@ -2174,6 +2174,8 @@ attribute_syntax [__unsafeForceInlineEarly] : UnsafeForceInlineEarlyAttribute; __attributeTarget(FuncDecl) attribute_syntax [DllImport(modulePath: String)] : DllImportAttribute; +__attributeTarget(InterfaceDecl) +attribute_syntax [COM] : ComInterfaceAttribute; // Inheritance Control __attributeTarget(AggTypeDecl) diff --git a/source/slang/slang-ast-modifier.h b/source/slang/slang-ast-modifier.h index 8654a2391..a8185e06e 100644 --- a/source/slang/slang-ast-modifier.h +++ b/source/slang/slang-ast-modifier.h @@ -932,6 +932,12 @@ class DllImportAttribute : public Attribute String modulePath; }; + /// An attribute that marks an interface type as a COM interface declaration. +class ComInterfaceAttribute : public Attribute +{ + SLANG_AST_CLASS(ComInterfaceAttribute) +}; + /// A `[__requiresNVAPI]` attribute indicates that the declaration being modifed /// requires NVAPI operations for its implementation on D3D. class RequiresNVAPIAttribute : public Attribute diff --git a/source/slang/slang-check-decl.cpp b/source/slang/slang-check-decl.cpp index 3c654a48b..6c414b292 100644 --- a/source/slang/slang-check-decl.cpp +++ b/source/slang/slang-check-decl.cpp @@ -3232,6 +3232,16 @@ namespace Slang _validateCrossModuleInheritance(decl, inheritanceDecl); } + + if (decl->findModifier<ComInterfaceAttribute>()) + { + // `associatedtype` declaration is not allowed in a COM interface declaration. + for (auto associatedType : decl->getMembersOfType<AssocTypeDecl>()) + { + getSink()->diagnose( + associatedType, Diagnostics::associatedTypeNotAllowInComInterface); + } + } } void SemanticsDeclBasesVisitor::visitStructDecl(StructDecl* decl) diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h index 559323696..57035e84e 100644 --- a/source/slang/slang-diagnostic-defs.h +++ b/source/slang/slang-diagnostic-defs.h @@ -310,6 +310,9 @@ DIAGNOSTIC(31102, Error, nonPositiveNumThreads, "expected a positive integer in DIAGNOSTIC(31120, Error, invalidAttributeTarget, "invalid syntax target for user defined attribute") DIAGNOSTIC(31121, Error, anyValueSizeExceedsLimit, "'anyValueSize' cannot exceed $0") + +DIAGNOSTIC(31122, Error, associatedTypeNotAllowInComInterface, "associatedtype not allowed in a [COM] interface") + // Enums DIAGNOSTIC(32000, Error, invalidEnumTagType, "invalid tag type for 'enum': '$0'") diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp index 6b8939d85..a6edc0a1f 100644 --- a/source/slang/slang-emit-c-like.cpp +++ b/source/slang/slang-emit-c-like.cpp @@ -1506,12 +1506,12 @@ void CLikeSourceEmitter::emitIntrinsicCallExprImpl( } } -void CLikeSourceEmitter::_emitCallArgList(IRCall* inst) +void CLikeSourceEmitter::_emitCallArgList(IRCall* inst, int startingOperandIndex) { bool isFirstArg = true; m_writer->emit("("); UInt argCount = inst->getOperandCount(); - for (UInt aa = 1; aa < argCount; ++aa) + for (UInt aa = startingOperandIndex; aa < argCount; ++aa) { auto operand = inst->getOperand(aa); if (as<IRVoidType>(operand->getDataType())) @@ -1531,6 +1531,22 @@ void CLikeSourceEmitter::_emitCallArgList(IRCall* inst) m_writer->emit(")"); } +void CLikeSourceEmitter::emitComInterfaceCallExpr(IRCall* inst, EmitOpInfo const& inOuterPrec) +{ + auto funcValue = inst->getOperand(0); + auto object = funcValue->getOperand(0); + auto methodKey = funcValue->getOperand(1); + auto prec = getInfo(EmitOp::Postfix); + + auto outerPrec = inOuterPrec; + bool needClose = maybeEmitParens(outerPrec, prec); + emitOperand(object, leftSide(outerPrec, prec)); + m_writer->emit("->"); + m_writer->emit(getName(methodKey)); + _emitCallArgList(inst, 2); + maybeCloseParens(needClose); +} + void CLikeSourceEmitter::emitCallExpr(IRCall* inst, EmitOpInfo outerPrec) { auto funcValue = inst->getOperand(0); @@ -1538,6 +1554,14 @@ void CLikeSourceEmitter::emitCallExpr(IRCall* inst, EmitOpInfo outerPrec) // Does this function declare any requirements. handleRequiredCapabilities(funcValue); + // Detect if this is a call into a COM interface method. + if (funcValue->getOp() == kIROp_lookup_interface_method && + funcValue->getOperand(0)->getDataType()->getOp() == kIROp_ComPtrType) + { + emitComInterfaceCallExpr(inst, outerPrec); + return; + } + // We want to detect any call to an intrinsic operation, // that we can emit it directly without mangling, etc. if(auto targetIntrinsic = findBestTargetIntrinsicDecoration(funcValue)) diff --git a/source/slang/slang-emit-c-like.h b/source/slang/slang-emit-c-like.h index 109731566..51e54611e 100644 --- a/source/slang/slang-emit-c-like.h +++ b/source/slang/slang-emit-c-like.h @@ -302,6 +302,8 @@ public: // to the new name with the arguments of the old operation. static bool isOrdinaryName(const UnownedStringSlice& name); + void emitComInterfaceCallExpr(IRCall* inst, EmitOpInfo const& inOuterPrec); + void emitIntrinsicCallExpr( IRCall* inst, IRTargetIntrinsicDecoration* targetIntrinsic, @@ -485,7 +487,7 @@ public: virtual void _emitPostfixTypeAttr(IRAttr* attr); // Emit the argument list (including paranthesis) in a `CallInst` - void _emitCallArgList(IRCall* call); + void _emitCallArgList(IRCall* call, int startingOperandIndex = 1); String _generateUniqueName(const UnownedStringSlice& slice); diff --git a/source/slang/slang-emit-cpp.cpp b/source/slang/slang-emit-cpp.cpp index 37b8bfbce..81d32c297 100644 --- a/source/slang/slang-emit-cpp.cpp +++ b/source/slang/slang-emit-cpp.cpp @@ -537,6 +537,15 @@ SlangResult CPPSourceEmitter::calcTypeName(IRType* type, CodeGenTarget target, S out << "String"; return SLANG_OK; } + case kIROp_ComPtrType: + { + out << "ComPtr<"; + auto comPtrType = static_cast<IRComPtrType*>(type); + auto baseType = cast<IRType>(comPtrType->getOperand(0)); + SLANG_RETURN_ON_FAIL(calcTypeName(baseType, target, out)); + out << ">"; + return SLANG_OK; + } default: { if (isNominalOp(type->getOp())) @@ -1712,12 +1721,77 @@ void CPPSourceEmitter::_emitWitnessTableDefinitions() } } +void CPPSourceEmitter::emitComInterface(IRInterfaceType* interfaceType) +{ + m_writer->emit("struct "); + emitSimpleType(interfaceType); + m_writer->emit(" : "); + // Emit base types. + bool isFirst = true; + for (UInt i = 0; i < interfaceType->getOperandCount(); i++) + { + auto entry = as<IRInterfaceRequirementEntry>(interfaceType->getOperand(i)); + if (auto witnessTableType = as<IRWitnessTableType>(entry->getRequirementVal())) + { + if (isFirst) + { + isFirst = false; + } + else + { + m_writer->emit(", "); + } + emitType((IRType*)witnessTableType->getConformanceType()); + } + } + if (isFirst) + { + m_writer->emit("ISlangUnknown"); + } + + // Emit methods. + m_writer->emit("\n{\n"); + m_writer->indent(); + for (UInt i = 0; i < interfaceType->getOperandCount(); i++) + { + auto entry = as<IRInterfaceRequirementEntry>(interfaceType->getOperand(i)); + if (auto funcVal = as<IRFuncType>(entry->getRequirementVal())) + { + m_writer->emit("virtual SLANG_NO_THROW "); + emitType(funcVal->getResultType()); + m_writer->emit(" SLANG_MCALL "); + m_writer->emit(getName(entry->getRequirementKey())); + m_writer->emit("("); + bool isFirstParam = true; + for (UInt p = 1; p < funcVal->getParamCount(); p++) + { + auto paramType = funcVal->getParamType(p); + if (!isFirstParam) + m_writer->emit(", "); + else + isFirstParam = false; + + emitParamType(paramType, String("param") + String(p)); + } + m_writer->emit(") = 0;\n"); + } + } + m_writer->dedent(); + m_writer->emit("};\n"); +} + void CPPSourceEmitter::emitInterface(IRInterfaceType* interfaceType) { // Skip built-in interfaces. if (isBuiltin(interfaceType)) return; + if (interfaceType->findDecoration<IRComInterfaceDecoration>()) + { + emitComInterface(interfaceType); + return; + } + m_writer->emit("struct "); emitSimpleType(interfaceType); m_writer->emit("\n{\n"); diff --git a/source/slang/slang-emit-cpp.h b/source/slang/slang-emit-cpp.h index a75fe2caf..dc9f78df2 100644 --- a/source/slang/slang-emit-cpp.h +++ b/source/slang/slang-emit-cpp.h @@ -69,10 +69,10 @@ protected: virtual void emitGlobalRTTISymbolPrefix(); virtual void emitWitnessTable(IRWitnessTable* witnessTable) SLANG_OVERRIDE; virtual void emitInterface(IRInterfaceType* interfaceType) SLANG_OVERRIDE; + void emitComInterface(IRInterfaceType* interfaceType); virtual void emitRTTIObject(IRRTTIObject* rttiObject) SLANG_OVERRIDE; virtual bool tryEmitGlobalParamImpl(IRGlobalParam* varDecl, IRType* varType) SLANG_OVERRIDE; virtual void emitIntrinsicCallExprImpl(IRCall* inst, IRTargetIntrinsicDecoration* targetIntrinsic, EmitOpInfo const& inOuterPrec) SLANG_OVERRIDE; - virtual void emitLoopControlDecorationImpl(IRLoopControlDecoration* decl) SLANG_OVERRIDE; virtual const UnownedStringSlice* getVectorElementNames(BaseType elemType, Index elemCount); diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp index 0539f9d1d..dd176d859 100644 --- a/source/slang/slang-emit.cpp +++ b/source/slang/slang-emit.cpp @@ -20,6 +20,7 @@ #include "slang-ir-inline.h" #include "slang-ir-legalize-varying-params.h" #include "slang-ir-link.h" +#include "slang-ir-com-interface.h" #include "slang-ir-lower-generics.h" #include "slang-ir-lower-tuple-types.h" #include "slang-ir-lower-bit-cast.h" @@ -692,6 +693,7 @@ Result linkAndOptimizeIR( default: break; case CodeGenTarget::HostCPPSource: + lowerComInterfaces(irModule, sink); generateDllImportFuncs(irModule, sink); break; } diff --git a/source/slang/slang-ir-com-interface.cpp b/source/slang/slang-ir-com-interface.cpp new file mode 100644 index 000000000..1bcf3d2b6 --- /dev/null +++ b/source/slang/slang-ir-com-interface.cpp @@ -0,0 +1,98 @@ +// slang-ir-com-interface.cpp +#include "slang-ir-com-interface.h" + +#include "slang-ir.h" +#include "slang-ir-insts.h" + +namespace Slang +{ + +struct ComInterfaceLoweringContext +{ + IRModule* module; + DiagnosticSink* diagnosticSink; + + SharedIRBuilder sharedBuilder; + + Dictionary<IRInterfaceType*, IRComPtrType*> comPtrTypes; + + void replaceTypeUses(IRInst* inst, IRInst* newValue) + { + List<IRUse*> uses; + for (auto use = inst->firstUse; use; use = use->nextUse) + { + uses.add(use); + } + for (auto use : uses) + { + switch (use->getUser()->getOp()) + { + case kIROp_WitnessTableIDType: + case kIROp_WitnessTableType: + case kIROp_ThisType: + case kIROp_RTTIPointerType: + case kIROp_RTTIHandleType: + case kIROp_ComPtrType: + continue; + default: + break; + } + use->set(newValue); + } + } + + IRComPtrType* processInterfaceType(IRInterfaceType* type) + { + if (!type->findDecoration<IRComInterfaceDecoration>()) + return nullptr; + + IRComPtrType* result = nullptr; + + if (comPtrTypes.TryGetValue(type, result)) + return result; + + IRBuilder builder(sharedBuilder); + builder.setInsertInto(module->getModuleInst()); + result = builder.getComPtrType(type); + + replaceTypeUses(type, result); + return result; + } + + void processThisType(IRThisType* type) + { + auto comPtrType = processInterfaceType(as<IRInterfaceType>(type->getConstraintType())); + if (!comPtrType) + return; + replaceTypeUses(type, comPtrType); + } + + void processModule() + { + for (auto child : module->getGlobalInsts()) + { + switch (child->getOp()) + { + case kIROp_InterfaceType: + processInterfaceType(as<IRInterfaceType>(child)); + break; + case kIROp_ThisType: + processThisType(as<IRThisType>(child)); + break; + default: + break; + } + } + } +}; + +void lowerComInterfaces(IRModule* module, DiagnosticSink* sink) +{ + ComInterfaceLoweringContext context; + context.module = module; + context.diagnosticSink = sink; + context.sharedBuilder.init(module); + return context.processModule(); +} + +} diff --git a/source/slang/slang-ir-com-interface.h b/source/slang/slang-ir-com-interface.h new file mode 100644 index 000000000..0f6737880 --- /dev/null +++ b/source/slang/slang-ir-com-interface.h @@ -0,0 +1,15 @@ +// slang-ir-com-interface.cpp +#pragma once + +namespace Slang +{ + +struct IRModule; +class DiagnosticSink; + +/// Lower com interface types. +/// A use of `IRInterfaceType` with `IRComInterfaceDecoration` will be translated into a `IRComPtr` type. +/// A use of `IRThisType` with a COM interface will also be translated into a `IRComPtr` type. +void lowerComInterfaces(IRModule* module, DiagnosticSink* sink); + +} diff --git a/source/slang/slang-ir-dll-import.cpp b/source/slang/slang-ir-dll-import.cpp index ed0a3e007..02743cba4 100644 --- a/source/slang/slang-ir-dll-import.cpp +++ b/source/slang/slang-ir-dll-import.cpp @@ -216,6 +216,10 @@ struct DllImportContext { builder.emitReturn(call); } + else + { + builder.emitReturn(); + } } void processModule() diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp index 4fb4e007b..284e1fa11 100644 --- a/source/slang/slang-ir-generics-lowering-context.cpp +++ b/source/slang/slang-ir-generics-lowering-context.cpp @@ -170,9 +170,14 @@ namespace Slang } case kIROp_ThisType: { + auto interfaceType = cast<IRThisType>(paramType)->getConstraintType(); - if (isBuiltin(cast<IRThisType>(paramType)->getConstraintType())) + if (isBuiltin(interfaceType)) return (IRType*)paramType; + + if (interfaceType->findDecoration<IRComInterfaceDecoration>()) + return (IRType*)interfaceType; + auto anyValueSize = getInterfaceAnyValueSize( cast<IRThisType>(paramType)->getConstraintType(), paramType->sourceLoc); @@ -187,6 +192,9 @@ namespace Slang if (isBuiltin(paramType)) return (IRType*)paramType; + if (paramType->findDecoration<IRComInterfaceDecoration>()) + return (IRType*)paramType; + // In the dynamic-dispatch case, a value of interface type // is going to be packed into the "any value" part of a tuple. // The size of the "any value" part depends on the interface diff --git a/source/slang/slang-ir-inst-defs.h b/source/slang/slang-ir-inst-defs.h index 267f9ab43..f9e0a5f34 100644 --- a/source/slang/slang-ir-inst-defs.h +++ b/source/slang/slang-ir-inst-defs.h @@ -105,6 +105,9 @@ INST(Nop, nop, 0, 0) INST_RANGE(OutTypeBase, OutType, InOutType) INST_RANGE(PtrTypeBase, PtrType, InOutType) + // A ComPtr<T> type is treated as a opaque type that represents a reference-counted handle to a COM object. + INST(ComPtrType, ComPtr, 1, 0) + /* SamplerStateTypeBase */ INST(SamplerStateType, SamplerState, 0, 0) INST(SamplerComparisonStateType, SamplerComparisonState, 0, 0) @@ -609,6 +612,8 @@ INST(HighLevelDeclDecoration, highLevelDecl, 1, 0) /// An dllImport decoration marks a function as imported from a DLL. Slang will generate dynamic function loading logic to use this function at runtime. INST(DllImportDecoration, dllImport, 2, 0) + /// Marks an interface as a COM interface declaration. + INST(ComInterfaceDecoration, COMInterface, 0, 0) /* Decorations for RTTI objects */ INST(RTTITypeSizeDecoration, RTTI_typeSize, 1, 0) diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index 3fc71b195..0e54802e5 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -177,6 +177,15 @@ struct IRAnyValueSizeDecoration : IRDecoration } }; +struct IRComInterfaceDecoration : IRDecoration +{ + enum + { + kOp = kIROp_ComInterfaceDecoration + }; + IR_LEAF_ISA(ComInterfaceDecoration) +}; + /// A decoration on `IRParam`s that represent generic parameters, /// marking the interface type that the generic parameter conforms to. /// A generic parameter can have more than one `IRTypeConstraintDecoration`s @@ -2110,6 +2119,8 @@ public: IRPtrTypeBase* getPtrType(IROp op, IRType* valueType); IRPtrType* getPtrType(IROp op, IRType* valueType, IRIntegerValue addressSpace); + IRComPtrType* getComPtrType(IRType* valueType); + /// Get a 'SPIRV literal' IRSPIRVLiteralType* getSPIRVLiteralType(IRType* type); @@ -2929,6 +2940,11 @@ public: addDecoration(inst, kIROp_AnyValueSizeDecoration, getIntValue(getIntType(), value)); } + void addComInterfaceDecoration(IRInst* inst) + { + addDecoration(inst, kIROp_ComInterfaceDecoration); + } + void addTypeConstraintDecoration(IRInst* inst, IRInst* constraintType) { addDecoration(inst, kIROp_TypeConstraintDecoration, constraintType); diff --git a/source/slang/slang-ir-link.cpp b/source/slang/slang-ir-link.cpp index 80ba0b610..b67d95abf 100644 --- a/source/slang/slang-ir-link.cpp +++ b/source/slang/slang-ir-link.cpp @@ -618,12 +618,14 @@ IRInterfaceType* cloneInterfaceTypeImpl( IROriginalValuesForClone const& originalValues) { auto clonedInterface = builder->createInterfaceType(originalInterface->getOperandCount(), nullptr); + registerClonedValue(context, clonedInterface, originalValues); + for (UInt i = 0; i < originalInterface->getOperandCount(); i++) { auto clonedKey = cloneValue(context, originalInterface->getOperand(i)); clonedInterface->setOperand(i, clonedKey); } - cloneSimpleGlobalValueImpl(context, originalInterface, originalValues, clonedInterface); + cloneSimpleGlobalValueImpl(context, originalInterface, originalValues, clonedInterface, false); return clonedInterface; } diff --git a/source/slang/slang-ir-lower-existential.cpp b/source/slang/slang-ir-lower-existential.cpp index ab948bc7a..dfa714a82 100644 --- a/source/slang/slang-ir-lower-existential.cpp +++ b/source/slang/slang-ir-lower-existential.cpp @@ -105,7 +105,16 @@ namespace Slang auto builder = &builderStorage; builder->setInsertBefore(extractInst); - auto element = extractTupleElement(builder, extractInst->getOperand(0), elementId); + IRInst* element = nullptr; + if (extractInst->getOperand(0)->getDataType()->findDecoration<IRComInterfaceDecoration>()) + { + // If this is an COM interface, the elements (witness table/rtti) are just the interface value itself. + element = extractInst->getOperand(0); + } + else + { + element = extractTupleElement(builder, extractInst->getOperand(0), elementId); + } extractInst->replaceUsesWith(element); extractInst->removeAndDeallocate(); } diff --git a/source/slang/slang-ir-lower-generic-call.cpp b/source/slang/slang-ir-lower-generic-call.cpp index 094baaca1..da9f54764 100644 --- a/source/slang/slang-ir-lower-generic-call.cpp +++ b/source/slang/slang-ir-lower-generic-call.cpp @@ -274,6 +274,15 @@ namespace Slang { // If we see a call(lookup_interface_method(...), ...), we need to translate // all occurences of associatedtypes. + + // If `w` in `lookup_interface_method(w, ...)` is a COM interface, bail. + if (lookupInst->getWitnessTable() + ->getDataType() + ->findDecoration<IRComInterfaceDecoration>()) + { + return; + } + auto interfaceType = cast<IRInterfaceType>( cast<IRWitnessTableTypeBase>(lookupInst->getWitnessTable()->getDataType()) ->getConformanceType()); diff --git a/source/slang/slang-ir-lower-generic-function.cpp b/source/slang/slang-ir-lower-generic-function.cpp index 0bfc62fdb..600f21b20 100644 --- a/source/slang/slang-ir-lower-generic-function.cpp +++ b/source/slang/slang-ir-lower-generic-function.cpp @@ -152,6 +152,10 @@ namespace Slang // Do not lower intrinsic interfaces. if (isBuiltin(interfaceType)) return interfaceType; + // Do not lower COM interfaces. + if (interfaceType->findDecoration<IRComInterfaceDecoration>()) + return interfaceType; + List<IRInterfaceRequirementEntry*> newEntries; IRBuilder builder(sharedContext->sharedBuilderStorage); diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp index ea45ecfff..5d8e6d929 100644 --- a/source/slang/slang-ir-lower-generics.cpp +++ b/source/slang/slang-ir-lower-generics.cpp @@ -80,6 +80,9 @@ namespace Slang { if (inst->getOp() == kIROp_InterfaceType) { + if (inst->findDecoration<IRComInterfaceDecoration>()) + continue; + interfaceInsts.add(inst); } } @@ -134,6 +137,8 @@ namespace Slang { auto witnessTableType = lookupWitnessMethod->getWitnessTable()->getDataType(); auto interfaceType = cast<IRWitnessTableType>(witnessTableType)->getConformanceType(); + if (interfaceType->findDecoration<IRComInterfaceDecoration>()) + return; if (!implementedInterfaces.Contains(interfaceType)) { context->sink->diagnose(interfaceType->sourceLoc, Diagnostics::noTypeConformancesFoundForInterface, interfaceType); diff --git a/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp b/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp index d37ac4fd2..6c6a7dec5 100644 --- a/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp +++ b/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp @@ -119,6 +119,11 @@ struct AssociatedTypeLookupSpecializationContext void processLookupInterfaceMethodInst(IRLookupWitnessMethod* inst) { + if (inst->getWitnessTable()->getDataType()->findDecoration<IRComInterfaceDecoration>()) + { + return; + } + // Ignore lookups for RTTI objects for now, since they are not used anywhere. if (!as<IRWitnessTableType>(inst->getDataType())) { diff --git a/source/slang/slang-ir-witness-table-wrapper.cpp b/source/slang/slang-ir-witness-table-wrapper.cpp index 751c4bc21..c8a1e2dbe 100644 --- a/source/slang/slang-ir-witness-table-wrapper.cpp +++ b/source/slang/slang-ir-witness-table-wrapper.cpp @@ -170,6 +170,8 @@ namespace Slang auto interfaceType = cast<IRInterfaceType>(witnessTable->getConformanceType()); if (isBuiltin(interfaceType)) return; + if (interfaceType->findDecoration<IRComInterfaceDecoration>()) + return; // We need to consider whether the concrete type that is conforming // in this witness table actually fits within the declared any-value diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 84af6459e..f4add4efc 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -2637,6 +2637,11 @@ namespace Slang return (IRPtrType*)getType(op, 2, operands); } + IRComPtrType* IRBuilder::getComPtrType(IRType* valueType) + { + return (IRComPtrType*)getType(kIROp_ComPtrType, valueType); + } + IRArrayTypeBase* IRBuilder::getArrayTypeBase( IROp op, IRType* elementType, diff --git a/source/slang/slang-ir.h b/source/slang/slang-ir.h index c125e7d2c..7a1a0b8aa 100644 --- a/source/slang/slang-ir.h +++ b/source/slang/slang-ir.h @@ -1287,6 +1287,8 @@ SIMPLE_IR_PARENT_TYPE(OutTypeBase, PtrTypeBase) SIMPLE_IR_TYPE(OutType, OutTypeBase) SIMPLE_IR_TYPE(InOutType, OutTypeBase) +SIMPLE_IR_TYPE(ComPtrType, Type) + struct IRPseudoPtrType : public IRPtrTypeBase { IR_LEAF_ISA(PseudoPtrType); diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 9fec8f839..585b02a02 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -1056,6 +1056,11 @@ static void addLinkageDecoration( { builder->addExternCppDecoration(inst, mangledName); } + if (as<InterfaceDecl>(decl->parentDecl) && + decl->parentDecl->hasModifier<ComInterfaceAttribute>()) + { + builder->addExternCppDecoration(inst, decl->getName()->text.getUnownedSlice()); + } if (auto dllImportModifier = decl->findModifier<DllImportAttribute>()) { auto libraryName = dllImportModifier->modulePath; @@ -6285,6 +6290,10 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo> { subBuilder->addAnyValueSizeDecoration(irInterface, anyValueSizeAttr->size); } + if (auto comInterfaceAttr = decl->findModifier<ComInterfaceAttribute>()) + { + subBuilder->addComInterfaceDecoration(irInterface); + } if (auto builtinAttr = decl->findModifier<BuiltinAttribute>()) { subBuilder->addBuiltinDecoration(irInterface); |
