Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions llvm/include/llvm/IR/DataLayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -501,10 +501,7 @@ class DataLayout {
///
/// This is the amount that alloca reserves for this type. For example,
/// returns 12 or 16 for x86_fp80, depending on alignment.
TypeSize getTypeAllocSize(Type *Ty) const {
// Round up to the next alignment boundary.
return alignTo(getTypeStoreSize(Ty), getABITypeAlign(Ty).value());
}
TypeSize getTypeAllocSize(Type *Ty) const;

/// Returns the offset in bits between successive objects of the
/// specified type, including alignment padding; always a multiple of 8.
Expand Down
38 changes: 38 additions & 0 deletions llvm/lib/IR/DataLayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,6 +844,44 @@ Align DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
}
}

TypeSize DataLayout::getTypeAllocSize(Type *Ty) const {
switch (Ty->getTypeID()) {
case Type::ArrayTyID: {
// The alignment of the array is the alignment of the element, so there
// is no need for further adjustment.
auto *ATy = cast<ArrayType>(Ty);
return ATy->getNumElements() * getTypeAllocSize(ATy->getElementType());
}
case Type::StructTyID: {
const StructLayout *Layout = getStructLayout(cast<StructType>(Ty));
TypeSize Size = Layout->getSizeInBytes();

if (cast<StructType>(Ty)->isPacked())
return Size;

Align A = std::max(StructABIAlignment, Layout->getAlignment());
return alignTo(Size, A.value());
}
case Type::IntegerTyID: {
unsigned BitWidth = Ty->getIntegerBitWidth();
TypeSize Size = TypeSize::getFixed(divideCeil(BitWidth, 8));
Align A = getIntegerAlignment(BitWidth, /*ABI=*/true);
return alignTo(Size, A.value());
}
case Type::PointerTyID: {
unsigned AS = Ty->getPointerAddressSpace();
TypeSize Size = TypeSize::getFixed(getPointerSize(AS));
return alignTo(Size, getPointerABIAlignment(AS).value());
}
case Type::TargetExtTyID: {
Type *LayoutTy = cast<TargetExtType>(Ty)->getLayoutType();
return getTypeAllocSize(LayoutTy);
}
default:
return alignTo(getTypeStoreSize(Ty), getABITypeAlign(Ty).value());
}
}

Align DataLayout::getABITypeAlign(Type *Ty) const {
return getAlignment(Ty, true);
}
Expand Down
3 changes: 0 additions & 3 deletions llvm/test/CodeGen/AArch64/alloca-oversized.ll
Copy link
Contributor Author

@nikic nikic Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we can see that this is not entirely NFC. The reason is that this implementation does not always go through the size in bits, which may end up discarding high bits of the type. As such, the new implementation is technically "more correct". But really type sizes the overflow when converting bits <-> bytes are not really something we can sensibly support -- we should probably try to make the IR verifier reject these.

Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ define void @test_oversized(ptr %dst, i32 %cond) {
; CHECK-NEXT: .cfi_offset w30, -8
; CHECK-NEXT: .cfi_offset w29, -16
; CHECK-NEXT: mov x8, sp
; CHECK-NEXT: mov x9, #2305843009213693952 // =0x2000000000000000
; CHECK-NEXT: sub x8, x8, x9
; CHECK-NEXT: sub x9, x29, #32
; CHECK-NEXT: mov sp, x8
; CHECK-NEXT: cmp w1, #0
; CHECK-NEXT: csel x8, x9, x8, eq
; CHECK-NEXT: str x8, [x0]
Expand Down