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
12namespace llvm::sandboxir {
13
14const 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
26llvm::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
38BBIterator Instruction::getIterator() const {
39 auto *I = cast<llvm::Instruction>(Val);
40 return BasicBlock::iterator(I->getParent(), I->getIterator(), &Ctx);
41}
42
43Instruction *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
58Instruction *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
66void 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
74void 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
100void 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
125void 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
135void Instruction::insertAfter(Instruction *AfterI) {
136 insertInto(BB: AfterI->getParent(), WhereIt: std::next(x: AfterI->getIterator()));
137}
138
139void 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
161BasicBlock *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
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#include "llvm/SandboxIR/Values.def"
176 default:
177 return false;
178 }
179}
180
181void 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
189void 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
196void 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
203void 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
210void 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
217void 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
225void 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
233void 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
241void 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
249void 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
257void 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
264void 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
271Type *Instruction::getAccessType() const {
272 return Ctx.getType(LLVMTy: cast<llvm::Instruction>(Val)->getAccessType());
273}
274
275void 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
283void Instruction::dumpOS(raw_ostream &OS) const {
284 OS << "Unimplemented! Please override dump().";
285}
286#endif // NDEBUG
287
288VAArgInst *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
296Value *VAArgInst::getPointerOperand() {
297 return Ctx.getValue(V: cast<llvm::VAArgInst>(Val)->getPointerOperand());
298}
299
300FreezeInst *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
307FenceInst *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
314void 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
322void 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
329Value *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
340void SelectInst::swapValues() {
341 Ctx.getTracker().emplaceIfTracking<UseSwap>(Args: getOperandUse(OpIdx: 1),
342 Args: getOperandUse(OpIdx: 2));
343 cast<llvm::SelectInst>(Val)->swapValues();
344}
345
346bool SelectInst::classof(const Value *From) {
347 return From->getSubclassID() == ClassID::Select;
348}
349
350BranchInst *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
358BranchInst *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
367bool BranchInst::classof(const Value *From) {
368 return From->getSubclassID() == ClassID::Br;
369}
370
371Value *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
376BasicBlock *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
383void BranchInst::setSuccessor(unsigned Idx, BasicBlock *NewSucc) {
384 assert((Idx == 0 || Idx == 1) && "Out of bounds!");
385 setOperand(OperandIdx: 2u - Idx, Operand: NewSucc);
386}
387
388BasicBlock *BranchInst::LLVMBBToSBBB::operator()(llvm::BasicBlock *BB) const {
389 return cast<BasicBlock>(Val: Ctx.getValue(V: BB));
390}
391const BasicBlock *
392BranchInst::ConstLLVMBBToSBBB::operator()(const llvm::BasicBlock *BB) const {
393 return cast<BasicBlock>(Val: Ctx.getValue(V: BB));
394}
395
396void 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
403LoadInst *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
413bool LoadInst::classof(const Value *From) {
414 return From->getSubclassID() == ClassID::Load;
415}
416
417Value *LoadInst::getPointerOperand() const {
418 return Ctx.getValue(V: cast<llvm::LoadInst>(Val)->getPointerOperand());
419}
420
421void 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
428StoreInst *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
437bool StoreInst::classof(const Value *From) {
438 return From->getSubclassID() == ClassID::Store;
439}
440
441Value *StoreInst::getValueOperand() const {
442 return Ctx.getValue(V: cast<llvm::StoreInst>(Val)->getValueOperand());
443}
444
445Value *StoreInst::getPointerOperand() const {
446 return Ctx.getValue(V: cast<llvm::StoreInst>(Val)->getPointerOperand());
447}
448
449UnreachableInst *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
455bool UnreachableInst::classof(const Value *From) {
456 return From->getSubclassID() == ClassID::Unreachable;
457}
458
459ReturnInst *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
469ReturnInst *ReturnInst::create(Value *RetVal, InsertPosition Pos,
470 Context &Ctx) {
471 auto &Builder = setInsertPos(Pos);
472 return createCommon(RetVal, Builder, Ctx);
473}
474
475Value *ReturnInst::getReturnValue() const {
476 auto *LLVMRetVal = cast<llvm::ReturnInst>(Val)->getReturnValue();
477 return LLVMRetVal != nullptr ? Ctx.getValue(V: LLVMRetVal) : nullptr;
478}
479
480FunctionType *CallBase::getFunctionType() const {
481 return cast<FunctionType>(
482 Val: Ctx.getType(LLVMTy: cast<llvm::CallBase>(Val)->getFunctionType()));
483}
484
485Value *CallBase::getCalledOperand() const {
486 return Ctx.getValue(V: cast<llvm::CallBase>(Val)->getCalledOperand());
487}
488
489Use 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
494Function *CallBase::getCalledFunction() const {
495 return cast_or_null<Function>(
496 Val: Ctx.getValue(V: cast<llvm::CallBase>(Val)->getCalledFunction()));
497}
498Function *CallBase::getCaller() {
499 return cast<Function>(Val: Ctx.getValue(V: cast<llvm::CallBase>(Val)->getCaller()));
500}
501
502void 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
515CallInst *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
528InvokeInst *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
544BasicBlock *InvokeInst::getNormalDest() const {
545 return cast<BasicBlock>(
546 Val: Ctx.getValue(V: cast<llvm::InvokeInst>(Val)->getNormalDest()));
547}
548BasicBlock *InvokeInst::getUnwindDest() const {
549 return cast<BasicBlock>(
550 Val: Ctx.getValue(V: cast<llvm::InvokeInst>(Val)->getUnwindDest()));
551}
552void InvokeInst::setNormalDest(BasicBlock *BB) {
553 setOperand(OperandIdx: 1, Operand: BB);
554 assert(getNormalDest() == BB && "LLVM IR uses a different operan index!");
555}
556void InvokeInst::setUnwindDest(BasicBlock *BB) {
557 setOperand(OperandIdx: 2, Operand: BB);
558 assert(getUnwindDest() == BB && "LLVM IR uses a different operan index!");
559}
560LandingPadInst *InvokeInst::getLandingPadInst() const {
561 return cast<LandingPadInst>(
562 Val: Ctx.getValue(V: cast<llvm::InvokeInst>(Val)->getLandingPadInst()));
563 ;
564}
565BasicBlock *InvokeInst::getSuccessor(unsigned SuccIdx) const {
566 return cast<BasicBlock>(
567 Val: Ctx.getValue(V: cast<llvm::InvokeInst>(Val)->getSuccessor(i: SuccIdx)));
568}
569
570CallBrInst *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
593Value *CallBrInst::getIndirectDestLabel(unsigned Idx) const {
594 return Ctx.getValue(V: cast<llvm::CallBrInst>(Val)->getIndirectDestLabel(i: Idx));
595}
596Value *CallBrInst::getIndirectDestLabelUse(unsigned Idx) const {
597 return Ctx.getValue(
598 V: cast<llvm::CallBrInst>(Val)->getIndirectDestLabelUse(i: Idx));
599}
600BasicBlock *CallBrInst::getDefaultDest() const {
601 return cast<BasicBlock>(
602 Val: Ctx.getValue(V: cast<llvm::CallBrInst>(Val)->getDefaultDest()));
603}
604BasicBlock *CallBrInst::getIndirectDest(unsigned Idx) const {
605 return cast<BasicBlock>(
606 Val: Ctx.getValue(V: cast<llvm::CallBrInst>(Val)->getIndirectDest(i: Idx)));
607}
608llvm::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}
615void 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}
621void 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}
629BasicBlock *CallBrInst::getSuccessor(unsigned Idx) const {
630 return cast<BasicBlock>(
631 Val: Ctx.getValue(V: cast<llvm::CallBrInst>(Val)->getSuccessor(i: Idx)));
632}
633
634LandingPadInst *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
643void 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
650Constant *LandingPadInst::getClause(unsigned Idx) const {
651 return cast<Constant>(
652 Val: Ctx.getValue(V: cast<llvm::LandingPadInst>(Val)->getClause(Idx)));
653}
654
655Value *FuncletPadInst::getParentPad() const {
656 return Ctx.getValue(V: cast<llvm::FuncletPadInst>(Val)->getParentPad());
657}
658
659void 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
666Value *FuncletPadInst::getArgOperand(unsigned Idx) const {
667 return Ctx.getValue(V: cast<llvm::FuncletPadInst>(Val)->getArgOperand(i: Idx));
668}
669
670void 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
678CatchSwitchInst *CatchPadInst::getCatchSwitch() const {
679 return cast<CatchSwitchInst>(
680 Val: Ctx.getValue(V: cast<llvm::CatchPadInst>(Val)->getCatchSwitch()));
681}
682
683CatchPadInst *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
696CleanupPadInst *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
709CatchReturnInst *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
717CatchPadInst *CatchReturnInst::getCatchPad() const {
718 return cast<CatchPadInst>(
719 Val: Ctx.getValue(V: cast<llvm::CatchReturnInst>(Val)->getCatchPad()));
720}
721
722void 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
730BasicBlock *CatchReturnInst::getSuccessor() const {
731 return cast<BasicBlock>(
732 Val: Ctx.getValue(V: cast<llvm::CatchReturnInst>(Val)->getSuccessor()));
733}
734
735void 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
743Value *CatchReturnInst::getCatchSwitchParentPad() const {
744 return Ctx.getValue(
745 V: cast<llvm::CatchReturnInst>(Val)->getCatchSwitchParentPad());
746}
747
748CleanupReturnInst *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
759CleanupPadInst *CleanupReturnInst::getCleanupPad() const {
760 return cast<CleanupPadInst>(
761 Val: Ctx.getValue(V: cast<llvm::CleanupReturnInst>(Val)->getCleanupPad()));
762}
763
764void 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
773BasicBlock *CleanupReturnInst::getUnwindDest() const {
774 return cast_or_null<BasicBlock>(
775 Val: Ctx.getValue(V: cast<llvm::CleanupReturnInst>(Val)->getUnwindDest()));
776}
777
778void 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
787Value *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
803Type *GetElementPtrInst::getSourceElementType() const {
804 return Ctx.getType(
805 LLVMTy: cast<llvm::GetElementPtrInst>(Val)->getSourceElementType());
806}
807
808Type *GetElementPtrInst::getResultElementType() const {
809 return Ctx.getType(
810 LLVMTy: cast<llvm::GetElementPtrInst>(Val)->getResultElementType());
811}
812
813Value *GetElementPtrInst::getPointerOperand() const {
814 return Ctx.getValue(V: cast<llvm::GetElementPtrInst>(Val)->getPointerOperand());
815}
816
817Type *GetElementPtrInst::getPointerOperandType() const {
818 return Ctx.getType(
819 LLVMTy: cast<llvm::GetElementPtrInst>(Val)->getPointerOperandType());
820}
821
822BasicBlock *PHINode::LLVMBBToBB::operator()(llvm::BasicBlock *LLVMBB) const {
823 return cast<BasicBlock>(Val: Ctx.getValue(V: LLVMBB));
824}
825
826PHINode *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
834bool PHINode::classof(const Value *From) {
835 return From->getSubclassID() == ClassID::PHI;
836}
837
838Value *PHINode::getIncomingValue(unsigned Idx) const {
839 return Ctx.getValue(V: cast<llvm::PHINode>(Val)->getIncomingValue(i: Idx));
840}
841void 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}
848BasicBlock *PHINode::getIncomingBlock(unsigned Idx) const {
849 return cast<BasicBlock>(
850 Val: Ctx.getValue(V: cast<llvm::PHINode>(Val)->getIncomingBlock(i: Idx)));
851}
852BasicBlock *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}
857void 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}
868void 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}
875Value *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}
883Value *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}
893int 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}
897Value *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}
903Value *PHINode::hasConstantValue() const {
904 llvm::Value *LLVMV = cast<llvm::PHINode>(Val)->hasConstantValue();
905 return LLVMV != nullptr ? Ctx.getValue(V: LLVMV) : nullptr;
906}
907void 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}
914void 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
929Value *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
941Value *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
951Type *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
962void 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
969void CmpInst::swapOperands() {
970 if (ICmpInst *IC = dyn_cast<ICmpInst>(Val: this))
971 IC->swapOperands();
972 else
973 cast<FCmpInst>(Val: this)->swapOperands();
974}
975
976void ICmpInst::swapOperands() {
977 Ctx.getTracker().emplaceIfTracking<CmpSwapOperands>(Args: this);
978 cast<llvm::ICmpInst>(Val)->swapOperands();
979}
980
981void FCmpInst::swapOperands() {
982 Ctx.getTracker().emplaceIfTracking<CmpSwapOperands>(Args: this);
983 cast<llvm::FCmpInst>(Val)->swapOperands();
984}
985
986#ifndef NDEBUG
987void CmpInst::dumpOS(raw_ostream &OS) const {
988 dumpCommonPrefix(OS);
989 dumpCommonSuffix(OS);
990}
991
992void CmpInst::dump() const {
993 dumpOS(dbgs());
994 dbgs() << "\n";
995}
996#endif // NDEBUG
997
998static 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.
1033static 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
1042CatchSwitchInst *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
1052Value *CatchSwitchInst::getParentPad() const {
1053 return Ctx.getValue(V: cast<llvm::CatchSwitchInst>(Val)->getParentPad());
1054}
1055
1056void 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
1063BasicBlock *CatchSwitchInst::getUnwindDest() const {
1064 return cast_or_null<BasicBlock>(
1065 Val: Ctx.getValue(V: cast<llvm::CatchSwitchInst>(Val)->getUnwindDest()));
1066}
1067
1068void 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
1076void 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
1082ResumeInst *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
1088Value *ResumeInst::getValue() const {
1089 return Ctx.getValue(V: cast<llvm::ResumeInst>(Val)->getValue());
1090}
1091
1092SwitchInst *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
1101Value *SwitchInst::getCondition() const {
1102 return Ctx.getValue(V: cast<llvm::SwitchInst>(Val)->getCondition());
1103}
1104
1105void 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
1113BasicBlock *SwitchInst::getDefaultDest() const {
1114 return cast<BasicBlock>(
1115 Val: Ctx.getValue(V: cast<llvm::SwitchInst>(Val)->getDefaultDest()));
1116}
1117
1118void 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}
1125ConstantInt *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
1131void 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
1138SwitchInst::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
1149BasicBlock *SwitchInst::getSuccessor(unsigned Idx) const {
1150 return cast<BasicBlock>(
1151 Val: Ctx.getValue(V: cast<llvm::SwitchInst>(Val)->getSuccessor(idx: Idx)));
1152}
1153
1154void 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
1163Value *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
1175Value *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.
1185static 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}
1227Value *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
1239Value *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
1250void 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
1258void 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
1265void 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
1272void 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
1279void 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
1286Value *AtomicRMWInst::getPointerOperand() {
1287 return Ctx.getValue(V: cast<llvm::AtomicRMWInst>(Val)->getPointerOperand());
1288}
1289
1290Value *AtomicRMWInst::getValOperand() {
1291 return Ctx.getValue(V: cast<llvm::AtomicRMWInst>(Val)->getValOperand());
1292}
1293
1294AtomicRMWInst *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
1305void 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
1313Value *AtomicCmpXchgInst::getPointerOperand() {
1314 return Ctx.getValue(V: cast<llvm::AtomicCmpXchgInst>(Val)->getPointerOperand());
1315}
1316
1317Value *AtomicCmpXchgInst::getCompareOperand() {
1318 return Ctx.getValue(V: cast<llvm::AtomicCmpXchgInst>(Val)->getCompareOperand());
1319}
1320
1321Value *AtomicCmpXchgInst::getNewValOperand() {
1322 return Ctx.getValue(V: cast<llvm::AtomicCmpXchgInst>(Val)->getNewValOperand());
1323}
1324
1325AtomicCmpXchgInst *
1326AtomicCmpXchgInst::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
1338void 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
1345void 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
1352void 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
1359void 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
1367void 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
1375AllocaInst *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
1384Type *AllocaInst::getAllocatedType() const {
1385 return Ctx.getType(LLVMTy: cast<llvm::AllocaInst>(Val)->getAllocatedType());
1386}
1387
1388void 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
1395void 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
1403void 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
1410Value *AllocaInst::getArraySize() {
1411 return Ctx.getValue(V: cast<llvm::AllocaInst>(Val)->getArraySize());
1412}
1413
1414PointerType *AllocaInst::getType() const {
1415 return cast<PointerType>(Val: Ctx.getType(LLVMTy: cast<llvm::AllocaInst>(Val)->getType()));
1416}
1417
1418Value *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
1430bool CastInst::classof(const Value *From) {
1431 return From->getSubclassID() == ClassID::Cast;
1432}
1433
1434Type *CastInst::getSrcTy() const {
1435 return Ctx.getType(LLVMTy: cast<llvm::CastInst>(Val)->getSrcTy());
1436}
1437
1438Type *CastInst::getDestTy() const {
1439 return Ctx.getType(LLVMTy: cast<llvm::CastInst>(Val)->getDestTy());
1440}
1441
1442void 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
1449Value *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
1461Value *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 *NewExtract = 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
1471Value *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
1483Value *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
1494void ShuffleVectorInst::setShuffleMask(ArrayRef<int> Mask) {
1495 Ctx.getTracker().emplaceIfTracking<ShuffleVectorSetMask>(Args: this);
1496 cast<llvm::ShuffleVectorInst>(Val)->setShuffleMask(Mask);
1497}
1498
1499VectorType *ShuffleVectorInst::getType() const {
1500 return cast<VectorType>(
1501 Val: Ctx.getType(LLVMTy: cast<llvm::ShuffleVectorInst>(Val)->getType()));
1502}
1503
1504void 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
1511Constant *ShuffleVectorInst::getShuffleMaskForBitcode() const {
1512 return Ctx.getOrCreateConstant(
1513 LLVMC: cast<llvm::ShuffleVectorInst>(Val)->getShuffleMaskForBitcode());
1514}
1515
1516Constant *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
1523VectorType *ExtractElementInst::getVectorOperandType() const {
1524 return cast<VectorType>(Val: Ctx.getType(LLVMTy: getVectorOperand()->getType()->LLVMTy));
1525}
1526
1527Value *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 *NewExtractValueInst = 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
1538Type *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
1543Value *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
1554ConstantTokenNone *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