LLVM 24.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.
185 uint64_t Offset =
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, Options);
341 else if (TheTriple.isWindowsMSVCEnvironment())
343 else if (TheTriple.isOSWindows())
344 MAI = new ARMCOFFMCAsmInfoGNU(Options);
345 else
346 MAI = new ARMELFMCAsmInfo(TheTriple, Options);
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) {
358 return createARMELFStreamer(Ctx, std::move(MAB), std::move(OW),
359 std::move(Emitter), T.isThumb(), T.isAndroid());
360}
361
362static MCStreamer *
363createARMMachOStreamer(MCContext &Ctx, std::unique_ptr<MCAsmBackend> &&MAB,
364 std::unique_ptr<MCObjectWriter> &&OW,
365 std::unique_ptr<MCCodeEmitter> &&Emitter) {
366 return createMachOStreamer(Ctx, std::move(MAB), std::move(OW),
367 std::move(Emitter), false);
368}
369
371 unsigned SyntaxVariant,
372 const MCAsmInfo &MAI,
373 const MCInstrInfo &MII,
374 const MCRegisterInfo &MRI) {
375 if (SyntaxVariant == 0)
376 return new ARMInstPrinter(MAI, MII, MRI);
377 return nullptr;
378}
379
381 MCContext &Ctx) {
382 if (TT.isOSBinFormatMachO())
384 // Default to the stock relocation info.
385 return llvm::createMCRelocationInfo(TT, Ctx);
386}
387
388namespace {
389
390class ARMMCInstrAnalysis : public MCInstrAnalysis {
391public:
392 ARMMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
393
394 bool isUnconditionalBranch(const MCInst &Inst) const override {
395 // BCCs with the "always" predicate are unconditional branches.
396 if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
397 return true;
399 }
400
401 bool isConditionalBranch(const MCInst &Inst) const override {
402 // BCCs with the "always" predicate are unconditional branches.
403 if (Inst.getOpcode() == ARM::Bcc && Inst.getOperand(1).getImm()==ARMCC::AL)
404 return false;
406 }
407
408 bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
409 uint64_t &Target) const override {
410 const MCInstrDesc &Desc = Info->get(Inst.getOpcode());
411
412 // Find the PC-relative immediate operand in the instruction.
413 for (unsigned OpNum = 0; OpNum < Desc.getNumOperands(); ++OpNum) {
414 if (Inst.getOperand(OpNum).isImm() &&
415 Desc.operands()[OpNum].OperandType == MCOI::OPERAND_PCREL) {
416 int64_t Imm = Inst.getOperand(OpNum).getImm();
418 return true;
419 }
420 }
421 return false;
422 }
423
424 std::optional<uint64_t>
425 evaluateMemoryOperandAddress(const MCInst &Inst, const MCSubtargetInfo *STI,
426 uint64_t Addr, uint64_t Size) const override;
427
428 std::vector<std::pair<uint64_t, uint64_t>>
429 findPltEntries(uint64_t PltSectionVA, ArrayRef<uint8_t> PltContents,
430 const MCSubtargetInfo &STI) const override;
431};
432
433} // namespace
434
435static std::optional<uint64_t>
436// NOLINTNEXTLINE(readability-identifier-naming)
438 unsigned MemOpIndex, uint64_t Addr) {
439 if (MemOpIndex + 1 >= Desc.getNumOperands())
440 return std::nullopt;
441
442 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
443 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
444 if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())
445 return std::nullopt;
446
447 int32_t OffImm = (int32_t)MO2.getImm();
448 // Special value for #-0. All others are normal.
449 if (OffImm == INT32_MIN)
450 OffImm = 0;
451 return Addr + OffImm;
452}
453
454static std::optional<uint64_t>
456 unsigned MemOpIndex, uint64_t Addr) {
457 if (MemOpIndex + 2 >= Desc.getNumOperands())
458 return std::nullopt;
459
460 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
461 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
462 const MCOperand &MO3 = Inst.getOperand(MemOpIndex + 2);
463 if (!MO1.isReg() || MO1.getReg() != ARM::PC || MO2.getReg() || !MO3.isImm())
464 return std::nullopt;
465
466 unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm());
468
469 if (Op == ARM_AM::sub)
470 return Addr - ImmOffs;
471 return Addr + ImmOffs;
472}
473
474static std::optional<uint64_t>
476 unsigned MemOpIndex, uint64_t Addr) {
477 if (MemOpIndex + 1 >= Desc.getNumOperands())
478 return std::nullopt;
479
480 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
481 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
482 if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())
483 return std::nullopt;
484
485 unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm());
487
488 if (Op == ARM_AM::sub)
489 return Addr - ImmOffs * 4;
490 return Addr + ImmOffs * 4;
491}
492
493static std::optional<uint64_t>
495 unsigned MemOpIndex, uint64_t Addr) {
496 if (MemOpIndex + 1 >= Desc.getNumOperands())
497 return std::nullopt;
498
499 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
500 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
501 if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())
502 return std::nullopt;
503
504 unsigned ImmOffs = ARM_AM::getAM5FP16Offset(MO2.getImm());
506
507 if (Op == ARM_AM::sub)
508 return Addr - ImmOffs * 2;
509 return Addr + ImmOffs * 2;
510}
511
512static std::optional<uint64_t>
513// NOLINTNEXTLINE(readability-identifier-naming)
515 unsigned MemOpIndex, uint64_t Addr) {
516 if (MemOpIndex + 1 >= Desc.getNumOperands())
517 return std::nullopt;
518
519 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
520 const MCOperand &MO2 = Inst.getOperand(MemOpIndex + 1);
521 if (!MO1.isReg() || MO1.getReg() != ARM::PC || !MO2.isImm())
522 return std::nullopt;
523
524 int32_t OffImm = (int32_t)MO2.getImm();
525 assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
526
527 // Special value for #-0. All others are normal.
528 if (OffImm == INT32_MIN)
529 OffImm = 0;
530 return Addr + OffImm;
531}
532
533static std::optional<uint64_t>
534// NOLINTNEXTLINE(readability-identifier-naming)
536 unsigned MemOpIndex, uint64_t Addr) {
537 const MCOperand &MO1 = Inst.getOperand(MemOpIndex);
538 if (!MO1.isImm())
539 return std::nullopt;
540
541 int32_t OffImm = (int32_t)MO1.getImm();
542
543 // Special value for #-0. All others are normal.
544 if (OffImm == INT32_MIN)
545 OffImm = 0;
546 return Addr + OffImm;
547}
548
549static std::optional<uint64_t>
550// NOLINTNEXTLINE(readability-identifier-naming)
552 unsigned MemOpIndex, uint64_t Addr) {
553 return evaluateMemOpAddrForAddrModeT2_pc(Inst, Desc, MemOpIndex, Addr);
554}
555
556std::optional<uint64_t> ARMMCInstrAnalysis::evaluateMemoryOperandAddress(
557 const MCInst &Inst, const MCSubtargetInfo *STI, uint64_t Addr,
558 uint64_t Size) const {
559 const MCInstrDesc &Desc = Info->get(Inst.getOpcode());
560
561 // Only load instructions can have PC-relative memory addressing.
562 if (!Desc.mayLoad())
563 return std::nullopt;
564
565 // PC-relative addressing does not update the base register.
566 uint64_t TSFlags = Desc.TSFlags;
567 unsigned IndexMode =
569 if (IndexMode != ARMII::IndexModeNone)
570 return std::nullopt;
571
572 // Find the memory addressing operand in the instruction.
573 unsigned OpIndex = Desc.NumDefs;
574 while (OpIndex < Desc.getNumOperands() &&
575 Desc.operands()[OpIndex].OperandType != MCOI::OPERAND_MEMORY)
576 ++OpIndex;
577 if (OpIndex == Desc.getNumOperands())
578 return std::nullopt;
579
580 // Base address for PC-relative addressing is always 32-bit aligned.
581 Addr &= ~0x3;
582
583 // For ARM instructions the PC offset is 8 bytes, for Thumb instructions it
584 // is 4 bytes.
585 switch (Desc.TSFlags & ARMII::FormMask) {
586 default:
587 Addr += 8;
588 break;
589 case ARMII::ThumbFrm:
590 Addr += 4;
591 break;
592 // VLDR* instructions share the same opcode (and thus the same form) for Arm
593 // and Thumb. Use a bit longer route through STI in that case.
595 Addr += STI->hasFeature(ARM::ModeThumb) ? 4 : 8;
596 break;
597 }
598
599 // Evaluate the address depending on the addressing mode
600 unsigned AddrMode = (TSFlags & ARMII::AddrModeMask);
601 switch (AddrMode) {
602 default:
603 return std::nullopt;
605 return evaluateMemOpAddrForAddrMode_i12(Inst, Desc, OpIndex, Addr);
606 case ARMII::AddrMode3:
607 return evaluateMemOpAddrForAddrMode3(Inst, Desc, OpIndex, Addr);
608 case ARMII::AddrMode5:
609 return evaluateMemOpAddrForAddrMode5(Inst, Desc, OpIndex, Addr);
611 return evaluateMemOpAddrForAddrMode5FP16(Inst, Desc, OpIndex, Addr);
613 return evaluateMemOpAddrForAddrModeT2_i8s4(Inst, Desc, OpIndex, Addr);
615 return evaluateMemOpAddrForAddrModeT2_pc(Inst, Desc, OpIndex, Addr);
617 return evaluateMemOpAddrForAddrModeT1_s(Inst, Desc, OpIndex, Addr);
618 }
619}
620
621template <typename T, size_t N>
622static bool instructionsMatch(const T (&Insns)[N], const uint8_t *Buf,
624 for (size_t I = 0; I < N; ++I) {
625 T Val = support::endian::read<T>(Buf + I * sizeof(T), E);
626 if (Val != Insns[I])
627 return false;
628 }
629 return true;
630}
631
632std::vector<std::pair<uint64_t, uint64_t>>
633ARMMCInstrAnalysis::findPltEntries(uint64_t PltSectionVA,
634 ArrayRef<uint8_t> PltContents,
635 const MCSubtargetInfo &STI) const {
636 llvm::endianness DataEndianness = STI.getTargetTriple().isLittleEndian()
637 ? endianness::little
638 : endianness::big;
639 llvm::endianness InstrEndianness =
640 STI.checkFeatures("+big-endian-instructions") ? endianness::big
641 : endianness::little;
642
643 // Do a lightweight parsing of PLT entries.
644 std::vector<std::pair<uint64_t, uint64_t>> Result;
645 if (STI.checkFeatures("+thumb-mode")) {
646 for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End;
647 Byte += 16) {
648 // Expected instruction sequence:
649 //
650 // movw ip, #lower16
651 // movt ip, #upper16
652 // add ip, pc
653 // ldr.w pc, [ip]
654 // b . -4
655
656 uint32_t MovwPart1 =
657 support::endian::read16(PltContents.data() + Byte, InstrEndianness);
658 if ((MovwPart1 & 0xffb0) != 0xf200)
659 continue;
660
661 uint32_t MovwPart2 = support::endian::read16(
662 PltContents.data() + Byte + 2, InstrEndianness);
663 if ((MovwPart2 & 0x8f00) != 0xc00)
664 continue;
665
666 uint64_t OffsetLower = (MovwPart2 & 0xff) + ((MovwPart2 & 0x7000) >> 4) +
667 ((MovwPart1 & 0x400) << 1) +
668 ((MovwPart1 & 0xf) << 12);
669
670 uint32_t MovtPart1 = support::endian::read16(
671 PltContents.data() + Byte + 4, InstrEndianness);
672 if ((MovtPart1 & 0xfbf0) != 0xf2c0)
673 continue;
674
675 uint32_t MovtPart2 = support::endian::read16(
676 PltContents.data() + Byte + 6, InstrEndianness);
677 if ((MovtPart2 & 0x8f00) != 0xc00)
678 continue;
679
680 uint64_t OffsetHigher =
681 ((MovtPart2 & 0xff) << 16) + ((MovtPart2 & 0x7000) << 12) +
682 ((MovtPart1 & 0x400) << 17) + ((MovtPart1 & 0xf) << 28);
683
684 const uint16_t Insns[] = {
685 0x44fc, // add ip, pc
686 0xf8dc, 0xf000, // ldr.w pc, [ip]
687 0xe7fc, // b . -4
688 };
689
690 if (!instructionsMatch(Insns, PltContents.data() + Byte + 8,
691 InstrEndianness))
692 continue;
693
694 // add ip, pc at Byte + 8 + thumb-pc-bias = 12
695 uint64_t Offset = (PltSectionVA + Byte + 12) + OffsetLower + OffsetHigher;
696 Result.emplace_back(PltSectionVA + Byte, Offset);
697 }
698 } else {
699 const uint32_t LongEntryInsns[] = {
700 0xe59fc004, // ldr ip, L2
701 0xe08cc00f, // L1: add ip, ip, pc
702 0xe59cf000, // ldr pc, [ip]
703 };
704
705 for (uint64_t Byte = 0, End = PltContents.size(); Byte + 12 < End;
706 Byte += 4) {
707 // Is it a long entry?
708 if (instructionsMatch(LongEntryInsns, PltContents.data() + Byte,
709 InstrEndianness)) {
710 // Expected instruction sequence:
711 //
712 // ldr ip, L2
713 // L1: add ip, ip, pc
714 // ldr pc, [ip]
715 // L2: .word Offset(&(.got.plt) - L1 - 8
716
717 uint64_t Offset = (PltSectionVA + Byte + 12) +
719 PltContents.data() + Byte + 12, DataEndianness);
720 Result.emplace_back(PltSectionVA + Byte, Offset);
721 Byte += 12;
722 } else {
723 // Expected instruction sequence:
724 //
725 // L1: add ip, pc, #0x0NN00000 Offset(&(.got.plt) - L1 - 8
726 // add ip, ip, #0x000NN000 Offset(&(.got.plt) - L1 - 8
727 // ldr pc, [ip, #0x00000NNN] Offset(&(.got.plt) - L1 - 8
728
729 uint32_t Add1 =
730 support::endian::read32(PltContents.data() + Byte, InstrEndianness);
731 if ((Add1 & 0xe28fc600) != 0xe28fc600)
732 continue;
733 uint32_t Add2 = support::endian::read32(PltContents.data() + Byte + 4,
734 InstrEndianness);
735 if ((Add2 & 0xe28cca00) != 0xe28cca00)
736 continue;
737 uint32_t Ldr = support::endian::read32(PltContents.data() + Byte + 8,
738 InstrEndianness);
739 if ((Ldr & 0xe5bcf000) != 0xe5bcf000)
740 continue;
741
742 // add ip, pc, #offset at Byte + 0 + arm-pc-bias = 8
743 uint64_t Offset = (PltSectionVA + Byte + 8) + ((Add1 & 0xff) << 20) +
744 ((Add2 & 0xff) << 12) + (Ldr & 0xfff);
745 Result.emplace_back(PltSectionVA + Byte, Offset);
746 Byte += 8;
747 }
748 }
749 }
750 return Result;
751}
752
754 return new ARMMCInstrAnalysis(Info);
755}
756
757bool ARM::isCDECoproc(size_t Coproc, const MCSubtargetInfo &STI) {
758 // Unfortunately we don't have ARMTargetInfo in the disassembler, so we have
759 // to rely on feature bits.
760 if (Coproc >= 8)
761 return false;
762 return STI.getFeatureBits()[ARM::FeatureCoprocCDE0 + Coproc];
763}
764
765// Force static initialization.
769 // Register the MC asm info.
771
772 // Register the MC instruction info.
774
775 // Register the MC register info.
777
778 // Register the MC subtarget info.
781
785
786 // Register the obj target streamer.
789
790 // Register the asm streamer.
792
793 // Register the null TargetStreamer.
795
796 // Register the MCInstPrinter.
798
799 // Register the MC relocation info.
801 }
802
803 // Register the MC instruction analyzer.
807
811 }
815 }
816}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned Imm
unsigned uint64_t
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)
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#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:57
Register Reg
#define T
size_t size() const
Get the array size.
Definition ArrayRef.h:141
const T * data() const
Definition ArrayRef.h:138
This class is intended to be used as a base class for asm properties and features specific to the tar...
Definition MCAsmInfo.h:67
void addInitialFrameState(const MCCFIInstruction &Inst)
Definition MCAsmInfo.cpp:39
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:628
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:89
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...
void mapLLVMRegToCVReg(MCRegister LLVMReg, int CVReg)
virtual int64_t getDwarfRegNum(MCRegister Reg, bool isEH) const
Map a target register to an equivalent dwarf register number.
Create MCExprs from relocations found in an object file.
Streaming machine code generation interface.
Definition MCStreamer.h:222
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
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Target - Wrapper for Target specific information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
bool isOSBinFormatMachO() const
Tests whether the environment is MachO.
Definition Triple.h:876
LLVM_ABI bool isLittleEndian() const
Tests whether the target triple is little endian.
Definition Triple.cpp:2213
bool isOSWindows() const
Tests whether the OS is Windows.
Definition Triple.h:778
bool isOSDarwin() const
Is this a "Darwin" OS (macOS, iOS, tvOS, watchOS, DriverKit, XROS, or bridgeOS).
Definition Triple.h:724
bool isWindowsMSVCEnvironment() const
Checks if the environment could be MSVC.
Definition Triple.h:792
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:392
value_type read(const void *memory, endianness endian)
Read a value of a particular endianness from memory.
Definition Endian.h:53
uint16_t read16(const void *P, endianness E)
Definition Endian.h:389
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
LLVM_ABI 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.