diff options
| author | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-11 17:37:42 +0800 |
|---|---|---|
| committer | Richard-Qin-X <richard.qin.001@gmail.com> | 2026-08-11 17:37:42 +0800 |
| commit | 6a7b083f322f4ac47e58cbf9d4d5fd4d1f6fecd0 (patch) | |
| tree | f363c502f0e2b9cda2f12928049275a433db6ad4 /backend/lib/MIR/MIDebugSyntax.cpp | |
| parent | adcf8c9b1bd1b47e00bf859693112cea1f7e8c9f (diff) | |
| download | rcc-project-6a7b083f322f4ac47e58cbf9d4d5fd4d1f6fecd0.tar.gz rcc-project-6a7b083f322f4ac47e58cbf9d4d5fd4d1f6fecd0.tar.xz | |
[MIR] Accept fixed-baseline LLVM syntax
Diffstat (limited to 'backend/lib/MIR/MIDebugSyntax.cpp')
| -rw-r--r-- | backend/lib/MIR/MIDebugSyntax.cpp | 179 |
1 files changed, 159 insertions, 20 deletions
diff --git a/backend/lib/MIR/MIDebugSyntax.cpp b/backend/lib/MIR/MIDebugSyntax.cpp index fc08df6..e614a21 100644 --- a/backend/lib/MIR/MIDebugSyntax.cpp +++ b/backend/lib/MIR/MIDebugSyntax.cpp @@ -5,7 +5,10 @@ #include <array> #include <charconv> #include <cstdint> +#include <optional> #include <ranges> +#include <span> +#include <string> #include <string_view> #include <system_error> #include <utility> @@ -20,26 +23,8 @@ namespace { return Error == std::errc{} && End == Text.data() + Text.size(); } -} // namespace - -std::optional<std::uint64_t> parseDIExpressionOpcodeName(std::string_view Name) noexcept { - const auto NumberedOpcode = [Name](std::string_view Prefix, - std::uint64_t Base) -> std::optional<std::uint64_t> { - if (!Name.starts_with(Prefix)) - return std::nullopt; - std::uint64_t Index = 0; - if (!parseIndex(Name.substr(Prefix.size()), Index) || Index > 31) - return std::nullopt; - return Base + Index; - }; - if (auto Opcode = NumberedOpcode("DW_OP_lit", 0x30U)) - return Opcode; - if (auto Opcode = NumberedOpcode("DW_OP_reg", 0x50U)) - return Opcode; - if (auto Opcode = NumberedOpcode("DW_OP_breg", 0x70U)) - return Opcode; - - constexpr auto NamedOpcodes = std::to_array<std::pair<std::string_view, std::uint64_t>>({ +[[nodiscard]] const auto &namedOpcodes() { + static constexpr auto Opcodes = std::to_array<std::pair<std::string_view, std::uint64_t>>({ {"DW_OP_addr", 0x03}, {"DW_OP_deref", 0x06}, {"DW_OP_const1u", 0x08}, @@ -114,7 +99,104 @@ std::optional<std::uint64_t> parseDIExpressionOpcodeName(std::string_view Name) {"DW_OP_LLVM_entry_value", 0x1003}, {"DW_OP_LLVM_implicit_pointer", 0x1004}, {"DW_OP_LLVM_arg", 0x1005}, + {"DW_OP_LLVM_extract_bits_sext", 0x1006}, + {"DW_OP_LLVM_extract_bits_zext", 0x1007}, }); + return Opcodes; +} + +[[nodiscard]] const auto &attributeEncodings() { + static constexpr auto Encodings = std::to_array<std::pair<std::string_view, std::uint64_t>>({ + {"DW_ATE_address", 0x01}, + {"DW_ATE_boolean", 0x02}, + {"DW_ATE_complex_float", 0x03}, + {"DW_ATE_float", 0x04}, + {"DW_ATE_signed", 0x05}, + {"DW_ATE_signed_char", 0x06}, + {"DW_ATE_unsigned", 0x07}, + {"DW_ATE_unsigned_char", 0x08}, + {"DW_ATE_imaginary_float", 0x09}, + {"DW_ATE_packed_decimal", 0x0A}, + {"DW_ATE_numeric_string", 0x0B}, + {"DW_ATE_edited", 0x0C}, + {"DW_ATE_signed_fixed", 0x0D}, + {"DW_ATE_unsigned_fixed", 0x0E}, + {"DW_ATE_decimal_float", 0x0F}, + {"DW_ATE_UTF", 0x10}, + {"DW_ATE_UCS", 0x11}, + {"DW_ATE_ASCII", 0x12}, + }); + return Encodings; +} + +[[nodiscard]] std::optional<std::string> opcodeName(std::uint64_t Opcode) { + if (Opcode >= 0x30U && Opcode <= 0x4FU) + return "DW_OP_lit" + std::to_string(Opcode - 0x30U); + if (Opcode >= 0x50U && Opcode <= 0x6FU) + return "DW_OP_reg" + std::to_string(Opcode - 0x50U); + if (Opcode >= 0x70U && Opcode <= 0x8FU) + return "DW_OP_breg" + std::to_string(Opcode - 0x70U); + const auto &Opcodes = namedOpcodes(); + const auto Found = + std::ranges::find_if(Opcodes, [Opcode](const auto &Entry) { return Entry.second == Opcode; }); + if (Found == Opcodes.end()) + return std::nullopt; + return std::string(Found->first); +} + +[[nodiscard]] std::size_t opcodeSize(std::uint64_t Opcode) noexcept { + if (Opcode >= 0x70U && Opcode <= 0x8FU) + return 2; + switch (Opcode) { + case 0x92: + case 0x1000: + case 0x1001: + case 0x1006: + case 0x1007: + return 3; + case 0x10: + case 0x11: + case 0x23: + case 0x90: + case 0x94: + case 0x1002: + case 0x1003: + case 0x1005: + return 2; + default: + return 1; + } +} + +[[nodiscard]] std::optional<std::string_view> attributeName(std::uint64_t Encoding) noexcept { + const auto &Encodings = attributeEncodings(); + const auto Found = std::ranges::find_if( + Encodings, [Encoding](const auto &Entry) { return Entry.second == Encoding; }); + if (Found == Encodings.end()) + return std::nullopt; + return Found->first; +} + +} // namespace + +std::optional<std::uint64_t> parseDIExpressionOpcodeName(std::string_view Name) noexcept { + const auto NumberedOpcode = [Name](std::string_view Prefix, + std::uint64_t Base) -> std::optional<std::uint64_t> { + if (!Name.starts_with(Prefix)) + return std::nullopt; + std::uint64_t Index = 0; + if (!parseIndex(Name.substr(Prefix.size()), Index) || Index > 31) + return std::nullopt; + return Base + Index; + }; + if (auto Opcode = NumberedOpcode("DW_OP_lit", 0x30U)) + return Opcode; + if (auto Opcode = NumberedOpcode("DW_OP_reg", 0x50U)) + return Opcode; + if (auto Opcode = NumberedOpcode("DW_OP_breg", 0x70U)) + return Opcode; + + const auto &NamedOpcodes = namedOpcodes(); const auto *const Found = std::ranges::find_if(NamedOpcodes, [Name](const auto &Entry) { return Entry.first == Name; }); if (Found == NamedOpcodes.end()) @@ -122,4 +204,61 @@ std::optional<std::uint64_t> parseDIExpressionOpcodeName(std::string_view Name) return Found->second; } +std::optional<std::uint64_t> +parseDIExpressionAttributeEncodingName(std::string_view Name) noexcept { + const auto &Encodings = attributeEncodings(); + const auto Found = + std::ranges::find_if(Encodings, [Name](const auto &Entry) { return Entry.first == Name; }); + if (Found == Encodings.end()) + return std::nullopt; + return Found->second; +} + +std::string invalidDIExpressionElementMessage(std::string_view Name) { + if (Name.starts_with("DW_OP_")) + return "invalid DWARF op '" + std::string(Name) + "'"; + if (Name.starts_with("DW_ATE_")) + return "invalid DWARF attribute encoding '" + std::string(Name) + "'"; + return "expected unsigned integer"; +} + +std::string formatDIExpression(std::span<const std::uint64_t> Elements) { + std::string Result = "!DIExpression("; + std::size_t Position = 0; + bool First = true; + while (Position < Elements.size()) { + const std::uint64_t Opcode = Elements[Position]; + const auto Name = opcodeName(Opcode); + const std::size_t Size = opcodeSize(Opcode); + if (!Name || Position + Size > Elements.size()) { + Result = "!DIExpression("; + for (std::size_t Index = 0; Index < Elements.size(); ++Index) { + if (Index != 0) + Result.append(", "); + Result.append(std::to_string(Elements[Index])); + } + Result.push_back(')'); + return Result; + } + + if (!First) + Result.append(", "); + First = false; + Result.append(*Name); + for (std::size_t Argument = 1; Argument < Size; ++Argument) { + Result.append(", "); + if (Opcode == 0x1001U && Argument == 2U) { + if (const auto Encoding = attributeName(Elements[Position + Argument])) { + Result.append(*Encoding); + continue; + } + } + Result.append(std::to_string(Elements[Position + Argument])); + } + Position += Size; + } + Result.push_back(')'); + return Result; +} + } // namespace rcc::mir |
