diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-07 01:27:41 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-07 01:27:41 +0800 |
| commit | 76d89700953ddd81cf31ab8f260eddf67e93aa85 (patch) | |
| tree | c96a453164154b2d1559cea36910df52103f0f19 /backend/lib/MIR/MIParser.cpp | |
| parent | 183e2354e9fdd107be420cbb185c1d239434aa48 (diff) | |
| download | rcc-project-76d89700953ddd81cf31ab8f260eddf67e93aa85.tar.gz rcc-project-76d89700953ddd81cf31ab8f260eddf67e93aa85.tar.xz | |
[MIR] Complete document parsing and printing
Implement the single LLVM-compatible MIR document path with structured\nembedded-IR references, YAML mappings, constants, and deterministic printing.\n\nKeep pointer LLT widths DataLayout-derived, reject layout-dependent output\nwhen embedded IR is omitted, and record the fixed-baseline compatibility\ncontract and regression coverage.
Diffstat (limited to 'backend/lib/MIR/MIParser.cpp')
| -rw-r--r-- | backend/lib/MIR/MIParser.cpp | 154 |
1 files changed, 43 insertions, 111 deletions
diff --git a/backend/lib/MIR/MIParser.cpp b/backend/lib/MIR/MIParser.cpp index b632415..ecf4986 100644 --- a/backend/lib/MIR/MIParser.cpp +++ b/backend/lib/MIR/MIParser.cpp @@ -13,6 +13,7 @@ #include "rcc/CodeGen/TargetDescription.h" #include "rcc/CodeGen/TargetMIRTextInfo.h" #include "rcc/CodeGen/TargetRegisterInfo.h" +#include "rcc/MIR/MIDebugSyntax.h" #include "rcc/MIR/MILexer.h" #include <algorithm> @@ -23,6 +24,7 @@ #include <cstddef> #include <cstdint> #include <cstring> +#include <iterator> #include <limits> #include <memory> #include <optional> @@ -256,106 +258,6 @@ namespace { return static_cast<std::uint16_t>(Bits >> 16U); } -[[nodiscard]] std::optional<std::uint64_t> debugExpressionOpcode(std::string_view Name) noexcept { - if (Name.starts_with("DW_OP_lit")) { - std::uint64_t Index = 0; - if (parseUnsignedDigits(Name.substr(9), Index) && Index <= 31) - return 0x30U + Index; - } - if (Name.starts_with("DW_OP_reg")) { - std::uint64_t Index = 0; - if (parseUnsignedDigits(Name.substr(9), Index) && Index <= 31) - return 0x50U + Index; - } - if (Name.starts_with("DW_OP_breg")) { - std::uint64_t Index = 0; - if (parseUnsignedDigits(Name.substr(10), Index) && Index <= 31) - return 0x70U + Index; - } - - constexpr auto NamedOpcodes = std::to_array<std::pair<std::string_view, std::uint64_t>>({ - {"DW_OP_addr", 0x03}, - {"DW_OP_deref", 0x06}, - {"DW_OP_const1u", 0x08}, - {"DW_OP_const1s", 0x09}, - {"DW_OP_const2u", 0x0A}, - {"DW_OP_const2s", 0x0B}, - {"DW_OP_const4u", 0x0C}, - {"DW_OP_const4s", 0x0D}, - {"DW_OP_const8u", 0x0E}, - {"DW_OP_const8s", 0x0F}, - {"DW_OP_constu", 0x10}, - {"DW_OP_consts", 0x11}, - {"DW_OP_dup", 0x12}, - {"DW_OP_drop", 0x13}, - {"DW_OP_over", 0x14}, - {"DW_OP_pick", 0x15}, - {"DW_OP_swap", 0x16}, - {"DW_OP_rot", 0x17}, - {"DW_OP_xderef", 0x18}, - {"DW_OP_abs", 0x19}, - {"DW_OP_and", 0x1A}, - {"DW_OP_div", 0x1B}, - {"DW_OP_minus", 0x1C}, - {"DW_OP_mod", 0x1D}, - {"DW_OP_mul", 0x1E}, - {"DW_OP_neg", 0x1F}, - {"DW_OP_not", 0x20}, - {"DW_OP_or", 0x21}, - {"DW_OP_plus", 0x22}, - {"DW_OP_plus_uconst", 0x23}, - {"DW_OP_shl", 0x24}, - {"DW_OP_shr", 0x25}, - {"DW_OP_shra", 0x26}, - {"DW_OP_xor", 0x27}, - {"DW_OP_bra", 0x28}, - {"DW_OP_eq", 0x29}, - {"DW_OP_ge", 0x2A}, - {"DW_OP_gt", 0x2B}, - {"DW_OP_le", 0x2C}, - {"DW_OP_lt", 0x2D}, - {"DW_OP_ne", 0x2E}, - {"DW_OP_skip", 0x2F}, - {"DW_OP_regx", 0x90}, - {"DW_OP_fbreg", 0x91}, - {"DW_OP_bregx", 0x92}, - {"DW_OP_piece", 0x93}, - {"DW_OP_deref_size", 0x94}, - {"DW_OP_xderef_size", 0x95}, - {"DW_OP_nop", 0x96}, - {"DW_OP_push_object_address", 0x97}, - {"DW_OP_call2", 0x98}, - {"DW_OP_call4", 0x99}, - {"DW_OP_call_ref", 0x9A}, - {"DW_OP_form_tls_address", 0x9B}, - {"DW_OP_call_frame_cfa", 0x9C}, - {"DW_OP_bit_piece", 0x9D}, - {"DW_OP_implicit_value", 0x9E}, - {"DW_OP_stack_value", 0x9F}, - {"DW_OP_implicit_pointer", 0xA0}, - {"DW_OP_addrx", 0xA1}, - {"DW_OP_constx", 0xA2}, - {"DW_OP_entry_value", 0xA3}, - {"DW_OP_const_type", 0xA4}, - {"DW_OP_regval_type", 0xA5}, - {"DW_OP_deref_type", 0xA6}, - {"DW_OP_xderef_type", 0xA7}, - {"DW_OP_convert", 0xA8}, - {"DW_OP_reinterpret", 0xA9}, - {"DW_OP_LLVM_fragment", 0x1000}, - {"DW_OP_LLVM_convert", 0x1001}, - {"DW_OP_LLVM_tag_offset", 0x1002}, - {"DW_OP_LLVM_entry_value", 0x1003}, - {"DW_OP_LLVM_implicit_pointer", 0x1004}, - {"DW_OP_LLVM_arg", 0x1005}, - }); - const auto *const Found = - std::ranges::find_if(NamedOpcodes, [Name](const auto &Entry) { return Entry.first == Name; }); - if (Found == NamedOpcodes.end()) - return std::nullopt; - return Found->second; -} - [[nodiscard]] std::optional<std::uint64_t> minimumTypeSizeInBits(LLT Type) noexcept { if (!Type.isValid() || Type.isToken()) return std::nullopt; @@ -817,6 +719,13 @@ bool MIParser::Impl::parseScalarLowLevelType(const MIToken &TypeToken, LLT &Resu Created = LLT::makeFloat(FloatSemantics::BFloat); break; case ScalarKind::Pointer: + if (Context.PointerSizeInBits) { + auto PointerSize = Context.PointerSizeInBits(static_cast<std::uint32_t>(Value)); + if (!PointerSize) + return importError(TypeToken, PointerSize.error()); + Created = LLT::makePointer(Value, *PointerSize); + break; + } if (Context.DefaultPointerSizeInBits == 0) return fail(TypeToken, "pointer low-level type requires an explicit pointer size"); Created = LLT::makePointer(Value, Context.DefaultPointerSizeInBits); @@ -1335,7 +1244,9 @@ std::optional<JumpTableIndex> MIParser::Impl::jumpTableIndexFor(const MIToken &T return std::nullopt; } for (const MIJumpTableSlot &Slot : Context.JumpTables) { - if (Slot.TextID == ID && Function.jumpTableInfo().table(Slot.Index) != nullptr) + if (Slot.TextID == ID && (Function.jumpTableInfo().table(Slot.Index) != nullptr || + (Slot.Index.value() < Function.jumpTableInfo().tables().size() && + Function.jumpTableInfo().tables()[Slot.Index.value()].isPending()))) return Slot.Index; } static_cast<void>(fail(Token, "use of undefined jump table #" + std::to_string(ID))); @@ -1566,7 +1477,7 @@ bool MIParser::Impl::parseMetadataOperand(ParsedOperand &Result) { std::vector<std::uint64_t> Elements; while (!at(MITokenKind::RightParen)) { if (at(MITokenKind::Identifier)) { - const auto Opcode = debugExpressionOpcode(token().stringValue()); + const auto Opcode = parseDIExpressionOpcodeName(token().stringValue()); if (!Opcode) return fail("unknown debug expression opcode '" + std::string(token().stringValue()) + "'"); @@ -2036,8 +1947,16 @@ bool MIParser::Impl::parseMemoryOperand(const MachineMemOperand *&Result) { if (!at(MITokenKind::StringConstant)) return fail("syncscope requires a quoted scope name"); const std::string_view Name = token().stringValue(); - const auto Scope = std::ranges::find_if( + auto Scope = std::ranges::find_if( Context.SyncScopes, [Name](const MISyncScopeSlot &Slot) { return Slot.Name == Name; }); + if (Scope == Context.SyncScopes.end() && Context.InternSyncScope) { + const MIToken NameToken = token(); + auto ID = Context.InternSyncScope(Name); + if (!ID) + return importError(NameToken, ID.error()); + Context.SyncScopes.push_back({.Name = std::string(Name), .ID = *ID}); + Scope = std::prev(Context.SyncScopes.end()); + } if (Scope == Context.SyncScopes.end()) return fail("unknown synchronization scope '" + std::string(Name) + "'"); Description.SyncScope = Scope->ID; @@ -2994,20 +2913,33 @@ Expected<void> MIParser::Impl::parse() { return makeUnexpected(ErrorCode::InvalidArgument, "MI parser requires a staging machine function with an empty body"); } + for (const MIVirtualRegisterSlot &Slot : Context.VirtualRegisters) { + if (!Slot.Reg.isVirtual() || !Function.registerInfo().isKnownVirtualRegister(Slot.Reg)) { + return makeUnexpected(ErrorCode::InvalidArgument, + "MI parser virtual-register slot maps to an unknown register"); + } + if (!NumericVirtualRegisters.emplace(Slot.TextID, Slot.Reg).second) { + return makeUnexpected(ErrorCode::InvalidArgument, + "MI parser virtual-register text IDs must be unique"); + } + } if (tokenize()) return failureResult(); if (parseFirstPass() || parseSecondPass() || inferSuccessors()) return failureResult(); Function.renumberBlocks(); - auto Verified = MachineVerifier::verify( - Function, Target, - MachineVerifierOptions{ - .Mode = MachineVerifierMode::Generic, .Stage = std::nullopt, .VerifyProperties = false}); - if (!Verified) { - static_cast<void>(fail(token(), "parsed machine function failed verification: " + - std::string(Verified.error().message()))); - return failureResult(); + if (Options.VerifyAfterParse) { + auto Verified = + MachineVerifier::verify(Function, Target, + MachineVerifierOptions{.Mode = MachineVerifierMode::Generic, + .Stage = std::nullopt, + .VerifyProperties = false}); + if (!Verified) { + static_cast<void>(fail(token(), "parsed machine function failed verification: " + + std::string(Verified.error().message()))); + return failureResult(); + } } return {}; } |
