1 | //===- Instruction.cpp - The Instructions of Sandbox IR -------------------===// |
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 | #include "llvm/SandboxIR/Instruction.h" |
10 | #include "llvm/SandboxIR/Function.h" |
11 | |
12 | namespace llvm::sandboxir { |
13 | |
14 | const char *Instruction::getOpcodeName(Opcode Opc) { |
15 | switch (Opc) { |
16 | #define OP(OPC) \ |
17 | case Opcode::OPC: \ |
18 | return #OPC; |
19 | #define OPCODES(...) __VA_ARGS__ |
20 | #define DEF_INSTR(ID, OPC, CLASS) OPC |
21 | #include "llvm/SandboxIR/Values.def" |
22 | } |
23 | llvm_unreachable("Unknown Opcode" ); |
24 | } |
25 | |
26 | llvm::Instruction *Instruction::getTopmostLLVMInstruction() const { |
27 | Instruction *Prev = getPrevNode(); |
28 | if (Prev == nullptr) { |
29 | // If at top of the BB, return the first BB instruction. |
30 | return &*cast<llvm::BasicBlock>(Val: getParent()->Val)->begin(); |
31 | } |
32 | // Else get the Previous sandbox IR instruction's bottom IR instruction and |
33 | // return its successor. |
34 | llvm::Instruction *PrevBotI = cast<llvm::Instruction>(Val: Prev->Val); |
35 | return PrevBotI->getNextNode(); |
36 | } |
37 | |
38 | BBIterator Instruction::getIterator() const { |
39 | auto *I = cast<llvm::Instruction>(Val); |
40 | return BasicBlock::iterator(I->getParent(), I->getIterator(), &Ctx); |
41 | } |
42 | |
43 | Instruction *Instruction::getNextNode() const { |
44 | assert(getParent() != nullptr && "Detached!" ); |
45 | assert(getIterator() != getParent()->end() && "Already at end!" ); |
46 | // `Val` is the bottom-most LLVM IR instruction. Get the next in the chain, |
47 | // and get the corresponding sandboxir Instruction that maps to it. This works |
48 | // even for SandboxIR Instructions that map to more than one LLVM Instruction. |
49 | auto *LLVMI = cast<llvm::Instruction>(Val); |
50 | assert(LLVMI->getParent() != nullptr && "LLVM IR instr is detached!" ); |
51 | auto *NextLLVMI = LLVMI->getNextNode(); |
52 | auto *NextI = cast_or_null<Instruction>(Val: Ctx.getValue(V: NextLLVMI)); |
53 | if (NextI == nullptr) |
54 | return nullptr; |
55 | return NextI; |
56 | } |
57 | |
58 | Instruction *Instruction::getPrevNode() const { |
59 | assert(getParent() != nullptr && "Detached!" ); |
60 | auto It = getIterator(); |
61 | if (It != getParent()->begin()) |
62 | return std::prev(x: getIterator()).get(); |
63 | return nullptr; |
64 | } |
65 | |
66 | void Instruction::removeFromParent() { |
67 | Ctx.getTracker().emplaceIfTracking<RemoveFromParent>(Args: this); |
68 | |
69 | // Detach all the LLVM IR instructions from their parent BB. |
70 | for (llvm::Instruction *I : getLLVMInstrs()) |
71 | I->removeFromParent(); |
72 | } |
73 | |
74 | void Instruction::eraseFromParent() { |
75 | assert(users().empty() && "Still connected to users, can't erase!" ); |
76 | |
77 | Ctx.runEraseInstrCallbacks(I: this); |
78 | std::unique_ptr<Value> Detached = Ctx.detach(V: this); |
79 | auto LLVMInstrs = getLLVMInstrs(); |
80 | |
81 | auto &Tracker = Ctx.getTracker(); |
82 | if (Tracker.isTracking()) { |
83 | Tracker.track(Change: std::make_unique<EraseFromParent>(args: std::move(Detached))); |
84 | // We don't actually delete the IR instruction, because then it would be |
85 | // impossible to bring it back from the dead at the same memory location. |
86 | // Instead we remove it from its BB and track its current location. |
87 | for (llvm::Instruction *I : LLVMInstrs) |
88 | I->removeFromParent(); |
89 | // TODO: Multi-instructions need special treatment because some of the |
90 | // references are internal to the instruction. |
91 | for (llvm::Instruction *I : LLVMInstrs) |
92 | I->dropAllReferences(); |
93 | } else { |
94 | // Erase in reverse to avoid erasing nstructions with attached uses. |
95 | for (llvm::Instruction *I : reverse(C&: LLVMInstrs)) |
96 | I->eraseFromParent(); |
97 | } |
98 | } |
99 | |
100 | void Instruction::moveBefore(BasicBlock &BB, const BBIterator &WhereIt) { |
101 | if (std::next(x: getIterator()) == WhereIt) |
102 | // Destination is same as origin, nothing to do. |
103 | return; |
104 | |
105 | Ctx.runMoveInstrCallbacks(I: this, Where: WhereIt); |
106 | Ctx.getTracker().emplaceIfTracking<MoveInstr>(Args: this); |
107 | |
108 | auto *LLVMBB = cast<llvm::BasicBlock>(Val: BB.Val); |
109 | llvm::BasicBlock::iterator It; |
110 | if (WhereIt == BB.end()) { |
111 | It = LLVMBB->end(); |
112 | } else { |
113 | Instruction *WhereI = &*WhereIt; |
114 | It = WhereI->getTopmostLLVMInstruction()->getIterator(); |
115 | } |
116 | // TODO: Move this to the verifier of sandboxir::Instruction. |
117 | assert(is_sorted(getLLVMInstrs(), |
118 | [](auto *I1, auto *I2) { return I1->comesBefore(I2); }) && |
119 | "Expected program order!" ); |
120 | // Do the actual move in LLVM IR. |
121 | for (auto *I : getLLVMInstrs()) |
122 | I->moveBefore(BB&: *LLVMBB, I: It); |
123 | } |
124 | |
125 | void Instruction::insertBefore(Instruction *BeforeI) { |
126 | llvm::Instruction *BeforeTopI = BeforeI->getTopmostLLVMInstruction(); |
127 | |
128 | Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(Args: this); |
129 | |
130 | // Insert the LLVM IR Instructions in program order. |
131 | for (llvm::Instruction *I : getLLVMInstrs()) |
132 | I->insertBefore(InsertPos: BeforeTopI->getIterator()); |
133 | } |
134 | |
135 | void Instruction::insertAfter(Instruction *AfterI) { |
136 | insertInto(BB: AfterI->getParent(), WhereIt: std::next(x: AfterI->getIterator())); |
137 | } |
138 | |
139 | void Instruction::insertInto(BasicBlock *BB, const BBIterator &WhereIt) { |
140 | llvm::BasicBlock *LLVMBB = cast<llvm::BasicBlock>(Val: BB->Val); |
141 | llvm::Instruction *LLVMBeforeI; |
142 | llvm::BasicBlock::iterator LLVMBeforeIt; |
143 | Instruction *BeforeI; |
144 | if (WhereIt != BB->end()) { |
145 | BeforeI = &*WhereIt; |
146 | LLVMBeforeI = BeforeI->getTopmostLLVMInstruction(); |
147 | LLVMBeforeIt = LLVMBeforeI->getIterator(); |
148 | } else { |
149 | BeforeI = nullptr; |
150 | LLVMBeforeI = nullptr; |
151 | LLVMBeforeIt = LLVMBB->end(); |
152 | } |
153 | |
154 | Ctx.getTracker().emplaceIfTracking<InsertIntoBB>(Args: this); |
155 | |
156 | // Insert the LLVM IR Instructions in program order. |
157 | for (llvm::Instruction *I : getLLVMInstrs()) |
158 | I->insertInto(ParentBB: LLVMBB, It: LLVMBeforeIt); |
159 | } |
160 | |
161 | BasicBlock *Instruction::getParent() const { |
162 | // Get the LLVM IR Instruction that this maps to, get its parent, and get the |
163 | // corresponding sandboxir::BasicBlock by looking it up in sandboxir::Context. |
164 | auto *BB = cast<llvm::Instruction>(Val)->getParent(); |
165 | if (BB == nullptr) |
166 | return nullptr; |
167 | return cast<BasicBlock>(Val: Ctx.getValue(V: BB)); |
168 | } |
169 | |
170 | bool Instruction::classof(const sandboxir::Value *From) { |
171 | switch (From->getSubclassID()) { |
172 | #define DEF_INSTR(ID, OPC, CLASS) \ |
173 | case ClassID::ID: \ |
174 | return true; |
175 | #include "llvm/SandboxIR/Values.def" |
176 | default: |
177 | return false; |
178 | } |
179 | } |
180 | |
181 | void Instruction::setHasNoUnsignedWrap(bool B) { |
182 | Ctx.getTracker() |
183 | .emplaceIfTracking<GenericSetter<&Instruction::hasNoUnsignedWrap, |
184 | &Instruction::setHasNoUnsignedWrap>>( |
185 | Args: this); |
186 | cast<llvm::Instruction>(Val)->setHasNoUnsignedWrap(B); |
187 | } |
188 | |
189 | void Instruction::setHasNoSignedWrap(bool B) { |
190 | Ctx.getTracker() |
191 | .emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedWrap, |
192 | &Instruction::setHasNoSignedWrap>>(Args: this); |
193 | cast<llvm::Instruction>(Val)->setHasNoSignedWrap(B); |
194 | } |
195 | |
196 | void Instruction::setFast(bool B) { |
197 | Ctx.getTracker() |
198 | .emplaceIfTracking< |
199 | GenericSetter<&Instruction::isFast, &Instruction::setFast>>(Args: this); |
200 | cast<llvm::Instruction>(Val)->setFast(B); |
201 | } |
202 | |
203 | void Instruction::setIsExact(bool B) { |
204 | Ctx.getTracker() |
205 | .emplaceIfTracking< |
206 | GenericSetter<&Instruction::isExact, &Instruction::setIsExact>>(Args: this); |
207 | cast<llvm::Instruction>(Val)->setIsExact(B); |
208 | } |
209 | |
210 | void Instruction::setHasAllowReassoc(bool B) { |
211 | Ctx.getTracker() |
212 | .emplaceIfTracking<GenericSetter<&Instruction::hasAllowReassoc, |
213 | &Instruction::setHasAllowReassoc>>(Args: this); |
214 | cast<llvm::Instruction>(Val)->setHasAllowReassoc(B); |
215 | } |
216 | |
217 | void Instruction::setHasNoNaNs(bool B) { |
218 | Ctx.getTracker() |
219 | .emplaceIfTracking< |
220 | GenericSetter<&Instruction::hasNoNaNs, &Instruction::setHasNoNaNs>>( |
221 | Args: this); |
222 | cast<llvm::Instruction>(Val)->setHasNoNaNs(B); |
223 | } |
224 | |
225 | void Instruction::setHasNoInfs(bool B) { |
226 | Ctx.getTracker() |
227 | .emplaceIfTracking< |
228 | GenericSetter<&Instruction::hasNoInfs, &Instruction::setHasNoInfs>>( |
229 | Args: this); |
230 | cast<llvm::Instruction>(Val)->setHasNoInfs(B); |
231 | } |
232 | |
233 | void Instruction::setHasNoSignedZeros(bool B) { |
234 | Ctx.getTracker() |
235 | .emplaceIfTracking<GenericSetter<&Instruction::hasNoSignedZeros, |
236 | &Instruction::setHasNoSignedZeros>>( |
237 | Args: this); |
238 | cast<llvm::Instruction>(Val)->setHasNoSignedZeros(B); |
239 | } |
240 | |
241 | void Instruction::setHasAllowReciprocal(bool B) { |
242 | Ctx.getTracker() |
243 | .emplaceIfTracking<GenericSetter<&Instruction::hasAllowReciprocal, |
244 | &Instruction::setHasAllowReciprocal>>( |
245 | Args: this); |
246 | cast<llvm::Instruction>(Val)->setHasAllowReciprocal(B); |
247 | } |
248 | |
249 | void Instruction::setHasAllowContract(bool B) { |
250 | Ctx.getTracker() |
251 | .emplaceIfTracking<GenericSetter<&Instruction::hasAllowContract, |
252 | &Instruction::setHasAllowContract>>( |
253 | Args: this); |
254 | cast<llvm::Instruction>(Val)->setHasAllowContract(B); |
255 | } |
256 | |
257 | void Instruction::setFastMathFlags(FastMathFlags FMF) { |
258 | Ctx.getTracker() |
259 | .emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags, |
260 | &Instruction::copyFastMathFlags>>(Args: this); |
261 | cast<llvm::Instruction>(Val)->setFastMathFlags(FMF); |
262 | } |
263 | |
264 | void Instruction::copyFastMathFlags(FastMathFlags FMF) { |
265 | Ctx.getTracker() |
266 | .emplaceIfTracking<GenericSetter<&Instruction::getFastMathFlags, |
267 | &Instruction::copyFastMathFlags>>(Args: this); |
268 | cast<llvm::Instruction>(Val)->copyFastMathFlags(FMF); |
269 | } |
270 | |
271 | Type *Instruction::getAccessType() const { |
272 | return Ctx.getType(LLVMTy: cast<llvm::Instruction>(Val)->getAccessType()); |
273 | } |
274 | |
275 | void Instruction::setHasApproxFunc(bool B) { |
276 | Ctx.getTracker() |
277 | .emplaceIfTracking<GenericSetter<&Instruction::hasApproxFunc, |
278 | &Instruction::setHasApproxFunc>>(Args: this); |
279 | cast<llvm::Instruction>(Val)->setHasApproxFunc(B); |
280 | } |
281 | |
282 | #ifndef NDEBUG |
283 | void Instruction::dumpOS(raw_ostream &OS) const { |
284 | OS << "Unimplemented! Please override dump()." ; |
285 | } |
286 | #endif // NDEBUG |
287 | |
288 | VAArgInst *VAArgInst::create(Value *List, Type *Ty, InsertPosition Pos, |
289 | Context &Ctx, const Twine &Name) { |
290 | auto &Builder = setInsertPos(Pos); |
291 | auto *LLVMI = |
292 | cast<llvm::VAArgInst>(Val: Builder.CreateVAArg(List: List->Val, Ty: Ty->LLVMTy, Name)); |
293 | return Ctx.createVAArgInst(SI: LLVMI); |
294 | } |
295 | |
296 | Value *VAArgInst::getPointerOperand() { |
297 | return Ctx.getValue(V: cast<llvm::VAArgInst>(Val)->getPointerOperand()); |
298 | } |
299 | |
300 | FreezeInst *FreezeInst::create(Value *V, InsertPosition Pos, Context &Ctx, |
301 | const Twine &Name) { |
302 | auto &Builder = setInsertPos(Pos); |
303 | auto *LLVMI = cast<llvm::FreezeInst>(Val: Builder.CreateFreeze(V: V->Val, Name)); |
304 | return Ctx.createFreezeInst(SI: LLVMI); |
305 | } |
306 | |
307 | FenceInst *FenceInst::create(AtomicOrdering Ordering, InsertPosition Pos, |
308 | Context &Ctx, SyncScope::ID SSID) { |
309 | auto &Builder = Instruction::setInsertPos(Pos); |
310 | llvm::FenceInst *LLVMI = Builder.CreateFence(Ordering, SSID); |
311 | return Ctx.createFenceInst(SI: LLVMI); |
312 | } |
313 | |
314 | void FenceInst::setOrdering(AtomicOrdering Ordering) { |
315 | Ctx.getTracker() |
316 | .emplaceIfTracking< |
317 | GenericSetter<&FenceInst::getOrdering, &FenceInst::setOrdering>>( |
318 | Args: this); |
319 | cast<llvm::FenceInst>(Val)->setOrdering(Ordering); |
320 | } |
321 | |
322 | void FenceInst::setSyncScopeID(SyncScope::ID SSID) { |
323 | Ctx.getTracker() |
324 | .emplaceIfTracking<GenericSetter<&FenceInst::getSyncScopeID, |
325 | &FenceInst::setSyncScopeID>>(Args: this); |
326 | cast<llvm::FenceInst>(Val)->setSyncScopeID(SSID); |
327 | } |
328 | |
329 | Value *SelectInst::create(Value *Cond, Value *True, Value *False, |
330 | InsertPosition Pos, Context &Ctx, const Twine &Name) { |
331 | auto &Builder = Instruction::setInsertPos(Pos); |
332 | llvm::Value *NewV = |
333 | Builder.CreateSelect(C: Cond->Val, True: True->Val, False: False->Val, Name); |
334 | if (auto *NewSI = dyn_cast<llvm::SelectInst>(Val: NewV)) |
335 | return Ctx.createSelectInst(SI: NewSI); |
336 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
337 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
338 | } |
339 | |
340 | void SelectInst::swapValues() { |
341 | Ctx.getTracker().emplaceIfTracking<UseSwap>(Args: getOperandUse(OpIdx: 1), |
342 | Args: getOperandUse(OpIdx: 2)); |
343 | cast<llvm::SelectInst>(Val)->swapValues(); |
344 | } |
345 | |
346 | bool SelectInst::classof(const Value *From) { |
347 | return From->getSubclassID() == ClassID::Select; |
348 | } |
349 | |
350 | BranchInst *BranchInst::create(BasicBlock *IfTrue, InsertPosition Pos, |
351 | Context &Ctx) { |
352 | auto &Builder = setInsertPos(Pos); |
353 | llvm::BranchInst *NewBr = |
354 | Builder.CreateBr(Dest: cast<llvm::BasicBlock>(Val: IfTrue->Val)); |
355 | return Ctx.createBranchInst(I: NewBr); |
356 | } |
357 | |
358 | BranchInst *BranchInst::create(BasicBlock *IfTrue, BasicBlock *IfFalse, |
359 | Value *Cond, InsertPosition Pos, Context &Ctx) { |
360 | auto &Builder = setInsertPos(Pos); |
361 | llvm::BranchInst *NewBr = |
362 | Builder.CreateCondBr(Cond: Cond->Val, True: cast<llvm::BasicBlock>(Val: IfTrue->Val), |
363 | False: cast<llvm::BasicBlock>(Val: IfFalse->Val)); |
364 | return Ctx.createBranchInst(I: NewBr); |
365 | } |
366 | |
367 | bool BranchInst::classof(const Value *From) { |
368 | return From->getSubclassID() == ClassID::Br; |
369 | } |
370 | |
371 | Value *BranchInst::getCondition() const { |
372 | assert(isConditional() && "Cannot get condition of an uncond branch!" ); |
373 | return Ctx.getValue(V: cast<llvm::BranchInst>(Val)->getCondition()); |
374 | } |
375 | |
376 | BasicBlock *BranchInst::getSuccessor(unsigned SuccIdx) const { |
377 | assert(SuccIdx < getNumSuccessors() && |
378 | "Successor # out of range for Branch!" ); |
379 | return cast_or_null<BasicBlock>( |
380 | Val: Ctx.getValue(V: cast<llvm::BranchInst>(Val)->getSuccessor(i: SuccIdx))); |
381 | } |
382 | |
383 | void BranchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) { |
384 | assert((Idx == 0 || Idx == 1) && "Out of bounds!" ); |
385 | setOperand(OperandIdx: 2u - Idx, Operand: NewSucc); |
386 | } |
387 | |
388 | BasicBlock *BranchInst::LLVMBBToSBBB::operator()(llvm::BasicBlock *BB) const { |
389 | return cast<BasicBlock>(Val: Ctx.getValue(V: BB)); |
390 | } |
391 | const BasicBlock * |
392 | BranchInst::ConstLLVMBBToSBBB::operator()(const llvm::BasicBlock *BB) const { |
393 | return cast<BasicBlock>(Val: Ctx.getValue(V: BB)); |
394 | } |
395 | |
396 | void LoadInst::setVolatile(bool V) { |
397 | Ctx.getTracker() |
398 | .emplaceIfTracking< |
399 | GenericSetter<&LoadInst::isVolatile, &LoadInst::setVolatile>>(Args: this); |
400 | cast<llvm::LoadInst>(Val)->setVolatile(V); |
401 | } |
402 | |
403 | LoadInst *LoadInst::create(Type *Ty, Value *Ptr, MaybeAlign Align, |
404 | InsertPosition Pos, bool IsVolatile, Context &Ctx, |
405 | const Twine &Name) { |
406 | auto &Builder = setInsertPos(Pos); |
407 | auto *NewLI = |
408 | Builder.CreateAlignedLoad(Ty: Ty->LLVMTy, Ptr: Ptr->Val, Align, isVolatile: IsVolatile, Name); |
409 | auto *NewSBI = Ctx.createLoadInst(LI: NewLI); |
410 | return NewSBI; |
411 | } |
412 | |
413 | bool LoadInst::classof(const Value *From) { |
414 | return From->getSubclassID() == ClassID::Load; |
415 | } |
416 | |
417 | Value *LoadInst::getPointerOperand() const { |
418 | return Ctx.getValue(V: cast<llvm::LoadInst>(Val)->getPointerOperand()); |
419 | } |
420 | |
421 | void StoreInst::setVolatile(bool V) { |
422 | Ctx.getTracker() |
423 | .emplaceIfTracking< |
424 | GenericSetter<&StoreInst::isVolatile, &StoreInst::setVolatile>>(Args: this); |
425 | cast<llvm::StoreInst>(Val)->setVolatile(V); |
426 | } |
427 | |
428 | StoreInst *StoreInst::create(Value *V, Value *Ptr, MaybeAlign Align, |
429 | InsertPosition Pos, bool IsVolatile, |
430 | Context &Ctx) { |
431 | auto &Builder = setInsertPos(Pos); |
432 | auto *NewSI = Builder.CreateAlignedStore(Val: V->Val, Ptr: Ptr->Val, Align, isVolatile: IsVolatile); |
433 | auto *NewSBI = Ctx.createStoreInst(SI: NewSI); |
434 | return NewSBI; |
435 | } |
436 | |
437 | bool StoreInst::classof(const Value *From) { |
438 | return From->getSubclassID() == ClassID::Store; |
439 | } |
440 | |
441 | Value *StoreInst::getValueOperand() const { |
442 | return Ctx.getValue(V: cast<llvm::StoreInst>(Val)->getValueOperand()); |
443 | } |
444 | |
445 | Value *StoreInst::getPointerOperand() const { |
446 | return Ctx.getValue(V: cast<llvm::StoreInst>(Val)->getPointerOperand()); |
447 | } |
448 | |
449 | UnreachableInst *UnreachableInst::create(InsertPosition Pos, Context &Ctx) { |
450 | auto &Builder = setInsertPos(Pos); |
451 | llvm::UnreachableInst *NewUI = Builder.CreateUnreachable(); |
452 | return Ctx.createUnreachableInst(UI: NewUI); |
453 | } |
454 | |
455 | bool UnreachableInst::classof(const Value *From) { |
456 | return From->getSubclassID() == ClassID::Unreachable; |
457 | } |
458 | |
459 | ReturnInst *ReturnInst::createCommon(Value *RetVal, IRBuilder<> &Builder, |
460 | Context &Ctx) { |
461 | llvm::ReturnInst *NewRI; |
462 | if (RetVal != nullptr) |
463 | NewRI = Builder.CreateRet(V: RetVal->Val); |
464 | else |
465 | NewRI = Builder.CreateRetVoid(); |
466 | return Ctx.createReturnInst(I: NewRI); |
467 | } |
468 | |
469 | ReturnInst *ReturnInst::create(Value *RetVal, InsertPosition Pos, |
470 | Context &Ctx) { |
471 | auto &Builder = setInsertPos(Pos); |
472 | return createCommon(RetVal, Builder, Ctx); |
473 | } |
474 | |
475 | Value *ReturnInst::getReturnValue() const { |
476 | auto *LLVMRetVal = cast<llvm::ReturnInst>(Val)->getReturnValue(); |
477 | return LLVMRetVal != nullptr ? Ctx.getValue(V: LLVMRetVal) : nullptr; |
478 | } |
479 | |
480 | FunctionType *CallBase::getFunctionType() const { |
481 | return cast<FunctionType>( |
482 | Val: Ctx.getType(LLVMTy: cast<llvm::CallBase>(Val)->getFunctionType())); |
483 | } |
484 | |
485 | Value *CallBase::getCalledOperand() const { |
486 | return Ctx.getValue(V: cast<llvm::CallBase>(Val)->getCalledOperand()); |
487 | } |
488 | |
489 | Use CallBase::getCalledOperandUse() const { |
490 | llvm::Use *LLVMUse = &cast<llvm::CallBase>(Val)->getCalledOperandUse(); |
491 | return Use(LLVMUse, cast<User>(Val: Ctx.getValue(V: LLVMUse->getUser())), Ctx); |
492 | } |
493 | |
494 | Function *CallBase::getCalledFunction() const { |
495 | return cast_or_null<Function>( |
496 | Val: Ctx.getValue(V: cast<llvm::CallBase>(Val)->getCalledFunction())); |
497 | } |
498 | Function *CallBase::getCaller() { |
499 | return cast<Function>(Val: Ctx.getValue(V: cast<llvm::CallBase>(Val)->getCaller())); |
500 | } |
501 | |
502 | void CallBase::setCalledFunction(Function *F) { |
503 | // F's function type is private, so we rely on `setCalledFunction()` to update |
504 | // it. But even though we are calling `setCalledFunction()` we also need to |
505 | // track this change at the SandboxIR level, which is why we call |
506 | // `setCalledOperand()` here. |
507 | // Note: This may break if `setCalledFunction()` early returns if `F` |
508 | // is already set, but we do have a unit test for it. |
509 | setCalledOperand(F); |
510 | cast<llvm::CallBase>(Val)->setCalledFunction( |
511 | FTy: cast<llvm::FunctionType>(Val: F->getFunctionType()->LLVMTy), |
512 | Fn: cast<llvm::Function>(Val: F->Val)); |
513 | } |
514 | |
515 | CallInst *CallInst::create(FunctionType *FTy, Value *Func, |
516 | ArrayRef<Value *> Args, InsertPosition Pos, |
517 | Context &Ctx, const Twine &NameStr) { |
518 | auto &Builder = setInsertPos(Pos); |
519 | SmallVector<llvm::Value *> LLVMArgs; |
520 | LLVMArgs.reserve(N: Args.size()); |
521 | for (Value *Arg : Args) |
522 | LLVMArgs.push_back(Elt: Arg->Val); |
523 | llvm::CallInst *NewCI = Builder.CreateCall( |
524 | FTy: cast<llvm::FunctionType>(Val: FTy->LLVMTy), Callee: Func->Val, Args: LLVMArgs, Name: NameStr); |
525 | return Ctx.createCallInst(I: NewCI); |
526 | } |
527 | |
528 | InvokeInst *InvokeInst::create(FunctionType *FTy, Value *Func, |
529 | BasicBlock *IfNormal, BasicBlock *IfException, |
530 | ArrayRef<Value *> Args, InsertPosition Pos, |
531 | Context &Ctx, const Twine &NameStr) { |
532 | auto &Builder = setInsertPos(Pos); |
533 | SmallVector<llvm::Value *> LLVMArgs; |
534 | LLVMArgs.reserve(N: Args.size()); |
535 | for (Value *Arg : Args) |
536 | LLVMArgs.push_back(Elt: Arg->Val); |
537 | llvm::InvokeInst *Invoke = Builder.CreateInvoke( |
538 | Ty: cast<llvm::FunctionType>(Val: FTy->LLVMTy), Callee: Func->Val, |
539 | NormalDest: cast<llvm::BasicBlock>(Val: IfNormal->Val), |
540 | UnwindDest: cast<llvm::BasicBlock>(Val: IfException->Val), Args: LLVMArgs, Name: NameStr); |
541 | return Ctx.createInvokeInst(I: Invoke); |
542 | } |
543 | |
544 | BasicBlock *InvokeInst::getNormalDest() const { |
545 | return cast<BasicBlock>( |
546 | Val: Ctx.getValue(V: cast<llvm::InvokeInst>(Val)->getNormalDest())); |
547 | } |
548 | BasicBlock *InvokeInst::getUnwindDest() const { |
549 | return cast<BasicBlock>( |
550 | Val: Ctx.getValue(V: cast<llvm::InvokeInst>(Val)->getUnwindDest())); |
551 | } |
552 | void InvokeInst::setNormalDest(BasicBlock *BB) { |
553 | setOperand(OperandIdx: 1, Operand: BB); |
554 | assert(getNormalDest() == BB && "LLVM IR uses a different operan index!" ); |
555 | } |
556 | void InvokeInst::setUnwindDest(BasicBlock *BB) { |
557 | setOperand(OperandIdx: 2, Operand: BB); |
558 | assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!" ); |
559 | } |
560 | LandingPadInst *InvokeInst::getLandingPadInst() const { |
561 | return cast<LandingPadInst>( |
562 | Val: Ctx.getValue(V: cast<llvm::InvokeInst>(Val)->getLandingPadInst())); |
563 | ; |
564 | } |
565 | BasicBlock *InvokeInst::getSuccessor(unsigned SuccIdx) const { |
566 | return cast<BasicBlock>( |
567 | Val: Ctx.getValue(V: cast<llvm::InvokeInst>(Val)->getSuccessor(i: SuccIdx))); |
568 | } |
569 | |
570 | CallBrInst *CallBrInst::create(FunctionType *FTy, Value *Func, |
571 | BasicBlock *DefaultDest, |
572 | ArrayRef<BasicBlock *> IndirectDests, |
573 | ArrayRef<Value *> Args, InsertPosition Pos, |
574 | Context &Ctx, const Twine &NameStr) { |
575 | auto &Builder = setInsertPos(Pos); |
576 | SmallVector<llvm::BasicBlock *> LLVMIndirectDests; |
577 | LLVMIndirectDests.reserve(N: IndirectDests.size()); |
578 | for (BasicBlock *IndDest : IndirectDests) |
579 | LLVMIndirectDests.push_back(Elt: cast<llvm::BasicBlock>(Val: IndDest->Val)); |
580 | |
581 | SmallVector<llvm::Value *> LLVMArgs; |
582 | LLVMArgs.reserve(N: Args.size()); |
583 | for (Value *Arg : Args) |
584 | LLVMArgs.push_back(Elt: Arg->Val); |
585 | |
586 | llvm::CallBrInst *CallBr = |
587 | Builder.CreateCallBr(Ty: cast<llvm::FunctionType>(Val: FTy->LLVMTy), Callee: Func->Val, |
588 | DefaultDest: cast<llvm::BasicBlock>(Val: DefaultDest->Val), |
589 | IndirectDests: LLVMIndirectDests, Args: LLVMArgs, Name: NameStr); |
590 | return Ctx.createCallBrInst(I: CallBr); |
591 | } |
592 | |
593 | Value *CallBrInst::getIndirectDestLabel(unsigned Idx) const { |
594 | return Ctx.getValue(V: cast<llvm::CallBrInst>(Val)->getIndirectDestLabel(i: Idx)); |
595 | } |
596 | Value *CallBrInst::getIndirectDestLabelUse(unsigned Idx) const { |
597 | return Ctx.getValue( |
598 | V: cast<llvm::CallBrInst>(Val)->getIndirectDestLabelUse(i: Idx)); |
599 | } |
600 | BasicBlock *CallBrInst::getDefaultDest() const { |
601 | return cast<BasicBlock>( |
602 | Val: Ctx.getValue(V: cast<llvm::CallBrInst>(Val)->getDefaultDest())); |
603 | } |
604 | BasicBlock *CallBrInst::getIndirectDest(unsigned Idx) const { |
605 | return cast<BasicBlock>( |
606 | Val: Ctx.getValue(V: cast<llvm::CallBrInst>(Val)->getIndirectDest(i: Idx))); |
607 | } |
608 | llvm::SmallVector<BasicBlock *, 16> CallBrInst::getIndirectDests() const { |
609 | SmallVector<BasicBlock *, 16> BBs; |
610 | for (llvm::BasicBlock *LLVMBB : |
611 | cast<llvm::CallBrInst>(Val)->getIndirectDests()) |
612 | BBs.push_back(Elt: cast<BasicBlock>(Val: Ctx.getValue(V: LLVMBB))); |
613 | return BBs; |
614 | } |
615 | void CallBrInst::setDefaultDest(BasicBlock *BB) { |
616 | Ctx.getTracker() |
617 | .emplaceIfTracking<GenericSetter<&CallBrInst::getDefaultDest, |
618 | &CallBrInst::setDefaultDest>>(Args: this); |
619 | cast<llvm::CallBrInst>(Val)->setDefaultDest(cast<llvm::BasicBlock>(Val: BB->Val)); |
620 | } |
621 | void CallBrInst::setIndirectDest(unsigned Idx, BasicBlock *BB) { |
622 | Ctx.getTracker() |
623 | .emplaceIfTracking<GenericSetterWithIdx<&CallBrInst::getIndirectDest, |
624 | &CallBrInst::setIndirectDest>>( |
625 | Args: this, Args: Idx); |
626 | cast<llvm::CallBrInst>(Val)->setIndirectDest(i: Idx, |
627 | B: cast<llvm::BasicBlock>(Val: BB->Val)); |
628 | } |
629 | BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const { |
630 | return cast<BasicBlock>( |
631 | Val: Ctx.getValue(V: cast<llvm::CallBrInst>(Val)->getSuccessor(i: Idx))); |
632 | } |
633 | |
634 | LandingPadInst *LandingPadInst::create(Type *RetTy, unsigned NumReservedClauses, |
635 | InsertPosition Pos, Context &Ctx, |
636 | const Twine &Name) { |
637 | auto &Builder = setInsertPos(Pos); |
638 | llvm::LandingPadInst *LLVMI = |
639 | Builder.CreateLandingPad(Ty: RetTy->LLVMTy, NumClauses: NumReservedClauses, Name); |
640 | return Ctx.createLandingPadInst(I: LLVMI); |
641 | } |
642 | |
643 | void LandingPadInst::setCleanup(bool V) { |
644 | Ctx.getTracker() |
645 | .emplaceIfTracking<GenericSetter<&LandingPadInst::isCleanup, |
646 | &LandingPadInst::setCleanup>>(Args: this); |
647 | cast<llvm::LandingPadInst>(Val)->setCleanup(V); |
648 | } |
649 | |
650 | Constant *LandingPadInst::getClause(unsigned Idx) const { |
651 | return cast<Constant>( |
652 | Val: Ctx.getValue(V: cast<llvm::LandingPadInst>(Val)->getClause(Idx))); |
653 | } |
654 | |
655 | Value *FuncletPadInst::getParentPad() const { |
656 | return Ctx.getValue(V: cast<llvm::FuncletPadInst>(Val)->getParentPad()); |
657 | } |
658 | |
659 | void FuncletPadInst::setParentPad(Value *ParentPad) { |
660 | Ctx.getTracker() |
661 | .emplaceIfTracking<GenericSetter<&FuncletPadInst::getParentPad, |
662 | &FuncletPadInst::setParentPad>>(Args: this); |
663 | cast<llvm::FuncletPadInst>(Val)->setParentPad(ParentPad->Val); |
664 | } |
665 | |
666 | Value *FuncletPadInst::getArgOperand(unsigned Idx) const { |
667 | return Ctx.getValue(V: cast<llvm::FuncletPadInst>(Val)->getArgOperand(i: Idx)); |
668 | } |
669 | |
670 | void FuncletPadInst::setArgOperand(unsigned Idx, Value *V) { |
671 | Ctx.getTracker() |
672 | .emplaceIfTracking<GenericSetterWithIdx<&FuncletPadInst::getArgOperand, |
673 | &FuncletPadInst::setArgOperand>>( |
674 | Args: this, Args: Idx); |
675 | cast<llvm::FuncletPadInst>(Val)->setArgOperand(i: Idx, v: V->Val); |
676 | } |
677 | |
678 | CatchSwitchInst *CatchPadInst::getCatchSwitch() const { |
679 | return cast<CatchSwitchInst>( |
680 | Val: Ctx.getValue(V: cast<llvm::CatchPadInst>(Val)->getCatchSwitch())); |
681 | } |
682 | |
683 | CatchPadInst *CatchPadInst::create(Value *ParentPad, ArrayRef<Value *> Args, |
684 | InsertPosition Pos, Context &Ctx, |
685 | const Twine &Name) { |
686 | auto &Builder = setInsertPos(Pos); |
687 | SmallVector<llvm::Value *> LLVMArgs; |
688 | LLVMArgs.reserve(N: Args.size()); |
689 | for (auto *Arg : Args) |
690 | LLVMArgs.push_back(Elt: Arg->Val); |
691 | llvm::CatchPadInst *LLVMI = |
692 | Builder.CreateCatchPad(ParentPad: ParentPad->Val, Args: LLVMArgs, Name); |
693 | return Ctx.createCatchPadInst(I: LLVMI); |
694 | } |
695 | |
696 | CleanupPadInst *CleanupPadInst::create(Value *ParentPad, ArrayRef<Value *> Args, |
697 | InsertPosition Pos, Context &Ctx, |
698 | const Twine &Name) { |
699 | auto &Builder = setInsertPos(Pos); |
700 | SmallVector<llvm::Value *> LLVMArgs; |
701 | LLVMArgs.reserve(N: Args.size()); |
702 | for (auto *Arg : Args) |
703 | LLVMArgs.push_back(Elt: Arg->Val); |
704 | llvm::CleanupPadInst *LLVMI = |
705 | Builder.CreateCleanupPad(ParentPad: ParentPad->Val, Args: LLVMArgs, Name); |
706 | return Ctx.createCleanupPadInst(I: LLVMI); |
707 | } |
708 | |
709 | CatchReturnInst *CatchReturnInst::create(CatchPadInst *CatchPad, BasicBlock *BB, |
710 | InsertPosition Pos, Context &Ctx) { |
711 | auto &Builder = setInsertPos(Pos); |
712 | llvm::CatchReturnInst *LLVMI = Builder.CreateCatchRet( |
713 | CatchPad: cast<llvm::CatchPadInst>(Val: CatchPad->Val), BB: cast<llvm::BasicBlock>(Val: BB->Val)); |
714 | return Ctx.createCatchReturnInst(I: LLVMI); |
715 | } |
716 | |
717 | CatchPadInst *CatchReturnInst::getCatchPad() const { |
718 | return cast<CatchPadInst>( |
719 | Val: Ctx.getValue(V: cast<llvm::CatchReturnInst>(Val)->getCatchPad())); |
720 | } |
721 | |
722 | void CatchReturnInst::setCatchPad(CatchPadInst *CatchPad) { |
723 | Ctx.getTracker() |
724 | .emplaceIfTracking<GenericSetter<&CatchReturnInst::getCatchPad, |
725 | &CatchReturnInst::setCatchPad>>(Args: this); |
726 | cast<llvm::CatchReturnInst>(Val)->setCatchPad( |
727 | cast<llvm::CatchPadInst>(Val: CatchPad->Val)); |
728 | } |
729 | |
730 | BasicBlock *CatchReturnInst::getSuccessor() const { |
731 | return cast<BasicBlock>( |
732 | Val: Ctx.getValue(V: cast<llvm::CatchReturnInst>(Val)->getSuccessor())); |
733 | } |
734 | |
735 | void CatchReturnInst::setSuccessor(BasicBlock *NewSucc) { |
736 | Ctx.getTracker() |
737 | .emplaceIfTracking<GenericSetter<&CatchReturnInst::getSuccessor, |
738 | &CatchReturnInst::setSuccessor>>(Args: this); |
739 | cast<llvm::CatchReturnInst>(Val)->setSuccessor( |
740 | cast<llvm::BasicBlock>(Val: NewSucc->Val)); |
741 | } |
742 | |
743 | Value *CatchReturnInst::getCatchSwitchParentPad() const { |
744 | return Ctx.getValue( |
745 | V: cast<llvm::CatchReturnInst>(Val)->getCatchSwitchParentPad()); |
746 | } |
747 | |
748 | CleanupReturnInst *CleanupReturnInst::create(CleanupPadInst *CleanupPad, |
749 | BasicBlock *UnwindBB, |
750 | InsertPosition Pos, Context &Ctx) { |
751 | auto &Builder = setInsertPos(Pos); |
752 | auto *LLVMUnwindBB = |
753 | UnwindBB != nullptr ? cast<llvm::BasicBlock>(Val: UnwindBB->Val) : nullptr; |
754 | llvm::CleanupReturnInst *LLVMI = Builder.CreateCleanupRet( |
755 | CleanupPad: cast<llvm::CleanupPadInst>(Val: CleanupPad->Val), UnwindBB: LLVMUnwindBB); |
756 | return Ctx.createCleanupReturnInst(I: LLVMI); |
757 | } |
758 | |
759 | CleanupPadInst *CleanupReturnInst::getCleanupPad() const { |
760 | return cast<CleanupPadInst>( |
761 | Val: Ctx.getValue(V: cast<llvm::CleanupReturnInst>(Val)->getCleanupPad())); |
762 | } |
763 | |
764 | void CleanupReturnInst::setCleanupPad(CleanupPadInst *CleanupPad) { |
765 | Ctx.getTracker() |
766 | .emplaceIfTracking<GenericSetter<&CleanupReturnInst::getCleanupPad, |
767 | &CleanupReturnInst::setCleanupPad>>( |
768 | Args: this); |
769 | cast<llvm::CleanupReturnInst>(Val)->setCleanupPad( |
770 | cast<llvm::CleanupPadInst>(Val: CleanupPad->Val)); |
771 | } |
772 | |
773 | BasicBlock *CleanupReturnInst::getUnwindDest() const { |
774 | return cast_or_null<BasicBlock>( |
775 | Val: Ctx.getValue(V: cast<llvm::CleanupReturnInst>(Val)->getUnwindDest())); |
776 | } |
777 | |
778 | void CleanupReturnInst::setUnwindDest(BasicBlock *NewDest) { |
779 | Ctx.getTracker() |
780 | .emplaceIfTracking<GenericSetter<&CleanupReturnInst::getUnwindDest, |
781 | &CleanupReturnInst::setUnwindDest>>( |
782 | Args: this); |
783 | cast<llvm::CleanupReturnInst>(Val)->setUnwindDest( |
784 | cast<llvm::BasicBlock>(Val: NewDest->Val)); |
785 | } |
786 | |
787 | Value *GetElementPtrInst::create(Type *Ty, Value *Ptr, |
788 | ArrayRef<Value *> IdxList, InsertPosition Pos, |
789 | Context &Ctx, const Twine &NameStr) { |
790 | auto &Builder = setInsertPos(Pos); |
791 | SmallVector<llvm::Value *> LLVMIdxList; |
792 | LLVMIdxList.reserve(N: IdxList.size()); |
793 | for (Value *Idx : IdxList) |
794 | LLVMIdxList.push_back(Elt: Idx->Val); |
795 | llvm::Value *NewV = |
796 | Builder.CreateGEP(Ty: Ty->LLVMTy, Ptr: Ptr->Val, IdxList: LLVMIdxList, Name: NameStr); |
797 | if (auto *NewGEP = dyn_cast<llvm::GetElementPtrInst>(Val: NewV)) |
798 | return Ctx.createGetElementPtrInst(I: NewGEP); |
799 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
800 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
801 | } |
802 | |
803 | Type *GetElementPtrInst::getSourceElementType() const { |
804 | return Ctx.getType( |
805 | LLVMTy: cast<llvm::GetElementPtrInst>(Val)->getSourceElementType()); |
806 | } |
807 | |
808 | Type *GetElementPtrInst::getResultElementType() const { |
809 | return Ctx.getType( |
810 | LLVMTy: cast<llvm::GetElementPtrInst>(Val)->getResultElementType()); |
811 | } |
812 | |
813 | Value *GetElementPtrInst::getPointerOperand() const { |
814 | return Ctx.getValue(V: cast<llvm::GetElementPtrInst>(Val)->getPointerOperand()); |
815 | } |
816 | |
817 | Type *GetElementPtrInst::getPointerOperandType() const { |
818 | return Ctx.getType( |
819 | LLVMTy: cast<llvm::GetElementPtrInst>(Val)->getPointerOperandType()); |
820 | } |
821 | |
822 | BasicBlock *PHINode::LLVMBBToBB::operator()(llvm::BasicBlock *LLVMBB) const { |
823 | return cast<BasicBlock>(Val: Ctx.getValue(V: LLVMBB)); |
824 | } |
825 | |
826 | PHINode *PHINode::create(Type *Ty, unsigned NumReservedValues, |
827 | InsertPosition Pos, Context &Ctx, const Twine &Name) { |
828 | auto &Builder = setInsertPos(Pos); |
829 | llvm::PHINode *NewPHI = |
830 | Builder.CreatePHI(Ty: Ty->LLVMTy, NumReservedValues, Name); |
831 | return Ctx.createPHINode(I: NewPHI); |
832 | } |
833 | |
834 | bool PHINode::classof(const Value *From) { |
835 | return From->getSubclassID() == ClassID::PHI; |
836 | } |
837 | |
838 | Value *PHINode::getIncomingValue(unsigned Idx) const { |
839 | return Ctx.getValue(V: cast<llvm::PHINode>(Val)->getIncomingValue(i: Idx)); |
840 | } |
841 | void PHINode::setIncomingValue(unsigned Idx, Value *V) { |
842 | Ctx.getTracker() |
843 | .emplaceIfTracking<GenericSetterWithIdx<&PHINode::getIncomingValue, |
844 | &PHINode::setIncomingValue>>(Args: this, |
845 | Args: Idx); |
846 | cast<llvm::PHINode>(Val)->setIncomingValue(i: Idx, V: V->Val); |
847 | } |
848 | BasicBlock *PHINode::getIncomingBlock(unsigned Idx) const { |
849 | return cast<BasicBlock>( |
850 | Val: Ctx.getValue(V: cast<llvm::PHINode>(Val)->getIncomingBlock(i: Idx))); |
851 | } |
852 | BasicBlock *PHINode::getIncomingBlock(const Use &U) const { |
853 | llvm::Use *LLVMUse = U.LLVMUse; |
854 | llvm::BasicBlock *BB = cast<llvm::PHINode>(Val)->getIncomingBlock(U: *LLVMUse); |
855 | return cast<BasicBlock>(Val: Ctx.getValue(V: BB)); |
856 | } |
857 | void PHINode::setIncomingBlock(unsigned Idx, BasicBlock *BB) { |
858 | // Helper to disambiguate PHINode::getIncomingBlock(unsigned). |
859 | constexpr BasicBlock *(PHINode::*GetIncomingBlockFn)(unsigned) const = |
860 | &PHINode::getIncomingBlock; |
861 | Ctx.getTracker() |
862 | .emplaceIfTracking< |
863 | GenericSetterWithIdx<GetIncomingBlockFn, &PHINode::setIncomingBlock>>( |
864 | Args: this, Args: Idx); |
865 | cast<llvm::PHINode>(Val)->setIncomingBlock(i: Idx, |
866 | BB: cast<llvm::BasicBlock>(Val: BB->Val)); |
867 | } |
868 | void PHINode::addIncoming(Value *V, BasicBlock *BB) { |
869 | auto &Tracker = Ctx.getTracker(); |
870 | Tracker.emplaceIfTracking<PHIAddIncoming>(Args: this); |
871 | |
872 | cast<llvm::PHINode>(Val)->addIncoming(V: V->Val, |
873 | BB: cast<llvm::BasicBlock>(Val: BB->Val)); |
874 | } |
875 | Value *PHINode::removeIncomingValue(unsigned Idx) { |
876 | auto &Tracker = Ctx.getTracker(); |
877 | Tracker.emplaceIfTracking<PHIRemoveIncoming>(Args: this, Args: Idx); |
878 | llvm::Value *LLVMV = |
879 | cast<llvm::PHINode>(Val)->removeIncomingValue(Idx, |
880 | /*DeletePHIIfEmpty=*/false); |
881 | return Ctx.getValue(V: LLVMV); |
882 | } |
883 | Value *PHINode::removeIncomingValue(BasicBlock *BB) { |
884 | auto &Tracker = Ctx.getTracker(); |
885 | Tracker.emplaceIfTracking<PHIRemoveIncoming>(Args: this, Args: getBasicBlockIndex(BB)); |
886 | |
887 | auto *LLVMBB = cast<llvm::BasicBlock>(Val: BB->Val); |
888 | llvm::Value *LLVMV = |
889 | cast<llvm::PHINode>(Val)->removeIncomingValue(BB: LLVMBB, |
890 | /*DeletePHIIfEmpty=*/false); |
891 | return Ctx.getValue(V: LLVMV); |
892 | } |
893 | int PHINode::getBasicBlockIndex(const BasicBlock *BB) const { |
894 | auto *LLVMBB = cast<llvm::BasicBlock>(Val: BB->Val); |
895 | return cast<llvm::PHINode>(Val)->getBasicBlockIndex(BB: LLVMBB); |
896 | } |
897 | Value *PHINode::getIncomingValueForBlock(const BasicBlock *BB) const { |
898 | auto *LLVMBB = cast<llvm::BasicBlock>(Val: BB->Val); |
899 | llvm::Value *LLVMV = |
900 | cast<llvm::PHINode>(Val)->getIncomingValueForBlock(BB: LLVMBB); |
901 | return Ctx.getValue(V: LLVMV); |
902 | } |
903 | Value *PHINode::hasConstantValue() const { |
904 | llvm::Value *LLVMV = cast<llvm::PHINode>(Val)->hasConstantValue(); |
905 | return LLVMV != nullptr ? Ctx.getValue(V: LLVMV) : nullptr; |
906 | } |
907 | void PHINode::replaceIncomingBlockWith(const BasicBlock *Old, BasicBlock *New) { |
908 | assert(New && Old && "Sandbox IR PHI node got a null basic block!" ); |
909 | for (unsigned Idx = 0, NumOps = cast<llvm::PHINode>(Val)->getNumOperands(); |
910 | Idx != NumOps; ++Idx) |
911 | if (getIncomingBlock(Idx) == Old) |
912 | setIncomingBlock(Idx, BB: New); |
913 | } |
914 | void PHINode::removeIncomingValueIf(function_ref<bool(unsigned)> Predicate) { |
915 | // Avoid duplicate tracking by going through this->removeIncomingValue here at |
916 | // the expense of some performance. Copy PHI::removeIncomingValueIf more |
917 | // directly if performance becomes an issue. |
918 | |
919 | // Removing the element at index X, moves the element previously at X + 1 |
920 | // to X. Working from the end avoids complications from that. |
921 | unsigned Idx = getNumIncomingValues(); |
922 | while (Idx > 0) { |
923 | if (Predicate(Idx - 1)) |
924 | removeIncomingValue(Idx: Idx - 1); |
925 | --Idx; |
926 | } |
927 | } |
928 | |
929 | Value *CmpInst::create(Predicate P, Value *S1, Value *S2, InsertPosition Pos, |
930 | Context &Ctx, const Twine &Name) { |
931 | auto &Builder = setInsertPos(Pos); |
932 | auto *LLVMV = Builder.CreateCmp(Pred: P, LHS: S1->Val, RHS: S2->Val, Name); |
933 | // It may have been folded into a constant. |
934 | if (auto *LLVMC = dyn_cast<llvm::Constant>(Val: LLVMV)) |
935 | return Ctx.getOrCreateConstant(LLVMC); |
936 | if (isa<llvm::ICmpInst>(Val: LLVMV)) |
937 | return Ctx.createICmpInst(I: cast<llvm::ICmpInst>(Val: LLVMV)); |
938 | return Ctx.createFCmpInst(I: cast<llvm::FCmpInst>(Val: LLVMV)); |
939 | } |
940 | |
941 | Value *CmpInst::createWithCopiedFlags(Predicate P, Value *S1, Value *S2, |
942 | const Instruction *F, InsertPosition Pos, |
943 | Context &Ctx, const Twine &Name) { |
944 | Value *V = create(P, S1, S2, Pos, Ctx, Name); |
945 | if (auto *C = dyn_cast<Constant>(Val: V)) |
946 | return C; |
947 | cast<llvm::CmpInst>(Val: V->Val)->copyIRFlags(V: F->Val); |
948 | return V; |
949 | } |
950 | |
951 | Type *CmpInst::makeCmpResultType(Type *OpndType) { |
952 | if (auto *VT = dyn_cast<VectorType>(Val: OpndType)) { |
953 | // TODO: Cleanup when we have more complete support for |
954 | // sandboxir::VectorType |
955 | return OpndType->getContext().getType(LLVMTy: llvm::VectorType::get( |
956 | ElementType: llvm::Type::getInt1Ty(C&: OpndType->getContext().LLVMCtx), |
957 | EC: cast<llvm::VectorType>(Val: VT->LLVMTy)->getElementCount())); |
958 | } |
959 | return Type::getInt1Ty(Ctx&: OpndType->getContext()); |
960 | } |
961 | |
962 | void CmpInst::setPredicate(Predicate P) { |
963 | Ctx.getTracker() |
964 | .emplaceIfTracking< |
965 | GenericSetter<&CmpInst::getPredicate, &CmpInst::setPredicate>>(Args: this); |
966 | cast<llvm::CmpInst>(Val)->setPredicate(P); |
967 | } |
968 | |
969 | void CmpInst::swapOperands() { |
970 | if (ICmpInst *IC = dyn_cast<ICmpInst>(Val: this)) |
971 | IC->swapOperands(); |
972 | else |
973 | cast<FCmpInst>(Val: this)->swapOperands(); |
974 | } |
975 | |
976 | void ICmpInst::swapOperands() { |
977 | Ctx.getTracker().emplaceIfTracking<CmpSwapOperands>(Args: this); |
978 | cast<llvm::ICmpInst>(Val)->swapOperands(); |
979 | } |
980 | |
981 | void FCmpInst::swapOperands() { |
982 | Ctx.getTracker().emplaceIfTracking<CmpSwapOperands>(Args: this); |
983 | cast<llvm::FCmpInst>(Val)->swapOperands(); |
984 | } |
985 | |
986 | #ifndef NDEBUG |
987 | void CmpInst::dumpOS(raw_ostream &OS) const { |
988 | dumpCommonPrefix(OS); |
989 | dumpCommonSuffix(OS); |
990 | } |
991 | |
992 | void CmpInst::dump() const { |
993 | dumpOS(dbgs()); |
994 | dbgs() << "\n" ; |
995 | } |
996 | #endif // NDEBUG |
997 | |
998 | static llvm::Instruction::CastOps getLLVMCastOp(Instruction::Opcode Opc) { |
999 | switch (Opc) { |
1000 | case Instruction::Opcode::ZExt: |
1001 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::ZExt); |
1002 | case Instruction::Opcode::SExt: |
1003 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SExt); |
1004 | case Instruction::Opcode::FPToUI: |
1005 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToUI); |
1006 | case Instruction::Opcode::FPToSI: |
1007 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPToSI); |
1008 | case Instruction::Opcode::FPExt: |
1009 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPExt); |
1010 | case Instruction::Opcode::PtrToInt: |
1011 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::PtrToInt); |
1012 | case Instruction::Opcode::IntToPtr: |
1013 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::IntToPtr); |
1014 | case Instruction::Opcode::SIToFP: |
1015 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::SIToFP); |
1016 | case Instruction::Opcode::UIToFP: |
1017 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::UIToFP); |
1018 | case Instruction::Opcode::Trunc: |
1019 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::Trunc); |
1020 | case Instruction::Opcode::FPTrunc: |
1021 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::FPTrunc); |
1022 | case Instruction::Opcode::BitCast: |
1023 | return static_cast<llvm::Instruction::CastOps>(llvm::Instruction::BitCast); |
1024 | case Instruction::Opcode::AddrSpaceCast: |
1025 | return static_cast<llvm::Instruction::CastOps>( |
1026 | llvm::Instruction::AddrSpaceCast); |
1027 | default: |
1028 | llvm_unreachable("Opcode not suitable for CastInst!" ); |
1029 | } |
1030 | } |
1031 | |
1032 | /// \Returns the LLVM opcode that corresponds to \p Opc. |
1033 | static llvm::Instruction::UnaryOps getLLVMUnaryOp(Instruction::Opcode Opc) { |
1034 | switch (Opc) { |
1035 | case Instruction::Opcode::FNeg: |
1036 | return static_cast<llvm::Instruction::UnaryOps>(llvm::Instruction::FNeg); |
1037 | default: |
1038 | llvm_unreachable("Not a unary op!" ); |
1039 | } |
1040 | } |
1041 | |
1042 | CatchSwitchInst *CatchSwitchInst::create(Value *ParentPad, BasicBlock *UnwindBB, |
1043 | unsigned NumHandlers, |
1044 | InsertPosition Pos, Context &Ctx, |
1045 | const Twine &Name) { |
1046 | auto &Builder = setInsertPos(Pos); |
1047 | llvm::CatchSwitchInst *LLVMCSI = Builder.CreateCatchSwitch( |
1048 | ParentPad: ParentPad->Val, UnwindBB: cast<llvm::BasicBlock>(Val: UnwindBB->Val), NumHandlers, Name); |
1049 | return Ctx.createCatchSwitchInst(I: LLVMCSI); |
1050 | } |
1051 | |
1052 | Value *CatchSwitchInst::getParentPad() const { |
1053 | return Ctx.getValue(V: cast<llvm::CatchSwitchInst>(Val)->getParentPad()); |
1054 | } |
1055 | |
1056 | void CatchSwitchInst::setParentPad(Value *ParentPad) { |
1057 | Ctx.getTracker() |
1058 | .emplaceIfTracking<GenericSetter<&CatchSwitchInst::getParentPad, |
1059 | &CatchSwitchInst::setParentPad>>(Args: this); |
1060 | cast<llvm::CatchSwitchInst>(Val)->setParentPad(ParentPad->Val); |
1061 | } |
1062 | |
1063 | BasicBlock *CatchSwitchInst::getUnwindDest() const { |
1064 | return cast_or_null<BasicBlock>( |
1065 | Val: Ctx.getValue(V: cast<llvm::CatchSwitchInst>(Val)->getUnwindDest())); |
1066 | } |
1067 | |
1068 | void CatchSwitchInst::setUnwindDest(BasicBlock *UnwindDest) { |
1069 | Ctx.getTracker() |
1070 | .emplaceIfTracking<GenericSetter<&CatchSwitchInst::getUnwindDest, |
1071 | &CatchSwitchInst::setUnwindDest>>(Args: this); |
1072 | cast<llvm::CatchSwitchInst>(Val)->setUnwindDest( |
1073 | cast<llvm::BasicBlock>(Val: UnwindDest->Val)); |
1074 | } |
1075 | |
1076 | void CatchSwitchInst::addHandler(BasicBlock *Dest) { |
1077 | Ctx.getTracker().emplaceIfTracking<CatchSwitchAddHandler>(Args: this); |
1078 | cast<llvm::CatchSwitchInst>(Val)->addHandler( |
1079 | Dest: cast<llvm::BasicBlock>(Val: Dest->Val)); |
1080 | } |
1081 | |
1082 | ResumeInst *ResumeInst::create(Value *Exn, InsertPosition Pos, Context &Ctx) { |
1083 | auto &Builder = setInsertPos(Pos); |
1084 | auto *LLVMI = cast<llvm::ResumeInst>(Val: Builder.CreateResume(Exn: Exn->Val)); |
1085 | return Ctx.createResumeInst(I: LLVMI); |
1086 | } |
1087 | |
1088 | Value *ResumeInst::getValue() const { |
1089 | return Ctx.getValue(V: cast<llvm::ResumeInst>(Val)->getValue()); |
1090 | } |
1091 | |
1092 | SwitchInst *SwitchInst::create(Value *V, BasicBlock *Dest, unsigned NumCases, |
1093 | InsertPosition Pos, Context &Ctx, |
1094 | const Twine &Name) { |
1095 | auto &Builder = setInsertPos(Pos); |
1096 | llvm::SwitchInst *LLVMSwitch = |
1097 | Builder.CreateSwitch(V: V->Val, Dest: cast<llvm::BasicBlock>(Val: Dest->Val), NumCases); |
1098 | return Ctx.createSwitchInst(I: LLVMSwitch); |
1099 | } |
1100 | |
1101 | Value *SwitchInst::getCondition() const { |
1102 | return Ctx.getValue(V: cast<llvm::SwitchInst>(Val)->getCondition()); |
1103 | } |
1104 | |
1105 | void SwitchInst::setCondition(Value *V) { |
1106 | Ctx.getTracker() |
1107 | .emplaceIfTracking< |
1108 | GenericSetter<&SwitchInst::getCondition, &SwitchInst::setCondition>>( |
1109 | Args: this); |
1110 | cast<llvm::SwitchInst>(Val)->setCondition(V->Val); |
1111 | } |
1112 | |
1113 | BasicBlock *SwitchInst::getDefaultDest() const { |
1114 | return cast<BasicBlock>( |
1115 | Val: Ctx.getValue(V: cast<llvm::SwitchInst>(Val)->getDefaultDest())); |
1116 | } |
1117 | |
1118 | void SwitchInst::setDefaultDest(BasicBlock *DefaultCase) { |
1119 | Ctx.getTracker() |
1120 | .emplaceIfTracking<GenericSetter<&SwitchInst::getDefaultDest, |
1121 | &SwitchInst::setDefaultDest>>(Args: this); |
1122 | cast<llvm::SwitchInst>(Val)->setDefaultDest( |
1123 | cast<llvm::BasicBlock>(Val: DefaultCase->Val)); |
1124 | } |
1125 | ConstantInt *SwitchInst::findCaseDest(BasicBlock *BB) { |
1126 | auto *LLVMC = cast<llvm::SwitchInst>(Val)->findCaseDest( |
1127 | BB: cast<llvm::BasicBlock>(Val: BB->Val)); |
1128 | return LLVMC != nullptr ? cast<ConstantInt>(Val: Ctx.getValue(V: LLVMC)) : nullptr; |
1129 | } |
1130 | |
1131 | void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) { |
1132 | Ctx.getTracker().emplaceIfTracking<SwitchAddCase>(Args: this, Args: OnVal); |
1133 | // TODO: Track this! |
1134 | cast<llvm::SwitchInst>(Val)->addCase(OnVal: cast<llvm::ConstantInt>(Val: OnVal->Val), |
1135 | Dest: cast<llvm::BasicBlock>(Val: Dest->Val)); |
1136 | } |
1137 | |
1138 | SwitchInst::CaseIt SwitchInst::removeCase(CaseIt It) { |
1139 | Ctx.getTracker().emplaceIfTracking<SwitchRemoveCase>(Args: this); |
1140 | |
1141 | auto *LLVMSwitch = cast<llvm::SwitchInst>(Val); |
1142 | unsigned CaseNum = It - case_begin(); |
1143 | llvm::SwitchInst::CaseIt LLVMIt(LLVMSwitch, CaseNum); |
1144 | auto LLVMCaseIt = LLVMSwitch->removeCase(I: LLVMIt); |
1145 | unsigned Num = LLVMCaseIt - LLVMSwitch->case_begin(); |
1146 | return CaseIt(this, Num); |
1147 | } |
1148 | |
1149 | BasicBlock *SwitchInst::getSuccessor(unsigned Idx) const { |
1150 | return cast<BasicBlock>( |
1151 | Val: Ctx.getValue(V: cast<llvm::SwitchInst>(Val)->getSuccessor(idx: Idx))); |
1152 | } |
1153 | |
1154 | void SwitchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) { |
1155 | Ctx.getTracker() |
1156 | .emplaceIfTracking<GenericSetterWithIdx<&SwitchInst::getSuccessor, |
1157 | &SwitchInst::setSuccessor>>(Args: this, |
1158 | Args: Idx); |
1159 | cast<llvm::SwitchInst>(Val)->setSuccessor( |
1160 | idx: Idx, NewSucc: cast<llvm::BasicBlock>(Val: NewSucc->Val)); |
1161 | } |
1162 | |
1163 | Value *UnaryOperator::create(Instruction::Opcode Op, Value *OpV, |
1164 | InsertPosition Pos, Context &Ctx, |
1165 | const Twine &Name) { |
1166 | auto &Builder = setInsertPos(Pos); |
1167 | auto *NewLLVMV = Builder.CreateUnOp(Opc: getLLVMUnaryOp(Opc: Op), V: OpV->Val, Name); |
1168 | if (auto *NewUnOpV = dyn_cast<llvm::UnaryOperator>(Val: NewLLVMV)) { |
1169 | return Ctx.createUnaryOperator(I: NewUnOpV); |
1170 | } |
1171 | assert(isa<llvm::Constant>(NewLLVMV) && "Expected constant" ); |
1172 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewLLVMV)); |
1173 | } |
1174 | |
1175 | Value *UnaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *OpV, |
1176 | Value *CopyFrom, InsertPosition Pos, |
1177 | Context &Ctx, const Twine &Name) { |
1178 | auto *NewV = create(Op, OpV, Pos, Ctx, Name); |
1179 | if (auto *UnI = dyn_cast<llvm::UnaryOperator>(Val: NewV->Val)) |
1180 | UnI->copyIRFlags(V: CopyFrom->Val); |
1181 | return NewV; |
1182 | } |
1183 | |
1184 | /// \Returns the LLVM opcode that corresponds to \p Opc. |
1185 | static llvm::Instruction::BinaryOps getLLVMBinaryOp(Instruction::Opcode Opc) { |
1186 | switch (Opc) { |
1187 | case Instruction::Opcode::Add: |
1188 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Add); |
1189 | case Instruction::Opcode::FAdd: |
1190 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FAdd); |
1191 | case Instruction::Opcode::Sub: |
1192 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Sub); |
1193 | case Instruction::Opcode::FSub: |
1194 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FSub); |
1195 | case Instruction::Opcode::Mul: |
1196 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Mul); |
1197 | case Instruction::Opcode::FMul: |
1198 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FMul); |
1199 | case Instruction::Opcode::UDiv: |
1200 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::UDiv); |
1201 | case Instruction::Opcode::SDiv: |
1202 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SDiv); |
1203 | case Instruction::Opcode::FDiv: |
1204 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FDiv); |
1205 | case Instruction::Opcode::URem: |
1206 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::URem); |
1207 | case Instruction::Opcode::SRem: |
1208 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::SRem); |
1209 | case Instruction::Opcode::FRem: |
1210 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::FRem); |
1211 | case Instruction::Opcode::Shl: |
1212 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Shl); |
1213 | case Instruction::Opcode::LShr: |
1214 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::LShr); |
1215 | case Instruction::Opcode::AShr: |
1216 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::AShr); |
1217 | case Instruction::Opcode::And: |
1218 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::And); |
1219 | case Instruction::Opcode::Or: |
1220 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Or); |
1221 | case Instruction::Opcode::Xor: |
1222 | return static_cast<llvm::Instruction::BinaryOps>(llvm::Instruction::Xor); |
1223 | default: |
1224 | llvm_unreachable("Not a binary op!" ); |
1225 | } |
1226 | } |
1227 | Value *BinaryOperator::create(Instruction::Opcode Op, Value *LHS, Value *RHS, |
1228 | InsertPosition Pos, Context &Ctx, |
1229 | const Twine &Name) { |
1230 | auto &Builder = setInsertPos(Pos); |
1231 | llvm::Value *NewV = |
1232 | Builder.CreateBinOp(Opc: getLLVMBinaryOp(Opc: Op), LHS: LHS->Val, RHS: RHS->Val, Name); |
1233 | if (auto *NewBinOp = dyn_cast<llvm::BinaryOperator>(Val: NewV)) |
1234 | return Ctx.createBinaryOperator(I: NewBinOp); |
1235 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
1236 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
1237 | } |
1238 | |
1239 | Value *BinaryOperator::createWithCopiedFlags(Instruction::Opcode Op, Value *LHS, |
1240 | Value *RHS, Value *CopyFrom, |
1241 | InsertPosition Pos, Context &Ctx, |
1242 | const Twine &Name) { |
1243 | |
1244 | Value *NewV = create(Op, LHS, RHS, Pos, Ctx, Name); |
1245 | if (auto *NewBO = dyn_cast<BinaryOperator>(Val: NewV)) |
1246 | cast<llvm::BinaryOperator>(Val: NewBO->Val)->copyIRFlags(V: CopyFrom->Val); |
1247 | return NewV; |
1248 | } |
1249 | |
1250 | void PossiblyDisjointInst::setIsDisjoint(bool B) { |
1251 | Ctx.getTracker() |
1252 | .emplaceIfTracking<GenericSetter<&PossiblyDisjointInst::isDisjoint, |
1253 | &PossiblyDisjointInst::setIsDisjoint>>( |
1254 | Args: this); |
1255 | cast<llvm::PossiblyDisjointInst>(Val)->setIsDisjoint(B); |
1256 | } |
1257 | |
1258 | void AtomicRMWInst::setAlignment(Align Align) { |
1259 | Ctx.getTracker() |
1260 | .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getAlign, |
1261 | &AtomicRMWInst::setAlignment>>(Args: this); |
1262 | cast<llvm::AtomicRMWInst>(Val)->setAlignment(Align); |
1263 | } |
1264 | |
1265 | void AtomicRMWInst::setVolatile(bool V) { |
1266 | Ctx.getTracker() |
1267 | .emplaceIfTracking<GenericSetter<&AtomicRMWInst::isVolatile, |
1268 | &AtomicRMWInst::setVolatile>>(Args: this); |
1269 | cast<llvm::AtomicRMWInst>(Val)->setVolatile(V); |
1270 | } |
1271 | |
1272 | void AtomicRMWInst::setOrdering(AtomicOrdering Ordering) { |
1273 | Ctx.getTracker() |
1274 | .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getOrdering, |
1275 | &AtomicRMWInst::setOrdering>>(Args: this); |
1276 | cast<llvm::AtomicRMWInst>(Val)->setOrdering(Ordering); |
1277 | } |
1278 | |
1279 | void AtomicRMWInst::setSyncScopeID(SyncScope::ID SSID) { |
1280 | Ctx.getTracker() |
1281 | .emplaceIfTracking<GenericSetter<&AtomicRMWInst::getSyncScopeID, |
1282 | &AtomicRMWInst::setSyncScopeID>>(Args: this); |
1283 | cast<llvm::AtomicRMWInst>(Val)->setSyncScopeID(SSID); |
1284 | } |
1285 | |
1286 | Value *AtomicRMWInst::getPointerOperand() { |
1287 | return Ctx.getValue(V: cast<llvm::AtomicRMWInst>(Val)->getPointerOperand()); |
1288 | } |
1289 | |
1290 | Value *AtomicRMWInst::getValOperand() { |
1291 | return Ctx.getValue(V: cast<llvm::AtomicRMWInst>(Val)->getValOperand()); |
1292 | } |
1293 | |
1294 | AtomicRMWInst *AtomicRMWInst::create(BinOp Op, Value *Ptr, Value *Val, |
1295 | MaybeAlign Align, AtomicOrdering Ordering, |
1296 | InsertPosition Pos, Context &Ctx, |
1297 | SyncScope::ID SSID, const Twine &Name) { |
1298 | auto &Builder = setInsertPos(Pos); |
1299 | auto *LLVMAtomicRMW = |
1300 | Builder.CreateAtomicRMW(Op, Ptr: Ptr->Val, Val: Val->Val, Align, Ordering, SSID); |
1301 | LLVMAtomicRMW->setName(Name); |
1302 | return Ctx.createAtomicRMWInst(I: LLVMAtomicRMW); |
1303 | } |
1304 | |
1305 | void AtomicCmpXchgInst::setSyncScopeID(SyncScope::ID SSID) { |
1306 | Ctx.getTracker() |
1307 | .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSyncScopeID, |
1308 | &AtomicCmpXchgInst::setSyncScopeID>>( |
1309 | Args: this); |
1310 | cast<llvm::AtomicCmpXchgInst>(Val)->setSyncScopeID(SSID); |
1311 | } |
1312 | |
1313 | Value *AtomicCmpXchgInst::getPointerOperand() { |
1314 | return Ctx.getValue(V: cast<llvm::AtomicCmpXchgInst>(Val)->getPointerOperand()); |
1315 | } |
1316 | |
1317 | Value *AtomicCmpXchgInst::getCompareOperand() { |
1318 | return Ctx.getValue(V: cast<llvm::AtomicCmpXchgInst>(Val)->getCompareOperand()); |
1319 | } |
1320 | |
1321 | Value *AtomicCmpXchgInst::getNewValOperand() { |
1322 | return Ctx.getValue(V: cast<llvm::AtomicCmpXchgInst>(Val)->getNewValOperand()); |
1323 | } |
1324 | |
1325 | AtomicCmpXchgInst * |
1326 | AtomicCmpXchgInst::create(Value *Ptr, Value *Cmp, Value *New, MaybeAlign Align, |
1327 | AtomicOrdering SuccessOrdering, |
1328 | AtomicOrdering FailureOrdering, InsertPosition Pos, |
1329 | Context &Ctx, SyncScope::ID SSID, const Twine &Name) { |
1330 | auto &Builder = setInsertPos(Pos); |
1331 | auto *LLVMAtomicCmpXchg = |
1332 | Builder.CreateAtomicCmpXchg(Ptr: Ptr->Val, Cmp: Cmp->Val, New: New->Val, Align, |
1333 | SuccessOrdering, FailureOrdering, SSID); |
1334 | LLVMAtomicCmpXchg->setName(Name); |
1335 | return Ctx.createAtomicCmpXchgInst(I: LLVMAtomicCmpXchg); |
1336 | } |
1337 | |
1338 | void AtomicCmpXchgInst::setAlignment(Align Align) { |
1339 | Ctx.getTracker() |
1340 | .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getAlign, |
1341 | &AtomicCmpXchgInst::setAlignment>>(Args: this); |
1342 | cast<llvm::AtomicCmpXchgInst>(Val)->setAlignment(Align); |
1343 | } |
1344 | |
1345 | void AtomicCmpXchgInst::setVolatile(bool V) { |
1346 | Ctx.getTracker() |
1347 | .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isVolatile, |
1348 | &AtomicCmpXchgInst::setVolatile>>(Args: this); |
1349 | cast<llvm::AtomicCmpXchgInst>(Val)->setVolatile(V); |
1350 | } |
1351 | |
1352 | void AtomicCmpXchgInst::setWeak(bool IsWeak) { |
1353 | Ctx.getTracker() |
1354 | .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::isWeak, |
1355 | &AtomicCmpXchgInst::setWeak>>(Args: this); |
1356 | cast<llvm::AtomicCmpXchgInst>(Val)->setWeak(IsWeak); |
1357 | } |
1358 | |
1359 | void AtomicCmpXchgInst::setSuccessOrdering(AtomicOrdering Ordering) { |
1360 | Ctx.getTracker() |
1361 | .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getSuccessOrdering, |
1362 | &AtomicCmpXchgInst::setSuccessOrdering>>( |
1363 | Args: this); |
1364 | cast<llvm::AtomicCmpXchgInst>(Val)->setSuccessOrdering(Ordering); |
1365 | } |
1366 | |
1367 | void AtomicCmpXchgInst::setFailureOrdering(AtomicOrdering Ordering) { |
1368 | Ctx.getTracker() |
1369 | .emplaceIfTracking<GenericSetter<&AtomicCmpXchgInst::getFailureOrdering, |
1370 | &AtomicCmpXchgInst::setFailureOrdering>>( |
1371 | Args: this); |
1372 | cast<llvm::AtomicCmpXchgInst>(Val)->setFailureOrdering(Ordering); |
1373 | } |
1374 | |
1375 | AllocaInst *AllocaInst::create(Type *Ty, unsigned AddrSpace, InsertPosition Pos, |
1376 | Context &Ctx, Value *ArraySize, |
1377 | const Twine &Name) { |
1378 | auto &Builder = setInsertPos(Pos); |
1379 | auto *NewAlloca = |
1380 | Builder.CreateAlloca(Ty: Ty->LLVMTy, AddrSpace, ArraySize: ArraySize->Val, Name); |
1381 | return Ctx.createAllocaInst(I: NewAlloca); |
1382 | } |
1383 | |
1384 | Type *AllocaInst::getAllocatedType() const { |
1385 | return Ctx.getType(LLVMTy: cast<llvm::AllocaInst>(Val)->getAllocatedType()); |
1386 | } |
1387 | |
1388 | void AllocaInst::setAllocatedType(Type *Ty) { |
1389 | Ctx.getTracker() |
1390 | .emplaceIfTracking<GenericSetter<&AllocaInst::getAllocatedType, |
1391 | &AllocaInst::setAllocatedType>>(Args: this); |
1392 | cast<llvm::AllocaInst>(Val)->setAllocatedType(Ty->LLVMTy); |
1393 | } |
1394 | |
1395 | void AllocaInst::setAlignment(Align Align) { |
1396 | Ctx.getTracker() |
1397 | .emplaceIfTracking< |
1398 | GenericSetter<&AllocaInst::getAlign, &AllocaInst::setAlignment>>( |
1399 | Args: this); |
1400 | cast<llvm::AllocaInst>(Val)->setAlignment(Align); |
1401 | } |
1402 | |
1403 | void AllocaInst::setUsedWithInAlloca(bool V) { |
1404 | Ctx.getTracker() |
1405 | .emplaceIfTracking<GenericSetter<&AllocaInst::isUsedWithInAlloca, |
1406 | &AllocaInst::setUsedWithInAlloca>>(Args: this); |
1407 | cast<llvm::AllocaInst>(Val)->setUsedWithInAlloca(V); |
1408 | } |
1409 | |
1410 | Value *AllocaInst::getArraySize() { |
1411 | return Ctx.getValue(V: cast<llvm::AllocaInst>(Val)->getArraySize()); |
1412 | } |
1413 | |
1414 | PointerType *AllocaInst::getType() const { |
1415 | return cast<PointerType>(Val: Ctx.getType(LLVMTy: cast<llvm::AllocaInst>(Val)->getType())); |
1416 | } |
1417 | |
1418 | Value *CastInst::create(Type *DestTy, Opcode Op, Value *Operand, |
1419 | InsertPosition Pos, Context &Ctx, const Twine &Name) { |
1420 | assert(getLLVMCastOp(Op) && "Opcode not suitable for CastInst!" ); |
1421 | auto &Builder = setInsertPos(Pos); |
1422 | auto *NewV = |
1423 | Builder.CreateCast(Op: getLLVMCastOp(Opc: Op), V: Operand->Val, DestTy: DestTy->LLVMTy, Name); |
1424 | if (auto *NewCI = dyn_cast<llvm::CastInst>(Val: NewV)) |
1425 | return Ctx.createCastInst(I: NewCI); |
1426 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
1427 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
1428 | } |
1429 | |
1430 | bool CastInst::classof(const Value *From) { |
1431 | return From->getSubclassID() == ClassID::Cast; |
1432 | } |
1433 | |
1434 | Type *CastInst::getSrcTy() const { |
1435 | return Ctx.getType(LLVMTy: cast<llvm::CastInst>(Val)->getSrcTy()); |
1436 | } |
1437 | |
1438 | Type *CastInst::getDestTy() const { |
1439 | return Ctx.getType(LLVMTy: cast<llvm::CastInst>(Val)->getDestTy()); |
1440 | } |
1441 | |
1442 | void PossiblyNonNegInst::setNonNeg(bool B) { |
1443 | Ctx.getTracker() |
1444 | .emplaceIfTracking<GenericSetter<&PossiblyNonNegInst::hasNonNeg, |
1445 | &PossiblyNonNegInst::setNonNeg>>(Args: this); |
1446 | cast<llvm::PossiblyNonNegInst>(Val)->setNonNeg(B); |
1447 | } |
1448 | |
1449 | Value *InsertElementInst::create(Value *Vec, Value *NewElt, Value *Idx, |
1450 | InsertPosition Pos, Context &Ctx, |
1451 | const Twine &Name) { |
1452 | auto &Builder = Instruction::setInsertPos(Pos); |
1453 | llvm::Value *NewV = |
1454 | Builder.CreateInsertElement(Vec: Vec->Val, NewElt: NewElt->Val, Idx: Idx->Val, Name); |
1455 | if (auto *NewInsert = dyn_cast<llvm::InsertElementInst>(Val: NewV)) |
1456 | return Ctx.createInsertElementInst(IEI: NewInsert); |
1457 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
1458 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
1459 | } |
1460 | |
1461 | Value *ExtractElementInst::create(Value *Vec, Value *Idx, InsertPosition Pos, |
1462 | Context &Ctx, const Twine &Name) { |
1463 | auto &Builder = setInsertPos(Pos); |
1464 | llvm::Value *NewV = Builder.CreateExtractElement(Vec: Vec->Val, Idx: Idx->Val, Name); |
1465 | if (auto * = dyn_cast<llvm::ExtractElementInst>(Val: NewV)) |
1466 | return Ctx.createExtractElementInst(EEI: NewExtract); |
1467 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
1468 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
1469 | } |
1470 | |
1471 | Value *ShuffleVectorInst::create(Value *V1, Value *V2, Value *Mask, |
1472 | InsertPosition Pos, Context &Ctx, |
1473 | const Twine &Name) { |
1474 | auto &Builder = setInsertPos(Pos); |
1475 | llvm::Value *NewV = |
1476 | Builder.CreateShuffleVector(V1: V1->Val, V2: V2->Val, Mask: Mask->Val, Name); |
1477 | if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(Val: NewV)) |
1478 | return Ctx.createShuffleVectorInst(SVI: NewShuffle); |
1479 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
1480 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
1481 | } |
1482 | |
1483 | Value *ShuffleVectorInst::create(Value *V1, Value *V2, ArrayRef<int> Mask, |
1484 | InsertPosition Pos, Context &Ctx, |
1485 | const Twine &Name) { |
1486 | auto &Builder = setInsertPos(Pos); |
1487 | llvm::Value *NewV = Builder.CreateShuffleVector(V1: V1->Val, V2: V2->Val, Mask, Name); |
1488 | if (auto *NewShuffle = dyn_cast<llvm::ShuffleVectorInst>(Val: NewV)) |
1489 | return Ctx.createShuffleVectorInst(SVI: NewShuffle); |
1490 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
1491 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
1492 | } |
1493 | |
1494 | void ShuffleVectorInst::setShuffleMask(ArrayRef<int> Mask) { |
1495 | Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(Args: this); |
1496 | cast<llvm::ShuffleVectorInst>(Val)->setShuffleMask(Mask); |
1497 | } |
1498 | |
1499 | VectorType *ShuffleVectorInst::getType() const { |
1500 | return cast<VectorType>( |
1501 | Val: Ctx.getType(LLVMTy: cast<llvm::ShuffleVectorInst>(Val)->getType())); |
1502 | } |
1503 | |
1504 | void ShuffleVectorInst::commute() { |
1505 | Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(Args: this); |
1506 | Ctx.getTracker().emplaceIfTracking<UseSwap>(Args: getOperandUse(OpIdx: 0), |
1507 | Args: getOperandUse(OpIdx: 1)); |
1508 | cast<llvm::ShuffleVectorInst>(Val)->commute(); |
1509 | } |
1510 | |
1511 | Constant *ShuffleVectorInst::getShuffleMaskForBitcode() const { |
1512 | return Ctx.getOrCreateConstant( |
1513 | LLVMC: cast<llvm::ShuffleVectorInst>(Val)->getShuffleMaskForBitcode()); |
1514 | } |
1515 | |
1516 | Constant *ShuffleVectorInst::convertShuffleMaskForBitcode(ArrayRef<int> Mask, |
1517 | Type *ResultTy) { |
1518 | return ResultTy->getContext().getOrCreateConstant( |
1519 | LLVMC: llvm::ShuffleVectorInst::convertShuffleMaskForBitcode(Mask, |
1520 | ResultTy: ResultTy->LLVMTy)); |
1521 | } |
1522 | |
1523 | VectorType *ExtractElementInst::getVectorOperandType() const { |
1524 | return cast<VectorType>(Val: Ctx.getType(LLVMTy: getVectorOperand()->getType()->LLVMTy)); |
1525 | } |
1526 | |
1527 | Value *ExtractValueInst::create(Value *Agg, ArrayRef<unsigned> Idxs, |
1528 | InsertPosition Pos, Context &Ctx, |
1529 | const Twine &Name) { |
1530 | auto &Builder = setInsertPos(Pos); |
1531 | llvm::Value *NewV = Builder.CreateExtractValue(Agg: Agg->Val, Idxs, Name); |
1532 | if (auto * = dyn_cast<llvm::ExtractValueInst>(Val: NewV)) |
1533 | return Ctx.createExtractValueInst(IVI: NewExtractValueInst); |
1534 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
1535 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
1536 | } |
1537 | |
1538 | Type *ExtractValueInst::getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs) { |
1539 | auto *LLVMTy = llvm::ExtractValueInst::getIndexedType(Agg: Agg->LLVMTy, Idxs); |
1540 | return Agg->getContext().getType(LLVMTy); |
1541 | } |
1542 | |
1543 | Value *InsertValueInst::create(Value *Agg, Value *Val, ArrayRef<unsigned> Idxs, |
1544 | InsertPosition Pos, Context &Ctx, |
1545 | const Twine &Name) { |
1546 | auto &Builder = setInsertPos(Pos); |
1547 | llvm::Value *NewV = Builder.CreateInsertValue(Agg: Agg->Val, Val: Val->Val, Idxs, Name); |
1548 | if (auto *NewInsertValueInst = dyn_cast<llvm::InsertValueInst>(Val: NewV)) |
1549 | return Ctx.createInsertValueInst(IVI: NewInsertValueInst); |
1550 | assert(isa<llvm::Constant>(NewV) && "Expected constant" ); |
1551 | return Ctx.getOrCreateConstant(LLVMC: cast<llvm::Constant>(Val: NewV)); |
1552 | } |
1553 | |
1554 | ConstantTokenNone *ConstantTokenNone::get(Context &Ctx) { |
1555 | auto *LLVMC = llvm::ConstantTokenNone::get(Context&: Ctx.LLVMCtx); |
1556 | return cast<ConstantTokenNone>(Val: Ctx.getOrCreateConstant(LLVMC)); |
1557 | } |
1558 | |
1559 | } // namespace llvm::sandboxir |
1560 | |