mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-07 20:43:40 +00:00
transform: fix incorrect alignment of heap-to-stack transform
It assumed the maximum alignment was equal to sizeof(void*), which is definitely not the case. So this only worked more or less by accident previously. It now uses the alignment as specified by the frontend, or else `unsafe.Alignof(complex128)` which is typically the maximum alignment of a given platform (though this shouldn't really happen in practice: the optimizer should keep the 'align' attribute in place).
This commit is contained in:
committed by
Ron Evans
parent
571447c7c1
commit
e6caa3fe9e
+14
-17
@@ -29,10 +29,14 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
|
||||
|
||||
targetData := llvm.NewTargetData(mod.DataLayout())
|
||||
defer targetData.Dispose()
|
||||
ptrType := llvm.PointerType(mod.Context().Int8Type(), 0)
|
||||
builder := mod.Context().NewBuilder()
|
||||
ctx := mod.Context()
|
||||
builder := ctx.NewBuilder()
|
||||
defer builder.Dispose()
|
||||
|
||||
// Determine the maximum alignment on this platform.
|
||||
complex128Type := ctx.StructType([]llvm.Type{ctx.DoubleType(), ctx.DoubleType()}, false)
|
||||
maxAlign := int64(targetData.ABITypeAlignment(complex128Type))
|
||||
|
||||
for _, heapalloc := range getUses(allocator) {
|
||||
logAllocs := printAllocs != nil && printAllocs.MatchString(heapalloc.InstructionParent().Parent().Name())
|
||||
if heapalloc.Operand(0).IsAConstantInt().IsNil() {
|
||||
@@ -90,21 +94,14 @@ func OptimizeAllocs(mod llvm.Module, printAllocs *regexp.Regexp, maxStackAlloc u
|
||||
}
|
||||
// The pointer value does not escape.
|
||||
|
||||
// Determine the appropriate alignment of the alloca. The size of the
|
||||
// allocation gives us a hint what the alignment should be.
|
||||
var alignment int
|
||||
if size%2 != 0 {
|
||||
alignment = 1
|
||||
} else if size%4 != 0 {
|
||||
alignment = 2
|
||||
} else if size%8 != 0 {
|
||||
alignment = 4
|
||||
} else {
|
||||
alignment = 8
|
||||
}
|
||||
if pointerAlignment := targetData.ABITypeAlignment(ptrType); pointerAlignment < alignment {
|
||||
// Use min(alignment, alignof(void*)) as the alignment.
|
||||
alignment = pointerAlignment
|
||||
// Determine the appropriate alignment of the alloca.
|
||||
attr := heapalloc.GetCallSiteEnumAttribute(0, llvm.AttributeKindID("align"))
|
||||
alignment := int(maxAlign)
|
||||
if !attr.IsNil() {
|
||||
// 'align' return value attribute is set, so use it.
|
||||
// This is basically always the case, but to be sure we'll default
|
||||
// to maxAlign if it isn't.
|
||||
alignment = int(attr.GetEnumValue())
|
||||
}
|
||||
|
||||
// Insert alloca in the entry block. Do it here so that mem2reg can
|
||||
|
||||
Reference in New Issue
Block a user