summaryrefslogtreecommitdiffstats
path: root/source
diff options
context:
space:
mode:
authorYong He <yonghe@outlook.com>2023-08-09 20:11:09 -0700
committerGitHub <noreply@github.com>2023-08-09 20:11:09 -0700
commitf875d3f5ba9c1ddc6aa9a0960efd5ab27ae4e4c9 (patch)
tree42dae9fd6c260dfdafe7ce4a1ffc392e799c855d /source
parent03a5bb4bc0391e2de3c2dfb9ff3213bc0ccd9664 (diff)
Support implciit casted swizzled lvalue. (#3077)
* Support implciit casted swizzled lvalue. * Fix warnings. * Fix. * fix comment. * Prefer mangled linkage name for global params. * Update tests. --------- Co-authored-by: Yong He <yhe@nvidia.com>
Diffstat (limited to 'source')
-rw-r--r--source/slang/slang-check-constraint.cpp17
-rw-r--r--source/slang/slang-check-conversion.cpp15
-rw-r--r--source/slang/slang-check-impl.h2
-rw-r--r--source/slang/slang-emit-c-like.cpp2
-rw-r--r--source/slang/slang-ir-lower-l-value-cast.cpp28
-rw-r--r--source/slang/slang-ir-ssa.cpp11
-rw-r--r--source/slang/slang-lower-to-ir.cpp95
7 files changed, 108 insertions, 62 deletions
diff --git a/source/slang/slang-check-constraint.cpp b/source/slang/slang-check-constraint.cpp
index b9d33a1c1..d66bf35cc 100644
--- a/source/slang/slang-check-constraint.cpp
+++ b/source/slang/slang-check-constraint.cpp
@@ -186,20 +186,15 @@ namespace Slang
{
if (auto rightBasic = as<BasicExpressionType>(right))
{
- auto leftFlavor = leftBasic->getBaseType();
- auto rightFlavor = rightBasic->getBaseType();
+ auto costConvertRightToLeft = getConversionCost(leftBasic, rightBasic);
+ auto costConvertLeftToRight = getConversionCost(rightBasic, leftBasic);
- // TODO(tfoley): Need a special-case rule here that if
- // either operand is of type `half`, then we promote
- // to at least `float`
-
- // Return the one that had higher rank...
- if (leftFlavor > rightFlavor)
- return left;
+ // Return the one that had lower conversion cost.
+ if (costConvertRightToLeft > costConvertLeftToRight)
+ return right;
else
{
- SLANG_ASSERT(rightFlavor > leftFlavor); // equality was handles at the top of this function
- return right;
+ return left;
}
}
diff --git a/source/slang/slang-check-conversion.cpp b/source/slang/slang-check-conversion.cpp
index d89808c3d..09a783fb4 100644
--- a/source/slang/slang-check-conversion.cpp
+++ b/source/slang/slang-check-conversion.cpp
@@ -1360,15 +1360,20 @@ namespace Slang
Type* toType,
Type* fromType)
{
- // Can we convert at all?
- ConversionCost conversionCost;
- if(!canCoerce(toType, fromType, nullptr, &conversionCost))
- return false;
+ auto conversionCost = getConversionCost(toType, fromType);
// Is the conversion cheap enough to be done implicitly?
- if(conversionCost >= kConversionCost_GeneralConversion)
+ if (conversionCost >= kConversionCost_GeneralConversion)
return false;
return true;
}
+
+ ConversionCost SemanticsVisitor::getConversionCost(Type* toType, Type* fromType)
+ {
+ ConversionCost conversionCost = kConversionCost_Impossible;
+ if (!canCoerce(toType, fromType, nullptr, &conversionCost))
+ return kConversionCost_Impossible;
+ return conversionCost;
+ }
}
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index 88f1e2975..6cb719e43 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -1911,6 +1911,8 @@ namespace Slang
Type* toType,
Type* fromType);
+ ConversionCost getConversionCost(Type* toType, Type* fromType);
+
Type* _tryJoinTypeWithInterface(
Type* type,
Type* interfaceType);
diff --git a/source/slang/slang-emit-c-like.cpp b/source/slang/slang-emit-c-like.cpp
index 5bd57e81c..e2faba808 100644
--- a/source/slang/slang-emit-c-like.cpp
+++ b/source/slang/slang-emit-c-like.cpp
@@ -951,7 +951,7 @@ String CLikeSourceEmitter::generateName(IRInst* inst)
// Just use the linkages mangled name directly.
return externCppDecoration->getName();
}
-
+
// If we have a name hint on the instruction, then we will try to use that
// to provide the basis for the actual name in the output code.
if(auto nameHintDecoration = inst->findDecoration<IRNameHintDecoration>())
diff --git a/source/slang/slang-ir-lower-l-value-cast.cpp b/source/slang/slang-ir-lower-l-value-cast.cpp
index cd03d2bd5..aca58cef3 100644
--- a/source/slang/slang-ir-lower-l-value-cast.cpp
+++ b/source/slang/slang-ir-lower-l-value-cast.cpp
@@ -166,15 +166,10 @@ struct LValueCastLoweringContext
// convert in.
// Okay we are going to replace the implicit casts with temporaries around call sites/uses.
- List<IRInst*> useSites;
+ List<IRUse*> useSites;
for (auto use = castInst->firstUse; use; use = use->nextUse)
{
- auto useSite = use->getUser();
-
- if (useSites.indexOf(useSite) < 0)
- {
- useSites.add(useSite);
- }
+ useSites.add(use);
}
// If there is a name hint on the source, we'll copy it over to the temporaries
@@ -187,7 +182,8 @@ struct LValueCastLoweringContext
for (auto useSite : useSites)
{
- builder.setInsertBefore(useSite);
+ auto user = useSite->getUser();
+ builder.setInsertBefore(user);
auto tmpVar = builder.emitVar(toValueType);
if (nameHintDecoration)
@@ -196,27 +192,17 @@ struct LValueCastLoweringContext
}
// If it's inout we convert via cast whats in the castOperand
- if (castInst->getOp() == kIROp_InOutImplicitCast)
+ if (castInst->getOp() == kIROp_InOutImplicitCast && user->getOp() != kIROp_Store)
{
builder.emitStore(tmpVar, builder.emitCast(toValueType, builder.emitLoad(castOperand)));
}
// Convert the temporary back to the original location
- builder.setInsertAfter(useSite);
+ builder.setInsertAfter(user);
builder.emitStore(castOperand, builder.emitCast(fromValueType, builder.emitLoad(tmpVar)));
// Go through all of the operands of the use inst relacing, with the temporary
- const auto operandCount = Count(useSite->getOperandCount());
- auto operands = useSite->getOperands();
-
- for (Index i = 0; i < operandCount; ++i)
- {
- auto& callSiteOperand = operands[i];
- if(callSiteOperand.get() == castInst)
- {
- callSiteOperand.set(tmpVar);
- }
- }
+ builder.replaceOperand(useSite, tmpVar);
}
// When we are done we can destroy the inst
diff --git a/source/slang/slang-ir-ssa.cpp b/source/slang/slang-ir-ssa.cpp
index 48cf2976f..18eba677e 100644
--- a/source/slang/slang-ir-ssa.cpp
+++ b/source/slang/slang-ir-ssa.cpp
@@ -379,11 +379,18 @@ static void cloneRelevantDecorations(
break;
case kIROp_PreciseDecoration:
- case kIROp_NameHintDecoration:
// Copy these decorations if the target doesn't already have them,
// but don't make duplicate decorations on the target.
//
- if( !val->findDecorationImpl(decoration->getOp()) )
+ if (!val->findDecorationImpl(decoration->getOp()))
+ {
+ cloneDecoration(nullptr, decoration, val, var->getModule());
+ }
+ break;
+ case kIROp_NameHintDecoration:
+ // If the target already contains a linkage decoration, don't add
+ // a name decoration to avoid issues with emit logic.
+ if (!val->findDecorationImpl(decoration->getOp()) && !val->findDecoration<IRLinkageDecoration>())
{
cloneDecoration(nullptr, decoration, val, var->getModule());
}
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index f642409a1..b1a38febd 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -98,6 +98,7 @@ struct SwizzledLValueInfo;
struct SwizzledMatrixLValueInfo;
struct CopiedValInfo;
struct ExtractedExistentialValInfo;
+struct ImplicitCastLValueInfo;
// This type is our core representation of lowered values.
// In the simple case, it just wraps an `IRInst*`.
@@ -138,6 +139,9 @@ struct LoweredValInfo
// The value extracted from an opened existential
ExtractedExistential,
+
+ // The L-Value that is an implicit cast.
+ ImplicitCastedLValue,
};
union
@@ -217,6 +221,9 @@ struct LoweredValInfo
static LoweredValInfo swizzledMatrixLValue(
SwizzledMatrixLValueInfo* extInfo);
+ static LoweredValInfo implicitCastedLValue(
+ ImplicitCastLValueInfo* extInfo);
+
SwizzledLValueInfo* getSwizzledLValueInfo()
{
SLANG_ASSERT(flavor == Flavor::SwizzledLValue);
@@ -237,6 +244,12 @@ struct LoweredValInfo
SLANG_ASSERT(flavor == Flavor::ExtractedExistential);
return (ExtractedExistentialValInfo*)ext;
}
+
+ ImplicitCastLValueInfo* getImplicitCastedLValue()
+ {
+ SLANG_ASSERT(flavor == Flavor::ImplicitCastedLValue);
+ return (ImplicitCastLValueInfo*)ext;
+ }
};
// This case is used to indicate a reference to an AST-level
@@ -362,6 +375,18 @@ struct ExtractedExistentialValInfo : ExtendedValueInfo
IRInst* witnessTable;
};
+struct ImplicitCastLValueInfo : ExtendedValueInfo
+{
+ // The type of the expression.
+ IRType* type;
+
+ // The base expression (this should be an l-value)
+ LoweredValInfo base;
+
+ // The type of the lvalue (inout, out, ref, etc.)
+ ParameterDirection lValueType;
+};
+
LoweredValInfo LoweredValInfo::boundMember(
BoundMemberInfo* boundMemberInfo)
{
@@ -407,6 +432,15 @@ LoweredValInfo LoweredValInfo::swizzledMatrixLValue(
return info;
}
+LoweredValInfo LoweredValInfo::implicitCastedLValue(
+ ImplicitCastLValueInfo* extInfo)
+{
+ LoweredValInfo info;
+ info.flavor = Flavor::ImplicitCastedLValue;
+ info.ext = extInfo;
+ return info;
+}
+
LoweredValInfo LoweredValInfo::extractedExistential(
ExtractedExistentialValInfo* extInfo)
{
@@ -1124,7 +1158,13 @@ top:
return LoweredValInfo::simple(info->extractedVal);
}
-
+ case LoweredValInfo::Flavor::ImplicitCastedLValue:
+ {
+ auto info = lowered.getImplicitCastedLValue();
+ auto baseVal = materialize(context, info->base);
+ auto result = builder->emitCast(info->type, getSimpleVal(context, baseVal));
+ return LoweredValInfo::simple(result);
+ }
default:
SLANG_UNEXPECTED("unhandled value flavor");
UNREACHABLE_RETURN(LoweredValInfo());
@@ -4461,30 +4501,17 @@ struct LValueExprLoweringVisitor : ExprLoweringVisitorBase<LValueExprLoweringVis
LoweredValInfo visitLValueImplicitCastExpr(LValueImplicitCastExpr* expr)
{
- auto builder = getBuilder();
-
auto irType = lowerType(context, expr->type);
- auto irPtrType = builder->getPtrType(irType);
-
auto loweredArg = lowerLValueExpr(context, expr->arguments[0]);
- // It should be a ptr, because it is a LValue
- SLANG_ASSERT(loweredArg.flavor == LoweredValInfo::Flavor::Ptr);
-
- // We have the irValue (which should be a Ptr because it's an LValue)
- auto irLValue = loweredArg.val;
-
- IRInst* irCast = nullptr;
+ RefPtr<ImplicitCastLValueInfo> lValueInfo = new ImplicitCastLValueInfo();
+ lValueInfo->type = irType;
+ lValueInfo->base = loweredArg;
+ lValueInfo->lValueType = kParameterDirection_InOut;
if (as<OutImplicitCastExpr>(expr))
- {
- irCast = builder->emitOutImplicitCast(irPtrType, irLValue);
- }
- else
- {
- irCast = builder->emitInOutImplicitCast(irPtrType, irLValue);
- }
-
- return LoweredValInfo::ptr(irCast);
+ lValueInfo->lValueType = kParameterDirection_Out;
+ context->shared->extValues.add(lValueInfo);
+ return LoweredValInfo::implicitCastedLValue(lValueInfo);
}
// When visiting a swizzle expression in an l-value context,
@@ -5850,7 +5877,21 @@ LoweredValInfo tryGetAddress(
return LoweredValInfo::swizzledMatrixLValue(newSwizzleInfo);
}
break;
-
+ case LoweredValInfo::Flavor::ImplicitCastedLValue:
+ {
+ auto info = val.getImplicitCastedLValue();
+ auto baseAddr = tryGetAddress(context, info->base, TryGetAddressMode::Aggressive);
+ if (baseAddr.flavor == LoweredValInfo::Flavor::Ptr)
+ {
+ IRInst* result = nullptr;
+ if (info->lValueType == kParameterDirection_InOut)
+ result = context->irBuilder->emitInOutImplicitCast(context->irBuilder->getPtrType(info->type), baseAddr.val);
+ else
+ result = context->irBuilder->emitOutImplicitCast(context->irBuilder->getPtrType(info->type), baseAddr.val);
+ return LoweredValInfo::ptr(result);
+ }
+ }
+ break;
// TODO: are there other cases we need to handled here?
default:
@@ -6242,6 +6283,16 @@ top:
}
break;
+ case LoweredValInfo::Flavor::ImplicitCastedLValue:
+ {
+ auto leftInfo = left.getImplicitCastedLValue();
+ left = leftInfo->base;
+ auto rightVal = getSimpleVal(context, right);
+ right = LoweredValInfo::simple(builder->emitCast(leftInfo->type, rightVal));
+ goto top;
+ }
+ break;
+
default:
SLANG_UNIMPLEMENTED_X("assignment");
break;