aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/MC
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-09 18:31:49 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-09 18:31:49 +0800
commit379ff50dcc7ccf977379aee68fa9d10f69065d23 (patch)
treee0fac3952d46d0bbcaea32bcfc6087c95fff2992 /backend/include/rcc/MC
parent495c675771f43cfa12ab7a426a538be72fec1805 (diff)
downloadrcc-project-379ff50dcc7ccf977379aee68fa9d10f69065d23.tar.gz
rcc-project-379ff50dcc7ccf977379aee68fa9d10f69065d23.tar.xz
[MC] Implement RV64GC assembly emission
Diffstat (limited to 'backend/include/rcc/MC')
-rw-r--r--backend/include/rcc/MC/MCCFI.h54
-rw-r--r--backend/include/rcc/MC/MCContext.h43
-rw-r--r--backend/include/rcc/MC/MCExpr.h109
-rw-r--r--backend/include/rcc/MC/MCInst.h174
-rw-r--r--backend/include/rcc/MC/MCInstPrinter.h31
-rw-r--r--backend/include/rcc/MC/MCSection.h108
-rw-r--r--backend/include/rcc/MC/MCStreamer.h93
-rw-r--r--backend/include/rcc/MC/MCSymbol.h56
8 files changed, 668 insertions, 0 deletions
diff --git a/backend/include/rcc/MC/MCCFI.h b/backend/include/rcc/MC/MCCFI.h
new file mode 100644
index 0000000..e6ac396
--- /dev/null
+++ b/backend/include/rcc/MC/MCCFI.h
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_MC_MCCFI_H
+#define RCC_MC_MCCFI_H
+
+#include "rcc/MC/MCSymbol.h"
+#include "rcc/Support/Error.h"
+
+#include <cstdint>
+#include <vector>
+
+namespace rcc::mc {
+
+enum class MCCFIOperation : std::uint8_t {
+ StartProc,
+ EndProc,
+ Sections,
+ Personality,
+ LSDA,
+ SignalFrame,
+ ReturnColumn,
+ SameValue,
+ RememberState,
+ RestoreState,
+ Offset,
+ DefCFARegister,
+ DefCFAOffset,
+ DefCFA,
+ RelativeOffset,
+ AdjustCFAOffset,
+ Escape,
+ Restore,
+ Undefined,
+ Register,
+ WindowSave,
+ NegateReturnAddressState,
+ NegateReturnAddressStateWithPC,
+ GNUArgsSize,
+ Label,
+ ValueOffset,
+};
+
+struct MCCFIInstruction final {
+ MCCFIOperation Operation = MCCFIOperation::StartProc;
+ std::vector<std::int64_t> Operands;
+ std::vector<std::uint8_t> Bytes;
+ MCSymbolRef Symbol;
+
+ [[nodiscard]] Expected<void> verify() const;
+};
+
+} // namespace rcc::mc
+
+#endif // RCC_MC_MCCFI_H
diff --git a/backend/include/rcc/MC/MCContext.h b/backend/include/rcc/MC/MCContext.h
new file mode 100644
index 0000000..e9b2d90
--- /dev/null
+++ b/backend/include/rcc/MC/MCContext.h
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_MC_MCCONTEXT_H
+#define RCC_MC_MCCONTEXT_H
+
+#include "rcc/MC/MCSection.h"
+#include "rcc/MC/MCSymbol.h"
+#include "rcc/Support/Error.h"
+
+#include <cstdint>
+#include <functional>
+#include <string>
+#include <string_view>
+#include <unordered_map>
+
+namespace rcc::mc {
+
+class MCContext final {
+public:
+ [[nodiscard]] Expected<MCSymbolRef> getOrCreateSymbol(std::string Name, MCSymbolKind Kind);
+ [[nodiscard]] Expected<MCSymbolRef> createTemporarySymbol(std::string_view Prefix);
+ [[nodiscard]] MCSymbolRef symbol(std::string_view Name) const noexcept;
+
+ [[nodiscard]] Expected<MCSectionRef> getOrCreateSection(MCSectionDesc Description);
+ [[nodiscard]] MCSectionRef section(std::string_view Name) const noexcept;
+
+private:
+ struct StringHash final {
+ using is_transparent = void; // NOLINT(readability-identifier-naming)
+
+ [[nodiscard]] std::size_t operator()(std::string_view Value) const noexcept {
+ return std::hash<std::string_view>{}(Value);
+ }
+ };
+
+ std::unordered_map<std::string, MCSymbolRef, StringHash, std::equal_to<>> Symbols;
+ std::unordered_map<std::string, MCSectionRef, StringHash, std::equal_to<>> Sections;
+ std::uint64_t NextTemporarySymbol = 0;
+};
+
+} // namespace rcc::mc
+
+#endif // RCC_MC_MCCONTEXT_H
diff --git a/backend/include/rcc/MC/MCExpr.h b/backend/include/rcc/MC/MCExpr.h
new file mode 100644
index 0000000..15ff6fd
--- /dev/null
+++ b/backend/include/rcc/MC/MCExpr.h
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_MC_MCEXPR_H
+#define RCC_MC_MCEXPR_H
+
+#include "rcc/MC/MCSymbol.h"
+#include "rcc/Support/Error.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <variant>
+
+namespace rcc::mc {
+
+class MCExpr;
+using MCExprRef = std::shared_ptr<const MCExpr>;
+
+enum class MCUnaryOperator : std::uint8_t {
+ Plus,
+ Minus,
+ BitwiseNot,
+ LogicalNot,
+};
+
+enum class MCBinaryOperator : std::uint8_t {
+ Add,
+ Subtract,
+ Multiply,
+ Divide,
+ Modulo,
+ ShiftLeft,
+ ShiftRight,
+ BitwiseAnd,
+ BitwiseOr,
+ BitwiseXor,
+ LogicalAnd,
+ LogicalOr,
+ Equal,
+ NotEqual,
+ Less,
+ LessEqual,
+ Greater,
+ GreaterEqual,
+};
+
+struct MCSymbolRefExpr final {
+ MCSymbolRef Symbol;
+};
+
+struct MCUnaryExpr final {
+ MCUnaryOperator Operator = MCUnaryOperator::Plus;
+ MCExprRef Operand;
+};
+
+struct MCBinaryExpr final {
+ MCBinaryOperator Operator = MCBinaryOperator::Add;
+ MCExprRef Left;
+ MCExprRef Right;
+};
+
+struct MCTargetExpr final {
+ std::uint32_t Kind = 0;
+ MCExprRef Operand;
+};
+
+class MCExpr final {
+public:
+ enum class Kind : std::uint8_t {
+ Constant,
+ SymbolRef,
+ Unary,
+ Binary,
+ Target,
+ };
+
+ [[nodiscard]] static MCExprRef constant(std::int64_t Value);
+ [[nodiscard]] static Expected<MCExprRef> symbol(MCSymbolRef Symbol);
+ [[nodiscard]] static Expected<MCExprRef> unary(MCUnaryOperator Operator, MCExprRef Operand);
+ [[nodiscard]] static Expected<MCExprRef> binary(MCBinaryOperator Operator, MCExprRef Left,
+ MCExprRef Right);
+ [[nodiscard]] static Expected<MCExprRef> target(std::uint32_t Kind, MCExprRef Operand);
+
+ [[nodiscard]] Kind kind() const noexcept {
+ return ExpressionKind;
+ }
+
+ template <typename ValueT> [[nodiscard]] const ValueT *getIf() const noexcept {
+ return std::get_if<ValueT>(&Storage);
+ }
+
+ [[nodiscard]] Expected<void> verify(std::size_t MaximumDepth = 256) const;
+ [[nodiscard]] std::optional<std::int64_t> evaluateAbsolute() const noexcept;
+
+private:
+ using StorageT =
+ std::variant<std::int64_t, MCSymbolRefExpr, MCUnaryExpr, MCBinaryExpr, MCTargetExpr>;
+
+ MCExpr(Kind ExpressionKind, StorageT Storage)
+ : ExpressionKind(ExpressionKind), Storage(std::move(Storage)) {}
+
+ Kind ExpressionKind;
+ StorageT Storage;
+};
+
+} // namespace rcc::mc
+
+#endif // RCC_MC_MCEXPR_H
diff --git a/backend/include/rcc/MC/MCInst.h b/backend/include/rcc/MC/MCInst.h
new file mode 100644
index 0000000..c6da93b
--- /dev/null
+++ b/backend/include/rcc/MC/MCInst.h
@@ -0,0 +1,174 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_MC_MCINST_H
+#define RCC_MC_MCINST_H
+
+#include "rcc/MC/MCExpr.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <span>
+#include <utility>
+#include <variant>
+#include <vector>
+
+namespace rcc::mc {
+
+class MCRegister final {
+public:
+ constexpr MCRegister() noexcept = default;
+
+ [[nodiscard]] static constexpr MCRegister fromValue(std::uint32_t Value) noexcept {
+ return MCRegister(Value);
+ }
+
+ [[nodiscard]] constexpr std::uint32_t value() const noexcept {
+ return Value;
+ }
+
+ [[nodiscard]] constexpr bool isValid() const noexcept {
+ return Value != 0;
+ }
+
+ friend constexpr bool operator==(MCRegister Left, MCRegister Right) noexcept = default;
+
+private:
+ explicit constexpr MCRegister(std::uint32_t Value) noexcept : Value(Value) {}
+
+ std::uint32_t Value = 0;
+};
+
+class MCOpcode final {
+public:
+ constexpr MCOpcode() noexcept = default;
+
+ [[nodiscard]] static constexpr MCOpcode fromValue(std::uint32_t Value) noexcept {
+ return MCOpcode(Value);
+ }
+
+ [[nodiscard]] constexpr std::uint32_t value() const noexcept {
+ return Value;
+ }
+
+ [[nodiscard]] constexpr bool isValid() const noexcept {
+ return Value != 0;
+ }
+
+ friend constexpr bool operator==(MCOpcode Left, MCOpcode Right) noexcept = default;
+
+private:
+ explicit constexpr MCOpcode(std::uint32_t Value) noexcept : Value(Value) {}
+
+ std::uint32_t Value = 0;
+};
+
+class MCOperand final {
+public:
+ enum class Kind : std::uint8_t {
+ Register,
+ Immediate,
+ Float32Bits,
+ Float64Bits,
+ Expression,
+ };
+
+ [[nodiscard]] static MCOperand registerOperand(MCRegister Register) noexcept {
+ return MCOperand(Kind::Register, Register);
+ }
+
+ [[nodiscard]] static MCOperand immediate(std::int64_t Value) noexcept {
+ return MCOperand(Kind::Immediate, Value);
+ }
+
+ [[nodiscard]] static MCOperand float32Bits(std::uint32_t Value) noexcept {
+ return MCOperand(Kind::Float32Bits, Value);
+ }
+
+ [[nodiscard]] static MCOperand float64Bits(std::uint64_t Value) noexcept {
+ return MCOperand(Kind::Float64Bits, Value);
+ }
+
+ [[nodiscard]] static MCOperand expression(MCExprRef Value) {
+ return MCOperand(Kind::Expression, std::move(Value));
+ }
+
+ [[nodiscard]] Kind kind() const noexcept {
+ return OperandKind;
+ }
+
+ [[nodiscard]] const MCRegister *registerValue() const noexcept {
+ return std::get_if<MCRegister>(&Storage);
+ }
+
+ [[nodiscard]] const std::int64_t *immediateValue() const noexcept {
+ return std::get_if<std::int64_t>(&Storage);
+ }
+
+ [[nodiscard]] const std::uint32_t *float32BitsValue() const noexcept {
+ return std::get_if<std::uint32_t>(&Storage);
+ }
+
+ [[nodiscard]] const std::uint64_t *float64BitsValue() const noexcept {
+ return std::get_if<std::uint64_t>(&Storage);
+ }
+
+ [[nodiscard]] const MCExprRef *expressionValue() const noexcept {
+ return std::get_if<MCExprRef>(&Storage);
+ }
+
+private:
+ using StorageT = std::variant<MCRegister, std::int64_t, std::uint32_t, std::uint64_t, MCExprRef>;
+
+ MCOperand(Kind OperandKind, StorageT Storage)
+ : OperandKind(OperandKind), Storage(std::move(Storage)) {}
+
+ Kind OperandKind;
+ StorageT Storage;
+};
+
+class MCInst final {
+public:
+ explicit MCInst(MCOpcode InstructionOpcode) : InstructionOpcode(InstructionOpcode) {}
+
+ [[nodiscard]] MCOpcode opcode() const noexcept {
+ return InstructionOpcode;
+ }
+
+ void setFlags(std::uint32_t NewFlags) noexcept {
+ Flags = NewFlags;
+ }
+
+ [[nodiscard]] std::uint32_t flags() const noexcept {
+ return Flags;
+ }
+
+ void setSourceIdentity(std::uint64_t Identity) noexcept {
+ SourceIdentity = Identity;
+ }
+
+ [[nodiscard]] std::uint64_t sourceIdentity() const noexcept {
+ return SourceIdentity;
+ }
+
+ void reserveOperands(std::size_t Count) {
+ Operands.reserve(Count);
+ }
+
+ void addOperand(MCOperand Operand) {
+ Operands.push_back(std::move(Operand));
+ }
+
+ [[nodiscard]] std::span<const MCOperand> operands() const noexcept {
+ return Operands;
+ }
+
+private:
+ MCOpcode InstructionOpcode;
+ std::uint32_t Flags = 0;
+ std::uint64_t SourceIdentity = 0;
+ std::vector<MCOperand> Operands;
+};
+
+} // namespace rcc::mc
+
+#endif // RCC_MC_MCINST_H
diff --git a/backend/include/rcc/MC/MCInstPrinter.h b/backend/include/rcc/MC/MCInstPrinter.h
new file mode 100644
index 0000000..6024ced
--- /dev/null
+++ b/backend/include/rcc/MC/MCInstPrinter.h
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_MC_MCINSTPRINTER_H
+#define RCC_MC_MCINSTPRINTER_H
+
+#include "rcc/MC/MCInst.h"
+#include "rcc/Support/Error.h"
+
+#include <cstdint>
+#include <string>
+#include <string_view>
+
+namespace rcc::mc {
+
+class MCInstPrinter {
+public:
+ virtual ~MCInstPrinter() = default;
+
+ [[nodiscard]] virtual Expected<std::string> printInstruction(const MCInst &Instruction) const = 0;
+
+ [[nodiscard]] virtual Expected<std::string>
+ printTargetExpression(std::uint32_t Kind, std::string_view Operand) const = 0;
+};
+
+[[nodiscard]] Expected<std::string> printMCExpression(const MCExpr &Expression,
+ const MCInstPrinter &Printer);
+[[nodiscard]] Expected<std::string> printMCSymbolName(std::string_view Name);
+
+} // namespace rcc::mc
+
+#endif // RCC_MC_MCINSTPRINTER_H
diff --git a/backend/include/rcc/MC/MCSection.h b/backend/include/rcc/MC/MCSection.h
new file mode 100644
index 0000000..4f76427
--- /dev/null
+++ b/backend/include/rcc/MC/MCSection.h
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_MC_MCSECTION_H
+#define RCC_MC_MCSECTION_H
+
+#include "rcc/MC/MCSymbol.h"
+#include "rcc/Support/Error.h"
+
+#include <cstdint>
+#include <initializer_list>
+#include <memory>
+#include <optional>
+#include <string>
+#include <string_view>
+
+namespace rcc::mc {
+
+enum class MCSectionKind : std::uint8_t {
+ Text,
+ ReadOnly,
+ Data,
+ BSS,
+ TLSData,
+ TLSBSS,
+ EHFrame,
+ Custom,
+};
+
+enum class MCSectionFlag : std::uint8_t {
+ Alloc,
+ Executable,
+ Writable,
+ Merge,
+ Strings,
+ TLS,
+ Group,
+ Retain,
+ Count,
+};
+
+class MCSectionFlags final {
+public:
+ constexpr MCSectionFlags() noexcept = default;
+
+ constexpr MCSectionFlags(std::initializer_list<MCSectionFlag> Flags) noexcept {
+ for (const MCSectionFlag Flag : Flags)
+ set(Flag);
+ }
+
+ constexpr void set(MCSectionFlag Flag) noexcept {
+ const auto Index = static_cast<std::uint8_t>(Flag);
+ if (Index < static_cast<std::uint8_t>(MCSectionFlag::Count))
+ Mask |= std::uint16_t{1} << Index;
+ }
+
+ [[nodiscard]] constexpr bool has(MCSectionFlag Flag) const noexcept {
+ const auto Index = static_cast<std::uint8_t>(Flag);
+ return Index < static_cast<std::uint8_t>(MCSectionFlag::Count) &&
+ (Mask & (std::uint16_t{1} << Index)) != 0;
+ }
+
+ [[nodiscard]] constexpr std::uint16_t rawValue() const noexcept {
+ return Mask;
+ }
+
+ friend constexpr bool operator==(MCSectionFlags Left, MCSectionFlags Right) noexcept = default;
+
+private:
+ std::uint16_t Mask = 0;
+};
+
+struct MCSectionDesc final {
+ std::string Name;
+ MCSectionKind Kind = MCSectionKind::Custom;
+ MCSectionFlags Flags;
+ std::uint64_t Alignment = 1;
+ std::uint64_t EntrySize = 0;
+ MCSymbolRef Group;
+ std::optional<std::uint64_t> UniqueID;
+
+ [[nodiscard]] Expected<void> verify() const;
+
+ friend bool operator==(const MCSectionDesc &Left, const MCSectionDesc &Right) = default;
+};
+
+class MCSection final {
+public:
+ [[nodiscard]] std::string_view name() const noexcept {
+ return Description.Name;
+ }
+
+ [[nodiscard]] const MCSectionDesc &description() const noexcept {
+ return Description;
+ }
+
+private:
+ explicit MCSection(MCSectionDesc Description) : Description(std::move(Description)) {}
+
+ MCSectionDesc Description;
+
+ friend class MCContext;
+};
+
+using MCSectionRef = std::shared_ptr<const MCSection>;
+
+} // namespace rcc::mc
+
+#endif // RCC_MC_MCSECTION_H
diff --git a/backend/include/rcc/MC/MCStreamer.h b/backend/include/rcc/MC/MCStreamer.h
new file mode 100644
index 0000000..3add976
--- /dev/null
+++ b/backend/include/rcc/MC/MCStreamer.h
@@ -0,0 +1,93 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_MC_MCSTREAMER_H
+#define RCC_MC_MCSTREAMER_H
+
+#include "rcc/MC/MCCFI.h"
+#include "rcc/MC/MCInst.h"
+#include "rcc/MC/MCInstPrinter.h"
+#include "rcc/MC/MCSection.h"
+#include "rcc/MC/MCSymbol.h"
+#include "rcc/Support/Error.h"
+
+#include <cstdint>
+#include <span>
+#include <string>
+#include <string_view>
+#include <unordered_set>
+
+namespace rcc::mc {
+
+enum class MCSymbolAttribute : std::uint8_t {
+ Global,
+ Weak,
+ Local,
+ Hidden,
+ Protected,
+ Function,
+ Object,
+ TLSObject,
+};
+
+class MCStreamer {
+public:
+ virtual ~MCStreamer() = default;
+
+ [[nodiscard]] virtual Expected<void> switchSection(MCSectionRef Section) = 0;
+ [[nodiscard]] virtual Expected<void> emitLabel(MCSymbolRef Symbol) = 0;
+ [[nodiscard]] virtual Expected<void> emitInstruction(const MCInst &Instruction) = 0;
+ [[nodiscard]] virtual Expected<void> emitValue(MCExprRef Value, std::uint8_t Size) = 0;
+ [[nodiscard]] virtual Expected<void> emitBytes(std::span<const std::uint8_t> Bytes) = 0;
+ [[nodiscard]] virtual Expected<void> emitZeroFill(std::uint64_t Size) = 0;
+ [[nodiscard]] virtual Expected<void> emitAlignment(std::uint64_t Alignment, std::uint8_t Fill = 0,
+ std::uint64_t MaximumBytes = 0) = 0;
+ [[nodiscard]] virtual Expected<void> emitSymbolAttribute(MCSymbolRef Symbol,
+ MCSymbolAttribute Attribute) = 0;
+ [[nodiscard]] virtual Expected<void> emitSymbolSize(MCSymbolRef Symbol, MCExprRef Size) = 0;
+ [[nodiscard]] virtual Expected<void> emitDirective(std::string_view Name,
+ std::string_view Arguments = {}) = 0;
+ [[nodiscard]] virtual Expected<void> emitCFI(const MCCFIInstruction &Instruction) = 0;
+ [[nodiscard]] virtual Expected<void> emitInlineAssembly(std::string_view Text) = 0;
+ [[nodiscard]] virtual Expected<void> emitComment(std::string_view Text) = 0;
+ [[nodiscard]] virtual Expected<void> finish() = 0;
+};
+
+class AsmTextStreamer final : public MCStreamer {
+public:
+ explicit AsmTextStreamer(const MCInstPrinter &Printer) noexcept : Printer(&Printer) {}
+
+ [[nodiscard]] Expected<void> switchSection(MCSectionRef Section) override;
+ [[nodiscard]] Expected<void> emitLabel(MCSymbolRef Symbol) override;
+ [[nodiscard]] Expected<void> emitInstruction(const MCInst &Instruction) override;
+ [[nodiscard]] Expected<void> emitValue(MCExprRef Value, std::uint8_t Size) override;
+ [[nodiscard]] Expected<void> emitBytes(std::span<const std::uint8_t> Bytes) override;
+ [[nodiscard]] Expected<void> emitZeroFill(std::uint64_t Size) override;
+ [[nodiscard]] Expected<void> emitAlignment(std::uint64_t Alignment, std::uint8_t Fill = 0,
+ std::uint64_t MaximumBytes = 0) override;
+ [[nodiscard]] Expected<void> emitSymbolAttribute(MCSymbolRef Symbol,
+ MCSymbolAttribute Attribute) override;
+ [[nodiscard]] Expected<void> emitSymbolSize(MCSymbolRef Symbol, MCExprRef Size) override;
+ [[nodiscard]] Expected<void> emitDirective(std::string_view Name,
+ std::string_view Arguments = {}) override;
+ [[nodiscard]] Expected<void> emitCFI(const MCCFIInstruction &Instruction) override;
+ [[nodiscard]] Expected<void> emitInlineAssembly(std::string_view Text) override;
+ [[nodiscard]] Expected<void> emitComment(std::string_view Text) override;
+ [[nodiscard]] Expected<void> finish() override;
+
+ [[nodiscard]] Expected<std::string> takeOutput();
+
+private:
+ [[nodiscard]] Expected<void> appendLine(std::string_view Prefix, std::string_view Text);
+ [[nodiscard]] Expected<void> requireActiveSection() const;
+
+ const MCInstPrinter *Printer;
+ MCSectionRef CurrentSection;
+ std::unordered_set<std::string> DefinedSymbols;
+ std::string Output;
+ bool IsFinished = false;
+ bool OutputWasTaken = false;
+};
+
+} // namespace rcc::mc
+
+#endif // RCC_MC_MCSTREAMER_H
diff --git a/backend/include/rcc/MC/MCSymbol.h b/backend/include/rcc/MC/MCSymbol.h
new file mode 100644
index 0000000..1b7b878
--- /dev/null
+++ b/backend/include/rcc/MC/MCSymbol.h
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_MC_MCSYMBOL_H
+#define RCC_MC_MCSYMBOL_H
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <string_view>
+
+namespace rcc::mc {
+
+class MCContext;
+
+enum class MCSymbolKind : std::uint8_t {
+ Generic,
+ Function,
+ Object,
+ BasicBlock,
+ ConstantPool,
+ JumpTable,
+ LiteralIsland,
+ Section,
+ Temporary,
+};
+
+class MCSymbol final {
+public:
+ [[nodiscard]] std::string_view name() const noexcept {
+ return Name;
+ }
+
+ [[nodiscard]] MCSymbolKind kind() const noexcept {
+ return Kind;
+ }
+
+ [[nodiscard]] bool isTemporary() const noexcept {
+ return Kind == MCSymbolKind::Temporary || Kind == MCSymbolKind::BasicBlock ||
+ Kind == MCSymbolKind::ConstantPool || Kind == MCSymbolKind::JumpTable ||
+ Kind == MCSymbolKind::LiteralIsland;
+ }
+
+private:
+ MCSymbol(std::string Name, MCSymbolKind Kind) : Name(std::move(Name)), Kind(Kind) {}
+
+ std::string Name;
+ MCSymbolKind Kind;
+
+ friend class MCContext;
+};
+
+using MCSymbolRef = std::shared_ptr<const MCSymbol>;
+
+} // namespace rcc::mc
+
+#endif // RCC_MC_MCSYMBOL_H