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::Specifier: { |
118 | const auto &TargetExprA = cast<MCSpecifierExpr>(Val: A); |
119 | const auto &TargetExprB = cast<MCSpecifierExpr>(Val: B); |
120 | return equals(A: TargetExprA, B: TargetExprB, Comp); |
121 | } |
122 | case MCExpr::Target: |
123 | llvm_unreachable("Not implemented"); |
124 | } |
125 | |
126 | llvm_unreachable("Invalid expression kind!"); |
127 | } |
128 | |
129 | bool MCPlusBuilder::equals(const MCSpecifierExpr &A, const MCSpecifierExpr &B, |
130 | CompFuncTy Comp) const { |
131 | llvm_unreachable("target-specific expressions are unsupported"); |
132 | } |
133 | |
134 | bool MCPlusBuilder::isTerminator(const MCInst &Inst) const { |
135 | return Analysis->isTerminator(Inst) || |
136 | (opts::TerminalTrap && Info->get(Opcode: Inst.getOpcode()).isTrap()); |
137 | } |
138 | |
139 | void MCPlusBuilder::setTailCall(MCInst &Inst) const { |
140 | assert(!hasAnnotation(Inst, MCAnnotation::kTailCall)); |
141 | setAnnotationOpValue(Inst, Index: MCAnnotation::kTailCall, Value: true); |
142 | } |
143 | |
144 | bool MCPlusBuilder::isTailCall(const MCInst &Inst) const { |
145 | if (hasAnnotation(Inst, Index: MCAnnotation::kTailCall)) |
146 | return true; |
147 | if (getConditionalTailCall(Inst)) |
148 | return true; |
149 | return false; |
150 | } |
151 | |
152 | std::optional<MCLandingPad> MCPlusBuilder::getEHInfo(const MCInst &Inst) const { |
153 | if (!isCall(Inst)) |
154 | return std::nullopt; |
155 | std::optional<int64_t> LPSym = |
156 | getAnnotationOpValue(Inst, Index: MCAnnotation::kEHLandingPad); |
157 | if (!LPSym) |
158 | return std::nullopt; |
159 | std::optional<int64_t> Action = |
160 | getAnnotationOpValue(Inst, Index: MCAnnotation::kEHAction); |
161 | if (!Action) |
162 | return std::nullopt; |
163 | |
164 | return std::make_pair(x: reinterpret_cast<const MCSymbol *>(*LPSym), |
165 | y: static_cast<uint64_t>(*Action)); |
166 | } |
167 | |
168 | void MCPlusBuilder::addEHInfo(MCInst &Inst, const MCLandingPad &LP) const { |
169 | if (isCall(Inst)) { |
170 | assert(!getEHInfo(Inst)); |
171 | setAnnotationOpValue(Inst, Index: MCAnnotation::kEHLandingPad, |
172 | Value: reinterpret_cast<int64_t>(LP.first)); |
173 | setAnnotationOpValue(Inst, Index: MCAnnotation::kEHAction, |
174 | Value: static_cast<int64_t>(LP.second)); |
175 | } |
176 | } |
177 | |
178 | bool MCPlusBuilder::updateEHInfo(MCInst &Inst, const MCLandingPad &LP) const { |
179 | if (!isInvoke(Inst)) |
180 | return false; |
181 | |
182 | setAnnotationOpValue(Inst, Index: MCAnnotation::kEHLandingPad, |
183 | Value: reinterpret_cast<int64_t>(LP.first)); |
184 | setAnnotationOpValue(Inst, Index: MCAnnotation::kEHAction, |
185 | Value: static_cast<int64_t>(LP.second)); |
186 | return true; |
187 | } |
188 | |
189 | int64_t MCPlusBuilder::getGnuArgsSize(const MCInst &Inst) const { |
190 | std::optional<int64_t> Value = |
191 | getAnnotationOpValue(Inst, Index: MCAnnotation::kGnuArgsSize); |
192 | if (!Value) |
193 | return -1LL; |
194 | return *Value; |
195 | } |
196 | |
197 | void MCPlusBuilder::addGnuArgsSize(MCInst &Inst, int64_t GnuArgsSize) const { |
198 | assert(GnuArgsSize >= 0 && "cannot set GNU_args_size to negative value"); |
199 | assert(getGnuArgsSize(Inst) == -1LL && "GNU_args_size already set"); |
200 | assert(isInvoke(Inst) && "GNU_args_size can only be set for invoke"); |
201 | |
202 | setAnnotationOpValue(Inst, Index: MCAnnotation::kGnuArgsSize, Value: GnuArgsSize); |
203 | } |
204 | |
205 | uint64_t MCPlusBuilder::getJumpTable(const MCInst &Inst) const { |
206 | std::optional<int64_t> Value = |
207 | getAnnotationOpValue(Inst, Index: MCAnnotation::kJumpTable); |
208 | if (!Value) |
209 | return 0; |
210 | return *Value; |
211 | } |
212 | |
213 | uint16_t MCPlusBuilder::getJumpTableIndexReg(const MCInst &Inst) const { |
214 | return getAnnotationAs<uint16_t>(Inst, Name: "JTIndexReg"); |
215 | } |
216 | |
217 | bool MCPlusBuilder::setJumpTable(MCInst &Inst, uint64_t Value, |
218 | uint16_t IndexReg, AllocatorIdTy AllocId) { |
219 | if (!isIndirectBranch(Inst)) |
220 | return false; |
221 | setAnnotationOpValue(Inst, Index: MCAnnotation::kJumpTable, Value); |
222 | getOrCreateAnnotationAs<uint16_t>(Inst, Name: "JTIndexReg", AllocatorId: AllocId) = IndexReg; |
223 | return true; |
224 | } |
225 | |
226 | bool MCPlusBuilder::unsetJumpTable(MCInst &Inst) const { |
227 | if (!getJumpTable(Inst)) |
228 | return false; |
229 | removeAnnotation(Inst, Index: MCAnnotation::kJumpTable); |
230 | removeAnnotation(Inst, Name: "JTIndexReg"); |
231 | return true; |
232 | } |
233 | |
234 | std::optional<uint64_t> |
235 | MCPlusBuilder::getConditionalTailCall(const MCInst &Inst) const { |
236 | std::optional<int64_t> Value = |
237 | getAnnotationOpValue(Inst, Index: MCAnnotation::kConditionalTailCall); |
238 | if (!Value) |
239 | return std::nullopt; |
240 | return static_cast<uint64_t>(*Value); |
241 | } |
242 | |
243 | bool MCPlusBuilder::setConditionalTailCall(MCInst &Inst, uint64_t Dest) const { |
244 | if (!isConditionalBranch(Inst)) |
245 | return false; |
246 | |
247 | setAnnotationOpValue(Inst, Index: MCAnnotation::kConditionalTailCall, Value: Dest); |
248 | return true; |
249 | } |
250 | |
251 | bool MCPlusBuilder::unsetConditionalTailCall(MCInst &Inst) const { |
252 | if (!getConditionalTailCall(Inst)) |
253 | return false; |
254 | removeAnnotation(Inst, Index: MCAnnotation::kConditionalTailCall); |
255 | return true; |
256 | } |
257 | |
258 | std::optional<uint32_t> MCPlusBuilder::getOffset(const MCInst &Inst) const { |
259 | std::optional<int64_t> Value = |
260 | getAnnotationOpValue(Inst, Index: MCAnnotation::kOffset); |
261 | if (!Value) |
262 | return std::nullopt; |
263 | return static_cast<uint32_t>(*Value); |
264 | } |
265 | |
266 | uint32_t MCPlusBuilder::getOffsetWithDefault(const MCInst &Inst, |
267 | uint32_t Default) const { |
268 | if (std::optional<uint32_t> Offset = getOffset(Inst)) |
269 | return *Offset; |
270 | return Default; |
271 | } |
272 | |
273 | bool MCPlusBuilder::setOffset(MCInst &Inst, uint32_t Offset) const { |
274 | setAnnotationOpValue(Inst, Index: MCAnnotation::kOffset, Value: Offset); |
275 | return true; |
276 | } |
277 | |
278 | bool MCPlusBuilder::clearOffset(MCInst &Inst) const { |
279 | if (!hasAnnotation(Inst, Index: MCAnnotation::kOffset)) |
280 | return false; |
281 | removeAnnotation(Inst, Index: MCAnnotation::kOffset); |
282 | return true; |
283 | } |
284 | |
285 | MCSymbol *MCPlusBuilder::getInstLabel(const MCInst &Inst) const { |
286 | if (std::optional<int64_t> Label = |
287 | getAnnotationOpValue(Inst, Index: MCAnnotation::kLabel)) |
288 | return reinterpret_cast<MCSymbol *>(*Label); |
289 | return nullptr; |
290 | } |
291 | |
292 | MCSymbol *MCPlusBuilder::getOrCreateInstLabel(MCInst &Inst, const Twine &Name, |
293 | MCContext *Ctx) const { |
294 | MCSymbol *Label = getInstLabel(Inst); |
295 | if (Label) |
296 | return Label; |
297 | |
298 | Label = Ctx->createNamedTempSymbol(Name); |
299 | setAnnotationOpValue(Inst, Index: MCAnnotation::kLabel, |
300 | Value: reinterpret_cast<int64_t>(Label)); |
301 | return Label; |
302 | } |
303 | |
304 | void MCPlusBuilder::setInstLabel(MCInst &Inst, MCSymbol *Label) const { |
305 | assert(!getInstLabel(Inst) && "Instruction already has assigned label."); |
306 | setAnnotationOpValue(Inst, Index: MCAnnotation::kLabel, |
307 | Value: reinterpret_cast<int64_t>(Label)); |
308 | } |
309 | |
310 | std::optional<uint32_t> MCPlusBuilder::getSize(const MCInst &Inst) const { |
311 | if (std::optional<int64_t> Value = |
312 | getAnnotationOpValue(Inst, Index: MCAnnotation::kSize)) |
313 | return static_cast<uint32_t>(*Value); |
314 | return std::nullopt; |
315 | } |
316 | |
317 | void MCPlusBuilder::setSize(MCInst &Inst, uint32_t Size) const { |
318 | setAnnotationOpValue(Inst, Index: MCAnnotation::kSize, Value: Size); |
319 | } |
320 | |
321 | bool MCPlusBuilder::isDynamicBranch(const MCInst &Inst) const { |
322 | if (!hasAnnotation(Inst, Index: MCAnnotation::kDynamicBranch)) |
323 | return false; |
324 | assert(isBranch(Inst) && "Branch expected."); |
325 | return true; |
326 | } |
327 | |
328 | std::optional<uint32_t> |
329 | MCPlusBuilder::getDynamicBranchID(const MCInst &Inst) const { |
330 | if (std::optional<int64_t> Value = |
331 | getAnnotationOpValue(Inst, Index: MCAnnotation::kDynamicBranch)) { |
332 | assert(isBranch(Inst) && "Branch expected."); |
333 | return static_cast<uint32_t>(*Value); |
334 | } |
335 | return std::nullopt; |
336 | } |
337 | |
338 | void MCPlusBuilder::setDynamicBranch(MCInst &Inst, uint32_t ID) const { |
339 | assert(isBranch(Inst) && "Branch expected."); |
340 | setAnnotationOpValue(Inst, Index: MCAnnotation::kDynamicBranch, Value: ID); |
341 | } |
342 | |
343 | bool MCPlusBuilder::hasAnnotation(const MCInst &Inst, unsigned Index) const { |
344 | return (bool)getAnnotationOpValue(Inst, Index); |
345 | } |
346 | |
347 | bool MCPlusBuilder::removeAnnotation(MCInst &Inst, unsigned Index) const { |
348 | std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst); |
349 | if (!FirstAnnotationOp) |
350 | return false; |
351 | |
352 | for (unsigned I = Inst.getNumOperands() - 1; I >= *FirstAnnotationOp; --I) { |
353 | const int64_t ImmValue = Inst.getOperand(i: I).getImm(); |
354 | if (extractAnnotationIndex(ImmValue) == Index) { |
355 | Inst.erase(I: Inst.begin() + I); |
356 | return true; |
357 | } |
358 | } |
359 | return false; |
360 | } |
361 | |
362 | void MCPlusBuilder::stripAnnotations(MCInst &Inst, bool KeepTC) const { |
363 | KeepTC &= hasAnnotation(Inst, Index: MCAnnotation::kTailCall); |
364 | |
365 | removeAnnotations(Inst); |
366 | |
367 | if (KeepTC) |
368 | setTailCall(Inst); |
369 | } |
370 | |
371 | void MCPlusBuilder::printAnnotations(const MCInst &Inst, |
372 | raw_ostream &OS) const { |
373 | std::optional<unsigned> FirstAnnotationOp = getFirstAnnotationOpIndex(Inst); |
374 | if (!FirstAnnotationOp) |
375 | return; |
376 | |
377 | for (unsigned I = *FirstAnnotationOp; I < Inst.getNumOperands(); ++I) { |
378 | const int64_t Imm = Inst.getOperand(i: I).getImm(); |
379 | const unsigned Index = extractAnnotationIndex(ImmValue: Imm); |
380 | const int64_t Value = extractAnnotationValue(ImmValue: Imm); |
381 | const auto *Annotation = reinterpret_cast<const MCAnnotation *>(Value); |
382 | if (Index >= MCAnnotation::kGeneric) { |
383 | OS << " # "<< AnnotationNames[Index - MCAnnotation::kGeneric] << ": "; |
384 | Annotation->print(OS); |
385 | } |
386 | } |
387 | } |
388 | |
389 | void MCPlusBuilder::getClobberedRegs(const MCInst &Inst, |
390 | BitVector &Regs) const { |
391 | if (isPrefix(Inst) || isCFI(Inst)) |
392 | return; |
393 | |
394 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
395 | |
396 | for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) |
397 | Regs |= getAliases(Reg: ImplicitDef, /*OnlySmaller=*/false); |
398 | |
399 | for (const MCOperand &Operand : defOperands(Inst)) { |
400 | assert(Operand.isReg()); |
401 | Regs |= getAliases(Reg: Operand.getReg(), /*OnlySmaller=*/false); |
402 | } |
403 | } |
404 | |
405 | void MCPlusBuilder::getTouchedRegs(const MCInst &Inst, BitVector &Regs) const { |
406 | if (isPrefix(Inst) || isCFI(Inst)) |
407 | return; |
408 | |
409 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
410 | |
411 | for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) |
412 | Regs |= getAliases(Reg: ImplicitDef, /*OnlySmaller=*/false); |
413 | for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) |
414 | Regs |= getAliases(Reg: ImplicitUse, /*OnlySmaller=*/false); |
415 | |
416 | for (unsigned I = 0, E = Inst.getNumOperands(); I != E; ++I) { |
417 | if (!Inst.getOperand(i: I).isReg()) |
418 | continue; |
419 | Regs |= getAliases(Reg: Inst.getOperand(i: I).getReg(), /*OnlySmaller=*/false); |
420 | } |
421 | } |
422 | |
423 | void MCPlusBuilder::getWrittenRegs(const MCInst &Inst, BitVector &Regs) const { |
424 | if (isPrefix(Inst) || isCFI(Inst)) |
425 | return; |
426 | |
427 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
428 | |
429 | for (MCPhysReg ImplicitDef : InstInfo.implicit_defs()) |
430 | Regs |= getAliases(Reg: ImplicitDef, /*OnlySmaller=*/true); |
431 | |
432 | for (const MCOperand &Operand : defOperands(Inst)) { |
433 | assert(Operand.isReg()); |
434 | Regs |= getAliases(Reg: Operand.getReg(), /*OnlySmaller=*/true); |
435 | } |
436 | } |
437 | |
438 | void MCPlusBuilder::getUsedRegs(const MCInst &Inst, BitVector &Regs) const { |
439 | if (isPrefix(Inst) || isCFI(Inst)) |
440 | return; |
441 | |
442 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
443 | |
444 | for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) |
445 | Regs |= getAliases(Reg: ImplicitUse, /*OnlySmaller=*/true); |
446 | |
447 | for (const MCOperand &Operand : useOperands(Inst)) { |
448 | if (!Operand.isReg()) |
449 | continue; |
450 | Regs |= getAliases(Reg: Operand.getReg(), /*OnlySmaller=*/true); |
451 | } |
452 | } |
453 | |
454 | void MCPlusBuilder::getSrcRegs(const MCInst &Inst, BitVector &Regs) const { |
455 | if (isPrefix(Inst) || isCFI(Inst)) |
456 | return; |
457 | |
458 | if (isCall(Inst)) { |
459 | BitVector CallRegs = BitVector(Regs.size(), false); |
460 | getCalleeSavedRegs(Regs&: CallRegs); |
461 | CallRegs.flip(); |
462 | Regs |= CallRegs; |
463 | return; |
464 | } |
465 | |
466 | if (isReturn(Inst)) { |
467 | getDefaultLiveOut(Regs); |
468 | return; |
469 | } |
470 | |
471 | if (isRep(Inst)) |
472 | getRepRegs(Regs); |
473 | |
474 | const MCInstrDesc &InstInfo = Info->get(Opcode: Inst.getOpcode()); |
475 | |
476 | for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) |
477 | Regs |= getAliases(Reg: ImplicitUse, /*OnlySmaller=*/true); |
478 | |
479 | for (const MCOperand &Operand : useOperands(Inst)) |
480 | if (Operand.isReg()) |
481 | Regs |= getAliases(Reg: Operand.getReg(), /*OnlySmaller=*/true); |
482 | } |
483 | |
484 | bool MCPlusBuilder::hasDefOfPhysReg(const MCInst &MI, unsigned Reg) const { |
485 | const MCInstrDesc &InstInfo = Info->get(Opcode: MI.getOpcode()); |
486 | return InstInfo.hasDefOfPhysReg(MI, Reg, RI: *RegInfo); |
487 | } |
488 | |
489 | bool MCPlusBuilder::hasUseOfPhysReg(const MCInst &MI, unsigned Reg) const { |
490 | const MCInstrDesc &InstInfo = Info->get(Opcode: MI.getOpcode()); |
491 | for (int I = InstInfo.NumDefs; I < InstInfo.NumOperands; ++I) |
492 | if (MI.getOperand(i: I).isReg() && MI.getOperand(i: I).getReg() && |
493 | RegInfo->isSubRegisterEq(RegA: Reg, RegB: MI.getOperand(i: I).getReg())) |
494 | return true; |
495 | for (MCPhysReg ImplicitUse : InstInfo.implicit_uses()) { |
496 | if (ImplicitUse == Reg || RegInfo->isSubRegister(RegA: Reg, RegB: ImplicitUse)) |
497 | return true; |
498 | } |
499 | return false; |
500 | } |
501 | |
502 | const BitVector &MCPlusBuilder::getAliases(MCPhysReg Reg, |
503 | bool OnlySmaller) const { |
504 | if (OnlySmaller) |
505 | return SmallerAliasMap[Reg]; |
506 | return AliasMap[Reg]; |
507 | } |
508 | |
509 | void MCPlusBuilder::initAliases() { |
510 | assert(AliasMap.size() == 0 && SmallerAliasMap.size() == 0); |
511 | // Build alias map |
512 | for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) { |
513 | BitVector BV(RegInfo->getNumRegs(), false); |
514 | BV.set(I); |
515 | AliasMap.emplace_back(args&: BV); |
516 | SmallerAliasMap.emplace_back(args&: BV); |
517 | } |
518 | |
519 | // Cache all aliases for each register |
520 | for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I != E; ++I) { |
521 | for (MCRegAliasIterator AI(I, RegInfo, true); AI.isValid(); ++AI) |
522 | AliasMap[I].set(*AI); |
523 | } |
524 | |
525 | // Propagate smaller alias info upwards. Skip reg 0 (mapped to NoRegister) |
526 | for (MCPhysReg I = 1, E = RegInfo->getNumRegs(); I < E; ++I) |
527 | for (MCSubRegIterator SI(I, RegInfo); SI.isValid(); ++SI) |
528 | SmallerAliasMap[I] |= SmallerAliasMap[*SI]; |
529 | |
530 | LLVM_DEBUG({ |
531 | dbgs() << "Dumping reg alias table:\n"; |
532 | for (MCPhysReg I = 0, E = RegInfo->getNumRegs(); I != E; ++I) { |
533 | dbgs() << "Reg "<< I << ": "; |
534 | const BitVector &BV = AliasMap[I]; |
535 | int Idx = BV.find_first(); |
536 | while (Idx != -1) { |
537 | dbgs() << Idx << " "; |
538 | Idx = BV.find_next(Idx); |
539 | } |
540 | dbgs() << "\n"; |
541 | } |
542 | }); |
543 | } |
544 | |
545 | void MCPlusBuilder::initSizeMap() { |
546 | SizeMap.resize(new_size: RegInfo->getNumRegs()); |
547 | // Build size map |
548 | for (auto RC : RegInfo->regclasses()) |
549 | for (MCPhysReg Reg : RC) |
550 | SizeMap[Reg] = RC.getSizeInBits() / 8; |
551 | } |
552 | |
553 | bool MCPlusBuilder::setOperandToSymbolRef(MCInst &Inst, int OpNum, |
554 | const MCSymbol *Symbol, |
555 | int64_t Addend, MCContext *Ctx, |
556 | uint32_t RelType) const { |
557 | MCOperand Operand; |
558 | if (!Addend) { |
559 | Operand = MCOperand::createExpr(Val: getTargetExprFor( |
560 | Inst, Expr: MCSymbolRefExpr::create(Symbol, Ctx&: *Ctx), Ctx&: *Ctx, RelType)); |
561 | } else { |
562 | Operand = MCOperand::createExpr(Val: getTargetExprFor( |
563 | Inst, |
564 | Expr: MCBinaryExpr::createAdd(LHS: MCSymbolRefExpr::create(Symbol, Ctx&: *Ctx), |
565 | RHS: MCConstantExpr::create(Value: Addend, Ctx&: *Ctx), Ctx&: *Ctx), |
566 | Ctx&: *Ctx, RelType)); |
567 | } |
568 | Inst.getOperand(i: OpNum) = Operand; |
569 | return true; |
570 | } |
571 |
Definitions
- TerminalTrap
- equals
- equals
- equals
- equals
- isTerminator
- setTailCall
- isTailCall
- getEHInfo
- addEHInfo
- updateEHInfo
- getGnuArgsSize
- addGnuArgsSize
- getJumpTable
- getJumpTableIndexReg
- setJumpTable
- unsetJumpTable
- getConditionalTailCall
- setConditionalTailCall
- unsetConditionalTailCall
- getOffset
- getOffsetWithDefault
- setOffset
- clearOffset
- getInstLabel
- getOrCreateInstLabel
- setInstLabel
- getSize
- setSize
- isDynamicBranch
- getDynamicBranchID
- setDynamicBranch
- hasAnnotation
- removeAnnotation
- stripAnnotations
- printAnnotations
- getClobberedRegs
- getTouchedRegs
- getWrittenRegs
- getUsedRegs
- getSrcRegs
- hasDefOfPhysReg
- hasUseOfPhysReg
- getAliases
- initAliases
- initSizeMap
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more