1 | //===- bolt/Core/MCPlusBuilder.cpp - Interface for MCPlus -----------------===// |
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 implements the MCPlusBuilder class. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #include "bolt/Core/MCPlusBuilder.h" |
14 | #include "bolt/Core/MCPlus.h" |
15 | #include "bolt/Utils/CommandLineOpts.h" |
16 | #include "llvm/MC/MCContext.h" |
17 | #include "llvm/MC/MCInst.h" |
18 | #include "llvm/MC/MCInstrAnalysis.h" |
19 | #include "llvm/MC/MCInstrDesc.h" |
20 | #include "llvm/MC/MCInstrInfo.h" |
21 | #include "llvm/MC/MCRegisterInfo.h" |
22 | #include "llvm/Support/CommandLine.h" |
23 | #include "llvm/Support/Debug.h" |
24 | #include <cstdint> |
25 | |
26 | #define DEBUG_TYPE "mcplus" |
27 | |
28 | using namespace llvm; |
29 | using namespace bolt; |
30 | using namespace MCPlus; |
31 | |
32 | namespace opts { |
33 | cl::opt<bool> |
34 | TerminalTrap("terminal-trap" , |
35 | cl::desc("Assume that execution stops at trap instruction" ), |
36 | cl::init(Val: true), cl::Hidden, cl::cat(BoltCategory)); |
37 | } |
38 | |
39 | bool MCPlusBuilder::equals(const MCInst &A, const MCInst &B, |
40 | CompFuncTy Comp) const { |
41 | if (A.getOpcode() != B.getOpcode()) |
42 | return false; |
43 | |
44 | unsigned NumOperands = MCPlus::getNumPrimeOperands(Inst: A); |
45 | if (NumOperands != MCPlus::getNumPrimeOperands(Inst: B)) |
46 | return false; |
47 | |
48 | for (unsigned Index = 0; Index < NumOperands; ++Index) |
49 | if (!equals(A: A.getOperand(i: Index), B: B.getOperand(i: Index), Comp)) |
50 | return false; |
51 | |
52 | return true; |
53 | } |
54 | |
55 | bool MCPlusBuilder::equals(const MCOperand &A, const MCOperand &B, |
56 | CompFuncTy Comp) const { |
57 | if (A.isReg()) { |
58 | if (!B.isReg()) |
59 | return false; |
60 | return A.getReg() == B.getReg(); |
61 | } else if (A.isImm()) { |
62 | if (!B.isImm()) |
63 | return false; |
64 | return A.getImm() == B.getImm(); |
65 | } else if (A.isSFPImm()) { |
66 | if (!B.isSFPImm()) |
67 | return false; |
68 | return A.getSFPImm() == B.getSFPImm(); |
69 | } else if (A.isDFPImm()) { |
70 | if (!B.isDFPImm()) |
71 | return false; |
72 | return A.getDFPImm() == B.getDFPImm(); |
73 | } else if (A.isExpr()) { |
74 | if (!B.isExpr()) |
75 | return false; |
76 | return equals(A: *A.getExpr(), B: *B.getExpr(), Comp); |
77 | } else { |
78 | llvm_unreachable("unexpected operand kind" ); |
79 | return false; |
80 | } |
81 | } |
82 | |
83 | bool MCPlusBuilder::equals(const MCExpr &A, const MCExpr &B, |
84 | CompFuncTy Comp) const { |
85 | if (A.getKind() != B.getKind()) |
86 | return false; |
87 | |
88 | switch (A.getKind()) { |
89 | case MCExpr::Constant: { |
90 | const auto &ConstA = cast<MCConstantExpr>(Val: A); |
91 | const auto &ConstB = cast<MCConstantExpr>(Val: B); |
92 | return ConstA.getValue() == ConstB.getValue(); |
93 | } |
94 | |
95 | case MCExpr::SymbolRef: { |
96 | const MCSymbolRefExpr &SymbolA = cast<MCSymbolRefExpr>(Val: A); |
97 | const MCSymbolRefExpr &SymbolB = cast<MCSymbolRefExpr>(Val: B); |
98 | return SymbolA.getKind() == SymbolB.getKind() && |
99 | Comp(&SymbolA.getSymbol(), &SymbolB.getSymbol()); |
100 | } |
101 | |
102 | case MCExpr::Unary: { |
103 | const auto &UnaryA = cast<MCUnaryExpr>(Val: A); |
104 | const auto &UnaryB = cast<MCUnaryExpr>(Val: B); |
105 | return UnaryA.getOpcode() == UnaryB.getOpcode() && |
106 | equals(A: *UnaryA.getSubExpr(), B: *UnaryB.getSubExpr(), Comp); |
107 | } |
108 | |
109 | case MCExpr::Binary: { |
110 | const auto &BinaryA = cast<MCBinaryExpr>(Val: A); |
111 | const auto &BinaryB = cast<MCBinaryExpr>(Val: B); |
112 | return BinaryA.getOpcode() == BinaryB.getOpcode() && |
113 | equals(A: *BinaryA.getLHS(), B: *BinaryB.getLHS(), Comp) && |
114 | equals(A: *BinaryA.getRHS(), B: *BinaryB.getRHS(), Comp); |
115 | } |
116 | |
117 | case MCExpr::Target: { |
118 | const auto &TargetExprA = cast<MCTargetExpr>(Val: A); |
119 | const auto &TargetExprB = cast<MCTargetExpr>(Val: B); |
120 | return equals(A: TargetExprA, B: TargetExprB, Comp); |
121 | } |
122 | } |
123 | |
124 | llvm_unreachable("Invalid expression kind!" ); |
125 | } |
126 | |
127 | bool MCPlusBuilder::equals(const MCTargetExpr &A, const MCTargetExpr &B, |
128 | CompFuncTy Comp) const { |
129 | llvm_unreachable("target-specific expressions are unsupported" ); |
130 | } |
131 | |
132 | bool MCPlusBuilder::isTerminator(const MCInst &Inst) const { |
133 | return Analysis->isTerminator(Inst) || |
134 | (opts::TerminalTrap && Info->get(Opcode: Inst.getOpcode()).isTrap()); |
135 | } |
136 | |
137 | void MCPlusBuilder::setTailCall(MCInst &Inst) const { |
138 | assert(!hasAnnotation(Inst, MCAnnotation::kTailCall)); |
139 | setAnnotationOpValue(Inst, Index: MCAnnotation::kTailCall, Value: true); |
140 | } |
141 | |
142 | bool MCPlusBuilder::isTailCall(const MCInst &Inst) const { |
143 | if (hasAnnotation(Inst, Index: MCAnnotation::kTailCall)) |
144 | return true; |
145 | if (getConditionalTailCall(Inst)) |
146 | return true; |
147 | return false; |
148 | } |
149 | |
150 | std::optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const { |
151 | if (!isCall(Inst)) |
152 | return std::nullopt; |
153 | std::optional<int64_t> LPSym = |
154 | getAnnotationOpValue(Inst, Index: MCAnnotation::kEHLandingPad); |
155 | if (!LPSym) |
156 | return std::nullopt; |
157 | std::optional<int64_t> Action = |
158 | getAnnotationOpValue(Inst, Index: MCAnnotation::kEHAction); |
159 | if (!Action) |
160 | return std::nullopt; |
161 | |
162 | return std::make_pair(x: reinterpret_cast<const MCSymbol *>(*LPSym), |
163 | y: static_cast<uint64_t>(*Action)); |
164 | } |
165 | |
166 | void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) const { |
167 | if (isCall(Inst)) { |
168 | assert(!getEHInfo(Inst)); |
169 | setAnnotationOpValue(Inst, Index: MCAnnotation::kEHLandingPad, |
170 | Value: reinterpret_cast<int64_t>(LP.first)); |
171 | setAnnotationOpValue(Inst, Index: MCAnnotation::kEHAction, |
172 | Value: static_cast<int64_t>(LP.second)); |
173 | } |
174 | } |
175 | |
176 | bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) const { |
177 | if (!isInvoke(Inst)) |
178 | return false; |
179 | |
180 | setAnnotationOpValue(Inst, Index: MCAnnotation::kEHLandingPad, |
181 | Value: reinterpret_cast<int64_t>(LP.first)); |
182 | setAnnotationOpValue(Inst, Index: MCAnnotation::kEHAction, |
183 | Value: static_cast<int64_t>(LP.second)); |
184 | return true; |
185 | } |
186 | |
187 | int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const { |
188 | std::optional<int64_t> Value = |
189 | getAnnotationOpValue(Inst, Index: MCAnnotation::kGnuArgsSize); |
190 | if (!Value) |
191 | return -1LL; |
192 | return *Value; |
193 | } |
194 | |
195 | void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize) const { |
196 | assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value" ); |
197 | assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set" ); |
198 | assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke" ); |
199 | |
200 | setAnnotationOpValue(Inst, Index: MCAnnotation::kGnuArgsSize, Value: GnuArgsSize); |
201 | } |
202 | |
203 | uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const { |
204 | std::optional<int64_t> Value = |
205 | getAnnotationOpValue(Inst, Index: MCAnnotation::kJumpTable); |
206 | if (!Value) |
207 | return 0; |
208 | return *Value; |
209 | } |
210 | |
211 | uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const { |
212 | return getAnnotationAs<uint16_t>(Inst, Name: "JTIndexReg" ); |
213 | } |
214 | |
215 | bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value, |
216 | uint16_t IndexReg, AllocatorIdTy AllocId) { |
217 | if (!isIndirectBranch(Inst)) |
218 | return false; |
219 | setAnnotationOpValue(Inst, Index: MCAnnotation::kJumpTable, Value); |
220 | getOrCreateAnnotationAs<uint16_t>(Inst, Name: "JTIndexReg" , AllocatorId: AllocId) = IndexReg; |
221 | return true; |
222 | } |
223 | |
224 | bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) const { |
225 | if (!getJumpTable(Inst)) |
226 | return false; |
227 | removeAnnotation(Inst, Index: MCAnnotation::kJumpTable); |
228 | removeAnnotation(Inst, Name: "JTIndexReg" ); |
229 | return true; |
230 | } |
231 | |
232 | std::optional<uint64_t> |
233 | MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const { |
234 | std::optional<int64_t> Value = |
235 | getAnnotationOpValue(Inst, Index: MCAnnotation::kConditionalTailCall); |
236 | if (!Value) |
237 | return std::nullopt; |
238 | return static_cast<uint64_t>(*Value); |
239 | } |
240 | |
241 | bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) const { |
242 | if (!isConditionalBranch(Inst)) |
243 | return false; |
244 | |
245 | setAnnotationOpValue(Inst, Index: MCAnnotation::kConditionalTailCall, Value: Dest); |
246 | return true; |
247 | } |
248 | |
249 | bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) const { |
250 | if (!getConditionalTailCall(Inst)) |
251 | return false; |
252 | removeAnnotation(Inst, Index: MCAnnotation::kConditionalTailCall); |
253 | return true; |
254 | } |
255 | |
256 | std::optional<uint32_t> MCPlusBuilder::getOffset(const MCInst &Inst) const { |
257 | std::optional<int64_t> Value = |
258 | getAnnotationOpValue(Inst, Index: MCAnnotation::kOffset); |
259 | if (!Value) |
260 | return std::nullopt; |
261 | return static_cast<uint32_t>(*Value); |
262 | } |
263 | |
264 | uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst, |
265 | uint32_t Default) const { |
266 | if (std::optional<uint32_t> Offset = getOffset(Inst)) |
267 | return *Offset; |
268 | return Default; |
269 | } |
270 | |
271 | bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset) const { |
272 | setAnnotationOpValue(Inst, Index: MCAnnotation::kOffset, Value: Offset); |
273 | return true; |
274 | } |
275 | |
276 | bool MCPlusBuilder::clearOffset(MCInst &Inst) const { |
277 | if (!hasAnnotation(Inst, Index: MCAnnotation::kOffset)) |
278 | return false; |
279 | removeAnnotation(Inst, Index: MCAnnotation::kOffset); |
280 | return true; |
281 | } |
282 | |
283 | MCSymbol *MCPlusBuilder::getInstLabel(const MCInst &Inst) const { |
284 | if (std::optional<int64_t> Label = |
285 | getAnnotationOpValue(Inst, Index: MCAnnotation::kLabel)) |
286 | return reinterpret_cast<MCSymbol *>(*Label); |
287 | return nullptr; |
288 | } |
289 | |
290 | MCSymbol *MCPlusBuilder::getOrCreateInstLabel(MCInst &Inst, const Twine &Name, |
291 | MCContext *Ctx) const { |
292 | MCSymbol *Label = getInstLabel(Inst); |
293 | if (Label) |
294 | return Label; |
295 | |
296 | Label = Ctx->createNamedTempSymbol(Name); |
297 | setAnnotationOpValue(Inst, Index: MCAnnotation::kLabel, |
298 | Value: reinterpret_cast<int64_t>(Label)); |
299 | return Label; |
300 | } |
301 | |
302 | void MCPlusBuilder::setInstLabel(MCInst &Inst, MCSymbol *Label) const { |
303 | assert(!getInstLabel(Inst) && "Instruction already has assigned label." ); |
304 | setAnnotationOpValue(Inst, Index: MCAnnotation::kLabel, |
305 | Value: reinterpret_cast<int64_t>(Label)); |
306 | } |
307 | |
308 | std::optional<uint32_t> MCPlusBuilder::getSize(const MCInst &Inst) const { |
309 | if (std::optional<int64_t> Value = |
310 | getAnnotationOpValue(Inst, Index: MCAnnotation::kSize)) |
311 | return static_cast<uint32_t>(*Value); |
312 | return std::nullopt; |
313 | } |
314 | |
315 | void MCPlusBuilder::setSize(MCInst &Inst, uint32_t Size) const { |
316 | setAnnotationOpValue(Inst, Index: MCAnnotation::kSize, Value: Size); |
317 | } |
318 | |
319 | bool MCPlusBuilder::isDynamicBranch(const MCInst &Inst) const { |
320 | if (!hasAnnotation(Inst, Index: MCAnnotation::kDynamicBranch)) |
321 | return false; |
322 | assert(isBranch(Inst) && "Branch expected." ); |
323 | return true; |
324 | } |
325 | |
326 | std::optional<uint32_t> |
327 | MCPlusBuilder::getDynamicBranchID(const MCInst &Inst) const { |
328 | if (std::optional<int64_t> Value = |
329 | getAnnotationOpValue(Inst, Index: MCAnnotation::kDynamicBranch)) { |
330 | assert(isBranch(Inst) && "Branch expected." ); |
331 | return static_cast<uint32_t>(*Value); |
332 | } |
333 | return std::nullopt; |
334 | } |
335 | |
336 | void MCPlusBuilder::setDynamicBranch(MCInst &Inst, uint32_t ID) const { |
337 | assert(isBranch(Inst) && "Branch expected." ); |
338 | setAnnotationOpValue(Inst, Index: MCAnnotation::kDynamicBranch, Value: ID); |
339 | } |
340 | |
341 | bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const { |
342 | return (bool)getAnnotationOpValue(Inst, Index); |
343 | } |
344 | |
345 | bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) const { |
346 | std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst); |
347 | if (!FirstAnnotationOp) |
348 | return false; |
349 | |
350 | for (unsigned I = Inst.getNumOperands() - 1; I >= *FirstAnnotationOp; --I) { |
351 | const int64_t ImmValue = Inst.getOperand(i: I).getImm(); |
352 | if (extractAnnotationIndex(ImmValue) == Index) { |
353 | Inst.erase(I: Inst.begin() + I); |
354 | return true; |
355 | } |
356 | } |
357 | return false; |
358 | } |
359 | |
360 | void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) const { |
361 | KeepTC &= hasAnnotation(Inst, Index: MCAnnotation::kTailCall); |
362 | |
363 | removeAnnotations(Inst); |
364 | |
365 | if (KeepTC) |
366 | setTailCall(Inst); |
367 | } |
368 | |
369 | void MCPlusBuilder::printAnnotations(const MCInst &Inst, |
370 | raw_ostream &OS) const { |
371 | std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst); |
372 | if (!FirstAnnotationOp) |
373 | return; |
374 | |
375 | for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) { |
376 | const int64_t Imm = Inst.getOperand(i: I).getImm(); |
377 | const unsigned Index = extractAnnotationIndex(ImmValue: Imm); |
378 | const int64_t Value = extractAnnotationValue(ImmValue: Imm); |
379 | const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value); |
380 | if (Index >= MCAnnotation::kGeneric) { |
381 | OS << " # " << AnnotationNames[Index - MCAnnotation::kGeneric] << ": " ; |
382 | Annotation->print(OS); |
383 | } |
384 | } |
385 | } |
386 | |
387 | void MCPlusBuilder::getClobberedRegs(const MCInst &Inst, |
388 | BitVector &Regs) const { |
389 | if (isPrefix(Inst) || isCFI(Inst)) |
390 | return; |
391 | |
392 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
393 | |
394 | for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) |
395 | Regs |= getAliases(Reg: ImplicitDef, /*OnlySmaller=*/false); |
396 | |
397 | for (const MCOperand &Operand : defOperands(Inst)) { |
398 | assert(Operand.isReg()); |
399 | Regs |= getAliases(Reg: Operand.getReg(), /*OnlySmaller=*/false); |
400 | } |
401 | } |
402 | |
403 | void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const { |
404 | if (isPrefix(Inst) || isCFI(Inst)) |
405 | return; |
406 | |
407 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
408 | |
409 | for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) |
410 | Regs |= getAliases(Reg: ImplicitDef, /*OnlySmaller=*/false); |
411 | for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) |
412 | Regs |= getAliases(Reg: ImplicitUse, /*OnlySmaller=*/false); |
413 | |
414 | for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) { |
415 | if (!Inst.getOperand(i: I).isReg()) |
416 | continue; |
417 | Regs |= getAliases(Reg: Inst.getOperand(i: I).getReg(), /*OnlySmaller=*/false); |
418 | } |
419 | } |
420 | |
421 | void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const { |
422 | if (isPrefix(Inst) || isCFI(Inst)) |
423 | return; |
424 | |
425 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
426 | |
427 | for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) |
428 | Regs |= getAliases(Reg: ImplicitDef, /*OnlySmaller=*/true); |
429 | |
430 | for (const MCOperand &Operand : defOperands(Inst)) { |
431 | assert(Operand.isReg()); |
432 | Regs |= getAliases(Reg: Operand.getReg(), /*OnlySmaller=*/true); |
433 | } |
434 | } |
435 | |
436 | void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const { |
437 | if (isPrefix(Inst) || isCFI(Inst)) |
438 | return; |
439 | |
440 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
441 | |
442 | for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) |
443 | Regs |= getAliases(Reg: ImplicitUse, /*OnlySmaller=*/true); |
444 | |
445 | for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) { |
446 | if (!Inst.getOperand(i: I).isReg()) |
447 | continue; |
448 | Regs |= getAliases(Reg: Inst.getOperand(i: I).getReg(), /*OnlySmaller=*/true); |
449 | } |
450 | } |
451 | |
452 | void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const { |
453 | if (isPrefix(Inst) || isCFI(Inst)) |
454 | return; |
455 | |
456 | if (isCall(Inst)) { |
457 | BitVector CallRegs = BitVector(Regs.size(), false); |
458 | getCalleeSavedRegs(Regs&: CallRegs); |
459 | CallRegs.flip(); |
460 | Regs |= CallRegs; |
461 | return; |
462 | } |
463 | |
464 | if (isReturn(Inst)) { |
465 | getDefaultLiveOut(Regs); |
466 | return; |
467 | } |
468 | |
469 | if (isRep(Inst)) |
470 | getRepRegs(Regs); |
471 | |
472 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
473 | |
474 | for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) |
475 | Regs |= getAliases(Reg: ImplicitUse, /*OnlySmaller=*/true); |
476 | |
477 | for (const MCOperand &Operand : useOperands(Inst)) |
478 | if (Operand.isReg()) |
479 | Regs |= getAliases(Reg: Operand.getReg(), /*OnlySmaller=*/true); |
480 | } |
481 | |
482 | bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const { |
483 | const MCInstrDesc &InstInfo = Info->get(Opcode: MI.getOpcode()); |
484 | return InstInfo.hasDefOfPhysReg(MI, Reg, RI: *RegInfo); |
485 | } |
486 | |
487 | bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const { |
488 | const MCInstrDesc &InstInfo = Info->get(Opcode: MI.getOpcode()); |
489 | for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I) |
490 | if (MI.getOperand(i: I).isReg() && MI.getOperand(i: I).getReg() && |
491 | RegInfo->isSubRegisterEq(RegA: Reg, RegB: MI.getOperand(i: I).getReg())) |
492 | return true; |
493 | for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) { |
494 | if (ImplicitUse == Reg || RegInfo->isSubRegister(RegA: Reg, RegB: ImplicitUse)) |
495 | return true; |
496 | } |
497 | return false; |
498 | } |
499 | |
500 | const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg, |
501 | bool OnlySmaller) const { |
502 | if (OnlySmaller) |
503 | return SmallerAliasMap[Reg]; |
504 | return AliasMap[Reg]; |
505 | } |
506 | |
507 | void MCPlusBuilder::initAliases() { |
508 | assert(AliasMap.size() == 0 && SmallerAliasMap.size() == 0); |
509 | // Build alias map |
510 | for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) { |
511 | BitVector BV(RegInfo->getNumRegs(), false); |
512 | BV.set(I); |
513 | AliasMap.emplace_back(args&: BV); |
514 | SmallerAliasMap.emplace_back(args&: BV); |
515 | } |
516 | |
517 | // Cache all aliases for each register |
518 | for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I != E; ++I) { |
519 | for (MCRegAliasIterator AI(I, RegInfo, true); AI.isValid(); ++AI) |
520 | AliasMap[I].set(*AI); |
521 | } |
522 | |
523 | // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister) |
524 | for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I) |
525 | for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI) |
526 | SmallerAliasMap[I] |= SmallerAliasMap[*SI]; |
527 | |
528 | LLVM_DEBUG({ |
529 | dbgs() << "Dumping reg alias table:\n" ; |
530 | for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) { |
531 | dbgs() << "Reg " << I << ": " ; |
532 | const BitVector &BV = AliasMap[I]; |
533 | int Idx = BV.find_first(); |
534 | while (Idx != -1) { |
535 | dbgs() << Idx << " " ; |
536 | Idx = BV.find_next(Idx); |
537 | } |
538 | dbgs() << "\n" ; |
539 | } |
540 | }); |
541 | } |
542 | |
543 | void MCPlusBuilder::initSizeMap() { |
544 | SizeMap.resize(new_size: RegInfo->getNumRegs()); |
545 | // Build size map |
546 | for (auto RC : RegInfo->regclasses()) |
547 | for (MCPhysReg Reg : RC) |
548 | SizeMap[Reg] = RC.getSizeInBits() / 8; |
549 | } |
550 | |
551 | bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum, |
552 | const MCSymbol *Symbol, |
553 | int64_t Addend, MCContext *Ctx, |
554 | uint64_t RelType) const { |
555 | MCOperand Operand; |
556 | if (!Addend) { |
557 | Operand = MCOperand::createExpr(Val: getTargetExprFor( |
558 | Inst, Expr: MCSymbolRefExpr::create(Symbol, Ctx&: *Ctx), Ctx&: *Ctx, RelType)); |
559 | } else { |
560 | Operand = MCOperand::createExpr(Val: getTargetExprFor( |
561 | Inst, |
562 | Expr: MCBinaryExpr::createAdd(LHS: MCSymbolRefExpr::create(Symbol, Ctx&: *Ctx), |
563 | RHS: MCConstantExpr::create(Value: Addend, Ctx&: *Ctx), Ctx&: *Ctx), |
564 | Ctx&: *Ctx, RelType)); |
565 | } |
566 | Inst.getOperand(i: OpNum) = Operand; |
567 | return true; |
568 | } |
569 | |