void RemoveStruct::structMemoryArrange(Type* val_ty, int actual_width, int &use_width, bool &flag) {
// val_ty是struct type,actual_width是需要取地址的长度,use_width是该struct需要的内存排布总长度,flag是取地址的长度是否取到无意义的地址空间标志位,无意义时改为false
int step_width = 1;
int val_width;
int struct_val_elements = val_ty->getStructNumElements();
for (int i = 0; i < struct_val_elements; i++) {
if (val_ty->getStructElementType(i)->isIntegerTy()) {
val_width = val_ty->getStructElementType(i)->getIntegerBitWidth();
while (use_width % val_width != 0) {
use_width += step_width;
}
use_width += val_width;
//outs() << " " << use_width;
} else if (val_ty->getStructElementType(i)->isArrayTy()) {
if (val_ty->getStructElementType(i)->getArrayElementType()->isIntegerTy()) {
for (int j = 0; j < val_ty->getStructElementType(i)->getArrayNumElements(); ++j) {
val_width = val_ty->getStructElementType(i)->getArrayElementType()->getIntegerBitWidth();
while (use_width % val_width != 0) {
use_width += step_width;
}
use_width += val_width;
//outs() << " " << use_width;
}
} else if (val_ty->getStructElementType(i)->getArrayElementType()->isArrayTy()) {
assert(0);//TODO
} else if (val_ty->getStructElementType(i)->getArrayElementType()->isStructTy()) {
assert(0);//TODO
}
} else if (val_ty->getStructElementType(i)->isStructTy()) {
int align = 0;
// BieCastStructAlign()为了得到当前Struct变量的align大小,当之前的use_width可以整除此struct的align,该struct内存排布连续排布,当整除不了时,则需要补齐大小,补齐大小为 align - (use_width % align)
BitCastStructAlign(val_ty->getStructElementType(i), align);
if (use_width % align == 0) {
structMemoryArrange(val_ty->getStructElementType(i), actual_width, use_width, flag);
} else {
if (actual_width >= use_width && actual_width < (use_width + align - (use_width % align))) {
flag = false;
}
use_width += align - (use_width % align);
structMemoryArrange(val_ty->getStructElementType(i), actual_width, use_width, flag);
}
} else {
outs() << "This Type is not considered! " << val_ty->getStructElementType(i) << "\n";
assert(0);
}
}
// 为了结尾时的字节对齐
int last = 0;
BitCastStructAlign(val_ty, last);
if (use_width % last != 0) {
if (actual_width >= use_width && actual_width < (use_width + last - (use_width % last))) {
flag = false;
}
use_width += last - (use_width % last);
}
//outs() << " " << use_width;
}
void RemoveStruct::BitCastStructAlign(Type* val_ty, int &align) {
int struct_val_elements = val_ty->getStructNumElements();
for (int i = 0; i < struct_val_elements; i++) {
if (val_ty->getStructElementType(i)->isIntegerTy()) {
if (val_ty->getStructElementType(i)->getIntegerBitWidth() > align) {
align = val_ty->getStructElementType(i)->getIntegerBitWidth(); }
} else if (val_ty->getStructElementType(i)->isArrayTy()) {
BitCastArrayAlign(val_ty->getStructElementType(i), align);
} else if (val_ty->getStructElementType(i)->isStructTy()) {
BitCastStructAlign(val_ty->getStructElementType(i), align);
} else {
outs() << "This Type is not considered! " << val_ty->getStructElementType(i) << "\n";
assert(0);
}
}
}
void RemoveStruct::BitCastArrayAlign(Type* val_ty, int &align) {
if (val_ty->getArrayElementType()->isIntegerTy()) {
if (val_ty->getArrayElementType()->getIntegerBitWidth() > align) {
align = val_ty->getArrayElementType()->getIntegerBitWidth();
}
} else if (val_ty->getArrayElementType()->isArrayTy()) {
// array
BitCastArrayAlign(val_ty->getArrayElementType(), align);
} else if (val_ty->getArrayElementType()->isStructTy()) {
BitCastStructAlign(val_ty->getArrayElementType(), align);
} else {
outs() << "This Type is not considered! " << val_ty->getArrayElementType() << "\n";
assert(0);
}
}