-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[HLSL] Implement output parameter #101083
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
e8ec3e2
ac6799f
d865dbf
6c8c058
3441e91
2283f0a
6b66117
7acfe26
c094804
1f1f398
adb4d3c
a529de0
5f7e351
80c4c8d
7ab1395
1bb6cae
7b21187
54ebfa0
821c565
4c2be5c
b883f66
55804b1
57dfb16
f407786
e39cd29
92aa4c0
3c7a96f
bd003fd
ddb0711
6e5c7ce
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7061,6 +7061,67 @@ class ArraySectionExpr : public Expr { | |
void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } | ||
}; | ||
|
||
/// This class represents temporary values used to represent inout and out | ||
/// arguments in HLSL. From the callee perspective these parameters are more or | ||
/// less __restrict__ T&. They are guaranteed to not alias any memory. inout | ||
/// parameters are initialized by the caller, and out parameters are references | ||
/// to uninitialized memory. | ||
/// | ||
/// In the caller, the argument expression creates a temporary in local memory | ||
/// and the address of the temporary is passed into the callee. There may be | ||
/// implicit conversion sequences to initialize the temporary, and on expiration | ||
/// of the temporary an inverse conversion sequence is applied as a write-back | ||
/// conversion to the source l-value. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Somewhere in this declaration — either here or on the getter/setter pairs below — you need to actually document the structure of the sub-expressions. That's needed whenever the sub-expressions don't obviously reflect the structure of the source code, which at minimum is true whenever an OVE is involved. |
||
class HLSLOutArgExpr : public Expr { | ||
friend class ASTStmtReader; | ||
|
||
Expr *Base; | ||
Expr *Writeback; | ||
OpaqueValueExpr *OpaqueVal; | ||
bool IsInOut; | ||
|
||
HLSLOutArgExpr(QualType Ty, Expr *B, Expr *WB, OpaqueValueExpr *OpV, | ||
bool IsInOut) | ||
: Expr(HLSLOutArgExprClass, Ty, VK_LValue, OK_Ordinary), Base(B), | ||
Writeback(WB), OpaqueVal(OpV), IsInOut(IsInOut) { | ||
assert(!Ty->isDependentType() && "HLSLOutArgExpr given a dependent type!"); | ||
} | ||
|
||
explicit HLSLOutArgExpr(EmptyShell Shell) | ||
: Expr(HLSLOutArgExprClass, Shell) {} | ||
|
||
public: | ||
static HLSLOutArgExpr *Create(const ASTContext &C, QualType Ty, Expr *Base, | ||
bool IsInOut, Expr *WB, OpaqueValueExpr *OpV); | ||
static HLSLOutArgExpr *CreateEmpty(const ASTContext &Ctx); | ||
|
||
const Expr *getBase() const { return Base; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You need to document what the expressions are here, because it's pretty subtle. So the way you've written it, this a conversion of the base l-value to the type of the parameter, the writeback is an assignment of the temporary result back to the base l-value, and the OVE represents the temporary result. I think this is problematic, though; see the comment in Sema. |
||
Expr *getBase() { return Base; } | ||
|
||
const Expr *getWriteback() const { return Writeback; } | ||
Expr *getWriteback() { return Writeback; } | ||
|
||
const OpaqueValueExpr *getOpaqueValue() const { return OpaqueVal; } | ||
OpaqueValueExpr *getOpaqueValue() { return OpaqueVal; } | ||
|
||
bool isInOut() const { return IsInOut; } | ||
rjmccall marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
SourceLocation getBeginLoc() const LLVM_READONLY { | ||
return Base->getBeginLoc(); | ||
} | ||
|
||
SourceLocation getEndLoc() const LLVM_READONLY { return Base->getEndLoc(); } | ||
|
||
static bool classof(const Stmt *T) { | ||
return T->getStmtClass() == HLSLOutArgExprClass; | ||
} | ||
|
||
// Iterators | ||
child_range children() { | ||
return child_range((Stmt **)&Base, ((Stmt **)&Writeback) + 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I certainly hope we don't do this elsewhere. Please declare an array field and make the accessors pull the elements out. |
||
} | ||
}; | ||
|
||
/// Frontend produces RecoveryExprs on semantic errors that prevent creating | ||
/// other well-formed expressions. E.g. when type-checking of a binary operator | ||
/// fails, we cannot produce a BinaryOperator expression. Instead, we can choose | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3507,6 +3507,12 @@ CXXNameMangler::mangleExtParameterInfo(FunctionProtoType::ExtParameterInfo PI) { | |
case ParameterABI::Ordinary: | ||
break; | ||
|
||
// HLSL parameter mangling. | ||
case ParameterABI::HLSLOut: | ||
case ParameterABI::HLSLInOut: | ||
mangleVendorQualifier(getParameterABISpelling(PI.getABI())); | ||
break; | ||
|
||
// All of these start with "swift", so they come before "ns_consumed". | ||
case ParameterABI::SwiftContext: | ||
case ParameterABI::SwiftAsyncContext: | ||
|
@@ -5703,6 +5709,12 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity, | |
Out << "E"; | ||
break; | ||
} | ||
case Expr::HLSLOutArgExprClass: { | ||
const auto *OAE = cast<clang::HLSLOutArgExpr>(E); | ||
Out << (OAE->isInOut() ? "_inout_" : "_out_"); | ||
mangleType(E->getType()); | ||
break; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, so this is wrong in every way. :) Expression mangling generally follows the syntax. Since there is no argument-side syntax for passing an argument to an If it were important to mangle this for some reason, you would want to mangle it as a vendor extended expression, |
||
} | ||
|
||
if (AsTemplateArg && !IsPrimaryExpr) | ||
|
Uh oh!
There was an error while loading. Please reload this page.