LLVM 17.0.0git
ARMMCInstLower.cpp
Go to the documentation of this file.
1//===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains code to lower ARM MachineInstrs to their corresponding
10// MCInst records.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARM.h"
15#include "ARMAsmPrinter.h"
16#include "ARMBaseInstrInfo.h"
18#include "ARMSubtarget.h"
22#include "llvm/ADT/APFloat.h"
26#include "llvm/IR/Constants.h"
27#include "llvm/MC/MCContext.h"
28#include "llvm/MC/MCExpr.h"
29#include "llvm/MC/MCInst.h"
31#include "llvm/MC/MCStreamer.h"
33#include <cassert>
34#include <cstdint>
35
36using namespace llvm;
37
38MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
39 const MCSymbol *Symbol) {
42 SymbolVariant = MCSymbolRefExpr::VK_ARM_SBREL;
43
44 const MCExpr *Expr =
45 MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
47 default:
48 llvm_unreachable("Unknown target flag on symbol operand");
50 break;
51 case ARMII::MO_LO16:
52 Expr =
53 MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
55 break;
56 case ARMII::MO_HI16:
57 Expr =
58 MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
60 break;
61 }
62
63 if (!MO.isJTI() && MO.getOffset())
64 Expr = MCBinaryExpr::createAdd(Expr,
68 return MCOperand::createExpr(Expr);
69
70}
71
73 MCOperand &MCOp) {
74 switch (MO.getType()) {
75 default: llvm_unreachable("unknown operand type");
77 // Ignore all implicit register operands.
78 if (MO.isImplicit())
79 return false;
80 assert(!MO.getSubReg() && "Subregs should be eliminated!");
81 MCOp = MCOperand::createReg(MO.getReg());
82 break;
84 MCOp = MCOperand::createImm(MO.getImm());
85 break;
88 MO.getMBB()->getSymbol(), OutContext));
89 break;
91 MCOp = GetSymbolRef(MO,
92 GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags()));
93 break;
95 MCOp = GetSymbolRef(MO,
97 break;
99 MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
100 break;
102 if (Subtarget->genExecuteOnly())
103 llvm_unreachable("execute-only should not generate constant pools");
104 MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
105 break;
107 MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));
108 break;
110 APFloat Val = MO.getFPImm()->getValueAPF();
111 bool ignored;
113 MCOp = MCOperand::createDFPImm(bit_cast<uint64_t>(Val.convertToDouble()));
114 break;
115 }
117 // Ignore call clobbers.
118 return false;
119 }
120 return true;
121}
122
124 ARMAsmPrinter &AP) {
125 OutMI.setOpcode(MI->getOpcode());
126
127 // In the MC layer, we keep modified immediates in their encoded form
128 bool EncodeImms = false;
129 switch (MI->getOpcode()) {
130 default: break;
131 case ARM::MOVi:
132 case ARM::MVNi:
133 case ARM::CMPri:
134 case ARM::CMNri:
135 case ARM::TSTri:
136 case ARM::TEQri:
137 case ARM::MSRi:
138 case ARM::ADCri:
139 case ARM::ADDri:
140 case ARM::ADDSri:
141 case ARM::SBCri:
142 case ARM::SUBri:
143 case ARM::SUBSri:
144 case ARM::ANDri:
145 case ARM::ORRri:
146 case ARM::EORri:
147 case ARM::BICri:
148 case ARM::RSBri:
149 case ARM::RSBSri:
150 case ARM::RSCri:
151 EncodeImms = true;
152 break;
153 }
154
155 for (const MachineOperand &MO : MI->operands()) {
156 MCOperand MCOp;
157 if (AP.lowerOperand(MO, MCOp)) {
158 if (MCOp.isImm() && EncodeImms) {
159 int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());
160 if (Enc != -1)
161 MCOp.setImm(Enc);
162 }
163 OutMI.addOperand(MCOp);
164 }
165 }
166}
167
168void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
169{
170 if (MI.getParent()->getParent()->getInfo<ARMFunctionInfo>()
171 ->isThumbFunction())
172 {
173 MI.emitError("An attempt to perform XRay instrumentation for a"
174 " Thumb function (not supported). Detected when emitting a sled.");
175 return;
176 }
177 static const int8_t NoopsInSledCount = 6;
178 // We want to emit the following pattern:
179 //
180 // .Lxray_sled_N:
181 // ALIGN
182 // B #20
183 // ; 6 NOP instructions (24 bytes)
184 // .tmpN
185 //
186 // We need the 24 bytes (6 instructions) because at runtime, we'd be patching
187 // over the full 28 bytes (7 instructions) with the following pattern:
188 //
189 // PUSH{ r0, lr }
190 // MOVW r0, #<lower 16 bits of function ID>
191 // MOVT r0, #<higher 16 bits of function ID>
192 // MOVW ip, #<lower 16 bits of address of __xray_FunctionEntry/Exit>
193 // MOVT ip, #<higher 16 bits of address of __xray_FunctionEntry/Exit>
194 // BLX ip
195 // POP{ r0, lr }
196 //
197 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
198 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
199 OutStreamer->emitLabel(CurSled);
201
202 // Emit "B #20" instruction, which jumps over the next 24 bytes (because
203 // register pc is 8 bytes ahead of the jump instruction by the moment CPU
204 // is executing it).
205 // By analogy to ARMAsmPrinter::emitPseudoExpansionLowering() |case ARM::B|.
206 // It is not clear why |addReg(0)| is needed (the last operand).
207 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc).addImm(20)
208 .addImm(ARMCC::AL).addReg(0));
209
210 emitNops(NoopsInSledCount);
211
212 OutStreamer->emitLabel(Target);
213 recordSled(CurSled, MI, Kind, 2);
214}
215
217{
218 EmitSled(MI, SledKind::FUNCTION_ENTER);
219}
220
222{
223 EmitSled(MI, SledKind::FUNCTION_EXIT);
224}
225
227{
228 EmitSled(MI, SledKind::TAIL_CALL);
229}
This file declares a class to represent arbitrary precision floating point values and provide a varie...
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Looks at all the uses of the given value Returns the Liveness deduced from the uses of this value Adds all uses that cause the result to be MaybeLive to MaybeLiveRetUses If the result is MaybeLiveUses might be modified but its content should be ignored(since it might not be complete). DeadArgumentEliminationPass
IRTranslator LLVM IR MI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition: APFloat.cpp:5377
double convertToDouble() const
Converts this APFloat to host double value.
Definition: APFloat.cpp:5436
MCSymbol * GetCPISymbol(unsigned CPID) const override
Return the symbol for the specified constant pool entry.
bool lowerOperand(const MachineOperand &MO, MCOperand &MCOp)
void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
static const ARMMCExpr * createLower16(const MCExpr *Expr, MCContext &Ctx)
Definition: ARMMCExpr.h:42
static const ARMMCExpr * createUpper16(const MCExpr *Expr, MCContext &Ctx)
Definition: ARMMCExpr.h:38
void emitNops(unsigned N)
Emit N NOP instructions.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:398
MCSymbol * GetJTISymbol(unsigned JTID, bool isLinkerPrivate=false) const
Return the symbol for the specified jump table entry.
void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind, uint8_t Version=0)
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:94
MCSymbol * GetExternalSymbolSymbol(StringRef Sym) const
Return the MCSymbol for the specified ExternalSymbol.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:99
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
Definition: AsmPrinter.cpp:393
const APFloat & getValueAPF() const
Definition: Constants.h:301
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:525
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:318
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
Instances of this class represent operands of the MCInst class.
Definition: MCInst.h:36
static MCOperand createReg(unsigned Reg)
Definition: MCInst.h:134
void setImm(int64_t Val)
Definition: MCInst.h:85
static MCOperand createExpr(const MCExpr *Val)
Definition: MCInst.h:162
int64_t getImm() const
Definition: MCInst.h:80
static MCOperand createImm(int64_t Val)
Definition: MCInst.h:141
bool isImm() const
Definition: MCInst.h:62
static MCOperand createDFPImm(uint64_t Val)
Definition: MCInst.h:155
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
Representation of each machine instruction.
Definition: MachineInstr.h:68
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isImplicit() const
MachineBasicBlock * getMBB() const
bool isJTI() const
isJTI - Tests if this is a MO_JumpTableIndex operand.
const BlockAddress * getBlockAddress() const
unsigned getTargetFlags() const
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
const char * getSymbolName() const
Register getReg() const
getReg - Returns the register number.
const ConstantFP * getFPImm() const
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_RegisterMask
Mask of preserved registers.
@ MO_BlockAddress
Address of a basic block.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
@ MO_ExternalSymbol
Name of external global symbol.
@ MO_JumpTableIndex
Address of indexed Jump Table for switch.
@ MO_FPImmediate
Floating-point immediate operand.
int64_t getOffset() const
Return the offset from the symbol in this operand.
Target - Wrapper for Target specific information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ MO_OPTION_MASK
MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects just that part of the flag set.
Definition: ARMBaseInfo.h:258
@ MO_LO16
MO_LO16 - On a symbol operand, this represents a relocation containing lower 16 bit of the address.
Definition: ARMBaseInfo.h:250
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
Definition: ARMBaseInfo.h:270
@ MO_HI16
MO_HI16 - On a symbol operand, this represents a relocation containing higher 16 bit of the address.
Definition: ARMBaseInfo.h:254
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP)
static constexpr roundingMode rmTowardZero
Definition: APFloat.h:221
static const fltSemantics & IEEEdouble() LLVM_READNONE
Definition: APFloat.cpp:247
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39