LLVM 22.0.0git
ARMMCTargetDesc.cpp
Go to the documentation of this file.
1//===-- ARMMCTargetDesc.cpp - ARM Target Descriptions ---------------------===//
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 provides ARM specific target descriptions.
10//
11//===----------------------------------------------------------------------===//
12
13#include "ARMMCTargetDesc.h"
14#include "ARMAddressingModes.h"
15#include "ARMBaseInfo.h"
16#include "ARMInstPrinter.h"
17#include "ARMMCAsmInfo.h"
24#include "llvm/MC/MCInstrInfo.h"
27#include "llvm/MC/MCStreamer.h"
33
34using namespace llvm;
35
36#define GET_REGINFO_MC_DESC
37#include "ARMGenRegisterInfo.inc"
38
40 std::string &Info) {
41 if (STI.hasFeature(llvm::ARM::HasV7Ops) &&
42 (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 15) &&
43 (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 0) &&
44 // Checks for the deprecated CP15ISB encoding:
45 // mcr p15, #0, rX, c7, c5, #4
46 (MI.getOperand(3).isImm() && MI.getOperand(3).getImm() == 7)) {
47 if ((MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 4)) {
48 if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 5) {
49 Info = "deprecated since v7, use 'isb'";
50 return true;
51 }
52
53 // Checks for the deprecated CP15DSB encoding:
54 // mcr p15, #0, rX, c7, c10, #4
55 if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10) {
56 Info = "deprecated since v7, use 'dsb'";
57 return true;
58 }
59 }
60 // Checks for the deprecated CP15DMB encoding:
61 // mcr p15, #0, rX, c7, c10, #5
62 if (MI.getOperand(4).isImm() && MI.getOperand(4).getImm() == 10 &&
63 (MI.getOperand(5).isImm() && MI.getOperand(5).getImm() == 5)) {
64 Info = "deprecated since v7, use 'dmb'";
65 return true;
66 }
67 }
68 if (STI.hasFeature(llvm::ARM::HasV7Ops) &&
69 ((MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 10) ||
70 (MI.getOperand(0).isImm() && MI.getOperand(0).getImm() == 11))) {
71 Info = "since v7, cp10 and cp11 are reserved for advanced SIMD or floating "
72 "point instructions";
73 return true;
74 }
75 return false;
76}
77
79 std::string &Info) {
80 if (STI.hasFeature(llvm::ARM::HasV7Ops) &&
81 ((MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 10) ||
82 (MI.getOperand(1).isImm() && MI.getOperand(1).getImm() == 11))) {
83 Info = "since v7, cp10 and cp11 are reserved for advanced SIMD or floating "
84 "point instructions";
85 return true;
86 }
87 return false;
88}
89
91 std::string &Info) {
92 assert(!STI.hasFeature(llvm::ARM::ModeThumb) &&
93 "cannot predicate thumb instructions");
94
95 assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
96 for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
97 assert(MI.getOperand(OI).isReg() && "expected register");
98 if (MI.getOperand(OI).getReg() == ARM::PC) {
99 Info = "use of PC in the list is deprecated";
100 return true;
101 }
102 }
103 return false;
104}
105
107 std::string &Info) {
108 assert(!STI.hasFeature(llvm::ARM::ModeThumb) &&
109 "cannot predicate thumb instructions");
110
111 assert(MI.getNumOperands() >= 4 && "expected >= 4 arguments");
112 bool ListContainsPC = false, ListContainsLR = false;
113 for (unsigned OI = 4, OE = MI.getNumOperands(); OI < OE; ++OI) {
114 assert(MI.getOperand(OI).isReg() && "expected register");
115 switch (MI.getOperand(OI).getReg().id()) {
116 default:
117 break;
118 case ARM::LR:
119 ListContainsLR = true;
120 break;
121 case ARM::PC:
122 ListContainsPC = true;
123 break;
124 }
125 }
126
127 if (ListContainsPC && ListContainsLR) {
128 Info = "use of LR and PC simultaneously in the list is deprecated";
129 return true;
130 }
131
132 return false;
133}
134
135#define GET_INSTRINFO_MC_DESC
136#define ENABLE_INSTR_PREDICATE_VERIFIER
137#include "ARMGenInstrInfo.inc"
138
139#define GET_SUBTARGETINFO_MC_DESC
140#include "ARMGenSubtargetInfo.inc"
141
142std::string ARM_MC::ParseARMTriple(const Triple &TT, StringRef CPU) {
143 std::string ARMArchFeature;
144
145 ARM::ArchKind ArchID = ARM::parseArch(TT.getArchName());
146 if (ArchID != ARM::ArchKind::INVALID && (CPU.empty() || CPU == "generic"))
147 ARMArchFeature = (ARMArchFeature + "+" + ARM::getArchName(ArchID)).str();
148
149 if (TT.isThumb()) {
150 if (!ARMArchFeature.empty())
151 ARMArchFeature += ",";
152 ARMArchFeature += "+thumb-mode,+v4t";
153 }
154
155 if (TT.isOSWindows()) {
156 if (!ARMArchFeature.empty())
157 ARMArchFeature += ",";
158 ARMArchFeature += "+noarm";
159 }
160
161 return ARMArchFeature;
162}
163
164bool ARM_MC::isPredicated(const MCInst &MI, const MCInstrInfo *MCII) {
165 const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
166 int PredOpIdx = Desc.findFirstPredOperandIdx();
167 return PredOpIdx != -1 && MI.getOperand(PredOpIdx).getImm() != ARMCC::AL;
168}
169
170bool ARM_MC::isCPSRDefined(const MCInst &MI, const MCInstrInfo *MCII) {
171 const MCInstrDesc &Desc = MCII->get(MI.getOpcode());
172 for (unsigned I = 0; I < MI.getNumOperands(); ++I) {
173 const MCOperand &MO = MI.getOperand(I);
174 if (MO.isReg() && MO.getReg() == ARM::CPSR &&
175 Desc.operands()[I].isOptionalDef())
176 return true;
177 }
178 return false;
179}
180
182 uint64_t Addr, int64_t Imm) {
183 // For ARM instructions the PC offset is 8 bytes, for Thumb instructions it
184 // is 4 bytes.
186 ((InstDesc.TSFlags & ARMII::FormMask) == ARMII::ThumbFrm) ? 4 : 8;
187
188 // A Thumb instruction BLX(i) can be 16-bit aligned while targets Arm code
189 // which is 32-bit aligned. The target address for the case is calculated as
190 // targetAddress = Align(PC,4) + imm32;
191 // where
192 // Align(x, y) = y * (x DIV y);
193 if (InstDesc.getOpcode() == ARM::tBLXi)
194 Addr &= ~0x3;
195
196 return Addr + Imm + Offset;
197}
198
200 StringRef CPU, StringRef FS) {
201 std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
202 if (!FS.empty()) {
203 if (!ArchFS.empty())
204 ArchFS = (Twine(ArchFS) + "," + FS).str();
205 else
206 ArchFS = std::string(FS);
207 }
208
209 return createARMMCSubtargetInfoImpl(TT, CPU, /*TuneCPU*/ CPU, ArchFS);
210}
211
213 MCInstrInfo *X = new MCInstrInfo();
214 InitARMMCInstrInfo(X);
215 return X;
216}
217
219 // Mapping from CodeView to MC register id.
220 static const struct {
222 MCPhysReg Reg;
223 } RegMap[] = {
224 {codeview::RegisterId::ARM_R0, ARM::R0},
225 {codeview::RegisterId::ARM_R1, ARM::R1},
226 {codeview::RegisterId::ARM_R2, ARM::R2},
227 {codeview::RegisterId::ARM_R3, ARM::R3},
228 {codeview::RegisterId::ARM_R4, ARM::R4},
229 {codeview::RegisterId::ARM_R5, ARM::R5},
230 {codeview::RegisterId::ARM_R6, ARM::R6},
231 {codeview::RegisterId::ARM_R7, ARM::R7},
232 {codeview::RegisterId::ARM_R8, ARM::R8},
233 {codeview::RegisterId::ARM_R9, ARM::R9},
234 {codeview::RegisterId::ARM_R10, ARM::R10},
235 {codeview::RegisterId::ARM_R11, ARM::R11},
236 {codeview::RegisterId::ARM_R12, ARM::R12},
237 {codeview::RegisterId::ARM_SP, ARM::SP},
238 {codeview::RegisterId::ARM_LR, ARM::LR},
239 {codeview::RegisterId::ARM_PC, ARM::PC},
240 {codeview::RegisterId::ARM_CPSR, ARM::CPSR},
241 {codeview::RegisterId::ARM_FPSCR, ARM::FPSCR},
242 {codeview::RegisterId::ARM_FPEXC, ARM::FPEXC},
243 {codeview::RegisterId::ARM_FS0, ARM::S0},
244 {codeview::RegisterId::ARM_FS1, ARM::S1},
245 {codeview::RegisterId::ARM_FS2, ARM::S2},
246 {codeview::RegisterId::ARM_FS3, ARM::S3},
247 {codeview::RegisterId::ARM_FS4, ARM::S4},
248 {codeview::RegisterId::ARM_FS5, ARM::S5},
249 {codeview::RegisterId::ARM_FS6, ARM::S6},
250 {codeview::RegisterId::ARM_FS7, ARM::S7},
251 {codeview::RegisterId::ARM_FS8, ARM::S8},
252 {codeview::RegisterId::ARM_FS9, ARM::S9},
253 {codeview::RegisterId::ARM_FS10, ARM::S10},
254 {codeview::RegisterId::ARM_FS11, ARM::S11},
255 {codeview::RegisterId::ARM_FS12, ARM::S12},
256 {codeview::RegisterId::ARM_FS13, ARM::S13},
257 {codeview::RegisterId::ARM_FS14, ARM::S14},
258 {codeview::RegisterId::ARM_FS15, ARM::S15},
259 {codeview::RegisterId::ARM_FS16, ARM::S16},
260 {codeview::RegisterId::ARM_FS17, ARM::S17},
261 {codeview::RegisterId::ARM_FS18, ARM::S18},
262 {codeview::RegisterId::ARM_FS19, ARM::S19},
263 {codeview::RegisterId::ARM_FS20, ARM::S20},
264 {codeview::RegisterId::ARM_FS21, ARM::S21},
265 {codeview::RegisterId::ARM_FS22, ARM::S22},
266 {codeview::RegisterId::ARM_FS23, ARM::S23},
267 {codeview::RegisterId::ARM_FS24, ARM::S24},
268 {codeview::RegisterId::ARM_FS25, ARM::S25},
269 {codeview::RegisterId::ARM_FS26, ARM::S26},
270 {codeview::RegisterId::ARM_FS27, ARM::S27},
271 {codeview::RegisterId::ARM_FS28, ARM::S28},
272 {codeview::RegisterId::ARM_FS29, ARM::S29},
273 {codeview::RegisterId::ARM_FS30, ARM::S30},
274 {codeview::RegisterId::ARM_FS31, ARM::S31},
275 {codeview::RegisterId::ARM_ND0, ARM::D0},
276 {codeview::RegisterId::ARM_ND1, ARM::D1},
277 {codeview::RegisterId::ARM_ND2, ARM::D2},
278 {codeview::RegisterId::ARM_ND3, ARM::D3},
279 {codeview::RegisterId::ARM_ND4, ARM::D4},
280 {codeview::RegisterId::ARM_ND5, ARM::D5},
281 {codeview::RegisterId::ARM_ND6, ARM::D6},
282 {codeview::RegisterId::ARM_ND7, ARM::D7},
283 {codeview::RegisterId::ARM_ND8, ARM::D8},
284 {codeview::RegisterId::ARM_ND9, ARM::D9},
285 {codeview::RegisterId::ARM_ND10, ARM::D10},
286 {codeview::RegisterId::ARM_ND11, ARM::D11},
287 {codeview::RegisterId::ARM_ND12, ARM::D12},
288 {codeview::RegisterId::ARM_ND13, ARM::D13},
289 {codeview::RegisterId::ARM_ND14, ARM::D14},
290 {codeview::RegisterId::ARM_ND15, ARM::D15},
291 {codeview::RegisterId::ARM_ND16, ARM::D16},
292 {codeview::RegisterId::ARM_ND17, ARM::D17},
293 {codeview::RegisterId::ARM_ND18, ARM::D18},
294 {codeview::RegisterId::ARM_ND19, ARM::D19},
295 {codeview::RegisterId::ARM_ND20, ARM::D20},
296 {codeview::RegisterId::ARM_ND21, ARM::D21},
297 {codeview::RegisterId::ARM_ND22, ARM::D22},
298 {codeview::RegisterId::ARM_ND23, ARM::D23},
299 {codeview::RegisterId::ARM_ND24, ARM::D24},
300 {codeview::RegisterId::ARM_ND25, ARM::D25},
301 {codeview::RegisterId::ARM_ND26, ARM::D26},
302 {codeview::RegisterId::ARM_ND27, ARM::D27},
303 {codeview::RegisterId::ARM_ND28, ARM::D28},
304 {codeview::RegisterId::ARM_ND29, ARM::D29},
305 {codeview::RegisterId::ARM_ND30, ARM::D30},
306 {codeview::RegisterId::ARM_ND31, ARM::D31},
307 {codeview::RegisterId::ARM_NQ0, ARM::Q0},
308 {codeview::RegisterId::ARM_NQ1, ARM::Q1},
309 {codeview::RegisterId::ARM_NQ2, ARM::Q2},
310 {codeview::RegisterId::ARM_NQ3, ARM::Q3},
311 {codeview::RegisterId::ARM_NQ4, ARM::Q4},
312 {codeview::RegisterId::ARM_NQ5, ARM::Q5},
313 {codeview::RegisterId::ARM_NQ6, ARM::Q6},
314 {codeview::RegisterId::ARM_NQ7, ARM::Q7},
315 {codeview::RegisterId::ARM_NQ8, ARM::Q8},
316 {codeview::RegisterId::ARM_NQ9, ARM::Q9},
317 {codeview::RegisterId::ARM_NQ10, ARM::Q10},
318 {codeview::RegisterId::ARM_NQ11, ARM::Q11},
319 {codeview::RegisterId::ARM_NQ12, ARM::Q12},
320 {codeview::RegisterId::ARM_NQ13, ARM::Q13},
321 {codeview::RegisterId::ARM_NQ14, ARM::Q14},
322 {codeview::RegisterId::ARM_NQ15, ARM::Q15},
323 };
324 for (const auto &I : RegMap)
325 MRI->mapLLVMRegToCVReg(I.Reg, static_cast<int>(I.CVReg));
326}
327
330 InitARMMCRegisterInfo(X, ARM::LR, 0, 0, ARM::PC);
332 return X;
333}
334
336 const Triple &TheTriple,
337 const MCTargetOptions &Options) {
338 MCAsmInfo *MAI;
339 if (TheTriple.isOSDarwin() || TheTriple.isOSBinFormatMachO())
340 MAI = new ARMMCAsmInfoDarwin(TheTriple);
341 else if (TheTriple.isWindowsMSVCEnvironment())
342 MAI = new ARMCOFFMCAsmInfoMicrosoft();
343 else if (TheTriple.isOSWindows())
344 MAI = new ARMCOFFMCAsmInfoGNU();
345 else
346 MAI = new ARMELFMCAsmInfo(TheTriple);
347
348 unsigned Reg = MRI.getDwarfRegNum(ARM::SP, true);
350
351 return MAI;
352}
353
355 std::unique_ptr<MCAsmBackend> &&MAB,
356 std::unique_ptr<MCObjectWriter> &&OW,
357 std::unique_ptr<MCCodeEmitter> &&Emitter) {
359 Ctx, std::move(MAB), std::move(OW), std::move(Emitter),
360 (T.getArch() == Triple::thumb || T.getArch() == Triple::thumbeb),
361 T.isAndroid());
362}
363
364static MCStreamer *
365createARMMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&MAB,
366 std::unique_ptr<MCObjectWriter> &&OW,
367 std::unique_ptr<MCCodeEmitter> &&Emitter) {
368 return createMachOStreamer(Ctx, std::move(MAB), std::move(OW),
369 std::move(Emitter), false);
370}
371
373 unsigned SyntaxVariant,
374 const MCAsmInfo &MAI,
375 const MCInstrInfo &MII,
376 const MCRegisterInfo &MRI) {
377 if (SyntaxVariant == 0)
378 return new ARMInstPrinter(MAI, MII, MRI);
379 return nullptr;
380}
381
383 MCContext &Ctx) {
384 if (TT.isOSBinFormatMachO())
386 // Default to the stock relocation info.
387 return llvm::createMCRelocationInfo(TT, Ctx);
388}
389
390namespace {
391
392class ARMMCInstrAnalysis : public MCInstrAnalysis {
393public:
394 ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
395
396 bool isUnconditionalBranch(const MCInst &Inst) const override {
397 // BCCs with the "always" predicate are unconditional branches.
398 if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
399 return true;
401 }
402
403 bool isConditionalBranch(const MCInst &Inst) const override {
404 // BCCs with the "always" predicate are unconditional branches.
405 if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
406 return false;
408 }
409
410 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
411 uint64_t &Target) const override {
412 const MCInstrDesc &Desc = Info->get(Inst.getOpcode());
413
414 // Find the PC-relative immediate operand in the instruction.
415 for (unsigned OpNum = 0; OpNum < Desc.getNumOperands(); ++OpNum) {
416 if (Inst.getOperand(OpNum).isImm() &&
417 Desc.operands()[OpNum].OperandType == MCOI::OPERAND_PCREL) {
418 int64_t Imm = Inst.getOperand(OpNum).getImm();
420 return true;
421 }
422 }
423 return false;
424 }
425
426 std::optional<uint64_t>
427 evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI,
428 uint64_t Addr, uint64_t Size) const override;
429
430 std::vector<std::pair<uint64_t, uint64_t>>
431 findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
432 const MCSubtargetInfo &STI) const override;
433};
434
435} // namespace
436
437static std::optional<uint64_t>
438// NOLINTNEXTLINE(readability-identifier-naming)
440 unsigned MemOpIndex, uint64_t Addr) {
441 if (MemOpIndex + 1 >= Desc.getNumOperands())
442 return std::nullopt;
443
444 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
445 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
446 if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())
447 return std::nullopt;
448
449 int32_t OffImm = (int32_t)MO2.getImm();
450 // Special value for #-0. All others are normal.
451 if (OffImm == INT32_MIN)
452 OffImm = 0;
453 return Addr + OffImm;
454}
455
456static std::optional<uint64_t>
458 unsigned MemOpIndex, uint64_t Addr) {
459 if (MemOpIndex + 2 >= Desc.getNumOperands())
460 return std::nullopt;
461
462 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
463 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
464 const MCOperand &MO3 = Inst.getOperand(MemOpIndex + 2);
465 if (!MO1.isReg() || MO1.getReg() != ARM::PC || MO2.getReg() || !MO3.isImm())
466 return std::nullopt;
467
468 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
470
471 if (Op == ARM_AM::sub)
472 return Addr - ImmOffs;
473 return Addr + ImmOffs;
474}
475
476static std::optional<uint64_t>
478 unsigned MemOpIndex, uint64_t Addr) {
479 if (MemOpIndex + 1 >= Desc.getNumOperands())
480 return std::nullopt;
481
482 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
483 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
484 if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())
485 return std::nullopt;
486
487 unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
489
490 if (Op == ARM_AM::sub)
491 return Addr - ImmOffs * 4;
492 return Addr + ImmOffs * 4;
493}
494
495static std::optional<uint64_t>
497 unsigned MemOpIndex, uint64_t Addr) {
498 if (MemOpIndex + 1 >= Desc.getNumOperands())
499 return std::nullopt;
500
501 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
502 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
503 if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())
504 return std::nullopt;
505
506 unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());
508
509 if (Op == ARM_AM::sub)
510 return Addr - ImmOffs * 2;
511 return Addr + ImmOffs * 2;
512}
513
514static std::optional<uint64_t>
515// NOLINTNEXTLINE(readability-identifier-naming)
517 unsigned MemOpIndex, uint64_t Addr) {
518 if (MemOpIndex + 1 >= Desc.getNumOperands())
519 return std::nullopt;
520
521 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
522 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
523 if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())
524 return std::nullopt;
525
526 int32_t OffImm = (int32_t)MO2.getImm();
527 assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
528
529 // Special value for #-0. All others are normal.
530 if (OffImm == INT32_MIN)
531 OffImm = 0;
532 return Addr + OffImm;
533}
534
535static std::optional<uint64_t>
536// NOLINTNEXTLINE(readability-identifier-naming)
538 unsigned MemOpIndex, uint64_t Addr) {
539 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
540 if (!MO1.isImm())
541 return std::nullopt;
542
543 int32_t OffImm = (int32_t)MO1.getImm();
544
545 // Special value for #-0. All others are normal.
546 if (OffImm == INT32_MIN)
547 OffImm = 0;
548 return Addr + OffImm;
549}
550
551static std::optional<uint64_t>
552// NOLINTNEXTLINE(readability-identifier-naming)
554 unsigned MemOpIndex, uint64_t Addr) {
555 return evaluateMemOpAddrForAddrModeT2_pc(Inst, Desc, MemOpIndex, Addr);
556}
557
558std::optional<uint64_t> ARMMCInstrAnalysis::evaluateMemoryOperandAddress(
559 const MCInst &Inst, const MCSubtargetInfo *STI, uint64_t Addr,
560 uint64_t Size) const {
561 const MCInstrDesc &Desc = Info->get(Inst.getOpcode());
562
563 // Only load instructions can have PC-relative memory addressing.
564 if (!Desc.mayLoad())
565 return std::nullopt;
566
567 // PC-relative addressing does not update the base register.
568 uint64_t TSFlags = Desc.TSFlags;
569 unsigned IndexMode =
571 if (IndexMode != ARMII::IndexModeNone)
572 return std::nullopt;
573
574 // Find the memory addressing operand in the instruction.
575 unsigned OpIndex = Desc.NumDefs;
576 while (OpIndex < Desc.getNumOperands() &&
577 Desc.operands()[OpIndex].OperandType != MCOI::OPERAND_MEMORY)
578 ++OpIndex;
579 if (OpIndex == Desc.getNumOperands())
580 return std::nullopt;
581
582 // Base address for PC-relative addressing is always 32-bit aligned.
583 Addr &= ~0x3;
584
585 // For ARM instructions the PC offset is 8 bytes, for Thumb instructions it
586 // is 4 bytes.
587 switch (Desc.TSFlags & ARMII::FormMask) {
588 default:
589 Addr += 8;
590 break;
591 case ARMII::ThumbFrm:
592 Addr += 4;
593 break;
594 // VLDR* instructions share the same opcode (and thus the same form) for Arm
595 // and Thumb. Use a bit longer route through STI in that case.
597 Addr += STI->hasFeature(ARM::ModeThumb) ? 4 : 8;
598 break;
599 }
600
601 // Eveluate the address depending on the addressing mode
602 unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
603 switch (AddrMode) {
604 default:
605 return std::nullopt;
607 return evaluateMemOpAddrForAddrMode_i12(Inst, Desc, OpIndex, Addr);
608 case ARMII::AddrMode3:
609 return evaluateMemOpAddrForAddrMode3(Inst, Desc, OpIndex, Addr);
610 case ARMII::AddrMode5:
611 return evaluateMemOpAddrForAddrMode5(Inst, Desc, OpIndex, Addr);
619 return evaluateMemOpAddrForAddrModeT1_s(Inst, Desc, OpIndex, Addr);
620 }
621}
622
623template <typename T, size_t N>
624static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf,
626 for (size_t I = 0; I < N; ++I) {
627 T Val = support::endian::read<T>(Buf + I * sizeof(T), E);
628 if (Val != Insns[I])
629 return false;
630 }
631 return true;
632}
633
634std::vector<std::pair<uint64_t, uint64_t>>
635ARMMCInstrAnalysis::findPltEntries(uint64_t PltSectionVA,
636 ArrayRef<uint8_t> PltContents,
637 const MCSubtargetInfo &STI) const {
638 llvm::endianness DataEndianness = STI.getTargetTriple().isLittleEndian()
639 ? endianness::little
640 : endianness::big;
641 llvm::endianness InstrEndianness =
642 STI.checkFeatures("+big-endian-instructions") ? endianness::big
643 : endianness::little;
644
645 // Do a lightweight parsing of PLT entries.
646 std::vector<std::pair<uint64_t, uint64_t>> Result;
647 if (STI.checkFeatures("+thumb-mode")) {
648 for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End;
649 Byte += 16) {
650 // Expected instruction sequence:
651 //
652 // movw ip, #lower16
653 // movt ip, #upper16
654 // add ip, pc
655 // ldr.w pc, [ip]
656 // b . -4
657
658 uint32_t MovwPart1 =
659 support::endian::read16(PltContents.data() + Byte, InstrEndianness);
660 if ((MovwPart1 & 0xffb0) != 0xf200)
661 continue;
662
663 uint32_t MovwPart2 = support::endian::read16(
664 PltContents.data() + Byte + 2, InstrEndianness);
665 if ((MovwPart2 & 0x8f00) != 0xc00)
666 continue;
667
668 uint64_t OffsetLower = (MovwPart2 & 0xff) + ((MovwPart2 & 0x7000) >> 4) +
669 ((MovwPart1 & 0x400) << 1) +
670 ((MovwPart1 & 0xf) << 12);
671
672 uint32_t MovtPart1 = support::endian::read16(
673 PltContents.data() + Byte + 4, InstrEndianness);
674 if ((MovtPart1 & 0xfbf0) != 0xf2c0)
675 continue;
676
677 uint32_t MovtPart2 = support::endian::read16(
678 PltContents.data() + Byte + 6, InstrEndianness);
679 if ((MovtPart2 & 0x8f00) != 0xc00)
680 continue;
681
682 uint64_t OffsetHigher =
683 ((MovtPart2 & 0xff) << 16) + ((MovtPart2 & 0x7000) << 12) +
684 ((MovtPart1 & 0x400) << 17) + ((MovtPart1 & 0xf) << 28);
685
686 const uint16_t Insns[] = {
687 0x44fc, // add ip, pc
688 0xf8dc, 0xf000, // ldr.w pc, [ip]
689 0xe7fc, // b . -4
690 };
691
692 if (!instructionsMatch(Insns, PltContents.data() + Byte + 8,
693 InstrEndianness))
694 continue;
695
696 // add ip, pc at Byte + 8 + thumb-pc-bias = 12
697 uint64_t Offset = (PltSectionVA + Byte + 12) + OffsetLower + OffsetHigher;
698 Result.emplace_back(PltSectionVA + Byte, Offset);
699 }
700 } else {
701 const uint32_t LongEntryInsns[] = {
702 0xe59fc004, // ldr ip, L2
703 0xe08cc00f, // L1: add ip, ip, pc
704 0xe59cf000, // ldr pc, [ip]
705 };
706
707 for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End;
708 Byte += 4) {
709 // Is it a long entry?
710 if (instructionsMatch(LongEntryInsns, PltContents.data() + Byte,
711 InstrEndianness)) {
712 // Expected instruction sequence:
713 //
714 // ldr ip, L2
715 // L1: add ip, ip, pc
716 // ldr pc, [ip]
717 // L2: .word Offset(&(.got.plt) - L1 - 8
718
719 uint64_t Offset = (PltSectionVA + Byte + 12) +
721 PltContents.data() + Byte + 12, DataEndianness);
722 Result.emplace_back(PltSectionVA + Byte, Offset);
723 Byte += 12;
724 } else {
725 // Expected instruction sequence:
726 //
727 // L1: add ip, pc, #0x0NN00000 Offset(&(.got.plt) - L1 - 8
728 // add ip, ip, #0x000NN000 Offset(&(.got.plt) - L1 - 8
729 // ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8
730
731 uint32_t Add1 =
732 support::endian::read32(PltContents.data() + Byte, InstrEndianness);
733 if ((Add1 & 0xe28fc600) != 0xe28fc600)
734 continue;
735 uint32_t Add2 = support::endian::read32(PltContents.data() + Byte + 4,
736 InstrEndianness);
737 if ((Add2 & 0xe28cca00) != 0xe28cca00)
738 continue;
739 uint32_t Ldr = support::endian::read32(PltContents.data() + Byte + 8,
740 InstrEndianness);
741 if ((Ldr & 0xe5bcf000) != 0xe5bcf000)
742 continue;
743
744 // add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8
745 uint64_t Offset = (PltSectionVA + Byte + 8) + ((Add1 & 0xff) << 20) +
746 ((Add2 & 0xff) << 12) + (Ldr & 0xfff);
747 Result.emplace_back(PltSectionVA + Byte, Offset);
748 Byte += 8;
749 }
750 }
751 }
752 return Result;
753}
754
756 return new ARMMCInstrAnalysis(Info);
757}
758
759bool ARM::isCDECoproc(size_t Coproc, const MCSubtargetInfo &STI) {
760 // Unfortunately we don't have ARMTargetInfo in the disassembler, so we have
761 // to rely on feature bits.
762 if (Coproc >= 8)
763 return false;
764 return STI.getFeatureBits()[ARM::FeatureCoprocCDE0 + Coproc];
765}
766
767// Force static initialization.
771 // Register the MC asm info.
773
774 // Register the MC instruction info.
776
777 // Register the MC register info.
779
780 // Register the MC subtarget info.
783
787
788 // Register the obj target streamer.
791
792 // Register the asm streamer.
794
795 // Register the null TargetStreamer.
797
798 // Register the MCInstPrinter.
800
801 // Register the MC relocation info.
803 }
804
805 // Register the MC instruction analyzer.
809
813 }
817 }
818}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isUnconditionalBranch(Instruction *Term)
Definition ADCE.cpp:215
static std::optional< uint64_t > evaluateMemOpAddrForAddrMode_i12(const MCInst &Inst, const MCInstrDesc &Desc, unsigned MemOpIndex, uint64_t Addr)
static bool getARMStoreDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI, std::string &Info)
static bool getARMLoadDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI, std::string &Info)
static std::optional< uint64_t > evaluateMemOpAddrForAddrModeT1_s(const MCInst &Inst, const MCInstrDesc &Desc, unsigned MemOpIndex, uint64_t Addr)
static MCStreamer * createARMMachOStreamer(MCContext &Ctx, std::unique_ptr< MCAsmBackend > &&MAB, std::unique_ptr< MCObjectWriter > &&OW, std::unique_ptr< MCCodeEmitter > &&Emitter)
static std::optional< uint64_t > evaluateMemOpAddrForAddrMode3(const MCInst &Inst, const MCInstrDesc &Desc, unsigned MemOpIndex, uint64_t Addr)
static MCInstrAnalysis * createARMMCInstrAnalysis(const MCInstrInfo *Info)
static std::optional< uint64_t > evaluateMemOpAddrForAddrMode5FP16(const MCInst &Inst, const MCInstrDesc &Desc, unsigned MemOpIndex, uint64_t Addr)
static bool instructionsMatch(const T(&Insns)[N], const uint8_t *Buf, llvm::endianness E)
static std::optional< uint64_t > evaluateMemOpAddrForAddrModeT2_pc(const MCInst &Inst, const MCInstrDesc &Desc, unsigned MemOpIndex, uint64_t Addr)
static bool getMCRDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI, std::string &Info)
static std::optional< uint64_t > evaluateMemOpAddrForAddrMode5(const MCInst &Inst, const MCInstrDesc &Desc, unsigned MemOpIndex, uint64_t Addr)
static MCInstrInfo * createARMMCInstrInfo()
static MCRelocationInfo * createARMMCRelocationInfo(const Triple &TT, MCContext &Ctx)
static MCInstPrinter * createARMMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, const MCRegisterInfo &MRI)
static MCRegisterInfo * createARMMCRegisterInfo(const Triple &Triple)
static bool getMRCDeprecationInfo(MCInst &MI, const MCSubtargetInfo &STI, std::string &Info)
static std::optional< uint64_t > evaluateMemOpAddrForAddrModeT2_i8s4(const MCInst &Inst, const MCInstrDesc &Desc, unsigned MemOpIndex, uint64_t Addr)
LLVM_ABI LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMTargetMC()
static MCAsmInfo * createARMMCAsmInfo(const MCRegisterInfo &MRI, const Triple &TheTriple, const MCTargetOptions &Options)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Analysis containing CSE Info
Definition CSEInfo.cpp:27
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
dxil DXContainer Global Emitter
IRTranslator LLVM IR MI
static LVOptions Options
Definition LVOptions.cpp:25
#define I(x, y, z)
Definition MD5.cpp:58
Register Reg
#define T
unsigned OpIndex
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
size_t size() const
size - Get the array size.
Definition ArrayRef.h:147
const T * data() const
Definition ArrayRef.h:144
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:64
void addInitialFrameState(const MCCFIInstruction &Inst)
Definition MCAsmInfo.cpp:74
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
Definition MCDwarf.h:585
Context object for machine code objects.
Definition MCContext.h:83
This is an instance of a target assembly language printer that converts an MCInst to valid target ass...
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getOpcode() const
Definition MCInst.h:202
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
virtual bool isUnconditionalBranch(const MCInst &Inst) const
virtual bool isConditionalBranch(const MCInst &Inst) const
Describe properties that are true of each instruction in the target description file.
unsigned getOpcode() const
Return the opcode number for this descriptor.
Interface to description of machine instruction set.
Definition MCInstrInfo.h:27
const MCInstrDesc & get(unsigned Opcode) const
Return the machine instruction descriptor that corresponds to the specified instruction opcode.
Definition MCInstrInfo.h:64
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
int64_t getImm() const
Definition MCInst.h:84
bool isImm() const
Definition MCInst.h:66
bool isReg() const
Definition MCInst.h:65
MCRegister getReg() const
Returns the register number.
Definition MCInst.h:73
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Create MCExprs from relocations found in an object file.
Streaming machine code generation interface.
Definition MCStreamer.h:220
Generic base class for all target subtargets.
bool checkFeatures(StringRef FS) const
Check whether the subtarget features are enabled/disabled as per the provided string,...
bool hasFeature(unsigned Feature) const
const Triple & getTargetTriple() const
const FeatureBitset & getFeatureBits() const
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition Triple.h:782
LLVM_ABI bool isLittleEndian() const
Tests whether the target triple is little endian.
Definition Triple.cpp:2075
bool isOSWindows() const
Tests whether the OS is Windows.
Definition Triple.h:679
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, DriverKit, XROS, or bridgeOS).
Definition Triple.h:611
bool isWindowsMSVCEnvironment() const
Checks if the environment could be MSVC.
Definition Triple.h:689
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
IndexMode
ARM Index Modes.
unsigned char getAM3Offset(unsigned AM3Opc)
unsigned char getAM5FP16Offset(unsigned AM5Opc)
AddrOpc getAM5Op(unsigned AM5Opc)
AddrOpc getAM5FP16Op(unsigned AM5Opc)
unsigned char getAM5Offset(unsigned AM5Opc)
AddrOpc getAM3Op(unsigned AM3Opc)
MCSubtargetInfo * createARMMCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS)
Create a ARM MCSubtargetInfo instance.
std::string ParseARMTriple(const Triple &TT, StringRef CPU)
bool isCPSRDefined(const MCInst &MI, const MCInstrInfo *MCII)
void initLLVMToCVRegMapping(MCRegisterInfo *MRI)
bool isPredicated(const MCInst &MI, const MCInstrInfo *MCII)
uint64_t evaluateBranchTarget(const MCInstrDesc &InstDesc, uint64_t Addr, int64_t Imm)
LLVM_ABI StringRef getArchName(ArchKind AK)
LLVM_ABI ArchKind parseArch(StringRef Arch)
bool isCDECoproc(size_t Coproc, const MCSubtargetInfo &STI)
@ D16
Only 16 D registers.
uint32_t read32(const void *P, endianness E)
Definition Endian.h:409
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition Endian.h:58
uint16_t read16(const void *P, endianness E)
Definition Endian.h:406
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:477
MCELFStreamer * createARMELFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > TAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter, bool IsThumb, bool IsAndroid)
Target & getTheThumbBETarget()
MCCodeEmitter * createARMLEMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
LLVM_ABI MCStreamer * createELFStreamer(MCContext &Ctx, std::unique_ptr< MCAsmBackend > &&TAB, std::unique_ptr< MCObjectWriter > &&OW, std::unique_ptr< MCCodeEmitter > &&CE)
MCAsmBackend * createARMBEAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
Op::Description Desc
MCAsmBackend * createARMLEAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
MCRelocationInfo * createARMMachORelocationInfo(MCContext &Ctx)
Construct ARM Mach-O relocation info.
LLVM_ABI MCStreamer * createMachOStreamer(MCContext &Ctx, std::unique_ptr< MCAsmBackend > &&TAB, std::unique_ptr< MCObjectWriter > &&OW, std::unique_ptr< MCCodeEmitter > &&CE, bool DWARFMustBeAtTheEnd, bool LabelSections=false)
LLVM_ABI MCRelocationInfo * createMCRelocationInfo(const Triple &TT, MCContext &Ctx)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
MCTargetStreamer * createARMObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI)
endianness
Definition bit.h:71
Target & getTheARMLETarget()
MCTargetStreamer * createARMNullTargetStreamer(MCStreamer &S)
MCCodeEmitter * createARMBEMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
MCStreamer * createARMWinCOFFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > &&MAB, std::unique_ptr< MCObjectWriter > &&OW, std::unique_ptr< MCCodeEmitter > &&Emitter)
MCTargetStreamer * createARMTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint)
Target & getTheARMBETarget()
Target & getTheThumbLETarget()
#define N
RegisterMCAsmInfoFn - Helper template for registering a target assembly info implementation.
static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn)
RegisterMCRegInfo - Register a MCRegisterInfo implementation for the given target.
static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn)
RegisterMCAsmBackend - Register a MCAsmBackend implementation for the given target.
static void RegisterMCCodeEmitter(Target &T, Target::MCCodeEmitterCtorTy Fn)
RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the given target.
static void RegisterMCSubtargetInfo(Target &T, Target::MCSubtargetInfoCtorFnTy Fn)
RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for the given target.
static void RegisterObjectTargetStreamer(Target &T, Target::ObjectTargetStreamerCtorTy Fn)
static void RegisterMCInstrAnalysis(Target &T, Target::MCInstrAnalysisCtorFnTy Fn)
RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for the given target.
static void RegisterELFStreamer(Target &T, Target::ELFStreamerCtorTy Fn)
static void RegisterNullTargetStreamer(Target &T, Target::NullTargetStreamerCtorTy Fn)
static void RegisterMCInstPrinter(Target &T, Target::MCInstPrinterCtorTy Fn)
RegisterMCInstPrinter - Register a MCInstPrinter implementation for the given target.
static void RegisterCOFFStreamer(Target &T, Target::COFFStreamerCtorTy Fn)
static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn)
RegisterMCInstrInfo - Register a MCInstrInfo implementation for the given target.
static void RegisterMachOStreamer(Target &T, Target::MachOStreamerCtorTy Fn)
static void RegisterAsmTargetStreamer(Target &T, Target::AsmTargetStreamerCtorTy Fn)
static void RegisterMCRelocationInfo(Target &T, Target::MCRelocationInfoCtorTy Fn)
RegisterMCRelocationInfo - Register an MCRelocationInfo implementation for the given target.