aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/MIR/MIDebugSyntax.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-11 17:37:42 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-11 17:37:42 +0800
commit6a7b083f322f4ac47e58cbf9d4d5fd4d1f6fecd0 (patch)
treef363c502f0e2b9cda2f12928049275a433db6ad4 /backend/lib/MIR/MIDebugSyntax.cpp
parentadcf8c9b1bd1b47e00bf859693112cea1f7e8c9f (diff)
downloadrcc-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.cpp179
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