Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 39 additions & 22 deletions clang/lib/Sema/HLSLExternalSemaSource.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -455,7 +455,7 @@ struct TemplateParameterListBuilder {
//
// BuiltinTypeMethodBuilder(Sema, RecordBuilder, "MethodName", ReturnType)
// .addParam("param_name", Type, InOutModifier)
// .callBuiltin("buildin_name", { BuiltinParams })
// .callBuiltin("builtin_name", BuiltinParams...)
// .finalizeMethod();
//
// The builder needs to have all of the method parameters before it can create
Expand All @@ -465,9 +465,9 @@ struct TemplateParameterListBuilder {
// referenced from the body building methods. Destructor or an explicit call to
// finalizeMethod() will complete the method definition.
//
// The callBuiltin helper method passes in the resource handle as the first
// argument of the builtin call. If this is not desired it takes a bool flag to
// disable this.
// The callBuiltin helper method accepts constants via `Expr *` or placeholder
// value arguments to indicate which function arguments to forward to the
// builtin.
//
// If the method that is being built has a non-void return type the
// finalizeMethod will create a return statent with the value of the last
Expand All @@ -489,6 +489,24 @@ struct BuiltinTypeMethodBuilder {
llvm::SmallVector<MethodParam> Params;
llvm::SmallVector<Stmt *> StmtsList;

// Argument placeholders, inspired by std::placeholder. These are the indices
// of arguments to forward to `callBuiltin`, and additionally `Handle` which
// refers to the resource handle.
enum class PlaceHolder { _0, _1, _2, _3, Handle = 127 };

Expr *convertPlaceholder(PlaceHolder PH) {
if (PH == PlaceHolder::Handle)
return getResourceHandleExpr();

ASTContext &AST = DeclBuilder.SemaRef.getASTContext();
ParmVarDecl *ParamDecl = Method->getParamDecl(static_cast<unsigned>(PH));
return DeclRefExpr::Create(
AST, NestedNameSpecifierLoc(), SourceLocation(), ParamDecl, false,
DeclarationNameInfo(ParamDecl->getDeclName(), SourceLocation()),
ParamDecl->getType(), VK_PRValue);
}
Expr *convertPlaceholder(Expr *E) { return E; }

public:
BuiltinTypeMethodBuilder(Sema &S, BuiltinTypeDeclBuilder &DB, StringRef Name,
QualType ReturnTy)
Expand All @@ -502,7 +520,10 @@ struct BuiltinTypeMethodBuilder {
HLSLParamModifierAttr::Spelling Modifier =
HLSLParamModifierAttr::Keyword_in) {
assert(Method == nullptr && "Cannot add param, method already created");
llvm_unreachable("not yet implemented");
const IdentifierInfo &II = DeclBuilder.SemaRef.getASTContext().Idents.get(
Name, tok::TokenKind::identifier);
Params.emplace_back(II, Ty, Modifier);
return *this;
}

private:
Expand Down Expand Up @@ -564,9 +585,10 @@ struct BuiltinTypeMethodBuilder {
OK_Ordinary);
}

BuiltinTypeMethodBuilder &
callBuiltin(StringRef BuiltinName, ArrayRef<Expr *> CallParms,
bool AddResourceHandleAsFirstArg = true) {
template <typename... Ts>
BuiltinTypeMethodBuilder &callBuiltin(StringRef BuiltinName, Ts... ArgSpecs) {
std::array<Expr *, sizeof...(ArgSpecs)> Args{
convertPlaceholder(std::forward<Ts>(ArgSpecs))...};

// The first statement added to a method or access to 'this` creates the
// declaration.
Expand All @@ -579,16 +601,9 @@ struct BuiltinTypeMethodBuilder {
AST, NestedNameSpecifierLoc(), SourceLocation(), FD, false,
FD->getNameInfo(), FD->getType(), VK_PRValue);

SmallVector<Expr *> NewCallParms;
if (AddResourceHandleAsFirstArg) {
NewCallParms.push_back(getResourceHandleExpr());
for (auto *P : CallParms)
NewCallParms.push_back(P);
}

Expr *Call = CallExpr::Create(
AST, DRE, AddResourceHandleAsFirstArg ? NewCallParms : CallParms,
FD->getReturnType(), VK_PRValue, SourceLocation(), FPOptionsOverride());
Expr *Call =
CallExpr::Create(AST, DRE, Args, FD->getReturnType(), VK_PRValue,
SourceLocation(), FPOptionsOverride());
StmtsList.push_back(Call);
return *this;
}
Expand Down Expand Up @@ -656,18 +671,20 @@ BuiltinTypeDeclBuilder::addSimpleTemplateParams(ArrayRef<StringRef> Names,
}

BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addIncrementCounterMethod() {
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
return BuiltinTypeMethodBuilder(SemaRef, *this, "IncrementCounter",
SemaRef.getASTContext().UnsignedIntTy)
.callBuiltin("__builtin_hlsl_buffer_update_counter",
{getConstantIntExpr(1)})
.callBuiltin("__builtin_hlsl_buffer_update_counter", PH::Handle,
getConstantIntExpr(1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How evil would it be to add a Expr *convertPlaceholder(int) that does the getConstantIntExpr for you, so this could be written as: .callBuiltin("__builtin_hlsl_buffer_update_conter", PH::Handle, 1)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels too magical to me (and also it introduces an annoying ambiguity with a literal zero - is it an int or a null Expr *?)

.finalizeMethod();
}

BuiltinTypeDeclBuilder &BuiltinTypeDeclBuilder::addDecrementCounterMethod() {
using PH = BuiltinTypeMethodBuilder::PlaceHolder;
return BuiltinTypeMethodBuilder(SemaRef, *this, "DecrementCounter",
SemaRef.getASTContext().UnsignedIntTy)
.callBuiltin("__builtin_hlsl_buffer_update_counter",
{getConstantIntExpr(-1)})
.callBuiltin("__builtin_hlsl_buffer_update_counter", PH::Handle,
getConstantIntExpr(-1))
.finalizeMethod();
}

Expand Down