| // Copyright 2023 Google LLC |
| // |
| // 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 |
| // |
| // https://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 MPACT_SIM_DECODER_INSTRUCTION_SET_VISITOR_H_ |
| #define MPACT_SIM_DECODER_INSTRUCTION_SET_VISITOR_H_ |
| |
| #include <cstddef> |
| #include <deque> |
| #include <list> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <tuple> |
| #include <utility> |
| #include <vector> |
| |
| #include "absl/container/btree_set.h" |
| #include "absl/container/flat_hash_map.h" |
| #include "absl/container/flat_hash_set.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "absl/strings/string_view.h" |
| #include "antlr4-runtime/ParserRuleContext.h" |
| #include "mpact/sim/decoder/InstructionSetLexer.h" |
| #include "mpact/sim/decoder/InstructionSetParser.h" |
| #include "mpact/sim/decoder/antlr_parser_wrapper.h" |
| #include "mpact/sim/decoder/bundle.h" |
| #include "mpact/sim/decoder/decoder_error_listener.h" |
| #include "mpact/sim/decoder/instruction.h" |
| #include "mpact/sim/decoder/instruction_set.h" |
| #include "mpact/sim/decoder/instruction_set_contexts.h" |
| #include "mpact/sim/decoder/opcode.h" |
| #include "mpact/sim/decoder/slot.h" |
| #include "mpact/sim/decoder/template_expression.h" |
| #include "re2/re2.h" |
| |
| // This file declares the classes that interact with the antlr4 library |
| // to parse an input stream and generate the parse tree, then visiting the |
| // parse tree to build up the internal representation from which further |
| // processing and eventual c++ code generation is done. |
| namespace mpact { |
| namespace sim { |
| namespace machine_description { |
| namespace instruction_set { |
| |
| // This struct holds information about a range assignment in an instruction |
| // generator. |
| struct RangeAssignmentInfo { |
| std::vector<std::string> range_names; |
| std::list<RE2> range_regexes; |
| std::vector<std::vector<std::string>> range_values; |
| }; |
| |
| using InstructionSetParser = ::sim::machine_description::instruction_set:: |
| generated::InstructionSetParser; |
| using ::sim::machine_description::instruction_set::generated:: |
| InstructionSetLexer; |
| |
| using IsaAntlrParserWrapper = |
| decoder::AntlrParserWrapper<InstructionSetParser, InstructionSetLexer>; |
| |
| // Visitor class for the Antlr4 parse tree. It does not derive from Antlr4 |
| // base classes so that the return types and method parameters could be |
| // customized. |
| class InstructionSetVisitor { |
| public: |
| InstructionSetVisitor(); |
| ~InstructionSetVisitor(); |
| |
| // Entry point for processing a source_stream input, generating any output |
| // files in the given directory. Returns OK if no errors were encountered. |
| absl::Status Process(const std::vector<std::string> &file_names, |
| const std::string &prefix, const std::string &isa_name, |
| const std::vector<std::string> &include_roots, |
| absl::string_view directory); |
| |
| // Global const expressions. |
| absl::Status AddConstant(absl::string_view name, absl::string_view type, |
| TemplateExpression *expr); |
| TemplateExpression *GetConstExpression(absl::string_view name) const; |
| // The current isa name. |
| const std::string &isa_name() const { return isa_name_; } |
| |
| private: |
| struct TemplateFunctionEvaluator { |
| TemplateFunction::Evaluator function; |
| size_t arity; |
| TemplateFunctionEvaluator(TemplateFunction::Evaluator function_, |
| size_t arity_) |
| : function(std::move(function_)), arity(arity_) {} |
| }; |
| |
| // Checks that any references to slots or bundles within a bundle |
| // declaration are to valid slots/bundles. |
| void PerformBundleReferenceChecks(InstructionSet *instruction_set, |
| Bundle *bundle); |
| // The following methods visits the parts of the parse tree indicated by |
| // the method name and builds up the internal representation used for |
| // decoder generation. |
| void VisitTopLevel(TopLevelCtx *ctx); |
| |
| std::unique_ptr<InstructionSet> VisitIsaDeclaration(IsaDeclCtx *ctx); |
| void VisitConstantDef(ConstantDefCtx *ctx); |
| void VisitBundleList(BundleListCtx *ctx, Bundle *bundle); |
| void VisitOpcodeList(OpcodeListCtx *ctx, Slot *slot); |
| void VisitOpcodeOperands(OpcodeOperandsCtx *ctx, int op_spec_number, |
| Instruction *parent, Instruction *child, Slot *slot); |
| void VisitSlotList(SlotListCtx *ctx, Bundle *); |
| void VisitIncludeFile(IncludeFileCtx *ctx); |
| void VisitSlotDeclaration(SlotDeclCtx *ctx, InstructionSet *instruction_set); |
| void VisitConstAndDefaultDecls(ConstAndDefaultCtx *ctx, Slot *slot); |
| TemplateExpression *VisitExpression(ExpressionCtx *ctx, Slot *slot, |
| Instruction *inst); |
| std::vector<int> VisitArraySpec(ArraySpecCtx *ctx); |
| void VisitNamespaceDecl(NamespaceDeclCtx *ctx, InstructionSet *isa); |
| void VisitBundleDeclaration(BundleDeclCtx *ctx, |
| InstructionSet *instruction_set); |
| void VisitDisasmWidthsDecl(DisasmWidthsCtx *ctx); |
| void VisitInstructionAttributeList(InstructionAttributeListCtx *ctx, |
| Slot *slot, Instruction *inst); |
| void VisitOpcodeAttributes(OpcodeAttributeListCtx *ctx, Instruction *inst, |
| Slot *slot); |
| void VisitSemfuncSpec(SemfuncSpecCtx *semfunc_spec, Instruction *inst); |
| void VisitResourceDetails(ResourceDetailsCtx *ctx, Instruction *inst, |
| Slot *slot); |
| std::optional<ResourceReference *> ProcessResourceReference( |
| Slot *slot, Instruction *inst, ResourceItemCtx *resource_item); |
| void VisitResourceDetailsLists(ResourceDetailsCtx *ctx, Slot *slot, |
| Instruction *inst, ResourceSpec *spec); |
| std::unique_ptr<InstructionSet> ProcessTopLevel(absl::string_view isa_name); |
| void ParseIncludeFile(antlr4::ParserRuleContext *ctx, |
| const std::string &file_name, |
| const std::vector<std::string> &dirs); |
| DestinationOperand *FindDestinationOpInExpression(ExpressionCtx *ctx, |
| const Slot *slot, |
| const Instruction *inst); |
| void PerformOpcodeOverrides( |
| absl::flat_hash_set<OpcodeSpecCtx *> overridden_ops_set, Slot *slot); |
| void PreProcessDeclarations(const std::vector<DeclarationCtx *> &ctx_vec); |
| void ProcessOpcodeList( |
| OpcodeListCtx *ctx, Slot *slot, |
| std::vector<Instruction *> &instruction_vec, |
| absl::flat_hash_set<std::string> &deleted_ops_set, |
| absl::flat_hash_set<OpcodeSpecCtx *> &overridden_ops_set); |
| void ProcessOpcodeSpec( |
| OpcodeSpecCtx *opcode_ctx, Slot *slot, |
| std::vector<Instruction *> &instruction_vec, |
| absl::flat_hash_set<std::string> &deleted_ops_set, |
| absl::flat_hash_set<OpcodeSpecCtx *> &overridden_ops_set); |
| // Process the GENERATE() directive. |
| absl::Status ProcessOpcodeGenerator( |
| OpcodeSpecCtx *ctx, Slot *slot, |
| std::vector<Instruction *> &instruction_vec, |
| absl::flat_hash_set<std::string> &deleted_ops_set, |
| absl::flat_hash_set<OpcodeSpecCtx *> &overridden_ops_set); |
| // Helper function fused by ProcessOpcodeGenerator. |
| std::string GenerateOpcodeSpec( |
| const std::vector<RangeAssignmentInfo *> &range_info_vec, int index, |
| const std::string &template_str_in) const; |
| // These methods parses the disassembly format string. |
| absl::Status ParseDisasmFormat(std::string format, Instruction *inst); |
| absl::StatusOr<std::string> ParseNumberFormat(std::string format); |
| absl::StatusOr<FormatInfo *> ParseFormatExpression(std::string expr, |
| Opcode *op); |
| |
| // Generate file prologues/epilogues. |
| std::string GenerateHdrFileProlog(absl::string_view file_name, |
| absl::string_view opcode_file_name, |
| absl::string_view guard_name, |
| absl::string_view encoding_base_name, |
| const std::vector<std::string> &namespaces); |
| std::tuple<std::string, std::string> GenerateEncFilePrologs( |
| absl::string_view file_name, absl::string_view guard_name, |
| absl::string_view opcode_file_name, absl::string_view encoding_type_name, |
| const std::vector<std::string> &namespaces); |
| std::string GenerateHdrFileEpilog(absl::string_view guard_name, |
| const std::vector<std::string> &namespaces); |
| std::string GenerateCcFileProlog(absl::string_view hdr_file_name, |
| const std::vector<std::string> &namespaces); |
| std::string GenerateNamespaceEpilog( |
| const std::vector<std::string> &namespaces); |
| std::string GenerateSimpleHdrProlog( |
| absl::string_view guard_name, const std::vector<std::string> &namespaces); |
| |
| // Error handler. |
| decoder::DecoderErrorListener *error_listener() const { |
| return error_listener_.get(); |
| } |
| void set_error_listener( |
| std::unique_ptr<decoder::DecoderErrorListener> listener) { |
| error_listener_ = std::move(listener); |
| } |
| |
| std::string isa_name_; |
| |
| // Slot and bundle maps - these point to the contexts for every slot and |
| // bundle that have been declared. |
| absl::flat_hash_map<std::string, SlotDeclCtx *> slot_decl_map_; |
| absl::flat_hash_map<std::string, BundleDeclCtx *> bundle_decl_map_; |
| absl::flat_hash_map<std::string, IsaDeclCtx *> isa_decl_map_; |
| |
| // Constant map |
| absl::flat_hash_map<std::string, TemplateExpression *> constant_map_; |
| // Include file strings. |
| absl::btree_set<std::string> include_files_; |
| |
| int current_file_index_ = 0; |
| // Vector of file names. |
| std::vector<std::string> file_names_; |
| // Map from context pointer to file index. |
| absl::flat_hash_map<antlr4::ParserRuleContext *, int> context_file_map_; |
| // Include file roots. |
| std::vector<std::string> include_dir_vec_; |
| // Keep track of files that are included in case there is recursive includes. |
| std::deque<std::string> include_file_stack_; |
| // Error listening object passed to the parser. |
| std::unique_ptr<decoder::DecoderErrorListener> error_listener_; |
| // For template functions evaluators. |
| absl::flat_hash_map<std::string, TemplateFunctionEvaluator> |
| template_function_evaluators_; |
| // Disassembler field widths. |
| std::vector<TemplateExpression *> disasm_field_widths_; |
| // AntlrParserWrapper vector. |
| std::vector<IsaAntlrParserWrapper *> antlr_parser_wrappers_; |
| }; |
| |
| } // namespace instruction_set |
| } // namespace machine_description |
| } // namespace sim |
| } // namespace mpact |
| |
| #endif // MPACT_SIM_DECODER_INSTRUCTION_SET_VISITOR_H_ |