aboutsummaryrefslogtreecommitdiff
path: root/backend/lib/MC/MCObjectStreamer.cpp
blob: 634b7130eb41f0c50b4c13e201eb54dc2d5bd41f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
// SPDX-License-Identifier: GPL-3.0-or-later

#include "rcc/MC/MCObjectStreamer.h"

#include <utility>

namespace rcc::mc {

Expected<void> ELFObjectStreamer::ensureOpen() const {
  if (IsFinished)
    return makeUnexpected(ErrorCode::ObjectWritingFailed, "object stream is already finalized");
  return {};
}

Expected<void> ELFObjectStreamer::switchSection(MCSectionRef Section) {
  auto Open = ensureOpen();
  return Open ? Assembler.switchSection(std::move(Section)) : Open;
}

Expected<void> ELFObjectStreamer::emitLabel(MCSymbolRef Symbol) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitLabel(std::move(Symbol)) : Open;
}

Expected<void> ELFObjectStreamer::emitInstruction(const MCInst &Instruction) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitInstruction(Instruction) : Open;
}

Expected<void> ELFObjectStreamer::emitValue(MCExprRef Value, std::uint8_t Size) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitValue(std::move(Value), Size) : Open;
}

Expected<void> ELFObjectStreamer::emitBytes(std::span<const std::uint8_t> Bytes) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitBytes(Bytes) : Open;
}

Expected<void> ELFObjectStreamer::emitZeroFill(std::uint64_t Size) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitZeroFill(Size) : Open;
}

Expected<void> ELFObjectStreamer::emitAlignment(std::uint64_t Alignment, std::uint8_t Fill,
                                                std::uint64_t MaximumBytes) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitAlignment(Alignment, Fill, MaximumBytes) : Open;
}

Expected<void> ELFObjectStreamer::emitSymbolAttribute(MCSymbolRef Symbol,
                                                      MCSymbolAttribute Attribute) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitSymbolAttribute(std::move(Symbol), Attribute) : Open;
}

Expected<void> ELFObjectStreamer::emitSymbolSize(MCSymbolRef Symbol, MCExprRef Size) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitSymbolSize(std::move(Symbol), std::move(Size)) : Open;
}

Expected<void> ELFObjectStreamer::emitCommonSymbol(MCSymbolRef Symbol, std::uint64_t Size,
                                                   std::uint64_t Alignment) {
  auto Open = ensureOpen();
  return Open ? Assembler.emitCommonSymbol(std::move(Symbol), Size, Alignment) : Open;
}

Expected<void> ELFObjectStreamer::emitDirective(std::string_view Name, std::string_view) {
  auto Open = ensureOpen();
  if (!Open)
    return Open;
  if (Name == "attribute")
    return {};
  return makeUnexpected(ErrorCode::Unsupported,
                        "native object emission does not support the MC directive '" +
                            std::string(Name) + "'");
}

Expected<void> ELFObjectStreamer::emitCFI(const MCCFIInstruction &Instruction) {
  auto Open = ensureOpen();
  if (!Open)
    return Open;
  return Assembler.emitCFI(Instruction);
}

Expected<void> ELFObjectStreamer::emitInlineAssembly(std::string_view Text) {
  auto Open = ensureOpen();
  if (!Open)
    return Open;
  if (Text.empty())
    return {};
  return makeUnexpected(ErrorCode::Unsupported,
                        "native object emission requires parsed inline assembly");
}

Expected<void> ELFObjectStreamer::emitComment(std::string_view) {
  return ensureOpen();
}

Expected<void> ELFObjectStreamer::configureDwarfFrame(MCSectionRef Section, MCDwarfFrameInfo Info) {
  auto Open = ensureOpen();
  if (!Open)
    return Open;
  return Assembler.configureDwarfFrame(std::move(Section), Info);
}

Expected<void> ELFObjectStreamer::finish() {
  auto Open = ensureOpen();
  if (!Open)
    return Open;
  auto Object = Assembler.assemble();
  if (!Object)
    return std::unexpected(Object.error());
  auto Written = Writer->writeObject(*Object);
  if (!Written)
    return std::unexpected(Written.error());
  Output = std::move(*Written);
  IsFinished = true;
  return {};
}

Expected<std::vector<std::uint8_t>> ELFObjectStreamer::takeOutput() {
  if (!IsFinished)
    return makeUnexpected(ErrorCode::ObjectWritingFailed,
                          "object output cannot be taken before finalization");
  if (OutputWasTaken)
    return makeUnexpected(ErrorCode::ObjectWritingFailed, "object output was already taken");
  OutputWasTaken = true;
  return std::move(Output);
}

} // namespace rcc::mc