1 //===- lib/MC/ARMELFStreamer.cpp - ELF Object Output for ARM --------------===// 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 // This file assembles .s files and emits ARM ELF .o object files. Different 11 // from generic ELF streamer in emitting mapping symbols ($a, $t and $d) to 12 // delimit regions of data and code. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #include "ARMRegisterInfo.h" 17 #include "ARMUnwindOp.h" 18 #include "ARMUnwindOpAsm.h" 19 #include "llvm/ADT/SmallPtrSet.h" 20 #include "llvm/ADT/Twine.h" 21 #include "llvm/MC/MCAsmBackend.h" 22 #include "llvm/MC/MCAssembler.h" 23 #include "llvm/MC/MCCodeEmitter.h" 24 #include "llvm/MC/MCContext.h" 25 #include "llvm/MC/MCELF.h" 26 #include "llvm/MC/MCELFStreamer.h" 27 #include "llvm/MC/MCELFSymbolFlags.h" 28 #include "llvm/MC/MCExpr.h" 29 #include "llvm/MC/MCInst.h" 30 #include "llvm/MC/MCInstPrinter.h" 31 #include "llvm/MC/MCObjectStreamer.h" 32 #include "llvm/MC/MCRegisterInfo.h" 33 #include "llvm/MC/MCSection.h" 34 #include "llvm/MC/MCSectionELF.h" 35 #include "llvm/MC/MCStreamer.h" 36 #include "llvm/MC/MCSymbol.h" 37 #include "llvm/MC/MCValue.h" 38 #include "llvm/Support/Debug.h" 39 #include "llvm/Support/ELF.h" 40 #include "llvm/Support/FormattedStream.h" 41 #include "llvm/Support/raw_ostream.h" 42 43 using namespace llvm; 44 45 static std::string GetAEABIUnwindPersonalityName(unsigned Index) { 46 assert(Index < NUM_PERSONALITY_INDEX && "Invalid personality index"); 47 return (Twine("__aeabi_unwind_cpp_pr") + Twine(Index)).str(); 48 } 49 50 namespace { 51 52 class ARMELFStreamer; 53 54 class ARMTargetAsmStreamer : public ARMTargetStreamer { 55 formatted_raw_ostream &OS; 56 MCInstPrinter &InstPrinter; 57 58 virtual void emitFnStart(); 59 virtual void emitFnEnd(); 60 virtual void emitCantUnwind(); 61 virtual void emitPersonality(const MCSymbol *Personality); 62 virtual void emitHandlerData(); 63 virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); 64 virtual void emitPad(int64_t Offset); 65 virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, 66 bool isVector); 67 68 public: 69 ARMTargetAsmStreamer(formatted_raw_ostream &OS, MCInstPrinter &InstPrinter); 70 }; 71 72 ARMTargetAsmStreamer::ARMTargetAsmStreamer(formatted_raw_ostream &OS, 73 MCInstPrinter &InstPrinter) 74 : OS(OS), InstPrinter(InstPrinter) {} 75 void ARMTargetAsmStreamer::emitFnStart() { OS << "\t.fnstart\n"; } 76 void ARMTargetAsmStreamer::emitFnEnd() { OS << "\t.fnend\n"; } 77 void ARMTargetAsmStreamer::emitCantUnwind() { OS << "\t.cantunwind\n"; } 78 void ARMTargetAsmStreamer::emitPersonality(const MCSymbol *Personality) { 79 OS << "\t.personality " << Personality->getName() << '\n'; 80 } 81 void ARMTargetAsmStreamer::emitHandlerData() { OS << "\t.handlerdata\n"; } 82 void ARMTargetAsmStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, 83 int64_t Offset) { 84 OS << "\t.setfp\t"; 85 InstPrinter.printRegName(OS, FpReg); 86 OS << ", "; 87 InstPrinter.printRegName(OS, SpReg); 88 if (Offset) 89 OS << ", #" << Offset; 90 OS << '\n'; 91 } 92 void ARMTargetAsmStreamer::emitPad(int64_t Offset) { 93 OS << "\t.pad\t#" << Offset << '\n'; 94 } 95 void ARMTargetAsmStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, 96 bool isVector) { 97 assert(RegList.size() && "RegList should not be empty"); 98 if (isVector) 99 OS << "\t.vsave\t{"; 100 else 101 OS << "\t.save\t{"; 102 103 InstPrinter.printRegName(OS, RegList[0]); 104 105 for (unsigned i = 1, e = RegList.size(); i != e; ++i) { 106 OS << ", "; 107 InstPrinter.printRegName(OS, RegList[i]); 108 } 109 110 OS << "}\n"; 111 } 112 113 class ARMTargetELFStreamer : public ARMTargetStreamer { 114 ARMELFStreamer &getStreamer(); 115 virtual void emitFnStart(); 116 virtual void emitFnEnd(); 117 virtual void emitCantUnwind(); 118 virtual void emitPersonality(const MCSymbol *Personality); 119 virtual void emitHandlerData(); 120 virtual void emitSetFP(unsigned FpReg, unsigned SpReg, int64_t Offset = 0); 121 virtual void emitPad(int64_t Offset); 122 virtual void emitRegSave(const SmallVectorImpl<unsigned> &RegList, 123 bool isVector); 124 }; 125 126 /// Extend the generic ELFStreamer class so that it can emit mapping symbols at 127 /// the appropriate points in the object files. These symbols are defined in the 128 /// ARM ELF ABI: infocenter.arm.com/help/topic/com.arm.../IHI0044D_aaelf.pdf. 129 /// 130 /// In brief: $a, $t or $d should be emitted at the start of each contiguous 131 /// region of ARM code, Thumb code or data in a section. In practice, this 132 /// emission does not rely on explicit assembler directives but on inherent 133 /// properties of the directives doing the emission (e.g. ".byte" is data, "add 134 /// r0, r0, r0" an instruction). 135 /// 136 /// As a result this system is orthogonal to the DataRegion infrastructure used 137 /// by MachO. Beware! 138 class ARMELFStreamer : public MCELFStreamer { 139 public: 140 friend class ARMTargetELFStreamer; 141 142 ARMELFStreamer(MCContext &Context, MCTargetStreamer *TargetStreamer, 143 MCAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *Emitter, 144 bool IsThumb) 145 : MCELFStreamer(Context, TargetStreamer, TAB, OS, Emitter), 146 IsThumb(IsThumb), MappingSymbolCounter(0), LastEMS(EMS_None) { 147 Reset(); 148 } 149 150 ~ARMELFStreamer() {} 151 152 // ARM exception handling directives 153 void emitFnStart(); 154 void emitFnEnd(); 155 void emitCantUnwind(); 156 void emitPersonality(const MCSymbol *Per); 157 void emitHandlerData(); 158 void emitSetFP(unsigned NewFpReg, unsigned NewSpReg, int64_t Offset = 0); 159 void emitPad(int64_t Offset); 160 void emitRegSave(const SmallVectorImpl<unsigned> &RegList, bool isVector); 161 162 virtual void ChangeSection(const MCSection *Section, 163 const MCExpr *Subsection) { 164 // We have to keep track of the mapping symbol state of any sections we 165 // use. Each one should start off as EMS_None, which is provided as the 166 // default constructor by DenseMap::lookup. 167 LastMappingSymbols[getPreviousSection().first] = LastEMS; 168 LastEMS = LastMappingSymbols.lookup(Section); 169 170 MCELFStreamer::ChangeSection(Section, Subsection); 171 } 172 173 /// This function is the one used to emit instruction data into the ELF 174 /// streamer. We override it to add the appropriate mapping symbol if 175 /// necessary. 176 virtual void EmitInstruction(const MCInst& Inst) { 177 if (IsThumb) 178 EmitThumbMappingSymbol(); 179 else 180 EmitARMMappingSymbol(); 181 182 MCELFStreamer::EmitInstruction(Inst); 183 } 184 185 /// This is one of the functions used to emit data into an ELF section, so the 186 /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if 187 /// necessary. 188 virtual void EmitBytes(StringRef Data) { 189 EmitDataMappingSymbol(); 190 MCELFStreamer::EmitBytes(Data); 191 } 192 193 /// This is one of the functions used to emit data into an ELF section, so the 194 /// ARM streamer overrides it to add the appropriate mapping symbol ($d) if 195 /// necessary. 196 virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) { 197 EmitDataMappingSymbol(); 198 MCELFStreamer::EmitValueImpl(Value, Size); 199 } 200 201 virtual void EmitAssemblerFlag(MCAssemblerFlag Flag) { 202 MCELFStreamer::EmitAssemblerFlag(Flag); 203 204 switch (Flag) { 205 case MCAF_SyntaxUnified: 206 return; // no-op here. 207 case MCAF_Code16: 208 IsThumb = true; 209 return; // Change to Thumb mode 210 case MCAF_Code32: 211 IsThumb = false; 212 return; // Change to ARM mode 213 case MCAF_Code64: 214 return; 215 case MCAF_SubsectionsViaSymbols: 216 return; 217 } 218 } 219 220 private: 221 enum ElfMappingSymbol { 222 EMS_None, 223 EMS_ARM, 224 EMS_Thumb, 225 EMS_Data 226 }; 227 228 void EmitDataMappingSymbol() { 229 if (LastEMS == EMS_Data) return; 230 EmitMappingSymbol("$d"); 231 LastEMS = EMS_Data; 232 } 233 234 void EmitThumbMappingSymbol() { 235 if (LastEMS == EMS_Thumb) return; 236 EmitMappingSymbol("$t"); 237 LastEMS = EMS_Thumb; 238 } 239 240 void EmitARMMappingSymbol() { 241 if (LastEMS == EMS_ARM) return; 242 EmitMappingSymbol("$a"); 243 LastEMS = EMS_ARM; 244 } 245 246 void EmitMappingSymbol(StringRef Name) { 247 MCSymbol *Start = getContext().CreateTempSymbol(); 248 EmitLabel(Start); 249 250 MCSymbol *Symbol = 251 getContext().GetOrCreateSymbol(Name + "." + 252 Twine(MappingSymbolCounter++)); 253 254 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); 255 MCELF::SetType(SD, ELF::STT_NOTYPE); 256 MCELF::SetBinding(SD, ELF::STB_LOCAL); 257 SD.setExternal(false); 258 AssignSection(Symbol, getCurrentSection().first); 259 260 const MCExpr *Value = MCSymbolRefExpr::Create(Start, getContext()); 261 Symbol->setVariableValue(Value); 262 } 263 264 void EmitThumbFunc(MCSymbol *Func) { 265 // FIXME: Anything needed here to flag the function as thumb? 266 267 getAssembler().setIsThumbFunc(Func); 268 269 MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Func); 270 SD.setFlags(SD.getFlags() | ELF_Other_ThumbFunc); 271 } 272 273 // Helper functions for ARM exception handling directives 274 void Reset(); 275 276 void EmitPersonalityFixup(StringRef Name); 277 void FlushPendingOffset(); 278 void FlushUnwindOpcodes(bool NoHandlerData); 279 280 void SwitchToEHSection(const char *Prefix, unsigned Type, unsigned Flags, 281 SectionKind Kind, const MCSymbol &Fn); 282 void SwitchToExTabSection(const MCSymbol &FnStart); 283 void SwitchToExIdxSection(const MCSymbol &FnStart); 284 285 bool IsThumb; 286 int64_t MappingSymbolCounter; 287 288 DenseMap<const MCSection *, ElfMappingSymbol> LastMappingSymbols; 289 ElfMappingSymbol LastEMS; 290 291 // ARM Exception Handling Frame Information 292 MCSymbol *ExTab; 293 MCSymbol *FnStart; 294 const MCSymbol *Personality; 295 unsigned PersonalityIndex; 296 unsigned FPReg; // Frame pointer register 297 int64_t FPOffset; // Offset: (final frame pointer) - (initial $sp) 298 int64_t SPOffset; // Offset: (final $sp) - (initial $sp) 299 int64_t PendingOffset; // Offset: (final $sp) - (emitted $sp) 300 bool UsedFP; 301 bool CantUnwind; 302 SmallVector<uint8_t, 64> Opcodes; 303 UnwindOpcodeAssembler UnwindOpAsm; 304 }; 305 } // end anonymous namespace 306 307 ARMELFStreamer &ARMTargetELFStreamer::getStreamer() { 308 ARMELFStreamer *S = static_cast<ARMELFStreamer *>(Streamer); 309 return *S; 310 } 311 312 void ARMTargetELFStreamer::emitFnStart() { getStreamer().emitFnStart(); } 313 void ARMTargetELFStreamer::emitFnEnd() { getStreamer().emitFnEnd(); } 314 void ARMTargetELFStreamer::emitCantUnwind() { getStreamer().emitCantUnwind(); } 315 void ARMTargetELFStreamer::emitPersonality(const MCSymbol *Personality) { 316 getStreamer().emitPersonality(Personality); 317 } 318 void ARMTargetELFStreamer::emitHandlerData() { 319 getStreamer().emitHandlerData(); 320 } 321 void ARMTargetELFStreamer::emitSetFP(unsigned FpReg, unsigned SpReg, 322 int64_t Offset) { 323 getStreamer().emitSetFP(FpReg, SpReg, Offset); 324 } 325 void ARMTargetELFStreamer::emitPad(int64_t Offset) { 326 getStreamer().emitPad(Offset); 327 } 328 void ARMTargetELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, 329 bool isVector) { 330 getStreamer().emitRegSave(RegList, isVector); 331 } 332 333 inline void ARMELFStreamer::SwitchToEHSection(const char *Prefix, 334 unsigned Type, 335 unsigned Flags, 336 SectionKind Kind, 337 const MCSymbol &Fn) { 338 const MCSectionELF &FnSection = 339 static_cast<const MCSectionELF &>(Fn.getSection()); 340 341 // Create the name for new section 342 StringRef FnSecName(FnSection.getSectionName()); 343 SmallString<128> EHSecName(Prefix); 344 if (FnSecName != ".text") { 345 EHSecName += FnSecName; 346 } 347 348 // Get .ARM.extab or .ARM.exidx section 349 const MCSectionELF *EHSection = NULL; 350 if (const MCSymbol *Group = FnSection.getGroup()) { 351 EHSection = getContext().getELFSection( 352 EHSecName, Type, Flags | ELF::SHF_GROUP, Kind, 353 FnSection.getEntrySize(), Group->getName()); 354 } else { 355 EHSection = getContext().getELFSection(EHSecName, Type, Flags, Kind); 356 } 357 assert(EHSection && "Failed to get the required EH section"); 358 359 // Switch to .ARM.extab or .ARM.exidx section 360 SwitchSection(EHSection); 361 EmitCodeAlignment(4, 0); 362 } 363 364 inline void ARMELFStreamer::SwitchToExTabSection(const MCSymbol &FnStart) { 365 SwitchToEHSection(".ARM.extab", 366 ELF::SHT_PROGBITS, 367 ELF::SHF_ALLOC, 368 SectionKind::getDataRel(), 369 FnStart); 370 } 371 372 inline void ARMELFStreamer::SwitchToExIdxSection(const MCSymbol &FnStart) { 373 SwitchToEHSection(".ARM.exidx", 374 ELF::SHT_ARM_EXIDX, 375 ELF::SHF_ALLOC | ELF::SHF_LINK_ORDER, 376 SectionKind::getDataRel(), 377 FnStart); 378 } 379 380 void ARMELFStreamer::Reset() { 381 ExTab = NULL; 382 FnStart = NULL; 383 Personality = NULL; 384 PersonalityIndex = NUM_PERSONALITY_INDEX; 385 FPReg = ARM::SP; 386 FPOffset = 0; 387 SPOffset = 0; 388 PendingOffset = 0; 389 UsedFP = false; 390 CantUnwind = false; 391 392 Opcodes.clear(); 393 UnwindOpAsm.Reset(); 394 } 395 396 void ARMELFStreamer::emitFnStart() { 397 assert(FnStart == 0); 398 FnStart = getContext().CreateTempSymbol(); 399 EmitLabel(FnStart); 400 } 401 402 void ARMELFStreamer::emitFnEnd() { 403 assert(FnStart && ".fnstart must preceeds .fnend"); 404 405 // Emit unwind opcodes if there is no .handlerdata directive 406 if (!ExTab && !CantUnwind) 407 FlushUnwindOpcodes(true); 408 409 // Emit the exception index table entry 410 SwitchToExIdxSection(*FnStart); 411 412 if (PersonalityIndex < NUM_PERSONALITY_INDEX) 413 EmitPersonalityFixup(GetAEABIUnwindPersonalityName(PersonalityIndex)); 414 415 const MCSymbolRefExpr *FnStartRef = 416 MCSymbolRefExpr::Create(FnStart, 417 MCSymbolRefExpr::VK_ARM_PREL31, 418 getContext()); 419 420 EmitValue(FnStartRef, 4); 421 422 if (CantUnwind) { 423 EmitIntValue(EXIDX_CANTUNWIND, 4); 424 } else if (ExTab) { 425 // Emit a reference to the unwind opcodes in the ".ARM.extab" section. 426 const MCSymbolRefExpr *ExTabEntryRef = 427 MCSymbolRefExpr::Create(ExTab, 428 MCSymbolRefExpr::VK_ARM_PREL31, 429 getContext()); 430 EmitValue(ExTabEntryRef, 4); 431 } else { 432 // For the __aeabi_unwind_cpp_pr0, we have to emit the unwind opcodes in 433 // the second word of exception index table entry. The size of the unwind 434 // opcodes should always be 4 bytes. 435 assert(PersonalityIndex == AEABI_UNWIND_CPP_PR0 && 436 "Compact model must use __aeabi_cpp_unwind_pr0 as personality"); 437 assert(Opcodes.size() == 4u && 438 "Unwind opcode size for __aeabi_cpp_unwind_pr0 must be equal to 4"); 439 EmitBytes(StringRef(reinterpret_cast<const char*>(Opcodes.data()), 440 Opcodes.size())); 441 } 442 443 // Switch to the section containing FnStart 444 SwitchSection(&FnStart->getSection()); 445 446 // Clean exception handling frame information 447 Reset(); 448 } 449 450 void ARMELFStreamer::emitCantUnwind() { CantUnwind = true; } 451 452 // Add the R_ARM_NONE fixup at the same position 453 void ARMELFStreamer::EmitPersonalityFixup(StringRef Name) { 454 const MCSymbol *PersonalitySym = getContext().GetOrCreateSymbol(Name); 455 456 const MCSymbolRefExpr *PersonalityRef = MCSymbolRefExpr::Create( 457 PersonalitySym, MCSymbolRefExpr::VK_ARM_NONE, getContext()); 458 459 AddValueSymbols(PersonalityRef); 460 MCDataFragment *DF = getOrCreateDataFragment(); 461 DF->getFixups().push_back(MCFixup::Create(DF->getContents().size(), 462 PersonalityRef, 463 MCFixup::getKindForSize(4, false))); 464 } 465 466 void ARMELFStreamer::FlushPendingOffset() { 467 if (PendingOffset != 0) { 468 UnwindOpAsm.EmitSPOffset(-PendingOffset); 469 PendingOffset = 0; 470 } 471 } 472 473 void ARMELFStreamer::FlushUnwindOpcodes(bool NoHandlerData) { 474 // Emit the unwind opcode to restore $sp. 475 if (UsedFP) { 476 const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 477 int64_t LastRegSaveSPOffset = SPOffset - PendingOffset; 478 UnwindOpAsm.EmitSPOffset(LastRegSaveSPOffset - FPOffset); 479 UnwindOpAsm.EmitSetSP(MRI->getEncodingValue(FPReg)); 480 } else { 481 FlushPendingOffset(); 482 } 483 484 // Finalize the unwind opcode sequence 485 UnwindOpAsm.Finalize(PersonalityIndex, Opcodes); 486 487 // For compact model 0, we have to emit the unwind opcodes in the .ARM.exidx 488 // section. Thus, we don't have to create an entry in the .ARM.extab 489 // section. 490 if (NoHandlerData && PersonalityIndex == AEABI_UNWIND_CPP_PR0) 491 return; 492 493 // Switch to .ARM.extab section. 494 SwitchToExTabSection(*FnStart); 495 496 // Create .ARM.extab label for offset in .ARM.exidx 497 assert(!ExTab); 498 ExTab = getContext().CreateTempSymbol(); 499 EmitLabel(ExTab); 500 501 // Emit personality 502 if (Personality) { 503 const MCSymbolRefExpr *PersonalityRef = 504 MCSymbolRefExpr::Create(Personality, 505 MCSymbolRefExpr::VK_ARM_PREL31, 506 getContext()); 507 508 EmitValue(PersonalityRef, 4); 509 } 510 511 // Emit unwind opcodes 512 EmitBytes(StringRef(reinterpret_cast<const char *>(Opcodes.data()), 513 Opcodes.size())); 514 515 // According to ARM EHABI section 9.2, if the __aeabi_unwind_cpp_pr1() or 516 // __aeabi_unwind_cpp_pr2() is used, then the handler data must be emitted 517 // after the unwind opcodes. The handler data consists of several 32-bit 518 // words, and should be terminated by zero. 519 // 520 // In case that the .handlerdata directive is not specified by the 521 // programmer, we should emit zero to terminate the handler data. 522 if (NoHandlerData && !Personality) 523 EmitIntValue(0, 4); 524 } 525 526 void ARMELFStreamer::emitHandlerData() { FlushUnwindOpcodes(false); } 527 528 void ARMELFStreamer::emitPersonality(const MCSymbol *Per) { 529 Personality = Per; 530 UnwindOpAsm.setPersonality(Per); 531 } 532 533 void ARMELFStreamer::emitSetFP(unsigned NewFPReg, unsigned NewSPReg, 534 int64_t Offset) { 535 assert((NewSPReg == ARM::SP || NewSPReg == FPReg) && 536 "the operand of .setfp directive should be either $sp or $fp"); 537 538 UsedFP = true; 539 FPReg = NewFPReg; 540 541 if (NewSPReg == ARM::SP) 542 FPOffset = SPOffset + Offset; 543 else 544 FPOffset += Offset; 545 } 546 547 void ARMELFStreamer::emitPad(int64_t Offset) { 548 // Track the change of the $sp offset 549 SPOffset -= Offset; 550 551 // To squash multiple .pad directives, we should delay the unwind opcode 552 // until the .save, .vsave, .handlerdata, or .fnend directives. 553 PendingOffset -= Offset; 554 } 555 556 void ARMELFStreamer::emitRegSave(const SmallVectorImpl<unsigned> &RegList, 557 bool IsVector) { 558 // Collect the registers in the register list 559 unsigned Count = 0; 560 uint32_t Mask = 0; 561 const MCRegisterInfo *MRI = getContext().getRegisterInfo(); 562 for (size_t i = 0; i < RegList.size(); ++i) { 563 unsigned Reg = MRI->getEncodingValue(RegList[i]); 564 assert(Reg < (IsVector ? 32U : 16U) && "Register out of range"); 565 unsigned Bit = (1u << Reg); 566 if ((Mask & Bit) == 0) { 567 Mask |= Bit; 568 ++Count; 569 } 570 } 571 572 // Track the change the $sp offset: For the .save directive, the 573 // corresponding push instruction will decrease the $sp by (4 * Count). 574 // For the .vsave directive, the corresponding vpush instruction will 575 // decrease $sp by (8 * Count). 576 SPOffset -= Count * (IsVector ? 8 : 4); 577 578 // Emit the opcode 579 FlushPendingOffset(); 580 if (IsVector) 581 UnwindOpAsm.EmitVFPRegSave(Mask); 582 else 583 UnwindOpAsm.EmitRegSave(Mask); 584 } 585 586 namespace llvm { 587 588 MCStreamer *createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, 589 bool isVerboseAsm, bool useLoc, bool useCFI, 590 bool useDwarfDirectory, 591 MCInstPrinter *InstPrint, MCCodeEmitter *CE, 592 MCAsmBackend *TAB, bool ShowInst) { 593 ARMTargetAsmStreamer *S = new ARMTargetAsmStreamer(OS, *InstPrint); 594 595 return llvm::createAsmStreamer(Ctx, S, OS, isVerboseAsm, useLoc, useCFI, 596 useDwarfDirectory, InstPrint, CE, TAB, 597 ShowInst); 598 } 599 600 MCELFStreamer* createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, 601 raw_ostream &OS, MCCodeEmitter *Emitter, 602 bool RelaxAll, bool NoExecStack, 603 bool IsThumb) { 604 ARMTargetELFStreamer *TS = new ARMTargetELFStreamer(); 605 ARMELFStreamer *S = 606 new ARMELFStreamer(Context, TS, TAB, OS, Emitter, IsThumb); 607 // FIXME: This should eventually end up somewhere else where more 608 // intelligent flag decisions can be made. For now we are just maintaining 609 // the status quo for ARM and setting EF_ARM_EABI_VER5 as the default. 610 S->getAssembler().setELFHeaderEFlags(ELF::EF_ARM_EABI_VER5); 611 612 if (RelaxAll) 613 S->getAssembler().setRelaxAll(true); 614 if (NoExecStack) 615 S->getAssembler().setNoExecStack(true); 616 return S; 617 } 618 619 } 620 621 622