summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang2
-rw-r--r--source/slang/slang-ast-modifier.h6
-rw-r--r--source/slang/slang-check-decl.cpp10
-rw-r--r--source/slang/slang-diagnostic-defs.h3
-rw-r--r--source/slang/slang-emit-c-like.cpp28
-rw-r--r--source/slang/slang-emit-c-like.h4
-rw-r--r--source/slang/slang-emit-cpp.cpp74
-rw-r--r--source/slang/slang-emit-cpp.h2
-rw-r--r--source/slang/slang-emit.cpp2
-rw-r--r--source/slang/slang-ir-com-interface.cpp98
-rw-r--r--source/slang/slang-ir-com-interface.h15
-rw-r--r--source/slang/slang-ir-dll-import.cpp4
-rw-r--r--source/slang/slang-ir-generics-lowering-context.cpp10
-rw-r--r--source/slang/slang-ir-inst-defs.h5
-rw-r--r--source/slang/slang-ir-insts.h16
-rw-r--r--source/slang/slang-ir-link.cpp4
-rw-r--r--source/slang/slang-ir-lower-existential.cpp11
-rw-r--r--source/slang/slang-ir-lower-generic-call.cpp9
-rw-r--r--source/slang/slang-ir-lower-generic-function.cpp4
-rw-r--r--source/slang/slang-ir-lower-generics.cpp5
-rw-r--r--source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp5
-rw-r--r--source/slang/slang-ir-witness-table-wrapper.cpp2
-rw-r--r--source/slang/slang-ir.cpp5
-rw-r--r--source/slang/slang-ir.h2
-rw-r--r--source/slang/slang-lower-to-ir.cpp9
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);