| // 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 <deque> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #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/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/opcode.h" |
| #include "mpact/sim/decoder/slot.h" |
| #include "mpact/sim/decoder/template_expression.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 { |
| |
| 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_) {} |
| }; |
| |
| // Type aliases for antlr4 context types. |
| using TopLevelCtx = InstructionSetParser::Top_levelContext; |
| using NamespaceDeclCtx = InstructionSetParser::Namespace_declContext; |
| using ConstantDefCtx = InstructionSetParser::Constant_defContext; |
| using IncludeFileCtx = InstructionSetParser::Include_fileContext; |
| using DeclarationCtx = InstructionSetParser::DeclarationContext; |
| using IsaDeclCtx = InstructionSetParser::Isa_declarationContext; |
| using BundleDeclCtx = InstructionSetParser::Bundle_declarationContext; |
| using SlotDeclCtx = InstructionSetParser::Slot_declarationContext; |
| using BaseItemListCtx = InstructionSetParser::Base_item_listContext; |
| using ExpressionCtx = InstructionSetParser::ExpressionContext; |
| using ArraySpecCtx = InstructionSetParser::Array_specContext; |
| using OpcodeSpecCtx = InstructionSetParser::Opcode_specContext; |
| using BundleListCtx = InstructionSetParser::Bundle_listContext; |
| using SlotListCtx = InstructionSetParser::Slot_listContext; |
| using OpcodeListCtx = InstructionSetParser::Opcode_listContext; |
| using OpcodeOperandsCtx = InstructionSetParser::Opcode_operandsContext; |
| using IdentListCtx = InstructionSetParser::Ident_listContext; |
| using DisasmWidthsCtx = InstructionSetParser::Disasm_widthsContext; |
| using ConstAndDefaultCtx = |
| InstructionSetParser::Const_and_default_declContext; |
| using OpcodeAttributeListCtx = |
| InstructionSetParser::Opcode_attribute_listContext; |
| using InstructionAttributeListCtx = |
| InstructionSetParser::Instruction_attribute_listContext; |
| using SemfuncSpecCtx = InstructionSetParser::Semfunc_specContext; |
| using ResourceItemCtx = InstructionSetParser::Resource_itemContext; |
| using ResourceDetailsCtx = InstructionSetParser::Resource_detailsContext; |
| // Checks that any references to slots or bundles within a bundle |
| // declaration are to valid slots/bundles. |
| absl::Status 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) const; |
| 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); |
| |
| // 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::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_; |
| |
| // 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_ |