1*0b57cec5SDimitry Andric //===-- ARMAsmPrinter.h - ARM implementation of AsmPrinter ------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric 9*0b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_ARM_ARMASMPRINTER_H 10*0b57cec5SDimitry Andric #define LLVM_LIB_TARGET_ARM_ARMASMPRINTER_H 11*0b57cec5SDimitry Andric 12*0b57cec5SDimitry Andric #include "ARMSubtarget.h" 13*0b57cec5SDimitry Andric #include "llvm/CodeGen/AsmPrinter.h" 14*0b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric namespace llvm { 17*0b57cec5SDimitry Andric 18*0b57cec5SDimitry Andric class ARMFunctionInfo; 19*0b57cec5SDimitry Andric class MCOperand; 20*0b57cec5SDimitry Andric class MachineConstantPool; 21*0b57cec5SDimitry Andric class MachineOperand; 22*0b57cec5SDimitry Andric class MCSymbol; 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric namespace ARM { 25*0b57cec5SDimitry Andric enum DW_ISA { 26*0b57cec5SDimitry Andric DW_ISA_ARM_thumb = 1, 27*0b57cec5SDimitry Andric DW_ISA_ARM_arm = 2 28*0b57cec5SDimitry Andric }; 29*0b57cec5SDimitry Andric } 30*0b57cec5SDimitry Andric 31*0b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY ARMAsmPrinter : public AsmPrinter { 32*0b57cec5SDimitry Andric 33*0b57cec5SDimitry Andric /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can 34*0b57cec5SDimitry Andric /// make the right decision when printing asm code for different targets. 35*0b57cec5SDimitry Andric const ARMSubtarget *Subtarget; 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric /// AFI - Keep a pointer to ARMFunctionInfo for the current 38*0b57cec5SDimitry Andric /// MachineFunction. 39*0b57cec5SDimitry Andric ARMFunctionInfo *AFI; 40*0b57cec5SDimitry Andric 41*0b57cec5SDimitry Andric /// MCP - Keep a pointer to constantpool entries of the current 42*0b57cec5SDimitry Andric /// MachineFunction. 43*0b57cec5SDimitry Andric const MachineConstantPool *MCP; 44*0b57cec5SDimitry Andric 45*0b57cec5SDimitry Andric /// InConstantPool - Maintain state when emitting a sequence of constant 46*0b57cec5SDimitry Andric /// pool entries so we can properly mark them as data regions. 47*0b57cec5SDimitry Andric bool InConstantPool; 48*0b57cec5SDimitry Andric 49*0b57cec5SDimitry Andric /// ThumbIndirectPads - These maintain a per-function list of jump pad 50*0b57cec5SDimitry Andric /// labels used for ARMv4t thumb code to make register indirect calls. 51*0b57cec5SDimitry Andric SmallVector<std::pair<unsigned, MCSymbol*>, 4> ThumbIndirectPads; 52*0b57cec5SDimitry Andric 53*0b57cec5SDimitry Andric /// OptimizationGoals - Maintain a combined optimization goal for all 54*0b57cec5SDimitry Andric /// functions in a module: one of Tag_ABI_optimization_goals values, 55*0b57cec5SDimitry Andric /// -1 if uninitialized, 0 if conflicting goals 56*0b57cec5SDimitry Andric int OptimizationGoals; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric /// List of globals that have had their storage promoted to a constant 59*0b57cec5SDimitry Andric /// pool. This lives between calls to runOnMachineFunction and collects 60*0b57cec5SDimitry Andric /// data from every MachineFunction. It is used during doFinalization 61*0b57cec5SDimitry Andric /// when all non-function globals are emitted. 62*0b57cec5SDimitry Andric SmallPtrSet<const GlobalVariable*,2> PromotedGlobals; 63*0b57cec5SDimitry Andric /// Set of globals in PromotedGlobals that we've emitted labels for. 64*0b57cec5SDimitry Andric /// We need to emit labels even for promoted globals so that DWARF 65*0b57cec5SDimitry Andric /// debug info can link properly. 66*0b57cec5SDimitry Andric SmallPtrSet<const GlobalVariable*,2> EmittedPromotedGlobalLabels; 67*0b57cec5SDimitry Andric 68*0b57cec5SDimitry Andric public: 69*0b57cec5SDimitry Andric explicit ARMAsmPrinter(TargetMachine &TM, 70*0b57cec5SDimitry Andric std::unique_ptr<MCStreamer> Streamer); 71*0b57cec5SDimitry Andric 72*0b57cec5SDimitry Andric StringRef getPassName() const override { 73*0b57cec5SDimitry Andric return "ARM Assembly Printer"; 74*0b57cec5SDimitry Andric } 75*0b57cec5SDimitry Andric 76*0b57cec5SDimitry Andric void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O); 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override; 79*0b57cec5SDimitry Andric bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 80*0b57cec5SDimitry Andric const char *ExtraCode, raw_ostream &O) override; 81*0b57cec5SDimitry Andric bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, 82*0b57cec5SDimitry Andric const char *ExtraCode, raw_ostream &O) override; 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, 85*0b57cec5SDimitry Andric const MCSubtargetInfo *EndInfo) const override; 86*0b57cec5SDimitry Andric 87*0b57cec5SDimitry Andric void EmitJumpTableAddrs(const MachineInstr *MI); 88*0b57cec5SDimitry Andric void EmitJumpTableInsts(const MachineInstr *MI); 89*0b57cec5SDimitry Andric void EmitJumpTableTBInst(const MachineInstr *MI, unsigned OffsetWidth); 90*0b57cec5SDimitry Andric void EmitInstruction(const MachineInstr *MI) override; 91*0b57cec5SDimitry Andric bool runOnMachineFunction(MachineFunction &F) override; 92*0b57cec5SDimitry Andric 93*0b57cec5SDimitry Andric void EmitConstantPool() override { 94*0b57cec5SDimitry Andric // we emit constant pools customly! 95*0b57cec5SDimitry Andric } 96*0b57cec5SDimitry Andric void EmitFunctionBodyEnd() override; 97*0b57cec5SDimitry Andric void EmitFunctionEntryLabel() override; 98*0b57cec5SDimitry Andric void EmitStartOfAsmFile(Module &M) override; 99*0b57cec5SDimitry Andric void EmitEndOfAsmFile(Module &M) override; 100*0b57cec5SDimitry Andric void EmitXXStructor(const DataLayout &DL, const Constant *CV) override; 101*0b57cec5SDimitry Andric void EmitGlobalVariable(const GlobalVariable *GV) override; 102*0b57cec5SDimitry Andric 103*0b57cec5SDimitry Andric MCSymbol *GetCPISymbol(unsigned CPID) const override; 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric // lowerOperand - Convert a MachineOperand into the equivalent MCOperand. 106*0b57cec5SDimitry Andric bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp); 107*0b57cec5SDimitry Andric 108*0b57cec5SDimitry Andric //===------------------------------------------------------------------===// 109*0b57cec5SDimitry Andric // XRay implementation 110*0b57cec5SDimitry Andric //===------------------------------------------------------------------===// 111*0b57cec5SDimitry Andric public: 112*0b57cec5SDimitry Andric // XRay-specific lowering for ARM. 113*0b57cec5SDimitry Andric void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI); 114*0b57cec5SDimitry Andric void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI); 115*0b57cec5SDimitry Andric void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI); 116*0b57cec5SDimitry Andric 117*0b57cec5SDimitry Andric private: 118*0b57cec5SDimitry Andric void EmitSled(const MachineInstr &MI, SledKind Kind); 119*0b57cec5SDimitry Andric 120*0b57cec5SDimitry Andric // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() 121*0b57cec5SDimitry Andric void emitAttributes(); 122*0b57cec5SDimitry Andric 123*0b57cec5SDimitry Andric // Generic helper used to emit e.g. ARMv5 mul pseudos 124*0b57cec5SDimitry Andric void EmitPatchedInstruction(const MachineInstr *MI, unsigned TargetOpc); 125*0b57cec5SDimitry Andric 126*0b57cec5SDimitry Andric void EmitUnwindingInstruction(const MachineInstr *MI); 127*0b57cec5SDimitry Andric 128*0b57cec5SDimitry Andric // emitPseudoExpansionLowering - tblgen'erated. 129*0b57cec5SDimitry Andric bool emitPseudoExpansionLowering(MCStreamer &OutStreamer, 130*0b57cec5SDimitry Andric const MachineInstr *MI); 131*0b57cec5SDimitry Andric 132*0b57cec5SDimitry Andric public: 133*0b57cec5SDimitry Andric unsigned getISAEncoding() override { 134*0b57cec5SDimitry Andric // ARM/Darwin adds ISA to the DWARF info for each function. 135*0b57cec5SDimitry Andric const Triple &TT = TM.getTargetTriple(); 136*0b57cec5SDimitry Andric if (!TT.isOSBinFormatMachO()) 137*0b57cec5SDimitry Andric return 0; 138*0b57cec5SDimitry Andric bool isThumb = TT.isThumb() || 139*0b57cec5SDimitry Andric TT.getSubArch() == Triple::ARMSubArch_v7m || 140*0b57cec5SDimitry Andric TT.getSubArch() == Triple::ARMSubArch_v6m; 141*0b57cec5SDimitry Andric return isThumb ? ARM::DW_ISA_ARM_thumb : ARM::DW_ISA_ARM_arm; 142*0b57cec5SDimitry Andric } 143*0b57cec5SDimitry Andric 144*0b57cec5SDimitry Andric private: 145*0b57cec5SDimitry Andric MCOperand GetSymbolRef(const MachineOperand &MO, const MCSymbol *Symbol); 146*0b57cec5SDimitry Andric MCSymbol *GetARMJTIPICJumpTableLabel(unsigned uid) const; 147*0b57cec5SDimitry Andric 148*0b57cec5SDimitry Andric MCSymbol *GetARMGVSymbol(const GlobalValue *GV, unsigned char TargetFlags); 149*0b57cec5SDimitry Andric 150*0b57cec5SDimitry Andric public: 151*0b57cec5SDimitry Andric /// EmitMachineConstantPoolValue - Print a machine constantpool value to 152*0b57cec5SDimitry Andric /// the .s file. 153*0b57cec5SDimitry Andric void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override; 154*0b57cec5SDimitry Andric }; 155*0b57cec5SDimitry Andric } // end namespace llvm 156*0b57cec5SDimitry Andric 157*0b57cec5SDimitry Andric #endif 158