Adding capability to mark operands as possibly generating relocation info. This only applies to generated assemblers. PiperOrigin-RevId: 713424216 Change-Id: I3b9ba49354f6d64c3285f4acc28d3ff1fbd95a02
diff --git a/mpact/sim/decoder/InstructionSet.g4 b/mpact/sim/decoder/InstructionSet.g4 index f26e41e..b8e71e5 100644 --- a/mpact/sim/decoder/InstructionSet.g4 +++ b/mpact/sim/decoder/InstructionSet.g4
@@ -320,10 +320,15 @@ ; source_operand - : source=IDENT + : operand | '[' array_source=IDENT ']' ; +operand + : op_attribute=OP_ATTRIBUTE '(' op_name=IDENT ')' + | op_name=IDENT + ; + // Destination operands may include a latency. dest_list @@ -331,7 +336,7 @@ ; dest_operand - : (dest=IDENT | '[' array_dest=IDENT ']') + : (operand | '[' array_dest=IDENT ']') ( '(' (expression | wildcard='*' ) ')' )? ; @@ -515,6 +520,8 @@ SLOTS : 'slots'; TEMPLATE : 'template'; +OP_ATTRIBUTE : '%reloc'; + // Other tokens. STRING_LITERAL : UNTERMINATED_STRING_LITERAL '"'; fragment UNTERMINATED_STRING_LITERAL : '"' (~["\\\r\n] | '\\' (. | EOF))*;
diff --git a/mpact/sim/decoder/instruction_set_visitor.cc b/mpact/sim/decoder/instruction_set_visitor.cc index 6398a7c..7783807 100644 --- a/mpact/sim/decoder/instruction_set_visitor.cc +++ b/mpact/sim/decoder/instruction_set_visitor.cc
@@ -1608,25 +1608,37 @@ if (ctx->pred != nullptr) { std::string name = ctx->pred->getText(); child->opcode()->set_predicate_op_name(name); - parent->opcode()->op_locator_map().insert( - std::make_pair(name, OperandLocator(op_spec_number, 'p', 0))); + parent->opcode()->op_locator_map().insert(std::make_pair( + name, OperandLocator(op_spec_number, 'p', /*is_reloc=*/false, + /*instance=*/0))); } if (ctx->source != nullptr) { int instance = 0; for (auto *source_op : ctx->source->source_operand()) { std::string name; - bool is_array; - if (source_op->source != nullptr) { - name = source_op->source->getText(); - is_array = false; + bool is_array = false; + bool is_reloc = false; + if (source_op->operand() != nullptr) { + name = source_op->operand()->op_name->getText(); + if (source_op->operand()->op_attribute != nullptr) { + auto attr = source_op->operand()->op_attribute->getText(); + if (attr == "%reloc") { + is_reloc = true; + } else { + error_listener()->semanticError( + file_names_[context_file_map_.at(slot->ctx())], + source_op->operand()->op_attribute, + absl::StrCat("Invalid operand attribute '", attr, "'")); + } + } } else { name = source_op->array_source->getText(); is_array = true; } - child->opcode()->AppendSourceOp(name, is_array); + child->opcode()->AppendSourceOp(name, is_array, is_reloc); parent->opcode()->op_locator_map().insert(std::make_pair( - name, - OperandLocator(op_spec_number, is_array ? 't' : 's', instance))); + name, OperandLocator(op_spec_number, is_array ? 't' : 's', is_reloc, + instance))); instance++; } } @@ -1634,10 +1646,21 @@ int instance = 0; for (auto *dest_op : ctx->dest_list()->dest_operand()) { std::string ident; - bool is_array; - if (dest_op->dest != nullptr) { - ident = dest_op->dest->getText(); - is_array = false; + bool is_array = false; + bool is_reloc = false; + if (dest_op->operand() != nullptr) { + ident = dest_op->operand()->op_name->getText(); + if (dest_op->operand()->op_attribute != nullptr) { + auto attr = dest_op->operand()->op_attribute->getText(); + if (attr == "%reloc") { + is_reloc = true; + } else { + error_listener()->semanticError( + file_names_[context_file_map_.at(slot->ctx())], + dest_op->operand()->op_attribute, + absl::StrCat("Invalid operand attribute '", attr, "'")); + } + } } else { ident = dest_op->array_dest->getText(); is_array = true; @@ -1649,19 +1672,20 @@ context_file_map_.insert( {dest_op->expression(), context_file_map_.at(slot->ctx())}); child->opcode()->AppendDestOp( - ident, is_array, + ident, is_array, is_reloc, VisitExpression(dest_op->expression(), slot, child)); } else if (dest_op->wildcard != nullptr) { - child->opcode()->AppendDestOp(ident, is_array); + child->opcode()->AppendDestOp(ident, is_array, is_reloc); } else if (slot->default_latency() != nullptr) { - child->opcode()->AppendDestOp(ident, is_array, + child->opcode()->AppendDestOp(ident, is_array, is_reloc, slot->default_latency()->DeepCopy()); } else { - child->opcode()->AppendDestOp(ident, is_array, new TemplateConstant(1)); + child->opcode()->AppendDestOp(ident, is_array, is_reloc, + new TemplateConstant(1)); } parent->opcode()->op_locator_map().insert(std::make_pair( - ident, - OperandLocator(op_spec_number, is_array ? 'e' : 'd', instance))); + ident, OperandLocator(op_spec_number, is_array ? 'e' : 'd', is_reloc, + instance))); instance++; } }
diff --git a/mpact/sim/decoder/opcode.cc b/mpact/sim/decoder/opcode.cc index aaed476..a4a3d30 100644 --- a/mpact/sim/decoder/opcode.cc +++ b/mpact/sim/decoder/opcode.cc
@@ -44,19 +44,22 @@ dest_op_map_.clear(); } -void Opcode::AppendSourceOp(absl::string_view op_name, bool is_array) { - source_op_vec_.emplace_back(std::string(op_name), is_array); +void Opcode::AppendSourceOp(absl::string_view op_name, bool is_array, + bool is_reloc) { + source_op_vec_.emplace_back(std::string(op_name), is_array, is_reloc); } -void Opcode::AppendDestOp(absl::string_view op_name, bool is_array) { - auto *op = new DestinationOperand(std::string(op_name), is_array); +void Opcode::AppendDestOp(absl::string_view op_name, bool is_array, + bool is_reloc) { + auto *op = new DestinationOperand(std::string(op_name), is_array, is_reloc); dest_op_vec_.push_back(op); dest_op_map_.insert(std::make_pair(std::string(op_name), op)); } void Opcode::AppendDestOp(absl::string_view op_name, bool is_array, - TemplateExpression *expression) { - auto *op = new DestinationOperand(std::string(op_name), is_array, expression); + bool is_reloc, TemplateExpression *expression) { + auto *op = new DestinationOperand(std::string(op_name), is_array, is_reloc, + expression); dest_op_vec_.push_back(op); dest_op_map_.insert(std::make_pair(std::string(op_name), op)); } @@ -108,14 +111,15 @@ new_opcode->predicate_op_name_ = opcode->predicate_op_name(); new_opcode->op_locator_map_ = opcode->op_locator_map(); for (auto const &src_op : opcode->source_op_vec()) { - new_opcode->AppendSourceOp(src_op.name, src_op.is_array); + new_opcode->AppendSourceOp(src_op.name, src_op.is_array, src_op.is_reloc); } // Copy destination operands, but evaluate any latencies using the template // instantiation arguments, in case those expressions use them. for (auto const *dest_op : opcode->dest_op_vec()) { if (dest_op->expression() == nullptr) { - new_opcode->AppendDestOp(dest_op->name(), dest_op->is_array()); + new_opcode->AppendDestOp(dest_op->name(), dest_op->is_array(), + dest_op->is_reloc()); } else { // For each destination operand that has an expression, evaluate it in the // context of the passed in TemplateInstantiationArgs. This creates a copy @@ -124,7 +128,7 @@ auto result = dest_op->expression()->Evaluate(args); if (result.ok()) { new_opcode->AppendDestOp(dest_op->name(), dest_op->is_array(), - result.value()); + dest_op->is_reloc(), result.value()); } else { delete new_opcode; return absl::InternalError(absl::StrCat(
diff --git a/mpact/sim/decoder/opcode.h b/mpact/sim/decoder/opcode.h index 4b77fc3..1cacd87 100644 --- a/mpact/sim/decoder/opcode.h +++ b/mpact/sim/decoder/opcode.h
@@ -15,6 +15,8 @@ #ifndef MPACT_SIM_DECODER_OPCODE_H_ #define MPACT_SIM_DECODER_OPCODE_H_ +#include <stdbool.h> + #include <functional> #include <string> #include <utility> @@ -50,31 +52,39 @@ class DestinationOperand { public: // Operand latency is defined by the expression. - DestinationOperand(std::string name, bool is_array, + DestinationOperand(std::string name, bool is_array, bool is_reloc, TemplateExpression *expression) : name_(std::move(name)), pascal_case_name_(ToPascalCase(name_)), expression_(expression), - is_array_(is_array) {} + is_array_(is_array), + is_reloc_(is_reloc) {} // Operand latency is a constant. - DestinationOperand(std::string name, bool is_array, int latency) + DestinationOperand(std::string name, bool is_array, bool is_reloc, + int latency) : name_(std::move(name)), pascal_case_name_(ToPascalCase(name_)), expression_(new TemplateConstant(latency)), - is_array_(is_array) {} + is_array_(is_array), + is_reloc_(is_reloc) {} // This constructor is used when the destination operand latency is specified // as '*' - meaning that it will be computed at the time of decode. - explicit DestinationOperand(std::string name, bool is_array) + DestinationOperand(std::string name, bool is_array, bool is_reloc) : name_(std::move(name)), pascal_case_name_(ToPascalCase(name_)), expression_(nullptr), - is_array_(is_array) {} - ~DestinationOperand() { delete expression_; } + is_array_(is_array), + is_reloc_(is_reloc) {} + ~DestinationOperand() { + delete expression_; + expression_ = nullptr; + } const std::string &name() const { return name_; } const std::string &pascal_case_name() const { return pascal_case_name_; } TemplateExpression *expression() const { return expression_; } bool is_array() const { return is_array_; } + bool is_reloc() const { return is_reloc_; } bool HasLatency() const { return expression_ != nullptr; } absl::StatusOr<int> GetLatency() const { if (expression_ == nullptr) return -1; @@ -96,13 +106,15 @@ std::string pascal_case_name_; TemplateExpression *expression_; bool is_array_ = false; + bool is_reloc_ = false; }; struct SourceOperand { std::string name; bool is_array; - SourceOperand(std::string name_, bool is_array_) - : name(std::move(name_)), is_array(is_array_) {} + bool is_reloc; + SourceOperand(std::string name_, bool is_array_, bool is_reloc_) + : name(std::move(name_)), is_array(is_array_), is_reloc(is_reloc_) {} }; // This struct is used to specify the location of an operand within an @@ -120,9 +132,13 @@ static constexpr char kDestinationArray = 'e'; int op_spec_number; char type; + bool is_reloc; int instance; - OperandLocator(int op_spec_number_, char type_, int instance_) - : op_spec_number(op_spec_number_), type(type_), instance(instance_) {} + OperandLocator(int op_spec_number_, char type_, bool is_reloc_, int instance_) + : op_spec_number(op_spec_number_), + type(type_), + is_reloc(is_reloc_), + instance(instance_) {} }; struct FormatInfo { @@ -210,10 +226,10 @@ // to get the Predicate, Source and Destination operand interfaces (defined // in .../sim/generic/operand_interfaces.h. The implementation of these // methods will be left to the user of this generator tool. - void AppendSourceOp(absl::string_view op_name, bool is_array); - void AppendDestOp(absl::string_view op_name, bool is_array, + void AppendSourceOp(absl::string_view op_name, bool is_array, bool is_reloc); + void AppendDestOp(absl::string_view op_name, bool is_array, bool is_reloc, TemplateExpression *expression); - void AppendDestOp(absl::string_view op_name, bool is_array); + void AppendDestOp(absl::string_view op_name, bool is_array, bool is_reloc); DestinationOperand *GetDestOp(absl::string_view op_name); // Append child opcode specification. void AppendChild(Opcode *op) { child_ = op; }
diff --git a/mpact/sim/decoder/test/opcode_test.cc b/mpact/sim/decoder/test/opcode_test.cc index fba903c..8dba3f0 100644 --- a/mpact/sim/decoder/test/opcode_test.cc +++ b/mpact/sim/decoder/test/opcode_test.cc
@@ -90,7 +90,8 @@ TEST_F(OpcodeTest, SourceOperandNames) { for (int indx = 0; indx < 3; indx++) { std::string source_op_name = absl::StrCat("SourceOp", indx); - opcode_->AppendSourceOp(source_op_name, /*is_array=*/false); + opcode_->AppendSourceOp(source_op_name, /*is_array=*/false, + /*is_reloc=*/false); EXPECT_EQ(opcode_->source_op_vec().size(), indx + 1); EXPECT_STREQ(opcode_->source_op_vec()[indx].name.c_str(), source_op_name.c_str()); @@ -102,10 +103,12 @@ for (int indx = 0; indx < 2; indx++) { std::string dest_op_name = absl::StrCat("DestOp", indx); if (indx == 0) { - opcode_->AppendDestOp(dest_op_name, /*is_array=*/false); + opcode_->AppendDestOp(dest_op_name, /*is_array=*/false, + /*is_reloc=*/false); } else if (indx == 1) { // Using nullptr - the value isn't checked upon append. - opcode_->AppendDestOp(dest_op_name, /*is_array=*/false, nullptr); + opcode_->AppendDestOp(dest_op_name, /*is_array=*/false, + /*is_reloc=*/false, nullptr); } EXPECT_EQ(opcode_->dest_op_vec().size(), indx + 1); EXPECT_STREQ(opcode_->dest_op_vec()[indx]->name().c_str(),
diff --git a/mpact/sim/decoder/test/testfiles/example.isa b/mpact/sim/decoder/test/testfiles/example.isa index 3a6cc47..2038b83 100644 --- a/mpact/sim/decoder/test/testfiles/example.isa +++ b/mpact/sim/decoder/test/testfiles/example.isa
@@ -38,7 +38,7 @@ int mult_plus_2 = mult + my_const; default attributes = { one, two = 3, three = base, four = base_plus_1, five = 0}; opcodes { - vctsf{(pred : sy : dest(base_plus_1))}; + vctsf{(pred : sy : %reloc(dest)(base_plus_1))}; cvtfs{(pred : sy : dest(base + 1))}; adds{(pred : sy, sx : dest(base))}, attributes: {five = 1, six}; @@ -80,7 +80,7 @@ default opcode = semfunc: "[](Instruction *) {}"; opcodes { - ld{(pred : yop : ),(: : dest)}, + ld{(pred : %reloc(yop) : ),(: : dest)}, disasm:"%dest = sld %pred [smem:%yop]"; ld_offset{(pred : xop, yop : dest(abs(-2)))}; st{(pred)};