blob: d5848e6cd069cb8044d6e8b410b1ba946d2adf91 [file] [log] [blame]
Chris Lattner78393d72009-10-19 20:21:05 +00001//===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains code to lower ARM MachineInstrs to their corresponding
11// MCInst records.
12//
13//===----------------------------------------------------------------------===//
14
Chris Lattnerb28e6912010-11-14 20:31:06 +000015#include "ARM.h"
Jim Grosbachd0d13292010-12-01 03:45:07 +000016#include "ARMAsmPrinter.h"
Craig Toppera9253262014-03-22 23:51:00 +000017#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chenga20cde32011-07-20 23:34:39 +000018#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattner1b06acb2009-10-20 00:52:47 +000019#include "llvm/CodeGen/MachineBasicBlock.h"
Chandler Carruth9fb823b2013-01-02 11:36:10 +000020#include "llvm/IR/Constants.h"
Rafael Espindola894843c2014-01-07 21:19:40 +000021#include "llvm/IR/Mangler.h"
Chris Lattner889a6212009-10-19 21:53:00 +000022#include "llvm/MC/MCExpr.h"
Chris Lattner78393d72009-10-19 20:21:05 +000023#include "llvm/MC/MCInst.h"
Dean Michael Berris464015442016-09-19 00:54:35 +000024#include "llvm/MC/MCContext.h"
25#include "llvm/MC/MCSymbolELF.h"
26#include "llvm/MC/MCSectionELF.h"
Kuba Mracek06995e82016-11-23 02:07:04 +000027#include "llvm/MC/MCSectionMachO.h"
Dean Michael Berris464015442016-09-19 00:54:35 +000028#include "llvm/MC/MCInstBuilder.h"
29#include "llvm/MC/MCStreamer.h"
Chris Lattner78393d72009-10-19 20:21:05 +000030using namespace llvm;
31
Chris Lattnerc5afd122010-11-14 20:58:38 +000032
Jim Grosbach95dee402011-07-08 17:40:42 +000033MCOperand ARMAsmPrinter::GetSymbolRef(const MachineOperand &MO,
34 const MCSymbol *Symbol) {
Aaron Ballman86100fc2016-06-20 15:37:15 +000035 const MCExpr *Expr =
36 MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
37 switch (MO.getTargetFlags() & ARMII::MO_OPTION_MASK) {
38 default:
39 llvm_unreachable("Unknown target flag on symbol operand");
40 case ARMII::MO_NO_FLAG:
Chris Lattner3040e8c2010-11-14 20:40:08 +000041 break;
Aaron Ballman86100fc2016-06-20 15:37:15 +000042 case ARMII::MO_LO16:
43 Expr =
44 MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
45 Expr = ARMMCExpr::createLower16(Expr, OutContext);
46 break;
47 case ARMII::MO_HI16:
48 Expr =
49 MCSymbolRefExpr::create(Symbol, MCSymbolRefExpr::VK_None, OutContext);
50 Expr = ARMMCExpr::createUpper16(Expr, OutContext);
51 break;
Chris Lattner3040e8c2010-11-14 20:40:08 +000052 }
Jim Grosbach38d90de2010-11-30 23:29:24 +000053
Jim Grosbach0d35df12010-09-17 18:25:25 +000054 if (!MO.isJTI() && MO.getOffset())
Jim Grosbach13760bd2015-05-30 01:25:56 +000055 Expr = MCBinaryExpr::createAdd(Expr,
56 MCConstantExpr::create(MO.getOffset(),
Jim Grosbach95dee402011-07-08 17:40:42 +000057 OutContext),
58 OutContext);
Jim Grosbache9119e42015-05-13 18:37:00 +000059 return MCOperand::createExpr(Expr);
Jim Grosbach38d90de2010-11-30 23:29:24 +000060
Jim Grosbach0d35df12010-09-17 18:25:25 +000061}
62
Jim Grosbach95dee402011-07-08 17:40:42 +000063bool ARMAsmPrinter::lowerOperand(const MachineOperand &MO,
64 MCOperand &MCOp) {
65 switch (MO.getType()) {
Craig Toppere55c5562012-02-07 02:50:20 +000066 default: llvm_unreachable("unknown operand type");
Jim Grosbach95dee402011-07-08 17:40:42 +000067 case MachineOperand::MO_Register:
68 // Ignore all non-CPSR implicit register operands.
69 if (MO.isImplicit() && MO.getReg() != ARM::CPSR)
70 return false;
71 assert(!MO.getSubReg() && "Subregs should be eliminated!");
Jim Grosbache9119e42015-05-13 18:37:00 +000072 MCOp = MCOperand::createReg(MO.getReg());
Jim Grosbach95dee402011-07-08 17:40:42 +000073 break;
74 case MachineOperand::MO_Immediate:
Jim Grosbache9119e42015-05-13 18:37:00 +000075 MCOp = MCOperand::createImm(MO.getImm());
Jim Grosbach95dee402011-07-08 17:40:42 +000076 break;
77 case MachineOperand::MO_MachineBasicBlock:
Jim Grosbach13760bd2015-05-30 01:25:56 +000078 MCOp = MCOperand::createExpr(MCSymbolRefExpr::create(
Jim Grosbach95dee402011-07-08 17:40:42 +000079 MO.getMBB()->getSymbol(), OutContext));
80 break;
Tim Northoverdb962e2c2013-11-25 16:24:52 +000081 case MachineOperand::MO_GlobalAddress: {
82 MCOp = GetSymbolRef(MO,
83 GetARMGVSymbol(MO.getGlobal(), MO.getTargetFlags()));
Jim Grosbach95dee402011-07-08 17:40:42 +000084 break;
Tim Northoverdb962e2c2013-11-25 16:24:52 +000085 }
Jim Grosbach95dee402011-07-08 17:40:42 +000086 case MachineOperand::MO_ExternalSymbol:
Etienne Bergeron715ec092016-06-21 15:21:04 +000087 MCOp = GetSymbolRef(MO,
Jim Grosbach95dee402011-07-08 17:40:42 +000088 GetExternalSymbolSymbol(MO.getSymbolName()));
89 break;
90 case MachineOperand::MO_JumpTableIndex:
91 MCOp = GetSymbolRef(MO, GetJTISymbol(MO.getIndex()));
92 break;
93 case MachineOperand::MO_ConstantPoolIndex:
94 MCOp = GetSymbolRef(MO, GetCPISymbol(MO.getIndex()));
95 break;
96 case MachineOperand::MO_BlockAddress:
97 MCOp = GetSymbolRef(MO, GetBlockAddressSymbol(MO.getBlockAddress()));
98 break;
99 case MachineOperand::MO_FPImmediate: {
100 APFloat Val = MO.getFPImm()->getValueAPF();
101 bool ignored;
Stephan Bergmann17c7f702016-12-14 11:57:17 +0000102 Val.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &ignored);
Jim Grosbache9119e42015-05-13 18:37:00 +0000103 MCOp = MCOperand::createFPImm(Val.convertToDouble());
Jim Grosbach95dee402011-07-08 17:40:42 +0000104 break;
105 }
Jakob Stoklund Olesenf1fb1d22012-01-18 23:52:19 +0000106 case MachineOperand::MO_RegisterMask:
107 // Ignore call clobbers.
108 return false;
Jim Grosbach95dee402011-07-08 17:40:42 +0000109 }
110 return true;
111}
112
Chris Lattnerde16ca82010-11-14 21:00:02 +0000113void llvm::LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI,
Jim Grosbachd0d13292010-12-01 03:45:07 +0000114 ARMAsmPrinter &AP) {
Chris Lattner78393d72009-10-19 20:21:05 +0000115 OutMI.setOpcode(MI->getOpcode());
Jim Grosbach7aeff132010-09-13 18:25:42 +0000116
Asiri Rathnayakea0199b92014-12-02 10:53:20 +0000117 // In the MC layer, we keep modified immediates in their encoded form
118 bool EncodeImms = false;
119 switch (MI->getOpcode()) {
120 default: break;
121 case ARM::MOVi:
122 case ARM::MVNi:
123 case ARM::CMPri:
124 case ARM::CMNri:
125 case ARM::TSTri:
126 case ARM::TEQri:
127 case ARM::MSRi:
128 case ARM::ADCri:
129 case ARM::ADDri:
130 case ARM::ADDSri:
131 case ARM::SBCri:
132 case ARM::SUBri:
133 case ARM::SUBSri:
134 case ARM::ANDri:
135 case ARM::ORRri:
136 case ARM::EORri:
137 case ARM::BICri:
138 case ARM::RSBri:
139 case ARM::RSBSri:
140 case ARM::RSCri:
141 EncodeImms = true;
142 break;
143 }
144
Chris Lattner78393d72009-10-19 20:21:05 +0000145 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
146 const MachineOperand &MO = MI->getOperand(i);
Jim Grosbach7aeff132010-09-13 18:25:42 +0000147
Chris Lattner78393d72009-10-19 20:21:05 +0000148 MCOperand MCOp;
Asiri Rathnayakea0199b92014-12-02 10:53:20 +0000149 if (AP.lowerOperand(MO, MCOp)) {
150 if (MCOp.isImm() && EncodeImms) {
151 int32_t Enc = ARM_AM::getSOImmVal(MCOp.getImm());
152 if (Enc != -1)
153 MCOp.setImm(Enc);
154 }
Jim Grosbach95dee402011-07-08 17:40:42 +0000155 OutMI.addOperand(MCOp);
Asiri Rathnayakea0199b92014-12-02 10:53:20 +0000156 }
Chris Lattner78393d72009-10-19 20:21:05 +0000157 }
Chris Lattner78393d72009-10-19 20:21:05 +0000158}
Dean Michael Berris464015442016-09-19 00:54:35 +0000159
160void ARMAsmPrinter::EmitSled(const MachineInstr &MI, SledKind Kind)
161{
162 if (MI.getParent()->getParent()->getInfo<ARMFunctionInfo>()
163 ->isThumbFunction())
164 {
165 MI.emitError("An attempt to perform XRay instrumentation for a"
166 " Thumb function (not supported). Detected when emitting a sled.");
167 return;
168 }
169 static const int8_t NoopsInSledCount = 6;
170 // We want to emit the following pattern:
171 //
172 // .Lxray_sled_N:
173 // ALIGN
174 // B #20
175 // ; 6 NOP instructions (24 bytes)
176 // .tmpN
177 //
178 // We need the 24 bytes (6 instructions) because at runtime, we'd be patching
179 // over the full 28 bytes (7 instructions) with the following pattern:
180 //
181 // PUSH{ r0, lr }
182 // MOVW r0, #<lower 16 bits of function ID>
183 // MOVT r0, #<higher 16 bits of function ID>
184 // MOVW ip, #<lower 16 bits of address of __xray_FunctionEntry/Exit>
185 // MOVT ip, #<higher 16 bits of address of __xray_FunctionEntry/Exit>
186 // BLX ip
187 // POP{ r0, lr }
188 //
189 OutStreamer->EmitCodeAlignment(4);
190 auto CurSled = OutContext.createTempSymbol("xray_sled_", true);
191 OutStreamer->EmitLabel(CurSled);
192 auto Target = OutContext.createTempSymbol();
193
194 // Emit "B #20" instruction, which jumps over the next 24 bytes (because
195 // register pc is 8 bytes ahead of the jump instruction by the moment CPU
196 // is executing it).
197 // By analogy to ARMAsmPrinter::emitPseudoExpansionLowering() |case ARM::B|.
198 // It is not clear why |addReg(0)| is needed (the last operand).
199 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc).addImm(20)
200 .addImm(ARMCC::AL).addReg(0));
201
202 MCInst Noop;
203 Subtarget->getInstrInfo()->getNoopForElfTarget(Noop);
204 for (int8_t I = 0; I < NoopsInSledCount; I++)
205 {
206 OutStreamer->EmitInstruction(Noop, getSubtargetInfo());
207 }
208
209 OutStreamer->EmitLabel(Target);
210 recordSled(CurSled, MI, Kind);
211}
212
213void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
214{
215 EmitSled(MI, SledKind::FUNCTION_ENTER);
216}
217
218void ARMAsmPrinter::LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
219{
220 EmitSled(MI, SledKind::FUNCTION_EXIT);
221}
222
Dean Michael Berris156f6ca2016-10-18 05:54:15 +0000223void ARMAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
224{
225 EmitSled(MI, SledKind::TAIL_CALL);
226}
227
Dean Michael Berris464015442016-09-19 00:54:35 +0000228void ARMAsmPrinter::EmitXRayTable()
229{
230 if (Sleds.empty())
231 return;
Kuba Mracek06995e82016-11-23 02:07:04 +0000232
233 MCSection *Section = nullptr;
Dean Michael Berris464015442016-09-19 00:54:35 +0000234 if (Subtarget->isTargetELF()) {
Kuba Mracek06995e82016-11-23 02:07:04 +0000235 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
236 ELF::SHF_ALLOC | ELF::SHF_GROUP |
237 ELF::SHF_MERGE,
238 0, CurrentFnSym->getName());
239 } else if (Subtarget->isTargetMachO()) {
240 Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
241 SectionKind::getReadOnlyWithRel());
242 } else {
243 llvm_unreachable("Unsupported target");
Dean Michael Berris464015442016-09-19 00:54:35 +0000244 }
Kuba Mracek06995e82016-11-23 02:07:04 +0000245
246 auto PrevSection = OutStreamer->getCurrentSectionOnly();
247 OutStreamer->SwitchSection(Section);
248 for (const auto &Sled : Sleds) {
249 OutStreamer->EmitSymbolValue(Sled.Sled, 4);
250 OutStreamer->EmitSymbolValue(CurrentFnSym, 4);
251 auto Kind = static_cast<uint8_t>(Sled.Kind);
252 OutStreamer->EmitBytes(
253 StringRef(reinterpret_cast<const char *>(&Kind), 1));
254 OutStreamer->EmitBytes(
255 StringRef(reinterpret_cast<const char *>(&Sled.AlwaysInstrument), 1));
256 OutStreamer->EmitZeros(6);
257 }
258 OutStreamer->SwitchSection(PrevSection);
259
Dean Michael Berris464015442016-09-19 00:54:35 +0000260 Sleds.clear();
261}