Import Tint changes from Dawn
Changes:
- d3f2b788cf964497ed3f01ab19359e76fcc2fc06 [tint][ir] Add Block() method to Instruction by Ben Clayton <bclayton@google.com>
- 293b4a5fc74eb7ba720e50b6138b2765538ee6cb [tint][ir] from_program.cc: Rename current_flow_block_ by Ben Clayton <bclayton@google.com>
- 212959b7383a69d4df61a17bc5710396411d060c [ir] Change function return attributes to not be list. by dan sinclair <dsinclair@chromium.org>
- 0df9b0312c1d2744125d3ff96bfdb856a3ca87b8 [ir] Add binding point to global vars. by dan sinclair <dsinclair@chromium.org>
- 765d45f31c086762ba480e4f33b6532c4cafc85f [ir] Add parameter attributes. by dan sinclair <dsinclair@chromium.org>
GitOrigin-RevId: d3f2b788cf964497ed3f01ab19359e76fcc2fc06
Change-Id: Iab919cf6bc4e3b0c35f563b7a6301109935cc875
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/134884
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index bc74d5d..83fcbf5 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -1209,6 +1209,7 @@
sources = [
"ir/binary.cc",
"ir/binary.h",
+ "ir/binding_point.h",
"ir/bitcast.cc",
"ir/bitcast.h",
"ir/block.cc",
@@ -1253,6 +1254,7 @@
"ir/instruction.h",
"ir/load.cc",
"ir/load.h",
+ "ir/location.h",
"ir/loop.cc",
"ir/loop.h",
"ir/module.cc",
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 277d819..c20c850 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -716,6 +716,7 @@
list(APPEND TINT_LIB_SRCS
ir/binary.cc
ir/binary.h
+ ir/binding_point.h
ir/bitcast.cc
ir/bitcast.h
ir/block.cc
@@ -762,6 +763,7 @@
ir/instruction.h
ir/load.cc
ir/load.h
+ ir/location.h
ir/loop.cc
ir/loop.h
ir/module.cc
diff --git a/src/tint/ir/binding_point.h b/src/tint/ir/binding_point.h
new file mode 100644
index 0000000..9db225e
--- /dev/null
+++ b/src/tint/ir/binding_point.h
@@ -0,0 +1,32 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_BINDING_POINT_H_
+#define SRC_TINT_IR_BINDING_POINT_H_
+
+#include <cstdint>
+
+namespace tint::ir {
+
+/// Binding information
+struct BindingPoint {
+ /// The `@group` part of the binding point
+ uint32_t group = 0;
+ /// The `@binding` part of the binding point
+ uint32_t binding = 0;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_BINDING_POINT_H_
diff --git a/src/tint/ir/block.cc b/src/tint/ir/block.cc
index 2030c19..4da1287 100644
--- a/src/tint/ir/block.cc
+++ b/src/tint/ir/block.cc
@@ -22,4 +22,16 @@
Block::~Block() = default;
+void Block::AddInstruction(Instruction* inst) {
+ instructions_.Push(inst);
+ inst->SetBlock(this);
+}
+
+void Block::SetInstructions(utils::VectorRef<Instruction*> instructions) {
+ for (auto* i : instructions) {
+ i->SetBlock(this);
+ }
+ instructions_ = std::move(instructions);
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/block.h b/src/tint/ir/block.h
index d40002d..20a2da7 100644
--- a/src/tint/ir/block.h
+++ b/src/tint/ir/block.h
@@ -48,14 +48,14 @@
/// Sets the instructions in the block
/// @param instructions the instructions to set
- void SetInstructions(utils::VectorRef<const Instruction*> instructions) {
- instructions_ = std::move(instructions);
- }
+ void SetInstructions(utils::VectorRef<Instruction*> instructions);
/// @returns the instructions in the block
utils::VectorRef<const Instruction*> Instructions() const { return instructions_; }
- /// @returns the instructions in the block
- utils::Vector<const Instruction*, 16>& Instructions() { return instructions_; }
+
+ /// Adds the instruction to the end of the block
+ /// @param inst the instruction to add
+ void AddInstruction(Instruction* inst);
/// Sets the params to the block
/// @param params the params for the block
diff --git a/src/tint/ir/disassembler.cc b/src/tint/ir/disassembler.cc
index 75cc2aa..d8e472a 100644
--- a/src/tint/ir/disassembler.cc
+++ b/src/tint/ir/disassembler.cc
@@ -139,39 +139,119 @@
Indent() << "}" << std::endl;
}
+void Disassembler::EmitBindingPoint(BindingPoint p) {
+ out_ << "@binding_point(" << p.group << ", " << p.binding << ")";
+}
+
+void Disassembler::EmitLocation(Location loc) {
+ out_ << "@location(" << loc.value << ")";
+ if (loc.interpolation.has_value()) {
+ out_ << ", @interpolate(";
+ out_ << loc.interpolation->type;
+ if (loc.interpolation->sampling != builtin::InterpolationSampling::kUndefined) {
+ out_ << ", ";
+ out_ << loc.interpolation->sampling;
+ }
+ out_ << ")";
+ }
+}
+
+void Disassembler::EmitParamAttributes(const FunctionParam* p) {
+ if (!p->Invariant() && !p->Location().has_value() && !p->BindingPoint().has_value() &&
+ !p->Builtin().has_value()) {
+ return;
+ }
+
+ out_ << " [";
+
+ bool need_comma = false;
+ auto comma = [&]() {
+ if (need_comma) {
+ out_ << ", ";
+ }
+ };
+
+ if (p->Invariant()) {
+ comma();
+ out_ << "@invariant";
+ need_comma = true;
+ }
+ if (p->Location().has_value()) {
+ EmitLocation(p->Location().value());
+ need_comma = true;
+ }
+ if (p->BindingPoint().has_value()) {
+ comma();
+ EmitBindingPoint(p->BindingPoint().value());
+ need_comma = true;
+ }
+ if (p->Builtin().has_value()) {
+ comma();
+ out_ << "@" << p->Builtin().value();
+ need_comma = true;
+ }
+ out_ << "]";
+}
+
+void Disassembler::EmitReturnAttributes(const Function* func) {
+ if (!func->ReturnInvariant() && !func->ReturnLocation().has_value() &&
+ !func->ReturnBuiltin().has_value()) {
+ return;
+ }
+
+ out_ << " [";
+
+ bool need_comma = false;
+ auto comma = [&]() {
+ if (need_comma) {
+ out_ << ", ";
+ }
+ };
+ if (func->ReturnInvariant()) {
+ comma();
+ out_ << "@invariant";
+ need_comma = true;
+ }
+ if (func->ReturnLocation().has_value()) {
+ comma();
+ EmitLocation(func->ReturnLocation().value());
+ need_comma = true;
+ }
+ if (func->ReturnBuiltin().has_value()) {
+ comma();
+ out_ << "@" << func->ReturnBuiltin().value();
+ need_comma = true;
+ }
+ out_ << "]";
+}
+
void Disassembler::EmitFunction(const Function* func) {
in_function_ = true;
- Indent() << "%" << IdOf(func) << " = func(";
- for (auto* p : func->Params()) {
+ Indent() << "%" << IdOf(func) << " =";
+
+ if (func->Stage() != Function::PipelineStage::kUndefined) {
+ out_ << " @" << func->Stage();
+ }
+ if (func->WorkgroupSize()) {
+ auto arr = func->WorkgroupSize().value();
+ out_ << " @workgroup_size(" << arr[0] << ", " << arr[1] << ", " << arr[2] << ")";
+ }
+
+ out_ << " func(";
+
+ for (const auto* p : func->Params()) {
if (p != func->Params().Front()) {
out_ << ", ";
}
out_ << "%" << IdOf(p) << ":" << p->Type()->FriendlyName();
+
+ EmitParamAttributes(p);
}
out_ << "):" << func->ReturnType()->FriendlyName();
- if (func->Stage() != Function::PipelineStage::kUndefined) {
- out_ << " [@" << func->Stage();
+ EmitReturnAttributes(func);
- if (func->WorkgroupSize()) {
- auto arr = func->WorkgroupSize().value();
- out_ << " @workgroup_size(" << arr[0] << ", " << arr[1] << ", " << arr[2] << ")";
- }
-
- if (!func->ReturnAttributes().IsEmpty()) {
- out_ << " ra:";
-
- for (auto attr : func->ReturnAttributes()) {
- out_ << " @" << attr;
- if (attr == Function::ReturnAttribute::kLocation) {
- out_ << "(" << func->ReturnLocation().value() << ")";
- }
- }
- }
-
- out_ << "]";
- }
out_ << " -> %b" << IdOf(func->StartTarget()) << " {" << std::endl;
{
@@ -302,6 +382,11 @@
out_ << ", ";
EmitValue(v->Initializer());
}
+ if (v->BindingPoint().has_value()) {
+ out_ << " ";
+ EmitBindingPoint(v->BindingPoint().value());
+ }
+
out_ << std::endl;
},
[&](const ir::Branch* b) { EmitBranch(b); },
diff --git a/src/tint/ir/disassembler.h b/src/tint/ir/disassembler.h
index 06f5b08..9194942 100644
--- a/src/tint/ir/disassembler.h
+++ b/src/tint/ir/disassembler.h
@@ -59,6 +59,10 @@
void Walk(const Block* blk);
void WalkInternal(const Block* blk);
void EmitFunction(const Function* func);
+ void EmitParamAttributes(const FunctionParam* p);
+ void EmitReturnAttributes(const Function* func);
+ void EmitBindingPoint(BindingPoint p);
+ void EmitLocation(Location loc);
void EmitInstruction(const Instruction* inst);
void EmitValueWithType(const Value* val);
void EmitValue(const Value* val);
diff --git a/src/tint/ir/from_program.cc b/src/tint/ir/from_program.cc
index 20555d0..3dc52e1 100644
--- a/src/tint/ir/from_program.cc
+++ b/src/tint/ir/from_program.cc
@@ -43,6 +43,7 @@
#include "src/tint/ast/if_statement.h"
#include "src/tint/ast/increment_decrement_statement.h"
#include "src/tint/ast/int_literal_expression.h"
+#include "src/tint/ast/interpolate_attribute.h"
#include "src/tint/ast/invariant_attribute.h"
#include "src/tint/ast/let.h"
#include "src/tint/ast/literal_expression.h"
@@ -140,8 +141,8 @@
/// The stack of control blocks.
utils::Vector<Branch*, 8> control_stack_;
- /// The current flow block for expressions.
- Block* current_flow_block_ = nullptr;
+ /// The current block for expressions.
+ Block* current_block_ = nullptr;
/// The current function being processed.
Function* current_function_ = nullptr;
@@ -166,14 +167,14 @@
diagnostics_.add_error(tint::diag::System::IR, err, s);
}
- bool NeedBranch() { return current_flow_block_ && !current_flow_block_->HasBranchTarget(); }
+ bool NeedBranch() { return current_block_ && !current_block_->HasBranchTarget(); }
void SetBranch(Branch* br) {
- TINT_ASSERT(IR, current_flow_block_);
- TINT_ASSERT(IR, !current_flow_block_->HasBranchTarget());
+ TINT_ASSERT(IR, current_block_);
+ TINT_ASSERT(IR, !current_block_->HasBranchTarget());
- current_flow_block_->Instructions().Push(br);
- current_flow_block_ = nullptr;
+ current_block_->AddInstruction(br);
+ current_block_ = nullptr;
}
Branch* FindEnclosingControl(ControlFlags flags) {
@@ -207,7 +208,7 @@
[&](const ast::Variable* var) {
// Setup the current flow node to be the root block for the module. The builder
// will handle creating it if it doesn't exist already.
- TINT_SCOPED_ASSIGNMENT(current_flow_block_, builder_.CreateRootBlockIfNeeded());
+ TINT_SCOPED_ASSIGNMENT(current_block_, builder_.CreateRootBlockIfNeeded());
EmitVariable(var);
},
[&](const ast::Function* func) { EmitFunction(func); },
@@ -230,6 +231,24 @@
return ResultType{std::move(mod)};
}
+ builtin::Interpolation ExtractInterpolation(const ast::InterpolateAttribute* interp) {
+ auto type = program_->Sem()
+ .Get(interp->type)
+ ->As<sem::BuiltinEnumExpression<builtin::InterpolationType>>();
+ builtin::InterpolationType interpolation_type = type->Value();
+
+ builtin::InterpolationSampling interpolation_sampling =
+ builtin::InterpolationSampling::kUndefined;
+ if (interp->sampling) {
+ auto sampling = program_->Sem()
+ .Get(interp->sampling)
+ ->As<sem::BuiltinEnumExpression<builtin::InterpolationSampling>>();
+ interpolation_sampling = sampling->Value();
+ }
+
+ return builtin::Interpolation{interpolation_type, interpolation_sampling};
+ }
+
void EmitFunction(const ast::Function* ast_func) {
// The flow stack should have been emptied when the previous function finished building.
TINT_ASSERT(IR, control_stack_.IsEmpty());
@@ -265,16 +284,16 @@
}
}
- utils::Vector<Function::ReturnAttribute, 1> return_attributes;
+ // Note, interpolated is only valid when paired with Location, so it will only be set
+ // when the location is set.
+ std::optional<builtin::Interpolation> interpolation;
for (auto* attr : ast_func->return_type_attributes) {
tint::Switch(
attr, //
- [&](const ast::LocationAttribute*) {
- return_attributes.Push(Function::ReturnAttribute::kLocation);
+ [&](const ast::InterpolateAttribute* interp) {
+ interpolation = ExtractInterpolation(interp);
},
- [&](const ast::InvariantAttribute*) {
- return_attributes.Push(Function::ReturnAttribute::kInvariant);
- },
+ [&](const ast::InvariantAttribute*) { ir_func->SetReturnInvariant(true); },
[&](const ast::BuiltinAttribute* b) {
if (auto* ident_sem =
program_->Sem()
@@ -282,13 +301,13 @@
->As<sem::BuiltinEnumExpression<builtin::BuiltinValue>>()) {
switch (ident_sem->Value()) {
case builtin::BuiltinValue::kPosition:
- return_attributes.Push(Function::ReturnAttribute::kPosition);
+ ir_func->SetReturnBuiltin(Function::ReturnBuiltin::kPosition);
break;
case builtin::BuiltinValue::kFragDepth:
- return_attributes.Push(Function::ReturnAttribute::kFragDepth);
+ ir_func->SetReturnBuiltin(Function::ReturnBuiltin::kFragDepth);
break;
case builtin::BuiltinValue::kSampleMask:
- return_attributes.Push(Function::ReturnAttribute::kSampleMask);
+ ir_func->SetReturnBuiltin(Function::ReturnBuiltin::kSampleMask);
break;
default:
TINT_ICE(IR, diagnostics_)
@@ -302,26 +321,98 @@
}
});
}
- ir_func->SetReturnAttributes(return_attributes);
+ if (sem->ReturnLocation().has_value()) {
+ ir_func->SetReturnLocation(sem->ReturnLocation().value(), interpolation);
+ }
}
- ir_func->SetReturnLocation(sem->ReturnLocation());
scopes_.Push();
TINT_DEFER(scopes_.Pop());
utils::Vector<FunctionParam*, 1> params;
for (auto* p : ast_func->params) {
- const auto* param_sem = program_->Sem().Get(p);
+ const auto* param_sem = program_->Sem().Get(p)->As<sem::Parameter>();
auto* ty = param_sem->Type()->Clone(clone_ctx_.type_ctx);
auto* param = builder_.FunctionParam(ty);
+ // Note, interpolated is only valid when paired with Location, so it will only be set
+ // when the location is set.
+ std::optional<builtin::Interpolation> interpolation;
+ for (auto* attr : p->attributes) {
+ tint::Switch(
+ attr, //
+ [&](const ast::InterpolateAttribute* interp) {
+ interpolation = ExtractInterpolation(interp);
+ },
+ [&](const ast::InvariantAttribute*) { param->SetInvariant(true); },
+ [&](const ast::BuiltinAttribute* b) {
+ if (auto* ident_sem =
+ program_->Sem()
+ .Get(b)
+ ->As<sem::BuiltinEnumExpression<builtin::BuiltinValue>>()) {
+ switch (ident_sem->Value()) {
+ case builtin::BuiltinValue::kVertexIndex:
+ param->SetBuiltin(FunctionParam::Builtin::kVertexIndex);
+ break;
+ case builtin::BuiltinValue::kInstanceIndex:
+ param->SetBuiltin(FunctionParam::Builtin::kInstanceIndex);
+ break;
+ case builtin::BuiltinValue::kPosition:
+ param->SetBuiltin(FunctionParam::Builtin::kPosition);
+ break;
+ case builtin::BuiltinValue::kFrontFacing:
+ param->SetBuiltin(FunctionParam::Builtin::kFrontFacing);
+ break;
+ case builtin::BuiltinValue::kLocalInvocationId:
+ param->SetBuiltin(FunctionParam::Builtin::kLocalInvocationId);
+ break;
+ case builtin::BuiltinValue::kLocalInvocationIndex:
+ param->SetBuiltin(
+ FunctionParam::Builtin::kLocalInvocationIndex);
+ break;
+ case builtin::BuiltinValue::kGlobalInvocationId:
+ param->SetBuiltin(FunctionParam::Builtin::kGlobalInvocationId);
+ break;
+ case builtin::BuiltinValue::kWorkgroupId:
+ param->SetBuiltin(FunctionParam::Builtin::kWorkgroupId);
+ break;
+ case builtin::BuiltinValue::kNumWorkgroups:
+ param->SetBuiltin(FunctionParam::Builtin::kNumWorkgroups);
+ break;
+ case builtin::BuiltinValue::kSampleIndex:
+ param->SetBuiltin(FunctionParam::Builtin::kSampleIndex);
+ break;
+ case builtin::BuiltinValue::kSampleMask:
+ param->SetBuiltin(FunctionParam::Builtin::kSampleMask);
+ break;
+ default:
+ TINT_ICE(IR, diagnostics_)
+ << "Unknown builtin value in parameter attributes "
+ << ident_sem->Value();
+ return;
+ }
+ } else {
+ TINT_ICE(IR, diagnostics_) << "Builtin attribute sem invalid";
+ return;
+ }
+ });
+
+ if (param_sem->Location().has_value()) {
+ param->SetLocation(param_sem->Location().value(), interpolation);
+ }
+ if (param_sem->BindingPoint().has_value()) {
+ param->SetBindingPoint(param_sem->BindingPoint()->group,
+ param_sem->BindingPoint()->binding);
+ }
+ }
+
scopes_.Set(p->name->symbol, param);
builder_.ir.SetName(param, p->name->symbol.NameView());
params.Push(param);
}
ir_func->SetParams(params);
- current_flow_block_ = ir_func->StartTarget();
+ current_block_ = ir_func->StartTarget();
EmitBlock(ast_func->body);
// If the branch target has already been set then a `return` was called. Only set in
@@ -331,7 +422,7 @@
}
TINT_ASSERT(IR, control_stack_.IsEmpty());
- current_flow_block_ = nullptr;
+ current_block_ = nullptr;
current_function_ = nullptr;
}
@@ -396,7 +487,7 @@
return;
}
auto store = builder_.Store(lhs.Get(), rhs.Get());
- current_flow_block_->Instructions().Push(store);
+ current_block_->AddInstruction(store);
}
void EmitIncrementDecrement(const ast::IncrementDecrementStatement* stmt) {
@@ -407,7 +498,7 @@
// Load from the LHS.
auto* lhs_value = builder_.Load(lhs.Get());
- current_flow_block_->Instructions().Push(lhs_value);
+ current_block_->AddInstruction(lhs_value);
auto* ty = lhs_value->Type();
@@ -420,10 +511,10 @@
} else {
inst = builder_.Subtract(ty, lhs_value, rhs);
}
- current_flow_block_->Instructions().Push(inst);
+ current_block_->AddInstruction(inst);
auto store = builder_.Store(lhs.Get(), inst);
- current_flow_block_->Instructions().Push(store);
+ current_block_->AddInstruction(store);
}
void EmitCompoundAssignment(const ast::CompoundAssignmentStatement* stmt) {
@@ -439,7 +530,7 @@
// Load from the LHS.
auto* lhs_value = builder_.Load(lhs.Get());
- current_flow_block_->Instructions().Push(lhs_value);
+ current_block_->AddInstruction(lhs_value);
auto* ty = lhs_value->Type();
@@ -489,10 +580,10 @@
TINT_ICE(IR, diagnostics_) << "missing binary operand type";
return;
}
- current_flow_block_->Instructions().Push(inst);
+ current_block_->AddInstruction(inst);
auto store = builder_.Store(lhs.Get(), inst);
- current_flow_block_->Instructions().Push(store);
+ current_block_->AddInstruction(store);
}
void EmitBlock(const ast::BlockStatement* block) {
@@ -512,12 +603,12 @@
return;
}
auto* if_inst = builder_.CreateIf(reg.Get());
- current_flow_block_->Instructions().Push(if_inst);
+ current_block_->AddInstruction(if_inst);
{
ControlStackScope scope(this, if_inst);
- current_flow_block_ = if_inst->True();
+ current_block_ = if_inst->True();
EmitBlock(stmt->body);
// If the true branch did not execute control flow, then go to the Merge().target
@@ -525,7 +616,7 @@
SetBranch(builder_.ExitIf(if_inst));
}
- current_flow_block_ = if_inst->False();
+ current_block_ = if_inst->False();
if (stmt->else_statement) {
EmitStatement(stmt->else_statement);
}
@@ -535,23 +626,23 @@
SetBranch(builder_.ExitIf(if_inst));
}
}
- current_flow_block_ = nullptr;
+ current_block_ = nullptr;
// If both branches went somewhere, then they both returned, continued or broke. So,
// there is no need for the if merge-block and there is nothing to branch to the merge
// block anyway.
if (IsConnected(if_inst->Merge())) {
- current_flow_block_ = if_inst->Merge();
+ current_block_ = if_inst->Merge();
}
}
void EmitLoop(const ast::LoopStatement* stmt) {
auto* loop_inst = builder_.CreateLoop();
- current_flow_block_->Instructions().Push(loop_inst);
+ current_block_->AddInstruction(loop_inst);
{
ControlStackScope scope(this, loop_inst);
- current_flow_block_ = loop_inst->Start();
+ current_block_ = loop_inst->Start();
// The loop doesn't use EmitBlock because it needs the scope stack to not get popped
// until after the continuing block.
@@ -569,7 +660,7 @@
// continue so we have to set the current block and then emit the branch if needed
// below otherwise empty continuing blocks will fail to branch back to the start
// block.
- current_flow_block_ = loop_inst->Continuing();
+ current_block_ = loop_inst->Continuing();
if (stmt->continuing) {
EmitBlock(stmt->continuing);
}
@@ -583,24 +674,24 @@
// The loop merge can get disconnected if the loop returns directly, or the continuing
// target branches, eventually, to the merge, but nothing branched to the
// Continuing() block.
- current_flow_block_ = loop_inst->Merge();
+ current_block_ = loop_inst->Merge();
if (!IsConnected(loop_inst->Merge())) {
- current_flow_block_ = nullptr;
+ current_block_ = nullptr;
}
}
void EmitWhile(const ast::WhileStatement* stmt) {
auto* loop_inst = builder_.CreateLoop();
- current_flow_block_->Instructions().Push(loop_inst);
+ current_block_->AddInstruction(loop_inst);
// Continue is always empty, just go back to the start
- current_flow_block_ = loop_inst->Continuing();
+ current_block_ = loop_inst->Continuing();
SetBranch(builder_.NextIteration(loop_inst));
{
ControlStackScope scope(this, loop_inst);
- current_flow_block_ = loop_inst->Start();
+ current_block_ = loop_inst->Start();
// Emit the while condition into the Start().target of the loop
auto reg = EmitExpression(stmt->condition);
@@ -610,15 +701,15 @@
// Create an `if (cond) {} else {break;}` control flow
auto* if_inst = builder_.CreateIf(reg.Get());
- current_flow_block_->Instructions().Push(if_inst);
+ current_block_->AddInstruction(if_inst);
- current_flow_block_ = if_inst->True();
+ current_block_ = if_inst->True();
SetBranch(builder_.ExitIf(if_inst));
- current_flow_block_ = if_inst->False();
+ current_block_ = if_inst->False();
SetBranch(builder_.ExitLoop(loop_inst));
- current_flow_block_ = if_inst->Merge();
+ current_block_ = if_inst->Merge();
EmitBlock(stmt->body);
if (NeedBranch()) {
@@ -627,12 +718,12 @@
}
// The while loop always has a path to the Merge().target as the break statement comes
// before anything inside the loop.
- current_flow_block_ = loop_inst->Merge();
+ current_block_ = loop_inst->Merge();
}
void EmitForLoop(const ast::ForLoopStatement* stmt) {
auto* loop_inst = builder_.CreateLoop();
- current_flow_block_->Instructions().Push(loop_inst);
+ current_block_->AddInstruction(loop_inst);
// Make sure the initializer ends up in a contained scope
scopes_.Push();
@@ -646,7 +737,7 @@
{
ControlStackScope scope(this, loop_inst);
- current_flow_block_ = loop_inst->Start();
+ current_block_ = loop_inst->Start();
if (stmt->condition) {
// Emit the condition into the target target of the loop
@@ -657,15 +748,15 @@
// Create an `if (cond) {} else {break;}` control flow
auto* if_inst = builder_.CreateIf(reg.Get());
- current_flow_block_->Instructions().Push(if_inst);
+ current_block_->AddInstruction(if_inst);
- current_flow_block_ = if_inst->True();
+ current_block_ = if_inst->True();
SetBranch(builder_.ExitIf(if_inst));
- current_flow_block_ = if_inst->False();
+ current_block_ = if_inst->False();
SetBranch(builder_.ExitLoop(loop_inst));
- current_flow_block_ = if_inst->Merge();
+ current_block_ = if_inst->Merge();
}
EmitBlock(stmt->body);
@@ -674,7 +765,7 @@
}
if (stmt->continuing) {
- current_flow_block_ = loop_inst->Continuing();
+ current_block_ = loop_inst->Continuing();
EmitStatement(stmt->continuing);
SetBranch(builder_.NextIteration(loop_inst));
}
@@ -682,7 +773,7 @@
// The while loop always has a path to the Merge().target as the break statement comes
// before anything inside the loop.
- current_flow_block_ = loop_inst->Merge();
+ current_block_ = loop_inst->Merge();
}
void EmitSwitch(const ast::SwitchStatement* stmt) {
@@ -692,7 +783,7 @@
return;
}
auto* switch_inst = builder_.CreateSwitch(reg.Get());
- current_flow_block_->Instructions().Push(switch_inst);
+ current_block_->AddInstruction(switch_inst);
{
ControlStackScope scope(this, switch_inst);
@@ -708,7 +799,7 @@
}
}
- current_flow_block_ = builder_.CreateCase(switch_inst, selectors);
+ current_block_ = builder_.CreateCase(switch_inst, selectors);
EmitBlock(c->Body()->Declaration());
if (NeedBranch()) {
@@ -716,10 +807,10 @@
}
}
}
- current_flow_block_ = nullptr;
+ current_block_ = nullptr;
if (IsConnected(switch_inst->Merge())) {
- current_flow_block_ = switch_inst->Merge();
+ current_block_ = switch_inst->Merge();
}
}
@@ -765,7 +856,7 @@
// figuring out the multi-level exit that is triggered.
void EmitDiscard(const ast::DiscardStatement*) {
auto* inst = builder_.Discard();
- current_flow_block_->Instructions().Push(inst);
+ current_block_->AddInstruction(inst);
}
void EmitBreakIf(const ast::BreakIfStatement* stmt) {
@@ -823,7 +914,7 @@
// If this expression maps to sem::Load, insert a load instruction to get the result.
if (result && sem->Is<sem::Load>()) {
auto* load = builder_.Load(result.Get());
- current_flow_block_->Instructions().Push(load);
+ current_block_->AddInstruction(load);
return load;
}
@@ -849,7 +940,12 @@
}
val->SetInitializer(init.Get());
}
- current_flow_block_->Instructions().Push(val);
+ current_block_->AddInstruction(val);
+
+ if (auto* gv = sem->As<sem::GlobalVariable>(); gv && var->HasBindingPoint()) {
+ val->SetBindingPoint(gv->BindingPoint().value().group,
+ gv->BindingPoint().value().binding);
+ }
// Store the declaration so we can get the instruction to store too
scopes_.Set(v->name->symbol, val);
@@ -916,7 +1012,7 @@
break;
}
- current_flow_block_->Instructions().Push(inst);
+ current_block_->AddInstruction(inst);
return inst;
}
@@ -940,7 +1036,7 @@
}
auto* if_inst = builder_.CreateIf(lhs.Get());
- current_flow_block_->Instructions().Push(if_inst);
+ current_block_->AddInstruction(if_inst);
auto* result = builder_.BlockParam(builder_.ir.Types().bool_());
if_inst->Merge()->SetParams(utils::Vector{result});
@@ -957,17 +1053,17 @@
if (expr->op == ast::BinaryOp::kLogicalAnd) {
// If the lhs is false, then that is the result we want to pass to the merge
// block as our argument
- current_flow_block_ = if_inst->False();
+ current_block_ = if_inst->False();
SetBranch(builder_.ExitIf(if_inst, std::move(alt_args)));
- current_flow_block_ = if_inst->True();
+ current_block_ = if_inst->True();
} else {
// If the lhs is true, then that is the result we want to pass to the merge
// block as our argument
- current_flow_block_ = if_inst->True();
+ current_block_ = if_inst->True();
SetBranch(builder_.ExitIf(if_inst, std::move(alt_args)));
- current_flow_block_ = if_inst->False();
+ current_block_ = if_inst->False();
}
rhs = EmitExpression(expr->rhs);
@@ -979,7 +1075,7 @@
SetBranch(builder_.ExitIf(if_inst, std::move(args)));
}
- current_flow_block_ = if_inst->Merge();
+ current_block_ = if_inst->Merge();
return result;
}
@@ -1061,7 +1157,7 @@
return utils::Failure;
}
- current_flow_block_->Instructions().Push(inst);
+ current_block_->AddInstruction(inst);
return inst;
}
@@ -1075,7 +1171,7 @@
auto* ty = sem->Type()->Clone(clone_ctx_.type_ctx);
auto* inst = builder_.Bitcast(ty, val.Get());
- current_flow_block_->Instructions().Push(inst);
+ current_block_->AddInstruction(inst);
return inst;
}
@@ -1139,7 +1235,7 @@
if (inst == nullptr) {
return utils::Failure;
}
- current_flow_block_->Instructions().Push(inst);
+ current_block_->AddInstruction(inst);
return inst;
}
diff --git a/src/tint/ir/from_program_binary_test.cc b/src/tint/ir/from_program_binary_test.cc
index 8cc5604..5f7bcb2 100644
--- a/src/tint/ir/from_program_binary_test.cc
+++ b/src/tint/ir/from_program_binary_test.cc
@@ -39,7 +39,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = add %3, 4u
@@ -62,7 +62,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = add %3, 1u
@@ -86,7 +86,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = add %3, 1u
@@ -110,7 +110,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = sub %3, 4u
@@ -133,7 +133,7 @@
%v1:ptr<private, i32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:i32 = load %v1
%4:i32 = sub %3, 1i
@@ -157,7 +157,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = sub %3, 1u
@@ -181,7 +181,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = mul %3, 4u
@@ -204,7 +204,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = mul %3, 1u
@@ -228,7 +228,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = div %3, 4u
@@ -251,7 +251,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = div %3, 1u
@@ -275,7 +275,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = mod %3, 4u
@@ -298,7 +298,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = mod %3, 1u
@@ -322,7 +322,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = and %3, 4u
@@ -345,7 +345,7 @@
%v1:ptr<private, bool, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:bool = load %v1
%4:bool = and %3, false
@@ -369,7 +369,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = or %3, 4u
@@ -392,7 +392,7 @@
%v1:ptr<private, bool, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:bool = load %v1
%4:bool = or %3, false
@@ -416,7 +416,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = xor %3, 4u
@@ -439,7 +439,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = xor %3, 1u
@@ -463,7 +463,7 @@
ret true
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:bool = call %my_func
if %3 [t: %b3, f: %b4, m: %b5]
@@ -515,7 +515,7 @@
ret true
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:bool = call %my_func
if %3 [t: %b3, f: %b4, m: %b5]
@@ -567,7 +567,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:bool = eq %3, 4u
@@ -590,7 +590,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:bool = neq %3, 4u
@@ -613,7 +613,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:bool = lt %3, 4u
@@ -636,7 +636,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:bool = gt %3, 4u
@@ -659,7 +659,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:bool = lte %3, 4u
@@ -682,7 +682,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:bool = gte %3, 4u
@@ -705,7 +705,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = shiftl %3, 4u
@@ -728,7 +728,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = shiftl %3, 1u
@@ -752,7 +752,7 @@
ret 0u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = shiftr %3, 4u
@@ -775,7 +775,7 @@
%v1:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = load %v1
%4:u32 = shiftr %3, 1u
@@ -801,7 +801,7 @@
ret 0.0f
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:f32 = call %my_func
%4:bool = lt %3, 2.0f
@@ -845,7 +845,7 @@
ret true
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%tint_symbol:bool = call %my_func, false
ret
diff --git a/src/tint/ir/from_program_builtin_test.cc b/src/tint/ir/from_program_builtin_test.cc
index acdbc8a..4d21b48 100644
--- a/src/tint/ir/from_program_builtin_test.cc
+++ b/src/tint/ir/from_program_builtin_test.cc
@@ -39,7 +39,7 @@
%i:ptr<private, f32, read_write> = var, 1.0f
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:f32 = load %i
%tint_symbol:f32 = asin %3
diff --git a/src/tint/ir/from_program_call_test.cc b/src/tint/ir/from_program_call_test.cc
index 155e42c..d305855 100644
--- a/src/tint/ir/from_program_call_test.cc
+++ b/src/tint/ir/from_program_call_test.cc
@@ -40,7 +40,7 @@
ret 0.0f
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:f32 = call %my_func
%tint_symbol:f32 = bitcast %3
@@ -60,7 +60,7 @@
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m.Get()), R"(%test_function = func():void [@fragment] -> %b1 {
+ EXPECT_EQ(Disassemble(m.Get()), R"(%test_function = @fragment func():void -> %b1 {
%b1 = block {
discard
ret
@@ -82,7 +82,7 @@
ret
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%4:void = call %my_func, 6.0f
ret
@@ -104,7 +104,7 @@
%i:ptr<private, i32, read_write> = var, 1i
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:i32 = load %i
%tint_symbol:f32 = convert i32, %3
@@ -142,7 +142,7 @@
%i:ptr<private, f32, read_write> = var, 1.0f
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:f32 = load %i
%tint_symbol:vec3<f32> = construct 2.0f, 3.0f, %3
diff --git a/src/tint/ir/from_program_function_test.cc b/src/tint/ir/from_program_function_test.cc
index 1be388a..57e78a3 100644
--- a/src/tint/ir/from_program_function_test.cc
+++ b/src/tint/ir/from_program_function_test.cc
@@ -34,7 +34,7 @@
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m.Get()), R"(%test = func():vec4<f32> [@vertex ra: @position] -> %b1 {
+ EXPECT_EQ(Disassemble(m.Get()), R"(%test = @vertex func():vec4<f32> [@position] -> %b1 {
%b1 = block {
ret vec4<f32> 0.0f
}
@@ -49,7 +49,7 @@
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m.Get()), R"(%test = func():void [@fragment] -> %b1 {
+ EXPECT_EQ(Disassemble(m.Get()), R"(%test = @fragment func():void -> %b1 {
%b1 = block {
ret
}
@@ -65,7 +65,7 @@
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
EXPECT_EQ(Disassemble(m.Get()),
- R"(%test = func():void [@compute @workgroup_size(8, 4, 2)] -> %b1 {
+ R"(%test = @compute @workgroup_size(8, 4, 2) func():void -> %b1 {
%b1 = block {
ret
}
@@ -96,7 +96,7 @@
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m.Get()), R"(%test = func():vec4<f32> [@vertex ra: @position] -> %b1 {
+ EXPECT_EQ(Disassemble(m.Get()), R"(%test = @vertex func():vec4<f32> [@position] -> %b1 {
%b1 = block {
ret vec4<f32> 1.0f, 2.0f, 3.0f, 4.0f
}
@@ -113,7 +113,7 @@
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
EXPECT_EQ(Disassemble(m.Get()),
- R"(%test = func():vec4<f32> [@vertex ra: @position @invariant] -> %b1 {
+ R"(%test = @vertex func():vec4<f32> [@invariant, @position] -> %b1 {
%b1 = block {
ret vec4<f32> 1.0f, 2.0f, 3.0f, 4.0f
}
@@ -129,7 +129,26 @@
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
EXPECT_EQ(Disassemble(m.Get()),
- R"(%test = func():vec4<f32> [@fragment ra: @location(1)] -> %b1 {
+ R"(%test = @fragment func():vec4<f32> [@location(1)] -> %b1 {
+ %b1 = block {
+ ret vec4<f32> 1.0f, 2.0f, 3.0f, 4.0f
+ }
+}
+)");
+}
+
+TEST_F(IR_BuilderImplTest, EmitFunction_ReturnLocation_Interpolate) {
+ Func("test", utils::Empty, ty.vec4<f32>(), utils::Vector{Return(vec4<f32>(1_f, 2_f, 3_f, 4_f))},
+ utils::Vector{Stage(ast::PipelineStage::kFragment)},
+ utils::Vector{Location(1_i), Interpolate(builtin::InterpolationType::kLinear,
+ builtin::InterpolationSampling::kCentroid)});
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(
+ Disassemble(m.Get()),
+ R"(%test = @fragment func():vec4<f32> [@location(1), @interpolate(linear, centroid)] -> %b1 {
%b1 = block {
ret vec4<f32> 1.0f, 2.0f, 3.0f, 4.0f
}
@@ -145,7 +164,7 @@
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m.Get()), R"(%test = func():f32 [@fragment ra: @frag_depth] -> %b1 {
+ EXPECT_EQ(Disassemble(m.Get()), R"(%test = @fragment func():f32 [@frag_depth] -> %b1 {
%b1 = block {
ret 1.0f
}
@@ -161,7 +180,7 @@
auto m = Build();
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
- EXPECT_EQ(Disassemble(m.Get()), R"(%test = func():u32 [@fragment ra: @sample_mask] -> %b1 {
+ EXPECT_EQ(Disassemble(m.Get()), R"(%test = @fragment func():u32 [@sample_mask] -> %b1 {
%b1 = block {
ret 1u
}
diff --git a/src/tint/ir/from_program_store_test.cc b/src/tint/ir/from_program_store_test.cc
index 38efea0..20ea290 100644
--- a/src/tint/ir/from_program_store_test.cc
+++ b/src/tint/ir/from_program_store_test.cc
@@ -40,7 +40,7 @@
%a:ptr<private, u32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
store %a, 4u
ret
diff --git a/src/tint/ir/from_program_test.cc b/src/tint/ir/from_program_test.cc
index f9be668..8f5348b 100644
--- a/src/tint/ir/from_program_test.cc
+++ b/src/tint/ir/from_program_test.cc
@@ -144,7 +144,7 @@
EXPECT_EQ(2u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
if true [t: %b2, f: %b3, m: %b4]
# True block
@@ -184,7 +184,7 @@
EXPECT_EQ(1u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
if true [t: %b2, f: %b3, m: %b4]
# True block
@@ -224,7 +224,7 @@
EXPECT_EQ(1u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
if true [t: %b2, f: %b3, m: %b4]
# True block
@@ -264,7 +264,7 @@
EXPECT_EQ(0u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
if true [t: %b2, f: %b3]
# True block
@@ -298,7 +298,7 @@
ASSERT_NE(loop_flow, nullptr);
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
if true [t: %b2, f: %b3, m: %b4]
# True block
@@ -347,7 +347,7 @@
EXPECT_EQ(1u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, m: %b3]
%b2 = block {
@@ -387,7 +387,7 @@
EXPECT_EQ(1u, if_flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, c: %b3, m: %b4]
%b2 = block {
@@ -442,7 +442,7 @@
EXPECT_EQ(1u, loop_flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, c: %b3, m: %b4]
%b2 = block {
@@ -475,7 +475,7 @@
auto m = res.Move();
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, c: %b3, m: %b4]
%b2 = block {
@@ -519,7 +519,7 @@
EXPECT_EQ(1u, if_flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, c: %b3]
%b2 = block {
@@ -568,7 +568,7 @@
EXPECT_EQ(0u, loop_flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2]
%b2 = block {
@@ -606,7 +606,7 @@
EXPECT_EQ(0u, loop_flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2]
%b2 = block {
@@ -640,7 +640,7 @@
EXPECT_EQ(0u, if_flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, m: %b3]
%b2 = block {
@@ -685,7 +685,7 @@
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
EXPECT_EQ(Disassemble(m.Get()),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, c: %b3, m: %b4]
%b2 = block {
@@ -813,7 +813,7 @@
EXPECT_EQ(1u, if_flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, c: %b3, m: %b4]
%b2 = block {
@@ -874,7 +874,7 @@
EXPECT_EQ(1u, if_flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, c: %b3, m: %b4]
%b2 = block {
@@ -967,7 +967,7 @@
EXPECT_EQ(1u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
loop [s: %b2, m: %b3]
%b2 = block {
@@ -1021,7 +1021,7 @@
EXPECT_EQ(3u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
switch 1i [c: (0i, %b2), c: (1i, %b3), c: (default, %b4), m: %b5]
# Case block
@@ -1082,7 +1082,7 @@
EXPECT_EQ(1u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
switch 1i [c: (0i 1i default, %b2), m: %b3]
# Case block
@@ -1121,7 +1121,7 @@
EXPECT_EQ(1u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
switch 1i [c: (default, %b2), m: %b3]
# Case block
@@ -1169,7 +1169,7 @@
// This is 1 because the if is dead-code eliminated and the return doesn't happen.
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
switch 1i [c: (0i, %b2), c: (default, %b3), m: %b4]
# Case block
@@ -1224,7 +1224,7 @@
EXPECT_EQ(0u, flow->Merge()->InboundBranches().Length());
EXPECT_EQ(Disassemble(m),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
switch 1i [c: (0i, %b2), c: (default, %b3)]
# Case block
@@ -1255,7 +1255,7 @@
ret 1i
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:i32 = call %b
ret
@@ -1264,5 +1264,85 @@
)");
}
+TEST_F(IR_BuilderImplTest, Func_WithParam_WithAttribute_Invariant) {
+ Func(
+ "f",
+ utils::Vector{Param("a", ty.vec4<f32>(),
+ utils::Vector{Invariant(), Builtin(builtin::BuiltinValue::kPosition)})},
+ ty.vec4<f32>(), utils::Vector{Return("a")},
+ utils::Vector{Stage(ast::PipelineStage::kFragment)}, utils::Vector{Location(1_i)});
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(
+ Disassemble(m.Get()),
+ R"(%f = @fragment func(%a:vec4<f32> [@invariant, @position]):vec4<f32> [@location(1)] -> %b1 {
+ %b1 = block {
+ ret %a
+ }
+}
+)");
+}
+
+TEST_F(IR_BuilderImplTest, Func_WithParam_WithAttribute_Location) {
+ Func("f", utils::Vector{Param("a", ty.f32(), utils::Vector{Location(2_i)})}, ty.f32(),
+ utils::Vector{Return("a")}, utils::Vector{Stage(ast::PipelineStage::kFragment)},
+ utils::Vector{Location(1_i)});
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()),
+ R"(%f = @fragment func(%a:f32 [@location(2)]):f32 [@location(1)] -> %b1 {
+ %b1 = block {
+ ret %a
+ }
+}
+)");
+}
+
+TEST_F(IR_BuilderImplTest, Func_WithParam_WithAttribute_Location_WithInterpolation_LinearCentroid) {
+ Func("f",
+ utils::Vector{Param(
+ "a", ty.f32(),
+ utils::Vector{Location(2_i), Interpolate(builtin::InterpolationType::kLinear,
+ builtin::InterpolationSampling::kCentroid)})},
+ ty.f32(), utils::Vector{Return("a")}, utils::Vector{Stage(ast::PipelineStage::kFragment)},
+ utils::Vector{Location(1_i)});
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(
+ Disassemble(m.Get()),
+ R"(%f = @fragment func(%a:f32 [@location(2), @interpolate(linear, centroid)]):f32 [@location(1)] -> %b1 {
+ %b1 = block {
+ ret %a
+ }
+}
+)");
+}
+
+TEST_F(IR_BuilderImplTest, Func_WithParam_WithAttribute_Location_WithInterpolation_Flat) {
+ Func("f",
+ utils::Vector{
+ Param("a", ty.f32(),
+ utils::Vector{Location(2_i), Interpolate(builtin::InterpolationType::kFlat)})},
+ ty.f32(), utils::Vector{Return("a")}, utils::Vector{Stage(ast::PipelineStage::kFragment)},
+ utils::Vector{Location(1_i)});
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(
+ Disassemble(m.Get()),
+ R"(%f = @fragment func(%a:f32 [@location(2), @interpolate(flat)]):f32 [@location(1)] -> %b1 {
+ %b1 = block {
+ ret %a
+ }
+}
+)");
+}
+
} // namespace
} // namespace tint::ir
diff --git a/src/tint/ir/from_program_unary_test.cc b/src/tint/ir/from_program_unary_test.cc
index bb58c02..b83e5d5 100644
--- a/src/tint/ir/from_program_unary_test.cc
+++ b/src/tint/ir/from_program_unary_test.cc
@@ -39,7 +39,7 @@
ret false
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:bool = call %my_func
%tint_symbol:bool = eq %3, false
@@ -62,7 +62,7 @@
ret 1u
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:u32 = call %my_func
%tint_symbol:u32 = complement %3
@@ -85,7 +85,7 @@
ret 1i
}
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
%3:i32 = call %my_func
%tint_symbol:i32 = negation %3
@@ -109,7 +109,7 @@
%v2:ptr<private, i32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
ret
}
@@ -133,7 +133,7 @@
%v3:ptr<private, i32, read_write> = var
}
-%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b2 {
+%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b2 {
%b2 = block {
store %v3, 42i
ret
diff --git a/src/tint/ir/from_program_var_test.cc b/src/tint/ir/from_program_var_test.cc
index c533738..91b8b8f 100644
--- a/src/tint/ir/from_program_var_test.cc
+++ b/src/tint/ir/from_program_var_test.cc
@@ -55,6 +55,21 @@
)");
}
+TEST_F(IR_BuilderImplTest, Emit_GlobalVar_GroupBinding) {
+ GlobalVar("a", ty.u32(), builtin::AddressSpace::kStorage,
+ utils::Vector{Group(2_u), Binding(3_u)});
+
+ auto m = Build();
+ ASSERT_TRUE(m) << (!m ? m.Failure() : "");
+
+ EXPECT_EQ(Disassemble(m.Get()), R"(# Root block
+%b1 = block {
+ %a:ptr<storage, u32, read> = var @binding_point(2, 3)
+}
+
+)");
+}
+
TEST_F(IR_BuilderImplTest, Emit_Var_NoInit) {
auto* a = Var("a", ty.u32(), builtin::AddressSpace::kFunction);
WrapInFunction(a);
@@ -63,7 +78,7 @@
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
EXPECT_EQ(Disassemble(m.Get()),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
%a:ptr<function, u32, read_write> = var
ret
@@ -81,7 +96,7 @@
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
EXPECT_EQ(Disassemble(m.Get()),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
%a:ptr<function, u32, read_write> = var, 2u
ret
@@ -99,7 +114,7 @@
ASSERT_TRUE(m) << (!m ? m.Failure() : "");
EXPECT_EQ(Disassemble(m.Get()),
- R"(%test_function = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+ R"(%test_function = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
%a:ptr<function, u32, read_write> = var
%3:u32 = load %a
diff --git a/src/tint/ir/function.cc b/src/tint/ir/function.cc
index 4e8ea4c..3769d4f 100644
--- a/src/tint/ir/function.cc
+++ b/src/tint/ir/function.cc
@@ -21,7 +21,9 @@
Function::Function(const type::Type* rt,
PipelineStage stage,
std::optional<std::array<uint32_t, 3>> wg_size)
- : Base(), return_type_(rt), pipeline_stage_(stage), workgroup_size_(wg_size) {}
+ : Base(), pipeline_stage_(stage), workgroup_size_(wg_size) {
+ return_.type = rt;
+}
Function::~Function() = default;
@@ -39,20 +41,14 @@
return out << "<unknown>";
}
-utils::StringStream& operator<<(utils::StringStream& out, Function::ReturnAttribute value) {
+utils::StringStream& operator<<(utils::StringStream& out, enum Function::ReturnBuiltin value) {
switch (value) {
- case Function::ReturnAttribute::kLocation:
- return out << "location";
- case Function::ReturnAttribute::kFragDepth:
+ case Function::ReturnBuiltin::kFragDepth:
return out << "frag_depth";
- case Function::ReturnAttribute::kSampleMask:
+ case Function::ReturnBuiltin::kSampleMask:
return out << "sample_mask";
- case Function::ReturnAttribute::kPosition:
+ case Function::ReturnBuiltin::kPosition:
return out << "position";
- case Function::ReturnAttribute::kInvariant:
- return out << "invariant";
- default:
- break;
}
return out << "<unknown>";
}
diff --git a/src/tint/ir/function.h b/src/tint/ir/function.h
index 172afdc..fa5c547 100644
--- a/src/tint/ir/function.h
+++ b/src/tint/ir/function.h
@@ -20,6 +20,7 @@
#include <utility>
#include "src/tint/ir/function_param.h"
+#include "src/tint/ir/location.h"
#include "src/tint/ir/value.h"
#include "src/tint/type/type.h"
@@ -46,20 +47,14 @@
kVertex,
};
- /// Attributes attached to return types
- enum class ReturnAttribute {
- /// No return attribute
- kNone,
- /// Location attribute
- kLocation,
+ /// Builtin attached to return types
+ enum class ReturnBuiltin {
/// Builtin Position attribute
kPosition,
/// Builtin FragDepth attribute
kFragDepth,
/// Builtin SampleMask
kSampleMask,
- /// Invariant attribute
- kInvariant,
};
/// Constructor
@@ -88,26 +83,35 @@
std::optional<std::array<uint32_t, 3>> WorkgroupSize() const { return workgroup_size_; }
/// @returns the return type for the function
- const type::Type* ReturnType() const { return return_type_; }
+ const type::Type* ReturnType() const { return return_.type; }
/// Sets the return attributes
- /// @param attrs the attributes to set
- void SetReturnAttributes(utils::VectorRef<ReturnAttribute> attrs) {
- return_attributes_ = std::move(attrs);
+ /// @param builtin the builtin to set
+ void SetReturnBuiltin(ReturnBuiltin builtin) {
+ TINT_ASSERT(IR, !return_.builtin.has_value());
+ return_.builtin = builtin;
}
- /// @returns the return attributes
- utils::VectorRef<ReturnAttribute> ReturnAttributes() const { return return_attributes_; }
+ /// @returns the return builtin attribute
+ std::optional<enum ReturnBuiltin> ReturnBuiltin() const { return return_.builtin; }
/// Sets the return location
/// @param loc the location to set
- void SetReturnLocation(std::optional<uint32_t> loc) { return_location_ = loc; }
+ /// @param interp the interpolation
+ void SetReturnLocation(uint32_t loc, std::optional<builtin::Interpolation> interp) {
+ return_.location = {loc, interp};
+ }
/// @returns the return location
- std::optional<uint32_t> ReturnLocation() const { return return_location_; }
+ std::optional<Location> ReturnLocation() const { return return_.location; }
+
+ /// Sets the return as invariant
+ /// @param val the invariant value to set
+ void SetReturnInvariant(bool val) { return_.invariant = val; }
+ /// @returns the return invariant value
+ bool ReturnInvariant() const { return return_.invariant; }
/// Sets the function parameters
/// @param params the function paramters
void SetParams(utils::VectorRef<FunctionParam*> params) { params_ = std::move(params); }
-
/// @returns the function parameters
utils::VectorRef<FunctionParam*> Params() const { return params_; }
@@ -118,20 +122,22 @@
Block* StartTarget() const { return start_target_; }
private:
- const type::Type* return_type_;
PipelineStage pipeline_stage_;
std::optional<std::array<uint32_t, 3>> workgroup_size_;
- utils::Vector<ReturnAttribute, 1> return_attributes_;
- std::optional<uint32_t> return_location_;
+ struct {
+ const type::Type* type = nullptr;
+ std::optional<enum ReturnBuiltin> builtin;
+ std::optional<Location> location;
+ bool invariant = false;
+ } return_;
utils::Vector<FunctionParam*, 1> params_;
-
Block* start_target_ = nullptr;
};
utils::StringStream& operator<<(utils::StringStream& out, Function::PipelineStage value);
-utils::StringStream& operator<<(utils::StringStream& out, Function::ReturnAttribute value);
+utils::StringStream& operator<<(utils::StringStream& out, enum Function::ReturnBuiltin value);
} // namespace tint::ir
diff --git a/src/tint/ir/function_param.cc b/src/tint/ir/function_param.cc
index a9570fa..ae94f24 100644
--- a/src/tint/ir/function_param.cc
+++ b/src/tint/ir/function_param.cc
@@ -22,4 +22,43 @@
FunctionParam::~FunctionParam() = default;
+utils::StringStream& operator<<(utils::StringStream& out, enum FunctionParam::Builtin value) {
+ switch (value) {
+ case FunctionParam::Builtin::kVertexIndex:
+ out << "vertex_index";
+ break;
+ case FunctionParam::Builtin::kInstanceIndex:
+ out << "instance_index";
+ break;
+ case FunctionParam::Builtin::kPosition:
+ out << "position";
+ break;
+ case FunctionParam::Builtin::kFrontFacing:
+ out << "front_facing";
+ break;
+ case FunctionParam::Builtin::kLocalInvocationId:
+ out << "local_invocation_id";
+ break;
+ case FunctionParam::Builtin::kLocalInvocationIndex:
+ out << "local_invocation_index";
+ break;
+ case FunctionParam::Builtin::kGlobalInvocationId:
+ out << "global_invocation_id";
+ break;
+ case FunctionParam::Builtin::kWorkgroupId:
+ out << "workgroup_id";
+ break;
+ case FunctionParam::Builtin::kNumWorkgroups:
+ out << "num_workgroups";
+ break;
+ case FunctionParam::Builtin::kSampleIndex:
+ out << "sample_index";
+ break;
+ case FunctionParam::Builtin::kSampleMask:
+ out << "sample_mask";
+ break;
+ }
+ return out;
+}
+
} // namespace tint::ir
diff --git a/src/tint/ir/function_param.h b/src/tint/ir/function_param.h
index 2da0584..45ce4e9 100644
--- a/src/tint/ir/function_param.h
+++ b/src/tint/ir/function_param.h
@@ -15,14 +15,45 @@
#ifndef SRC_TINT_IR_FUNCTION_PARAM_H_
#define SRC_TINT_IR_FUNCTION_PARAM_H_
+#include <utility>
+
+#include "src/tint/ir/binding_point.h"
+#include "src/tint/ir/location.h"
#include "src/tint/ir/value.h"
#include "src/tint/utils/castable.h"
+#include "src/tint/utils/vector.h"
namespace tint::ir {
/// A function parameter in the IR.
class FunctionParam : public utils::Castable<FunctionParam, Value> {
public:
+ /// Builtin attribute
+ enum class Builtin {
+ /// Builtin Vertex index
+ kVertexIndex,
+ /// Builtin Instance index
+ kInstanceIndex,
+ /// Builtin Position
+ kPosition,
+ /// Builtin FrontFacing
+ kFrontFacing,
+ /// Builtin Local invocation id
+ kLocalInvocationId,
+ /// Builtin Local invocation index
+ kLocalInvocationIndex,
+ /// Builtin Global invocation id
+ kGlobalInvocationId,
+ /// Builtin Workgroup id
+ kWorkgroupId,
+ /// Builtin Num workgroups
+ kNumWorkgroups,
+ /// Builtin Sample index
+ kSampleIndex,
+ /// Builtin Sample mask
+ kSampleMask,
+ };
+
/// Constructor
/// @param type the type of the var
explicit FunctionParam(const type::Type* type);
@@ -31,11 +62,47 @@
/// @returns the type of the var
const type::Type* Type() const override { return type_; }
+ /// Sets the builtin information. Note, it is currently an error if the builtin is already set.
+ /// @param val the builtin to set
+ void SetBuiltin(FunctionParam::Builtin val) {
+ TINT_ASSERT(IR, !builtin_.has_value());
+ builtin_ = val;
+ }
+ /// @returns the builtin set for the parameter
+ std::optional<FunctionParam::Builtin> Builtin() const { return builtin_; }
+
+ /// Sets the parameter as invariant
+ /// @param val the value to set for invariant
+ void SetInvariant(bool val) { invariant_ = val; }
+ /// @returns true if parameter is invariant
+ bool Invariant() const { return invariant_; }
+
+ /// Sets the location
+ /// @param loc the location value
+ /// @param interpolation if the location interpolation settings
+ void SetLocation(uint32_t loc, std::optional<builtin::Interpolation> interpolation) {
+ location_ = {loc, interpolation};
+ }
+ /// @returns the location if `Attributes` contains `kLocation`
+ std::optional<struct Location> Location() const { return location_; }
+
+ /// Sets the binding point
+ /// @param group the group
+ /// @param binding the binding
+ void SetBindingPoint(uint32_t group, uint32_t binding) { binding_point_ = {group, binding}; }
+ /// @returns the binding points if `Attributes` contains `kBindingPoint`
+ std::optional<struct BindingPoint> BindingPoint() const { return binding_point_; }
+
private:
- /// The type of the parameter
- const type::Type* type_;
+ const type::Type* type_ = nullptr;
+ std::optional<enum FunctionParam::Builtin> builtin_;
+ std::optional<struct Location> location_;
+ std::optional<struct BindingPoint> binding_point_;
+ bool invariant_ = false;
};
+utils::StringStream& operator<<(utils::StringStream& out, enum FunctionParam::Builtin value);
+
} // namespace tint::ir
#endif // SRC_TINT_IR_FUNCTION_PARAM_H_
diff --git a/src/tint/ir/if.cc b/src/tint/ir/if.cc
index 2069c6d..aa1e884 100644
--- a/src/tint/ir/if.cc
+++ b/src/tint/ir/if.cc
@@ -18,7 +18,7 @@
namespace tint::ir {
-If::If(Value* cond, Block* t, Block* f, Block* m)
+If::If(Value* cond, ir::Block* t, ir::Block* f, ir::Block* m)
: Base(utils::Empty), condition_(cond), true_(t), false_(f), merge_(m) {
TINT_ASSERT(IR, true_);
TINT_ASSERT(IR, false_);
diff --git a/src/tint/ir/if.h b/src/tint/ir/if.h
index ad4db1d..6dbe5fc 100644
--- a/src/tint/ir/if.h
+++ b/src/tint/ir/if.h
@@ -34,7 +34,7 @@
/// @param t the true block
/// @param f the false block
/// @param m the merge block
- explicit If(Value* cond, Block* t, Block* f, Block* m);
+ explicit If(Value* cond, ir::Block* t, ir::Block* f, ir::Block* m);
~If() override;
/// @returns the if condition
@@ -43,25 +43,25 @@
Value* Condition() { return condition_; }
/// @returns the true branch block
- const Block* True() const { return true_; }
+ const ir::Block* True() const { return true_; }
/// @returns the true branch block
- Block* True() { return true_; }
+ ir::Block* True() { return true_; }
/// @returns the false branch block
- const Block* False() const { return false_; }
+ const ir::Block* False() const { return false_; }
/// @returns the false branch block
- Block* False() { return false_; }
+ ir::Block* False() { return false_; }
/// @returns the merge branch block
- const Block* Merge() const { return merge_; }
+ const ir::Block* Merge() const { return merge_; }
/// @returns the merge branch block
- Block* Merge() { return merge_; }
+ ir::Block* Merge() { return merge_; }
private:
Value* condition_ = nullptr;
- Block* true_ = nullptr;
- Block* false_ = nullptr;
- Block* merge_ = nullptr;
+ ir::Block* true_ = nullptr;
+ ir::Block* false_ = nullptr;
+ ir::Block* merge_ = nullptr;
};
} // namespace tint::ir
diff --git a/src/tint/ir/instruction.h b/src/tint/ir/instruction.h
index c3c18cd..13bcc00 100644
--- a/src/tint/ir/instruction.h
+++ b/src/tint/ir/instruction.h
@@ -18,6 +18,11 @@
#include "src/tint/ir/value.h"
#include "src/tint/utils/castable.h"
+// Forward declarations
+namespace tint::ir {
+class Block;
+} // namespace tint::ir
+
namespace tint::ir {
/// An instruction in the IR.
@@ -26,9 +31,22 @@
/// Destructor
~Instruction() override;
+ /// Sets the block that owns this instruction
+ /// @param block the new owner block
+ void SetBlock(ir::Block* block) { block_ = block; }
+
+ /// @returns the block that owns this instruction
+ ir::Block* Block() { return block_; }
+
+ /// @returns the block that owns this instruction
+ const ir::Block* Block() const { return block_; }
+
protected:
/// Constructor
Instruction();
+
+ /// The block that owns this instruction
+ ir::Block* block_ = nullptr;
};
} // namespace tint::ir
diff --git a/src/tint/ir/location.h b/src/tint/ir/location.h
new file mode 100644
index 0000000..5edb882
--- /dev/null
+++ b/src/tint/ir/location.h
@@ -0,0 +1,34 @@
+// Copyright 2023 The Tint Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SRC_TINT_IR_LOCATION_H_
+#define SRC_TINT_IR_LOCATION_H_
+
+#include <optional>
+
+#include "src/tint/builtin/interpolation.h"
+
+namespace tint::ir {
+
+/// A function parameter in the IR.
+struct Location {
+ /// The location value
+ uint32_t value = 0;
+ /// The interpolation settings
+ std::optional<builtin::Interpolation> interpolation;
+};
+
+} // namespace tint::ir
+
+#endif // SRC_TINT_IR_LOCATION_H_
diff --git a/src/tint/ir/loop.cc b/src/tint/ir/loop.cc
index fe34283..bd697bf 100644
--- a/src/tint/ir/loop.cc
+++ b/src/tint/ir/loop.cc
@@ -18,7 +18,7 @@
namespace tint::ir {
-Loop::Loop(Block* s, Block* c, Block* m)
+Loop::Loop(ir::Block* s, ir::Block* c, ir::Block* m)
: Base(utils::Empty), start_(s), continuing_(c), merge_(m) {
TINT_ASSERT(IR, start_);
TINT_ASSERT(IR, continuing_);
diff --git a/src/tint/ir/loop.h b/src/tint/ir/loop.h
index 954a64a..aadfd30 100644
--- a/src/tint/ir/loop.h
+++ b/src/tint/ir/loop.h
@@ -27,28 +27,28 @@
/// @param s the start block
/// @param c the continuing block
/// @param m the merge block
- Loop(Block* s, Block* c, Block* m);
+ Loop(ir::Block* s, ir::Block* c, ir::Block* m);
~Loop() override;
/// @returns the switch start branch
- const Block* Start() const { return start_; }
+ const ir::Block* Start() const { return start_; }
/// @returns the switch start branch
- Block* Start() { return start_; }
+ ir::Block* Start() { return start_; }
/// @returns the switch continuing branch
- const Block* Continuing() const { return continuing_; }
+ const ir::Block* Continuing() const { return continuing_; }
/// @returns the switch continuing branch
- Block* Continuing() { return continuing_; }
+ ir::Block* Continuing() { return continuing_; }
/// @returns the switch merge branch
- const Block* Merge() const { return merge_; }
+ const ir::Block* Merge() const { return merge_; }
/// @returns the switch merge branch
- Block* Merge() { return merge_; }
+ ir::Block* Merge() { return merge_; }
private:
- Block* start_ = nullptr;
- Block* continuing_ = nullptr;
- Block* merge_ = nullptr;
+ ir::Block* start_ = nullptr;
+ ir::Block* continuing_ = nullptr;
+ ir::Block* merge_ = nullptr;
};
} // namespace tint::ir
diff --git a/src/tint/ir/switch.cc b/src/tint/ir/switch.cc
index 003feb2..3756f45 100644
--- a/src/tint/ir/switch.cc
+++ b/src/tint/ir/switch.cc
@@ -18,7 +18,7 @@
namespace tint::ir {
-Switch::Switch(Value* cond, Block* m) : Base(utils::Empty), condition_(cond), merge_(m) {
+Switch::Switch(Value* cond, ir::Block* m) : Base(utils::Empty), condition_(cond), merge_(m) {
TINT_ASSERT(IR, condition_);
TINT_ASSERT(IR, merge_);
condition_->AddUsage(this);
diff --git a/src/tint/ir/switch.h b/src/tint/ir/switch.h
index 588fee9..d9355f1 100644
--- a/src/tint/ir/switch.h
+++ b/src/tint/ir/switch.h
@@ -39,24 +39,24 @@
/// The case selector for this node
utils::Vector<CaseSelector, 4> selectors;
/// The start block for the case block.
- Block* start = nullptr;
+ ir::Block* start = nullptr;
/// @returns the case start target
- const Block* Start() const { return start; }
+ const ir::Block* Start() const { return start; }
/// @returns the case start target
- Block* Start() { return start; }
+ ir::Block* Start() { return start; }
};
/// Constructor
/// @param cond the condition
/// @param m the merge block
- explicit Switch(Value* cond, Block* m);
+ explicit Switch(Value* cond, ir::Block* m);
~Switch() override;
/// @returns the switch merge branch
- const Block* Merge() const { return merge_; }
+ const ir::Block* Merge() const { return merge_; }
/// @returns the switch merge branch
- Block* Merge() { return merge_; }
+ ir::Block* Merge() { return merge_; }
/// @returns the switch cases
utils::VectorRef<Case> Cases() const { return cases_; }
@@ -70,7 +70,7 @@
private:
Value* condition_ = nullptr;
- Block* merge_ = nullptr;
+ ir::Block* merge_ = nullptr;
utils::Vector<Case, 4> cases_;
};
diff --git a/src/tint/ir/transform/add_empty_entry_point_test.cc b/src/tint/ir/transform/add_empty_entry_point_test.cc
index ca918f2..1da2e7d 100644
--- a/src/tint/ir/transform/add_empty_entry_point_test.cc
+++ b/src/tint/ir/transform/add_empty_entry_point_test.cc
@@ -25,7 +25,7 @@
TEST_F(IR_AddEmptyEntryPointTest, EmptyModule) {
auto* expect = R"(
-%unused_entry_point = func():void [@compute @workgroup_size(1, 1, 1)] -> %b1 {
+%unused_entry_point = @compute @workgroup_size(1, 1, 1) func():void -> %b1 {
%b1 = block {
ret
}
@@ -43,7 +43,7 @@
mod.functions.Push(ep);
auto* expect = R"(
-%main = func():void [@fragment] -> %b1 {
+%main = @fragment func():void -> %b1 {
%b1 = block {
ret
}
diff --git a/src/tint/ir/var.h b/src/tint/ir/var.h
index 8561e5c..8048463 100644
--- a/src/tint/ir/var.h
+++ b/src/tint/ir/var.h
@@ -17,8 +17,10 @@
#include "src/tint/builtin/access.h"
#include "src/tint/builtin/address_space.h"
+#include "src/tint/ir/binding_point.h"
#include "src/tint/ir/instruction.h"
#include "src/tint/utils/castable.h"
+#include "src/tint/utils/vector.h"
namespace tint::ir {
@@ -39,9 +41,17 @@
/// @returns the initializer
const Value* Initializer() const { return initializer_; }
+ /// Sets the binding point
+ /// @param group the group
+ /// @param binding the binding
+ void SetBindingPoint(uint32_t group, uint32_t binding) { binding_point_ = {group, binding}; }
+ /// @returns the binding points if `Attributes` contains `kBindingPoint`
+ std::optional<struct BindingPoint> BindingPoint() const { return binding_point_; }
+
private:
const type::Type* type_;
Value* initializer_ = nullptr;
+ std::optional<struct BindingPoint> binding_point_;
};
} // namespace tint::ir
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
index 8ec7a9c..e16d116 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_loop_test.cc
@@ -24,11 +24,11 @@
auto* loop = b.CreateLoop();
- loop->Start()->Instructions().Push(b.Continue(loop));
- loop->Continuing()->Instructions().Push(b.BreakIf(b.Constant(true), loop));
- loop->Merge()->Instructions().Push(b.Return(func));
+ loop->Start()->AddInstruction(b.Continue(loop));
+ loop->Continuing()->AddInstruction(b.BreakIf(b.Constant(true), loop));
+ loop->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(loop);
+ func->StartTarget()->AddInstruction(loop);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -58,10 +58,10 @@
auto* loop = b.CreateLoop();
- loop->Start()->Instructions().Push(b.ExitLoop(loop));
- loop->Merge()->Instructions().Push(b.Return(func));
+ loop->Start()->AddInstruction(b.ExitLoop(loop));
+ loop->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(loop);
+ func->StartTarget()->AddInstruction(loop);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -89,15 +89,15 @@
auto* loop = b.CreateLoop();
auto* cond_break = b.CreateIf(b.Constant(true));
- cond_break->True()->Instructions().Push(b.ExitLoop(loop));
- cond_break->False()->Instructions().Push(b.ExitIf(cond_break));
- cond_break->Merge()->Instructions().Push(b.Continue(loop));
+ cond_break->True()->AddInstruction(b.ExitLoop(loop));
+ cond_break->False()->AddInstruction(b.ExitIf(cond_break));
+ cond_break->Merge()->AddInstruction(b.Continue(loop));
- loop->Start()->Instructions().Push(cond_break);
- loop->Continuing()->Instructions().Push(b.NextIteration(loop));
- loop->Merge()->Instructions().Push(b.Return(func));
+ loop->Start()->AddInstruction(cond_break);
+ loop->Continuing()->AddInstruction(b.NextIteration(loop));
+ loop->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(loop);
+ func->StartTarget()->AddInstruction(loop);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -132,15 +132,15 @@
auto* loop = b.CreateLoop();
auto* cond_break = b.CreateIf(b.Constant(true));
- cond_break->True()->Instructions().Push(b.Continue(loop));
- cond_break->False()->Instructions().Push(b.ExitIf(cond_break));
- cond_break->Merge()->Instructions().Push(b.ExitLoop(loop));
+ cond_break->True()->AddInstruction(b.Continue(loop));
+ cond_break->False()->AddInstruction(b.ExitIf(cond_break));
+ cond_break->Merge()->AddInstruction(b.ExitLoop(loop));
- loop->Start()->Instructions().Push(cond_break);
- loop->Continuing()->Instructions().Push(b.NextIteration(loop));
- loop->Merge()->Instructions().Push(b.Return(func));
+ loop->Start()->AddInstruction(cond_break);
+ loop->Continuing()->AddInstruction(b.NextIteration(loop));
+ loop->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(loop);
+ func->StartTarget()->AddInstruction(loop);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -176,9 +176,9 @@
auto* loop = b.CreateLoop();
- loop->Start()->Instructions().Push(b.Return(func));
+ loop->Start()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(loop);
+ func->StartTarget()->AddInstruction(loop);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -207,11 +207,11 @@
auto* result = b.Equal(mod.Types().i32(), b.Constant(1_i), b.Constant(2_i));
- loop->Start()->Instructions().Push(result);
- loop->Continuing()->Instructions().Push(b.BreakIf(result, loop));
- loop->Merge()->Instructions().Push(b.Return(func));
+ loop->Start()->AddInstruction(result);
+ loop->Continuing()->AddInstruction(b.BreakIf(result, loop));
+ loop->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(loop);
+ func->StartTarget()->AddInstruction(loop);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -242,15 +242,15 @@
auto* outer_loop = b.CreateLoop();
auto* inner_loop = b.CreateLoop();
- inner_loop->Start()->Instructions().Push(b.ExitLoop(inner_loop));
- inner_loop->Continuing()->Instructions().Push(b.NextIteration(inner_loop));
- inner_loop->Merge()->Instructions().Push(b.Continue(outer_loop));
+ inner_loop->Start()->AddInstruction(b.ExitLoop(inner_loop));
+ inner_loop->Continuing()->AddInstruction(b.NextIteration(inner_loop));
+ inner_loop->Merge()->AddInstruction(b.Continue(outer_loop));
- outer_loop->Start()->Instructions().Push(inner_loop);
- outer_loop->Continuing()->Instructions().Push(b.BreakIf(b.Constant(true), outer_loop));
- outer_loop->Merge()->Instructions().Push(b.Return(func));
+ outer_loop->Start()->AddInstruction(inner_loop);
+ outer_loop->Continuing()->AddInstruction(b.BreakIf(b.Constant(true), outer_loop));
+ outer_loop->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(outer_loop);
+ func->StartTarget()->AddInstruction(outer_loop);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -289,15 +289,15 @@
auto* outer_loop = b.CreateLoop();
auto* inner_loop = b.CreateLoop();
- inner_loop->Start()->Instructions().Push(b.Continue(inner_loop));
- inner_loop->Continuing()->Instructions().Push(b.BreakIf(b.Constant(true), inner_loop));
- inner_loop->Merge()->Instructions().Push(b.BreakIf(b.Constant(true), outer_loop));
+ inner_loop->Start()->AddInstruction(b.Continue(inner_loop));
+ inner_loop->Continuing()->AddInstruction(b.BreakIf(b.Constant(true), inner_loop));
+ inner_loop->Merge()->AddInstruction(b.BreakIf(b.Constant(true), outer_loop));
- outer_loop->Start()->Instructions().Push(b.Continue(outer_loop));
- outer_loop->Continuing()->Instructions().Push(inner_loop);
- outer_loop->Merge()->Instructions().Push(b.Return(func));
+ outer_loop->Start()->AddInstruction(b.Continue(outer_loop));
+ outer_loop->Continuing()->AddInstruction(inner_loop);
+ outer_loop->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(outer_loop);
+ func->StartTarget()->AddInstruction(outer_loop);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
diff --git a/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc b/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
index 5ef5901..92800a3 100644
--- a/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
+++ b/src/tint/writer/spirv/ir/generator_impl_ir_switch_test.cc
@@ -25,11 +25,11 @@
auto* swtch = b.CreateSwitch(b.Constant(42_i));
auto* def_case = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector()});
- def_case->Instructions().Push(b.ExitSwitch(swtch));
+ def_case->AddInstruction(b.ExitSwitch(swtch));
- swtch->Merge()->Instructions().Push(b.Return(func));
+ swtch->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(swtch);
+ func->StartTarget()->AddInstruction(swtch);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -55,17 +55,17 @@
auto* swtch = b.CreateSwitch(b.Constant(42_i));
auto* case_a = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
- case_a->Instructions().Push(b.ExitSwitch(swtch));
+ case_a->AddInstruction(b.ExitSwitch(swtch));
auto* case_b = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
- case_b->Instructions().Push(b.ExitSwitch(swtch));
+ case_b->AddInstruction(b.ExitSwitch(swtch));
auto* def_case = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector()});
- def_case->Instructions().Push(b.ExitSwitch(swtch));
+ def_case->AddInstruction(b.ExitSwitch(swtch));
- swtch->Merge()->Instructions().Push(b.Return(func));
+ swtch->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(swtch);
+ func->StartTarget()->AddInstruction(swtch);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -96,19 +96,19 @@
auto* case_a = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)},
ir::Switch::CaseSelector{b.Constant(3_i)}});
- case_a->Instructions().Push(b.ExitSwitch(swtch));
+ case_a->AddInstruction(b.ExitSwitch(swtch));
auto* case_b = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)},
ir::Switch::CaseSelector{b.Constant(4_i)}});
- case_b->Instructions().Push(b.ExitSwitch(swtch));
+ case_b->AddInstruction(b.ExitSwitch(swtch));
auto* def_case = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(5_i)},
ir::Switch::CaseSelector()});
- def_case->Instructions().Push(b.ExitSwitch(swtch));
+ def_case->AddInstruction(b.ExitSwitch(swtch));
- swtch->Merge()->Instructions().Push(b.Return(func));
+ swtch->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(swtch);
+ func->StartTarget()->AddInstruction(swtch);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -138,15 +138,15 @@
auto* swtch = b.CreateSwitch(b.Constant(42_i));
auto* case_a = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
- case_a->Instructions().Push(b.Return(func));
+ case_a->AddInstruction(b.Return(func));
auto* case_b = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(2_i)}});
- case_b->Instructions().Push(b.Return(func));
+ case_b->AddInstruction(b.Return(func));
auto* def_case = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector()});
- def_case->Instructions().Push(b.Return(func));
+ def_case->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(swtch);
+ func->StartTarget()->AddInstruction(swtch);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"
@@ -176,19 +176,19 @@
auto* swtch = b.CreateSwitch(b.Constant(42_i));
auto* cond_break = b.CreateIf(b.Constant(true));
- cond_break->True()->Instructions().Push(b.ExitSwitch(swtch));
- cond_break->False()->Instructions().Push(b.ExitIf(cond_break));
- cond_break->Merge()->Instructions().Push(b.Return(func));
+ cond_break->True()->AddInstruction(b.ExitSwitch(swtch));
+ cond_break->False()->AddInstruction(b.ExitIf(cond_break));
+ cond_break->Merge()->AddInstruction(b.Return(func));
auto* case_a = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector{b.Constant(1_i)}});
- case_a->Instructions().Push(cond_break);
+ case_a->AddInstruction(cond_break);
auto* def_case = b.CreateCase(swtch, utils::Vector{ir::Switch::CaseSelector()});
- def_case->Instructions().Push(b.ExitSwitch(swtch));
+ def_case->AddInstruction(b.ExitSwitch(swtch));
- swtch->Merge()->Instructions().Push(b.Return(func));
+ swtch->Merge()->AddInstruction(b.Return(func));
- func->StartTarget()->Instructions().Push(swtch);
+ func->StartTarget()->AddInstruction(swtch);
generator_.EmitFunction(func);
EXPECT_EQ(DumpModule(generator_.Module()), R"(OpName %1 "foo"