Artyom Goncharov via llvm-dev
2019-Jan-07 14:24 UTC
[llvm-dev] Arm jump-table and inline asm label give relocation error
Hi all, Given sample ------ source_filename = “sample.ll" target datalayout = "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" target triple = "thumbv7-apple-ios9.1.0" define hidden i32 @sample(i32) { br label %b b: %f = select i1 1, i32 2, i32 1 switch i32 %f, label %c [ i32 0, label %g i32 1, label %j i32 2, label %e i32 3, label %d ] c: br label %a a: br label %b e: br label %a d: call void asm sideeffect "this_is_the_label:", ""() br label %a g: br label %a j: br label %a } ------ Running: "clang -cc1 -x ir ./sample.ll -triple thumbv7-apple-ios9.1.0 -emit-obj -disable-llvm-passes -target-abi apcs-gnu -mfloat-abi soft -O0 -o sample.o.ll”, I get: "fatal error: error in backend: expected relocatable expression”. After sitting on it for some time I figured it can be fixed by just prefixing the label with “L” which makes it private global symbol. Otherwise the label forms a new atom (MCMachOStreamer::FinishImpl) which conflicts with fix-up evaluation (MCAssembler::evaluateFixup) for jump-table entry, e.g. given fix-up ------ LBB2_10 - (LCPI2_0 + 4)) / 2 ------ LCPI2_0 is the switch block “b”, assigned atom “sample" LBB2_10 is the target block “d” and will be assigned atom named “this_is_the_label”, but really it should be “sample”, so somewhere (MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl) deep down symbols resolution atoms from both symbols mismatch. The question here is whether this behaviour is expected. It seems to me any label defined within inline asm must have MCSymbol::IsTemporary set otherwise no way to resolve these fix-ups.
Tim Northover via llvm-dev
2019-Jan-07 15:09 UTC
[llvm-dev] Arm jump-table and inline asm label give relocation error
Hi Artyom, On Mon, 7 Jan 2019 at 14:24, Artyom Goncharov via llvm-dev <llvm-dev at lists.llvm.org> wrote:> After sitting on it for some time I figured it can be fixed by just prefixing the label with “L” which makes it private global symbol.Assembler-local; it makes sure the symbol won't exist at all in the object file, and that all references to it will have been resolved before the linker gets involved. There's also a (rarer) "l" prefix for things that can't be resolved by the compiler but the linker does have to eliminate.> The question here is whether this behaviour is expected. It seems to me any label defined within inline asm must have MCSymbol::IsTemporary set otherwise no way to resolve these fix-ups.That sounds about right. You've already figured out most of the details yourself; MachO objects produced by compiler are allowed to be split up and shuffled by the linker at any global symbol boundary[*]. MachO as a format is pretty deficient and only allows 16 different kinds of relocation (depending on how you count them). Most of those are already allocated on ARM so if someone actually wanted to support labels in asm blocks they'd need to fairly seriously rework either ARMConstandIslands (to avoid moving constants across such boundaries, and put them in the correct region in the first place) or CodeGen (to make constants addressable via relocations that already exist). I doubt anyone wants to do that without a *very* compelling use-case. ARMConstantIslands is hard enough to maintain when it only has to support sane situations. Cheers. Tim. [*] Theoretically it's controlled by the ".subsections_via_symbols" directive but that's been emitted unconditionally for years and I don't think anyone has any appetite for disabling it.> > > > _______________________________________________ > LLVM Developers mailing list > llvm-dev at lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev