January 22, 2015
I'm trying to track down an optimization bug.

I have written a D program and a C program that are essentially identical, and compiled them to assembly code with my arm-none-eabi-gdc/gcc build.

C Code: https://bpaste.net/show/6f420de3a892
C ASM : https://bpaste.net/show/42c75f6763bf
arm-none-eabi-gcc -O1 -S -ffunction-sections test.c -o test.s


D Code: https://bpaste.net/show/20faec5c4bb6
D ASM : https://bpaste.net/show/b2c200705d5d
arm-none-eabi-gdc -O1 -S -ffunction-sections test.d -o test.d.s

The problem is with the string literals at the very end of the ASM files:

C
****
.L12:
	.align	2
.L11:
	.word	.LC1
	.word	.LC2
	.word	.LC3
	.size	_start, .-_start
	.section	.rodata.str1.4,"aMS",%progbits,1
	.align	2
.LC0:
	.ascii	"\015\012\000"
	.space	1
.LC1:
	.ascii	"a\000"
	.space	2
.LC2:
	.ascii	"another string\000"
	.space	1
.LC3:
	.ascii	"do it again\000"
	.ident	"GCC: (GNU) 4.9.2"

D
****
.L6:
	.word	.LANCHOR0

... { blah blah }

.L13:
	.align	2
.L12:
	.word	.LANCHOR0
	.cantunwind
	.fnend
	.size	_D5start6_startFZv, .-_D5start6_startFZv
	.section	.rodata
	.align	2
	.set	.LANCHOR0,. + 0
.LC0:
	.ascii	"\015\012"
	.space	2
.LC1:
	.ascii	"a"
	.space	3
.LC2:
	.ascii	"another string"
	.space	2
.LC3:
	.ascii	"do it again"
	.ident	"GCC: (GNU) 4.9.2"

Notice how the D code adds the section anchor .LANCHOR0, but the C code does not.

The D code then refers to the sting literals with something like this...
ldr	r3, .L6
add	r3, sp, #16
... essentially referring to the string literal as an offset from .LANCHOR

This is causing a problem for me because if I put my string literals in separate sections (i.e. -fdata-sections), compile with -O1 (i.e. -fsection-anchors), and link with --gc-section, then the linker strips out my string literals because it doesn't see the link to the string literal. (At least that's my theory).

The C code, on the other hand, does not use the section anchor and instead seems to put them in some kind of array of strings like this:
.L11:
	.word	.LC1
	.word	.LC2
	.word	.LC3

Therefore, the linker can see the link to the string literals and doesn't strip them out (Again, that's my theory)

Can anything be done about this in GDC?

Thanks always for the help,
Mike
January 22, 2015
Am Thu, 22 Jan 2015 11:34:27 +0000
schrieb "Mike" <none@none.com>:

> I'm trying to track down an optimization bug.
> 
> I have written a D program and a C program that are essentially identical, and compiled them to assembly code with my arm-none-eabi-gdc/gcc build.
> 
> C Code: https://bpaste.net/show/6f420de3a892
> C ASM : https://bpaste.net/show/42c75f6763bf
> arm-none-eabi-gcc -O1 -S -ffunction-sections test.c -o test.s
> 
> 
> D Code: https://bpaste.net/show/20faec5c4bb6
> D ASM : https://bpaste.net/show/b2c200705d5d
> arm-none-eabi-gdc -O1 -S -ffunction-sections test.d -o test.d.s
> 
> The problem is with the string literals at the very end of the ASM files:
> 
> C
> ****
> .L12:
> 	.align	2
> .L11:
> 	.word	.LC1
> 	.word	.LC2
> 	.word	.LC3
> 	.size	_start, .-_start
> 	.section	.rodata.str1.4,"aMS",%progbits,1
> 	.align	2
> .LC0:
> 	.ascii	"\015\012\000"
> 	.space	1
> .LC1:
> 	.ascii	"a\000"
> 	.space	2
> .LC2:
> 	.ascii	"another string\000"
> 	.space	1
> .LC3:
> 	.ascii	"do it again\000"
> 	.ident	"GCC: (GNU) 4.9.2"
> 
> D
> ****
> .L6:
> 	.word	.LANCHOR0
> 
> ... { blah blah }
> 
> .L13:
> 	.align	2
> .L12:
> 	.word	.LANCHOR0
> 	.cantunwind
> 	.fnend
> 	.size	_D5start6_startFZv, .-_D5start6_startFZv
> 	.section	.rodata
> 	.align	2
> 	.set	.LANCHOR0,. + 0
> .LC0:
> 	.ascii	"\015\012"
> 	.space	2
> .LC1:
> 	.ascii	"a"
> 	.space	3
> .LC2:
> 	.ascii	"another string"
> 	.space	2
> .LC3:
> 	.ascii	"do it again"
> 	.ident	"GCC: (GNU) 4.9.2"
> 
> Notice how the D code adds the section anchor .LANCHOR0, but the C code does not.
> 
> The D code then refers to the sting literals with something like
> this...
> ldr	r3, .L6
> add	r3, sp, #16
> ... essentially referring to the string literal as an offset from
> .LANCHOR
> 
> This is causing a problem for me because if I put my string literals in separate sections (i.e. -fdata-sections), compile with -O1 (i.e. -fsection-anchors), and link with --gc-section, then the linker strips out my string literals because it doesn't see the link to the string literal. (At least that's my theory).
> 
> The C code, on the other hand, does not use the section anchor
> and instead seems to put them in some kind of array of strings
> like this:
> .L11:
> 	.word	.LC1
> 	.word	.LC2
> 	.word	.LC3
> 
> Therefore, the linker can see the link to the string literals and doesn't strip them out (Again, that's my theory)
> 
> Can anything be done about this in GDC?
> 
> Thanks always for the help,
> Mike

It's probably because we put the literals directly into .rodata but C
puts them into .rodata.str1.4. I guess GCC would prefer section anchors
in both cases for optimization purposes but can't use anchors
for .rodata.str1.4. Maybe the linker performs merging or
something similar on .rodata.str1.4 which makes anchor-based addressing
invalid.

We can try to put our string literals into .rodata.str1.4 and see if this helps. However, I think you can't rely on the fact that section anchors are not used, it might be just an limitation in GCCs optimizer.



Main point to look at is gcc/varasm.c: default_elf_select_section selects the section. mergeable_string_section is the .rodata.str1.4 section, decls are put into this section if categorize_decl_for_section returns SECCAT_RODATA_MERGE_STR. We pass var_decls (the string structs) to this function but it only categorizes a decl as a string if it's a STRING_CST.

Unfortunately gcc is pretty dumb in this regard. Even in C:
const char mesg [] = "Hello World!"; //=>.rodata
const char* mesg = "Hello World! "; //=>rodata.str...

Our code is always equal to
const String s = {length, &"Hello World!"};
which is in the same category as the first C example.

Maybe we could do something like this:
const char* value = "Hello World";
const String s = {length, &value};
But I'm not sure if we can have char* declarations without a name.


@Iain any idea how we could make this work? There might be other benefits like string constant merging, etc.