| 1 | //===-- SystemZELFAsmPrinter.cpp - SystemZ ELF asm printer ----------------===// |
| 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 SystemZELFAsmPrinter class. |
| 10 | // |
| 11 | //===----------------------------------------------------------------------===// |
| 12 | |
| 13 | #include "SystemZELFAsmPrinter.h" |
| 14 | #include "MCTargetDesc/SystemZMCTargetDesc.h" |
| 15 | #include "SystemZConstantPoolValue.h" |
| 16 | #include "SystemZMCInstLower.h" |
| 17 | #include "SystemZSubtarget.h" |
| 18 | #include "llvm/BinaryFormat/ELF.h" |
| 19 | #include "llvm/CodeGen/MachineConstantPool.h" |
| 20 | #include "llvm/CodeGen/StackMaps.h" |
| 21 | #include "llvm/IR/Module.h" |
| 22 | #include "llvm/MC/MCExpr.h" |
| 23 | #include "llvm/MC/MCInstBuilder.h" |
| 24 | #include "llvm/MC/MCSectionELF.h" |
| 25 | #include "llvm/MC/MCStreamer.h" |
| 26 | |
| 27 | using namespace llvm; |
| 28 | |
| 29 | // Emit the largest nop instruction smaller than or equal to NumBytes |
| 30 | // bytes. Return the size of nop emitted. |
| 31 | static unsigned EmitNop(MCContext &OutContext, MCStreamer &OutStreamer, |
| 32 | unsigned NumBytes, const MCSubtargetInfo &STI) { |
| 33 | if (NumBytes < 2) { |
| 34 | llvm_unreachable("Zero nops?" ); |
| 35 | return 0; |
| 36 | } else if (NumBytes < 4) { |
| 37 | OutStreamer.emitInstruction( |
| 38 | Inst: MCInstBuilder(SystemZ::BCRAsm).addImm(Val: 0).addReg(Reg: SystemZ::R0D), STI); |
| 39 | return 2; |
| 40 | } else if (NumBytes < 6) { |
| 41 | OutStreamer.emitInstruction( |
| 42 | Inst: MCInstBuilder(SystemZ::BCAsm).addImm(Val: 0).addReg(Reg: 0).addImm(Val: 0).addReg(Reg: 0), |
| 43 | STI); |
| 44 | return 4; |
| 45 | } else { |
| 46 | MCSymbol *DotSym = OutContext.createTempSymbol(); |
| 47 | const MCSymbolRefExpr *Dot = MCSymbolRefExpr::create(Symbol: DotSym, Ctx&: OutContext); |
| 48 | OutStreamer.emitLabel(Symbol: DotSym); |
| 49 | OutStreamer.emitInstruction( |
| 50 | Inst: MCInstBuilder(SystemZ::BRCLAsm).addImm(Val: 0).addExpr(Val: Dot), STI); |
| 51 | return 6; |
| 52 | } |
| 53 | } |
| 54 | |
| 55 | static const MCSymbolRefExpr *getTLSGetOffset(MCContext &Context) { |
| 56 | StringRef Name = "__tls_get_offset" ; |
| 57 | return MCSymbolRefExpr::create(Symbol: Context.getOrCreateSymbol(Name), |
| 58 | specifier: SystemZ::S_PLT, Ctx&: Context); |
| 59 | } |
| 60 | |
| 61 | static const MCSymbolRefExpr *getGlobalOffsetTable(MCContext &Context) { |
| 62 | StringRef Name = "_GLOBAL_OFFSET_TABLE_" ; |
| 63 | return MCSymbolRefExpr::create(Symbol: Context.getOrCreateSymbol(Name), Ctx&: Context); |
| 64 | } |
| 65 | |
| 66 | SystemZELFAsmPrinter::SystemZELFAsmPrinter(TargetMachine &TM, |
| 67 | std::unique_ptr<MCStreamer> Streamer) |
| 68 | : SystemZAsmPrinter(TM, std::move(Streamer)) {} |
| 69 | |
| 70 | void SystemZELFAsmPrinter::emitInstruction(const MachineInstr *MI) { |
| 71 | SystemZMCInstLower Lower(MF->getContext(), *this); |
| 72 | |
| 73 | switch (MI->getOpcode()) { |
| 74 | case TargetOpcode::FENTRY_CALL: |
| 75 | LowerFENTRY_CALL(MI: *MI, Lower); |
| 76 | return; |
| 77 | case TargetOpcode::STACKMAP: |
| 78 | LowerSTACKMAP(MI: *MI); |
| 79 | return; |
| 80 | case TargetOpcode::PATCHPOINT: |
| 81 | LowerPATCHPOINT(MI: *MI, Lower); |
| 82 | return; |
| 83 | case TargetOpcode::PATCHABLE_FUNCTION_ENTER: |
| 84 | LowerPATCHABLE_FUNCTION_ENTER(MI: *MI, Lower); |
| 85 | return; |
| 86 | case TargetOpcode::PATCHABLE_RET: |
| 87 | LowerPATCHABLE_RET(MI: *MI, Lower); |
| 88 | return; |
| 89 | case SystemZ::CallBASR: |
| 90 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::BASR) |
| 91 | .addReg(Reg: SystemZ::R14D) |
| 92 | .addReg(Reg: MI->getOperand(i: 0).getReg())); |
| 93 | return; |
| 94 | case SystemZ::CallBRASL: |
| 95 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::BRASL) |
| 96 | .addReg(Reg: SystemZ::R14D) |
| 97 | .addExpr(Val: Lower.getExpr(MO: MI->getOperand(i: 0), |
| 98 | SystemZ::S_PLT))); |
| 99 | return; |
| 100 | case SystemZ::CallJG: |
| 101 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::JG) |
| 102 | .addExpr(Val: Lower.getExpr(MO: MI->getOperand(i: 0), |
| 103 | SystemZ::S_PLT))); |
| 104 | return; |
| 105 | case SystemZ::CallBRCL: |
| 106 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::BRCL) |
| 107 | .addImm(Val: MI->getOperand(i: 0).getImm()) |
| 108 | .addImm(Val: MI->getOperand(i: 1).getImm()) |
| 109 | .addExpr(Val: Lower.getExpr(MO: MI->getOperand(i: 2), |
| 110 | SystemZ::S_PLT))); |
| 111 | return; |
| 112 | case SystemZ::TLS_GDCALL: |
| 113 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::BRASL) |
| 114 | .addReg(Reg: SystemZ::R14D) |
| 115 | .addExpr(Val: getTLSGetOffset(Context&: MF->getContext())) |
| 116 | .addExpr(Val: Lower.getExpr(MO: MI->getOperand(i: 0), |
| 117 | SystemZ::S_TLSGD))); |
| 118 | return; |
| 119 | case SystemZ::TLS_LDCALL: |
| 120 | EmitToStreamer( |
| 121 | S&: *OutStreamer, |
| 122 | Inst: MCInstBuilder(SystemZ::BRASL) |
| 123 | .addReg(Reg: SystemZ::R14D) |
| 124 | .addExpr(Val: getTLSGetOffset(Context&: MF->getContext())) |
| 125 | .addExpr(Val: Lower.getExpr(MO: MI->getOperand(i: 0), SystemZ::S_TLSLDM))); |
| 126 | return; |
| 127 | case SystemZ::GOT: |
| 128 | EmitToStreamer(S&: *OutStreamer, |
| 129 | Inst: MCInstBuilder(SystemZ::LARL) |
| 130 | .addReg(Reg: MI->getOperand(i: 0).getReg()) |
| 131 | .addExpr(Val: getGlobalOffsetTable(Context&: MF->getContext()))); |
| 132 | return; |
| 133 | case SystemZ::LOAD_TLS_BLOCK_ADDR: |
| 134 | lowerLOAD_TLS_BLOCK_ADDR(MI: *MI, Lower); |
| 135 | return; |
| 136 | case SystemZ::LOAD_GLOBAL_STACKGUARD_ADDR: |
| 137 | lowerLOAD_GLOBAL_STACKGUARD_ADDR(MI: *MI, Lower); |
| 138 | return; |
| 139 | default: |
| 140 | SystemZAsmPrinter::emitInstruction(MI); |
| 141 | return; |
| 142 | } |
| 143 | } |
| 144 | |
| 145 | void SystemZELFAsmPrinter::LowerFENTRY_CALL(const MachineInstr &MI, |
| 146 | SystemZMCInstLower &Lower) { |
| 147 | MCContext &Ctx = MF->getContext(); |
| 148 | if (MF->getFunction().hasFnAttribute(Kind: "mrecord-mcount" )) { |
| 149 | MCSymbol *DotSym = OutContext.createTempSymbol(); |
| 150 | OutStreamer->pushSection(); |
| 151 | OutStreamer->switchSection( |
| 152 | Section: Ctx.getELFSection(Section: "__mcount_loc" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC)); |
| 153 | OutStreamer->emitSymbolValue(Sym: DotSym, Size: 8); |
| 154 | OutStreamer->popSection(); |
| 155 | OutStreamer->emitLabel(Symbol: DotSym); |
| 156 | } |
| 157 | |
| 158 | if (MF->getFunction().hasFnAttribute(Kind: "mnop-mcount" )) { |
| 159 | EmitNop(OutContext&: Ctx, OutStreamer&: *OutStreamer, NumBytes: 6, STI: getSubtargetInfo()); |
| 160 | return; |
| 161 | } |
| 162 | |
| 163 | MCSymbol *fentry = Ctx.getOrCreateSymbol(Name: "__fentry__" ); |
| 164 | const MCSymbolRefExpr *Op = |
| 165 | MCSymbolRefExpr::create(Symbol: fentry, specifier: SystemZ::S_PLT, Ctx); |
| 166 | OutStreamer->emitInstruction( |
| 167 | Inst: MCInstBuilder(SystemZ::BRASL).addReg(Reg: SystemZ::R0D).addExpr(Val: Op), |
| 168 | STI: getSubtargetInfo()); |
| 169 | } |
| 170 | |
| 171 | void SystemZELFAsmPrinter::LowerSTACKMAP(const MachineInstr &MI) { |
| 172 | auto *TII = MF->getSubtarget<SystemZSubtarget>().getInstrInfo(); |
| 173 | |
| 174 | unsigned NumNOPBytes = MI.getOperand(i: 1).getImm(); |
| 175 | |
| 176 | auto &Ctx = OutStreamer->getContext(); |
| 177 | MCSymbol *MILabel = Ctx.createTempSymbol(); |
| 178 | OutStreamer->emitLabel(Symbol: MILabel); |
| 179 | |
| 180 | SM.recordStackMap(L: *MILabel, MI); |
| 181 | assert(NumNOPBytes % 2 == 0 && "Invalid number of NOP bytes requested!" ); |
| 182 | |
| 183 | // Scan ahead to trim the shadow. |
| 184 | unsigned ShadowBytes = 0; |
| 185 | const MachineBasicBlock &MBB = *MI.getParent(); |
| 186 | MachineBasicBlock::const_iterator MII(MI); |
| 187 | ++MII; |
| 188 | while (ShadowBytes < NumNOPBytes) { |
| 189 | if (MII == MBB.end() || MII->getOpcode() == TargetOpcode::PATCHPOINT || |
| 190 | MII->getOpcode() == TargetOpcode::STACKMAP) |
| 191 | break; |
| 192 | ShadowBytes += TII->getInstSizeInBytes(MI: *MII); |
| 193 | if (MII->isCall()) |
| 194 | break; |
| 195 | ++MII; |
| 196 | } |
| 197 | |
| 198 | // Emit nops. |
| 199 | while (ShadowBytes < NumNOPBytes) |
| 200 | ShadowBytes += EmitNop(OutContext, OutStreamer&: *OutStreamer, NumBytes: NumNOPBytes - ShadowBytes, |
| 201 | STI: getSubtargetInfo()); |
| 202 | } |
| 203 | |
| 204 | // Lower a patchpoint of the form: |
| 205 | // [<def>], <id>, <numBytes>, <target>, <numArgs> |
| 206 | void SystemZELFAsmPrinter::LowerPATCHPOINT(const MachineInstr &MI, |
| 207 | SystemZMCInstLower &Lower) { |
| 208 | auto &Ctx = OutStreamer->getContext(); |
| 209 | MCSymbol *MILabel = Ctx.createTempSymbol(); |
| 210 | OutStreamer->emitLabel(Symbol: MILabel); |
| 211 | |
| 212 | SM.recordPatchPoint(L: *MILabel, MI); |
| 213 | PatchPointOpers Opers(&MI); |
| 214 | |
| 215 | unsigned EncodedBytes = 0; |
| 216 | const MachineOperand &CalleeMO = Opers.getCallTarget(); |
| 217 | |
| 218 | if (CalleeMO.isImm()) { |
| 219 | uint64_t CallTarget = CalleeMO.getImm(); |
| 220 | if (CallTarget) { |
| 221 | unsigned ScratchIdx = -1; |
| 222 | unsigned ScratchReg = 0; |
| 223 | do { |
| 224 | ScratchIdx = Opers.getNextScratchIdx(StartIdx: ScratchIdx + 1); |
| 225 | ScratchReg = MI.getOperand(i: ScratchIdx).getReg(); |
| 226 | } while (ScratchReg == SystemZ::R0D); |
| 227 | |
| 228 | // Materialize the call target address |
| 229 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::LLILF) |
| 230 | .addReg(Reg: ScratchReg) |
| 231 | .addImm(Val: CallTarget & 0xFFFFFFFF)); |
| 232 | EncodedBytes += 6; |
| 233 | if (CallTarget >> 32) { |
| 234 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::IIHF) |
| 235 | .addReg(Reg: ScratchReg) |
| 236 | .addImm(Val: CallTarget >> 32)); |
| 237 | EncodedBytes += 6; |
| 238 | } |
| 239 | |
| 240 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::BASR) |
| 241 | .addReg(Reg: SystemZ::R14D) |
| 242 | .addReg(Reg: ScratchReg)); |
| 243 | EncodedBytes += 2; |
| 244 | } |
| 245 | } else if (CalleeMO.isGlobal()) { |
| 246 | const MCExpr *Expr = Lower.getExpr(MO: CalleeMO, SystemZ::S_PLT); |
| 247 | EmitToStreamer( |
| 248 | S&: *OutStreamer, |
| 249 | Inst: MCInstBuilder(SystemZ::BRASL).addReg(Reg: SystemZ::R14D).addExpr(Val: Expr)); |
| 250 | EncodedBytes += 6; |
| 251 | } |
| 252 | |
| 253 | // Emit padding. |
| 254 | unsigned NumBytes = Opers.getNumPatchBytes(); |
| 255 | assert(NumBytes >= EncodedBytes && |
| 256 | "Patchpoint can't request size less than the length of a call." ); |
| 257 | assert((NumBytes - EncodedBytes) % 2 == 0 && |
| 258 | "Invalid number of NOP bytes requested!" ); |
| 259 | while (EncodedBytes < NumBytes) |
| 260 | EncodedBytes += EmitNop(OutContext, OutStreamer&: *OutStreamer, NumBytes: NumBytes - EncodedBytes, |
| 261 | STI: getSubtargetInfo()); |
| 262 | } |
| 263 | |
| 264 | void SystemZELFAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER( |
| 265 | const MachineInstr &MI, SystemZMCInstLower &Lower) { |
| 266 | const MachineFunction &MF = *(MI.getParent()->getParent()); |
| 267 | const Function &F = MF.getFunction(); |
| 268 | |
| 269 | // If patchable-function-entry is set, emit in-function nops here. |
| 270 | if (F.hasFnAttribute(Kind: "patchable-function-entry" )) { |
| 271 | unsigned Num = F.getFnAttributeAsParsedInteger(Kind: "patchable-function-entry" ); |
| 272 | for (unsigned I = 0; I < Num; ++I) |
| 273 | EmitToStreamer(S&: *OutStreamer, Inst: MF.getSubtarget().getInstrInfo()->getNop()); |
| 274 | return; |
| 275 | } |
| 276 | // Otherwise, emit xray sled. |
| 277 | // .begin: |
| 278 | // j .end # -> stmg %r2, %r15, 16(%r15) |
| 279 | // nop |
| 280 | // llilf %2, FuncID |
| 281 | // brasl %r14, __xray_FunctionEntry@GOT |
| 282 | // .end: |
| 283 | // |
| 284 | // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number |
| 285 | // of instructions change. |
| 286 | bool HasVectorFeature = |
| 287 | TM.getMCSubtargetInfo().hasFeature(Feature: SystemZ::FeatureVector) && |
| 288 | !TM.getMCSubtargetInfo().hasFeature(Feature: SystemZ::FeatureSoftFloat); |
| 289 | MCSymbol *FuncEntry = OutContext.getOrCreateSymbol( |
| 290 | Name: HasVectorFeature ? "__xray_FunctionEntryVec" : "__xray_FunctionEntry" ); |
| 291 | MCSymbol *BeginOfSled = OutContext.createTempSymbol(Name: "xray_sled_" , AlwaysAddSuffix: true); |
| 292 | MCSymbol *EndOfSled = OutContext.createTempSymbol(); |
| 293 | OutStreamer->emitLabel(Symbol: BeginOfSled); |
| 294 | EmitToStreamer(S&: *OutStreamer, |
| 295 | Inst: MCInstBuilder(SystemZ::J) |
| 296 | .addExpr(Val: MCSymbolRefExpr::create(Symbol: EndOfSled, Ctx&: OutContext))); |
| 297 | EmitNop(OutContext, OutStreamer&: *OutStreamer, NumBytes: 2, STI: getSubtargetInfo()); |
| 298 | EmitToStreamer(S&: *OutStreamer, |
| 299 | Inst: MCInstBuilder(SystemZ::LLILF).addReg(Reg: SystemZ::R2D).addImm(Val: 0)); |
| 300 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::BRASL) |
| 301 | .addReg(Reg: SystemZ::R14D) |
| 302 | .addExpr(Val: MCSymbolRefExpr::create( |
| 303 | Symbol: FuncEntry, specifier: SystemZ::S_PLT, Ctx&: OutContext))); |
| 304 | OutStreamer->emitLabel(Symbol: EndOfSled); |
| 305 | recordSled(Sled: BeginOfSled, MI, Kind: SledKind::FUNCTION_ENTER, Version: 2); |
| 306 | } |
| 307 | |
| 308 | void SystemZELFAsmPrinter::LowerPATCHABLE_RET(const MachineInstr &MI, |
| 309 | SystemZMCInstLower &Lower) { |
| 310 | unsigned OpCode = MI.getOperand(i: 0).getImm(); |
| 311 | MCSymbol *FallthroughLabel = nullptr; |
| 312 | if (OpCode == SystemZ::CondReturn) { |
| 313 | FallthroughLabel = OutContext.createTempSymbol(); |
| 314 | int64_t Cond0 = MI.getOperand(i: 1).getImm(); |
| 315 | int64_t Cond1 = MI.getOperand(i: 2).getImm(); |
| 316 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::BRC) |
| 317 | .addImm(Val: Cond0) |
| 318 | .addImm(Val: Cond1 ^ Cond0) |
| 319 | .addExpr(Val: MCSymbolRefExpr::create( |
| 320 | Symbol: FallthroughLabel, Ctx&: OutContext))); |
| 321 | } |
| 322 | // .begin: |
| 323 | // br %r14 # -> stmg %r2, %r15, 24(%r15) |
| 324 | // nop |
| 325 | // nop |
| 326 | // llilf %2,FuncID |
| 327 | // j __xray_FunctionExit@GOT |
| 328 | // |
| 329 | // Update compiler-rt/lib/xray/xray_s390x.cpp accordingly when number |
| 330 | // of instructions change. |
| 331 | bool HasVectorFeature = |
| 332 | TM.getMCSubtargetInfo().hasFeature(Feature: SystemZ::FeatureVector) && |
| 333 | !TM.getMCSubtargetInfo().hasFeature(Feature: SystemZ::FeatureSoftFloat); |
| 334 | MCSymbol *FuncExit = OutContext.getOrCreateSymbol( |
| 335 | Name: HasVectorFeature ? "__xray_FunctionExitVec" : "__xray_FunctionExit" ); |
| 336 | MCSymbol *BeginOfSled = OutContext.createTempSymbol(Name: "xray_sled_" , AlwaysAddSuffix: true); |
| 337 | OutStreamer->emitLabel(Symbol: BeginOfSled); |
| 338 | EmitToStreamer(S&: *OutStreamer, |
| 339 | Inst: MCInstBuilder(SystemZ::BR).addReg(Reg: SystemZ::R14D)); |
| 340 | EmitNop(OutContext, OutStreamer&: *OutStreamer, NumBytes: 4, STI: getSubtargetInfo()); |
| 341 | EmitToStreamer(S&: *OutStreamer, |
| 342 | Inst: MCInstBuilder(SystemZ::LLILF).addReg(Reg: SystemZ::R2D).addImm(Val: 0)); |
| 343 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::J) |
| 344 | .addExpr(Val: MCSymbolRefExpr::create( |
| 345 | Symbol: FuncExit, specifier: SystemZ::S_PLT, Ctx&: OutContext))); |
| 346 | if (FallthroughLabel) |
| 347 | OutStreamer->emitLabel(Symbol: FallthroughLabel); |
| 348 | recordSled(Sled: BeginOfSled, MI, Kind: SledKind::FUNCTION_EXIT, Version: 2); |
| 349 | } |
| 350 | |
| 351 | void SystemZELFAsmPrinter::lowerLOAD_TLS_BLOCK_ADDR(const MachineInstr &MI, |
| 352 | SystemZMCInstLower &Lower) { |
| 353 | Register AddrReg = MI.getOperand(i: 0).getReg(); |
| 354 | const MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo(); |
| 355 | |
| 356 | // EAR can only load the low subregister so use a shift for %a0 to produce |
| 357 | // the GR containing %a0 and %a1. |
| 358 | const Register Reg32 = |
| 359 | MRI.getTargetRegisterInfo()->getSubReg(Reg: AddrReg, Idx: SystemZ::subreg_l32); |
| 360 | |
| 361 | // ear <reg>, %a0 |
| 362 | EmitToStreamer(S&: *OutStreamer, |
| 363 | Inst: MCInstBuilder(SystemZ::EAR).addReg(Reg: Reg32).addReg(Reg: SystemZ::A0)); |
| 364 | |
| 365 | // sllg <reg>, <reg>, 32 |
| 366 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::SLLG) |
| 367 | .addReg(Reg: AddrReg) |
| 368 | .addReg(Reg: AddrReg) |
| 369 | .addReg(Reg: 0) |
| 370 | .addImm(Val: 32)); |
| 371 | |
| 372 | // ear <reg>, %a1 |
| 373 | EmitToStreamer(S&: *OutStreamer, |
| 374 | Inst: MCInstBuilder(SystemZ::EAR).addReg(Reg: Reg32).addReg(Reg: SystemZ::A1)); |
| 375 | } |
| 376 | |
| 377 | void SystemZELFAsmPrinter::lowerLOAD_GLOBAL_STACKGUARD_ADDR( |
| 378 | const MachineInstr &MI, SystemZMCInstLower &Lower) { |
| 379 | Register AddrReg = MI.getOperand(i: 0).getReg(); |
| 380 | const MachineFunction &MF = *(MI.getParent()->getParent()); |
| 381 | const Module *M = MF.getFunction().getParent(); |
| 382 | const TargetLowering *TLI = MF.getSubtarget().getTargetLowering(); |
| 383 | |
| 384 | // Obtain the global value (assert if stack guard variable can't be found). |
| 385 | const GlobalVariable *GV = cast<GlobalVariable>( |
| 386 | Val: TLI->getSDagStackGuard(M: *M, Libcalls: TLI->getLibcallLoweringInfo())); |
| 387 | |
| 388 | // If configured, emit the `__stack_protector_loc` entry |
| 389 | if (M->hasStackProtectorGuardRecord()) { |
| 390 | MCSymbol *Sym = OutContext.createTempSymbol(); |
| 391 | OutStreamer->pushSection(); |
| 392 | OutStreamer->switchSection(Section: OutContext.getELFSection( |
| 393 | Section: "__stack_protector_loc" , Type: ELF::SHT_PROGBITS, Flags: ELF::SHF_ALLOC)); |
| 394 | OutStreamer->emitSymbolValue(Sym, Size: getDataLayout().getPointerSize()); |
| 395 | OutStreamer->popSection(); |
| 396 | OutStreamer->emitLabel(Symbol: Sym); |
| 397 | } |
| 398 | // Emit the address load. |
| 399 | if (M->getPICLevel() == PICLevel::NotPIC) { |
| 400 | EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(SystemZ::LARL) |
| 401 | .addReg(Reg: AddrReg) |
| 402 | .addExpr(Val: MCSymbolRefExpr::create( |
| 403 | Symbol: getSymbol(GV), Ctx&: OutContext))); |
| 404 | } else { |
| 405 | EmitToStreamer(S&: *OutStreamer, |
| 406 | Inst: MCInstBuilder(SystemZ::LGRL) |
| 407 | .addReg(Reg: AddrReg) |
| 408 | .addExpr(Val: MCSymbolRefExpr::create( |
| 409 | Symbol: getSymbol(GV), specifier: SystemZ::S_GOTENT, Ctx&: OutContext))); |
| 410 | } |
| 411 | } |
| 412 | |
| 413 | // The *alignment* of 128-bit vector types is different between the software |
| 414 | // and hardware vector ABIs. If there is an externally visible use of a |
| 415 | // vector type in the module it should be annotated with an attribute. |
| 416 | void SystemZELFAsmPrinter::emitAttributes(Module &M) { |
| 417 | if (M.getModuleFlag(Key: "s390x-visible-vector-ABI" )) { |
| 418 | bool HasVectorFeature = |
| 419 | TM.getMCSubtargetInfo().hasFeature(Feature: SystemZ::FeatureVector); |
| 420 | OutStreamer->emitGNUAttribute(Tag: 8, Value: HasVectorFeature ? 2 : 1); |
| 421 | } |
| 422 | } |
| 423 | |
| 424 | // Convert a SystemZ-specific constant pool modifier into the associated |
| 425 | // specifier. |
| 426 | static uint8_t getSpecifierFromModifier(SystemZCP::SystemZCPModifier Modifier) { |
| 427 | switch (Modifier) { |
| 428 | case SystemZCP::TLSGD: |
| 429 | return SystemZ::S_TLSGD; |
| 430 | case SystemZCP::TLSLDM: |
| 431 | return SystemZ::S_TLSLDM; |
| 432 | case SystemZCP::DTPOFF: |
| 433 | return SystemZ::S_DTPOFF; |
| 434 | case SystemZCP::NTPOFF: |
| 435 | return SystemZ::S_NTPOFF; |
| 436 | } |
| 437 | llvm_unreachable("Invalid SystemCPModifier!" ); |
| 438 | } |
| 439 | |
| 440 | void SystemZELFAsmPrinter::emitMachineConstantPoolValue( |
| 441 | MachineConstantPoolValue *MCPV) { |
| 442 | auto *ZCPV = static_cast<SystemZConstantPoolValue *>(MCPV); |
| 443 | |
| 444 | const MCExpr *Expr = MCSymbolRefExpr::create( |
| 445 | Symbol: getSymbol(GV: ZCPV->getGlobalValue()), |
| 446 | specifier: getSpecifierFromModifier(Modifier: ZCPV->getModifier()), Ctx&: OutContext); |
| 447 | uint64_t Size = getDataLayout().getTypeAllocSize(Ty: ZCPV->getType()); |
| 448 | |
| 449 | OutStreamer->emitValue(Value: Expr, Size); |
| 450 | } |
| 451 | |
| 452 | void SystemZELFAsmPrinter::emitEndOfAsmFile(Module &M) { emitAttributes(M); } |
| 453 | |