[llvm-dev] Lowering a reasonably complex struct seems to create over complex and invalid assembly fixups on some targets

Tim Northover via llvm-dev llvm-dev at lists.llvm.org
Sat Jul 14 04:47:49 PDT 2018


Hi Carl,

On Sat, 14 Jul 2018 at 11:47, carl-llvm-dev at petosoft.com via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
> .long (__unnamed_4&65535)-((_TMRfV4main10Brightness&65535)+16)
> .long (__unnamed_5&65535)-((_TMRfV4main10Brightness&65535)+20)

Ouch.

> AVR is an experimental target but I think MIPS is mature?  So I’m trying to get to the bottom of how LLVM is lowering to these expressions in fixups, when they cannot be evaluated by the MC layer?

I think the code you're after is in
lib/CodeGen/AsmPrinter/AsmPrinter.cpp, around line 2124 where it's
converting a ptrtoint ConstantExpr to an MCExpr.

Obviously the immediate fix is to do ptrtoint to i32 here instead of
truncating later. And to a certain extent this kind of problem is
inevitable. You can always and trivially write something in a Global
definition that is simply not implementable by the assembler
(relocations are not infinitely flexible on most platforms), so it's
the front-end's responsibility to emit constants that are valid.

What LLVM actually seems to be doing is assuming that expressions may
be evaluated at a precision beyond pointer width, which seems pretty
valid from a few test-cases I've run. When casting a bare pointer it's
fine to omit the "and", but for more complex expressions it can change
the value. Something like

    @tmp = global i8 zeroinitializer
    @var = global i64 ptrtoint(i8* getelementptr(i8, i8* @tmp, i32 1000) to i64)

cannot be simply emitted as ".quad tmp + 1000" on (say) 32-bit Mips
because that introduces a R_MIPS_64 relocation which will do 64-bit
arithmetic, but the GEP should wrap around at 2^32.

Of course, it's completely different on other targets: i386 does
32-bit arithmetic anyway (via R_386_32), ARM produces an error
message. So you could make a reasonable argument that the MC layer
and/or the translation in AsmPrinter.cpp is being a bit too
opinionated on how assemblers work and should be more generic.

Personally, I'm undecided about the platonic best option here. But I'd
probably quietly fix the front-end if it was my problem.

Cheers.

Tim.


More information about the llvm-dev mailing list