aboutsummaryrefslogtreecommitdiff
path: root/backend/include/rcc/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'backend/include/rcc/CodeGen')
-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
5 files changed, 403 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