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;
126 MCOp = MCOperand::createDFPImm(bit_cast<uint64_t>(Val.convertToDouble()));
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);
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}
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...
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
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)
Definition: AsmPrinter.cpp:433
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.
Definition: AsmPrinter.cpp:428
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
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:386
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: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.
Definition: MachineInstr.h:72
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...
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.
Definition: AddressRanges.h:18
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP)
static constexpr roundingMode rmTowardZero
Definition: APFloat.h:308
static LLVM_ABI const fltSemantics & IEEEdouble() LLVM_READNONE
Definition: APFloat.cpp:267
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39