diff options
| author | Yong He <yonghe@outlook.com> | 2025-06-04 13:05:58 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-06-04 13:05:58 -0700 |
| commit | 812e478989e27983b8dea7ab11964de751654ba2 (patch) | |
| tree | e6db6def9c7896ee48c5fe42926856644e81c0e6 /source/slang/slang-ir-lower-optional-type.cpp | |
| parent | b9dc21d362f65f22bc707bede733a9537b80460a (diff) | |
Make interface types non c-style in Slang2026. (#7260)
* Make interface types non c-style.
* Make Optional<T> work with autodiff and existential types.
* Fix.
* patch behind slang 2026.
* Fix warnings.
* cleanup.
* Fix tests.
* Fix.
* Fix com interface lowering.
* Add comment to test.
* regenerate command line reference
* Add test for passing `none` to autodiff function.
* Fix recording of `getDynamicObjectRTTIBytes`.
* Fix nested Optional types.
---------
Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com>
Diffstat (limited to 'source/slang/slang-ir-lower-optional-type.cpp')
| -rw-r--r-- | source/slang/slang-ir-lower-optional-type.cpp | 107 |
1 files changed, 63 insertions, 44 deletions
diff --git a/source/slang/slang-ir-lower-optional-type.cpp b/source/slang/slang-ir-lower-optional-type.cpp index 5c9dcd722..1f9f398d3 100644 --- a/source/slang/slang-ir-lower-optional-type.cpp +++ b/source/slang/slang-ir-lower-optional-type.cpp @@ -8,6 +8,13 @@ namespace Slang { +enum LoweredOptionalTypeKind +{ + Struct, + PtrValue, + ExistentialValue, +}; + struct OptionalTypeLoweringContext { IRModule* module; @@ -16,10 +23,6 @@ struct OptionalTypeLoweringContext InstWorkList workList; InstHashSet workListSet; - IRGeneric* genericOptionalStructType = nullptr; - IRStructKey* valueKey = nullptr; - IRStructKey* hasValueKey = nullptr; - OptionalTypeLoweringContext(IRModule* inModule) : module(inModule), workList(inModule), workListSet(inModule) { @@ -30,6 +33,9 @@ struct OptionalTypeLoweringContext IRType* optionalType = nullptr; IRType* valueType = nullptr; IRType* loweredType = nullptr; + IRStructKey* hasValueKey = nullptr; + IRStructKey* valueKey = nullptr; + LoweredOptionalTypeKind kind = LoweredOptionalTypeKind::Struct; }; Dictionary<IRInst*, RefPtr<LoweredOptionalTypeInfo>> mapLoweredTypeToOptionalTypeInfo; Dictionary<IRInst*, RefPtr<LoweredOptionalTypeInfo>> loweredOptionalTypes; @@ -42,37 +48,29 @@ struct OptionalTypeLoweringContext return type; } - IRInst* getOrCreateGenericOptionalStruct() + IRInst* createOptionalStruct(IRType* type, LoweredOptionalTypeInfo* info) { - if (genericOptionalStructType) - return genericOptionalStructType; IRBuilder builder(module); builder.setInsertInto(module->getModuleInst()); - valueKey = builder.createStructKey(); - builder.addNameHintDecoration(valueKey, UnownedStringSlice("value")); - hasValueKey = builder.createStructKey(); - builder.addNameHintDecoration(hasValueKey, UnownedStringSlice("hasValue")); - - genericOptionalStructType = builder.emitGeneric(); - builder.addNameHintDecoration( - genericOptionalStructType, - UnownedStringSlice("_slang_Optional")); + info->valueKey = builder.createStructKey(); + builder.addNameHintDecoration(info->valueKey, UnownedStringSlice("value")); + info->hasValueKey = builder.createStructKey(); + builder.addNameHintDecoration(info->hasValueKey, UnownedStringSlice("hasValue")); - builder.setInsertInto(genericOptionalStructType); - auto block = builder.emitBlock(); - auto typeParam = builder.emitParam(builder.getTypeKind()); auto structType = builder.createStructType(); - builder.addNameHintDecoration(structType, UnownedStringSlice("_slang_Optional")); - builder.createStructField(structType, valueKey, (IRType*)typeParam); - builder.createStructField(structType, hasValueKey, builder.getBoolType()); - builder.setInsertInto(block); - builder.emitReturn(structType); - genericOptionalStructType->setFullType(builder.getTypeKind()); - return genericOptionalStructType; + StringBuilder sb; + sb << "_slang_Optional_"; + getTypeNameHint(sb, type); + builder.addNameHintDecoration(structType, sb.getUnownedSlice()); + builder.createStructField(structType, info->valueKey, type); + builder.createStructField(structType, info->hasValueKey, builder.getBoolType()); + + info->kind = LoweredOptionalTypeKind::Struct; + return structType; } - bool typeHasNullValue(IRInst* type) + bool typeHasNullValue(IRInst* type, LoweredOptionalTypeKind& outKind) { switch (type->getOp()) { @@ -81,21 +79,25 @@ struct OptionalTypeLoweringContext case kIROp_NativeStringType: case kIROp_PtrType: case kIROp_ClassType: + outKind = LoweredOptionalTypeKind::PtrValue; return true; case kIROp_InterfaceType: - return isComInterfaceType((IRType*)type); + if (isComInterfaceType((IRType*)type)) + outKind = LoweredOptionalTypeKind::PtrValue; + else + outKind = LoweredOptionalTypeKind::ExistentialValue; + return true; default: return false; } } - LoweredOptionalTypeInfo* getLoweredOptionalType(IRBuilder* builder, IRInst* type) + LoweredOptionalTypeInfo* getLoweredOptionalType(IRBuilder*, IRInst* type) { if (auto loweredInfo = loweredOptionalTypes.tryGetValue(type)) return loweredInfo->Ptr(); if (auto loweredInfo = mapLoweredTypeToOptionalTypeInfo.tryGetValue(type)) return loweredInfo->Ptr(); - if (!type) return nullptr; if (type->getOp() != kIROp_OptionalType) @@ -104,19 +106,21 @@ struct OptionalTypeLoweringContext RefPtr<LoweredOptionalTypeInfo> info = new LoweredOptionalTypeInfo(); auto optionalType = cast<IROptionalType>(type); auto valueType = optionalType->getValueType(); + while (auto valueOptionalType = as<IROptionalType>(valueType)) + { + // If the value type is also an Optional, we need to keep lowering it. + valueType = valueOptionalType->getValueType(); + } + info->optionalType = (IRType*)type; info->valueType = valueType; - if (typeHasNullValue(valueType)) + if (typeHasNullValue(valueType, info->kind)) { info->loweredType = valueType; } else { - auto genericType = getOrCreateGenericOptionalStruct(); - IRInst* args[] = {valueType}; - auto specializedType = - builder->emitSpecializeInst(builder->getTypeKind(), genericType, 1, args); - info->loweredType = (IRType*)specializedType; + info->loweredType = (IRType*)createOptionalStruct(valueType, info); } mapLoweredTypeToOptionalTypeInfo[info->loweredType] = info; loweredOptionalTypes[type] = info; @@ -171,6 +175,12 @@ struct OptionalTypeLoweringContext inst->replaceUsesWith(makeStruct); inst->removeAndDeallocate(); } + else if (info->kind == LoweredOptionalTypeKind::ExistentialValue) + { + auto zero = builder->emitDefaultConstruct(info->loweredType); + inst->replaceUsesWith(zero); + inst->removeAndDeallocate(); + } else { inst->replaceUsesWith(builder->getNullPtrValue(info->valueType)); @@ -183,13 +193,20 @@ struct OptionalTypeLoweringContext auto loweredOptionalTypeInfo = getLoweredOptionalType(builder, optionalInst->getDataType()); SLANG_ASSERT(loweredOptionalTypeInfo); IRInst* result = nullptr; - if (loweredOptionalTypeInfo->loweredType != loweredOptionalTypeInfo->valueType) - { - result = builder->emitFieldExtract(builder->getBoolType(), optionalInst, hasValueKey); - } - else + switch (loweredOptionalTypeInfo->kind) { + case LoweredOptionalTypeKind::Struct: + result = builder->emitFieldExtract( + builder->getBoolType(), + optionalInst, + loweredOptionalTypeInfo->hasValueKey); + break; + case LoweredOptionalTypeKind::PtrValue: result = builder->emitCastPtrToBool(optionalInst); + break; + case LoweredOptionalTypeKind::ExistentialValue: + result = builder->emitIsNullExistential(optionalInst); + break; } return result; } @@ -214,11 +231,13 @@ struct OptionalTypeLoweringContext auto base = inst->getOptionalOperand(); auto loweredOptionalTypeInfo = getLoweredOptionalType(builder, base->getDataType()); - if (loweredOptionalTypeInfo->loweredType != loweredOptionalTypeInfo->valueType) + if (loweredOptionalTypeInfo->kind == LoweredOptionalTypeKind::Struct) { SLANG_ASSERT(loweredOptionalTypeInfo); - auto getElement = - builder->emitFieldExtract(loweredOptionalTypeInfo->valueType, base, valueKey); + auto getElement = builder->emitFieldExtract( + loweredOptionalTypeInfo->valueType, + base, + loweredOptionalTypeInfo->valueKey); inst->replaceUsesWith(getElement); } else |
