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