diff options
| author | Yong He <yonghe@outlook.com> | 2024-03-04 21:57:50 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-04 21:57:50 -0800 |
| commit | bb017e6aa8ddbfac6b9a78a66f4706964fbeaff4 (patch) | |
| tree | e902a0c319a326a035f815e6ac16a3d19fc860d3 /source/slang/slang-lower-to-ir.cpp | |
| parent | 2297623aad4c249bccae3fe363ada31e308131ac (diff) | |
Extend `as` and `is` operator to work on generic types. (#3672)
Diffstat (limited to 'source/slang/slang-lower-to-ir.cpp')
| -rw-r--r-- | source/slang/slang-lower-to-ir.cpp | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp index 409cd65ee..638a9c577 100644 --- a/source/slang/slang-lower-to-ir.cpp +++ b/source/slang/slang-lower-to-ir.cpp @@ -4314,9 +4314,7 @@ struct ExprLoweringVisitorBase : public ExprVisitor<Derived, LoweredValInfo> getBuilder()->emitMakeStruct(irType, args.getCount(), args.getBuffer())); } } - - SLANG_UNEXPECTED("unexpected type when creating default value"); - UNREACHABLE_RETURN(LoweredValInfo()); + return LoweredValInfo::simple(getBuilder()->emitDefaultConstruct(irType)); } LoweredValInfo getDefaultVal(DeclRef<VarDeclBase> decl) @@ -4718,20 +4716,32 @@ struct ExprLoweringVisitorBase : public ExprVisitor<Derived, LoweredValInfo> LoweredValInfo visitAsTypeExpr(AsTypeExpr* expr) { auto value = lowerLValueExpr(context, expr->value); - auto existentialInfo = value.getExtractedExistentialValInfo(); + ExtractedExistentialValInfo* existentialInfo = nullptr; auto optType = lowerType(context, expr->type); SLANG_RELEASE_ASSERT(optType->getOp() == kIROp_OptionalType); auto targetType = optType->getOperand(0); - auto witness = lowerSimpleVal(context, expr->witnessArg); auto builder = getBuilder(); auto var = builder->emitVar(optType); - auto isType = builder->emitIsType(existentialInfo->extractedVal, existentialInfo->witnessTable, targetType, witness); + IRInst* isType = nullptr; + if (expr->witnessArg) + { + auto witness = lowerSimpleVal(context, expr->witnessArg); + existentialInfo = value.getExtractedExistentialValInfo(); + isType = builder->emitIsType(existentialInfo->extractedVal, existentialInfo->witnessTable, targetType, witness); + } + else + { + SLANG_ASSERT(value.val); + auto leftType = lowerType(context, expr->value->type); + IRInst* args[] = { leftType, targetType }; + isType = builder->emitIntrinsicInst(builder->getBoolType(), kIROp_TypeEquals, 2, args); + } IRBlock* trueBlock; IRBlock* falseBlock; IRBlock* afterBlock; builder->emitIfElseWithBlocks(isType, trueBlock, falseBlock, afterBlock); builder->setInsertInto(trueBlock); - auto irVal = builder->emitReinterpret(targetType, existentialInfo->extractedVal); + auto irVal = builder->emitReinterpret(targetType, existentialInfo ? existentialInfo->extractedVal : getSimpleVal(context, value)); auto optionalVal = builder->emitMakeOptionalValue(optType, irVal); builder->emitStore(var, optionalVal); builder->emitBranch(afterBlock); @@ -4751,11 +4761,29 @@ struct ExprLoweringVisitorBase : public ExprVisitor<Derived, LoweredValInfo> { return LoweredValInfo::simple(getBuilder()->getBoolValue(expr->constantVal->value)); } - auto value = lowerLValueExpr(context, expr->value); - auto type = lowerType(context, expr->type); - auto witness = lowerSimpleVal(context, expr->witnessArg); - auto existentialInfo = value.getExtractedExistentialValInfo(); - auto irVal = getBuilder()->emitIsType(existentialInfo->extractedVal, existentialInfo->witnessTable, type, witness); + // If expr is a witness, then this is a run-time type check from for an existential type. + if (expr->witnessArg) + { + auto value = lowerLValueExpr(context, expr->value); + auto type = lowerType(context, expr->typeExpr.type); + auto witness = lowerSimpleVal(context, expr->witnessArg); + auto existentialInfo = value.getExtractedExistentialValInfo(); + auto irVal = getBuilder()->emitIsType(existentialInfo->extractedVal, existentialInfo->witnessTable, type, witness); + return LoweredValInfo::simple(irVal); + } + // For all other cases, we map to a simple type equality check in the IR. + IRType* leftType = nullptr; + if (auto typeType = as<TypeType>(expr->value->type)) + { + leftType = lowerType(context, typeType->getType()); + } + else + { + leftType = lowerType(context, expr->value->type); + } + auto rightType = lowerType(context, expr->typeExpr.type); + IRInst* args[] = { leftType, rightType }; + auto irVal = getBuilder()->emitIntrinsicInst(getBuilder()->getBoolType(), kIROp_TypeEquals, 2, args); return LoweredValInfo::simple(irVal); } |
