18
18
//
19
19
// namespace sandboxir {
20
20
//
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
28
34
// |
29
35
// +- CmpInst
30
36
// |
@@ -82,6 +88,8 @@ class ReturnInst;
82
88
class StoreInst ;
83
89
class User ;
84
90
class Value ;
91
+ class CallBase ;
92
+ class CallInst ;
85
93
86
94
// / Iterator for the `Use` edges of a User's operands.
87
95
// / \Returns the operand `Use` when dereferenced.
@@ -103,12 +111,20 @@ class OperandUseIterator {
103
111
OperandUseIterator () = default ;
104
112
value_type operator *() const ;
105
113
OperandUseIterator &operator ++();
114
+ OperandUseIterator operator ++(int ) {
115
+ auto Copy = *this ;
116
+ this ->operator ++();
117
+ return Copy;
118
+ }
106
119
bool operator ==(const OperandUseIterator &Other) const {
107
120
return Use == Other.Use ;
108
121
}
109
122
bool operator !=(const OperandUseIterator &Other) const {
110
123
return !(*this == Other);
111
124
}
125
+ OperandUseIterator operator +(unsigned Num) const ;
126
+ OperandUseIterator operator -(unsigned Num) const ;
127
+ int operator -(const OperandUseIterator &Other) const ;
112
128
};
113
129
114
130
// / Iterator for the `Use` edges of a Value's users.
@@ -135,6 +151,7 @@ class UserUseIterator {
135
151
bool operator !=(const UserUseIterator &Other) const {
136
152
return !(*this == Other);
137
153
}
154
+ const sandboxir::Use &getUse () const { return Use; }
138
155
};
139
156
140
157
// / A SandboxIR Value has users. This is the base class.
@@ -184,6 +201,8 @@ class Value {
184
201
friend class LoadInst ; // For getting `Val`.
185
202
friend class StoreInst ; // For getting `Val`.
186
203
friend class ReturnInst ; // For getting `Val`.
204
+ friend class CallBase ; // For getting `Val`.
205
+ friend class CallInst ; // For getting `Val`.
187
206
188
207
// / All values point to the context.
189
208
Context &Ctx;
@@ -417,7 +436,10 @@ class User : public Value {
417
436
class Constant : public sandboxir ::User {
418
437
Constant (llvm::Constant *C, sandboxir::Context &SBCtx)
419
438
: 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.
421
443
Use getOperandUseInternal (unsigned OpIdx, bool Verify) const final {
422
444
return getOperandUseDefault (OpIdx, Verify);
423
445
}
@@ -435,7 +457,7 @@ class Constant : public sandboxir::User {
435
457
return getUseOperandNoDefault (Use);
436
458
}
437
459
#ifndef NDEBUG
438
- void verify () const final {
460
+ void verify () const override {
439
461
assert (isa<llvm::Constant>(Val) && " Expected Constant!" );
440
462
}
441
463
friend raw_ostream &operator <<(raw_ostream &OS,
@@ -518,6 +540,7 @@ class Instruction : public sandboxir::User {
518
540
friend class LoadInst ; // For getTopmostLLVMInstruction().
519
541
friend class StoreInst ; // For getTopmostLLVMInstruction().
520
542
friend class ReturnInst ; // For getTopmostLLVMInstruction().
543
+ friend class CallInst ; // For getTopmostLLVMInstruction().
521
544
522
545
// / \Returns the LLVM IR Instructions that this SandboxIR maps to in program
523
546
// / order.
@@ -835,6 +858,177 @@ class ReturnInst final : public Instruction {
835
858
#endif
836
859
};
837
860
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
+
838
1032
// / An LLLVM Instruction that has no SandboxIR equivalent class gets mapped to
839
1033
// / an OpaqueInstr.
840
1034
class OpaqueInst : public sandboxir ::Instruction {
@@ -983,6 +1177,8 @@ class Context {
983
1177
friend StoreInst; // For createStoreInst()
984
1178
ReturnInst *createReturnInst (llvm::ReturnInst *I);
985
1179
friend ReturnInst; // For createReturnInst()
1180
+ CallInst *createCallInst (llvm::CallInst *I);
1181
+ friend CallInst; // For createCallInst()
986
1182
987
1183
public:
988
1184
Context (LLVMContext &LLVMCtx)
@@ -1010,7 +1206,7 @@ class Context {
1010
1206
size_t getNumValues () const { return LLVMValueToValueMap.size (); }
1011
1207
};
1012
1208
1013
- class Function : public sandboxir ::Value {
1209
+ class Function : public Constant {
1014
1210
// / Helper for mapped_iterator.
1015
1211
struct LLVMBBToBB {
1016
1212
Context &Ctx;
@@ -1021,7 +1217,7 @@ class Function : public sandboxir::Value {
1021
1217
};
1022
1218
// / Use Context::createFunction() instead.
1023
1219
Function (llvm::Function *F, sandboxir::Context &Ctx)
1024
- : sandboxir::Value (ClassID::Function, F, Ctx) {}
1220
+ : Constant (ClassID::Function, F, Ctx) {}
1025
1221
friend class Context ; // For constructor.
1026
1222
1027
1223
public:
@@ -1047,6 +1243,9 @@ class Function : public sandboxir::Value {
1047
1243
LLVMBBToBB BBGetter (Ctx);
1048
1244
return iterator (cast<llvm::Function>(Val)->end (), BBGetter);
1049
1245
}
1246
+ FunctionType *getFunctionType () const {
1247
+ return cast<llvm::Function>(Val)->getFunctionType ();
1248
+ }
1050
1249
1051
1250
#ifndef NDEBUG
1052
1251
void verify () const final {
0 commit comments