LLVM 20.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;
62 Expr = MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
64 break;
66 Expr = MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
68 break;
70 Expr = MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
72 break;
74 Expr = MCSymbolRefExpr::create(Symbol, SymbolVariant, OutContext);
76 break;
77 }
78
79 if (!MO.isJTI() && MO.getOffset())
80 Expr = MCBinaryExpr::createAdd(Expr,
84 return MCOperand::createExpr(Expr);
85
86}
87
89 MCOperand &MCOp) {
90 switch (MO.getType()) {
91 default: llvm_unreachable("unknown operand type");
93 // Ignore all implicit register operands.
94 if (MO.isImplicit())
95 return false;
96 assert(!MO.getSubReg() && "Subregs should be eliminated!");
97 MCOp = MCOperand::createReg(MO.getReg());
98 break;
100 MCOp = MCOperand::createImm(MO.getImm());
101 break;
104 MO.getMBB()->getSymbol(), OutContext));
105 break;
107 MCOp = GetSymbolRef(MO,
108 GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags()));
109 break;
111 MCOp = GetSymbolRef(MO,
113 break;
115 MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
116 break;
118 if (Subtarget->genExecuteOnly())
119 llvm_unreachable("execute-only should not generate constant pools");
120 MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
121 break;
123 MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));
124 break;
126 APFloat Val = MO.getFPImm()->getValueAPF();
127 bool ignored;
129 MCOp = MCOperand::createDFPImm(bit_cast<uint64_t>(Val.convertToDouble()));
130 break;
131 }
133 // Ignore call clobbers.
134 return false;
135 }
136 return true;
137}
138
140 ARMAsmPrinter &AP) {
141 OutMI.setOpcode(MI->getOpcode());
142
143 // In the MC layer, we keep modified immediates in their encoded form
144 bool EncodeImms = false;
145 switch (MI->getOpcode()) {
146 default: break;
147 case ARM::MOVi:
148 case ARM::MVNi:
149 case ARM::CMPri:
150 case ARM::CMNri:
151 case ARM::TSTri:
152 case ARM::TEQri:
153 case ARM::MSRi:
154 case ARM::ADCri:
155 case ARM::ADDri:
156 case ARM::ADDSri:
157 case ARM::SBCri:
158 case ARM::SUBri:
159 case ARM::SUBSri:
160 case ARM::ANDri:
161 case ARM::ORRri:
162 case ARM::EORri:
163 case ARM::BICri:
164 case ARM::RSBri:
165 case ARM::RSBSri:
166 case ARM::RSCri:
167 EncodeImms = true;
168 break;
169 }
170
171 for (const MachineOperand &MO : MI->operands()) {
172 MCOperand MCOp;
173 if (AP.lowerOperand(MO, MCOp)) {
174 if (MCOp.isImm() && EncodeImms) {
175 int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());
176 if (Enc != -1)
177 MCOp.setImm(Enc);
178 }
179 OutMI.addOperand(MCOp);
180 }
181 }
182}
183
184void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
185{
186 if (MI.getParent()->getParent()->getInfo<ARMFunctionInfo>()
187 ->isThumbFunction())
188 {
189 MI.emitError("An attempt to perform XRay instrumentation for a"
190 " Thumb function (not supported). Detected when emitting a sled.");
191 return;
192 }
193 static const int8_t NoopsInSledCount = 6;
194 // We want to emit the following pattern:
195 //
196 // .Lxray_sled_N:
197 // ALIGN
198 // B #20
199 // ; 6 NOP instructions (24 bytes)
200 // .tmpN
201 //
202 // We need the 24 bytes (6 instructions) because at runtime, we'd be patching
203 // over the full 28 bytes (7 instructions) with the following pattern:
204 //
205 // PUSH{ r0, lr }
206 // MOVW r0, #<lower 16 bits of function ID>
207 // MOVT r0, #<higher 16 bits of function ID>
208 // MOVW ip, #<lower 16 bits of address of __xray_FunctionEntry/Exit>
209 // MOVT ip, #<higher 16 bits of address of __xray_FunctionEntry/Exit>
210 // BLX ip
211 // POP{ r0, lr }
212 //
213 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
214 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
215 OutStreamer->emitLabel(CurSled);
217
218 // Emit "B #20" instruction, which jumps over the next 24 bytes (because
219 // register pc is 8 bytes ahead of the jump instruction by the moment CPU
220 // is executing it).
221 // By analogy to ARMAsmPrinter::lowerPseudoInstExpansion() |case ARM::B|.
222 // It is not clear why |addReg(0)| is needed (the last operand).
223 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc).addImm(20)
224 .addImm(ARMCC::AL).addReg(0));
225
226 emitNops(NoopsInSledCount);
227
228 OutStreamer->emitLabel(Target);
229 recordSled(CurSled, MI, Kind, 2);
230}
231
233{
234 EmitSled(MI, SledKind::FUNCTION_ENTER);
235}
236
238{
239 EmitSled(MI, SledKind::FUNCTION_EXIT);
240}
241
243{
244 EmitSled(MI, SledKind::TAIL_CALL);
245}
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:5337
double convertToDouble() const
Converts this APFloat to host double value.
Definition: APFloat.cpp:5396
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 * createUpper8_15(const MCExpr *Expr, MCContext &Ctx)
Definition: ARMMCExpr.h:55
static const ARMMCExpr * createLower0_7(const MCExpr *Expr, MCContext &Ctx)
Definition: ARMMCExpr.h:67
static const ARMMCExpr * createUpper0_7(const MCExpr *Expr, MCContext &Ctx)
Definition: ARMMCExpr.h:59
static const ARMMCExpr * createLower16(const MCExpr *Expr, MCContext &Ctx)
Definition: ARMMCExpr.h:51
static const ARMMCExpr * createUpper16(const MCExpr *Expr, MCContext &Ctx)
Definition: ARMMCExpr.h:47
static const ARMMCExpr * createLower8_15(const MCExpr *Expr, MCContext &Ctx)
Definition: ARMMCExpr.h:63
void emitNops(unsigned N)
Emit N NOP instructions.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
Definition: AsmPrinter.cpp:403
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:96
MCSymbol * GetExternalSymbolSymbol(Twine 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:101
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:398
const APFloat & getValueAPF() const
Definition: Constants.h:312
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:532
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:193
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:346
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
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:393
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:69
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_LO_0_7
MO_LO_0_7 - On a symbol operand, this represents a relocation containing bits 0 through 7 of the addr...
Definition: ARMBaseInfo.h:293
@ MO_LO_8_15
MO_LO_8_15 - On a symbol operand, this represents a relocation containing bits 8 through 15 of the ad...
Definition: ARMBaseInfo.h:299
@ MO_HI_8_15
MO_HI_8_15 - On a symbol operand, this represents a relocation containing bits 24 through 31 of the a...
Definition: ARMBaseInfo.h:310
@ 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
@ MO_HI_0_7
MO_HI_0_7 - On a symbol operand, this represents a relocation containing bits 16 through 23 of the ad...
Definition: ARMBaseInfo.h:304
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:258
static const fltSemantics & IEEEdouble() LLVM_READNONE
Definition: APFloat.cpp:282
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39