2913 lines · cpp
1//===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains a printer that converts from our internal representation10// of machine-dependent LLVM code to GAS-format ARM assembly language.11//12//===----------------------------------------------------------------------===//13 14#include "ARMAsmPrinter.h"15#include "ARM.h"16#include "ARMConstantPoolValue.h"17#include "ARMMachineFunctionInfo.h"18#include "ARMTargetMachine.h"19#include "ARMTargetObjectFile.h"20#include "MCTargetDesc/ARMInstPrinter.h"21#include "MCTargetDesc/ARMMCAsmInfo.h"22#include "TargetInfo/ARMTargetInfo.h"23#include "llvm/ADT/SmallString.h"24#include "llvm/BinaryFormat/COFF.h"25#include "llvm/CodeGen/MachineJumpTableInfo.h"26#include "llvm/CodeGen/MachineModuleInfoImpls.h"27#include "llvm/IR/Constants.h"28#include "llvm/IR/DataLayout.h"29#include "llvm/IR/Mangler.h"30#include "llvm/IR/Module.h"31#include "llvm/IR/Type.h"32#include "llvm/MC/MCAsmInfo.h"33#include "llvm/MC/MCAssembler.h"34#include "llvm/MC/MCContext.h"35#include "llvm/MC/MCELFStreamer.h"36#include "llvm/MC/MCInst.h"37#include "llvm/MC/MCInstBuilder.h"38#include "llvm/MC/MCObjectStreamer.h"39#include "llvm/MC/MCStreamer.h"40#include "llvm/MC/MCSymbol.h"41#include "llvm/MC/TargetRegistry.h"42#include "llvm/Support/ARMBuildAttributes.h"43#include "llvm/Support/Compiler.h"44#include "llvm/Support/Debug.h"45#include "llvm/Support/ErrorHandling.h"46#include "llvm/Support/raw_ostream.h"47#include "llvm/Target/TargetMachine.h"48using namespace llvm;49 50#define DEBUG_TYPE "asm-printer"51 52ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM,53 std::unique_ptr<MCStreamer> Streamer)54 : AsmPrinter(TM, std::move(Streamer), ID), AFI(nullptr), MCP(nullptr),55 InConstantPool(false), OptimizationGoals(-1) {}56 57const ARMBaseTargetMachine &ARMAsmPrinter::getTM() const {58 return static_cast<const ARMBaseTargetMachine &>(TM);59}60 61void ARMAsmPrinter::emitFunctionBodyEnd() {62 // Make sure to terminate any constant pools that were at the end63 // of the function.64 if (!InConstantPool)65 return;66 InConstantPool = false;67 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);68}69 70void ARMAsmPrinter::emitFunctionEntryLabel() {71 auto &TS =72 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());73 if (AFI->isThumbFunction()) {74 TS.emitCode16();75 TS.emitThumbFunc(CurrentFnSym);76 } else {77 TS.emitCode32();78 }79 80 // Emit symbol for CMSE non-secure entry point81 if (AFI->isCmseNSEntryFunction()) {82 MCSymbol *S =83 OutContext.getOrCreateSymbol("__acle_se_" + CurrentFnSym->getName());84 emitLinkage(&MF->getFunction(), S);85 OutStreamer->emitSymbolAttribute(S, MCSA_ELF_TypeFunction);86 OutStreamer->emitLabel(S);87 }88 AsmPrinter::emitFunctionEntryLabel();89}90 91void ARMAsmPrinter::emitXXStructor(const DataLayout &DL, const Constant *CV) {92 uint64_t Size = getDataLayout().getTypeAllocSize(CV->getType());93 assert(Size && "C++ constructor pointer had zero size!");94 95 const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts());96 assert(GV && "C++ constructor pointer was not a GlobalValue!");97 98 const MCExpr *E = MCSymbolRefExpr::create(99 GetARMGVSymbol(GV, ARMII::MO_NO_FLAG),100 (TM.getTargetTriple().isOSBinFormatELF() ? ARM::S_TARGET1 : ARM::S_None),101 OutContext);102 103 OutStreamer->emitValue(E, Size);104}105 106void ARMAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {107 if (PromotedGlobals.count(GV))108 // The global was promoted into a constant pool. It should not be emitted.109 return;110 AsmPrinter::emitGlobalVariable(GV);111}112 113/// runOnMachineFunction - This uses the emitInstruction()114/// method to print assembly for each instruction.115///116bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {117 AFI = MF.getInfo<ARMFunctionInfo>();118 MCP = MF.getConstantPool();119 120 SetupMachineFunction(MF);121 const Function &F = MF.getFunction();122 const TargetMachine& TM = MF.getTarget();123 124 // Collect all globals that had their storage promoted to a constant pool.125 // Functions are emitted before variables, so this accumulates promoted126 // globals from all functions in PromotedGlobals.127 PromotedGlobals.insert_range(AFI->getGlobalsPromotedToConstantPool());128 129 // Calculate this function's optimization goal.130 unsigned OptimizationGoal;131 if (F.hasOptNone())132 // For best debugging illusion, speed and small size sacrificed133 OptimizationGoal = 6;134 else if (F.hasMinSize())135 // Aggressively for small size, speed and debug illusion sacrificed136 OptimizationGoal = 4;137 else if (F.hasOptSize())138 // For small size, but speed and debugging illusion preserved139 OptimizationGoal = 3;140 else if (TM.getOptLevel() == CodeGenOptLevel::Aggressive)141 // Aggressively for speed, small size and debug illusion sacrificed142 OptimizationGoal = 2;143 else if (TM.getOptLevel() > CodeGenOptLevel::None)144 // For speed, but small size and good debug illusion preserved145 OptimizationGoal = 1;146 else // TM.getOptLevel() == CodeGenOptLevel::None147 // For good debugging, but speed and small size preserved148 OptimizationGoal = 5;149 150 // Combine a new optimization goal with existing ones.151 if (OptimizationGoals == -1) // uninitialized goals152 OptimizationGoals = OptimizationGoal;153 else if (OptimizationGoals != (int)OptimizationGoal) // conflicting goals154 OptimizationGoals = 0;155 156 if (TM.getTargetTriple().isOSBinFormatCOFF()) {157 bool Local = F.hasLocalLinkage();158 COFF::SymbolStorageClass Scl =159 Local ? COFF::IMAGE_SYM_CLASS_STATIC : COFF::IMAGE_SYM_CLASS_EXTERNAL;160 int Type = COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT;161 162 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);163 OutStreamer->emitCOFFSymbolStorageClass(Scl);164 OutStreamer->emitCOFFSymbolType(Type);165 OutStreamer->endCOFFSymbolDef();166 }167 168 // Emit the rest of the function body.169 emitFunctionBody();170 171 // Emit the XRay table for this function.172 emitXRayTable();173 174 // If we need V4T thumb mode Register Indirect Jump pads, emit them.175 // These are created per function, rather than per TU, since it's176 // relatively easy to exceed the thumb branch range within a TU.177 if (! ThumbIndirectPads.empty()) {178 auto &TS =179 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());180 TS.emitCode16();181 emitAlignment(Align(2));182 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {183 OutStreamer->emitLabel(TIP.second);184 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX)185 .addReg(TIP.first)186 // Add predicate operands.187 .addImm(ARMCC::AL)188 .addReg(0));189 }190 ThumbIndirectPads.clear();191 }192 193 // We didn't modify anything.194 return false;195}196 197void ARMAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,198 raw_ostream &O) {199 assert(MO.isGlobal() && "caller should check MO.isGlobal");200 unsigned TF = MO.getTargetFlags();201 if (TF & ARMII::MO_LO16)202 O << ":lower16:";203 else if (TF & ARMII::MO_HI16)204 O << ":upper16:";205 else if (TF & ARMII::MO_LO_0_7)206 O << ":lower0_7:";207 else if (TF & ARMII::MO_LO_8_15)208 O << ":lower8_15:";209 else if (TF & ARMII::MO_HI_0_7)210 O << ":upper0_7:";211 else if (TF & ARMII::MO_HI_8_15)212 O << ":upper8_15:";213 214 GetARMGVSymbol(MO.getGlobal(), TF)->print(O, MAI);215 printOffset(MO.getOffset(), O);216}217 218void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,219 raw_ostream &O) {220 const MachineOperand &MO = MI->getOperand(OpNum);221 222 switch (MO.getType()) {223 default: llvm_unreachable("<unknown operand type>");224 case MachineOperand::MO_Register: {225 Register Reg = MO.getReg();226 assert(Reg.isPhysical());227 assert(!MO.getSubReg() && "Subregs should be eliminated!");228 if(ARM::GPRPairRegClass.contains(Reg)) {229 const MachineFunction &MF = *MI->getParent()->getParent();230 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();231 Reg = TRI->getSubReg(Reg, ARM::gsub_0);232 }233 O << ARMInstPrinter::getRegisterName(Reg);234 break;235 }236 case MachineOperand::MO_Immediate: {237 O << '#';238 unsigned TF = MO.getTargetFlags();239 if (TF == ARMII::MO_LO16)240 O << ":lower16:";241 else if (TF == ARMII::MO_HI16)242 O << ":upper16:";243 else if (TF == ARMII::MO_LO_0_7)244 O << ":lower0_7:";245 else if (TF == ARMII::MO_LO_8_15)246 O << ":lower8_15:";247 else if (TF == ARMII::MO_HI_0_7)248 O << ":upper0_7:";249 else if (TF == ARMII::MO_HI_8_15)250 O << ":upper8_15:";251 O << MO.getImm();252 break;253 }254 case MachineOperand::MO_MachineBasicBlock:255 MO.getMBB()->getSymbol()->print(O, MAI);256 return;257 case MachineOperand::MO_GlobalAddress: {258 PrintSymbolOperand(MO, O);259 break;260 }261 case MachineOperand::MO_ConstantPoolIndex:262 assert(!MF->getSubtarget<ARMSubtarget>().genExecuteOnly() &&263 "execute-only should not generate constant pools");264 GetCPISymbol(MO.getIndex())->print(O, MAI);265 break;266 }267}268 269MCSymbol *ARMAsmPrinter::GetCPISymbol(unsigned CPID) const {270 // The AsmPrinter::GetCPISymbol superclass method tries to use CPID as271 // indexes in MachineConstantPool, which isn't in sync with indexes used here.272 const DataLayout &DL = getDataLayout();273 return OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +274 "CPI" + Twine(getFunctionNumber()) + "_" +275 Twine(CPID));276}277 278//===--------------------------------------------------------------------===//279 280MCSymbol *ARMAsmPrinter::281GetARMJTIPICJumpTableLabel(unsigned uid) const {282 const DataLayout &DL = getDataLayout();283 SmallString<60> Name;284 raw_svector_ostream(Name) << DL.getPrivateGlobalPrefix() << "JTI"285 << getFunctionNumber() << '_' << uid;286 return OutContext.getOrCreateSymbol(Name);287}288 289bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,290 const char *ExtraCode, raw_ostream &O) {291 // Does this asm operand have a single letter operand modifier?292 if (ExtraCode && ExtraCode[0]) {293 if (ExtraCode[1] != 0) return true; // Unknown modifier.294 295 switch (ExtraCode[0]) {296 default:297 // See if this is a generic print operand298 return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O);299 case 'P': // Print a VFP double precision register.300 case 'q': // Print a NEON quad precision register.301 printOperand(MI, OpNum, O);302 return false;303 case 'y': // Print a VFP single precision register as indexed double.304 if (MI->getOperand(OpNum).isReg()) {305 MCRegister Reg = MI->getOperand(OpNum).getReg().asMCReg();306 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();307 // Find the 'd' register that has this 's' register as a sub-register,308 // and determine the lane number.309 for (MCPhysReg SR : TRI->superregs(Reg)) {310 if (!ARM::DPRRegClass.contains(SR))311 continue;312 bool Lane0 = TRI->getSubReg(SR, ARM::ssub_0) == Reg;313 O << ARMInstPrinter::getRegisterName(SR) << (Lane0 ? "[0]" : "[1]");314 return false;315 }316 }317 return true;318 case 'B': // Bitwise inverse of integer or symbol without a preceding #.319 if (!MI->getOperand(OpNum).isImm())320 return true;321 O << ~(MI->getOperand(OpNum).getImm());322 return false;323 case 'L': // The low 16 bits of an immediate constant.324 if (!MI->getOperand(OpNum).isImm())325 return true;326 O << (MI->getOperand(OpNum).getImm() & 0xffff);327 return false;328 case 'M': { // A register range suitable for LDM/STM.329 if (!MI->getOperand(OpNum).isReg())330 return true;331 const MachineOperand &MO = MI->getOperand(OpNum);332 Register RegBegin = MO.getReg();333 // This takes advantage of the 2 operand-ness of ldm/stm and that we've334 // already got the operands in registers that are operands to the335 // inline asm statement.336 O << "{";337 if (ARM::GPRPairRegClass.contains(RegBegin)) {338 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();339 Register Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0);340 O << ARMInstPrinter::getRegisterName(Reg0) << ", ";341 RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1);342 }343 O << ARMInstPrinter::getRegisterName(RegBegin);344 345 // FIXME: The register allocator not only may not have given us the346 // registers in sequence, but may not be in ascending registers. This347 // will require changes in the register allocator that'll need to be348 // propagated down here if the operands change.349 unsigned RegOps = OpNum + 1;350 while (MI->getOperand(RegOps).isReg()) {351 O << ", "352 << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg());353 RegOps++;354 }355 356 O << "}";357 358 return false;359 }360 case 'R': // The most significant register of a pair.361 case 'Q': { // The least significant register of a pair.362 if (OpNum == 0)363 return true;364 const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);365 if (!FlagsOP.isImm())366 return true;367 InlineAsm::Flag F(FlagsOP.getImm());368 369 // This operand may not be the one that actually provides the register. If370 // it's tied to a previous one then we should refer instead to that one371 // for registers and their classes.372 unsigned TiedIdx;373 if (F.isUseOperandTiedToDef(TiedIdx)) {374 for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) {375 unsigned OpFlags = MI->getOperand(OpNum).getImm();376 const InlineAsm::Flag F(OpFlags);377 OpNum += F.getNumOperandRegisters() + 1;378 }379 F = InlineAsm::Flag(MI->getOperand(OpNum).getImm());380 381 // Later code expects OpNum to be pointing at the register rather than382 // the flags.383 OpNum += 1;384 }385 386 const unsigned NumVals = F.getNumOperandRegisters();387 unsigned RC;388 bool FirstHalf;389 const ARMBaseTargetMachine &ATM =390 static_cast<const ARMBaseTargetMachine &>(TM);391 392 // 'Q' should correspond to the low order register and 'R' to the high393 // order register. Whether this corresponds to the upper or lower half394 // depends on the endianess mode.395 if (ExtraCode[0] == 'Q')396 FirstHalf = ATM.isLittleEndian();397 else398 // ExtraCode[0] == 'R'.399 FirstHalf = !ATM.isLittleEndian();400 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();401 if (F.hasRegClassConstraint(RC) &&402 ARM::GPRPairRegClass.hasSubClassEq(TRI->getRegClass(RC))) {403 if (NumVals != 1)404 return true;405 const MachineOperand &MO = MI->getOperand(OpNum);406 if (!MO.isReg())407 return true;408 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();409 Register Reg =410 TRI->getSubReg(MO.getReg(), FirstHalf ? ARM::gsub_0 : ARM::gsub_1);411 O << ARMInstPrinter::getRegisterName(Reg);412 return false;413 }414 if (NumVals != 2)415 return true;416 unsigned RegOp = FirstHalf ? OpNum : OpNum + 1;417 if (RegOp >= MI->getNumOperands())418 return true;419 const MachineOperand &MO = MI->getOperand(RegOp);420 if (!MO.isReg())421 return true;422 Register Reg = MO.getReg();423 O << ARMInstPrinter::getRegisterName(Reg);424 return false;425 }426 427 case 'e': // The low doubleword register of a NEON quad register.428 case 'f': { // The high doubleword register of a NEON quad register.429 if (!MI->getOperand(OpNum).isReg())430 return true;431 Register Reg = MI->getOperand(OpNum).getReg();432 if (!ARM::QPRRegClass.contains(Reg))433 return true;434 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();435 Register SubReg =436 TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? ARM::dsub_0 : ARM::dsub_1);437 O << ARMInstPrinter::getRegisterName(SubReg);438 return false;439 }440 441 // This modifier is not yet supported.442 case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.443 return true;444 case 'H': { // The highest-numbered register of a pair.445 const MachineOperand &MO = MI->getOperand(OpNum);446 if (!MO.isReg())447 return true;448 const MachineFunction &MF = *MI->getParent()->getParent();449 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();450 Register Reg = MO.getReg();451 if(!ARM::GPRPairRegClass.contains(Reg))452 return false;453 Reg = TRI->getSubReg(Reg, ARM::gsub_1);454 O << ARMInstPrinter::getRegisterName(Reg);455 return false;456 }457 }458 }459 460 printOperand(MI, OpNum, O);461 return false;462}463 464bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,465 unsigned OpNum, const char *ExtraCode,466 raw_ostream &O) {467 // Does this asm operand have a single letter operand modifier?468 if (ExtraCode && ExtraCode[0]) {469 if (ExtraCode[1] != 0) return true; // Unknown modifier.470 471 switch (ExtraCode[0]) {472 case 'A': // A memory operand for a VLD1/VST1 instruction.473 default: return true; // Unknown modifier.474 case 'm': // The base register of a memory operand.475 if (!MI->getOperand(OpNum).isReg())476 return true;477 O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg());478 return false;479 }480 }481 482 const MachineOperand &MO = MI->getOperand(OpNum);483 assert(MO.isReg() && "unexpected inline asm memory operand");484 O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";485 return false;486}487 488static bool isThumb(const MCSubtargetInfo& STI) {489 return STI.hasFeature(ARM::ModeThumb);490}491 492void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,493 const MCSubtargetInfo *EndInfo) const {494 // If either end mode is unknown (EndInfo == NULL) or different than495 // the start mode, then restore the start mode.496 const bool WasThumb = isThumb(StartInfo);497 if (!EndInfo || WasThumb != isThumb(*EndInfo)) {498 auto &TS =499 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());500 if (WasThumb)501 TS.emitCode16();502 else503 TS.emitCode32();504 }505}506 507void ARMAsmPrinter::emitStartOfAsmFile(Module &M) {508 const Triple &TT = TM.getTargetTriple();509 auto &TS =510 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());511 // Use unified assembler syntax.512 TS.emitSyntaxUnified();513 514 // Emit ARM Build Attributes515 if (TT.isOSBinFormatELF())516 emitAttributes();517 518 // Use the triple's architecture and subarchitecture to determine519 // if we're thumb for the purposes of the top level code16 state.520 if (!M.getModuleInlineAsm().empty() && TT.isThumb())521 TS.emitCode16();522}523 524static void525emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,526 MachineModuleInfoImpl::StubValueTy &MCSym) {527 // L_foo$stub:528 OutStreamer.emitLabel(StubLabel);529 // .indirect_symbol _foo530 OutStreamer.emitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);531 532 if (MCSym.getInt())533 // External to current translation unit.534 OutStreamer.emitIntValue(0, 4/*size*/);535 else536 // Internal to current translation unit.537 //538 // When we place the LSDA into the TEXT section, the type info539 // pointers need to be indirect and pc-rel. We accomplish this by540 // using NLPs; however, sometimes the types are local to the file.541 // We need to fill in the value for the NLP in those cases.542 OutStreamer.emitValue(543 MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()),544 4 /*size*/);545}546 547 548void ARMAsmPrinter::emitEndOfAsmFile(Module &M) {549 const Triple &TT = TM.getTargetTriple();550 if (TT.isOSBinFormatMachO()) {551 // All darwin targets use mach-o.552 const TargetLoweringObjectFileMachO &TLOFMacho =553 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());554 MachineModuleInfoMachO &MMIMacho =555 MMI->getObjFileInfo<MachineModuleInfoMachO>();556 557 // Output non-lazy-pointers for external and common global variables.558 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();559 560 if (!Stubs.empty()) {561 // Switch with ".non_lazy_symbol_pointer" directive.562 OutStreamer->switchSection(TLOFMacho.getNonLazySymbolPointerSection());563 emitAlignment(Align(4));564 565 for (auto &Stub : Stubs)566 emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second);567 568 Stubs.clear();569 OutStreamer->addBlankLine();570 }571 572 Stubs = MMIMacho.GetThreadLocalGVStubList();573 if (!Stubs.empty()) {574 // Switch with ".non_lazy_symbol_pointer" directive.575 OutStreamer->switchSection(TLOFMacho.getThreadLocalPointerSection());576 emitAlignment(Align(4));577 578 for (auto &Stub : Stubs)579 emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second);580 581 Stubs.clear();582 OutStreamer->addBlankLine();583 }584 585 // Funny Darwin hack: This flag tells the linker that no global symbols586 // contain code that falls through to other global symbols (e.g. the obvious587 // implementation of multiple entry points). If this doesn't occur, the588 // linker can safely perform dead code stripping. Since LLVM never589 // generates code that does this, it is always safe to set.590 OutStreamer->emitSubsectionsViaSymbols();591 }592 593 // The last attribute to be emitted is ABI_optimization_goals594 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();595 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);596 597 if (OptimizationGoals > 0 &&598 (TT.isTargetAEABI() || TT.isTargetGNUAEABI() || TT.isTargetMuslAEABI()))599 ATS.emitAttribute(ARMBuildAttrs::ABI_optimization_goals, OptimizationGoals);600 OptimizationGoals = -1;601 602 ATS.finishAttributeSection();603}604 605//===----------------------------------------------------------------------===//606// Helper routines for emitStartOfAsmFile() and emitEndOfAsmFile()607// FIXME:608// The following seem like one-off assembler flags, but they actually need609// to appear in the .ARM.attributes section in ELF.610// Instead of subclassing the MCELFStreamer, we do the work here.611 612// Returns true if all function definitions have the same function attribute613// value. It also returns true when the module has no functions.614static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr,615 StringRef Value) {616 return !any_of(M, [&](const Function &F) {617 if (F.isDeclaration())618 return false;619 return F.getFnAttribute(Attr).getValueAsString() != Value;620 });621}622// Returns true if all functions definitions have the same denormal mode.623// It also returns true when the module has no functions.624static bool checkDenormalAttributeConsistency(const Module &M, StringRef Attr,625 DenormalMode Value) {626 return !any_of(M, [&](const Function &F) {627 if (F.isDeclaration())628 return false;629 StringRef AttrVal = F.getFnAttribute(Attr).getValueAsString();630 return parseDenormalFPAttribute(AttrVal) != Value;631 });632}633 634// Returns true if all functions have different denormal modes.635static bool checkDenormalAttributeInconsistency(const Module &M) {636 auto F = M.functions().begin();637 auto E = M.functions().end();638 if (F == E)639 return false;640 DenormalMode Value = F->getDenormalModeRaw();641 ++F;642 return std::any_of(F, E, [&](const Function &F) {643 return !F.isDeclaration() && F.getDenormalModeRaw() != Value;644 });645}646 647void ARMAsmPrinter::emitAttributes() {648 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();649 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);650 651 ATS.emitTextAttribute(ARMBuildAttrs::conformance, "2.09");652 653 ATS.switchVendor("aeabi");654 655 // Compute ARM ELF Attributes based on the default subtarget that656 // we'd have constructed. The existing ARM behavior isn't LTO clean657 // anyhow.658 // FIXME: For ifunc related functions we could iterate over and look659 // for a feature string that doesn't match the default one.660 const Triple &TT = TM.getTargetTriple();661 StringRef CPU = TM.getTargetCPU();662 StringRef FS = TM.getTargetFeatureString();663 std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);664 if (!FS.empty()) {665 if (!ArchFS.empty())666 ArchFS = (Twine(ArchFS) + "," + FS).str();667 else668 ArchFS = std::string(FS);669 }670 const ARMBaseTargetMachine &ATM =671 static_cast<const ARMBaseTargetMachine &>(TM);672 const ARMSubtarget STI(TT, std::string(CPU), ArchFS, ATM,673 ATM.isLittleEndian());674 675 // Emit build attributes for the available hardware.676 ATS.emitTargetAttributes(STI);677 678 // RW data addressing.679 if (isPositionIndependent()) {680 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data,681 ARMBuildAttrs::AddressRWPCRel);682 } else if (STI.isRWPI()) {683 // RWPI specific attributes.684 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data,685 ARMBuildAttrs::AddressRWSBRel);686 }687 688 // RO data addressing.689 if (isPositionIndependent() || STI.isROPI()) {690 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RO_data,691 ARMBuildAttrs::AddressROPCRel);692 }693 694 // GOT use.695 if (isPositionIndependent()) {696 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use,697 ARMBuildAttrs::AddressGOT);698 } else {699 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use,700 ARMBuildAttrs::AddressDirect);701 }702 703 // Set FP Denormals.704 if (checkDenormalAttributeConsistency(*MMI->getModule(), "denormal-fp-math",705 DenormalMode::getPreserveSign()))706 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,707 ARMBuildAttrs::PreserveFPSign);708 else if (checkDenormalAttributeConsistency(*MMI->getModule(),709 "denormal-fp-math",710 DenormalMode::getPositiveZero()))711 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,712 ARMBuildAttrs::PositiveZero);713 else if (checkDenormalAttributeInconsistency(*MMI->getModule()) ||714 checkDenormalAttributeConsistency(715 *MMI->getModule(), "denormal-fp-math", DenormalMode::getIEEE()))716 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,717 ARMBuildAttrs::IEEEDenormals);718 else {719 if (!STI.hasVFP2Base()) {720 // When the target doesn't have an FPU (by design or721 // intention), the assumptions made on the software support722 // mirror that of the equivalent hardware support *if it723 // existed*. For v7 and better we indicate that denormals are724 // flushed preserving sign, and for V6 we indicate that725 // denormals are flushed to positive zero.726 if (STI.hasV7Ops())727 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,728 ARMBuildAttrs::PreserveFPSign);729 } else if (STI.hasVFP3Base()) {730 // In VFPv4, VFPv4U, VFPv3, or VFPv3U, it is preserved. That is,731 // the sign bit of the zero matches the sign bit of the input or732 // result that is being flushed to zero.733 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,734 ARMBuildAttrs::PreserveFPSign);735 }736 // For VFPv2 implementations it is implementation defined as737 // to whether denormals are flushed to positive zero or to738 // whatever the sign of zero is (ARM v7AR ARM 2.7.5). Historically739 // LLVM has chosen to flush this to positive zero (most likely for740 // GCC compatibility), so that's the chosen value here (the741 // absence of its emission implies zero).742 }743 744 // Set FP exceptions and rounding745 if (checkFunctionsAttributeConsistency(*MMI->getModule(),746 "no-trapping-math", "true") ||747 TM.Options.NoTrappingFPMath)748 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions,749 ARMBuildAttrs::Not_Allowed);750 else {751 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, ARMBuildAttrs::Allowed);752 753 // If the user has permitted this code to choose the IEEE 754754 // rounding at run-time, emit the rounding attribute.755 if (TM.Options.HonorSignDependentRoundingFPMathOption)756 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_rounding, ARMBuildAttrs::Allowed);757 }758 759 // TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath is the760 // equivalent of GCC's -ffinite-math-only flag.761 if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath)762 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,763 ARMBuildAttrs::Allowed);764 else765 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,766 ARMBuildAttrs::AllowIEEE754);767 768 // FIXME: add more flags to ARMBuildAttributes.h769 // 8-bytes alignment stuff.770 ATS.emitAttribute(ARMBuildAttrs::ABI_align_needed, 1);771 ATS.emitAttribute(ARMBuildAttrs::ABI_align_preserved, 1);772 773 // Hard float. Use both S and D registers and conform to AAPCS-VFP.774 if (getTM().isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)775 ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS);776 777 // FIXME: To support emitting this build attribute as GCC does, the778 // -mfp16-format option and associated plumbing must be779 // supported. For now the __fp16 type is exposed by default, so this780 // attribute should be emitted with value 1.781 ATS.emitAttribute(ARMBuildAttrs::ABI_FP_16bit_format,782 ARMBuildAttrs::FP16FormatIEEE);783 784 if (const Module *SourceModule = MMI->getModule()) {785 // ABI_PCS_wchar_t to indicate wchar_t width786 // FIXME: There is no way to emit value 0 (wchar_t prohibited).787 if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>(788 SourceModule->getModuleFlag("wchar_size"))) {789 int WCharWidth = WCharWidthValue->getZExtValue();790 assert((WCharWidth == 2 || WCharWidth == 4) &&791 "wchar_t width must be 2 or 4 bytes");792 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_wchar_t, WCharWidth);793 }794 795 // ABI_enum_size to indicate enum width796 // FIXME: There is no way to emit value 0 (enums prohibited) or value 3797 // (all enums contain a value needing 32 bits to encode).798 if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>(799 SourceModule->getModuleFlag("min_enum_size"))) {800 int EnumWidth = EnumWidthValue->getZExtValue();801 assert((EnumWidth == 1 || EnumWidth == 4) &&802 "Minimum enum width must be 1 or 4 bytes");803 int EnumBuildAttr = EnumWidth == 1 ? 1 : 2;804 ATS.emitAttribute(ARMBuildAttrs::ABI_enum_size, EnumBuildAttr);805 }806 807 auto *PACValue = mdconst::extract_or_null<ConstantInt>(808 SourceModule->getModuleFlag("sign-return-address"));809 if (PACValue && PACValue->isOne()) {810 // If "+pacbti" is used as an architecture extension,811 // Tag_PAC_extension is emitted in812 // ARMTargetStreamer::emitTargetAttributes().813 if (!STI.hasPACBTI()) {814 ATS.emitAttribute(ARMBuildAttrs::PAC_extension,815 ARMBuildAttrs::AllowPACInNOPSpace);816 }817 ATS.emitAttribute(ARMBuildAttrs::PACRET_use, ARMBuildAttrs::PACRETUsed);818 }819 820 auto *BTIValue = mdconst::extract_or_null<ConstantInt>(821 SourceModule->getModuleFlag("branch-target-enforcement"));822 if (BTIValue && !BTIValue->isZero()) {823 // If "+pacbti" is used as an architecture extension,824 // Tag_BTI_extension is emitted in825 // ARMTargetStreamer::emitTargetAttributes().826 if (!STI.hasPACBTI()) {827 ATS.emitAttribute(ARMBuildAttrs::BTI_extension,828 ARMBuildAttrs::AllowBTIInNOPSpace);829 }830 ATS.emitAttribute(ARMBuildAttrs::BTI_use, ARMBuildAttrs::BTIUsed);831 }832 }833 834 // We currently do not support using R9 as the TLS pointer.835 if (STI.isRWPI())836 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,837 ARMBuildAttrs::R9IsSB);838 else if (STI.isR9Reserved())839 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,840 ARMBuildAttrs::R9Reserved);841 else842 ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,843 ARMBuildAttrs::R9IsGPR);844}845 846//===----------------------------------------------------------------------===//847 848static MCSymbol *getBFLabel(StringRef Prefix, unsigned FunctionNumber,849 unsigned LabelId, MCContext &Ctx) {850 851 MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)852 + "BF" + Twine(FunctionNumber) + "_" + Twine(LabelId));853 return Label;854}855 856static MCSymbol *getPICLabel(StringRef Prefix, unsigned FunctionNumber,857 unsigned LabelId, MCContext &Ctx) {858 859 MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)860 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));861 return Label;862}863 864static uint8_t getModifierSpecifier(ARMCP::ARMCPModifier Modifier) {865 switch (Modifier) {866 case ARMCP::no_modifier:867 return ARM::S_None;868 case ARMCP::TLSGD:869 return ARM::S_TLSGD;870 case ARMCP::TPOFF:871 return ARM::S_TPOFF;872 case ARMCP::GOTTPOFF:873 return ARM::S_GOTTPOFF;874 case ARMCP::SBREL:875 return ARM::S_SBREL;876 case ARMCP::GOT_PREL:877 return ARM::S_GOT_PREL;878 case ARMCP::SECREL:879 return ARM::S_COFF_SECREL;880 }881 llvm_unreachable("Invalid ARMCPModifier!");882}883 884MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,885 unsigned char TargetFlags) {886 const Triple &TT = TM.getTargetTriple();887 if (TT.isOSBinFormatMachO()) {888 bool IsIndirect =889 (TargetFlags & ARMII::MO_NONLAZY) && getTM().isGVIndirectSymbol(GV);890 891 if (!IsIndirect)892 return getSymbol(GV);893 894 // FIXME: Remove this when Darwin transition to @GOT like syntax.895 MCSymbol *MCSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");896 MachineModuleInfoMachO &MMIMachO =897 MMI->getObjFileInfo<MachineModuleInfoMachO>();898 MachineModuleInfoImpl::StubValueTy &StubSym =899 GV->isThreadLocal() ? MMIMachO.getThreadLocalGVStubEntry(MCSym)900 : MMIMachO.getGVStubEntry(MCSym);901 902 if (!StubSym.getPointer())903 StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV),904 !GV->hasInternalLinkage());905 return MCSym;906 } else if (TT.isOSBinFormatCOFF()) {907 assert(TT.isOSWindows() && "Windows is the only supported COFF target");908 909 bool IsIndirect =910 (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB));911 if (!IsIndirect)912 return getSymbol(GV);913 914 SmallString<128> Name;915 if (TargetFlags & ARMII::MO_DLLIMPORT)916 Name = "__imp_";917 else if (TargetFlags & ARMII::MO_COFFSTUB)918 Name = ".refptr.";919 getNameWithPrefix(Name, GV);920 921 MCSymbol *MCSym = OutContext.getOrCreateSymbol(Name);922 923 if (TargetFlags & ARMII::MO_COFFSTUB) {924 MachineModuleInfoCOFF &MMICOFF =925 MMI->getObjFileInfo<MachineModuleInfoCOFF>();926 MachineModuleInfoImpl::StubValueTy &StubSym =927 MMICOFF.getGVStubEntry(MCSym);928 929 if (!StubSym.getPointer())930 StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), true);931 }932 933 return MCSym;934 } else if (TT.isOSBinFormatELF()) {935 return getSymbolPreferLocal(*GV);936 }937 llvm_unreachable("unexpected target");938}939 940void ARMAsmPrinter::emitMachineConstantPoolValue(941 MachineConstantPoolValue *MCPV) {942 const DataLayout &DL = getDataLayout();943 int Size = DL.getTypeAllocSize(MCPV->getType());944 945 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);946 947 if (ACPV->isPromotedGlobal()) {948 // This constant pool entry is actually a global whose storage has been949 // promoted into the constant pool. This global may be referenced still950 // by debug information, and due to the way AsmPrinter is set up, the debug951 // info is immutable by the time we decide to promote globals to constant952 // pools. Because of this, we need to ensure we emit a symbol for the global953 // with private linkage (the default) so debug info can refer to it.954 //955 // However, if this global is promoted into several functions we must ensure956 // we don't try and emit duplicate symbols!957 auto *ACPC = cast<ARMConstantPoolConstant>(ACPV);958 for (const auto *GV : ACPC->promotedGlobals()) {959 if (!EmittedPromotedGlobalLabels.count(GV)) {960 MCSymbol *GVSym = getSymbol(GV);961 OutStreamer->emitLabel(GVSym);962 EmittedPromotedGlobalLabels.insert(GV);963 }964 }965 return emitGlobalConstant(DL, ACPC->getPromotedGlobalInit());966 }967 968 MCSymbol *MCSym;969 if (ACPV->isLSDA()) {970 MCSym = getMBBExceptionSym(MF->front());971 } else if (ACPV->isBlockAddress()) {972 const BlockAddress *BA =973 cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress();974 MCSym = GetBlockAddressSymbol(BA);975 } else if (ACPV->isGlobalValue()) {976 const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();977 978 // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so979 // flag the global as MO_NONLAZY.980 unsigned char TF =981 TM.getTargetTriple().isOSBinFormatMachO() ? ARMII::MO_NONLAZY : 0;982 MCSym = GetARMGVSymbol(GV, TF);983 } else if (ACPV->isMachineBasicBlock()) {984 const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();985 MCSym = MBB->getSymbol();986 } else {987 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");988 auto Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();989 MCSym = GetExternalSymbolSymbol(Sym);990 }991 992 // Create an MCSymbol for the reference.993 const MCExpr *Expr = MCSymbolRefExpr::create(994 MCSym, getModifierSpecifier(ACPV->getModifier()), OutContext);995 996 if (ACPV->getPCAdjustment()) {997 MCSymbol *PCLabel =998 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),999 ACPV->getLabelId(), OutContext);1000 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);1001 PCRelExpr =1002 MCBinaryExpr::createAdd(PCRelExpr,1003 MCConstantExpr::create(ACPV->getPCAdjustment(),1004 OutContext),1005 OutContext);1006 if (ACPV->mustAddCurrentAddress()) {1007 // We want "(<expr> - .)", but MC doesn't have a concept of the '.'1008 // label, so just emit a local label end reference that instead.1009 MCSymbol *DotSym = OutContext.createTempSymbol();1010 OutStreamer->emitLabel(DotSym);1011 const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);1012 PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext);1013 }1014 Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext);1015 }1016 OutStreamer->emitValue(Expr, Size);1017}1018 1019void ARMAsmPrinter::emitJumpTableAddrs(const MachineInstr *MI) {1020 const MachineOperand &MO1 = MI->getOperand(1);1021 unsigned JTI = MO1.getIndex();1022 1023 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for1024 // ARM mode tables.1025 emitAlignment(Align(4));1026 1027 // Emit a label for the jump table.1028 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);1029 OutStreamer->emitLabel(JTISymbol);1030 1031 // Mark the jump table as data-in-code.1032 OutStreamer->emitDataRegion(MCDR_DataRegionJT32);1033 1034 // Emit each entry of the table.1035 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();1036 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();1037 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;1038 1039 for (MachineBasicBlock *MBB : JTBBs) {1040 // Construct an MCExpr for the entry. We want a value of the form:1041 // (BasicBlockAddr - TableBeginAddr)1042 //1043 // For example, a table with entries jumping to basic blocks BB0 and BB11044 // would look like:1045 // LJTI_0_0:1046 // .word (LBB0 - LJTI_0_0)1047 // .word (LBB1 - LJTI_0_0)1048 const MCExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);1049 1050 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();1051 if (isPositionIndependent() || STI.isROPI())1052 Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol,1053 OutContext),1054 OutContext);1055 // If we're generating a table of Thumb addresses in static relocation1056 // model, we need to add one to keep interworking correctly.1057 else if (AFI->isThumbFunction())1058 Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(1,OutContext),1059 OutContext);1060 OutStreamer->emitValue(Expr, 4);1061 }1062 // Mark the end of jump table data-in-code region.1063 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);1064}1065 1066void ARMAsmPrinter::emitJumpTableInsts(const MachineInstr *MI) {1067 const MachineOperand &MO1 = MI->getOperand(1);1068 unsigned JTI = MO1.getIndex();1069 1070 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for1071 // ARM mode tables.1072 emitAlignment(Align(4));1073 1074 // Emit a label for the jump table.1075 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);1076 OutStreamer->emitLabel(JTISymbol);1077 1078 // Emit each entry of the table.1079 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();1080 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();1081 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;1082 1083 for (MachineBasicBlock *MBB : JTBBs) {1084 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),1085 OutContext);1086 // If this isn't a TBB or TBH, the entries are direct branch instructions.1087 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2B)1088 .addExpr(MBBSymbolExpr)1089 .addImm(ARMCC::AL)1090 .addReg(0));1091 }1092}1093 1094void ARMAsmPrinter::emitJumpTableTBInst(const MachineInstr *MI,1095 unsigned OffsetWidth) {1096 assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width");1097 const MachineOperand &MO1 = MI->getOperand(1);1098 unsigned JTI = MO1.getIndex();1099 1100 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();1101 if (STI.isThumb1Only())1102 emitAlignment(Align(4));1103 1104 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);1105 OutStreamer->emitLabel(JTISymbol);1106 1107 // Emit each entry of the table.1108 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();1109 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();1110 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;1111 1112 // Mark the jump table as data-in-code.1113 OutStreamer->emitDataRegion(OffsetWidth == 1 ? MCDR_DataRegionJT81114 : MCDR_DataRegionJT16);1115 1116 for (auto *MBB : JTBBs) {1117 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),1118 OutContext);1119 // Otherwise it's an offset from the dispatch instruction. Construct an1120 // MCExpr for the entry. We want a value of the form:1121 // (BasicBlockAddr - TBBInstAddr + 4) / 21122 //1123 // For example, a TBB table with entries jumping to basic blocks BB0 and BB11124 // would look like:1125 // LJTI_0_0:1126 // .byte (LBB0 - (LCPI0_0 + 4)) / 21127 // .byte (LBB1 - (LCPI0_0 + 4)) / 21128 // where LCPI0_0 is a label defined just before the TBB instruction using1129 // this table.1130 MCSymbol *TBInstPC = GetCPISymbol(MI->getOperand(0).getImm());1131 const MCExpr *Expr = MCBinaryExpr::createAdd(1132 MCSymbolRefExpr::create(TBInstPC, OutContext),1133 MCConstantExpr::create(4, OutContext), OutContext);1134 Expr = MCBinaryExpr::createSub(MBBSymbolExpr, Expr, OutContext);1135 Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(2, OutContext),1136 OutContext);1137 OutStreamer->emitValue(Expr, OffsetWidth);1138 }1139 // Mark the end of jump table data-in-code region. 32-bit offsets use1140 // actual branch instructions here, so we don't mark those as a data-region1141 // at all.1142 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);1143 1144 // Make sure the next instruction is 2-byte aligned.1145 emitAlignment(Align(2));1146}1147 1148std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,1149 codeview::JumpTableEntrySize>1150ARMAsmPrinter::getCodeViewJumpTableInfo(int JTI,1151 const MachineInstr *BranchInstr,1152 const MCSymbol *BranchLabel) const {1153 codeview::JumpTableEntrySize EntrySize;1154 const MCSymbol *BaseLabel;1155 uint64_t BaseOffset = 0;1156 switch (BranchInstr->getOpcode()) {1157 case ARM::BR_JTadd:1158 case ARM::BR_JTr:1159 case ARM::tBR_JTr:1160 // Word relative to the jump table address.1161 EntrySize = codeview::JumpTableEntrySize::UInt32;1162 BaseLabel = GetARMJTIPICJumpTableLabel(JTI);1163 break;1164 case ARM::tTBH_JT:1165 case ARM::t2TBH_JT:1166 // half-word shifted left, relative to *after* the branch instruction.1167 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;1168 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());1169 BaseLabel = BranchLabel;1170 BaseOffset = 4;1171 break;1172 case ARM::tTBB_JT:1173 case ARM::t2TBB_JT:1174 // byte shifted left, relative to *after* the branch instruction.1175 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;1176 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());1177 BaseLabel = BranchLabel;1178 BaseOffset = 4;1179 break;1180 case ARM::t2BR_JT:1181 // Direct jump.1182 BaseLabel = nullptr;1183 EntrySize = codeview::JumpTableEntrySize::Pointer;1184 break;1185 default:1186 llvm_unreachable("Unknown jump table instruction");1187 }1188 1189 return std::make_tuple(BaseLabel, BaseOffset, BranchLabel, EntrySize);1190}1191 1192void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {1193 assert(MI->getFlag(MachineInstr::FrameSetup) &&1194 "Only instruction which are involved into frame setup code are allowed");1195 1196 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();1197 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);1198 const MachineFunction &MF = *MI->getParent()->getParent();1199 const TargetRegisterInfo *TargetRegInfo =1200 MF.getSubtarget().getRegisterInfo();1201 const MachineRegisterInfo &MachineRegInfo = MF.getRegInfo();1202 1203 Register FramePtr = TargetRegInfo->getFrameRegister(MF);1204 unsigned Opc = MI->getOpcode();1205 unsigned SrcReg, DstReg;1206 1207 switch (Opc) {1208 case ARM::tPUSH:1209 // special case: tPUSH does not have src/dst regs.1210 SrcReg = DstReg = ARM::SP;1211 break;1212 case ARM::tLDRpci:1213 case ARM::t2MOVi16:1214 case ARM::t2MOVTi16:1215 case ARM::tMOVi8:1216 case ARM::tADDi8:1217 case ARM::tLSLri:1218 // special cases:1219 // 1) for Thumb1 code we sometimes materialize the constant via constpool1220 // load.1221 // 2) for Thumb1 execute only code we materialize the constant via the1222 // following pattern:1223 // movs r3, #:upper8_15:<const>1224 // lsls r3, #81225 // adds r3, #:upper0_7:<const>1226 // lsls r3, #81227 // adds r3, #:lower8_15:<const>1228 // lsls r3, #81229 // adds r3, #:lower0_7:<const>1230 // So we need to special-case MOVS, ADDS and LSLS, and keep track of1231 // where we are in the sequence with the simplest of state machines.1232 // 3) for Thumb2 execute only code we materialize the constant via1233 // immediate constants in 2 separate instructions (MOVW/MOVT).1234 SrcReg = ~0U;1235 DstReg = MI->getOperand(0).getReg();1236 break;1237 case ARM::VMRS:1238 SrcReg = ARM::FPSCR;1239 DstReg = MI->getOperand(0).getReg();1240 break;1241 case ARM::VMRS_FPEXC:1242 SrcReg = ARM::FPEXC;1243 DstReg = MI->getOperand(0).getReg();1244 break;1245 default:1246 SrcReg = MI->getOperand(1).getReg();1247 DstReg = MI->getOperand(0).getReg();1248 break;1249 }1250 1251 // Try to figure out the unwinding opcode out of src / dst regs.1252 if (MI->mayStore()) {1253 // Register saves.1254 assert(DstReg == ARM::SP &&1255 "Only stack pointer as a destination reg is supported");1256 1257 SmallVector<MCRegister, 4> RegList;1258 // Skip src & dst reg, and pred ops.1259 unsigned StartOp = 2 + 2;1260 // Use all the operands.1261 unsigned NumOffset = 0;1262 // Amount of SP adjustment folded into a push, before the1263 // registers are stored (pad at higher addresses).1264 unsigned PadBefore = 0;1265 // Amount of SP adjustment folded into a push, after the1266 // registers are stored (pad at lower addresses).1267 unsigned PadAfter = 0;1268 1269 switch (Opc) {1270 default:1271 MI->print(errs());1272 llvm_unreachable("Unsupported opcode for unwinding information");1273 case ARM::tPUSH:1274 // Special case here: no src & dst reg, but two extra imp ops.1275 StartOp = 2; NumOffset = 2;1276 [[fallthrough]];1277 case ARM::STMDB_UPD:1278 case ARM::t2STMDB_UPD:1279 case ARM::VSTMDDB_UPD:1280 assert(SrcReg == ARM::SP &&1281 "Only stack pointer as a source reg is supported");1282 for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset;1283 i != NumOps; ++i) {1284 const MachineOperand &MO = MI->getOperand(i);1285 // Actually, there should never be any impdef stuff here. Skip it1286 // temporary to workaround PR11902.1287 if (MO.isImplicit())1288 continue;1289 // Registers, pushed as a part of folding an SP update into the1290 // push instruction are marked as undef and should not be1291 // restored when unwinding, because the function can modify the1292 // corresponding stack slots.1293 if (MO.isUndef()) {1294 assert(RegList.empty() &&1295 "Pad registers must come before restored ones");1296 unsigned Width =1297 TargetRegInfo->getRegSizeInBits(MO.getReg(), MachineRegInfo) / 8;1298 PadAfter += Width;1299 continue;1300 }1301 // Check for registers that are remapped (for a Thumb1 prologue that1302 // saves high registers).1303 Register Reg = MO.getReg();1304 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Reg))1305 Reg = RemappedReg;1306 RegList.push_back(Reg);1307 }1308 break;1309 case ARM::STR_PRE_IMM:1310 case ARM::STR_PRE_REG:1311 case ARM::t2STR_PRE:1312 assert(MI->getOperand(2).getReg() == ARM::SP &&1313 "Only stack pointer as a source reg is supported");1314 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))1315 SrcReg = RemappedReg;1316 1317 RegList.push_back(SrcReg);1318 break;1319 case ARM::t2STRD_PRE:1320 assert(MI->getOperand(3).getReg() == ARM::SP &&1321 "Only stack pointer as a source reg is supported");1322 SrcReg = MI->getOperand(1).getReg();1323 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))1324 SrcReg = RemappedReg;1325 RegList.push_back(SrcReg);1326 SrcReg = MI->getOperand(2).getReg();1327 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))1328 SrcReg = RemappedReg;1329 RegList.push_back(SrcReg);1330 PadBefore = -MI->getOperand(4).getImm() - 8;1331 break;1332 }1333 if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {1334 if (PadBefore)1335 ATS.emitPad(PadBefore);1336 ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);1337 // Account for the SP adjustment, folded into the push.1338 if (PadAfter)1339 ATS.emitPad(PadAfter);1340 }1341 } else {1342 // Changes of stack / frame pointer.1343 if (SrcReg == ARM::SP) {1344 int64_t Offset = 0;1345 switch (Opc) {1346 default:1347 MI->print(errs());1348 llvm_unreachable("Unsupported opcode for unwinding information");1349 case ARM::tLDRspi:1350 // Used to restore LR in a prologue which uses it as a temporary, has1351 // no effect on unwind tables.1352 return;1353 case ARM::MOVr:1354 case ARM::tMOVr:1355 Offset = 0;1356 break;1357 case ARM::ADDri:1358 case ARM::t2ADDri:1359 case ARM::t2ADDri12:1360 case ARM::t2ADDspImm:1361 case ARM::t2ADDspImm12:1362 Offset = -MI->getOperand(2).getImm();1363 break;1364 case ARM::SUBri:1365 case ARM::t2SUBri:1366 case ARM::t2SUBri12:1367 case ARM::t2SUBspImm:1368 case ARM::t2SUBspImm12:1369 Offset = MI->getOperand(2).getImm();1370 break;1371 case ARM::tSUBspi:1372 Offset = MI->getOperand(2).getImm()*4;1373 break;1374 case ARM::tADDspi:1375 case ARM::tADDrSPi:1376 Offset = -MI->getOperand(2).getImm()*4;1377 break;1378 case ARM::tADDhirr:1379 Offset =1380 -AFI->EHPrologueOffsetInRegs.lookup(MI->getOperand(2).getReg());1381 break;1382 }1383 1384 if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {1385 if (DstReg == FramePtr && FramePtr != ARM::SP)1386 // Set-up of the frame pointer. Positive values correspond to "add"1387 // instruction.1388 ATS.emitSetFP(FramePtr, ARM::SP, -Offset);1389 else if (DstReg == ARM::SP) {1390 // Change of SP by an offset. Positive values correspond to "sub"1391 // instruction.1392 ATS.emitPad(Offset);1393 } else {1394 // Move of SP to a register. Positive values correspond to an "add"1395 // instruction.1396 ATS.emitMovSP(DstReg, -Offset);1397 }1398 }1399 } else if (DstReg == ARM::SP) {1400 MI->print(errs());1401 llvm_unreachable("Unsupported opcode for unwinding information");1402 } else {1403 int64_t Offset = 0;1404 switch (Opc) {1405 case ARM::tMOVr:1406 // If a Thumb1 function spills r8-r11, we copy the values to low1407 // registers before pushing them. Record the copy so we can emit the1408 // correct ".save" later.1409 AFI->EHPrologueRemappedRegs[DstReg] = SrcReg;1410 break;1411 case ARM::VMRS:1412 case ARM::VMRS_FPEXC:1413 // If a function spills FPSCR or FPEXC, we copy the values to low1414 // registers before pushing them. However, we can't issue annotations1415 // for FP status registers because ".save" requires GPR registers, and1416 // ".vsave" requires DPR registers, so don't record the copy and simply1417 // emit annotations for the source registers used for the store.1418 break;1419 case ARM::tLDRpci: {1420 // Grab the constpool index and check, whether it corresponds to1421 // original or cloned constpool entry.1422 unsigned CPI = MI->getOperand(1).getIndex();1423 const MachineConstantPool *MCP = MF.getConstantPool();1424 if (CPI >= MCP->getConstants().size())1425 CPI = AFI->getOriginalCPIdx(CPI);1426 assert(CPI != -1U && "Invalid constpool index");1427 1428 // Derive the actual offset.1429 const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];1430 assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry");1431 Offset = cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue();1432 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;1433 break;1434 }1435 case ARM::t2MOVi16:1436 Offset = MI->getOperand(1).getImm();1437 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;1438 break;1439 case ARM::t2MOVTi16:1440 Offset = MI->getOperand(2).getImm();1441 AFI->EHPrologueOffsetInRegs[DstReg] |= (Offset << 16);1442 break;1443 case ARM::tMOVi8:1444 Offset = MI->getOperand(2).getImm();1445 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;1446 break;1447 case ARM::tLSLri:1448 assert(MI->getOperand(3).getImm() == 8 &&1449 "The shift amount is not equal to 8");1450 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&1451 "The source register is not equal to the destination register");1452 AFI->EHPrologueOffsetInRegs[DstReg] <<= 8;1453 break;1454 case ARM::tADDi8:1455 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&1456 "The source register is not equal to the destination register");1457 Offset = MI->getOperand(3).getImm();1458 AFI->EHPrologueOffsetInRegs[DstReg] += Offset;1459 break;1460 case ARM::t2PAC:1461 case ARM::t2PACBTI:1462 AFI->EHPrologueRemappedRegs[ARM::R12] = ARM::RA_AUTH_CODE;1463 break;1464 default:1465 MI->print(errs());1466 llvm_unreachable("Unsupported opcode for unwinding information");1467 }1468 }1469 }1470}1471 1472// Simple pseudo-instructions have their lowering (with expansion to real1473// instructions) auto-generated.1474#include "ARMGenMCPseudoLowering.inc"1475 1476// Helper function to check if a register is live (used as an implicit operand)1477// in the given call instruction.1478static bool isRegisterLiveInCall(const MachineInstr &Call, MCRegister Reg) {1479 for (const MachineOperand &MO : Call.implicit_operands()) {1480 if (MO.isReg() && MO.getReg() == Reg && MO.isUse()) {1481 return true;1482 }1483 }1484 return false;1485}1486 1487void ARMAsmPrinter::EmitKCFI_CHECK_ARM32(Register AddrReg, int64_t Type,1488 const MachineInstr &Call,1489 int64_t PrefixNops) {1490 // Choose scratch register: r12 primary, r3 if target is r12.1491 unsigned ScratchReg = ARM::R12;1492 if (AddrReg == ARM::R12) {1493 ScratchReg = ARM::R3;1494 }1495 1496 // Calculate ESR for ARM mode (16-bit): 0x8000 | (scratch_reg << 5) | addr_reg1497 // Note: scratch_reg is always 0x1F since the EOR sequence clobbers it.1498 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(1499 MF->getSubtarget().getRegisterInfo());1500 unsigned AddrIndex = TRI->getEncodingValue(AddrReg);1501 unsigned ESR = 0x8000 | (31 << 5) | (AddrIndex & 31);1502 1503 // Check if r3 is live and needs to be spilled.1504 bool NeedSpillR3 =1505 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, ARM::R3);1506 1507 // If we need to spill r3, push it first.1508 if (NeedSpillR3) {1509 // push {r3}1510 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STMDB_UPD)1511 .addReg(ARM::SP)1512 .addReg(ARM::SP)1513 .addImm(ARMCC::AL)1514 .addReg(0)1515 .addReg(ARM::R3));1516 }1517 1518 // Clear bit 0 of target address to handle Thumb function pointers.1519 // In 32-bit ARM, function pointers may have the low bit set to indicate1520 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).1521 // We need to clear it to avoid an alignment fault when loading.1522 // bic scratch, target, #11523 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BICri)1524 .addReg(ScratchReg)1525 .addReg(AddrReg)1526 .addImm(1)1527 .addImm(ARMCC::AL)1528 .addReg(0)1529 .addReg(0));1530 1531 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]1532 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)1533 .addReg(ScratchReg)1534 .addReg(ScratchReg)1535 .addImm(-(PrefixNops * 4 + 4))1536 .addImm(ARMCC::AL)1537 .addReg(0));1538 1539 // Each EOR instruction XORs one byte of the type, shifted to its position.1540 for (int i = 0; i < 4; i++) {1541 uint8_t byte = (Type >> (i * 8)) & 0xFF;1542 uint32_t imm = byte << (i * 8);1543 bool isLast = (i == 3);1544 1545 // Encode as ARM modified immediate.1546 int SOImmVal = ARM_AM::getSOImmVal(imm);1547 assert(SOImmVal != -1 &&1548 "Cannot encode immediate as ARM modified immediate");1549 1550 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)1551 EmitToStreamer(*OutStreamer,1552 MCInstBuilder(ARM::EORri)1553 .addReg(ScratchReg)1554 .addReg(ScratchReg)1555 .addImm(SOImmVal)1556 .addImm(ARMCC::AL)1557 .addReg(0)1558 .addReg(isLast ? ARM::CPSR : ARM::NoRegister));1559 }1560 1561 // If we spilled r3, restore it immediately after the comparison.1562 // This must happen before the branch so r3 is valid on both paths.1563 if (NeedSpillR3) {1564 // pop {r3}1565 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDMIA_UPD)1566 .addReg(ARM::SP)1567 .addReg(ARM::SP)1568 .addImm(ARMCC::AL)1569 .addReg(0)1570 .addReg(ARM::R3));1571 }1572 1573 // beq .Lpass (branch if types match, i.e., scratch is zero)1574 MCSymbol *Pass = OutContext.createTempSymbol();1575 EmitToStreamer(*OutStreamer,1576 MCInstBuilder(ARM::Bcc)1577 .addExpr(MCSymbolRefExpr::create(Pass, OutContext))1578 .addImm(ARMCC::EQ)1579 .addReg(ARM::CPSR));1580 1581 // udf #ESR (trap with encoded diagnostic)1582 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::UDF).addImm(ESR));1583 1584 OutStreamer->emitLabel(Pass);1585}1586 1587void ARMAsmPrinter::EmitKCFI_CHECK_Thumb2(Register AddrReg, int64_t Type,1588 const MachineInstr &Call,1589 int64_t PrefixNops) {1590 // Choose scratch register: r12 primary, r3 if target is r12.1591 unsigned ScratchReg = ARM::R12;1592 if (AddrReg == ARM::R12) {1593 ScratchReg = ARM::R3;1594 }1595 1596 // Calculate ESR for Thumb mode (8-bit): 0x80 | addr_reg1597 // Bit 7: KCFI trap indicator1598 // Bits 6-5: Reserved1599 // Bits 4-0: Address register encoding1600 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(1601 MF->getSubtarget().getRegisterInfo());1602 unsigned AddrIndex = TRI->getEncodingValue(AddrReg);1603 unsigned ESR = 0x80 | (AddrIndex & 0x1F);1604 1605 // Check if r3 is live and needs to be spilled.1606 bool NeedSpillR3 =1607 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, ARM::R3);1608 1609 // If we need to spill r3, push it first.1610 if (NeedSpillR3) {1611 // push {r3}1612 EmitToStreamer(1613 *OutStreamer,1614 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));1615 }1616 1617 // Clear bit 0 of target address to handle Thumb function pointers.1618 // In 32-bit ARM, function pointers may have the low bit set to indicate1619 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).1620 // We need to clear it to avoid an alignment fault when loading.1621 // bic scratch, target, #11622 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2BICri)1623 .addReg(ScratchReg)1624 .addReg(AddrReg)1625 .addImm(1)1626 .addImm(ARMCC::AL)1627 .addReg(0)1628 .addReg(0));1629 1630 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]1631 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi8)1632 .addReg(ScratchReg)1633 .addReg(ScratchReg)1634 .addImm(-(PrefixNops * 4 + 4))1635 .addImm(ARMCC::AL)1636 .addReg(0));1637 1638 // Each EOR instruction XORs one byte of the type, shifted to its position.1639 for (int i = 0; i < 4; i++) {1640 uint8_t byte = (Type >> (i * 8)) & 0xFF;1641 uint32_t imm = byte << (i * 8);1642 bool isLast = (i == 3);1643 1644 // Verify the immediate can be encoded as Thumb2 modified immediate.1645 assert(ARM_AM::getT2SOImmVal(imm) != -1 &&1646 "Cannot encode immediate as Thumb2 modified immediate");1647 1648 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)1649 EmitToStreamer(*OutStreamer,1650 MCInstBuilder(ARM::t2EORri)1651 .addReg(ScratchReg)1652 .addReg(ScratchReg)1653 .addImm(imm)1654 .addImm(ARMCC::AL)1655 .addReg(0)1656 .addReg(isLast ? ARM::CPSR : ARM::NoRegister));1657 }1658 1659 // If we spilled r3, restore it immediately after the comparison.1660 // This must happen before the branch so r3 is valid on both paths.1661 if (NeedSpillR3) {1662 // pop {r3}1663 EmitToStreamer(1664 *OutStreamer,1665 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));1666 }1667 1668 // beq .Lpass (branch if types match, i.e., scratch is zero)1669 MCSymbol *Pass = OutContext.createTempSymbol();1670 EmitToStreamer(*OutStreamer,1671 MCInstBuilder(ARM::t2Bcc)1672 .addExpr(MCSymbolRefExpr::create(Pass, OutContext))1673 .addImm(ARMCC::EQ)1674 .addReg(ARM::CPSR));1675 1676 // udf #ESR (trap with encoded diagnostic)1677 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tUDF).addImm(ESR));1678 1679 OutStreamer->emitLabel(Pass);1680}1681 1682void ARMAsmPrinter::EmitKCFI_CHECK_Thumb1(Register AddrReg, int64_t Type,1683 const MachineInstr &Call,1684 int64_t PrefixNops) {1685 // For Thumb1, use R2 unconditionally as scratch register (a low register1686 // required for tLDRi). R3 is used for building the type hash.1687 unsigned ScratchReg = ARM::R2;1688 unsigned TempReg = ARM::R3;1689 1690 // Check if r3 is live and needs to be spilled.1691 bool NeedSpillR3 = isRegisterLiveInCall(Call, ARM::R3);1692 1693 // Spill r3 if needed1694 if (NeedSpillR3) {1695 EmitToStreamer(1696 *OutStreamer,1697 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));1698 }1699 1700 // Check if r2 is live and needs to be spilled.1701 bool NeedSpillR2 = isRegisterLiveInCall(Call, ARM::R2);1702 1703 // Push R2 if it's live1704 if (NeedSpillR2) {1705 EmitToStreamer(1706 *OutStreamer,1707 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));1708 }1709 1710 // Clear bit 0 from target address1711 // TempReg (R3) is used first as helper for BIC, then later for building type1712 // hash.1713 1714 // movs temp, #11715 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)1716 .addReg(TempReg)1717 .addReg(ARM::CPSR)1718 .addImm(1)1719 .addImm(ARMCC::AL)1720 .addReg(0));1721 1722 // mov scratch, target1723 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)1724 .addReg(ScratchReg)1725 .addReg(AddrReg)1726 .addImm(ARMCC::AL));1727 1728 // bics scratch, temp (scratch = scratch & ~temp)1729 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBIC)1730 .addReg(ScratchReg)1731 .addReg(ARM::CPSR)1732 .addReg(ScratchReg)1733 .addReg(TempReg)1734 .addImm(ARMCC::AL)1735 .addReg(0));1736 1737 // Load type hash. Thumb1 doesn't support negative offsets, so subtract.1738 int offset = PrefixNops * 4 + 4;1739 1740 // subs scratch, #offset1741 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tSUBi8)1742 .addReg(ScratchReg)1743 .addReg(ARM::CPSR)1744 .addReg(ScratchReg)1745 .addImm(offset)1746 .addImm(ARMCC::AL)1747 .addReg(0));1748 1749 // ldr scratch, [scratch, #0]1750 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)1751 .addReg(ScratchReg)1752 .addReg(ScratchReg)1753 .addImm(0)1754 .addImm(ARMCC::AL)1755 .addReg(0));1756 1757 // Load expected type inline (instead of EOR sequence)1758 //1759 // This creates the 32-bit value byte-by-byte in the temp register:1760 // movs temp, #byte3 (high byte)1761 // lsls temp, temp, #81762 // adds temp, #byte21763 // lsls temp, temp, #81764 // adds temp, #byte11765 // lsls temp, temp, #81766 // adds temp, #byte0 (low byte)1767 1768 uint8_t byte0 = (Type >> 0) & 0xFF;1769 uint8_t byte1 = (Type >> 8) & 0xFF;1770 uint8_t byte2 = (Type >> 16) & 0xFF;1771 uint8_t byte3 = (Type >> 24) & 0xFF;1772 1773 // movs temp, #byte3 (start with high byte)1774 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)1775 .addReg(TempReg)1776 .addReg(ARM::CPSR)1777 .addImm(byte3)1778 .addImm(ARMCC::AL)1779 .addReg(0));1780 1781 // lsls temp, temp, #81782 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)1783 .addReg(TempReg)1784 .addReg(ARM::CPSR)1785 .addReg(TempReg)1786 .addImm(8)1787 .addImm(ARMCC::AL)1788 .addReg(0));1789 1790 // adds temp, #byte21791 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)1792 .addReg(TempReg)1793 .addReg(ARM::CPSR)1794 .addReg(TempReg)1795 .addImm(byte2)1796 .addImm(ARMCC::AL)1797 .addReg(0));1798 1799 // lsls temp, temp, #81800 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)1801 .addReg(TempReg)1802 .addReg(ARM::CPSR)1803 .addReg(TempReg)1804 .addImm(8)1805 .addImm(ARMCC::AL)1806 .addReg(0));1807 1808 // adds temp, #byte11809 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)1810 .addReg(TempReg)1811 .addReg(ARM::CPSR)1812 .addReg(TempReg)1813 .addImm(byte1)1814 .addImm(ARMCC::AL)1815 .addReg(0));1816 1817 // lsls temp, temp, #81818 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)1819 .addReg(TempReg)1820 .addReg(ARM::CPSR)1821 .addReg(TempReg)1822 .addImm(8)1823 .addImm(ARMCC::AL)1824 .addReg(0));1825 1826 // adds temp, #byte0 (low byte)1827 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)1828 .addReg(TempReg)1829 .addReg(ARM::CPSR)1830 .addReg(TempReg)1831 .addImm(byte0)1832 .addImm(ARMCC::AL)1833 .addReg(0));1834 1835 // cmp scratch, temp1836 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tCMPr)1837 .addReg(ScratchReg)1838 .addReg(TempReg)1839 .addImm(ARMCC::AL)1840 .addReg(0));1841 1842 // Restore registers if spilled (pop in reverse order of push: R2, then R3)1843 if (NeedSpillR2) {1844 // pop {r2}1845 EmitToStreamer(1846 *OutStreamer,1847 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));1848 }1849 1850 // Restore r3 if spilled1851 if (NeedSpillR3) {1852 // pop {r3}1853 EmitToStreamer(1854 *OutStreamer,1855 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));1856 }1857 1858 // beq .Lpass (branch if types match, i.e., scratch == temp)1859 MCSymbol *Pass = OutContext.createTempSymbol();1860 EmitToStreamer(*OutStreamer,1861 MCInstBuilder(ARM::tBcc)1862 .addExpr(MCSymbolRefExpr::create(Pass, OutContext))1863 .addImm(ARMCC::EQ)1864 .addReg(ARM::CPSR));1865 1866 // bkpt #0 (trap with encoded diagnostic)1867 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBKPT).addImm(0));1868 1869 OutStreamer->emitLabel(Pass);1870}1871 1872void ARMAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {1873 Register AddrReg = MI.getOperand(0).getReg();1874 const int64_t Type = MI.getOperand(1).getImm();1875 1876 // Get the call instruction that follows this KCFI_CHECK.1877 assert(std::next(MI.getIterator())->isCall() &&1878 "KCFI_CHECK not followed by a call instruction");1879 const MachineInstr &Call = *std::next(MI.getIterator());1880 1881 // Adjust the offset for patchable-function-prefix.1882 int64_t PrefixNops = 0;1883 MI.getMF()1884 ->getFunction()1885 .getFnAttribute("patchable-function-prefix")1886 .getValueAsString()1887 .getAsInteger(10, PrefixNops);1888 1889 // Emit the appropriate instruction sequence based on the opcode variant.1890 switch (MI.getOpcode()) {1891 case ARM::KCFI_CHECK_ARM:1892 EmitKCFI_CHECK_ARM32(AddrReg, Type, Call, PrefixNops);1893 break;1894 case ARM::KCFI_CHECK_Thumb2:1895 EmitKCFI_CHECK_Thumb2(AddrReg, Type, Call, PrefixNops);1896 break;1897 case ARM::KCFI_CHECK_Thumb1:1898 EmitKCFI_CHECK_Thumb1(AddrReg, Type, Call, PrefixNops);1899 break;1900 default:1901 llvm_unreachable("Unexpected KCFI_CHECK opcode");1902 }1903}1904 1905void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) {1906 ARM_MC::verifyInstructionPredicates(MI->getOpcode(),1907 getSubtargetInfo().getFeatureBits());1908 1909 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();1910 const DataLayout &DL = getDataLayout();1911 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();1912 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);1913 1914 // If we just ended a constant pool, mark it as such.1915 if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {1916 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);1917 InConstantPool = false;1918 }1919 1920 // Emit unwinding stuff for frame-related instructions1921 if (TM.getTargetTriple().isTargetEHABICompatible() &&1922 MI->getFlag(MachineInstr::FrameSetup))1923 EmitUnwindingInstruction(MI);1924 1925 // Do any auto-generated pseudo lowerings.1926 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {1927 EmitToStreamer(*OutStreamer, OutInst);1928 return;1929 }1930 1931 assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&1932 "Pseudo flag setting opcode should be expanded early");1933 1934 // Check for manual lowerings.1935 unsigned Opc = MI->getOpcode();1936 switch (Opc) {1937 case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");1938 case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");1939 case ARM::KCFI_CHECK_ARM:1940 case ARM::KCFI_CHECK_Thumb2:1941 case ARM::KCFI_CHECK_Thumb1:1942 LowerKCFI_CHECK(*MI);1943 return;1944 case ARM::LEApcrel:1945 case ARM::tLEApcrel:1946 case ARM::t2LEApcrel: {1947 // FIXME: Need to also handle globals and externals1948 MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());1949 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==1950 ARM::t2LEApcrel ? ARM::t2ADR1951 : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR1952 : ARM::ADR))1953 .addReg(MI->getOperand(0).getReg())1954 .addExpr(MCSymbolRefExpr::create(CPISymbol, OutContext))1955 // Add predicate operands.1956 .addImm(MI->getOperand(2).getImm())1957 .addReg(MI->getOperand(3).getReg()));1958 return;1959 }1960 case ARM::LEApcrelJT:1961 case ARM::tLEApcrelJT:1962 case ARM::t2LEApcrelJT: {1963 MCSymbol *JTIPICSymbol =1964 GetARMJTIPICJumpTableLabel(MI->getOperand(1).getIndex());1965 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==1966 ARM::t2LEApcrelJT ? ARM::t2ADR1967 : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR1968 : ARM::ADR))1969 .addReg(MI->getOperand(0).getReg())1970 .addExpr(MCSymbolRefExpr::create(JTIPICSymbol, OutContext))1971 // Add predicate operands.1972 .addImm(MI->getOperand(2).getImm())1973 .addReg(MI->getOperand(3).getReg()));1974 return;1975 }1976 // Darwin call instructions are just normal call instructions with different1977 // clobber semantics (they clobber R9).1978 case ARM::BX_CALL: {1979 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr)1980 .addReg(ARM::LR)1981 .addReg(ARM::PC)1982 // Add predicate operands.1983 .addImm(ARMCC::AL)1984 .addReg(0)1985 // Add 's' bit operand (always reg0 for this)1986 .addReg(0));1987 1988 assert(STI.hasV4TOps() && "Expected V4TOps for BX call");1989 EmitToStreamer(*OutStreamer,1990 MCInstBuilder(ARM::BX).addReg(MI->getOperand(0).getReg()));1991 return;1992 }1993 case ARM::tBX_CALL: {1994 assert(!STI.hasV5TOps() && "Expected BLX to be selected for v5t+");1995 1996 // On ARM v4t, when doing a call from thumb mode, we need to ensure1997 // that the saved lr has its LSB set correctly (the arch doesn't1998 // have blx).1999 // So here we generate a bl to a small jump pad that does bx rN.2000 // The jump pads are emitted after the function body.2001 2002 Register TReg = MI->getOperand(0).getReg();2003 MCSymbol *TRegSym = nullptr;2004 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {2005 if (TIP.first == TReg) {2006 TRegSym = TIP.second;2007 break;2008 }2009 }2010 2011 if (!TRegSym) {2012 TRegSym = OutContext.createTempSymbol();2013 ThumbIndirectPads.push_back(std::make_pair(TReg, TRegSym));2014 }2015 2016 // Create a link-saving branch to the Reg Indirect Jump Pad.2017 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBL)2018 // Predicate comes first here.2019 .addImm(ARMCC::AL).addReg(0)2020 .addExpr(MCSymbolRefExpr::create(TRegSym, OutContext)));2021 return;2022 }2023 case ARM::BMOVPCRX_CALL: {2024 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr)2025 .addReg(ARM::LR)2026 .addReg(ARM::PC)2027 // Add predicate operands.2028 .addImm(ARMCC::AL)2029 .addReg(0)2030 // Add 's' bit operand (always reg0 for this)2031 .addReg(0));2032 2033 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr)2034 .addReg(ARM::PC)2035 .addReg(MI->getOperand(0).getReg())2036 // Add predicate operands.2037 .addImm(ARMCC::AL)2038 .addReg(0)2039 // Add 's' bit operand (always reg0 for this)2040 .addReg(0));2041 return;2042 }2043 case ARM::BMOVPCB_CALL: {2044 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr)2045 .addReg(ARM::LR)2046 .addReg(ARM::PC)2047 // Add predicate operands.2048 .addImm(ARMCC::AL)2049 .addReg(0)2050 // Add 's' bit operand (always reg0 for this)2051 .addReg(0));2052 2053 const MachineOperand &Op = MI->getOperand(0);2054 const GlobalValue *GV = Op.getGlobal();2055 const unsigned TF = Op.getTargetFlags();2056 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);2057 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);2058 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc)2059 .addExpr(GVSymExpr)2060 // Add predicate operands.2061 .addImm(ARMCC::AL)2062 .addReg(0));2063 return;2064 }2065 case ARM::MOVi16_ga_pcrel:2066 case ARM::t2MOVi16_ga_pcrel: {2067 MCInst TmpInst;2068 TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16);2069 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));2070 2071 unsigned TF = MI->getOperand(1).getTargetFlags();2072 const GlobalValue *GV = MI->getOperand(1).getGlobal();2073 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);2074 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);2075 2076 MCSymbol *LabelSym =2077 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),2078 MI->getOperand(2).getImm(), OutContext);2079 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);2080 unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;2081 const MCExpr *PCRelExpr = ARM::createLower16(2082 MCBinaryExpr::createSub(2083 GVSymExpr,2084 MCBinaryExpr::createAdd(LabelSymExpr,2085 MCConstantExpr::create(PCAdj, OutContext),2086 OutContext),2087 OutContext),2088 OutContext);2089 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));2090 2091 // Add predicate operands.2092 TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));2093 TmpInst.addOperand(MCOperand::createReg(0));2094 // Add 's' bit operand (always reg0 for this)2095 TmpInst.addOperand(MCOperand::createReg(0));2096 EmitToStreamer(*OutStreamer, TmpInst);2097 return;2098 }2099 case ARM::MOVTi16_ga_pcrel:2100 case ARM::t2MOVTi16_ga_pcrel: {2101 MCInst TmpInst;2102 TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel2103 ? ARM::MOVTi16 : ARM::t2MOVTi16);2104 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));2105 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));2106 2107 unsigned TF = MI->getOperand(2).getTargetFlags();2108 const GlobalValue *GV = MI->getOperand(2).getGlobal();2109 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);2110 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);2111 2112 MCSymbol *LabelSym =2113 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),2114 MI->getOperand(3).getImm(), OutContext);2115 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);2116 unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;2117 const MCExpr *PCRelExpr = ARM::createUpper16(2118 MCBinaryExpr::createSub(2119 GVSymExpr,2120 MCBinaryExpr::createAdd(LabelSymExpr,2121 MCConstantExpr::create(PCAdj, OutContext),2122 OutContext),2123 OutContext),2124 OutContext);2125 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));2126 // Add predicate operands.2127 TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));2128 TmpInst.addOperand(MCOperand::createReg(0));2129 // Add 's' bit operand (always reg0 for this)2130 TmpInst.addOperand(MCOperand::createReg(0));2131 EmitToStreamer(*OutStreamer, TmpInst);2132 return;2133 }2134 case ARM::t2BFi:2135 case ARM::t2BFic:2136 case ARM::t2BFLi:2137 case ARM::t2BFr:2138 case ARM::t2BFLr: {2139 // This is a Branch Future instruction.2140 2141 const MCExpr *BranchLabel = MCSymbolRefExpr::create(2142 getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),2143 MI->getOperand(0).getIndex(), OutContext),2144 OutContext);2145 2146 auto MCInst = MCInstBuilder(Opc).addExpr(BranchLabel);2147 if (MI->getOperand(1).isReg()) {2148 // For BFr/BFLr2149 MCInst.addReg(MI->getOperand(1).getReg());2150 } else {2151 // For BFi/BFLi/BFic2152 const MCExpr *BranchTarget;2153 if (MI->getOperand(1).isMBB())2154 BranchTarget = MCSymbolRefExpr::create(2155 MI->getOperand(1).getMBB()->getSymbol(), OutContext);2156 else if (MI->getOperand(1).isGlobal()) {2157 const GlobalValue *GV = MI->getOperand(1).getGlobal();2158 BranchTarget = MCSymbolRefExpr::create(2159 GetARMGVSymbol(GV, MI->getOperand(1).getTargetFlags()), OutContext);2160 } else if (MI->getOperand(1).isSymbol()) {2161 BranchTarget = MCSymbolRefExpr::create(2162 GetExternalSymbolSymbol(MI->getOperand(1).getSymbolName()),2163 OutContext);2164 } else2165 llvm_unreachable("Unhandled operand kind in Branch Future instruction");2166 2167 MCInst.addExpr(BranchTarget);2168 }2169 2170 if (Opc == ARM::t2BFic) {2171 const MCExpr *ElseLabel = MCSymbolRefExpr::create(2172 getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),2173 MI->getOperand(2).getIndex(), OutContext),2174 OutContext);2175 MCInst.addExpr(ElseLabel);2176 MCInst.addImm(MI->getOperand(3).getImm());2177 } else {2178 MCInst.addImm(MI->getOperand(2).getImm())2179 .addReg(MI->getOperand(3).getReg());2180 }2181 2182 EmitToStreamer(*OutStreamer, MCInst);2183 return;2184 }2185 case ARM::t2BF_LabelPseudo: {2186 // This is a pseudo op for a label used by a branch future instruction2187 2188 // Emit the label.2189 OutStreamer->emitLabel(getBFLabel(DL.getPrivateGlobalPrefix(),2190 getFunctionNumber(),2191 MI->getOperand(0).getIndex(), OutContext));2192 return;2193 }2194 case ARM::tPICADD: {2195 // This is a pseudo op for a label + instruction sequence, which looks like:2196 // LPC0:2197 // add r0, pc2198 // This adds the address of LPC0 to r0.2199 2200 // Emit the label.2201 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),2202 getFunctionNumber(),2203 MI->getOperand(2).getImm(), OutContext));2204 2205 // Form and emit the add.2206 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr)2207 .addReg(MI->getOperand(0).getReg())2208 .addReg(MI->getOperand(0).getReg())2209 .addReg(ARM::PC)2210 // Add predicate operands.2211 .addImm(ARMCC::AL)2212 .addReg(0));2213 return;2214 }2215 case ARM::PICADD: {2216 // This is a pseudo op for a label + instruction sequence, which looks like:2217 // LPC0:2218 // add r0, pc, r02219 // This adds the address of LPC0 to r0.2220 2221 // Emit the label.2222 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),2223 getFunctionNumber(),2224 MI->getOperand(2).getImm(), OutContext));2225 2226 // Form and emit the add.2227 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr)2228 .addReg(MI->getOperand(0).getReg())2229 .addReg(ARM::PC)2230 .addReg(MI->getOperand(1).getReg())2231 // Add predicate operands.2232 .addImm(MI->getOperand(3).getImm())2233 .addReg(MI->getOperand(4).getReg())2234 // Add 's' bit operand (always reg0 for this)2235 .addReg(0));2236 return;2237 }2238 case ARM::PICSTR:2239 case ARM::PICSTRB:2240 case ARM::PICSTRH:2241 case ARM::PICLDR:2242 case ARM::PICLDRB:2243 case ARM::PICLDRH:2244 case ARM::PICLDRSB:2245 case ARM::PICLDRSH: {2246 // This is a pseudo op for a label + instruction sequence, which looks like:2247 // LPC0:2248 // OP r0, [pc, r0]2249 // The LCP0 label is referenced by a constant pool entry in order to get2250 // a PC-relative address at the ldr instruction.2251 2252 // Emit the label.2253 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),2254 getFunctionNumber(),2255 MI->getOperand(2).getImm(), OutContext));2256 2257 // Form and emit the load2258 unsigned Opcode;2259 switch (MI->getOpcode()) {2260 default:2261 llvm_unreachable("Unexpected opcode!");2262 case ARM::PICSTR: Opcode = ARM::STRrs; break;2263 case ARM::PICSTRB: Opcode = ARM::STRBrs; break;2264 case ARM::PICSTRH: Opcode = ARM::STRH; break;2265 case ARM::PICLDR: Opcode = ARM::LDRrs; break;2266 case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;2267 case ARM::PICLDRH: Opcode = ARM::LDRH; break;2268 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;2269 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;2270 }2271 EmitToStreamer(*OutStreamer, MCInstBuilder(Opcode)2272 .addReg(MI->getOperand(0).getReg())2273 .addReg(ARM::PC)2274 .addReg(MI->getOperand(1).getReg())2275 .addImm(0)2276 // Add predicate operands.2277 .addImm(MI->getOperand(3).getImm())2278 .addReg(MI->getOperand(4).getReg()));2279 2280 return;2281 }2282 case ARM::CONSTPOOL_ENTRY: {2283 assert(!STI.genExecuteOnly() &&2284 "execute-only should not generate constant pools");2285 2286 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool2287 /// in the function. The first operand is the ID# for this instruction, the2288 /// second is the index into the MachineConstantPool that this is, the third2289 /// is the size in bytes of this constant pool entry.2290 /// The required alignment is specified on the basic block holding this MI.2291 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();2292 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();2293 2294 // If this is the first entry of the pool, mark it.2295 if (!InConstantPool) {2296 OutStreamer->emitDataRegion(MCDR_DataRegion);2297 InConstantPool = true;2298 }2299 2300 OutStreamer->emitLabel(GetCPISymbol(LabelId));2301 2302 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];2303 if (MCPE.isMachineConstantPoolEntry())2304 emitMachineConstantPoolValue(MCPE.Val.MachineCPVal);2305 else2306 emitGlobalConstant(DL, MCPE.Val.ConstVal);2307 return;2308 }2309 case ARM::JUMPTABLE_ADDRS:2310 emitJumpTableAddrs(MI);2311 return;2312 case ARM::JUMPTABLE_INSTS:2313 emitJumpTableInsts(MI);2314 return;2315 case ARM::JUMPTABLE_TBB:2316 case ARM::JUMPTABLE_TBH:2317 emitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2);2318 return;2319 case ARM::t2BR_JT: {2320 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)2321 .addReg(ARM::PC)2322 .addReg(MI->getOperand(0).getReg())2323 // Add predicate operands.2324 .addImm(ARMCC::AL)2325 .addReg(0));2326 return;2327 }2328 case ARM::t2TBB_JT:2329 case ARM::t2TBH_JT: {2330 unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH;2331 // Lower and emit the PC label, then the instruction itself.2332 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));2333 EmitToStreamer(*OutStreamer, MCInstBuilder(Opc)2334 .addReg(MI->getOperand(0).getReg())2335 .addReg(MI->getOperand(1).getReg())2336 // Add predicate operands.2337 .addImm(ARMCC::AL)2338 .addReg(0));2339 return;2340 }2341 case ARM::tTBB_JT:2342 case ARM::tTBH_JT: {2343 2344 bool Is8Bit = MI->getOpcode() == ARM::tTBB_JT;2345 Register Base = MI->getOperand(0).getReg();2346 Register Idx = MI->getOperand(1).getReg();2347 assert(MI->getOperand(1).isKill() && "We need the index register as scratch!");2348 2349 // Multiply up idx if necessary.2350 if (!Is8Bit)2351 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)2352 .addReg(Idx)2353 .addReg(ARM::CPSR)2354 .addReg(Idx)2355 .addImm(1)2356 // Add predicate operands.2357 .addImm(ARMCC::AL)2358 .addReg(0));2359 2360 if (Base == ARM::PC) {2361 // TBB [base, idx] =2362 // ADDS idx, idx, base2363 // LDRB idx, [idx, #4] ; or LDRH if TBH2364 // LSLS idx, #12365 // ADDS pc, pc, idx2366 2367 // When using PC as the base, it's important that there is no padding2368 // between the last ADDS and the start of the jump table. The jump table2369 // is 4-byte aligned, so we ensure we're 4 byte aligned here too.2370 //2371 // FIXME: Ideally we could vary the LDRB index based on the padding2372 // between the sequence and jump table, however that relies on MCExprs2373 // for load indexes which are currently not supported.2374 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());2375 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr)2376 .addReg(Idx)2377 .addReg(Idx)2378 .addReg(Base)2379 // Add predicate operands.2380 .addImm(ARMCC::AL)2381 .addReg(0));2382 2383 unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi;2384 EmitToStreamer(*OutStreamer, MCInstBuilder(Opc)2385 .addReg(Idx)2386 .addReg(Idx)2387 .addImm(Is8Bit ? 4 : 2)2388 // Add predicate operands.2389 .addImm(ARMCC::AL)2390 .addReg(0));2391 } else {2392 // TBB [base, idx] =2393 // LDRB idx, [base, idx] ; or LDRH if TBH2394 // LSLS idx, #12395 // ADDS pc, pc, idx2396 2397 unsigned Opc = Is8Bit ? ARM::tLDRBr : ARM::tLDRHr;2398 EmitToStreamer(*OutStreamer, MCInstBuilder(Opc)2399 .addReg(Idx)2400 .addReg(Base)2401 .addReg(Idx)2402 // Add predicate operands.2403 .addImm(ARMCC::AL)2404 .addReg(0));2405 }2406 2407 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)2408 .addReg(Idx)2409 .addReg(ARM::CPSR)2410 .addReg(Idx)2411 .addImm(1)2412 // Add predicate operands.2413 .addImm(ARMCC::AL)2414 .addReg(0));2415 2416 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));2417 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr)2418 .addReg(ARM::PC)2419 .addReg(ARM::PC)2420 .addReg(Idx)2421 // Add predicate operands.2422 .addImm(ARMCC::AL)2423 .addReg(0));2424 return;2425 }2426 case ARM::tBR_JTr:2427 case ARM::BR_JTr: {2428 // mov pc, target2429 MCInst TmpInst;2430 unsigned Opc = MI->getOpcode() == ARM::BR_JTr ?2431 ARM::MOVr : ARM::tMOVr;2432 TmpInst.setOpcode(Opc);2433 TmpInst.addOperand(MCOperand::createReg(ARM::PC));2434 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));2435 // Add predicate operands.2436 TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));2437 TmpInst.addOperand(MCOperand::createReg(0));2438 // Add 's' bit operand (always reg0 for this)2439 if (Opc == ARM::MOVr)2440 TmpInst.addOperand(MCOperand::createReg(0));2441 EmitToStreamer(*OutStreamer, TmpInst);2442 return;2443 }2444 case ARM::BR_JTm_i12: {2445 // ldr pc, target2446 MCInst TmpInst;2447 TmpInst.setOpcode(ARM::LDRi12);2448 TmpInst.addOperand(MCOperand::createReg(ARM::PC));2449 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));2450 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));2451 // Add predicate operands.2452 TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));2453 TmpInst.addOperand(MCOperand::createReg(0));2454 EmitToStreamer(*OutStreamer, TmpInst);2455 return;2456 }2457 case ARM::BR_JTm_rs: {2458 // ldr pc, target2459 MCInst TmpInst;2460 TmpInst.setOpcode(ARM::LDRrs);2461 TmpInst.addOperand(MCOperand::createReg(ARM::PC));2462 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));2463 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));2464 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));2465 // Add predicate operands.2466 TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));2467 TmpInst.addOperand(MCOperand::createReg(0));2468 EmitToStreamer(*OutStreamer, TmpInst);2469 return;2470 }2471 case ARM::BR_JTadd: {2472 // add pc, target, idx2473 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr)2474 .addReg(ARM::PC)2475 .addReg(MI->getOperand(0).getReg())2476 .addReg(MI->getOperand(1).getReg())2477 // Add predicate operands.2478 .addImm(ARMCC::AL)2479 .addReg(0)2480 // Add 's' bit operand (always reg0 for this)2481 .addReg(0));2482 return;2483 }2484 case ARM::SPACE:2485 OutStreamer->emitZeros(MI->getOperand(1).getImm());2486 return;2487 case ARM::TRAP: {2488 // Non-Darwin binutils don't yet support the "trap" mnemonic.2489 // FIXME: Remove this special case when they do.2490 if (!TM.getTargetTriple().isOSBinFormatMachO()) {2491 uint32_t Val = 0xe7ffdefeUL;2492 OutStreamer->AddComment("trap");2493 ATS.emitInst(Val);2494 return;2495 }2496 break;2497 }2498 case ARM::tTRAP: {2499 // Non-Darwin binutils don't yet support the "trap" mnemonic.2500 // FIXME: Remove this special case when they do.2501 if (!TM.getTargetTriple().isOSBinFormatMachO()) {2502 uint16_t Val = 0xdefe;2503 OutStreamer->AddComment("trap");2504 ATS.emitInst(Val, 'n');2505 return;2506 }2507 break;2508 }2509 case ARM::t2Int_eh_sjlj_setjmp:2510 case ARM::t2Int_eh_sjlj_setjmp_nofp:2511 case ARM::tInt_eh_sjlj_setjmp: {2512 // Two incoming args: GPR:$src, GPR:$val2513 // mov $val, pc2514 // adds $val, #72515 // str $val, [$src, #4]2516 // movs r0, #02517 // b LSJLJEH2518 // movs r0, #12519 // LSJLJEH:2520 Register SrcReg = MI->getOperand(0).getReg();2521 Register ValReg = MI->getOperand(1).getReg();2522 MCSymbol *Label = OutContext.createTempSymbol("SJLJEH");2523 OutStreamer->AddComment("eh_setjmp begin");2524 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)2525 .addReg(ValReg)2526 .addReg(ARM::PC)2527 // Predicate.2528 .addImm(ARMCC::AL)2529 .addReg(0));2530 2531 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi3)2532 .addReg(ValReg)2533 // 's' bit operand2534 .addReg(ARM::CPSR)2535 .addReg(ValReg)2536 .addImm(7)2537 // Predicate.2538 .addImm(ARMCC::AL)2539 .addReg(0));2540 2541 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tSTRi)2542 .addReg(ValReg)2543 .addReg(SrcReg)2544 // The offset immediate is #4. The operand value is scaled by 4 for the2545 // tSTR instruction.2546 .addImm(1)2547 // Predicate.2548 .addImm(ARMCC::AL)2549 .addReg(0));2550 2551 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)2552 .addReg(ARM::R0)2553 .addReg(ARM::CPSR)2554 .addImm(0)2555 // Predicate.2556 .addImm(ARMCC::AL)2557 .addReg(0));2558 2559 const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Label, OutContext);2560 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tB)2561 .addExpr(SymbolExpr)2562 .addImm(ARMCC::AL)2563 .addReg(0));2564 2565 OutStreamer->AddComment("eh_setjmp end");2566 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)2567 .addReg(ARM::R0)2568 .addReg(ARM::CPSR)2569 .addImm(1)2570 // Predicate.2571 .addImm(ARMCC::AL)2572 .addReg(0));2573 2574 OutStreamer->emitLabel(Label);2575 return;2576 }2577 2578 case ARM::Int_eh_sjlj_setjmp_nofp:2579 case ARM::Int_eh_sjlj_setjmp: {2580 // Two incoming args: GPR:$src, GPR:$val2581 // add $val, pc, #82582 // str $val, [$src, #+4]2583 // mov r0, #02584 // add pc, pc, #02585 // mov r0, #12586 Register SrcReg = MI->getOperand(0).getReg();2587 Register ValReg = MI->getOperand(1).getReg();2588 2589 OutStreamer->AddComment("eh_setjmp begin");2590 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDri)2591 .addReg(ValReg)2592 .addReg(ARM::PC)2593 .addImm(8)2594 // Predicate.2595 .addImm(ARMCC::AL)2596 .addReg(0)2597 // 's' bit operand (always reg0 for this).2598 .addReg(0));2599 2600 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STRi12)2601 .addReg(ValReg)2602 .addReg(SrcReg)2603 .addImm(4)2604 // Predicate.2605 .addImm(ARMCC::AL)2606 .addReg(0));2607 2608 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVi)2609 .addReg(ARM::R0)2610 .addImm(0)2611 // Predicate.2612 .addImm(ARMCC::AL)2613 .addReg(0)2614 // 's' bit operand (always reg0 for this).2615 .addReg(0));2616 2617 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDri)2618 .addReg(ARM::PC)2619 .addReg(ARM::PC)2620 .addImm(0)2621 // Predicate.2622 .addImm(ARMCC::AL)2623 .addReg(0)2624 // 's' bit operand (always reg0 for this).2625 .addReg(0));2626 2627 OutStreamer->AddComment("eh_setjmp end");2628 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVi)2629 .addReg(ARM::R0)2630 .addImm(1)2631 // Predicate.2632 .addImm(ARMCC::AL)2633 .addReg(0)2634 // 's' bit operand (always reg0 for this).2635 .addReg(0));2636 return;2637 }2638 case ARM::Int_eh_sjlj_longjmp: {2639 // ldr sp, [$src, #8]2640 // ldr $scratch, [$src, #4]2641 // ldr r7, [$src]2642 // bx $scratch2643 Register SrcReg = MI->getOperand(0).getReg();2644 Register ScratchReg = MI->getOperand(1).getReg();2645 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)2646 .addReg(ARM::SP)2647 .addReg(SrcReg)2648 .addImm(8)2649 // Predicate.2650 .addImm(ARMCC::AL)2651 .addReg(0));2652 2653 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)2654 .addReg(ScratchReg)2655 .addReg(SrcReg)2656 .addImm(4)2657 // Predicate.2658 .addImm(ARMCC::AL)2659 .addReg(0));2660 2661 if (STI.isTargetDarwin() || STI.isTargetWindows()) {2662 // These platforms always use the same frame register2663 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)2664 .addReg(STI.getFramePointerReg())2665 .addReg(SrcReg)2666 .addImm(0)2667 // Predicate.2668 .addImm(ARMCC::AL)2669 .addReg(0));2670 } else {2671 // If the calling code might use either R7 or R11 as2672 // frame pointer register, restore it into both.2673 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)2674 .addReg(ARM::R7)2675 .addReg(SrcReg)2676 .addImm(0)2677 // Predicate.2678 .addImm(ARMCC::AL)2679 .addReg(0));2680 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)2681 .addReg(ARM::R11)2682 .addReg(SrcReg)2683 .addImm(0)2684 // Predicate.2685 .addImm(ARMCC::AL)2686 .addReg(0));2687 }2688 2689 assert(STI.hasV4TOps());2690 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX)2691 .addReg(ScratchReg)2692 // Predicate.2693 .addImm(ARMCC::AL)2694 .addReg(0));2695 return;2696 }2697 case ARM::tInt_eh_sjlj_longjmp: {2698 // ldr $scratch, [$src, #8]2699 // mov sp, $scratch2700 // ldr $scratch, [$src, #4]2701 // ldr r7, [$src]2702 // bx $scratch2703 Register SrcReg = MI->getOperand(0).getReg();2704 Register ScratchReg = MI->getOperand(1).getReg();2705 2706 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)2707 .addReg(ScratchReg)2708 .addReg(SrcReg)2709 // The offset immediate is #8. The operand value is scaled by 4 for the2710 // tLDR instruction.2711 .addImm(2)2712 // Predicate.2713 .addImm(ARMCC::AL)2714 .addReg(0));2715 2716 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)2717 .addReg(ARM::SP)2718 .addReg(ScratchReg)2719 // Predicate.2720 .addImm(ARMCC::AL)2721 .addReg(0));2722 2723 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)2724 .addReg(ScratchReg)2725 .addReg(SrcReg)2726 .addImm(1)2727 // Predicate.2728 .addImm(ARMCC::AL)2729 .addReg(0));2730 2731 if (STI.isTargetDarwin() || STI.isTargetWindows()) {2732 // These platforms always use the same frame register2733 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)2734 .addReg(STI.getFramePointerReg())2735 .addReg(SrcReg)2736 .addImm(0)2737 // Predicate.2738 .addImm(ARMCC::AL)2739 .addReg(0));2740 } else {2741 // If the calling code might use either R7 or R11 as2742 // frame pointer register, restore it into both.2743 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)2744 .addReg(ARM::R7)2745 .addReg(SrcReg)2746 .addImm(0)2747 // Predicate.2748 .addImm(ARMCC::AL)2749 .addReg(0));2750 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)2751 .addReg(ARM::R11)2752 .addReg(SrcReg)2753 .addImm(0)2754 // Predicate.2755 .addImm(ARMCC::AL)2756 .addReg(0));2757 }2758 2759 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX)2760 .addReg(ScratchReg)2761 // Predicate.2762 .addImm(ARMCC::AL)2763 .addReg(0));2764 return;2765 }2766 case ARM::tInt_WIN_eh_sjlj_longjmp: {2767 // ldr.w r11, [$src, #0]2768 // ldr.w sp, [$src, #8]2769 // ldr.w pc, [$src, #4]2770 2771 Register SrcReg = MI->getOperand(0).getReg();2772 2773 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)2774 .addReg(ARM::R11)2775 .addReg(SrcReg)2776 .addImm(0)2777 // Predicate2778 .addImm(ARMCC::AL)2779 .addReg(0));2780 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)2781 .addReg(ARM::SP)2782 .addReg(SrcReg)2783 .addImm(8)2784 // Predicate2785 .addImm(ARMCC::AL)2786 .addReg(0));2787 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)2788 .addReg(ARM::PC)2789 .addReg(SrcReg)2790 .addImm(4)2791 // Predicate2792 .addImm(ARMCC::AL)2793 .addReg(0));2794 return;2795 }2796 case ARM::PATCHABLE_FUNCTION_ENTER:2797 LowerPATCHABLE_FUNCTION_ENTER(*MI);2798 return;2799 case ARM::PATCHABLE_FUNCTION_EXIT:2800 LowerPATCHABLE_FUNCTION_EXIT(*MI);2801 return;2802 case ARM::PATCHABLE_TAIL_CALL:2803 LowerPATCHABLE_TAIL_CALL(*MI);2804 return;2805 case ARM::SpeculationBarrierISBDSBEndBB: {2806 // Print DSB SYS + ISB2807 MCInst TmpInstDSB;2808 TmpInstDSB.setOpcode(ARM::DSB);2809 TmpInstDSB.addOperand(MCOperand::createImm(0xf));2810 EmitToStreamer(*OutStreamer, TmpInstDSB);2811 MCInst TmpInstISB;2812 TmpInstISB.setOpcode(ARM::ISB);2813 TmpInstISB.addOperand(MCOperand::createImm(0xf));2814 EmitToStreamer(*OutStreamer, TmpInstISB);2815 return;2816 }2817 case ARM::t2SpeculationBarrierISBDSBEndBB: {2818 // Print DSB SYS + ISB2819 MCInst TmpInstDSB;2820 TmpInstDSB.setOpcode(ARM::t2DSB);2821 TmpInstDSB.addOperand(MCOperand::createImm(0xf));2822 TmpInstDSB.addOperand(MCOperand::createImm(ARMCC::AL));2823 TmpInstDSB.addOperand(MCOperand::createReg(0));2824 EmitToStreamer(*OutStreamer, TmpInstDSB);2825 MCInst TmpInstISB;2826 TmpInstISB.setOpcode(ARM::t2ISB);2827 TmpInstISB.addOperand(MCOperand::createImm(0xf));2828 TmpInstISB.addOperand(MCOperand::createImm(ARMCC::AL));2829 TmpInstISB.addOperand(MCOperand::createReg(0));2830 EmitToStreamer(*OutStreamer, TmpInstISB);2831 return;2832 }2833 case ARM::SpeculationBarrierSBEndBB: {2834 // Print SB2835 MCInst TmpInstSB;2836 TmpInstSB.setOpcode(ARM::SB);2837 EmitToStreamer(*OutStreamer, TmpInstSB);2838 return;2839 }2840 case ARM::t2SpeculationBarrierSBEndBB: {2841 // Print SB2842 MCInst TmpInstSB;2843 TmpInstSB.setOpcode(ARM::t2SB);2844 EmitToStreamer(*OutStreamer, TmpInstSB);2845 return;2846 }2847 2848 case ARM::SEH_StackAlloc:2849 ATS.emitARMWinCFIAllocStack(MI->getOperand(0).getImm(),2850 MI->getOperand(1).getImm());2851 return;2852 2853 case ARM::SEH_SaveRegs:2854 case ARM::SEH_SaveRegs_Ret:2855 ATS.emitARMWinCFISaveRegMask(MI->getOperand(0).getImm(),2856 MI->getOperand(1).getImm());2857 return;2858 2859 case ARM::SEH_SaveSP:2860 ATS.emitARMWinCFISaveSP(MI->getOperand(0).getImm());2861 return;2862 2863 case ARM::SEH_SaveFRegs:2864 ATS.emitARMWinCFISaveFRegs(MI->getOperand(0).getImm(),2865 MI->getOperand(1).getImm());2866 return;2867 2868 case ARM::SEH_SaveLR:2869 ATS.emitARMWinCFISaveLR(MI->getOperand(0).getImm());2870 return;2871 2872 case ARM::SEH_Nop:2873 case ARM::SEH_Nop_Ret:2874 ATS.emitARMWinCFINop(MI->getOperand(0).getImm());2875 return;2876 2877 case ARM::SEH_PrologEnd:2878 ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false);2879 return;2880 2881 case ARM::SEH_EpilogStart:2882 ATS.emitARMWinCFIEpilogStart(ARMCC::AL);2883 return;2884 2885 case ARM::SEH_EpilogEnd:2886 ATS.emitARMWinCFIEpilogEnd();2887 return;2888 }2889 2890 MCInst TmpInst;2891 LowerARMMachineInstrToMCInst(MI, TmpInst, *this);2892 2893 EmitToStreamer(*OutStreamer, TmpInst);2894}2895 2896char ARMAsmPrinter::ID = 0;2897 2898INITIALIZE_PASS(ARMAsmPrinter, "arm-asm-printer", "ARM Assembly Printer", false,2899 false)2900 2901//===----------------------------------------------------------------------===//2902// Target Registry Stuff2903//===----------------------------------------------------------------------===//2904 2905// Force static initialization.2906extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void2907LLVMInitializeARMAsmPrinter() {2908 RegisterAsmPrinter<ARMAsmPrinter> X(getTheARMLETarget());2909 RegisterAsmPrinter<ARMAsmPrinter> Y(getTheARMBETarget());2910 RegisterAsmPrinter<ARMAsmPrinter> A(getTheThumbLETarget());2911 RegisterAsmPrinter<ARMAsmPrinter> B(getTheThumbBETarget());2912}2913