aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/Target/RISCV/RISCVObjectFile.cpp
diff options
context:
space:
mode:
authorRichard-Qin-X <richard.qin.001@gmail.com>2026-08-09 22:05:14 +0800
committerRichard-Qin-X <richard.qin.001@gmail.com>2026-08-09 22:05:14 +0800
commit3a57627e59ba18b6f9f9aae7bb60c390c0d3575a (patch)
tree736ca062bfffbd68177a512dfe145b06c16d11b1 /backend/lib/Target/RISCV/RISCVObjectFile.cpp
parent379ff50dcc7ccf977379aee68fa9d10f69065d23 (diff)
downloadrcc-project-3a57627e59ba18b6f9f9aae7bb60c390c0d3575a.tar.gz
rcc-project-3a57627e59ba18b6f9f9aae7bb60c390c0d3575a.tar.xz
[MC] Implement RV64GC object emission
Diffstat (limited to 'backend/lib/Target/RISCV/RISCVObjectFile.cpp')
-rw-r--r--backend/lib/Target/RISCV/RISCVObjectFile.cpp148
1 files changed, 148 insertions, 0 deletions
diff --git a/backend/lib/Target/RISCV/RISCVObjectFile.cpp b/backend/lib/Target/RISCV/RISCVObjectFile.cpp
new file mode 100644
index 0000000..15d4980
--- /dev/null
+++ b/backend/lib/Target/RISCV/RISCVObjectFile.cpp
@@ -0,0 +1,148 @@
+// SPDX-License-Identifier: GPL-3.0-or-later
+
+#include "rcc/Target/RISCV/RISCVObjectFile.h"
+
+#include "rcc/CodeGen/AsmPrinter.h"
+#include "rcc/CodeGen/CompilationUnit.h"
+#include "rcc/CodeGen/MachineFunction.h"
+#include "rcc/CodeGen/MachineMCContext.h"
+#include "rcc/MC/ELFObjectWriter.h"
+#include "rcc/MC/MCContext.h"
+#include "rcc/MC/MCObjectStreamer.h"
+#include "rcc/Target/RISCV/RISCVAsmBackend.h"
+#include "rcc/Target/RISCV/RISCVMCCodeEmitter.h"
+#include "rcc/Target/RISCV/RISCVMCTargetLowering.h"
+
+#include <cstdint>
+#include <utility>
+#include <vector>
+
+namespace rcc::riscv {
+namespace {
+
+constexpr std::uint16_t EMRISCV = 243;
+constexpr std::uint32_t SHTRISCVAttributes = 0x70000003;
+
+[[nodiscard]] AsmPrinterOptions printerOptions(ObjectEmissionOptions Options) noexcept {
+ return AsmPrinterOptions{
+ .EmitFunctionDirectives = Options.EmitFunctionDirectives,
+ .EmitCFI = Options.EmitCFI,
+ .EmitBlockLabels = Options.EmitBlockLabels,
+ .EmitInstructionSymbols = true,
+ .VerifyInput = Options.VerifyInput,
+ };
+}
+
+[[nodiscard]] std::vector<std::uint8_t> attributesSection() {
+ constexpr char Architecture[] = "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0_"
+ "zmmul1p0_zaamo1p0_zalrsc1p0";
+ const std::uint32_t FilePayloadSize = 1U + sizeof(Architecture) + 2U;
+ const std::uint32_t VendorSize = 4U + 6U + 1U + 4U + FilePayloadSize;
+ std::vector<std::uint8_t> Bytes;
+ Bytes.reserve(1U + VendorSize);
+ const auto AppendU32 = [&Bytes](std::uint32_t Value) {
+ for (std::uint8_t Shift = 0; Shift < 32; Shift += 8)
+ Bytes.push_back(static_cast<std::uint8_t>(Value >> Shift));
+ };
+ Bytes.push_back('A');
+ AppendU32(VendorSize);
+ Bytes.insert(Bytes.end(), {'r', 'i', 's', 'c', 'v', 0});
+ Bytes.push_back(1);
+ AppendU32(5U + FilePayloadSize);
+ Bytes.push_back(5);
+ Bytes.insert(Bytes.end(), Architecture, Architecture + sizeof(Architecture));
+ Bytes.push_back(4);
+ Bytes.push_back(16);
+ return Bytes;
+}
+
+[[nodiscard]] mc::ELFObjectTargetInfo objectTargetInfo() {
+ mc::ELFObjectTargetInfo Info;
+ Info.Machine = EMRISCV;
+ Info.ExtraSections.push_back(mc::ELFExtraSection{
+ .Name = ".riscv.attributes",
+ .Type = SHTRISCVAttributes,
+ .Flags = 0,
+ .Alignment = 1,
+ .EntrySize = 0,
+ .Contents = attributesSection(),
+ });
+ return Info;
+}
+
+struct ObjectEmissionContext final {
+ explicit ObjectEmissionContext(const TargetDescription &Target)
+ : MachineContext(Context), Lowering(Target), Emitter(Target), Writer(objectTargetInfo()),
+ Streamer(Emitter, Backend, Writer) {
+ mc::MCSectionDesc EHFrameDescription{
+ .Name = ".eh_frame",
+ .Kind = mc::MCSectionKind::EHFrame,
+ .Flags = {mc::MCSectionFlag::Alloc},
+ .Alignment = 8,
+ .EntrySize = 0,
+ .Group = {},
+ .UniqueID = std::nullopt,
+ };
+ auto EHFrame = Context.getOrCreateSection(std::move(EHFrameDescription));
+ if (!EHFrame) {
+ Initialization = std::unexpected(EHFrame.error());
+ return;
+ }
+ Initialization = Streamer.configureDwarfFrame(std::move(*EHFrame),
+ mc::MCDwarfFrameInfo{.CodeAlignment = 1,
+ .DataAlignment = -8,
+ .ReturnAddressRegister = 1,
+ .InitialCFARegister = 2,
+ .InitialCFAOffset = 0});
+ }
+
+ mc::MCContext Context;
+ MachineMCContext MachineContext;
+ RISCVMCTargetLowering Lowering;
+ RISCVMCCodeEmitter Emitter;
+ RISCVAsmBackend Backend;
+ mc::ELF64LEObjectWriter Writer;
+ mc::ELFObjectStreamer Streamer;
+ Expected<void> Initialization;
+};
+
+} // namespace
+
+Expected<std::vector<std::uint8_t>> emitObject(const CompilationUnit &Unit,
+ const TargetDescription &Target,
+ ObjectEmissionOptions Options) {
+ ObjectEmissionContext Context(Target);
+ if (!Context.Initialization)
+ return std::unexpected(Context.Initialization.error());
+ AsmPrinter Printer(Target, Context.Lowering, Context.MachineContext, Context.Streamer,
+ printerOptions(Options));
+ auto Emitted = Printer.emitCompilationUnit(Unit);
+ if (!Emitted)
+ return std::unexpected(Emitted.error());
+ return Context.Streamer.takeOutput();
+}
+
+Expected<std::vector<std::uint8_t>> emitObject(const MachineFunction &Function,
+ const TargetDescription &Target,
+ ObjectEmissionOptions Options) {
+ ObjectEmissionContext Context(Target);
+ if (!Context.Initialization)
+ return std::unexpected(Context.Initialization.error());
+ AsmPrinter Printer(Target, Context.Lowering, Context.MachineContext, Context.Streamer,
+ printerOptions(Options));
+ auto Header = Context.Lowering.emitFileHeader(Context.MachineContext, Context.Streamer);
+ if (!Header)
+ return std::unexpected(Header.error());
+ auto Emitted = Printer.emitFunction(Function);
+ if (!Emitted)
+ return std::unexpected(Emitted.error());
+ auto Trailer = Context.Lowering.emitFileTrailer(Context.MachineContext, Context.Streamer);
+ if (!Trailer)
+ return std::unexpected(Trailer.error());
+ auto Finished = Context.Streamer.finish();
+ if (!Finished)
+ return std::unexpected(Finished.error());
+ return Context.Streamer.takeOutput();
+}
+
+} // namespace rcc::riscv