summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-rw-r--r--source/slang/core.meta.slang201
-rw-r--r--source/slang/hlsl.meta.slang45
-rw-r--r--source/slang/slang-check-expr.cpp10
-rw-r--r--source/slang/slang-check-impl.h1
-rw-r--r--source/slang/slang-check-overload.cpp33
-rw-r--r--source/slang/slang-compound-intrinsics.h80
-rw-r--r--source/slang/slang-diagnostic-defs.h2
-rw-r--r--source/slang/slang-expr-defs.h2
-rw-r--r--source/slang/slang-lower-to-ir.cpp197
-rw-r--r--source/slang/slang-mangle.cpp8
-rw-r--r--source/slang/slang-modifier-defs.h12
-rw-r--r--source/slang/slang-stdlib.cpp25
-rw-r--r--source/slang/slang-syntax.h1
-rw-r--r--source/slang/slang.vcxproj1
-rw-r--r--source/slang/slang.vcxproj.filters3
15 files changed, 263 insertions, 358 deletions
diff --git a/source/slang/core.meta.slang b/source/slang/core.meta.slang
index f73178322..821905375 100644
--- a/source/slang/core.meta.slang
+++ b/source/slang/core.meta.slang
@@ -1455,11 +1455,8 @@ for (int tt = 0; tt < kBaseTextureTypeCount; ++tt)
}
-for (auto op : unaryOps)
+for (auto op : intrinsicUnaryOps)
{
- char const* fixity = (op.flags & POSTFIX) != 0 ? "__postfix " : "__prefix ";
- char const* qual = (op.flags & ASSIGNMENT) != 0 ? "in out " : "";
-
for (auto type : kBaseTypes)
{
if ((type.flags & op.flags) == 0)
@@ -1469,18 +1466,15 @@ for (auto op : unaryOps)
if (op.flags & BOOL_RESULT) resultType = "bool";
// scalar version
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << qual << type.name << " value);\n";
+ sb << "__prefix __intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << type.name << " value);\n";
// vector version
sb << "__generic<let N : int> ";
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << qual << "vector<" << type.name << ",N> value);\n";
+ sb << "__prefix __intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << "vector<" << type.name << ",N> value);\n";
// matrix version
sb << "__generic<let N : int, let M : int> ";
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << qual << "matrix<" << type.name << ",N,M> value);\n";
+ sb << "__prefix __intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << "matrix<" << type.name << ",N,M> value);\n";
}
// Synthesize generic versions
@@ -1490,27 +1484,85 @@ for (auto op : unaryOps)
if (op.flags & BOOL_RESULT) resultType = "bool";
// scalar version
- sb << fixity;
sb << "__generic<T : " << op.interface << ">\n";
- sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << qual << "T value);\n";
+ sb << "__prefix __intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << "T value);\n";
// vector version
sb << "__generic<T : " << op.interface << ", let N : int> ";
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << qual << "vector<T,N> value);\n";
+ sb << "__prefix __intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(vector<T,N> value);\n";
// matrix version
sb << "__generic<T : " << op.interface << ", let N : int, let M : int> ";
- sb << fixity;
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << qual << "matrix<T,N,M> value);\n";
+ sb << "__prefix __intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(matrix<T,N,M> value);\n";
}
}
-for (auto op : binaryOps)
+}}}}
+
+__generic<T : __BuiltinArithmeticType>
+[__unsafeForceInlineEarly]
+__prefix T operator+(T value)
+{ return value; }
+
+__generic<T : __BuiltinArithmeticType, let N : int>
+[__unsafeForceInlineEarly]
+__prefix vector<T,N> operator+(vector<T,N> value)
+{ return value; }
+
+__generic<T : __BuiltinArithmeticType, let R : int, let C : int>
+[__unsafeForceInlineEarly]
+__prefix matrix<T,R,C> operator+(matrix<T,R,C> value)
+{ return value; }
+
+${{{{
+
+static const struct IncDecOpInfo
+{
+ char const* name;
+ char const* binOp;
+} kIncDecOps[] =
+{
+ { "++", "+" },
+ { "--", "-" },
+};
+static const struct IncDecOpFixity
+{
+ char const* qual;
+ char const* bodyPrefix;
+ char const* returnVal;
+} kIncDecFixities[] =
{
- char const* leftQual = "";
- if(op.flags & ASSIGNMENT) leftQual = "in out ";
+ { "__prefix", "", "value" },
+ { "__postfix", " let result = value;", "result" },
+};
+for(auto op : kIncDecOps)
+for(auto fixity : kIncDecFixities)
+{
+}}}}
+
+$(fixity.qual)
+__generic<T : __BuiltinArithmeticType>
+[__unsafeForceInlineEarly]
+T operator$(op.name)(in out T value)
+{$(fixity.bodyPrefix) value = value $(op.binOp) T(1); return $(fixity.returnVal); }
+
+$(fixity.qual)
+__generic<T : __BuiltinArithmeticType, let N : int>
+[__unsafeForceInlineEarly]
+vector<T,N> operator$(op.name)(in out vector<T,N> value)
+{$(fixity.bodyPrefix) value = value $(op.binOp) T(1); return $(fixity.returnVal); }
+$(fixity.qual)
+__generic<T : __BuiltinArithmeticType, let R : int, let C : int>
+[__unsafeForceInlineEarly]
+matrix<T,R,C> operator$(op.name)(in out matrix<T,R,C> value)
+{$(fixity.bodyPrefix) value = value $(op.binOp) T(1); return $(fixity.returnVal); }
+
+${{{{
+}
+
+for (auto op : intrinsicBinaryOps)
+{
for (auto type : kBaseTypes)
{
if ((type.flags & op.flags) == 0)
@@ -1533,15 +1585,15 @@ for (auto op : binaryOps)
// the compiler)
// scalar version
- sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftQual << leftType << " left, " << rightType << " right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftType << " left, " << rightType << " right);\n";
// vector version
sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
// matrix version
sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
// We currently synthesize addiitonal overloads
// for the case where one or the other operand
@@ -1577,21 +1629,18 @@ for (auto op : binaryOps)
// for builtin in non-operator functions anyway.
// scalar-vector and scalar-matrix
- if (!(op.flags & ASSIGNMENT))
- {
- sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n";
+ sb << "__generic<let N : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftType << " left, vector<" << rightType << ",N> right);\n";
- sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << leftType << " left, matrix<" << rightType << ",N,M> right);\n";
- }
+ sb << "__generic<let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftType << " left, matrix<" << rightType << ",N,M> right);\n";
// vector-scalar and matrix-scalar
sb << "__generic<let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(vector<" << leftType << ",N> left, " << rightType << " right);\n";
sb << "__generic<let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, " << rightType << " right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(matrix<" << leftType << ",N,M> left, " << rightType << " right);\n";
}
// Synthesize generic versions
@@ -1606,36 +1655,102 @@ for (auto op : binaryOps)
// scalar version
sb << "__generic<T : " << op.interface << ">\n";
- sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftQual << leftType << " left, " << rightType << " right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") " << resultType << " operator" << op.opName << "(" << leftType << " left, " << rightType << " right);\n";
// vector version
sb << "__generic<T : " << op.interface << ", let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(vector<" << leftType << ",N> left, vector<" << rightType << ",N> right);\n";
// matrix version
sb << "__generic<T : " << op.interface << ", let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(matrix<" << leftType << ",N,M> left, matrix<" << rightType << ",N,M> right);\n";
// scalar-vector and scalar-matrix
- if (!(op.flags & ASSIGNMENT))
- {
- sb << "__generic<T : " << op.interface << ", let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << leftType << " left, vector<" << rightType << ",N> right);\n";
+ sb << "__generic<T : " << op.interface << ", let N : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftType << " left, vector<" << rightType << ",N> right);\n";
- sb << "__generic<T : " << op.interface << ", let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << leftType << " left, matrix<" << rightType << ",N,M> right);\n";
- }
+ sb << "__generic<T : " << op.interface << ", let N : int, let M : int> ";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftType << " left, matrix<" << rightType << ",N,M> right);\n";
// vector-scalar and matrix-scalar
sb << "__generic<T : " << op.interface << ", let N : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(" << leftQual << "vector<" << leftType << ",N> left, " << rightType << " right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") vector<" << resultType << ",N> operator" << op.opName << "(vector<" << leftType << ",N> left, " << rightType << " right);\n";
sb << "__generic<T : " << op.interface << ", let N : int, let M : int> ";
- sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(" << leftQual << "matrix<" << leftType << ",N,M> left, " << rightType << " right);\n";
+ sb << "__intrinsic_op(" << int(op.opCode) << ") matrix<" << resultType << ",N,M> operator" << op.opName << "(matrix<" << leftType << ",N,M> left, " << rightType << " right);\n";
}
}
+
+
+ static const struct CompoundBinaryOpInfo
+ {
+ char const* name;
+ char const* interface;
+ } kCompoundBinaryOps[] =
+ {
+ { "+", "__BuiltinArithmeticType" },
+ { "-", "__BuiltinArithmeticType" },
+ { "*", "__BuiltinArithmeticType" },
+ { "/", "__BuiltinArithmeticType" },
+ { "%", "__BuiltinIntegerType" },
+ { "%", "__BuiltinFloatingPointType" },
+ { "&", "__BuiltinLogicalType" },
+ { "|", "__BuiltinLogicalType" },
+ { "^", "__BuiltinLogicalType" },
+ { "<<", "__BuiltinIntegerType" },
+ { ">>", "__BuiltinIntegerType" },
+ };
+ for( auto op : kCompoundBinaryOps )
+ {
+ }}}}
+
+ __generic<T : $(op.interface)>
+ [__unsafeForceInlineEarly]
+ T operator$(op.name)=(in out T left, T right)
+ {
+ left = left $(op.name) right;
+ return left;
+ }
+
+ __generic<T : $(op.interface), let N : int>
+ [__unsafeForceInlineEarly]
+ vector<T,N> operator$(op.name)=(in out vector<T,N> left, vector<T,N> right)
+ {
+ left = left $(op.name) right;
+ return left;
+ }
+
+ __generic<T : $(op.interface), let N : int>
+ [__unsafeForceInlineEarly]
+ vector<T,N> operator$(op.name)=(in out vector<T,N> left, T right)
+ {
+ left = left $(op.name) right;
+ return left;
+ }
+
+ __generic<T : $(op.interface), let R : int, let C : int>
+ [__unsafeForceInlineEarly]
+ matrix<T,R,C> operator$(op.name)=(in out matrix<T,R,C> left, matrix<T,R,C> right)
+ {
+ left = left $(op.name) right;
+ return left;
+ }
+
+ __generic<T : $(op.interface), let R : int, let C : int>
+ [__unsafeForceInlineEarly]
+ matrix<T,R,C> operator$(op.name)=(in out matrix<T,R,C> left, T right)
+ {
+ left = left $(op.name) right;
+ return left;
+ }
+
+ ${{{{
+ }
+
}}}}
+
+
// Specialized function
__intrinsic_op
diff --git a/source/slang/hlsl.meta.slang b/source/slang/hlsl.meta.slang
index 2b556c10b..30c86b3eb 100644
--- a/source/slang/hlsl.meta.slang
+++ b/source/slang/hlsl.meta.slang
@@ -524,16 +524,19 @@ matrix<float,N,M> asfloat(matrix<uint,N,M> x)
}
// No op
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-float asfloat(float x);
+[__unsafeForceInlineEarly]
+float asfloat(float x)
+{ return x; }
__generic<let N : int>
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-vector<float,N> asfloat(vector<float,N> x);
+[__unsafeForceInlineEarly]
+vector<float,N> asfloat(vector<float,N> x)
+{ return x; }
__generic<let N : int, let M : int>
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-matrix<float,N,M> asfloat(matrix<float,N,M> x);
+[__unsafeForceInlineEarly]
+matrix<float,N,M> asfloat(matrix<float,N,M> x)
+{ return x; }
// Inverse sine (HLSL SM 1.0)
__generic<T : __BuiltinFloatingPointType>
@@ -599,16 +602,19 @@ matrix<int, N, M> asint(matrix<uint, N, M> x)
}
// No op
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-int asint(int x);
+[__unsafeForceInlineEarly]
+int asint(int x)
+{ return x; }
__generic<let N : int>
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-vector<int,N> asint(vector<int,N> x);
+[__unsafeForceInlineEarly]
+vector<int,N> asint(vector<int,N> x)
+{ return x; }
__generic<let N : int, let M : int>
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-matrix<int,N,M> asint(matrix<int,N,M> x);
+[__unsafeForceInlineEarly]
+matrix<int,N,M> asint(matrix<int,N,M> x)
+{ return x; }
// Reinterpret bits of double as a uint (HLSL SM 5.0)
@@ -657,16 +663,19 @@ matrix<uint, N, M> asuint(matrix<int, N, M> x)
MATRIX_MAP_UNARY(uint, N, M, asuint, x);
}
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-uint asuint(uint x);
+[__unsafeForceInlineEarly]
+uint asuint(uint x)
+{ return x; }
__generic<let N : int>
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-vector<uint,N> asuint(vector<uint,N> x);
+[__unsafeForceInlineEarly]
+vector<uint,N> asuint(vector<uint,N> x)
+{ return x; }
__generic<let N : int, let M : int>
-__intrinsic_op($(kCompoundIntrinsicOp_Pos))
-matrix<uint,N,M> asuint(matrix<uint,N,M> x);
+[__unsafeForceInlineEarly]
+matrix<uint,N,M> asuint(matrix<uint,N,M> x)
+{ return x; }
// Inverse tangent (HLSL SM 1.0)
__generic<T : __BuiltinFloatingPointType>
diff --git a/source/slang/slang-check-expr.cpp b/source/slang/slang-check-expr.cpp
index adfc36641..fbe38bac7 100644
--- a/source/slang/slang-check-expr.cpp
+++ b/source/slang/slang-check-expr.cpp
@@ -359,6 +359,7 @@ namespace Slang
}
RefPtr<Expr> SemanticsVisitor::createLookupResultExpr(
+ Name* name,
LookupResult const& lookupResult,
RefPtr<Expr> baseExpr,
SourceLoc loc)
@@ -366,6 +367,7 @@ namespace Slang
if (lookupResult.isOverloaded())
{
auto overloadedExpr = new OverloadedExpr();
+ overloadedExpr->name = name;
overloadedExpr->loc = loc;
overloadedExpr->type = QualType(
getSession()->getOverloadedType());
@@ -960,10 +962,11 @@ namespace Slang
// declarations on the type and try to call one of them.
{
+ Name* name = getName("operator[]");
LookupResult lookupResult = lookUpMember(
getSession(),
this,
- getName("operator[]"),
+ name,
baseType);
if (!lookupResult.isValid())
{
@@ -977,7 +980,7 @@ namespace Slang
// case the attempt to call it will trigger overload
// resolution.
RefPtr<Expr> subscriptFuncExpr = createLookupResultExpr(
- lookupResult, subscriptExpr->BaseExpression, subscriptExpr->loc);
+ name, lookupResult, subscriptExpr->BaseExpression, subscriptExpr->loc);
RefPtr<InvokeExpr> subscriptCallExpr = new InvokeExpr();
subscriptCallExpr->loc = subscriptExpr->loc;
@@ -1181,6 +1184,7 @@ namespace Slang
if (lookupResult.isValid())
{
return createLookupResultExpr(
+ expr->name,
lookupResult,
nullptr,
expr->loc);
@@ -1531,6 +1535,7 @@ namespace Slang
}
return createLookupResultExpr(
+ expr->name,
lookupResult,
baseExpression,
expr->loc);
@@ -1638,6 +1643,7 @@ namespace Slang
// to in this context...
return createLookupResultExpr(
+ expr->name,
lookupResult,
expr->BaseExpression,
expr->loc);
diff --git a/source/slang/slang-check-impl.h b/source/slang/slang-check-impl.h
index 8b32f8612..df0080ec1 100644
--- a/source/slang/slang-check-impl.h
+++ b/source/slang/slang-check-impl.h
@@ -356,6 +356,7 @@ namespace Slang
SourceLoc loc);
RefPtr<Expr> createLookupResultExpr(
+ Name* name,
LookupResult const& lookupResult,
RefPtr<Expr> baseExpr,
SourceLoc loc);
diff --git a/source/slang/slang-check-overload.cpp b/source/slang/slang-check-overload.cpp
index 41aa94a35..92d390bf0 100644
--- a/source/slang/slang-check-overload.cpp
+++ b/source/slang/slang-check-overload.cpp
@@ -1261,9 +1261,9 @@ namespace Slang
if (!first) sb << ", ";
first = false;
- formatType(sb, GetType(genericValParam));
- sb << " ";
sb << getText(genericValParam.GetName());
+ sb << ":";
+ formatType(sb, GetType(genericValParam));
}
else
{}
@@ -1279,14 +1279,24 @@ namespace Slang
static void formatDeclKindPrefix(StringBuilder& sb, Decl* decl)
{
+ if(auto genericDecl = as<GenericDecl>(decl))
+ {
+ decl = genericDecl->inner;
+ }
if(as<FuncDecl>(decl))
{
sb << "func ";
}
}
- void SemanticsVisitor::formatDeclResultType(StringBuilder& sb, DeclRef<Decl> const& declRef)
+ void SemanticsVisitor::formatDeclResultType(StringBuilder& sb, DeclRef<Decl> const& inDeclRef)
{
+ DeclRef<Decl> declRef = inDeclRef;
+ if(auto genericDeclRef = declRef.as<GenericDecl>())
+ {
+ declRef = DeclRef<Decl>(GetInner(genericDeclRef), genericDeclRef.substitutions);
+ }
+
if(as<ConstructorDecl>(declRef))
{}
else if(auto callableDeclRef = declRef.as<CallableDecl>())
@@ -1434,10 +1444,19 @@ namespace Slang
}
Name* funcName = nullptr;
- if (auto baseVar = as<VarExpr>(funcExpr))
- funcName = baseVar->name;
- else if(auto baseMemberRef = as<MemberExpr>(funcExpr))
- funcName = baseMemberRef->name;
+ {
+ Expr* baseExpr = funcExpr;
+
+ if(auto baseGenericApp = as<GenericAppExpr>(baseExpr))
+ baseExpr = baseGenericApp->FunctionExpr;
+
+ if (auto baseVar = as<VarExpr>(baseExpr))
+ funcName = baseVar->name;
+ else if(auto baseMemberRef = as<MemberExpr>(baseExpr))
+ funcName = baseMemberRef->name;
+ else if(auto baseOverloaded = as<OverloadedExpr>(baseExpr))
+ funcName = baseOverloaded->name;
+ }
String argsList = getCallSignatureString(context);
diff --git a/source/slang/slang-compound-intrinsics.h b/source/slang/slang-compound-intrinsics.h
deleted file mode 100644
index 682e7bc4a..000000000
--- a/source/slang/slang-compound-intrinsics.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// slang-compound-intrinsics.h
-#pragma once
-
-// Intrinsic functions in the Slang standard library are marked
-// with the `__intrinsic_op(...)` modifier. Many of these map
-// one-to-one to instruction opcodes in the Slang IR, and the
-// argument to `__intrinsic_op(...)` is the IR instruction
-// opcode in that case.
-//
-// In other cases, we have intrinsic operations like the `+=` or
-// `&&` operator that either need to map to multiple IR instructions
-// (or more generally, a number of instructions not equal to one),
-// or otherwise have complications thake one-to-one lowering
-// not possible.
-//
-// We refer to these as "compound" intrinsic ops, since the common
-// case is that they represent a composition of multiple instructions.
-//
-// In order to not conflict with the opcodes of any IR instructions,
-// these compound intrinsic ops will all be identified by *negative*
-// integer opcodes.
-
-// We start by defining an "X-macro" that lists all the compound
-// intrinsic ops we support.
-
-#define FOREACH_COMPOUND_INTRINSIC_OP(M) \
- M(Pos) \
- M(PreInc) \
- M(PreDec) \
- M(PostInc) \
- M(PostDec) \
- M(AddAssign) \
- M(SubAssign) \
- M(MulAssign) \
- M(DivAssign) \
- M(IRemAssign) \
- M(FRemAssign) \
- M(AndAssign) \
- M(OrAssign) \
- M(XorAssign ) \
- M(LshAssign) \
- M(RshAssign) \
- M(Assign) \
- M(And) \
- M(Or) \
- /* end */
-
-// We will use a simple type alias to capture the fact that
-// a 32-bit integer is sufficient to represent compound
-// intrinsic ops (as negative values) plus IR opcode values
-// for single-instruction intrinsics (as non-negative values)
-//
-typedef int32_t IntrinsicOp;
-
-// Next we use an enumeration declaration as an implementation
-// detail, to associate each of the above cases with a (positive)
-// integer.
-//
-enum class _CompoundIntrinsicOpVal : IntrinsicOp
-{
-#define DECLARE_COMPOUND_INTRINSIC_OP_VAL(NAME) NAME,
- FOREACH_COMPOUND_INTRINSIC_OP(DECLARE_COMPOUND_INTRINSIC_OP_VAL)
-#undef DECLARE_COMPOUND_INTRINSIC_OP_VAL
-};
-
-// Finally, we define a second enumeration that takes the values
-// from the first and performs a bitwise negation on them, which
-// guarantees we get strictly negative values.
-
- /// Compound/complex intrinsic operations, which do not map to a single IR instruction.
- ///
- /// All of the values of this enumeration are guaranteed to be negative, and thus
- /// cannot conflict with any valid value of type `IROp`
- ///
-enum CompoundIntrinsicOp : IntrinsicOp
-{
-#define DECLARE_COMPOUND_INTRINSIC_OP(NAME) kCompoundIntrinsicOp_##NAME = ~IntrinsicOp(_CompoundIntrinsicOpVal::NAME),
- FOREACH_COMPOUND_INTRINSIC_OP(DECLARE_COMPOUND_INTRINSIC_OP)
-#undef DECLARE_COMPOUND_INTRINSIC_OP
-};
diff --git a/source/slang/slang-diagnostic-defs.h b/source/slang/slang-diagnostic-defs.h
index ff64b023c..2fbd373cc 100644
--- a/source/slang/slang-diagnostic-defs.h
+++ b/source/slang/slang-diagnostic-defs.h
@@ -329,7 +329,7 @@ DIAGNOSTIC(39999, Error, expectedIntegerConstantNotLiteral, "could not extract v
DIAGNOSTIC(39999, Error, noApplicableOverloadForNameWithArgs, "no overload for '$0' applicable to arguments of type $1")
DIAGNOSTIC(39999, Error, noApplicableWithArgs, "no overload applicable to arguments of type $0")
-DIAGNOSTIC(39999, Error, ambiguousOverloadForNameWithArgs, "ambiguous call to '$0' operation with arguments of type $1")
+DIAGNOSTIC(39999, Error, ambiguousOverloadForNameWithArgs, "ambiguous call to '$0' with arguments of type $1")
DIAGNOSTIC(39999, Error, ambiguousOverloadWithArgs, "ambiguous call to overloaded operation with arguments of type $0")
DIAGNOSTIC(39999, Note, overloadCandidate, "candidate: $0")
diff --git a/source/slang/slang-expr-defs.h b/source/slang/slang-expr-defs.h
index a7105b07b..725bbb62d 100644
--- a/source/slang/slang-expr-defs.h
+++ b/source/slang/slang-expr-defs.h
@@ -21,6 +21,8 @@ SIMPLE_SYNTAX_CLASS(VarExpr, DeclRefExpr)
// An expression that references an overloaded set of declarations
// having the same name.
SYNTAX_CLASS(OverloadedExpr, Expr)
+ // The name that was looked up and found to be overloaded
+ FIELD(Name*, name)
// Optional: the base expression is this overloaded result
// arose from a member-reference expression.
diff --git a/source/slang/slang-lower-to-ir.cpp b/source/slang/slang-lower-to-ir.cpp
index f57e15bc4..029fe23f6 100644
--- a/source/slang/slang-lower-to-ir.cpp
+++ b/source/slang/slang-lower-to-ir.cpp
@@ -5,7 +5,6 @@
#include "slang-check.h"
#include "slang-ir.h"
-#include "slang-compound-intrinsics.h"
#include "slang-ir-constexpr.h"
#include "slang-ir-dce.h"
#include "slang-ir-inline.h"
@@ -475,7 +474,8 @@ bool isImportedDecl(IRGenContext* context, Decl* decl)
return false;
}
-static bool isInline(Decl* decl)
+ /// Is `decl` a function that should be force-inlined early in compilation (before linking)?
+static bool isForceInlineEarly(Decl* decl)
{
if(decl->HasModifier<UnsafeForceInlineEarlyAttribute>())
return true;
@@ -542,113 +542,6 @@ LoweredValInfo emitCallToVal(
}
}
-LoweredValInfo emitCompoundAssignOp(
- IRGenContext* context,
- IRType* type,
- IROp op,
- UInt argCount,
- IRInst* const* args)
-{
- auto builder = context->irBuilder;
- SLANG_UNREFERENCED_PARAMETER(argCount);
- SLANG_ASSERT(argCount == 2);
- auto leftPtr = args[0];
- auto rightVal = args[1];
-
- auto leftVal = builder->emitLoad(leftPtr);
-
- IRInst* innerArgs[] = { leftVal, rightVal };
- auto innerOp = builder->emitIntrinsicInst(type, op, 2, innerArgs);
-
- builder->emitStore(leftPtr, innerOp);
-
- return LoweredValInfo::ptr(leftPtr);
-}
-
-IRInst* getOneValOfType(
- IRGenContext* context,
- IRType* type)
-{
- switch(type->op)
- {
- case kIROp_IntType:
- case kIROp_UIntType:
- case kIROp_UInt64Type:
- return context->irBuilder->getIntValue(type, 1);
-
- case kIROp_HalfType:
- case kIROp_FloatType:
- case kIROp_DoubleType:
- return context->irBuilder->getFloatValue(type, 1.0);
-
- default:
- break;
- }
-
- // TODO: should make sure to handle vector and matrix types here
-
- SLANG_UNEXPECTED("inc/dec type");
- UNREACHABLE_RETURN(nullptr);
-}
-
-LoweredValInfo emitPrefixIncDecOp(
- IRGenContext* context,
- IRType* type,
- IROp op,
- UInt argCount,
- IRInst* const* args)
-{
- auto builder = context->irBuilder;
- SLANG_UNREFERENCED_PARAMETER(argCount);
- SLANG_ASSERT(argCount == 1);
- auto argPtr = args[0];
-
- auto preVal = builder->emitLoad(argPtr);
-
- IRInst* oneVal = getOneValOfType(context, type);
-
- IRInst* innerArgs[] = { preVal, oneVal };
- auto innerOp = builder->emitIntrinsicInst(type, op, 2, innerArgs);
-
- builder->emitStore(argPtr, innerOp);
-
- // For a prefix operator like `++i` we return
- // the value after the increment/decrement has
- // been applied. In casual terms we "increment
- // the varaible, then return its value."
- //
- return LoweredValInfo::simple(innerOp);
-}
-
-LoweredValInfo emitPostfixIncDecOp(
- IRGenContext* context,
- IRType* type,
- IROp op,
- UInt argCount,
- IRInst* const* args)
-{
- auto builder = context->irBuilder;
- SLANG_UNREFERENCED_PARAMETER(argCount);
- SLANG_ASSERT(argCount == 1);
- auto argPtr = args[0];
-
- auto preVal = builder->emitLoad(argPtr);
-
- IRInst* oneVal = getOneValOfType(context, type);
-
- IRInst* innerArgs[] = { preVal, oneVal };
- auto innerOp = builder->emitIntrinsicInst(type, op, 2, innerArgs);
-
- builder->emitStore(argPtr, innerOp);
-
- // For a postfix operator like `i++` we return
- // the value that we read before the increment/decrement
- // gets applied. In casual terms we "read
- // the variable, then increment it."
- //
- return LoweredValInfo::simple(preVal);
-}
-
LoweredValInfo lowerRValueExpr(
IRGenContext* context,
Expr* expr);
@@ -739,67 +632,16 @@ LoweredValInfo emitCallToDeclRef(
auto funcDecl = funcDeclRef.getDecl();
if(auto intrinsicOpModifier = funcDecl->FindModifier<IntrinsicOpModifier>())
{
- // An intrinsic op either maps to a single IR instruction
- // (in the case where the opcode value is >= 0), or to
- // a `CompountIntrinsicOp` (in the case where it is < 0).
+ // The intrinsic op maps to a single IR instruction,
+ // so we will emit an instruction with the chosen
+ // opcode, and the arguments to the call as its operands.
//
auto intrinsicOp = getIntrinsicOp(funcDecl, intrinsicOpModifier);
- if(intrinsicOp < 0)
- {
- // We have a compound op, which requires special-case
- // handling to generate zero or more IR instructions.
- //
- auto compoundOp = CompoundIntrinsicOp(intrinsicOp);
- switch (compoundOp)
- {
- case kCompoundIntrinsicOp_Pos:
- return LoweredValInfo::simple(args[0]);
-
-#define CASE(COMPOUND, OP) \
- case COMPOUND: return emitCompoundAssignOp(context, type, OP, argCount, args)
-
- CASE(kCompoundIntrinsicOp_AddAssign, kIROp_Add);
- CASE(kCompoundIntrinsicOp_SubAssign, kIROp_Sub);
- CASE(kCompoundIntrinsicOp_MulAssign, kIROp_Mul);
- CASE(kCompoundIntrinsicOp_DivAssign, kIROp_Div);
- CASE(kCompoundIntrinsicOp_IRemAssign,kIROp_IRem);
- CASE(kCompoundIntrinsicOp_FRemAssign,kIROp_FRem);
- CASE(kCompoundIntrinsicOp_AndAssign, kIROp_BitAnd);
- CASE(kCompoundIntrinsicOp_OrAssign, kIROp_BitOr);
- CASE(kCompoundIntrinsicOp_XorAssign, kIROp_BitXor);
- CASE(kCompoundIntrinsicOp_LshAssign, kIROp_Lsh);
- CASE(kCompoundIntrinsicOp_RshAssign, kIROp_Rsh);
-
-#undef CASE
-
-#define CASE(COMPOUND, OP) \
- case COMPOUND: return emitPrefixIncDecOp(context, type, OP, argCount, args)
- CASE(kCompoundIntrinsicOp_PreInc, kIROp_Add);
- CASE(kCompoundIntrinsicOp_PreDec, kIROp_Sub);
-#undef CASE
-
-#define CASE(COMPOUND, OP) \
- case COMPOUND: return emitPostfixIncDecOp(context, type, OP, argCount, args)
- CASE(kCompoundIntrinsicOp_PostInc, kIROp_Add);
- CASE(kCompoundIntrinsicOp_PostDec, kIROp_Sub);
-#undef CASE
- default:
- SLANG_UNIMPLEMENTED_X("IR pseudo-op");
- UNREACHABLE_RETURN(LoweredValInfo());
- }
- }
- else
- {
- // The intrinsic op maps to a single IR instruction,
- // so we will emit an instruction with the chosen
- // opcode, and the arguments to the call as its operands.
- //
- return LoweredValInfo::simple(builder->emitIntrinsicInst(
- type,
- IROp(intrinsicOp),
- argCount,
- args));
- }
+ return LoweredValInfo::simple(builder->emitIntrinsicInst(
+ type,
+ IROp(intrinsicOp),
+ argCount,
+ args));
}
if( auto ctorDeclRef = funcDeclRef.as<ConstructorDecl>() )
@@ -5184,7 +5026,7 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
if(auto initExpr = decl->initExpr)
{
auto initVal = lowerRValueExpr(context, initExpr);
- initVal = materialize(context, initVal);
+ initVal = LoweredValInfo::simple(getSimpleVal(context, initVal));
setGlobalValue(context, decl, initVal);
return initVal;
}
@@ -6042,7 +5884,22 @@ struct DeclLoweringVisitor : DeclVisitor<DeclLoweringVisitor, LoweredValInfo>
subBuilder->setInsertInto(irFunc);
- if (isImportedDecl(decl) && !isInline(decl))
+ // If a function is imported from another module then
+ // we usually don't want to emit it as a definition, and
+ // will instead only emit a declaration for it with an
+ // appropriate `[import(...)]` linkage decoration.
+ //
+ // However, if the function is marked with `[__unsafeForceInlineEarly]`
+ // then we need to make sure the IR for its definition is available
+ // to the mandatory optimization passes.
+ //
+ // TODO: The design here means that we will re-emit the inline
+ // function from its AST in every module that uses it. We should
+ // instead have logic to clone the target function in from the
+ // pre-generated IR for the module that defines it (or do some kind
+ // of minimal linking to bring in the inline functions).
+ //
+ if (isImportedDecl(decl) && !isForceInlineEarly(decl))
{
// Always emit imported declarations as declarations,
// and not definitions.
diff --git a/source/slang/slang-mangle.cpp b/source/slang/slang-mangle.cpp
index dfb55404e..2ad84d3d3 100644
--- a/source/slang/slang-mangle.cpp
+++ b/source/slang/slang-mangle.cpp
@@ -273,6 +273,14 @@ namespace Slang
if (declRef.is<RefAccessorDecl>()) emitRaw(context, "Ar");
}
+ // Special case: need a way to tell prefix and postfix unary
+ // operators apart.
+ {
+ if(declRef.getDecl()->HasModifier<PostfixModifier>()) emitRaw(context, "P");
+ if(declRef.getDecl()->HasModifier<PrefixModifier>()) emitRaw(context, "p");
+ }
+
+
// Are we the "inner" declaration beneath a generic decl?
if(parentGenericDeclRef && (parentGenericDeclRef.getDecl()->inner.Ptr() == declRef.getDecl()))
{
diff --git a/source/slang/slang-modifier-defs.h b/source/slang/slang-modifier-defs.h
index 58f2c5af9..7ea1d0101 100644
--- a/source/slang/slang-modifier-defs.h
+++ b/source/slang/slang-modifier-defs.h
@@ -36,17 +36,9 @@ SYNTAX_CLASS(IntrinsicOpModifier, Modifier)
// Token that names the intrinsic op.
FIELD(Token, opToken)
- // The opcode for the intrinsic operation.
+ // The IR opcode for the intrinsic operation.
//
- // If greather than or equal to zero, then `op`
- // is an `IROp` and directly identifies an IR
- // instruction that the intrinsic should translate to.
- //
- // If less than zero, then `op` is a `CompoundIntrinsicOp`
- // which maps to zero or more IR instructions using
- // special-case logic in the IR lowering phase.
- //
- FIELD_INIT(IntrinsicOp, op, 0)
+ FIELD_INIT(uint32_t, op, 0)
END_SYNTAX_CLASS()
// A modifier that marks something as an intrinsic function,
diff --git a/source/slang/slang-stdlib.cpp b/source/slang/slang-stdlib.cpp
index b23d1970b..1f59b1686 100644
--- a/source/slang/slang-stdlib.cpp
+++ b/source/slang/slang-stdlib.cpp
@@ -1,7 +1,6 @@
// slang-stdlib.cpp
#include "slang-compiler.h"
-#include "slang-compound-intrinsics.h"
#include "slang-ir.h"
#include "slang-syntax.h"
@@ -50,8 +49,6 @@ namespace Slang
BOOL_RESULT = 1 << 2,
BOOL_MASK = 1 << 3,
UINT_MASK = 1 << 4,
- ASSIGNMENT = 1 << 5,
- POSTFIX = 1 << 6,
INT_MASK = SINT_MASK | UINT_MASK,
ARITHMETIC_MASK = INT_MASK | FLOAT_MASK,
@@ -199,20 +196,15 @@ namespace Slang
}
}
- struct OpInfo { IntrinsicOp opCode; char const* opName; char const* interface; unsigned flags; };
+ struct IntrinsicOpInfo { IROp opCode; char const* opName; char const* interface; unsigned flags; };
- static const OpInfo unaryOps[] = {
- { kCompoundIntrinsicOp_Pos, "+", "__BuiltinArithmeticType", ARITHMETIC_MASK },
+ static const IntrinsicOpInfo intrinsicUnaryOps[] = {
{ kIROp_Neg, "-", "__BuiltinArithmeticType", ARITHMETIC_MASK },
{ kIROp_Not, "!", nullptr, BOOL_MASK | BOOL_RESULT },
{ kIROp_BitNot, "~", "__BuiltinIntegerType", INT_MASK },
- { kCompoundIntrinsicOp_PreInc, "++", "__BuiltinArithmeticType", ARITHMETIC_MASK | ASSIGNMENT },
- { kCompoundIntrinsicOp_PreDec, "--", "__BuiltinArithmeticType", ARITHMETIC_MASK | ASSIGNMENT },
- { kCompoundIntrinsicOp_PostInc, "++", "__BuiltinArithmeticType", ARITHMETIC_MASK | ASSIGNMENT | POSTFIX },
- { kCompoundIntrinsicOp_PostDec, "--", "__BuiltinArithmeticType", ARITHMETIC_MASK | ASSIGNMENT | POSTFIX },
};
- static const OpInfo binaryOps[] = {
+ static const IntrinsicOpInfo intrinsicBinaryOps[] = {
{ kIROp_Add, "+", "__BuiltinArithmeticType", ARITHMETIC_MASK },
{ kIROp_Sub, "-", "__BuiltinArithmeticType", ARITHMETIC_MASK },
{ kIROp_Mul, "*", "__BuiltinArithmeticType", ARITHMETIC_MASK },
@@ -232,17 +224,6 @@ namespace Slang
{ kIROp_Less, "<", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT },
{ kIROp_Geq, ">=", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT },
{ kIROp_Leq, "<=", "__BuiltinArithmeticType", ARITHMETIC_MASK | BOOL_RESULT },
- { kCompoundIntrinsicOp_AddAssign, "+=", "__BuiltinArithmeticType", ASSIGNMENT | ARITHMETIC_MASK },
- { kCompoundIntrinsicOp_SubAssign, "-=", "__BuiltinArithmeticType", ASSIGNMENT | ARITHMETIC_MASK },
- { kCompoundIntrinsicOp_MulAssign, "*=", "__BuiltinArithmeticType", ASSIGNMENT | ARITHMETIC_MASK },
- { kCompoundIntrinsicOp_DivAssign, "/=", "__BuiltinArithmeticType", ASSIGNMENT | ARITHMETIC_MASK },
- { kCompoundIntrinsicOp_IRemAssign, "%=", "__BuiltinIntegerType", ASSIGNMENT | INT_MASK },
- { kCompoundIntrinsicOp_FRemAssign, "%=", "__BuiltinFloatingPointType", ASSIGNMENT | FLOAT_MASK },
- { kCompoundIntrinsicOp_AndAssign, "&=", "__BuiltinLogicalType", ASSIGNMENT | LOGICAL_MASK },
- { kCompoundIntrinsicOp_OrAssign, "|=", "__BuiltinLogicalType", ASSIGNMENT | LOGICAL_MASK },
- { kCompoundIntrinsicOp_XorAssign, "^=", "__BuiltinLogicalType", ASSIGNMENT | LOGICAL_MASK },
- { kCompoundIntrinsicOp_LshAssign, "<<=", "__BuiltinIntegerType", ASSIGNMENT | INT_MASK },
- { kCompoundIntrinsicOp_RshAssign, ">>=", "__BuiltinIntegerType", ASSIGNMENT | INT_MASK },
};
String Session::getCoreLibraryCode()
diff --git a/source/slang/slang-syntax.h b/source/slang/slang-syntax.h
index 9c3945b4d..61219ecd2 100644
--- a/source/slang/slang-syntax.h
+++ b/source/slang/slang-syntax.h
@@ -2,7 +2,6 @@
#define SLANG_SYNTAX_H
#include "../core/slang-basic.h"
-#include "slang-compound-intrinsics.h"
#include "slang-lexer.h"
#include "slang-profile.h"
#include "slang-type-system-shared.h"
diff --git a/source/slang/slang.vcxproj b/source/slang/slang.vcxproj
index 0d702d9f5..027c43a95 100644
--- a/source/slang/slang.vcxproj
+++ b/source/slang/slang.vcxproj
@@ -193,7 +193,6 @@
<ClInclude Include="slang-check-impl.h" />
<ClInclude Include="slang-check.h" />
<ClInclude Include="slang-compiler.h" />
- <ClInclude Include="slang-compound-intrinsics.h" />
<ClInclude Include="slang-decl-defs.h" />
<ClInclude Include="slang-diagnostic-defs.h" />
<ClInclude Include="slang-diagnostics.h" />
diff --git a/source/slang/slang.vcxproj.filters b/source/slang/slang.vcxproj.filters
index a73a74756..9be567654 100644
--- a/source/slang/slang.vcxproj.filters
+++ b/source/slang/slang.vcxproj.filters
@@ -30,9 +30,6 @@
<ClInclude Include="slang-compiler.h">
<Filter>Header Files</Filter>
</ClInclude>
- <ClInclude Include="slang-compound-intrinsics.h">
- <Filter>Header Files</Filter>
- </ClInclude>
<ClInclude Include="slang-decl-defs.h">
<Filter>Header Files</Filter>
</ClInclude>