Add support for padding in arrays
MODIFY
ir/type.cpp
ir/type.cpp
@@ -835,13 +835,24 @@ const AggregateType* AggregateType::getAsAggregateType() const {
}
-ArrayType::ArrayType(string &&name, unsigned elements, Type &elementTy)
+ArrayType::ArrayType(string &&name, unsigned elements, Type &elementTy,
+ Type *paddingTy)
: AggregateType(move(name), false) {
- this->elements = elements;
defined = true;
+ if (paddingTy) {
+ this->elements = elements * 2;
+ children.resize(elements * 2, &elementTy);
+ is_padding.resize(elements * 2, false);
+ for (unsigned i = 1; i < elements * 2; i += 2) {
+ children[i] = paddingTy;
+ is_padding[i] = true;
+ }
+ } else {
+ this->elements = elements;
children.resize(elements, &elementTy);
is_padding.resize(elements, false);
}
+}
bool ArrayType::isArrayType() const {
return true;
@@ -850,8 +861,15 @@ bool ArrayType::isArrayType() const {
void ArrayType::print(ostream &os) const {
if (children.empty())
os << "(empty array)";
- else
- os << '[' << elements << " x " << *children[0] << ']';
+ else {
+ bool has_padding = elements > 1 && isPadding(1);
+ assert(!has_padding || elements % 2 == 0);
+ os << '[' << (has_padding ? elements / 2 : elements) << " x "
+ << *children[0];
+ if (has_padding)
+ os << ", padding: " << *children[1];
+ os << ']';
+ }
}

MODIFY
ir/type.h
ir/type.h
@@ -290,7 +290,8 @@ public:
class ArrayType final : public AggregateType {
public:
ArrayType(std::string &&name) : AggregateType(std::move(name)) {}
- ArrayType(std::string &&name, unsigned elements, Type &elementTy);
+ ArrayType(std::string &&name, unsigned elements, Type &elementTy,
+ Type *paddingTy = nullptr);
bool isArrayType() const override;
void print(std::ostream &os) const override;

MODIFY
llvm_util/utils.cpp
llvm_util/utils.cpp
@@ -154,12 +154,21 @@ Type* llvm_type2alive(const llvm::Type *ty) {
auto &cache = type_cache[ty];
if (!cache) {
auto aty = cast<llvm::ArrayType>(ty);
+ auto elemty = aty->getElementType();
auto elems = aty->getNumElements();
- auto ety = llvm_type2alive(aty->getElementType());
+ auto ety = llvm_type2alive(elemty);
if (!ety || elems > 128)
return nullptr;
+
+ auto sz_with_padding = DL->getTypeAllocSize(elemty);
+ auto sz = DL->getTypeStoreSize(elemty);
+ assert(DL->getTypeAllocSize(const_cast<llvm::ArrayType *>(aty)) ==
+ elems * sz_with_padding);
+ Type *paddingTy = sz == sz_with_padding ? 0 :
+ llvm_type2alive(llvm::IntegerType::get(aty->getContext(),
+ 8 * (sz_with_padding - sz)));
cache = make_unique<ArrayType>("ty_" + to_string(type_id_counter++),
- elems, *ety);
+ elems, *ety, paddingTy);
}
return cache.get();
}
@@ -273,9 +282,9 @@ Value* get_operand(llvm::Value *v,
return gvar;
}
- if (auto cnst = dyn_cast<llvm::ConstantAggregate>(v)) {
- vector<Value*> vals;
- auto aty = dynamic_cast<AggregateType *>(ty);
+ auto fillAggregateValues = [&constexpr_conv](AggregateType *aty,
+ function<llvm::Value *(unsigned)> get_elem, vector<Value*> &vals) -> bool
+ {
unsigned opi = 0;
for (unsigned i = 0; i < aty->numElementsConst(); ++i) {
@@ -288,13 +297,22 @@ Value* get_operand(llvm::Value *v,
current_fn->addConstant(move(poison));
vals.emplace_back(ret);
} else {
- if (auto op = get_operand(cnst->getOperand(opi), constexpr_conv))
+ if (auto op = get_operand(get_elem(opi), constexpr_conv))
vals.emplace_back(op);
else
- return nullptr;
+ return false;
++opi;
}
}
+ return true;
+ };
+
+ if (auto cnst = dyn_cast<llvm::ConstantAggregate>(v)) {
+ vector<Value*> vals;
+ if (!fillAggregateValues(dynamic_cast<AggregateType *>(ty),
+ [&cnst](auto i) { return cnst->getOperand(i); }, vals))
+ return nullptr;
+
auto val = make_unique<AggregateValue>(*ty, move(vals));
auto ret = val.get();
current_fn->addConstant(move(val));
@@ -303,12 +321,10 @@ Value* get_operand(llvm::Value *v,
if (auto cnst = dyn_cast<llvm::ConstantDataSequential>(v)) {
vector<Value*> vals;
- for (unsigned i = 0, e = cnst->getNumElements(); i != e; ++i) {
- if (auto op = get_operand(cnst->getElementAsConstant(i), constexpr_conv))
- vals.emplace_back(op);
- else
+ if (!fillAggregateValues(dynamic_cast<AggregateType *>(ty),
+ [&cnst](auto i) { return cnst->getElementAsConstant(i); }, vals))
return nullptr;
- }
+
auto val = make_unique<AggregateValue>(*ty, move(vals));
auto ret = val.get();
current_fn->addConstant(move(val));
@@ -317,12 +333,10 @@ Value* get_operand(llvm::Value *v,
if (auto cnst = dyn_cast<llvm::ConstantAggregateZero>(v)) {
vector<Value*> vals;
- for (unsigned i = 0, e = cnst->getNumElements(); i != e; ++i) {
- if (auto op = get_operand(cnst->getElementValue(i), constexpr_conv))
- vals.emplace_back(op);
- else
+ if (!fillAggregateValues(dynamic_cast<AggregateType *>(ty),
+ [&cnst](auto i) { return cnst->getElementValue(i); }, vals))
return nullptr;
- }
+
auto val = make_unique<AggregateValue>(*ty, move(vals));
auto ret = val.get();
current_fn->addConstant(move(val));

ADD
tests/alive-tv/constexpr/zeroinitializer.src.ll
+target datalayout = "i24:32:32" ; 4-bytes aligned
+; LangRef says zeroinitializer is exactly equivalent to explicit zero initialization
+
+define void @f([4 x i24]* %ptr) {
+ store [4 x i24] zeroinitializer, [4 x i24]* %ptr
+ ret void
+}

ADD
tests/alive-tv/constexpr/zeroinitializer.tgt.ll
+target datalayout = "i24:32:32" ; 4-bytes aligned
+; LangRef says zeroinitializer is exactly equivalent to explicit zero initialization
+
+define void @f([4 x i24]* %ptr) {
+ store [4 x i24] [i24 0, i24 0, i24 0, i24 0], [4 x i24]* %ptr
+ ret void
+}

ADD
tests/alive-tv/memory/array-gep.src.ll
+target datalayout = "i24:32:32" ; 4-bytes aligned
+
+define i24* @f([4 x i24]* %p) {
+ %q = getelementptr [4 x i24], [4 x i24]* %p, i32 0, i32 1
+ ret i24* %q
+}

ADD
tests/alive-tv/memory/array-gep.tgt.ll
+target datalayout = "i24:32:32" ; 4-bytes aligned
+
+define i24* @f([4 x i24]* %p) {
+ %p2 = bitcast [4 x i24]* %p to i8*
+ %q0 = getelementptr i8, i8* %p2, i32 4
+ %q = bitcast i8* %q0 to i24*
+ ret i24* %q
+}

Add support for padding in arrays (#213)