Thread (30 messages) flat view 30 messages, 6 authors, 2021-03-24

Re: [RFC PATCH 8/8] powerpc/64/asm: don't reassign labels

From: Daniel Axtens <hidden>
Date: 2021-02-26 00:29:13

Segher Boessenkool [off-list ref] writes:
On Thu, Feb 25, 2021 at 02:10:06PM +1100, Daniel Axtens wrote:
quoted
The assembler really does not like us reassigning things to the same
label:

<instantiation>:7:9: error: invalid reassignment of non-absolute variable 'fs_label'

This happens across a bunch of platforms:
https://github.com/ClangBuiltLinux/linux/issues/1043
https://github.com/ClangBuiltLinux/linux/issues/1008
https://github.com/ClangBuiltLinux/linux/issues/920
https://github.com/ClangBuiltLinux/linux/issues/1050

There is no hope of getting this fixed in LLVM, so if we want to build
with LLVM_IAS, we need to hack around it ourselves.

For us the big problem comes from this:

\#define USE_FIXED_SECTION(sname)				\
	fs_label = start_##sname;				\
	fs_start = sname##_start;				\
	use_ftsec sname;

\#define USE_TEXT_SECTION()
	fs_label = start_text;					\
	fs_start = text_start;					\
	.text

and in particular fs_label.
The "Setting Symbols" super short chapter reads:

"A symbol can be given an arbitrary value by writing a symbol, followed
by an equals sign '=', followed by an expression.  This is equivalent
to using the '.set' directive."

And ".set" has

"Set the value of SYMBOL to EXPRESSION.  This changes SYMBOL's value and
type to conform to EXPRESSION.  If SYMBOL was flagged as external, it
remains flagged.

You may '.set' a symbol many times in the same assembly provided that
the values given to the symbol are constants.  Values that are based on
expressions involving other symbols are allowed, but some targets may
restrict this to only being done once per assembly.  This is because
those targets do not set the addresses of symbols at assembly time, but
rather delay the assignment until a final link is performed.  This
allows the linker a chance to change the code in the files, changing the
location of, and the relative distance between, various different
symbols.

If you '.set' a global symbol, the value stored in the object file is
the last value stored into it."

So this really should be fixed in clang: it is basic assembler syntax.
No doubt I have explained this poorly.

LLVM does allow some things, this builds fine for example:

.set foo, 8192
addi %r3, %r3, foo
.set foo, 1234
addi %r3, %r3, foo

However, this does not:

a:
.set foo, a
addi %r3, %r3, foo@l
b:
.set foo, b
addi %r3, %r3, foo-a

clang -target ppc64le -integrated-as  foo.s -o foo.o -c
foo.s:5:11: error: invalid reassignment of non-absolute variable 'foo' in '.set' directive
.set foo, b
          ^

gas otoh, has no issues with reassignment:

$ powerpc64-linux-gnu-as foo.s -c -o foo.o
$ powerpc64-linux-gnu-objdump -dr foo.o

foo.o:     file format elf64-powerpc


Disassembly of section .text:

0000000000000000 <a>:
   0:	38 63 00 00 	addi    r3,r3,0
			2: R_PPC64_ADDR16_LO	.text

0000000000000004 <b>:
   4:	38 63 00 04 	addi    r3,r3,4


It seems the llvm assembler only does a single pass, so they're not keen
on trying to support reassigning labels with non-absolute values.

Kind regards,
Daniel
Segher
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help