LLVM 22.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) {
43
44 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);
46 default:
47 llvm_unreachable("Unknown target flag on symbol operand");
49 break;
50 case ARMII::MO_LO16:
51 Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);
52 Expr = ARM::createLower16(Expr, OutContext);
53 break;
54 case ARMII::MO_HI16:
55 Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);
56 Expr = ARM::createUpper16(Expr, OutContext);
57 break;
59 Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);
60 Expr = ARM::createLower0_7(Expr, OutContext);
61 break;
63 Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);
64 Expr = ARM::createLower8_15(Expr, OutContext);
65 break;
67 Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);
68 Expr = ARM::createUpper0_7(Expr, OutContext);
69 break;
71 Expr = MCSymbolRefExpr::create(Symbol, Specifier, OutContext);
72 Expr = ARM::createUpper8_15(Expr, OutContext);
73 break;
74 }
75
76 if (!MO.isJTI() && MO.getOffset())
77 Expr = MCBinaryExpr::createAdd(Expr,
81 return MCOperand::createExpr(Expr);
82
83}
84
86 MCOperand &MCOp) {
87 switch (MO.getType()) {
88 default: llvm_unreachable("unknown operand type");
90 // Ignore all implicit register operands.
91 if (MO.isImplicit())
92 return false;
93 assert(!MO.getSubReg() && "Subregs should be eliminated!");
94 MCOp = MCOperand::createReg(MO.getReg());
95 break;
97 MCOp = MCOperand::createImm(MO.getImm());
98 break;
101 MO.getMBB()->getSymbol(), OutContext));
102 break;
104 MCOp = GetSymbolRef(MO,
105 GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags()));
106 break;
108 MCOp = GetSymbolRef(MO,
110 break;
112 MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
113 break;
115 if (Subtarget->genExecuteOnly())
116 llvm_unreachable("execute-only should not generate constant pools");
117 MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
118 break;
120 MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));
121 break;
123 APFloat Val = MO.getFPImm()->getValueAPF();
124 bool ignored;
127 break;
128 }
130 // Ignore call clobbers.
131 return false;
132 }
133 return true;
134}
135
137 ARMAsmPrinter &AP) {
138 OutMI.setOpcode(MI->getOpcode());
139
140 // In the MC layer, we keep modified immediates in their encoded form
141 bool EncodeImms = false;
142 switch (MI->getOpcode()) {
143 default: break;
144 case ARM::MOVi:
145 case ARM::MVNi:
146 case ARM::CMPri:
147 case ARM::CMNri:
148 case ARM::TSTri:
149 case ARM::TEQri:
150 case ARM::MSRi:
151 case ARM::ADCri:
152 case ARM::ADDri:
153 case ARM::ADDSri:
154 case ARM::SBCri:
155 case ARM::SUBri:
156 case ARM::SUBSri:
157 case ARM::ANDri:
158 case ARM::ORRri:
159 case ARM::EORri:
160 case ARM::BICri:
161 case ARM::RSBri:
162 case ARM::RSBSri:
163 case ARM::RSCri:
164 EncodeImms = true;
165 break;
166 }
167
168 for (const MachineOperand &MO : MI->operands()) {
169 MCOperand MCOp;
170 if (AP.lowerOperand(MO, MCOp)) {
171 if (MCOp.isImm() && EncodeImms) {
172 int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());
173 if (Enc != -1)
174 MCOp.setImm(Enc);
175 }
176 OutMI.addOperand(MCOp);
177 }
178 }
179}
180
181void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
182{
183 const MachineFunction *MF = MI.getParent()->getParent();
185 const Function &Fn = MF->getFunction();
187 Fn,
188 "An attempt to perform XRay instrumentation for a Thumb function (not "
189 "supported). Detected when emitting a sled.",
190 MI.getDebugLoc()));
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);
216 auto Target = OutContext.createTempSymbol();
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
236
241
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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...
IRTranslator LLVM IR MI
LLVM_ABI opStatus convert(const fltSemantics &ToSemantics, roundingMode RM, bool *losesInfo)
Definition APFloat.cpp:6057
LLVM_ABI double convertToDouble() const
Converts this APFloat to host double value.
Definition APFloat.cpp:6115
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...
void emitNops(unsigned N)
Emit N NOP instructions.
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:108
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:100
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:105
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
const APFloat & getValueAPF() const
Definition Constants.h:320
Diagnostic information for unsupported feature in backend.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:359
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:343
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
void setImm(int64_t Val)
Definition MCInst.h:89
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
int64_t getImm() const
Definition MCInst.h:84
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
bool isImm() const
Definition MCInst.h:66
static MCOperand createDFPImm(uint64_t Val)
Definition MCInst.h:159
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
Representation of each machine instruction.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const GlobalValue * getGlobal() const
int64_t getImm() 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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
@ MO_OPTION_MASK
MO_OPTION_MASK - Most flags are mutually exclusive; this mask selects just that part of the flag set.
@ MO_LO16
MO_LO16 - On a symbol operand, this represents a relocation containing lower 16 bit of the address.
@ MO_LO_0_7
MO_LO_0_7 - On a symbol operand, this represents a relocation containing bits 0 through 7 of the addr...
@ MO_LO_8_15
MO_LO_8_15 - On a symbol operand, this represents a relocation containing bits 8 through 15 of the ad...
@ MO_HI_8_15
MO_HI_8_15 - On a symbol operand, this represents a relocation containing bits 24 through 31 of the a...
@ MO_SBREL
MO_SBREL - On a symbol operand, this represents a static base relative relocation.
@ MO_HI16
MO_HI16 - On a symbol operand, this represents a relocation containing higher 16 bit of the address.
@ MO_HI_0_7
MO_HI_0_7 - On a symbol operand, this represents a relocation containing bits 16 through 23 of the ad...
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
const MCSpecifierExpr * createUpper0_7(const MCExpr *Expr, MCContext &Ctx)
const MCSpecifierExpr * createUpper8_15(const MCExpr *Expr, MCContext &Ctx)
const MCSpecifierExpr * createLower16(const MCExpr *Expr, MCContext &Ctx)
const MCSpecifierExpr * createLower0_7(const MCExpr *Expr, MCContext &Ctx)
const MCSpecifierExpr * createLower8_15(const MCExpr *Expr, MCContext &Ctx)
const MCSpecifierExpr * createUpper16(const MCExpr *Expr, MCContext &Ctx)
This is an optimization pass for GlobalISel generic memory operations.
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP)
To bit_cast(const From &from) noexcept
Definition bit.h:90
static constexpr roundingMode rmTowardZero
Definition APFloat.h:308
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE
Definition APFloat.cpp:267