get一条GetElementPtrInst,将instr->getOperand(0)分struct和ArrayStruct处理。
void RemoveStruct::GetElementPtrInstProcess(Instruction *instr) {
assert(isa<GetElementPtrInst>(instr));
//确保处理的是structvalue
if (!hasStructType(instr->getOperand(0)->getType())) {
outs()<<"GetElementPtrInst Process(): instr->getOperand(0) is not structType!"<<"\n";
assert(0);
}
//先判断getelementptrInst的返回值是否为i8*,如果是的话,看getelementptrInst的user是不是memcpy,是的话,则不能分解该getelementptrInst,因为它只是取首地址的作用。
//If the GetElementPtrInst used to have the address for memcpy
//we cannot resloved it
Type *ptr = instr->getType()->getPointerElementType();
if (ptr->isIntegerTy() && ptr->getIntegerBitWidth()==8) {
GetElementPtrInstWithMemcpy(instr);
}
// GetElementPtrInst *getelementptr = dyn_cast<GetElementPtrInst>(instr);
// Type *src = getelementptr->getSourceElementType();
// Type *dest = getelementptr->getResultElementType();
// instr->getOperand(0) is the basis type value
Value *inst_op_0 = instr->getOperand(0);
//resloved the structure value
if (IsStructVal(inst_op_0->getType())) {
GetelementptrStructProcess(instr);
} else {
assert(IsArrayStructVal(inst_op_0->getType()));
vector<int> val_num;
val_num.clear();
bool flag = ArrayVarNums(inst_op_0->getType(), val_num);
GetelementptrArrayProcess(instr, val_num.size());
}
}
小结,仍需推敲
getelementptr的解决方案:
The first argument is always a type used as the basis for the calculations. The second argument is always a pointer or a vector of pointers, and is the base address to start from. The remaining arguments are indices。
第一个元素op_0是basis type value,说明计算地址的基础类型,第一个元素必须保留,该元素说明了该地址的几倍开始。
第二个元素op_1是the base address to start from,如果是array就是array[op_1]开始,那么这个index就必须保留,如果是struct,就是struct[op_1]开始,那么此时op_1是分解的位置。
完善getelementptr的处理函数:GetElementPtrInstProcess(Instruction *inst)
(1)inst的src和dest的structType类型一致时,仅保留getelementptr的list,不处理
(1.1)当inst的user为getelementptr inst2
(1.1.1)if(inst2的dest的structType != inst的srcstructType)加入(1)的list,分解inst的src的sub struct value,inst2的op_1assert为constant 0舍弃
(1.1.2)else assert(0),list just have a vector pointer,
(1.2)当接下来是callInst时,需要将array的信息传递下去
(2)当两者类型不一致时,则直接将其分解。
提取inst的op_0
(1)op_0为struct时,保留op_1,此时只保留op_1,万一op_2为pointer,
(2)op_0为Array struct时,分情况处理
情况一:getelementptrInst中第二个operand不是constantInt 0,则必须保留。
%46 = getelementptr inbounds %struct.CandidatePixel, %struct.CandidatePixel* %0, i64 %44, i32 0
情况二:instr->getNumOperands() <= array_layers + 2
后面是bitcast
%120 = getelementptr inbounds [2 x [2 x %struct.point]], [2 x [2 x %struct.point]]* @global_8, i64 0, i64 1
%121 = bitcast [2 x %struct.point]* %120 to i16*
%52 = getelementptr inbounds [2 x %struct.point], [2 x %struct.point]* %global_0, i64 0, i64 1
%53 = bitcast %struct.point* %52 to i16*
后面是callInst
%3 = getelementptr inbounds [2 x %struct.str], [2 x %struct.str]* %1, i64 0, i64 0
%4 = call fastcc i32 @sum(%struct.str* nonnull %3) #4
后面是getelementptrInst
%47 = getelementptr inbounds %struct.str, %struct.str* %0, i64 0, i32 8
%48 = getelementptr inbounds [2 x %struct.point], [2 x %struct.point]* %47, i64 0, i64 0, i32 0
情况二:instr->getNumOperands() > array_layers + 2 ,直接分解处理。
%6 = getelementptr inbounds [2 x [2 x %struct.str]], [2 x [2 x %struct.str]]* @global, i64 0, i64 0, i64 0, i32 0
%124 = getelementptr inbounds [2 x %struct.str], [2 x %struct.str]* @global, i64 0, i64 1, i32 1, i64 1, i32 0
情况三:getelementptrInst的operand_0从argument而来
define i32 @zculling.1(i32, %struct.CandidatePixel*, i32, %struct.Pixel*, i8*, i8*, i8*) #0
%56 = getelementptr inbounds %struct.Pixel, %struct.Pixel* %3, i64 %55
%57 = getelementptr inbounds %struct.Pixel, %struct.Pixel* %56, i32 0, i32 0
情况四:当getelementptrInst的返回address为i8*时,遍历instr的user是否存在memcpy,此时需要特殊处理。
当memcpy的len为一个i8时,正常处理;
当不是一个i8时,说明给了一个首地址,所以传递下去的getelementptr list只有op_0。