Description
I've tracked down a bug to bad alignment here: #63 (comment) After a lot of pain, I've found out that there is actually a hardcoded datalayout in the AVR backend, in AVRTargetMachine.cpp
, taking precedence over whatever the user puts in the LLVM IR file. This datalayout is currently as follows:
static const char *AVRDataLayout = "e-p:16:16:16-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-n8";
Expanded, the above states:
- 2-byte words are 2-byte-aligned, 4-byte words are 4-byte-aligned, 8-byte words are 8-byte-aligned
- floats are 4-byte-aligned, doubles are 8-byte-aligned
- Pointers take up 2 bytes and are 2-byte-aligned
- Aggregates are 8-byte-aligned
To my untrained eye, this looks completely bogus (except, yeah, pointers are 2 bytes:)), so I did a quick git blame
in the hope that I'd find a good reason. There is a commit which gives an explanation for the 2-byte alignment:
commit 553362942dbc6baa23225d7e39020631a9c15b91
Author: Dylan McKay <...>
Date: Wed Sep 28 13:29:10 2016 +0000
[AVR] Update the data layout
The previous data layout caused issues when dealing with atomics.
Foe example, it is illegal to load a 16-bit value with less than 16-bits
of alignment.
This changes the data layout so that all types are aligned by at least
their own width.
Interestingly, this also _slightly_ decreased register pressure in some
cases.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@282587 91177308-0d34-0410-b5e6-96231b3b80d8
but it still doesn't explain what's going on with the 4- and even 8-byte alignments (which were also introduced in the same commit). The original code is already missing an a
specifier, so that's probably just an oversight/typo.
If we need 2-byte alignment for >=2 byte words as the above commit states, what's the reason for going above that for wider types, that are going to be soft-implemented anyway?
Would this work instead? It would certainly fix #63
static const char *AVRDataLayout = "e-p:16:16-i8:8-i16:16-i32:16-i64:16-f32:16-f64:16-n8-a:16";