Add support for padding in struct type
MODIFY
ir/type.cpp
ir/type.cpp
@@ -614,6 +614,12 @@ AggregateType::AggregateType(string &&name, bool symbolic)
}
}
+AggregateType::AggregateType(string &&name, vector<Type*> &&vchildren,
+ vector<bool> &&vis_padding)
+: Type(move(name)), children(move(vchildren)), is_padding(move(vis_padding)) {
+ assert(children.size() == is_padding.size());
+}
+
expr AggregateType::numElements() const {
return defined ? expr::mkUInt(elements, var_vector_elements) :
var("elements", var_vector_elements);
@@ -817,6 +823,7 @@ VectorType::VectorType(string &&name, unsigned elements, Type &elementTy)
this->elements = elements;
defined = true;
children.resize(elements, &elementTy);
+ is_padding.resize(elements, false);
}
StateValue VectorType::extract(const StateValue &vector,
@@ -894,8 +901,9 @@ void VectorType::print(ostream &os) const {
}
-StructType::StructType(string &&name, vector<Type*> &&children)
- : AggregateType(move(name), move(children)) {
+StructType::StructType(string &&name, vector<Type*> &&children,
+ vector<bool> &&is_padding)
+ : AggregateType(move(name), move(children), move(is_padding)) {
elements = this->children.size();
defined = true;
}

MODIFY
ir/type.h
ir/type.h
@@ -235,13 +235,14 @@ public:
class AggregateType : public Type {
protected:
std::vector<Type*> children;
+ std::vector<bool> is_padding;
std::vector<std::unique_ptr<SymbolicType>> sym;
unsigned elements;
bool defined = false;
AggregateType(std::string &&name, bool symbolic = true);
- AggregateType(std::string &&name, std::vector<Type*> &&children)
- : Type(std::move(name)), children(std::move(children)) {}
+ AggregateType(std::string &&name, std::vector<Type*> &&children,
+ std::vector<bool> &&is_padding);
public:
smt::expr numElements() const;
@@ -250,6 +251,7 @@ public:
StateValue aggregateVals(const std::vector<StateValue> &vals) const;
IR::StateValue extract(const IR::StateValue &val, unsigned index) const;
Type& getChild(unsigned index) const { return *children[index]; }
+ bool isPadding(unsigned i) const { return is_padding[i]; }
unsigned bits() const override;
IR::StateValue getDummyValue(bool non_poison) const override;
@@ -307,7 +309,8 @@ public:
class StructType final : public AggregateType {
public:
StructType(std::string &&name) : AggregateType(std::move(name)) {}
- StructType(std::string &&name, std::vector<Type*> &&children);
+ StructType(std::string &&name, std::vector<Type*> &&children,
+ std::vector<bool> &&is_padding);
bool isStructType() const override;
smt::expr enforceStructType() const override;

MODIFY
llvm_util/utils.cpp
llvm_util/utils.cpp
@@ -104,14 +104,37 @@ Type* llvm_type2alive(const llvm::Type *ty) {
auto &cache = type_cache[ty];
if (!cache) {
vector<Type*> elems;
- for (auto e : cast<llvm::StructType>(ty)->elements()) {
- if (auto ty = llvm_type2alive(e))
+ vector<bool> is_padding;
+ auto strty = cast<llvm::StructType>(ty);
+ auto layout = DL->getStructLayout(const_cast<llvm::StructType *>(strty));
+ for (unsigned i = 0; i < strty->getNumElements(); ++i) {
+ auto e = strty->getElementType(i);
+ unsigned ofs = layout->getElementOffset(i);
+ unsigned sz = DL->getTypeStoreSize(e);
+
+ if (auto ty = llvm_type2alive(e)) {
elems.push_back(ty);
- else
+ is_padding.push_back(false);
+ } else
return nullptr;
+
+ unsigned ofs_next = i + 1 == strty->getNumElements() ?
+ DL->getTypeAllocSize(const_cast<llvm::StructType *>(strty)) :
+ layout->getElementOffset(i + 1);
+ assert(ofs + sz <= ofs_next);
+
+ if (ofs_next != ofs + sz) {
+ unsigned padsz = 8 * (ofs_next - ofs - sz);
+ auto padding_ty = llvm::IntegerType::get(strty->getContext(), padsz);
+ if (auto ty = llvm_type2alive(padding_ty)) {
+ elems.push_back(ty);
+ is_padding.push_back(true);
+ } else
+ return nullptr;
+ }
}
cache = make_unique<StructType>("ty_" + to_string(type_id_counter++),
- move(elems));
+ move(elems), move(is_padding));
}
return cache.get();
}
@@ -231,11 +254,25 @@ Value* get_operand(llvm::Value *v,
if (auto cnst = dyn_cast<llvm::ConstantAggregate>(v)) {
vector<Value*> vals;
- for (auto I = cnst->op_begin(), E = cnst->op_end(); I != E; ++I) {
- if (auto op = get_operand(*I, constexpr_conv))
+ auto aty = dynamic_cast<AggregateType *>(ty);
+ unsigned opi = 0;
+
+ for (unsigned i = 0; i < aty->numElementsConst(); ++i) {
+ if (aty->isPadding(i)) {
+ auto &padty = aty->getChild(i);
+ assert(padty.isIntType());
+ auto poison = make_unique<PoisonValue>(padty);
+ auto ret = poison.get();
+
+ current_fn->addConstant(move(poison));
+ vals.emplace_back(ret);
+ } else {
+ if (auto op = get_operand(cnst->getOperand(opi), constexpr_conv))
vals.emplace_back(op);
else
return nullptr;
+ ++opi;
+ }
}
auto val = make_unique<AggregateValue>(*ty, move(vals));
auto ret = val.get();

MODIFY
tests/alive-tv/memory/aggregate-bigendian.src.ll
tests/alive-tv/memory/aggregate-bigendian.src.ll
@@ -15,4 +15,18 @@ define i8 @test2({{i32,i8},i32}* %x) {
ret i8 %r
}
+define i32 @test3({{i32,i8},i32}* %x) {
+ store {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }, {{i32,i8},i32}* %x
+ %y = getelementptr {{i32,i8},i32}, {{i32,i8},i32}* %x, i32 0, i32 1
+ %r = load i32, i32* %y
+ ret i32 %r
+}
+define i16 @test4({{i32,i8},i32}* %x) {
+ store {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }, {{i32,i8},i32}* %x
+ %y = getelementptr {{i32,i8},i32}, {{i32,i8},i32}* %x, i32 0, i32 0, i32 0
+ %z = bitcast i32* %y to i16*
+ %w = getelementptr i16, i16* %z, i32 2
+ %r = load i16, i16* %w
+ ret i16 %r
+}

MODIFY
tests/alive-tv/memory/aggregate-bigendian.tgt.ll
tests/alive-tv/memory/aggregate-bigendian.tgt.ll
@@ -13,5 +13,16 @@ define i8 @test2({{i32,i8},i32}* %x) {
ret i8 186
}
+define i32 @test3({{i32,i8},i32}* %x) {
+ store {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }, {{i32,i8},i32}* %x
+ ; 0xCAFEBABE
+ ret i32 -889275714
+}
+
+define i16 @test4({{i32,i8},i32}* %x) {
+ store {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }, {{i32,i8},i32}* %x
+ ; 0xBA00
+ ret i16 47616
+}

MODIFY
tests/alive-tv/memory/aggregate.src.ll
tests/alive-tv/memory/aggregate.src.ll
@@ -15,3 +15,18 @@ define i8 @test2({{i32,i8},i32}* %x) {
ret i8 %r
}
+define i32 @test3({{i32,i8},i32}* %x) {
+ store {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }, {{i32,i8},i32}* %x
+ %y = getelementptr {{i32,i8},i32}, {{i32,i8},i32}* %x, i32 0, i32 1
+ %r = load i32, i32* %y
+ ret i32 %r
+}
+
+define i16 @test4({{i32,i8},i32}* %x) {
+ store {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }, {{i32,i8},i32}* %x
+ %y = getelementptr {{i32,i8},i32}, {{i32,i8},i32}* %x, i32 0, i32 0, i32 0
+ %z = bitcast i32* %y to i16*
+ %w = getelementptr i16, i16* %z, i32 2
+ %r = load i16, i16* %w
+ ret i16 %r
+}

MODIFY
tests/alive-tv/memory/aggregate.tgt.ll
tests/alive-tv/memory/aggregate.tgt.ll
@@ -13,3 +13,13 @@ define i8 @test2({{i32,i8},i32}* %x) {
ret i8 186
}
+define i32 @test3({{i32,i8},i32}* %x) {
+ store {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }, {{i32,i8},i32}* %x
+ ; 0xCAFEBABE
+ ret i32 -889275714
+}
+define i16 @test4({{i32,i8},i32}* %x) {
+ store {{i32,i8},i32} {{i32,i8} { i32 -559038737, i8 186 }, i32 -889275714 }, {{i32,i8},i32}* %x
+ ; 0x00BA
+ ret i16 186
+}

MODIFY
tools/alive_parser.cpp
tools/alive_parser.cpp
@@ -282,8 +282,10 @@ static Type& get_overflow_type(Type &type) {
auto p = overflow_aggregate_types.try_emplace(&type);
auto &st = p.first->second;
if (p.second)
+ // TODO: Knowing exact layout of { i1, ity } needs data layout.
st = make_unique<StructType>("structty_" + to_string(struct_num++),
- initializer_list<Type*>({ &type, int_types[1].get() }));
+ initializer_list<Type*>({ &type, int_types[1].get() }),
+ initializer_list<bool>({ false, false }));
return *st.get();
}

MODIFY
tools/transform.cpp
tools/transform.cpp
@@ -404,6 +404,10 @@ static void calculateAndInitConstants(Transform &t) {
} else
return NO_ACCESS;
+ if (dynamic_cast<const AggregateType *>(value_ty))
+ // TODO: AggregateType's elements are splitted and stored, so
+ // should they be checked instead
+ return UNKNOWN;
if (dynamic_cast<const PtrType *>(value_ty))
return gcd(align, bits_size_t / 8);
return gcd(align, util::divide_up(value_ty->bits(), 8));

Add support for padding in struct type (#202)