aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc
diff options
context:
space:
mode:
Diffstat (limited to 'backend/include/rcc')
-rw-r--r--backend/include/rcc/CodeGen/AsmPrinter.h57
-rw-r--r--backend/include/rcc/CodeGen/CompilationUnit.h13
-rw-r--r--backend/include/rcc/CodeGen/GlobalObject.h196
-rw-r--r--backend/include/rcc/CodeGen/MachineMCContext.h68
-rw-r--r--backend/include/rcc/CodeGen/TargetMCInstLowering.h69
-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
-rw-r--r--backend/include/rcc/Support/Error.h1
-rw-r--r--backend/include/rcc/Target/RISCV/RISCVAssemblyPrinter.h35
-rw-r--r--backend/include/rcc/Target/RISCV/RISCVInstPrinter.h36
-rw-r--r--backend/include/rcc/Target/RISCV/RISCVMCTargetLowering.h62
17 files changed, 1205 insertions, 0 deletions
diff --git a/backend/include/rcc/CodeGen/AsmPrinter.h b/backend/include/rcc/CodeGen/AsmPrinter.h
new file mode 100644
index 0000000..82bad7d
--- /dev/null
+++ b/backend/include/rcc/CodeGen/AsmPrinter.h
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_ASMPRINTER_H
+#define RCC_CODEGEN_ASMPRINTER_H
+
+#include "rcc/Support/Error.h"
+
+namespace rcc {
+
+class CompilationUnit;
+class MachineFunction;
+class MachineMCContext;
+class TargetDescription;
+class TargetMCInstLowering;
+
+namespace mc {
+class MCStreamer;
+} // namespace mc
+
+struct AsmPrinterOptions final {
+ bool EmitFunctionDirectives = true;
+ bool EmitCFI = true;
+ bool EmitBlockLabels = true;
+ bool EmitInstructionSymbols = true;
+ bool VerifyInput = true;
+};
+
+class AsmPrinter final {
+public:
+ AsmPrinter(const TargetDescription &Target, const TargetMCInstLowering &Lowering,
+ MachineMCContext &Context, mc::MCStreamer &Streamer,
+ AsmPrinterOptions Options = {}) noexcept
+ : Target(&Target), Lowering(&Lowering), Context(&Context), Streamer(&Streamer),
+ Options(Options) {}
+
+ [[nodiscard]] Expected<void> emitCompilationUnit(const CompilationUnit &Unit);
+ [[nodiscard]] Expected<void> emitFunction(const MachineFunction &Function);
+
+private:
+ [[nodiscard]] Expected<void> verifyFunction(const MachineFunction &Function) const;
+ [[nodiscard]] Expected<void> emitGlobalObjects(const CompilationUnit &Unit);
+ [[nodiscard]] Expected<void> emitFunctionBody(const MachineFunction &Function);
+ [[nodiscard]] Expected<void> emitConstantPool(const MachineFunction &Function);
+ [[nodiscard]] Expected<void> emitJumpTables(const MachineFunction &Function);
+
+ const TargetDescription *Target;
+ const TargetMCInstLowering *Lowering;
+ MachineMCContext *Context;
+ mc::MCStreamer *Streamer;
+ AsmPrinterOptions Options;
+ bool UnitEmissionStarted = false;
+ bool UnitEmissionFinished = false;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_ASMPRINTER_H
diff --git a/backend/include/rcc/CodeGen/CompilationUnit.h b/backend/include/rcc/CodeGen/CompilationUnit.h
index d798438..14fd86f 100644
--- a/backend/include/rcc/CodeGen/CompilationUnit.h
+++ b/backend/include/rcc/CodeGen/CompilationUnit.h
@@ -3,6 +3,7 @@
#ifndef RCC_CODEGEN_COMPILATIONUNIT_H
#define RCC_CODEGEN_COMPILATIONUNIT_H
+#include "rcc/CodeGen/GlobalObject.h"
#include "rcc/CodeGen/StableID.h"
#include "rcc/Support/Error.h"
@@ -28,6 +29,7 @@ public:
~CompilationUnit();
[[nodiscard]] Expected<MachineFunction *> createMachineFunction(std::string Name);
+ [[nodiscard]] Expected<GlobalObjectDesc *> addGlobalObject(GlobalObjectDesc Object);
[[nodiscard]] std::size_t functionCount() const noexcept {
return Functions.size();
@@ -40,6 +42,15 @@ public:
[[nodiscard]] MachineFunction *function(MachineFunctionStableID ID) noexcept;
[[nodiscard]] const MachineFunction *function(MachineFunctionStableID ID) const noexcept;
+ [[nodiscard]] std::size_t globalObjectCount() const noexcept {
+ return GlobalObjects.size();
+ }
+
+ [[nodiscard]] GlobalObjectDesc *globalObjectAt(std::size_t Index) noexcept;
+ [[nodiscard]] const GlobalObjectDesc *globalObjectAt(std::size_t Index) const noexcept;
+ [[nodiscard]] GlobalObjectDesc *globalObject(std::string_view Name) noexcept;
+ [[nodiscard]] const GlobalObjectDesc *globalObject(std::string_view Name) const noexcept;
+
[[nodiscard]] Expected<void> verify() const;
private:
@@ -53,6 +64,8 @@ private:
std::vector<std::unique_ptr<MachineFunction>> Functions;
std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> FunctionNameToIndex;
+ std::vector<std::unique_ptr<GlobalObjectDesc>> GlobalObjects;
+ std::unordered_map<std::string, std::size_t, StringHash, std::equal_to<>> GlobalNameToIndex;
StableIDGenerator<MachineFunctionStableID> FunctionIDGenerator;
};
diff --git a/backend/include/rcc/CodeGen/GlobalObject.h b/backend/include/rcc/CodeGen/GlobalObject.h
new file mode 100644
index 0000000..49f1f42
--- /dev/null
+++ b/backend/include/rcc/CodeGen/GlobalObject.h
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_GLOBALOBJECT_H
+#define RCC_CODEGEN_GLOBALOBJECT_H
+
+#include "rcc/CodeGen/GenericConstant.h"
+#include "rcc/CodeGen/MachineIRTypes.h"
+#include "rcc/CodeGen/TargetConstant.h"
+#include "rcc/Support/Error.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+#include <variant>
+#include <vector>
+
+namespace rcc {
+
+class GlobalInitializer;
+using GlobalInitializerRef = std::shared_ptr<const GlobalInitializer>;
+
+struct GlobalZeroFill final {
+ std::uint64_t Size = 0;
+};
+
+struct GlobalRepeatedInitializer final {
+ std::uint64_t Count = 0;
+ GlobalInitializerRef Value;
+};
+
+struct GlobalAggregateInitializer final {
+ std::vector<GlobalInitializerRef> Elements;
+};
+
+struct GlobalSymbolAddress final {
+ std::string Symbol;
+ std::int64_t Addend = 0;
+ std::uint8_t Size = 8;
+ std::uint32_t TargetFlags = 0;
+};
+
+struct GlobalSymbolDifference final {
+ std::string Minuend;
+ std::string Subtrahend;
+ std::int64_t Addend = 0;
+ std::uint8_t Size = 8;
+};
+
+struct GlobalAlignmentPadding final {
+ std::uint64_t Size = 0;
+ std::uint8_t Fill = 0;
+};
+
+struct GlobalUndefinedStorage final {
+ std::uint64_t Size = 0;
+};
+
+class GlobalInitializer final {
+public:
+ enum class Kind : std::uint8_t {
+ Invalid,
+ Integer,
+ Floating,
+ Bytes,
+ ZeroFill,
+ Repeated,
+ Aggregate,
+ SymbolAddress,
+ SymbolDifference,
+ Target,
+ AlignmentPadding,
+ UndefinedStorage,
+ };
+
+ GlobalInitializer() = default;
+ GlobalInitializer(const GlobalInitializer &) = delete;
+ GlobalInitializer &operator=(const GlobalInitializer &) = delete;
+ GlobalInitializer(GlobalInitializer &&) noexcept = default;
+ GlobalInitializer &operator=(GlobalInitializer &&) noexcept = default;
+ ~GlobalInitializer() = default;
+
+ [[nodiscard]] static GlobalInitializer integer(IntegerImmediate Value);
+ [[nodiscard]] static GlobalInitializer floating(FloatingPointBits Value);
+ [[nodiscard]] static Expected<GlobalInitializer> bytes(std::vector<std::byte> Value);
+ [[nodiscard]] static Expected<GlobalInitializer> zeroFill(std::uint64_t Size);
+ [[nodiscard]] static Expected<GlobalInitializer> repeated(std::uint64_t Count,
+ GlobalInitializer Value);
+ [[nodiscard]] static Expected<GlobalInitializer>
+ aggregate(std::vector<GlobalInitializer> Elements);
+ [[nodiscard]] static Expected<GlobalInitializer> symbolAddress(GlobalSymbolAddress Value);
+ [[nodiscard]] static Expected<GlobalInitializer> symbolDifference(GlobalSymbolDifference Value);
+ [[nodiscard]] static Expected<GlobalInitializer> target(TargetConstant Value);
+ [[nodiscard]] static Expected<GlobalInitializer> alignmentPadding(std::uint64_t Size,
+ std::uint8_t Fill = 0);
+ [[nodiscard]] static Expected<GlobalInitializer> undefinedStorage(std::uint64_t Size);
+
+ [[nodiscard]] Kind kind() const noexcept;
+
+ template <typename ValueT> [[nodiscard]] const ValueT *getIf() const noexcept {
+ return std::get_if<ValueT>(&Storage);
+ }
+
+ [[nodiscard]] Expected<void> verify(std::size_t MaximumDepth = 1024) const;
+ [[nodiscard]] Expected<std::uint64_t> storageSize(std::size_t MaximumDepth = 1024) const;
+
+private:
+ using StorageT =
+ std::variant<std::monostate, IntegerImmediate, FloatingPointBits, std::vector<std::byte>,
+ GlobalZeroFill, GlobalRepeatedInitializer, GlobalAggregateInitializer,
+ GlobalSymbolAddress, GlobalSymbolDifference, TargetConstant,
+ GlobalAlignmentPadding, GlobalUndefinedStorage>;
+
+ explicit GlobalInitializer(StorageT Storage) : Storage(std::move(Storage)) {}
+
+ StorageT Storage;
+};
+
+enum class GlobalLinkage : std::uint8_t {
+ External,
+ AvailableExternally,
+ LinkOnceAny,
+ LinkOnceODR,
+ WeakAny,
+ WeakODR,
+ Appending,
+ Internal,
+ Private,
+ ExternalWeak,
+ Common,
+ Count,
+};
+
+enum class GlobalVisibility : std::uint8_t {
+ Default,
+ Hidden,
+ Protected,
+ Count,
+};
+
+enum class GlobalTLSModel : std::uint8_t {
+ None,
+ GeneralDynamic,
+ LocalDynamic,
+ InitialExec,
+ LocalExec,
+ Count,
+};
+
+enum class GlobalUnnamedAddress : std::uint8_t {
+ None,
+ Local,
+ Global,
+ Count,
+};
+
+struct GlobalObjectDesc final {
+ std::string Symbol;
+ GenericConstantType ObjectType;
+ GlobalLinkage Linkage = GlobalLinkage::External;
+ GlobalVisibility Visibility = GlobalVisibility::Default;
+ bool DSOLocal = false;
+ std::optional<std::string> Section;
+ Alignment Align;
+ std::uint64_t Size = 0;
+ std::uint32_t AddressSpace = 0;
+ GlobalTLSModel TLSModel = GlobalTLSModel::None;
+ bool ExternallyInitialized = false;
+ std::optional<std::string> COMDAT;
+ bool IsConstant = false;
+ GlobalUnnamedAddress UnnamedAddress = GlobalUnnamedAddress::None;
+ std::optional<GlobalInitializer> Initializer;
+ std::vector<std::string> DebugExpressions;
+ std::optional<OriginID> StableOrigin;
+ std::uint64_t TargetFlags = 0;
+ std::vector<std::pair<std::string, std::string>> TargetAttributes;
+
+ GlobalObjectDesc() = default;
+ GlobalObjectDesc(const GlobalObjectDesc &) = delete;
+ GlobalObjectDesc &operator=(const GlobalObjectDesc &) = delete;
+ GlobalObjectDesc(GlobalObjectDesc &&) noexcept = default;
+ GlobalObjectDesc &operator=(GlobalObjectDesc &&) noexcept = default;
+ ~GlobalObjectDesc() = default;
+
+ [[nodiscard]] bool isDeclaration() const noexcept {
+ return !Initializer.has_value() && Linkage != GlobalLinkage::Common;
+ }
+
+ [[nodiscard]] Expected<void> verify() const;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_GLOBALOBJECT_H
diff --git a/backend/include/rcc/CodeGen/MachineMCContext.h b/backend/include/rcc/CodeGen/MachineMCContext.h
new file mode 100644
index 0000000..2464dc5
--- /dev/null
+++ b/backend/include/rcc/CodeGen/MachineMCContext.h
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_MACHINEMCCONTEXT_H
+#define RCC_CODEGEN_MACHINEMCCONTEXT_H
+
+#include "rcc/CodeGen/MachineIRTypes.h"
+#include "rcc/MC/MCContext.h"
+#include "rcc/MC/MCSymbol.h"
+#include "rcc/Support/Error.h"
+
+#include <string>
+#include <string_view>
+#include <unordered_map>
+
+namespace rcc {
+
+class CompilationUnit;
+struct GlobalObjectDesc;
+class MachineBasicBlock;
+class MachineFunction;
+
+class MachineMCContext final {
+public:
+ explicit MachineMCContext(mc::MCContext &Context) noexcept : Context(&Context) {}
+
+ [[nodiscard]] Expected<void> initialize(const CompilationUnit &Unit);
+ [[nodiscard]] Expected<void> initializeFunction(const MachineFunction &Function);
+
+ [[nodiscard]] mc::MCSymbolRef functionSymbol(const MachineFunction &Function) const noexcept;
+ [[nodiscard]] mc::MCSymbolRef globalSymbol(const GlobalObjectDesc &Object) const noexcept;
+ [[nodiscard]] mc::MCSymbolRef blockSymbol(const MachineBasicBlock &Block) const noexcept;
+ [[nodiscard]] mc::MCSymbolRef constantPoolSymbol(const MachineFunction &Function,
+ ConstantPoolIndex Index) const noexcept;
+ [[nodiscard]] mc::MCSymbolRef jumpTableSymbol(const MachineFunction &Function,
+ JumpTableIndex Index) const noexcept;
+
+ [[nodiscard]] Expected<mc::MCSymbolRef> symbol(std::string Name,
+ mc::MCSymbolKind Kind = mc::MCSymbolKind::Generic);
+ [[nodiscard]] Expected<mc::MCSymbolRef> blockAddressSymbol(std::string_view FunctionName,
+ std::string_view BlockName) const;
+
+ [[nodiscard]] mc::MCContext &context() const noexcept {
+ return *Context;
+ }
+
+private:
+ struct FunctionIndexKey final {
+ const MachineFunction *Function = nullptr;
+ std::uint32_t Index = 0;
+
+ friend bool operator==(FunctionIndexKey Left, FunctionIndexKey Right) noexcept = default;
+ };
+
+ struct FunctionIndexHash final {
+ [[nodiscard]] std::size_t operator()(FunctionIndexKey Key) const noexcept;
+ };
+
+ mc::MCContext *Context;
+ std::unordered_map<const MachineFunction *, mc::MCSymbolRef> FunctionSymbols;
+ std::unordered_map<const GlobalObjectDesc *, mc::MCSymbolRef> GlobalSymbols;
+ std::unordered_map<const MachineBasicBlock *, mc::MCSymbolRef> BlockSymbols;
+ std::unordered_map<FunctionIndexKey, mc::MCSymbolRef, FunctionIndexHash> ConstantPoolSymbols;
+ std::unordered_map<FunctionIndexKey, mc::MCSymbolRef, FunctionIndexHash> JumpTableSymbols;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_MACHINEMCCONTEXT_H
diff --git a/backend/include/rcc/CodeGen/TargetMCInstLowering.h b/backend/include/rcc/CodeGen/TargetMCInstLowering.h
new file mode 100644
index 0000000..875d2dd
--- /dev/null
+++ b/backend/include/rcc/CodeGen/TargetMCInstLowering.h
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_CODEGEN_TARGETMCINSTLOWERING_H
+#define RCC_CODEGEN_TARGETMCINSTLOWERING_H
+
+#include "rcc/MC/MCInst.h"
+#include "rcc/MC/MCInstPrinter.h"
+#include "rcc/MC/MCSection.h"
+#include "rcc/MC/MCStreamer.h"
+#include "rcc/Support/Error.h"
+
+namespace rcc {
+
+class MachineConstantPoolEntry;
+class GlobalInitializer;
+struct GlobalObjectDesc;
+class MachineFunction;
+class MachineInstr;
+class MachineJumpTableEntry;
+class MachineMCContext;
+struct GenericConstantData;
+class TargetConstant;
+
+class TargetMCInstLowering {
+public:
+ virtual ~TargetMCInstLowering() = default;
+
+ [[nodiscard]] virtual const mc::MCInstPrinter &instructionPrinter() const noexcept = 0;
+
+ [[nodiscard]] virtual Expected<mc::MCInst> lowerInstruction(const MachineInstr &Instruction,
+ MachineMCContext &Context) const = 0;
+
+ [[nodiscard]] virtual Expected<void> emitTerminalInstruction(const MachineInstr &Instruction,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const;
+
+ [[nodiscard]] virtual Expected<mc::MCSectionDesc>
+ textSection(const MachineFunction &Function) const = 0;
+ [[nodiscard]] virtual Expected<mc::MCSectionDesc>
+ globalSection(const GlobalObjectDesc &Object, MachineMCContext &Context) const = 0;
+ [[nodiscard]] virtual Expected<mc::MCSectionDesc>
+ constantPoolSection(const MachineFunction &Function,
+ const MachineConstantPoolEntry &Entry) const = 0;
+ [[nodiscard]] virtual Expected<mc::MCSectionDesc>
+ jumpTableSection(const MachineFunction &Function, const MachineJumpTableEntry &Entry) const = 0;
+
+ [[nodiscard]] virtual Expected<void> emitFileHeader(MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const;
+ [[nodiscard]] virtual Expected<void> emitFileTrailer(MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const;
+ [[nodiscard]] virtual Expected<void> emitGenericConstant(const GenericConstantData &Constant,
+ std::uint64_t Size,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const;
+ [[nodiscard]] virtual Expected<void> emitGlobalInitializer(const GlobalInitializer &Initializer,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const;
+ [[nodiscard]] virtual Expected<void> emitTargetConstant(const TargetConstant &Constant,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const;
+ [[nodiscard]] virtual Expected<void> emitTargetJumpTable(const MachineFunction &Function,
+ const MachineJumpTableEntry &Entry,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const;
+};
+
+} // namespace rcc
+
+#endif // RCC_CODEGEN_TARGETMCINSTLOWERING_H
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
diff --git a/backend/include/rcc/Support/Error.h b/backend/include/rcc/Support/Error.h
index d125383..3bdab97 100644
--- a/backend/include/rcc/Support/Error.h
+++ b/backend/include/rcc/Support/Error.h
@@ -25,6 +25,7 @@ enum class ErrorCode : std::uint8_t {
PseudoExpansionFailed,
FinalEncodabilityFailed,
CFGOptimizationFailed,
+ AssemblyLoweringFailed,
};
[[nodiscard]] std::string_view getErrorCodeName(ErrorCode Code) noexcept;
diff --git a/backend/include/rcc/Target/RISCV/RISCVAssemblyPrinter.h b/backend/include/rcc/Target/RISCV/RISCVAssemblyPrinter.h
new file mode 100644
index 0000000..5c8dca5
--- /dev/null
+++ b/backend/include/rcc/Target/RISCV/RISCVAssemblyPrinter.h
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_TARGET_RISCV_RISCVASSEMBLYPRINTER_H
+#define RCC_TARGET_RISCV_RISCVASSEMBLYPRINTER_H
+
+#include "rcc/CodeGen/AsmPrinter.h"
+#include "rcc/CodeGen/TargetDescription.h"
+#include "rcc/Support/Error.h"
+
+#include <string>
+
+namespace rcc {
+class CompilationUnit;
+class MachineFunction;
+} // namespace rcc
+
+namespace rcc::riscv {
+
+struct AssemblyEmissionOptions final {
+ bool EmitFunctionDirectives = true;
+ bool EmitCFI = true;
+ bool EmitBlockLabels = true;
+ bool VerifyInput = true;
+};
+
+[[nodiscard]] Expected<std::string> emitAssembly(const CompilationUnit &Unit,
+ const TargetDescription &Target,
+ AssemblyEmissionOptions Options = {});
+[[nodiscard]] Expected<std::string> emitAssembly(const MachineFunction &Function,
+ const TargetDescription &Target,
+ AssemblyEmissionOptions Options = {});
+
+} // namespace rcc::riscv
+
+#endif // RCC_TARGET_RISCV_RISCVASSEMBLYPRINTER_H
diff --git a/backend/include/rcc/Target/RISCV/RISCVInstPrinter.h b/backend/include/rcc/Target/RISCV/RISCVInstPrinter.h
new file mode 100644
index 0000000..564ca2f
--- /dev/null
+++ b/backend/include/rcc/Target/RISCV/RISCVInstPrinter.h
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_TARGET_RISCV_RISCVINSTPRINTER_H
+#define RCC_TARGET_RISCV_RISCVINSTPRINTER_H
+
+#include "rcc/CodeGen/TargetDescription.h"
+#include "rcc/MC/MCInstPrinter.h"
+
+#include <cstdint>
+#include <string>
+#include <string_view>
+
+namespace rcc::riscv {
+
+enum class RISCVMCExprKind : std::uint32_t {
+ CallPLT = 1,
+ PCRelativeHigh = 2,
+ PCRelativeLow = 3,
+};
+
+class RISCVInstPrinter final : public mc::MCInstPrinter {
+public:
+ explicit RISCVInstPrinter(const TargetDescription &Target) noexcept : Target(&Target) {}
+
+ [[nodiscard]] Expected<std::string>
+ printInstruction(const mc::MCInst &Instruction) const override;
+ [[nodiscard]] Expected<std::string>
+ printTargetExpression(std::uint32_t Kind, std::string_view Operand) const override;
+
+private:
+ const TargetDescription *Target;
+};
+
+} // namespace rcc::riscv
+
+#endif // RCC_TARGET_RISCV_RISCVINSTPRINTER_H
diff --git a/backend/include/rcc/Target/RISCV/RISCVMCTargetLowering.h b/backend/include/rcc/Target/RISCV/RISCVMCTargetLowering.h
new file mode 100644
index 0000000..fd620ad
--- /dev/null
+++ b/backend/include/rcc/Target/RISCV/RISCVMCTargetLowering.h
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#ifndef RCC_TARGET_RISCV_RISCVMCTARGETLOWERING_H
+#define RCC_TARGET_RISCV_RISCVMCTARGETLOWERING_H
+
+#include "rcc/CodeGen/TargetMCInstLowering.h"
+#include "rcc/Target/RISCV/RISCVInstPrinter.h"
+
+namespace rcc::riscv {
+
+class RISCVMCTargetLowering final : public TargetMCInstLowering {
+public:
+ explicit RISCVMCTargetLowering(const TargetDescription &Target) noexcept
+ : Target(&Target), Printer(Target) {}
+
+ [[nodiscard]] const mc::MCInstPrinter &instructionPrinter() const noexcept override {
+ return Printer;
+ }
+
+ [[nodiscard]] Expected<mc::MCInst> lowerInstruction(const MachineInstr &Instruction,
+ MachineMCContext &Context) const override;
+ [[nodiscard]] Expected<void> emitTerminalInstruction(const MachineInstr &Instruction,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const override;
+
+ [[nodiscard]] Expected<mc::MCSectionDesc>
+ textSection(const MachineFunction &Function) const override;
+ [[nodiscard]] Expected<mc::MCSectionDesc> globalSection(const GlobalObjectDesc &Object,
+ MachineMCContext &Context) const override;
+ [[nodiscard]] Expected<mc::MCSectionDesc>
+ constantPoolSection(const MachineFunction &Function,
+ const MachineConstantPoolEntry &Entry) const override;
+ [[nodiscard]] Expected<mc::MCSectionDesc>
+ jumpTableSection(const MachineFunction &Function,
+ const MachineJumpTableEntry &Entry) const override;
+
+ [[nodiscard]] Expected<void> emitFileHeader(MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const override;
+ [[nodiscard]] Expected<void> emitFileTrailer(MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const override;
+ [[nodiscard]] Expected<void> emitGenericConstant(const GenericConstantData &Constant,
+ std::uint64_t Size, MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const override;
+ [[nodiscard]] Expected<void> emitGlobalInitializer(const GlobalInitializer &Initializer,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const override;
+ [[nodiscard]] Expected<void> emitTargetConstant(const TargetConstant &Constant,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const override;
+ [[nodiscard]] Expected<void> emitTargetJumpTable(const MachineFunction &Function,
+ const MachineJumpTableEntry &Entry,
+ MachineMCContext &Context,
+ mc::MCStreamer &Streamer) const override;
+
+private:
+ const TargetDescription *Target;
+ RISCVInstPrinter Printer;
+};
+
+} // namespace rcc::riscv
+
+#endif // RCC_TARGET_RISCV_RISCVMCTARGETLOWERING_H