Skip to content

Commit 372a6be

Browse files
authored
[SandboxIR] Implement CallBase and CallInst (#100218)
This patch adds the `CallBase` SandboxIR class and its subclass: `CallInst`. Both are mirrors of `llvm::CallBase` and `llvm::CallInst` respectively. Since `llvm::CallBase` contains a large number of member functions so this patch implements only some of them. The `CallBase` unit tests uncovered an issue with the class hierarchy, where `sandboxir::Function` was not a subclass of `sandboxir::Constant`, so this was fixed. Testing tracking of the `CallBase` setters showed that `sandboxir::Use::set()` was not being tracked. So this is also part of this patch.
1 parent cc1dfb3 commit 372a6be

File tree

6 files changed

+608
-20
lines changed

6 files changed

+608
-20
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 210 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,19 @@
1818
//
1919
// namespace sandboxir {
2020
//
21-
// +- Argument +- BinaryOperator
22-
// | |
23-
// Value -+- BasicBlock +- BranchInst
24-
// | |
25-
// +- Function +- Constant +- CastInst
26-
// | | |
27-
// +- User ------+- Instruction -+- CallInst
21+
// Value -+- Argument
22+
// |
23+
// +- BasicBlock
24+
// |
25+
// +- User ------+- Constant ------ Function
26+
// |
27+
// +- Instruction -+- BinaryOperator
28+
// |
29+
// +- BranchInst
30+
// |
31+
// +- CastInst
32+
// |
33+
// +- CallBase ----- CallInst
2834
// |
2935
// +- CmpInst
3036
// |
@@ -82,6 +88,8 @@ class ReturnInst;
8288
class StoreInst;
8389
class User;
8490
class Value;
91+
class CallBase;
92+
class CallInst;
8593

8694
/// Iterator for the `Use` edges of a User's operands.
8795
/// \Returns the operand `Use` when dereferenced.
@@ -103,12 +111,20 @@ class OperandUseIterator {
103111
OperandUseIterator() = default;
104112
value_type operator*() const;
105113
OperandUseIterator &operator++();
114+
OperandUseIterator operator++(int) {
115+
auto Copy = *this;
116+
this->operator++();
117+
return Copy;
118+
}
106119
bool operator==(const OperandUseIterator &Other) const {
107120
return Use == Other.Use;
108121
}
109122
bool operator!=(const OperandUseIterator &Other) const {
110123
return !(*this == Other);
111124
}
125+
OperandUseIterator operator+(unsigned Num) const;
126+
OperandUseIterator operator-(unsigned Num) const;
127+
int operator-(const OperandUseIterator &Other) const;
112128
};
113129

114130
/// Iterator for the `Use` edges of a Value's users.
@@ -135,6 +151,7 @@ class UserUseIterator {
135151
bool operator!=(const UserUseIterator &Other) const {
136152
return !(*this == Other);
137153
}
154+
const sandboxir::Use &getUse() const { return Use; }
138155
};
139156

140157
/// A SandboxIR Value has users. This is the base class.
@@ -184,6 +201,8 @@ class Value {
184201
friend class LoadInst; // For getting `Val`.
185202
friend class StoreInst; // For getting `Val`.
186203
friend class ReturnInst; // For getting `Val`.
204+
friend class CallBase; // For getting `Val`.
205+
friend class CallInst; // For getting `Val`.
187206

188207
/// All values point to the context.
189208
Context &Ctx;
@@ -417,7 +436,10 @@ class User : public Value {
417436
class Constant : public sandboxir::User {
418437
Constant(llvm::Constant *C, sandboxir::Context &SBCtx)
419438
: sandboxir::User(ClassID::Constant, C, SBCtx) {}
420-
friend class Context; // For constructor.
439+
Constant(ClassID ID, llvm::Constant *C, sandboxir::Context &SBCtx)
440+
: sandboxir::User(ID, C, SBCtx) {}
441+
friend class Function; // For constructor
442+
friend class Context; // For constructor.
421443
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
422444
return getOperandUseDefault(OpIdx, Verify);
423445
}
@@ -435,7 +457,7 @@ class Constant : public sandboxir::User {
435457
return getUseOperandNoDefault(Use);
436458
}
437459
#ifndef NDEBUG
438-
void verify() const final {
460+
void verify() const override {
439461
assert(isa<llvm::Constant>(Val) && "Expected Constant!");
440462
}
441463
friend raw_ostream &operator<<(raw_ostream &OS,
@@ -518,6 +540,7 @@ class Instruction : public sandboxir::User {
518540
friend class LoadInst; // For getTopmostLLVMInstruction().
519541
friend class StoreInst; // For getTopmostLLVMInstruction().
520542
friend class ReturnInst; // For getTopmostLLVMInstruction().
543+
friend class CallInst; // For getTopmostLLVMInstruction().
521544

522545
/// \Returns the LLVM IR Instructions that this SandboxIR maps to in program
523546
/// order.
@@ -835,6 +858,177 @@ class ReturnInst final : public Instruction {
835858
#endif
836859
};
837860

861+
class CallBase : public Instruction {
862+
CallBase(ClassID ID, Opcode Opc, llvm::Instruction *I, Context &Ctx)
863+
: Instruction(ID, Opc, I, Ctx) {}
864+
friend class CallInst; // For constructor.
865+
866+
public:
867+
static bool classof(const Value *From) {
868+
auto Opc = From->getSubclassID();
869+
return Opc == Instruction::ClassID::Call ||
870+
Opc == Instruction::ClassID::Invoke ||
871+
Opc == Instruction::ClassID::CallBr;
872+
}
873+
874+
FunctionType *getFunctionType() const {
875+
return cast<llvm::CallBase>(Val)->getFunctionType();
876+
}
877+
878+
op_iterator data_operands_begin() { return op_begin(); }
879+
const_op_iterator data_operands_begin() const {
880+
return const_cast<CallBase *>(this)->data_operands_begin();
881+
}
882+
op_iterator data_operands_end() {
883+
auto *LLVMCB = cast<llvm::CallBase>(Val);
884+
auto Dist = LLVMCB->data_operands_end() - LLVMCB->data_operands_begin();
885+
return op_begin() + Dist;
886+
}
887+
const_op_iterator data_operands_end() const {
888+
auto *LLVMCB = cast<llvm::CallBase>(Val);
889+
auto Dist = LLVMCB->data_operands_end() - LLVMCB->data_operands_begin();
890+
return op_begin() + Dist;
891+
}
892+
iterator_range<op_iterator> data_ops() {
893+
return make_range(data_operands_begin(), data_operands_end());
894+
}
895+
iterator_range<const_op_iterator> data_ops() const {
896+
return make_range(data_operands_begin(), data_operands_end());
897+
}
898+
bool data_operands_empty() const {
899+
return data_operands_end() == data_operands_begin();
900+
}
901+
unsigned data_operands_size() const {
902+
return std::distance(data_operands_begin(), data_operands_end());
903+
}
904+
bool isDataOperand(Use U) const {
905+
assert(this == U.getUser() &&
906+
"Only valid to query with a use of this instruction!");
907+
return cast<llvm::CallBase>(Val)->isDataOperand(U.LLVMUse);
908+
}
909+
unsigned getDataOperandNo(Use U) const {
910+
assert(isDataOperand(U) && "Data operand # out of range!");
911+
return cast<llvm::CallBase>(Val)->getDataOperandNo(U.LLVMUse);
912+
}
913+
914+
/// Return the total number operands (not operand bundles) used by
915+
/// every operand bundle in this OperandBundleUser.
916+
unsigned getNumTotalBundleOperands() const {
917+
return cast<llvm::CallBase>(Val)->getNumTotalBundleOperands();
918+
}
919+
920+
op_iterator arg_begin() { return op_begin(); }
921+
const_op_iterator arg_begin() const { return op_begin(); }
922+
op_iterator arg_end() {
923+
return data_operands_end() - getNumTotalBundleOperands();
924+
}
925+
const_op_iterator arg_end() const {
926+
return const_cast<CallBase *>(this)->arg_end();
927+
}
928+
iterator_range<op_iterator> args() {
929+
return make_range(arg_begin(), arg_end());
930+
}
931+
iterator_range<const_op_iterator> args() const {
932+
return make_range(arg_begin(), arg_end());
933+
}
934+
bool arg_empty() const { return arg_end() == arg_begin(); }
935+
unsigned arg_size() const { return arg_end() - arg_begin(); }
936+
937+
Value *getArgOperand(unsigned OpIdx) const {
938+
assert(OpIdx < arg_size() && "Out of bounds!");
939+
return getOperand(OpIdx);
940+
}
941+
void setArgOperand(unsigned OpIdx, Value *NewOp) {
942+
assert(OpIdx < arg_size() && "Out of bounds!");
943+
setOperand(OpIdx, NewOp);
944+
}
945+
946+
Use getArgOperandUse(unsigned Idx) const {
947+
assert(Idx < arg_size() && "Out of bounds!");
948+
return getOperandUse(Idx);
949+
}
950+
Use getArgOperandUse(unsigned Idx) {
951+
assert(Idx < arg_size() && "Out of bounds!");
952+
return getOperandUse(Idx);
953+
}
954+
955+
bool isArgOperand(Use U) const {
956+
return cast<llvm::CallBase>(Val)->isArgOperand(U.LLVMUse);
957+
}
958+
unsigned getArgOperandNo(Use U) const {
959+
return cast<llvm::CallBase>(Val)->getArgOperandNo(U.LLVMUse);
960+
}
961+
bool hasArgument(const Value *V) const { return is_contained(args(), V); }
962+
963+
Value *getCalledOperand() const;
964+
Use getCalledOperandUse() const;
965+
966+
Function *getCalledFunction() const;
967+
bool isIndirectCall() const {
968+
return cast<llvm::CallBase>(Val)->isIndirectCall();
969+
}
970+
bool isCallee(Use U) const {
971+
return cast<llvm::CallBase>(Val)->isCallee(U.LLVMUse);
972+
}
973+
Function *getCaller();
974+
const Function *getCaller() const {
975+
return const_cast<CallBase *>(this)->getCaller();
976+
}
977+
bool isMustTailCall() const {
978+
return cast<llvm::CallBase>(Val)->isMustTailCall();
979+
}
980+
bool isTailCall() const { return cast<llvm::CallBase>(Val)->isTailCall(); }
981+
Intrinsic::ID getIntrinsicID() const {
982+
return cast<llvm::CallBase>(Val)->getIntrinsicID();
983+
}
984+
void setCalledOperand(Value *V) { getCalledOperandUse().set(V); }
985+
void setCalledFunction(Function *F);
986+
CallingConv::ID getCallingConv() const {
987+
return cast<llvm::CallBase>(Val)->getCallingConv();
988+
}
989+
bool isInlineAsm() const { return cast<llvm::CallBase>(Val)->isInlineAsm(); }
990+
};
991+
992+
class CallInst final : public CallBase {
993+
/// Use Context::createCallInst(). Don't call the
994+
/// constructor directly.
995+
CallInst(llvm::Instruction *I, Context &Ctx)
996+
: CallBase(ClassID::Call, Opcode::Call, I, Ctx) {}
997+
friend class Context; // For accessing the constructor in
998+
// create*()
999+
Use getOperandUseInternal(unsigned OpIdx, bool Verify) const final {
1000+
return getOperandUseDefault(OpIdx, Verify);
1001+
}
1002+
SmallVector<llvm::Instruction *, 1> getLLVMInstrs() const final {
1003+
return {cast<llvm::Instruction>(Val)};
1004+
}
1005+
1006+
public:
1007+
static CallInst *create(FunctionType *FTy, Value *Func,
1008+
ArrayRef<Value *> Args, BBIterator WhereIt,
1009+
BasicBlock *WhereBB, Context &Ctx,
1010+
const Twine &NameStr = "");
1011+
static CallInst *create(FunctionType *FTy, Value *Func,
1012+
ArrayRef<Value *> Args, Instruction *InsertBefore,
1013+
Context &Ctx, const Twine &NameStr = "");
1014+
static CallInst *create(FunctionType *FTy, Value *Func,
1015+
ArrayRef<Value *> Args, BasicBlock *InsertAtEnd,
1016+
Context &Ctx, const Twine &NameStr = "");
1017+
1018+
static bool classof(const Value *From) {
1019+
return From->getSubclassID() == ClassID::Call;
1020+
}
1021+
unsigned getUseOperandNo(const Use &Use) const final {
1022+
return getUseOperandNoDefault(Use);
1023+
}
1024+
unsigned getNumOfIRInstrs() const final { return 1u; }
1025+
#ifndef NDEBUG
1026+
void verify() const final {}
1027+
void dump(raw_ostream &OS) const override;
1028+
LLVM_DUMP_METHOD void dump() const override;
1029+
#endif
1030+
};
1031+
8381032
/// An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
8391033
/// an OpaqueInstr.
8401034
class OpaqueInst : public sandboxir::Instruction {
@@ -983,6 +1177,8 @@ class Context {
9831177
friend StoreInst; // For createStoreInst()
9841178
ReturnInst *createReturnInst(llvm::ReturnInst *I);
9851179
friend ReturnInst; // For createReturnInst()
1180+
CallInst *createCallInst(llvm::CallInst *I);
1181+
friend CallInst; // For createCallInst()
9861182

9871183
public:
9881184
Context(LLVMContext &LLVMCtx)
@@ -1010,7 +1206,7 @@ class Context {
10101206
size_t getNumValues() const { return LLVMValueToValueMap.size(); }
10111207
};
10121208

1013-
class Function : public sandboxir::Value {
1209+
class Function : public Constant {
10141210
/// Helper for mapped_iterator.
10151211
struct LLVMBBToBB {
10161212
Context &Ctx;
@@ -1021,7 +1217,7 @@ class Function : public sandboxir::Value {
10211217
};
10221218
/// Use Context::createFunction() instead.
10231219
Function(llvm::Function *F, sandboxir::Context &Ctx)
1024-
: sandboxir::Value(ClassID::Function, F, Ctx) {}
1220+
: Constant(ClassID::Function, F, Ctx) {}
10251221
friend class Context; // For constructor.
10261222

10271223
public:
@@ -1047,6 +1243,9 @@ class Function : public sandboxir::Value {
10471243
LLVMBBToBB BBGetter(Ctx);
10481244
return iterator(cast<llvm::Function>(Val)->end(), BBGetter);
10491245
}
1246+
FunctionType *getFunctionType() const {
1247+
return cast<llvm::Function>(Val)->getFunctionType();
1248+
}
10501249

10511250
#ifndef NDEBUG
10521251
void verify() const final {

llvm/include/llvm/SandboxIR/SandboxIRValues.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ DEF_INSTR(Br, OP(Br), BranchInst)
3030
DEF_INSTR(Load, OP(Load), LoadInst)
3131
DEF_INSTR(Store, OP(Store), StoreInst)
3232
DEF_INSTR(Ret, OP(Ret), ReturnInst)
33+
DEF_INSTR(Call, OP(Call), CallInst)
34+
DEF_INSTR(Invoke, OP(Invoke), InvokeInst)
35+
DEF_INSTR(CallBr, OP(CallBr), CallBrInst)
3336

3437
#ifdef DEF_VALUE
3538
#undef DEF_VALUE

llvm/include/llvm/SandboxIR/Use.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace llvm::sandboxir {
2121
class Context;
2222
class Value;
2323
class User;
24+
class CallBase;
2425

2526
/// Represents a Def-use/Use-def edge in SandboxIR.
2627
/// NOTE: Unlike llvm::Use, this is not an integral part of the use-def chains.
@@ -40,6 +41,7 @@ class Use {
4041
friend class User; // For constructor
4142
friend class OperandUseIterator; // For constructor
4243
friend class UserUseIterator; // For accessing members
44+
friend class CallBase; // For LLVMUse
4345

4446
public:
4547
operator Value *() const { return get(); }

0 commit comments

Comments
 (0)