1 //===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/MC/MCAsmInfo.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCStreamer.h"
13 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCObjectWriter.h"
15 #include "llvm/Support/ErrorHandling.h"
16 #include "llvm/Support/raw_ostream.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/Twine.h"
22 MCStreamer::MCStreamer(MCContext
&Ctx
) : Context(Ctx
) {
23 const MCSection
*section
= NULL
;
24 SectionStack
.push_back(std::make_pair(section
, section
));
27 MCStreamer::~MCStreamer() {
30 raw_ostream
&MCStreamer::GetCommentOS() {
31 // By default, discard comments.
35 void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta
,
36 const MCSymbol
*Label
, int PointerSize
) {
37 // emit the sequence to set the address
38 EmitIntValue(dwarf::DW_LNS_extended_op
, 1);
39 EmitULEB128IntValue(PointerSize
+ 1);
40 EmitIntValue(dwarf::DW_LNE_set_address
, 1);
41 EmitSymbolValue(Label
, PointerSize
);
43 // emit the sequence for the LineDelta (from 1) and a zero address delta.
44 MCDwarfLineAddr::Emit(this, LineDelta
, 0);
47 /// EmitIntValue - Special case of EmitValue that avoids the client having to
48 /// pass in a MCExpr for constant integers.
49 void MCStreamer::EmitIntValue(uint64_t Value
, unsigned Size
,
51 assert(Size
<= 8 && "Invalid size");
52 assert((isUIntN(8 * Size
, Value
) || isIntN(8 * Size
, Value
)) &&
55 // FIXME: Endianness assumption.
56 for (unsigned i
= 0; i
!= Size
; ++i
)
57 buf
[i
] = uint8_t(Value
>> (i
* 8));
58 EmitBytes(StringRef(buf
, Size
), AddrSpace
);
61 /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
62 /// client having to pass in a MCExpr for constant integers.
63 void MCStreamer::EmitULEB128IntValue(uint64_t Value
, unsigned AddrSpace
) {
65 raw_svector_ostream
OSE(Tmp
);
66 MCObjectWriter::EncodeULEB128(Value
, OSE
);
67 EmitBytes(OSE
.str(), AddrSpace
);
70 /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
71 /// client having to pass in a MCExpr for constant integers.
72 void MCStreamer::EmitSLEB128IntValue(int64_t Value
, unsigned AddrSpace
) {
74 raw_svector_ostream
OSE(Tmp
);
75 MCObjectWriter::EncodeSLEB128(Value
, OSE
);
76 EmitBytes(OSE
.str(), AddrSpace
);
79 void MCStreamer::EmitAbsValue(const MCExpr
*Value
, unsigned Size
,
81 if (getContext().getAsmInfo().hasAggressiveSymbolFolding()) {
82 EmitValue(Value
, Size
, AddrSpace
);
85 MCSymbol
*ABS
= getContext().CreateTempSymbol();
86 EmitAssignment(ABS
, Value
);
87 EmitSymbolValue(ABS
, Size
, AddrSpace
);
91 void MCStreamer::EmitValue(const MCExpr
*Value
, unsigned Size
,
93 EmitValueImpl(Value
, Size
, false, AddrSpace
);
96 void MCStreamer::EmitPCRelValue(const MCExpr
*Value
, unsigned Size
,
98 EmitValueImpl(Value
, Size
, true, AddrSpace
);
101 void MCStreamer::EmitSymbolValue(const MCSymbol
*Sym
, unsigned Size
,
102 bool isPCRel
, unsigned AddrSpace
) {
103 EmitValueImpl(MCSymbolRefExpr::Create(Sym
, getContext()), Size
, isPCRel
,
107 void MCStreamer::EmitSymbolValue(const MCSymbol
*Sym
, unsigned Size
,
108 unsigned AddrSpace
) {
109 EmitSymbolValue(Sym
, Size
, false, AddrSpace
);
112 void MCStreamer::EmitPCRelSymbolValue(const MCSymbol
*Sym
, unsigned Size
,
113 unsigned AddrSpace
) {
114 EmitSymbolValue(Sym
, Size
, true, AddrSpace
);
117 void MCStreamer::EmitGPRel32Value(const MCExpr
*Value
) {
118 report_fatal_error("unsupported directive in streamer");
121 /// EmitFill - Emit NumBytes bytes worth of the value specified by
122 /// FillValue. This implements directives such as '.space'.
123 void MCStreamer::EmitFill(uint64_t NumBytes
, uint8_t FillValue
,
124 unsigned AddrSpace
) {
125 const MCExpr
*E
= MCConstantExpr::Create(FillValue
, getContext());
126 for (uint64_t i
= 0, e
= NumBytes
; i
!= e
; ++i
)
127 EmitValue(E
, 1, AddrSpace
);
130 bool MCStreamer::EmitDwarfFileDirective(unsigned FileNo
,
131 StringRef Filename
) {
132 return getContext().GetDwarfFile(Filename
, FileNo
) == 0;
135 void MCStreamer::EmitDwarfLocDirective(unsigned FileNo
, unsigned Line
,
136 unsigned Column
, unsigned Flags
,
138 unsigned Discriminator
) {
139 getContext().setCurrentDwarfLoc(FileNo
, Line
, Column
, Flags
, Isa
,
143 MCDwarfFrameInfo
*MCStreamer::getCurrentFrameInfo() {
144 if (FrameInfos
.empty())
146 return &FrameInfos
.back();
149 void MCStreamer::EnsureValidFrame() {
150 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
151 if (!CurFrame
|| CurFrame
->End
)
152 report_fatal_error("No open frame");
155 void MCStreamer::EmitCFIStartProc() {
156 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
157 if (CurFrame
&& !CurFrame
->End
)
158 report_fatal_error("Starting a frame before finishing the previous one!");
159 MCDwarfFrameInfo Frame
;
160 Frame
.Begin
= getContext().CreateTempSymbol();
161 EmitLabel(Frame
.Begin
);
162 FrameInfos
.push_back(Frame
);
165 void MCStreamer::EmitCFIEndProc() {
167 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
168 CurFrame
->End
= getContext().CreateTempSymbol();
169 EmitLabel(CurFrame
->End
);
172 void MCStreamer::EmitCFIDefCfa(int64_t Register
, int64_t Offset
) {
174 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
175 MCSymbol
*Label
= getContext().CreateTempSymbol();
177 MachineLocation
Dest(MachineLocation::VirtualFP
);
178 MachineLocation
Source(Register
, -Offset
);
179 MCCFIInstruction
Instruction(Label
, Dest
, Source
);
180 CurFrame
->Instructions
.push_back(Instruction
);
183 void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset
) {
185 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
186 MCSymbol
*Label
= getContext().CreateTempSymbol();
188 MachineLocation
Dest(MachineLocation::VirtualFP
);
189 MachineLocation
Source(MachineLocation::VirtualFP
, -Offset
);
190 MCCFIInstruction
Instruction(Label
, Dest
, Source
);
191 CurFrame
->Instructions
.push_back(Instruction
);
194 void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment
) {
196 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
197 MCSymbol
*Label
= getContext().CreateTempSymbol();
199 MachineLocation
Dest(MachineLocation::VirtualFP
);
200 MachineLocation
Source(MachineLocation::VirtualFP
, Adjustment
);
201 MCCFIInstruction
Instruction(MCCFIInstruction::RelMove
, Label
, Dest
, Source
);
202 CurFrame
->Instructions
.push_back(Instruction
);
205 void MCStreamer::EmitCFIDefCfaRegister(int64_t Register
) {
207 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
208 MCSymbol
*Label
= getContext().CreateTempSymbol();
210 MachineLocation
Dest(Register
);
211 MachineLocation
Source(MachineLocation::VirtualFP
);
212 MCCFIInstruction
Instruction(Label
, Dest
, Source
);
213 CurFrame
->Instructions
.push_back(Instruction
);
216 void MCStreamer::EmitCFIOffset(int64_t Register
, int64_t Offset
) {
218 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
219 MCSymbol
*Label
= getContext().CreateTempSymbol();
221 MachineLocation
Dest(Register
, Offset
);
222 MachineLocation
Source(Register
, Offset
);
223 MCCFIInstruction
Instruction(Label
, Dest
, Source
);
224 CurFrame
->Instructions
.push_back(Instruction
);
227 void MCStreamer::EmitCFIRelOffset(int64_t Register
, int64_t Offset
) {
229 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
230 MCSymbol
*Label
= getContext().CreateTempSymbol();
232 MachineLocation
Dest(Register
, Offset
);
233 MachineLocation
Source(Register
, Offset
);
234 MCCFIInstruction
Instruction(MCCFIInstruction::RelMove
, Label
, Dest
, Source
);
235 CurFrame
->Instructions
.push_back(Instruction
);
238 void MCStreamer::EmitCFIPersonality(const MCSymbol
*Sym
,
241 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
242 CurFrame
->Personality
= Sym
;
243 CurFrame
->PersonalityEncoding
= Encoding
;
246 void MCStreamer::EmitCFILsda(const MCSymbol
*Sym
, unsigned Encoding
) {
248 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
249 CurFrame
->Lsda
= Sym
;
250 CurFrame
->LsdaEncoding
= Encoding
;
253 void MCStreamer::EmitCFIRememberState() {
255 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
256 MCSymbol
*Label
= getContext().CreateTempSymbol();
258 MCCFIInstruction
Instruction(MCCFIInstruction::Remember
, Label
);
259 CurFrame
->Instructions
.push_back(Instruction
);
262 void MCStreamer::EmitCFIRestoreState() {
263 // FIXME: Error if there is no matching cfi_remember_state.
265 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
266 MCSymbol
*Label
= getContext().CreateTempSymbol();
268 MCCFIInstruction
Instruction(MCCFIInstruction::Restore
, Label
);
269 CurFrame
->Instructions
.push_back(Instruction
);
272 void MCStreamer::EmitCFISameValue(int64_t Register
) {
274 MCDwarfFrameInfo
*CurFrame
= getCurrentFrameInfo();
275 MCSymbol
*Label
= getContext().CreateTempSymbol();
277 MCCFIInstruction
Instruction(MCCFIInstruction::SameValue
, Label
, Register
);
278 CurFrame
->Instructions
.push_back(Instruction
);
281 void MCStreamer::EmitFnStart() {
282 errs() << "Not implemented yet\n";
286 void MCStreamer::EmitFnEnd() {
287 errs() << "Not implemented yet\n";
291 void MCStreamer::EmitCantUnwind() {
292 errs() << "Not implemented yet\n";
296 void MCStreamer::EmitHandlerData() {
297 errs() << "Not implemented yet\n";
301 void MCStreamer::EmitPersonality(const MCSymbol
*Personality
) {
302 errs() << "Not implemented yet\n";
306 void MCStreamer::EmitSetFP(unsigned FpReg
, unsigned SpReg
, int64_t Offset
) {
307 errs() << "Not implemented yet\n";
311 void MCStreamer::EmitPad(int64_t Offset
) {
312 errs() << "Not implemented yet\n";
316 void MCStreamer::EmitRegSave(const SmallVectorImpl
<unsigned> &RegList
, bool) {
317 errs() << "Not implemented yet\n";
321 /// EmitRawText - If this file is backed by an assembly streamer, this dumps
322 /// the specified string in the output .s file. This capability is
323 /// indicated by the hasRawTextSupport() predicate.
324 void MCStreamer::EmitRawText(StringRef String
) {
325 errs() << "EmitRawText called on an MCStreamer that doesn't support it, "
326 " something must not be fully mc'ized\n";
330 void MCStreamer::EmitRawText(const Twine
&T
) {
331 SmallString
<128> Str
;
333 EmitRawText(Str
.str());