summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2022-08-22 14:17:56 -0700
committerGitHub <noreply@github.com>2022-08-22 14:17:56 -0700
commit4bd3e6e02324f913e8927fe69d32c0aafe9fc831 (patch)
tree1f6ff8449feb49d00dee2bc527f7dc531a07c196 /source
parent393185196ed65a9eeaf9502edbf3dcce87337d81 (diff)
Make Optional<PointerType> lower to PointerType instead of a struct. (#2373)
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-check-type.cpp36
-rw-r--r--source/slang/slang-diagnostic-defs.h4
-rw-r--r--source/slang/slang-emit.cpp36
-rw-r--r--source/slang/slang-ir-generics-lowering-context.cpp19
-rw-r--r--source/slang/slang-ir-generics-lowering-context.h2
-rw-r--r--source/slang/slang-ir-insts.h2
-rw-r--r--source/slang/slang-ir-lower-existential.cpp1
-rw-r--r--source/slang/slang-ir-lower-generic-call.cpp1
-rw-r--r--source/slang/slang-ir-lower-generic-function.cpp1
-rw-r--r--source/slang/slang-ir-lower-generics.cpp1
-rw-r--r--source/slang/slang-ir-lower-optional-type.cpp95
-rw-r--r--source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp1
-rw-r--r--source/slang/slang-ir-util.cpp21
-rw-r--r--source/slang/slang-ir-util.h2
-rw-r--r--source/slang/slang-ir-witness-table-wrapper.cpp1
-rw-r--r--source/slang/slang-ir.cpp11
16 files changed, 159 insertions, 75 deletions
diff --git a/source/slang/slang-check-type.cpp b/source/slang/slang-check-type.cpp
index aa2c69126..c59e1b308 100644
--- a/source/slang/slang-check-type.cpp
+++ b/source/slang/slang-check-type.cpp
@@ -187,15 +187,27 @@ namespace Slang
return DeclRefType::create(m_astBuilder, innerDeclRef);
}
+ bool isManagedType(Type* type)
+ {
+ if (auto declRefValueType = as<DeclRefType>(type))
+ {
+ if (as<ClassDecl>(declRefValueType->declRef.getDecl()))
+ return true;
+ if (as<InterfaceDecl>(declRefValueType->declRef.getDecl()))
+ return true;
+ }
+ return false;
+ }
+
bool SemanticsVisitor::CoerceToProperTypeImpl(
TypeExp const& typeExp,
Type** outProperType,
DiagnosticSink* diagSink)
{
+ Type* result = nullptr;
Type* type = typeExp.type;
auto originalExpr = typeExp.exp;
auto expr = originalExpr;
-
if(!type && expr)
{
expr = maybeResolveOverloadedExpr(expr, LookupMask::type, diagSink);
@@ -289,18 +301,26 @@ namespace Slang
// ignore non-parameter members
}
}
- if (outProperType)
- {
- *outProperType = InstantiateGenericType(genericDeclRef, args);
- }
- return true;
+ result = InstantiateGenericType(genericDeclRef, args);
}
// default case: we expect this to already be a proper type
- if (outProperType)
+ if (!result)
+ {
+ result = type;
+ }
+
+ // Check for invalid types.
+ // We don't allow pointers to managed types.
+ if (auto ptrType = as<PtrType>(result))
{
- *outProperType = type;
+ if (isManagedType(ptrType->getValueType()))
+ {
+ getSink()->diagnose(typeExp.exp, Diagnostics::cannotDefinePtrTypeToManagedResource);
+ }
}
+
+ *outProperType = result;
return true;
}
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index e44a880a2..811359d71 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -338,6 +338,10 @@ DIAGNOSTIC(32003, Error, unexpectedEnumTagExpr, "unexpected form for 'enum'
// 303xx: interfaces and associated types
DIAGNOSTIC(30300, Error, assocTypeInInterfaceOnly, "'associatedtype' can only be defined in an 'interface'.")
DIAGNOSTIC(30301, Error, globalGenParamInGlobalScopeOnly, "'type_param' can only be defined global scope.")
+
+// Interop
+DIAGNOSTIC(30400, Error, cannotDefinePtrTypeToManagedResource, "pointer to a managed resource is invalid, use `NativeRef<T>` instead")
+
// TODO: need to assign numbers to all these extra diagnostics...
DIAGNOSTIC(39999, Fatal, cyclicReference, "cyclic reference '$0'.")
DIAGNOSTIC(39999, Error, localVariableUsedBeforeDeclared, "local variable '$0' is being used before its declaration.")
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index 3ec03d0e7..11e0812d9 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -212,22 +212,6 @@ Result linkAndOptimizeIR(
// un-specialized IR.
dumpIRIfEnabled(codeGenContext, irModule);
- switch (target)
- {
- case CodeGenTarget::CPPSource:
- case CodeGenTarget::HostCPPSource:
- {
- lowerComInterfaces(irModule, artifactDesc.style, sink);
- generateDllImportFuncs(codeGenContext->getTargetReq(), irModule, sink);
- generateDllExportFuncs(irModule, sink);
- break;
- }
- default: break;
- }
-
- // Lower `Result<T,E>` types into ordinary struct types.
- lowerResultType(irModule, sink);
-
// Replace any global constants with their values.
//
replaceGlobalConstants(irModule);
@@ -323,6 +307,24 @@ Result linkAndOptimizeIR(
break;
}
+ lowerOptionalType(irModule, sink);
+ simplifyIR(irModule);
+
+ switch (target)
+ {
+ case CodeGenTarget::CPPSource:
+ case CodeGenTarget::HostCPPSource:
+ {
+ lowerComInterfaces(irModule, artifactDesc.style, sink);
+ generateDllImportFuncs(codeGenContext->getTargetReq(), irModule, sink);
+ generateDllExportFuncs(irModule, sink);
+ break;
+ }
+ default: break;
+ }
+
+ // Lower `Result<T,E>` types into ordinary struct types.
+ lowerResultType(irModule, sink);
// Desguar any union types, since these will be illegal on
// various targets.
@@ -393,8 +395,6 @@ Result linkAndOptimizeIR(
//
simplifyIR(irModule);
- lowerOptionalType(irModule, sink);
-
#if 0
dumpIRIfEnabled(codeGenContext, irModule, "AFTER DCE");
#endif
diff --git a/source/slang/slang-ir-generics-lowering-context.cpp b/source/slang/slang-ir-generics-lowering-context.cpp
index 48178340d..0ed7d75d7 100644
--- a/source/slang/slang-ir-generics-lowering-context.cpp
+++ b/source/slang/slang-ir-generics-lowering-context.cpp
@@ -3,6 +3,7 @@
#include "slang-ir-generics-lowering-context.h"
#include "slang-ir-layout.h"
+#include "slang-ir-util.h"
namespace Slang
{
@@ -36,24 +37,6 @@ namespace Slang
return false;
}
- bool isComInterfaceType(IRType* type)
- {
- if (!type) return false;
- if (type->findDecoration<IRComInterfaceDecoration>() ||
- type->getOp() == kIROp_ComPtrType)
- {
- return true;
- }
-
- if (auto ptrType = as<IRNativePtrType>(type))
- {
- auto valueType = ptrType->getValueType();
- return valueType->findDecoration<IRComInterfaceDecoration>() != nullptr;
- }
-
- return false;
- }
-
bool isTypeValue(IRInst* typeInst)
{
if (typeInst)
diff --git a/source/slang/slang-ir-generics-lowering-context.h b/source/slang/slang-ir-generics-lowering-context.h
index e373e2bec..85ba2443d 100644
--- a/source/slang/slang-ir-generics-lowering-context.h
+++ b/source/slang/slang-ir-generics-lowering-context.h
@@ -104,8 +104,6 @@ namespace Slang
bool isPolymorphicType(IRInst* typeInst);
- bool isComInterfaceType(IRType* type);
-
// Returns true if typeInst represents a type and should be lowered into
// Ptr(RTTIType).
bool isTypeValue(IRInst* typeInst);
diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h
index 7f4e991b0..61011634c 100644
--- a/source/slang/slang-ir-insts.h
+++ b/source/slang/slang-ir-insts.h
@@ -2927,6 +2927,8 @@ public:
IRType* type,
IRInst* val);
+ IRInst* emitCastPtrToBool(IRInst* val);
+
IRGlobalConstant* emitGlobalConstant(
IRType* type);
diff --git a/source/slang/slang-ir-lower-existential.cpp b/source/slang/slang-ir-lower-existential.cpp
index cfdacc7ac..2d533b424 100644
--- a/source/slang/slang-ir-lower-existential.cpp
+++ b/source/slang/slang-ir-lower-existential.cpp
@@ -4,6 +4,7 @@
#include "slang-ir-generics-lowering-context.h"
#include "slang-ir.h"
#include "slang-ir-insts.h"
+#include "slang-ir-util.h"
namespace Slang
{
diff --git a/source/slang/slang-ir-lower-generic-call.cpp b/source/slang/slang-ir-lower-generic-call.cpp
index 2a97bc28a..574db5dab 100644
--- a/source/slang/slang-ir-lower-generic-call.cpp
+++ b/source/slang/slang-ir-lower-generic-call.cpp
@@ -1,6 +1,7 @@
// slang-ir-lower-generic-call.cpp
#include "slang-ir-lower-generic-call.h"
#include "slang-ir-generics-lowering-context.h"
+#include "slang-ir-util.h"
namespace Slang
{
diff --git a/source/slang/slang-ir-lower-generic-function.cpp b/source/slang/slang-ir-lower-generic-function.cpp
index 1bd785e8e..e990447bf 100644
--- a/source/slang/slang-ir-lower-generic-function.cpp
+++ b/source/slang/slang-ir-lower-generic-function.cpp
@@ -5,6 +5,7 @@
#include "slang-ir.h"
#include "slang-ir-clone.h"
#include "slang-ir-insts.h"
+#include "slang-ir-util.h"
namespace Slang
{
diff --git a/source/slang/slang-ir-lower-generics.cpp b/source/slang/slang-ir-lower-generics.cpp
index 6b8150605..f94ce57d3 100644
--- a/source/slang/slang-ir-lower-generics.cpp
+++ b/source/slang/slang-ir-lower-generics.cpp
@@ -14,6 +14,7 @@
#include "slang-ir-specialize-dynamic-associatedtype-lookup.h"
#include "slang-ir-witness-table-wrapper.h"
#include "slang-ir-ssa-simplification.h"
+#include "slang-ir-util.h"
namespace Slang
diff --git a/source/slang/slang-ir-lower-optional-type.cpp b/source/slang/slang-ir-lower-optional-type.cpp
index 79be4e042..96f8353bb 100644
--- a/source/slang/slang-ir-lower-optional-type.cpp
+++ b/source/slang/slang-ir-lower-optional-type.cpp
@@ -3,6 +3,7 @@
#include "slang-ir-lower-optional-type.h"
#include "slang-ir.h"
#include "slang-ir-insts.h"
+#include "slang-ir-util.h"
namespace Slang
{
@@ -35,6 +36,23 @@ namespace Slang
return type;
}
+ bool typeHasNullValue(IRInst* type)
+ {
+ switch (type->getOp())
+ {
+ case kIROp_ComPtrType:
+ case kIROp_NativePtrType:
+ case kIROp_NativeStringType:
+ case kIROp_PtrType:
+ case kIROp_ClassType:
+ return true;
+ case kIROp_InterfaceType:
+ return isComInterfaceType((IRType*)type);
+ default:
+ return false;
+ }
+ }
+
LoweredOptionalTypeInfo* getLoweredOptionalType(IRBuilder* builder, IRInst* type)
{
if (auto loweredInfo = loweredOptionalTypes.TryGetValue(type))
@@ -48,25 +66,30 @@ namespace Slang
return nullptr;
RefPtr<LoweredOptionalTypeInfo> info = new LoweredOptionalTypeInfo();
- info->optionalType = (IRType*)type;
auto optionalType = cast<IROptionalType>(type);
auto valueType = optionalType->getValueType();
+ info->optionalType = (IRType*)type;
info->valueType = valueType;
-
- auto structType = builder->createStructType();
- info->loweredType = structType;
- builder->addNameHintDecoration(structType, UnownedStringSlice("OptionalType"));
-
- info->valueType = valueType;
- auto valueKey = builder->createStructKey();
- builder->addNameHintDecoration(valueKey, UnownedStringSlice("value"));
- info->valueField = builder->createStructField(structType, valueKey, (IRType*)valueType);
-
- auto boolType = builder->getBoolType();
- auto hasValueKey = builder->createStructKey();
- builder->addNameHintDecoration(hasValueKey, UnownedStringSlice("hasValue"));
- info->hasValueField = builder->createStructField(structType, hasValueKey, (IRType*)boolType);
-
+ if (typeHasNullValue(valueType))
+ {
+ info->loweredType = valueType;
+ }
+ else
+ {
+ auto structType = builder->createStructType();
+ info->loweredType = structType;
+ builder->addNameHintDecoration(structType, UnownedStringSlice("OptionalType"));
+
+ info->valueType = valueType;
+ auto valueKey = builder->createStructKey();
+ builder->addNameHintDecoration(valueKey, UnownedStringSlice("value"));
+ info->valueField = builder->createStructField(structType, valueKey, (IRType*)valueType);
+
+ auto boolType = builder->getBoolType();
+ auto hasValueKey = builder->createStructKey();
+ builder->addNameHintDecoration(hasValueKey, UnownedStringSlice("hasValue"));
+ info->hasValueField = builder->createStructField(structType, hasValueKey, (IRType*)boolType);
+ }
mapLoweredTypeToOptionalTypeInfo[info->loweredType] = info;
loweredOptionalTypes[type] = info;
return info.Ptr();
@@ -123,12 +146,19 @@ namespace Slang
{
auto loweredOptionalTypeInfo = getLoweredOptionalType(builder, optionalInst->getDataType());
SLANG_ASSERT(loweredOptionalTypeInfo);
-
- auto value = builder->emitFieldExtract(
- builder->getBoolType(),
- optionalInst,
- loweredOptionalTypeInfo->hasValueField->getKey());
- return value;
+ IRInst* result = nullptr;
+ if (loweredOptionalTypeInfo->loweredType != loweredOptionalTypeInfo->valueType)
+ {
+ result = builder->emitFieldExtract(
+ builder->getBoolType(),
+ optionalInst,
+ loweredOptionalTypeInfo->hasValueField->getKey());
+ }
+ else
+ {
+ result = builder->emitCastPtrToBool(optionalInst);
+ }
+ return result;
}
void processGetOptionalHasValue(IROptionalHasValue* inst)
@@ -151,13 +181,20 @@ namespace Slang
auto base = inst->getOptionalOperand();
auto loweredOptionalTypeInfo = getLoweredOptionalType(builder, base->getDataType());
- SLANG_ASSERT(loweredOptionalTypeInfo);
- SLANG_ASSERT(loweredOptionalTypeInfo->valueField);
- auto getElement = builder->emitFieldExtract(
- loweredOptionalTypeInfo->valueType,
- base,
- loweredOptionalTypeInfo->valueField->getKey());
- inst->replaceUsesWith(getElement);
+ if (loweredOptionalTypeInfo->loweredType != loweredOptionalTypeInfo->valueType)
+ {
+ SLANG_ASSERT(loweredOptionalTypeInfo);
+ SLANG_ASSERT(loweredOptionalTypeInfo->valueField);
+ auto getElement = builder->emitFieldExtract(
+ loweredOptionalTypeInfo->valueType,
+ base,
+ loweredOptionalTypeInfo->valueField->getKey());
+ inst->replaceUsesWith(getElement);
+ }
+ else
+ {
+ inst->replaceUsesWith(base);
+ }
inst->removeAndDeallocate();
}
diff --git a/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp b/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp
index dbcc7a54c..441d32d24 100644
--- a/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp
+++ b/source/slang/slang-ir-specialize-dynamic-associatedtype-lookup.cpp
@@ -3,6 +3,7 @@
#include "slang-ir-generics-lowering-context.h"
#include "slang-ir-insts.h"
#include "slang-ir.h"
+#include "slang-ir-util.h"
namespace Slang
{
diff --git a/source/slang/slang-ir-util.cpp b/source/slang/slang-ir-util.cpp
index d91252fcc..7775fdb91 100644
--- a/source/slang/slang-ir-util.cpp
+++ b/source/slang/slang-ir-util.cpp
@@ -1,4 +1,5 @@
#include "slang-ir-util.h"
+#include "slang-ir-insts.h"
namespace Slang
{
@@ -43,4 +44,24 @@ bool isPtrToArrayType(IRInst* type)
return isPointerOfType(type, kIROp_ArrayType) || isPointerOfType(type, kIROp_UnsizedArrayType);
}
+
+bool isComInterfaceType(IRType* type)
+{
+ if (!type) return false;
+ if (type->findDecoration<IRComInterfaceDecoration>() ||
+ type->getOp() == kIROp_ComPtrType)
+ {
+ return true;
+ }
+
+ if (auto ptrType = as<IRNativePtrType>(type))
+ {
+ auto valueType = ptrType->getValueType();
+ return valueType->findDecoration<IRComInterfaceDecoration>() != nullptr;
+ }
+
+ return false;
+}
+
+
}
diff --git a/source/slang/slang-ir-util.h b/source/slang/slang-ir-util.h
index 5a09638d4..2300c929d 100644
--- a/source/slang/slang-ir-util.h
+++ b/source/slang/slang-ir-util.h
@@ -22,6 +22,8 @@ bool isPointerOfType(IRInst* ptrType, IROp opCode);
// Builds a dictionary that maps from requirement key to requirement value for `interfaceType`.
Dictionary<IRInst*, IRInst*> buildInterfaceRequirementDict(IRInterfaceType* interfaceType);
+bool isComInterfaceType(IRType* type);
+
}
#endif
diff --git a/source/slang/slang-ir-witness-table-wrapper.cpp b/source/slang/slang-ir-witness-table-wrapper.cpp
index 5d1a9360e..1d84eee19 100644
--- a/source/slang/slang-ir-witness-table-wrapper.cpp
+++ b/source/slang/slang-ir-witness-table-wrapper.cpp
@@ -5,6 +5,7 @@
#include "slang-ir.h"
#include "slang-ir-clone.h"
#include "slang-ir-insts.h"
+#include "slang-ir-util.h"
namespace Slang
{
diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp
index fd7cbe408..20bf6060d 100644
--- a/source/slang/slang-ir.cpp
+++ b/source/slang/slang-ir.cpp
@@ -4369,6 +4369,17 @@ namespace Slang
return inst;
}
+ IRInst* IRBuilder::emitCastPtrToBool(IRInst* val)
+ {
+ auto inst = createInst<IRInst>(
+ this,
+ kIROp_CastPtrToBool,
+ getBoolType(),
+ val);
+ addInst(inst);
+ return inst;
+ }
+
IRGlobalConstant* IRBuilder::emitGlobalConstant(
IRType* type)
{