Skip to content

Commit 034f2b3

Browse files
authored
[SandboxIR] Implement SandboxIR Type (#106294)
This patch implements sandboxir::Type, a thin wrapper of llvm::Type. This is designed very similarly to sandbox::Value. Context owns all sandboxir::Type objects and maintains a map between llvm::Type and sandboxir::Type. There are a couple of reasons for migrating from llvm::Type to sandboxir::Type: - Creating an llvm::Type from within SandboxIR-only code doesn't work well because it requires you to pass llvm::Context to functions like llvm::Type::getInt32Ty(C), but you wouldn't normally have access to llvm::Context C. In unit tests this is not such a big deal because you have access to both, but it will become an issue in SandboxIR-only code. - Not being able to get the sandboxir::Context from llvm::Type results in awkward sandboir APIs with additional sandboxir::Context arguments. - llvm::Type::getContext() can basically give you access to the whole LLVM IR, which we should try to avoid.
1 parent dbbfc95 commit 034f2b3

File tree

9 files changed

+795
-108
lines changed

9 files changed

+795
-108
lines changed

llvm/include/llvm/SandboxIR/SandboxIR.h

Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@
102102
#include "llvm/IR/User.h"
103103
#include "llvm/IR/Value.h"
104104
#include "llvm/SandboxIR/Tracker.h"
105+
#include "llvm/SandboxIR/Type.h"
105106
#include "llvm/SandboxIR/Use.h"
106107
#include "llvm/Support/raw_ostream.h"
107108
#include <iterator>
@@ -386,7 +387,7 @@ class Value {
386387
return Cnt == Num;
387388
}
388389

389-
Type *getType() const { return Val->getType(); }
390+
Type *getType() const;
390391

391392
Context &getContext() const { return Ctx; }
392393

@@ -574,8 +575,7 @@ class ConstantInt : public Constant {
574575
public:
575576
/// If Ty is a vector type, return a Constant with a splat of the given
576577
/// value. Otherwise return a ConstantInt for the given value.
577-
static ConstantInt *get(Type *Ty, uint64_t V, Context &Ctx,
578-
bool IsSigned = false);
578+
static ConstantInt *get(Type *Ty, uint64_t V, bool IsSigned = false);
579579

580580
// TODO: Implement missing functions.
581581

@@ -1024,10 +1024,7 @@ class ExtractElementInst final
10241024
Value *getIndexOperand() { return getOperand(1); }
10251025
const Value *getVectorOperand() const { return getOperand(0); }
10261026
const Value *getIndexOperand() const { return getOperand(1); }
1027-
1028-
VectorType *getVectorOperandType() const {
1029-
return cast<VectorType>(getVectorOperand()->getType());
1030-
}
1027+
VectorType *getVectorOperandType() const;
10311028
};
10321029

10331030
class ShuffleVectorInst final
@@ -1072,9 +1069,7 @@ class ShuffleVectorInst final
10721069
}
10731070

10741071
/// Overload to return most specific vector type.
1075-
VectorType *getType() const {
1076-
return cast<llvm::ShuffleVectorInst>(Val)->getType();
1077-
}
1072+
VectorType *getType() const;
10781073

10791074
/// Return the shuffle mask value of this instruction for the given element
10801075
/// index. Return PoisonMaskElem if the element is undef.
@@ -1100,7 +1095,7 @@ class ShuffleVectorInst final
11001095
Constant *getShuffleMaskForBitcode() const;
11011096

11021097
static Constant *convertShuffleMaskForBitcode(ArrayRef<int> Mask,
1103-
Type *ResultTy, Context &Ctx);
1098+
Type *ResultTy);
11041099

11051100
void setShuffleMask(ArrayRef<int> Mask);
11061101

@@ -1646,9 +1641,7 @@ class ExtractValueInst : public UnaryInstruction {
16461641
/// with an extractvalue instruction with the specified parameters.
16471642
///
16481643
/// Null is returned if the indices are invalid for the specified type.
1649-
static Type *getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs) {
1650-
return llvm::ExtractValueInst::getIndexedType(Agg, Idxs);
1651-
}
1644+
static Type *getIndexedType(Type *Agg, ArrayRef<unsigned> Idxs);
16521645

16531646
using idx_iterator = llvm::ExtractValueInst::idx_iterator;
16541647

@@ -1843,9 +1836,7 @@ class CallBase : public SingleLLVMInstructionImpl<llvm::CallBase> {
18431836
Opc == Instruction::ClassID::CallBr;
18441837
}
18451838

1846-
FunctionType *getFunctionType() const {
1847-
return cast<llvm::CallBase>(Val)->getFunctionType();
1848-
}
1839+
FunctionType *getFunctionType() const;
18491840

18501841
op_iterator data_operands_begin() { return op_begin(); }
18511842
const_op_iterator data_operands_begin() const {
@@ -2261,12 +2252,8 @@ class GetElementPtrInst final
22612252
return From->getSubclassID() == ClassID::GetElementPtr;
22622253
}
22632254

2264-
Type *getSourceElementType() const {
2265-
return cast<llvm::GetElementPtrInst>(Val)->getSourceElementType();
2266-
}
2267-
Type *getResultElementType() const {
2268-
return cast<llvm::GetElementPtrInst>(Val)->getResultElementType();
2269-
}
2255+
Type *getSourceElementType() const;
2256+
Type *getResultElementType() const;
22702257
unsigned getAddressSpace() const {
22712258
return cast<llvm::GetElementPtrInst>(Val)->getAddressSpace();
22722259
}
@@ -2290,9 +2277,7 @@ class GetElementPtrInst final
22902277
static unsigned getPointerOperandIndex() {
22912278
return llvm::GetElementPtrInst::getPointerOperandIndex();
22922279
}
2293-
Type *getPointerOperandType() const {
2294-
return cast<llvm::GetElementPtrInst>(Val)->getPointerOperandType();
2295-
}
2280+
Type *getPointerOperandType() const;
22962281
unsigned getPointerAddressSpace() const {
22972282
return cast<llvm::GetElementPtrInst>(Val)->getPointerAddressSpace();
22982283
}
@@ -2843,9 +2828,7 @@ class AllocaInst final : public UnaryInstruction {
28432828
return const_cast<AllocaInst *>(this)->getArraySize();
28442829
}
28452830
/// Overload to return most specific pointer type.
2846-
PointerType *getType() const {
2847-
return cast<llvm::AllocaInst>(Val)->getType();
2848-
}
2831+
PointerType *getType() const;
28492832
/// Return the address space for the allocation.
28502833
unsigned getAddressSpace() const {
28512834
return cast<llvm::AllocaInst>(Val)->getAddressSpace();
@@ -2861,9 +2844,7 @@ class AllocaInst final : public UnaryInstruction {
28612844
return cast<llvm::AllocaInst>(Val)->getAllocationSizeInBits(DL);
28622845
}
28632846
/// Return the type that is being allocated by the instruction.
2864-
Type *getAllocatedType() const {
2865-
return cast<llvm::AllocaInst>(Val)->getAllocatedType();
2866-
}
2847+
Type *getAllocatedType() const;
28672848
/// for use only in special circumstances that need to generically
28682849
/// transform a whole instruction (eg: IR linking and vectorization).
28692850
void setAllocatedType(Type *Ty);
@@ -2945,8 +2926,8 @@ class CastInst : public UnaryInstruction {
29452926
const Twine &Name = "");
29462927
/// For isa/dyn_cast.
29472928
static bool classof(const Value *From);
2948-
Type *getSrcTy() const { return cast<llvm::CastInst>(Val)->getSrcTy(); }
2949-
Type *getDestTy() const { return cast<llvm::CastInst>(Val)->getDestTy(); }
2929+
Type *getSrcTy() const;
2930+
Type *getDestTy() const;
29502931
};
29512932

29522933
/// Instruction that can have a nneg flag (zext/uitofp).
@@ -3126,13 +3107,25 @@ class OpaqueInst : public SingleLLVMInstructionImpl<llvm::Instruction> {
31263107
class Context {
31273108
protected:
31283109
LLVMContext &LLVMCtx;
3110+
friend class Type; // For LLVMCtx.
3111+
friend class PointerType; // For LLVMCtx.
31293112
Tracker IRTracker;
31303113

31313114
/// Maps LLVM Value to the corresponding sandboxir::Value. Owns all
31323115
/// SandboxIR objects.
31333116
DenseMap<llvm::Value *, std::unique_ptr<sandboxir::Value>>
31343117
LLVMValueToValueMap;
31353118

3119+
/// Type has a protected destructor to prohibit the user from managing the
3120+
/// lifetime of the Type objects. Context is friend of Type, and this custom
3121+
/// deleter can destroy Type.
3122+
struct TypeDeleter {
3123+
void operator()(Type *Ty) { delete Ty; }
3124+
};
3125+
/// Maps LLVM Type to the corresonding sandboxir::Type. Owns all Sandbox IR
3126+
/// Type objects.
3127+
DenseMap<llvm::Type *, std::unique_ptr<Type, TypeDeleter>> LLVMTypeToTypeMap;
3128+
31363129
/// Remove \p V from the maps and returns the unique_ptr.
31373130
std::unique_ptr<Value> detachLLVMValue(llvm::Value *V);
31383131
/// Remove \p SBV from all SandboxIR maps and stop owning it. This effectively
@@ -3167,7 +3160,6 @@ class Context {
31673160
/// Create a sandboxir::BasicBlock for an existing LLVM IR \p BB. This will
31683161
/// also create all contents of the block.
31693162
BasicBlock *createBasicBlock(llvm::BasicBlock *BB);
3170-
31713163
friend class BasicBlock; // For getOrCreateValue().
31723164

31733165
IRBuilder<ConstantFolder> LLVMIRBuilder;
@@ -3257,6 +3249,17 @@ class Context {
32573249
const sandboxir::Value *getValue(const llvm::Value *V) const {
32583250
return getValue(const_cast<llvm::Value *>(V));
32593251
}
3252+
3253+
Type *getType(llvm::Type *LLVMTy) {
3254+
if (LLVMTy == nullptr)
3255+
return nullptr;
3256+
auto Pair = LLVMTypeToTypeMap.insert({LLVMTy, nullptr});
3257+
auto It = Pair.first;
3258+
if (Pair.second)
3259+
It->second = std::unique_ptr<Type, TypeDeleter>(new Type(LLVMTy, *this));
3260+
return It->second.get();
3261+
}
3262+
32603263
/// Create a sandboxir::Function for an existing LLVM IR \p F, including all
32613264
/// blocks and instructions.
32623265
/// This is the main API function for creating Sandbox IR.
@@ -3303,9 +3306,7 @@ class Function : public Constant {
33033306
LLVMBBToBB BBGetter(Ctx);
33043307
return iterator(cast<llvm::Function>(Val)->end(), BBGetter);
33053308
}
3306-
FunctionType *getFunctionType() const {
3307-
return cast<llvm::Function>(Val)->getFunctionType();
3308-
}
3309+
FunctionType *getFunctionType() const;
33093310

33103311
#ifndef NDEBUG
33113312
void verify() const final {

0 commit comments

Comments
 (0)