summaryrefslogtreecommitdiff
path: root/source/slang/slang-lower-to-ir.cpp
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2024-03-04 21:57:50 -0800
committerGitHub <noreply@github.com>2024-03-04 21:57:50 -0800
commitbb017e6aa8ddbfac6b9a78a66f4706964fbeaff4 (patch)
treee902a0c319a326a035f815e6ac16a3d19fc860d3 /source/slang/slang-lower-to-ir.cpp
parent2297623aad4c249bccae3fe363ada31e308131ac (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.cpp52
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);
}