LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 27688 - clang reorders module level asm statements
Summary: clang reorders module level asm statements
Status: RESOLVED DUPLICATE of bug 6364
Alias: None
Product: clang
Classification: Unclassified
Component: -New Bugs (show other bugs)
Version: unspecified
Hardware: PC Linux
: P normal
Assignee: Unassigned Clang Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2016-05-09 14:36 PDT by Richard Jones
Modified: 2016-05-10 13:47 PDT (History)
4 users (show)

See Also:
Fixed By Commit(s):


Attachments
asmorder.c (1015 bytes, text/plain)
2016-05-09 14:36 PDT, Richard Jones
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Richard Jones 2016-05-09 14:36:49 PDT
Created attachment 16335 [details]
asmorder.c

Firstly, I realize here that I'm operating well outside any C standards or
guarantees of any sort.  But this stuff is useful for some people.

If you want to write a PC BIOS option ROM in C, you can do it in
gcc using asm statements at the module level of the C file, at the
start and end.  These asm statements contain the option ROM header
and trailing and effectively "bracket" the C code in the middle.
(See attached example).

This can be compiled using:

  gcc -m16 -c asmorder.c
  ld  -m elf_i386 -Ttext 0 -e _start -s -o asmorder.img asmorder.o
  objcopy -O binary -j .text asmorder.img asmorder.bin

to produce the option ROM (I missed out a step for computing the
checksum of the ROM but it's not relevant for this discussion).

If you disassemble the object file, you'll see that the order of
the start & end asm statements is preserved, and the size of the
file in the header is computed correctly:

  objdump -d asmorder.o

However this does not work if you substitute clang for gcc.

The problem is that clang reorders the module level asm statements,
putting them all at the start of the file, and so the option ROM
format isn't recognized.

In short, gcc converts:

  asm("some stuff");
  some_C_functions;
  asm("more stuff");

into:

  some stuff
  assembler of some_C_functions
  more stuff

but clang turns it into:

  some stuff
  more stuff
  assembler of some_C_functions

Note I'm not using any optimization.

It would be nice if clang didn't do that, at least for asm statements
appearing at the beginning and end of the file.

gcc-6.0.0-0.20.fc24.x86_64 (also works in gcc 4 & 5)
clang-3.8.0-1.fc24.x86_64
Comment 1 Reid Kleckner 2016-05-09 15:10:40 PDT
This is an old, known difference between GCC and LLVM, although -fno-toplevel-reorder is long gone in GCC. In LLVM, functions, globals, aliases, and asms are all maintained in separate lists, so it is difficult to emit them in source order.

The good news is that your issue really seems to be .code16 related, which we are actively working to support as a compiler pragma.

*** This bug has been marked as a duplicate of bug 6364 ***
Comment 2 Richard Jones 2016-05-09 15:15:05 PDT
(In reply to comment #1)
> The good news is that your issue really seems to be .code16 related, which
> we are actively working to support as a compiler pragma.

Could you expand on what you mean by this?
Comment 3 Paolo Bonzini 2016-05-10 12:14:27 PDT
> The good news is that your issue really seems to be .code16 related,
> which we are actively working to support as a compiler pragma.

It's not, it really requires the prolog and epilog to be at the beginning and the end respectively.

Anyway, -fno-toplevel-reorder is definitely still there in GCC.  I'm not sure why you said here that it's "gone" and in PR6364 that it's "deprecated".
Comment 4 Reid Kleckner 2016-05-10 12:42:47 PDT
(In reply to comment #3)
> > The good news is that your issue really seems to be .code16 related,
> > which we are actively working to support as a compiler pragma.
> 
> It's not, it really requires the prolog and epilog to be at the beginning
> and the end respectively.

It's easy to achieve this in other ways, though, such as a linker order file.

> Anyway, -fno-toplevel-reorder is definitely still there in GCC.  I'm not
> sure why you said here that it's "gone" and in PR6364 that it's "deprecated".

My bad, it does exist:
https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
I actually did search for it, but it took me a while to remember the right name. :)

Anyway, the status is that we need to do *something* to enable writing a BIOS. We are not an assembly emitting compiler, though, so it may not look exactly like what GCC has with -fno-toplevel-reorder.
Comment 5 Paolo Bonzini 2016-05-10 13:47:02 PDT
A linker script or similar is a bit overengineered for a single 200-line file.  If we have a guarantee that the block at the beginning stays there, that's already something.  We have a small postprocessing pass to fill in a checksum; we can modify that to remove the need for the final asm block.