MCStreamer.cpp revision 5fbe5e783ee0c5ae27c17490a752d7e603e84ed2
1//===- lib/MC/MCStreamer.cpp - Streaming Machine Code Output --------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 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/MC/MCSymbol.h" 16#include "llvm/Support/ErrorHandling.h" 17#include "llvm/Support/raw_ostream.h" 18#include "llvm/ADT/SmallString.h" 19#include "llvm/ADT/Twine.h" 20#include <cstdlib> 21using namespace llvm; 22 23MCStreamer::MCStreamer(MCContext &Ctx) : Context(Ctx), EmitEHFrame(true), 24 EmitDebugFrame(false), 25 CurrentW64UnwindInfo(0) { 26 const MCSection *section = NULL; 27 SectionStack.push_back(std::make_pair(section, section)); 28} 29 30MCStreamer::~MCStreamer() { 31 for (unsigned i = 0; i < getNumW64UnwindInfos(); ++i) 32 delete W64UnwindInfos[i]; 33} 34 35const MCExpr *MCStreamer::BuildSymbolDiff(MCContext &Context, 36 const MCSymbol *A, 37 const MCSymbol *B) { 38 MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None; 39 const MCExpr *ARef = 40 MCSymbolRefExpr::Create(A, Variant, Context); 41 const MCExpr *BRef = 42 MCSymbolRefExpr::Create(B, Variant, Context); 43 const MCExpr *AddrDelta = 44 MCBinaryExpr::Create(MCBinaryExpr::Sub, ARef, BRef, Context); 45 return AddrDelta; 46} 47 48const MCExpr *MCStreamer::ForceExpAbs(const MCExpr* Expr) { 49 if (Context.getAsmInfo().hasAggressiveSymbolFolding() || 50 isa<MCSymbolRefExpr>(Expr)) 51 return Expr; 52 53 MCSymbol *ABS = Context.CreateTempSymbol(); 54 EmitAssignment(ABS, Expr); 55 return MCSymbolRefExpr::Create(ABS, Context); 56} 57 58raw_ostream &MCStreamer::GetCommentOS() { 59 // By default, discard comments. 60 return nulls(); 61} 62 63void MCStreamer::EmitDwarfSetLineAddr(int64_t LineDelta, 64 const MCSymbol *Label, int PointerSize) { 65 // emit the sequence to set the address 66 EmitIntValue(dwarf::DW_LNS_extended_op, 1); 67 EmitULEB128IntValue(PointerSize + 1); 68 EmitIntValue(dwarf::DW_LNE_set_address, 1); 69 EmitSymbolValue(Label, PointerSize); 70 71 // emit the sequence for the LineDelta (from 1) and a zero address delta. 72 MCDwarfLineAddr::Emit(this, LineDelta, 0); 73} 74 75/// EmitIntValue - Special case of EmitValue that avoids the client having to 76/// pass in a MCExpr for constant integers. 77void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size, 78 unsigned AddrSpace) { 79 assert(Size <= 8 && "Invalid size"); 80 assert((isUIntN(8 * Size, Value) || isIntN(8 * Size, Value)) && 81 "Invalid size"); 82 char buf[8]; 83 const bool isLittleEndian = Context.getAsmInfo().isLittleEndian(); 84 for (unsigned i = 0; i != Size; ++i) { 85 unsigned index = isLittleEndian ? i : (Size - i - 1); 86 buf[i] = uint8_t(Value >> (index * 8)); 87 } 88 EmitBytes(StringRef(buf, Size), AddrSpace); 89} 90 91/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the 92/// client having to pass in a MCExpr for constant integers. 93void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace) { 94 SmallString<32> Tmp; 95 raw_svector_ostream OSE(Tmp); 96 MCObjectWriter::EncodeULEB128(Value, OSE); 97 EmitBytes(OSE.str(), AddrSpace); 98} 99 100/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the 101/// client having to pass in a MCExpr for constant integers. 102void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) { 103 SmallString<32> Tmp; 104 raw_svector_ostream OSE(Tmp); 105 MCObjectWriter::EncodeSLEB128(Value, OSE); 106 EmitBytes(OSE.str(), AddrSpace); 107} 108 109void MCStreamer::EmitAbsValue(const MCExpr *Value, unsigned Size, 110 unsigned AddrSpace) { 111 const MCExpr *ABS = ForceExpAbs(Value); 112 EmitValue(ABS, Size, AddrSpace); 113} 114 115 116void MCStreamer::EmitValue(const MCExpr *Value, unsigned Size, 117 unsigned AddrSpace) { 118 EmitValueImpl(Value, Size, AddrSpace); 119} 120 121void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size, 122 unsigned AddrSpace) { 123 EmitValueImpl(MCSymbolRefExpr::Create(Sym, getContext()), Size, 124 AddrSpace); 125} 126 127void MCStreamer::EmitGPRel32Value(const MCExpr *Value) { 128 report_fatal_error("unsupported directive in streamer"); 129} 130 131/// EmitFill - Emit NumBytes bytes worth of the value specified by 132/// FillValue. This implements directives such as '.space'. 133void MCStreamer::EmitFill(uint64_t NumBytes, uint8_t FillValue, 134 unsigned AddrSpace) { 135 const MCExpr *E = MCConstantExpr::Create(FillValue, getContext()); 136 for (uint64_t i = 0, e = NumBytes; i != e; ++i) 137 EmitValue(E, 1, AddrSpace); 138} 139 140bool MCStreamer::EmitDwarfFileDirective(unsigned FileNo, 141 StringRef Filename) { 142 return getContext().GetDwarfFile(Filename, FileNo) == 0; 143} 144 145void MCStreamer::EmitDwarfLocDirective(unsigned FileNo, unsigned Line, 146 unsigned Column, unsigned Flags, 147 unsigned Isa, 148 unsigned Discriminator, 149 StringRef FileName) { 150 getContext().setCurrentDwarfLoc(FileNo, Line, Column, Flags, Isa, 151 Discriminator); 152} 153 154MCDwarfFrameInfo *MCStreamer::getCurrentFrameInfo() { 155 if (FrameInfos.empty()) 156 return NULL; 157 return &FrameInfos.back(); 158} 159 160void MCStreamer::EnsureValidFrame() { 161 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 162 if (!CurFrame || CurFrame->End) 163 report_fatal_error("No open frame"); 164} 165 166void MCStreamer::EmitEHSymAttributes(const MCSymbol *Symbol, 167 MCSymbol *EHSymbol) { 168} 169 170void MCStreamer::EmitLabel(MCSymbol *Symbol) { 171 assert(!Symbol->isVariable() && "Cannot emit a variable symbol!"); 172 assert(getCurrentSection() && "Cannot emit before setting section!"); 173 Symbol->setSection(*getCurrentSection()); 174 LastSymbol = Symbol; 175} 176 177void MCStreamer::EmitCompactUnwindEncoding(uint32_t CompactUnwindEncoding) { 178 EnsureValidFrame(); 179 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 180 CurFrame->CompactUnwindEncoding = CompactUnwindEncoding; 181} 182 183void MCStreamer::EmitCFISections(bool EH, bool Debug) { 184 assert(EH || Debug); 185 EmitEHFrame = EH; 186 EmitDebugFrame = Debug; 187} 188 189void MCStreamer::EmitCFIStartProc() { 190 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 191 if (CurFrame && !CurFrame->End) 192 report_fatal_error("Starting a frame before finishing the previous one!"); 193 194 MCDwarfFrameInfo Frame; 195 Frame.Function = LastSymbol; 196 197 // If the function is externally visible, we need to create a local 198 // symbol to avoid relocations. 199 StringRef Prefix = getContext().getAsmInfo().getPrivateGlobalPrefix(); 200 if (LastSymbol && LastSymbol->getName().startswith(Prefix)) { 201 Frame.Begin = LastSymbol; 202 } else { 203 Frame.Begin = getContext().CreateTempSymbol(); 204 EmitLabel(Frame.Begin); 205 } 206 207 FrameInfos.push_back(Frame); 208} 209 210void MCStreamer::EmitCFIEndProc() { 211 EnsureValidFrame(); 212 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 213 CurFrame->End = getContext().CreateTempSymbol(); 214 EmitLabel(CurFrame->End); 215} 216 217void MCStreamer::EmitCFIDefCfa(int64_t Register, int64_t Offset) { 218 EnsureValidFrame(); 219 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 220 MCSymbol *Label = getContext().CreateTempSymbol(); 221 EmitLabel(Label); 222 MachineLocation Dest(MachineLocation::VirtualFP); 223 MachineLocation Source(Register, -Offset); 224 MCCFIInstruction Instruction(Label, Dest, Source); 225 CurFrame->Instructions.push_back(Instruction); 226} 227 228void MCStreamer::EmitCFIDefCfaOffset(int64_t Offset) { 229 EnsureValidFrame(); 230 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 231 MCSymbol *Label = getContext().CreateTempSymbol(); 232 EmitLabel(Label); 233 MachineLocation Dest(MachineLocation::VirtualFP); 234 MachineLocation Source(MachineLocation::VirtualFP, -Offset); 235 MCCFIInstruction Instruction(Label, Dest, Source); 236 CurFrame->Instructions.push_back(Instruction); 237} 238 239void MCStreamer::EmitCFIAdjustCfaOffset(int64_t Adjustment) { 240 EnsureValidFrame(); 241 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 242 MCSymbol *Label = getContext().CreateTempSymbol(); 243 EmitLabel(Label); 244 MachineLocation Dest(MachineLocation::VirtualFP); 245 MachineLocation Source(MachineLocation::VirtualFP, Adjustment); 246 MCCFIInstruction Instruction(MCCFIInstruction::RelMove, Label, Dest, Source); 247 CurFrame->Instructions.push_back(Instruction); 248} 249 250void MCStreamer::EmitCFIDefCfaRegister(int64_t Register) { 251 EnsureValidFrame(); 252 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 253 MCSymbol *Label = getContext().CreateTempSymbol(); 254 EmitLabel(Label); 255 MachineLocation Dest(Register); 256 MachineLocation Source(MachineLocation::VirtualFP); 257 MCCFIInstruction Instruction(Label, Dest, Source); 258 CurFrame->Instructions.push_back(Instruction); 259} 260 261void MCStreamer::EmitCFIOffset(int64_t Register, int64_t Offset) { 262 EnsureValidFrame(); 263 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 264 MCSymbol *Label = getContext().CreateTempSymbol(); 265 EmitLabel(Label); 266 MachineLocation Dest(Register, Offset); 267 MachineLocation Source(Register, Offset); 268 MCCFIInstruction Instruction(Label, Dest, Source); 269 CurFrame->Instructions.push_back(Instruction); 270} 271 272void MCStreamer::EmitCFIRelOffset(int64_t Register, int64_t Offset) { 273 EnsureValidFrame(); 274 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 275 MCSymbol *Label = getContext().CreateTempSymbol(); 276 EmitLabel(Label); 277 MachineLocation Dest(Register, Offset); 278 MachineLocation Source(Register, Offset); 279 MCCFIInstruction Instruction(MCCFIInstruction::RelMove, Label, Dest, Source); 280 CurFrame->Instructions.push_back(Instruction); 281} 282 283void MCStreamer::EmitCFIPersonality(const MCSymbol *Sym, 284 unsigned Encoding) { 285 EnsureValidFrame(); 286 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 287 CurFrame->Personality = Sym; 288 CurFrame->PersonalityEncoding = Encoding; 289} 290 291void MCStreamer::EmitCFILsda(const MCSymbol *Sym, unsigned Encoding) { 292 EnsureValidFrame(); 293 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 294 CurFrame->Lsda = Sym; 295 CurFrame->LsdaEncoding = Encoding; 296} 297 298void MCStreamer::EmitCFIRememberState() { 299 EnsureValidFrame(); 300 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 301 MCSymbol *Label = getContext().CreateTempSymbol(); 302 EmitLabel(Label); 303 MCCFIInstruction Instruction(MCCFIInstruction::Remember, Label); 304 CurFrame->Instructions.push_back(Instruction); 305} 306 307void MCStreamer::EmitCFIRestoreState() { 308 // FIXME: Error if there is no matching cfi_remember_state. 309 EnsureValidFrame(); 310 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 311 MCSymbol *Label = getContext().CreateTempSymbol(); 312 EmitLabel(Label); 313 MCCFIInstruction Instruction(MCCFIInstruction::Restore, Label); 314 CurFrame->Instructions.push_back(Instruction); 315} 316 317void MCStreamer::EmitCFISameValue(int64_t Register) { 318 EnsureValidFrame(); 319 MCDwarfFrameInfo *CurFrame = getCurrentFrameInfo(); 320 MCSymbol *Label = getContext().CreateTempSymbol(); 321 EmitLabel(Label); 322 MCCFIInstruction Instruction(MCCFIInstruction::SameValue, Label, Register); 323 CurFrame->Instructions.push_back(Instruction); 324} 325 326void MCStreamer::setCurrentW64UnwindInfo(MCWin64EHUnwindInfo *Frame) { 327 W64UnwindInfos.push_back(Frame); 328 CurrentW64UnwindInfo = W64UnwindInfos.back(); 329} 330 331void MCStreamer::EnsureValidW64UnwindInfo() { 332 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 333 if (!CurFrame || CurFrame->End) 334 report_fatal_error("No open Win64 EH frame function!"); 335} 336 337void MCStreamer::EmitWin64EHStartProc(const MCSymbol *Symbol) { 338 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 339 if (CurFrame && !CurFrame->End) 340 report_fatal_error("Starting a function before ending the previous one!"); 341 MCWin64EHUnwindInfo *Frame = new MCWin64EHUnwindInfo; 342 Frame->Begin = getContext().CreateTempSymbol(); 343 Frame->Function = Symbol; 344 EmitLabel(Frame->Begin); 345 setCurrentW64UnwindInfo(Frame); 346} 347 348void MCStreamer::EmitWin64EHEndProc() { 349 EnsureValidW64UnwindInfo(); 350 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 351 if (CurFrame->ChainedParent) 352 report_fatal_error("Not all chained regions terminated!"); 353 CurFrame->End = getContext().CreateTempSymbol(); 354 EmitLabel(CurFrame->End); 355} 356 357void MCStreamer::EmitWin64EHStartChained() { 358 EnsureValidW64UnwindInfo(); 359 MCWin64EHUnwindInfo *Frame = new MCWin64EHUnwindInfo; 360 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 361 Frame->Begin = getContext().CreateTempSymbol(); 362 Frame->Function = CurFrame->Function; 363 Frame->ChainedParent = CurFrame; 364 EmitLabel(Frame->Begin); 365 setCurrentW64UnwindInfo(Frame); 366} 367 368void MCStreamer::EmitWin64EHEndChained() { 369 EnsureValidW64UnwindInfo(); 370 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 371 if (!CurFrame->ChainedParent) 372 report_fatal_error("End of a chained region outside a chained region!"); 373 CurFrame->End = getContext().CreateTempSymbol(); 374 EmitLabel(CurFrame->End); 375 CurrentW64UnwindInfo = CurFrame->ChainedParent; 376} 377 378void MCStreamer::EmitWin64EHHandler(const MCSymbol *Sym, bool Unwind, 379 bool Except) { 380 EnsureValidW64UnwindInfo(); 381 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 382 if (CurFrame->ChainedParent) 383 report_fatal_error("Chained unwind areas can't have handlers!"); 384 CurFrame->ExceptionHandler = Sym; 385 if (!Except && !Unwind) 386 report_fatal_error("Don't know what kind of handler this is!"); 387 if (Unwind) 388 CurFrame->HandlesUnwind = true; 389 if (Except) 390 CurFrame->HandlesExceptions = true; 391} 392 393void MCStreamer::EmitWin64EHHandlerData() { 394 EnsureValidW64UnwindInfo(); 395 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 396 if (CurFrame->ChainedParent) 397 report_fatal_error("Chained unwind areas can't have handlers!"); 398} 399 400void MCStreamer::EmitWin64EHPushReg(unsigned Register) { 401 EnsureValidW64UnwindInfo(); 402 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 403 MCSymbol *Label = getContext().CreateTempSymbol(); 404 MCWin64EHInstruction Inst(Win64EH::UOP_PushNonVol, Label, Register); 405 EmitLabel(Label); 406 CurFrame->Instructions.push_back(Inst); 407} 408 409void MCStreamer::EmitWin64EHSetFrame(unsigned Register, unsigned Offset) { 410 EnsureValidW64UnwindInfo(); 411 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 412 if (CurFrame->LastFrameInst >= 0) 413 report_fatal_error("Frame register and offset already specified!"); 414 if (Offset & 0x0F) 415 report_fatal_error("Misaligned frame pointer offset!"); 416 MCWin64EHInstruction Inst(Win64EH::UOP_SetFPReg, NULL, Register, Offset); 417 CurFrame->LastFrameInst = CurFrame->Instructions.size(); 418 CurFrame->Instructions.push_back(Inst); 419} 420 421void MCStreamer::EmitWin64EHAllocStack(unsigned Size) { 422 EnsureValidW64UnwindInfo(); 423 if (Size & 7) 424 report_fatal_error("Misaligned stack allocation!"); 425 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 426 MCSymbol *Label = getContext().CreateTempSymbol(); 427 MCWin64EHInstruction Inst(Label, Size); 428 EmitLabel(Label); 429 CurFrame->Instructions.push_back(Inst); 430} 431 432void MCStreamer::EmitWin64EHSaveReg(unsigned Register, unsigned Offset) { 433 EnsureValidW64UnwindInfo(); 434 if (Offset & 7) 435 report_fatal_error("Misaligned saved register offset!"); 436 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 437 MCSymbol *Label = getContext().CreateTempSymbol(); 438 MCWin64EHInstruction Inst( 439 Offset > 512*1024-8 ? Win64EH::UOP_SaveNonVolBig : Win64EH::UOP_SaveNonVol, 440 Label, Register, Offset); 441 EmitLabel(Label); 442 CurFrame->Instructions.push_back(Inst); 443} 444 445void MCStreamer::EmitWin64EHSaveXMM(unsigned Register, unsigned Offset) { 446 EnsureValidW64UnwindInfo(); 447 if (Offset & 0x0F) 448 report_fatal_error("Misaligned saved vector register offset!"); 449 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 450 MCSymbol *Label = getContext().CreateTempSymbol(); 451 MCWin64EHInstruction Inst( 452 Offset > 512*1024-16 ? Win64EH::UOP_SaveXMM128Big : Win64EH::UOP_SaveXMM128, 453 Label, Register, Offset); 454 EmitLabel(Label); 455 CurFrame->Instructions.push_back(Inst); 456} 457 458void MCStreamer::EmitWin64EHPushFrame(bool Code) { 459 EnsureValidW64UnwindInfo(); 460 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 461 if (CurFrame->Instructions.size() > 0) 462 report_fatal_error("If present, PushMachFrame must be the first UOP"); 463 MCSymbol *Label = getContext().CreateTempSymbol(); 464 MCWin64EHInstruction Inst(Win64EH::UOP_PushMachFrame, Label, Code); 465 EmitLabel(Label); 466 CurFrame->Instructions.push_back(Inst); 467} 468 469void MCStreamer::EmitWin64EHEndProlog() { 470 EnsureValidW64UnwindInfo(); 471 MCWin64EHUnwindInfo *CurFrame = CurrentW64UnwindInfo; 472 CurFrame->PrologEnd = getContext().CreateTempSymbol(); 473 EmitLabel(CurFrame->PrologEnd); 474} 475 476void MCStreamer::EmitFnStart() { 477 errs() << "Not implemented yet\n"; 478 abort(); 479} 480 481void MCStreamer::EmitFnEnd() { 482 errs() << "Not implemented yet\n"; 483 abort(); 484} 485 486void MCStreamer::EmitCantUnwind() { 487 errs() << "Not implemented yet\n"; 488 abort(); 489} 490 491void MCStreamer::EmitHandlerData() { 492 errs() << "Not implemented yet\n"; 493 abort(); 494} 495 496void MCStreamer::EmitPersonality(const MCSymbol *Personality) { 497 errs() << "Not implemented yet\n"; 498 abort(); 499} 500 501void MCStreamer::EmitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset) { 502 errs() << "Not implemented yet\n"; 503 abort(); 504} 505 506void MCStreamer::EmitPad(int64_t Offset) { 507 errs() << "Not implemented yet\n"; 508 abort(); 509} 510 511void MCStreamer::EmitRegSave(const SmallVectorImpl<unsigned> &RegList, bool) { 512 errs() << "Not implemented yet\n"; 513 abort(); 514} 515 516/// EmitRawText - If this file is backed by an assembly streamer, this dumps 517/// the specified string in the output .s file. This capability is 518/// indicated by the hasRawTextSupport() predicate. 519void MCStreamer::EmitRawText(StringRef String) { 520 errs() << "EmitRawText called on an MCStreamer that doesn't support it, " 521 " something must not be fully mc'ized\n"; 522 abort(); 523} 524 525void MCStreamer::EmitRawText(const Twine &T) { 526 SmallString<128> Str; 527 T.toVector(Str); 528 EmitRawText(Str.str()); 529} 530 531void MCStreamer::EmitFrames(bool usingCFI) { 532 if (!getNumFrameInfos()) 533 return; 534 535 if (EmitEHFrame) 536 MCDwarfFrameEmitter::Emit(*this, usingCFI, true); 537 538 if (EmitDebugFrame) 539 MCDwarfFrameEmitter::Emit(*this, usingCFI, false); 540} 541 542void MCStreamer::EmitW64Tables() { 543 if (!getNumW64UnwindInfos()) 544 return; 545 546 MCWin64EHUnwindEmitter::Emit(*this); 547} 548