LLVM's llc
utility can compile an LLVM bitfile into an assembly file:
$ llc-15 -march=avr -mcpu=atmega32u4 foo.ll -filetype=asm -o foo.ll.s
However, the resulting .s
file can't be assembled as-is with e.g. GCC's assembler, with some 150-odd errors:
$ avr-as -mmcu=atmega32u4 foo.ll.s
foo.ll.s: Assembler messages:
foo.ll.s:3213: Error: unrecognized symbol type ""
foo.ll.s:3213: Error: unknown opcode `lt'
foo.ll.s:3213: Error: unknown opcode `ruduino..i'
foo.ll.s:3213: Error: unknown opcode `gt'
foo.ll.s:3213: Error: junk at end of line, first unrecognized character is `1'
foo.ll.s:3214: Error: unknown opcode `_zn4core3p'
foo.ll.s:3214: Error: unknown opcode `lt'
foo.ll.s:3214: Error: unknown opcode `ruduino..i'
foo.ll.s:3214: Error: unknown opcode `gt'
foo.ll.s:3214: Error: junk at end of line, first unrecognized character is `1'
foo.ll.s:3221: Error: expected comma after name `_ZN4core3ptr58drop_in_place' in .size directive
foo.ll.s:3221: Error: unknown opcode `lt'
foo.ll.s:3221: Error: unknown opcode `ruduino..i'
foo.ll.s:3221: Error: unknown opcode `gt'
foo.ll.s:3221: Error: junk at end of line, first unrecognized character is `1'
foo.ll.s:3221: Error: unknown opcode `lt'
foo.ll.s:3221: Error: unknown opcode `ruduino..i'
foo.ll.s:3221: Error: unknown opcode `gt'
foo.ll.s:3221: Error: junk at end of line, first unrecognized character is `1'
foo.ll.s:6148: Error: garbage at end of line
foo.ll.s:6149: Error: garbage at end of line
foo.ll.s:8758: Error: garbage at end of line
foo.ll.s:8759: Error: garbage at end of line
foo.ll.s:8796: Error: garbage at end of line
foo.ll.s:8797: Error: garbage at end of line
foo.ll.s:8834: Error: garbage at end of line
foo.ll.s:8835: Error: garbage at end of line
foo.ll.s:9067: Error: garbage at end of line
foo.ll.s:9068: Error: garbage at end of line
foo.ll.s:9096: Error: garbage at end of line
foo.ll.s:9097: Error: garbage at end of line
foo.ll.s:9487: Error: garbage at end of line
foo.ll.s:9488: Error: garbage at end of line
foo.ll.s:9602: Error: garbage at end of line
foo.ll.s:9603: Error: garbage at end of line
foo.ll.s:9769: Error: garbage at end of line
foo.ll.s:9770: Error: garbage at end of line
foo.ll.s:9998: Error: garbage at end of line
foo.ll.s:9999: Error: garbage at end of line
foo.ll.s:11504: Error: garbage at end of line
foo.ll.s:11505: Error: garbage at end of line
foo.ll.s:11648: Error: unrecognized symbol type ""
foo.ll.s:11648: Error: unknown opcode `lt'
foo.ll.s:11648: Error: unknown opcode `impl'
foo.ll.s:11648: Error: unknown opcode `u20'
foo.ll.s:11648: Error: unknown opcode `core..fmt.'
foo.ll.s:11648: Error: unknown opcode `u20'
foo.ll.s:11648: Error: unknown opcode `for'
foo.ll.s:11648: Error: unknown opcode `u20'
foo.ll.s:11648: Error: unknown opcode `usize'
foo.ll.s:11648: Error: unknown opcode `gt'
foo.ll.s:11648: Error: junk at end of line, first unrecognized character is `3'
foo.ll.s:11649: Error: unknown opcode `_zn4core3f'
foo.ll.s:11649: Error: unknown opcode `lt'
foo.ll.s:11649: Error: unknown opcode `impl'
foo.ll.s:11649: Error: unknown opcode `u20'
foo.ll.s:11649: Error: unknown opcode `core..fmt.'
foo.ll.s:11649: Error: unknown opcode `u20'
foo.ll.s:11649: Error: unknown opcode `for'
foo.ll.s:11649: Error: unknown opcode `u20'
foo.ll.s:11649: Error: unknown opcode `usize'
foo.ll.s:11649: Error: unknown opcode `gt'
foo.ll.s:11649: Error: junk at end of line, first unrecognized character is `3'
foo.ll.s:11698: Error: garbage at end of line
foo.ll.s:11699: Error: garbage at end of line
foo.ll.s:11707: Error: garbage at end of line
foo.ll.s:11708: Error: garbage at end of line
foo.ll.s:11730: Error: garbage at end of line
foo.ll.s:11731: Error: garbage at end of line
foo.ll.s:11764: Error: garbage at end of line
foo.ll.s:11765: Error: garbage at end of line
foo.ll.s:12221: Error: expected comma after name `_ZN4core3fmt3num3imp54_' in .size directive
foo.ll.s:12221: Error: unknown opcode `lt'
foo.ll.s:12221: Error: unknown opcode `impl'
foo.ll.s:12221: Error: unknown opcode `u20'
foo.ll.s:12221: Error: unknown opcode `core..fmt.'
foo.ll.s:12221: Error: unknown opcode `u20'
foo.ll.s:12221: Error: unknown opcode `for'
foo.ll.s:12221: Error: unknown opcode `u20'
foo.ll.s:12221: Error: unknown opcode `usize'
foo.ll.s:12221: Error: unknown opcode `gt'
foo.ll.s:12221: Error: junk at end of line, first unrecognized character is `3'
foo.ll.s:12221: Error: unknown opcode `lt'
foo.ll.s:12221: Error: unknown opcode `impl'
foo.ll.s:12221: Error: unknown opcode `u20'
foo.ll.s:12221: Error: unknown opcode `core..fmt.'
foo.ll.s:12221: Error: unknown opcode `u20'
foo.ll.s:12221: Error: unknown opcode `for'
foo.ll.s:12221: Error: unknown opcode `u20'
foo.ll.s:12221: Error: unknown opcode `usize'
foo.ll.s:12221: Error: unknown opcode `gt'
foo.ll.s:12221: Error: junk at end of line, first unrecognized character is `3'
foo.ll.s:6148: Error: can't resolve `0' {*UND* section} - `lo8' {*UND* section}
foo.ll.s:6148: Error: expression too complex
foo.ll.s:6149: Error: can't resolve `0' {*UND* section} - `hi8' {*UND* section}
foo.ll.s:6149: Error: expression too complex
foo.ll.s:8758: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:8758: Error: expression too complex
foo.ll.s:8759: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:8759: Error: expression too complex
foo.ll.s:8796: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:8796: Error: expression too complex
foo.ll.s:8797: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:8797: Error: expression too complex
foo.ll.s:8834: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:8834: Error: expression too complex
foo.ll.s:8835: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:8835: Error: expression too complex
foo.ll.s:9067: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:9067: Error: expression too complex
foo.ll.s:9068: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:9068: Error: expression too complex
foo.ll.s:9096: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:9096: Error: expression too complex
foo.ll.s:9097: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:9097: Error: expression too complex
foo.ll.s:9487: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:9487: Error: expression too complex
foo.ll.s:9488: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:9488: Error: expression too complex
foo.ll.s:9602: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:9602: Error: expression too complex
foo.ll.s:9603: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:9603: Error: expression too complex
foo.ll.s:9769: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:9769: Error: expression too complex
foo.ll.s:9770: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:9770: Error: expression too complex
foo.ll.s:9998: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:9998: Error: expression too complex
foo.ll.s:9999: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:9999: Error: expression too complex
foo.ll.s:11504: Error: can't resolve `0' {.text section} - `lo8' {*UND* section}
foo.ll.s:11504: Error: expression too complex
foo.ll.s:11505: Error: can't resolve `0' {.text section} - `hi8' {*UND* section}
foo.ll.s:11505: Error: expression too complex
foo.ll.s:11698: Error: can't resolve `0' {*UND* section} - `lo8' {*UND* section}
foo.ll.s:11698: Error: expression too complex
foo.ll.s:11699: Error: can't resolve `0' {*UND* section} - `hi8' {*UND* section}
foo.ll.s:11699: Error: expression too complex
foo.ll.s:11707: Error: can't resolve `0' {*UND* section} - `lo8' {*UND* section}
foo.ll.s:11707: Error: expression too complex
foo.ll.s:11708: Error: can't resolve `0' {*UND* section} - `hi8' {*UND* section}
foo.ll.s:11708: Error: expression too complex
foo.ll.s:11730: Error: can't resolve `0' {*UND* section} - `lo8' {*UND* section}
foo.ll.s:11730: Error: expression too complex
foo.ll.s:11731: Error: can't resolve `0' {*UND* section} - `hi8' {*UND* section}
foo.ll.s:11731: Error: expression too complex
foo.ll.s:11764: Error: can't resolve `0' {*UND* section} - `lo8' {*UND* section}
foo.ll.s:11764: Error: expression too complex
foo.ll.s:11765: Error: can't resolve `0' {*UND* section} - `hi8' {*UND* section}
foo.ll.s:11765: Error: expression too complex
For reference, line 3213, the first line of llc
's output where avr-as
chokes is a .type
directive:
.type _ZN4core3ptr58drop_in_place$LT$ruduino..interrupt..DisableInterrupts$GT$17h24ba00b9e0a48e1bE,@function
_ZN4core3ptr58drop_in_place$LT$ruduino..interrupt..DisableInterrupts$GT$17h24ba00b9e0a48e1bE: ; @"_ZN4core3ptr58drop_in_place$LT$ruduino..interrupt..D
However, since the results are only coming from 37 unique lines out of foo.ll.s
's 13232 lines, the assembly format can't be that different from what avr-as
expects.
So is there either a different AVR assembler I can use to consume llc
's output, or is there some flag I need to pass to llc
, or is there some lightweight postprocessing I can do on the .s
file to feed it to avr-as
?
llvm-mc
has an assembler mode with -filetype=obj
, so we can do
llvm-mc-15 --arch=avr --mcpu=atmega32u4 foo.ll.s -filetype=obj -o foo.ll.s.o
(note that although llc
and llvm-mc
are both part of the LLVM suite, the command-line flags to set the target architecture are slightly different)
Unfortunately, in my experiece llc -filetype=obj
and llvm-mc -filetype=obj
doesn't generate exactly the same object file, but that is probably just an implementation bug and isn't intentional.