1 //===- AArch64TargetStreamer.cpp - AArch64TargetStreamer class ------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the AArch64TargetStreamer class. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "AArch64TargetStreamer.h" 14 #include "AArch64MCAsmInfo.h" 15 #include "AArch64Subtarget.h" 16 #include "llvm/BinaryFormat/ELF.h" 17 #include "llvm/MC/ConstantPools.h" 18 #include "llvm/MC/MCContext.h" 19 #include "llvm/MC/MCSection.h" 20 #include "llvm/MC/MCSectionELF.h" 21 #include "llvm/MC/MCSubtargetInfo.h" 22 #include "llvm/Support/CommandLine.h" 23 24 using namespace llvm; 25 26 static cl::opt<bool> MarkBTIProperty( 27 "aarch64-mark-bti-property", cl::Hidden, 28 cl::desc("Add .note.gnu.property with BTI to assembly files"), 29 cl::init(false)); 30 31 // 32 // AArch64TargetStreamer Implemenation 33 // 34 AArch64TargetStreamer::AArch64TargetStreamer(MCStreamer &S) 35 : MCTargetStreamer(S), ConstantPools(new AssemblerConstantPools()) {} 36 37 AArch64TargetStreamer::~AArch64TargetStreamer() = default; 38 39 // The constant pool handling is shared by all AArch64TargetStreamer 40 // implementations. 41 const MCExpr *AArch64TargetStreamer::addConstantPoolEntry(const MCExpr *Expr, 42 unsigned Size, 43 SMLoc Loc) { 44 return ConstantPools->addEntry(Streamer, Expr, Size, Loc); 45 } 46 47 void AArch64TargetStreamer::emitCurrentConstantPool() { 48 ConstantPools->emitForCurrentSection(Streamer); 49 } 50 51 void AArch64TargetStreamer::emitConstantPools() { 52 ConstantPools->emitAll(Streamer); 53 } 54 55 // finish() - write out any non-empty assembler constant pools and 56 // write out note.gnu.properties if need. 57 void AArch64TargetStreamer::finish() { 58 if (MarkBTIProperty) 59 emitNoteSection(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_BTI); 60 } 61 62 void AArch64TargetStreamer::emitNoteSection(unsigned Flags) { 63 if (Flags == 0) 64 return; 65 66 MCStreamer &OutStreamer = getStreamer(); 67 MCContext &Context = OutStreamer.getContext(); 68 // Emit a .note.gnu.property section with the flags. 69 MCSectionELF *Nt = Context.getELFSection(".note.gnu.property", ELF::SHT_NOTE, 70 ELF::SHF_ALLOC); 71 if (Nt->isRegistered()) { 72 SMLoc Loc; 73 Context.reportWarning( 74 Loc, 75 "The .note.gnu.property is not emitted because it is already present."); 76 return; 77 } 78 MCSection *Cur = OutStreamer.getCurrentSectionOnly(); 79 OutStreamer.switchSection(Nt); 80 81 // Emit the note header. 82 OutStreamer.emitValueToAlignment(Align(8)); 83 OutStreamer.emitIntValue(4, 4); // data size for "GNU\0" 84 OutStreamer.emitIntValue(4 * 4, 4); // Elf_Prop size 85 OutStreamer.emitIntValue(ELF::NT_GNU_PROPERTY_TYPE_0, 4); 86 OutStreamer.emitBytes(StringRef("GNU", 4)); // note name 87 88 // Emit the PAC/BTI properties. 89 OutStreamer.emitIntValue(ELF::GNU_PROPERTY_AARCH64_FEATURE_1_AND, 4); 90 OutStreamer.emitIntValue(4, 4); // data size 91 OutStreamer.emitIntValue(Flags, 4); // data 92 OutStreamer.emitIntValue(0, 4); // pad 93 94 OutStreamer.endSection(Nt); 95 OutStreamer.switchSection(Cur); 96 } 97 98 void AArch64TargetStreamer::emitInst(uint32_t Inst) { 99 char Buffer[4]; 100 101 // We can't just use EmitIntValue here, as that will swap the 102 // endianness on big-endian systems (instructions are always 103 // little-endian). 104 for (char &C : Buffer) { 105 C = uint8_t(Inst); 106 Inst >>= 8; 107 } 108 109 getStreamer().emitBytes(StringRef(Buffer, 4)); 110 } 111 112 MCTargetStreamer * 113 llvm::createAArch64ObjectTargetStreamer(MCStreamer &S, 114 const MCSubtargetInfo &STI) { 115 const Triple &TT = STI.getTargetTriple(); 116 if (TT.isOSBinFormatELF()) 117 return new AArch64TargetELFStreamer(S); 118 if (TT.isOSBinFormatCOFF()) 119 return new AArch64TargetWinCOFFStreamer(S); 120 return nullptr; 121 } 122 123 MCTargetStreamer *llvm::createAArch64NullTargetStreamer(MCStreamer &S) { 124 return new AArch64TargetStreamer(S); 125 } 126