Fangrui Song 1978c21d96
[ELF] ScriptLexer: generate tokens lazily
The current tokenize-whole-file approach has a few limitations.

* Lack of state information: `maybeSplitExpr` is needed to parse
  expressions. It's infeasible to add new states to behave more like GNU
  ld.
* `readInclude` may insert tokens in the middle, leading to a time
  complexity issue with N-nested `INCLUDE`.
* line/column information for diagnostics are inaccurate, especially
  after an `INCLUDE`.
* `getLineNumber` cannot be made more efficient without significant code
  complexity and memory consumption. https://reviews.llvm.org/D104137

The patch switches to a traditional lexer that generates tokens lazily.

* `atEOF` behavior is modified: we need to call `peek` to determine EOF.
* `peek` and `next` cannot call `setError` upon `atEOF`.
* Since `consume` no longer reports an error upon `atEOF`, the idiom `while (!errorCount() && !consume(")"))`
  would cause a dead loop. Use `while (peek() != ")" && !atEOF()) { ... } expect(")")` instead.
* An include stack is introduced to handle `readInclude`. This can be
  utilized to address #93947 properly.
* `tokens` and `pos` are removed.
* `commandString` is reimplemented. Since it is used in -Map output,
  `\n` needs to be replaced with space.

Pull Request: https://github.com/llvm/llvm-project/pull/100493
2024-07-26 14:26:38 -07:00

47 lines
2.5 KiB
Plaintext

# REQUIRES: x86
# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/map-file2.s -o %t.o
# RUN: ld.lld -o %t %t.o -Map=%t.map --script %s
# RUN: FileCheck -strict-whitespace %s < %t.map
SECTIONS {
. = 0x1000;
.aaa : { *(.aaa.*) }
.bbb : AT(0x2000) { *(.bbb.*) }
.ccc : AT(0x3000) { *(.ccc.*) }
. += 0x100;
.ddd : {
BYTE(0x11)
. += 0x100;
*(.ddd.*)
}
.text : { *(.text.*) }
}
# CHECK: VMA LMA Size Align Out In Symbol
# CHECK-NEXT: 0 0 1000 1 . = 0x1000
# CHECK-NEXT: 1000 1000 8 1 .aaa
# CHECK-NEXT: 1000 1000 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.aaa)
# CHECK-NEXT: 1008 2000 8 1 .bbb
# CHECK-NEXT: 1008 2000 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.bbb)
# CHECK-NEXT: 1010 3000 8 1 .ccc
# CHECK-NEXT: 1010 3000 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.ccc)
# CHECK-NEXT: 1018 3008 100 1 . += 0x100
# CHECK-NEXT: 1118 3108 109 1 .ddd
# CHECK-NEXT: 1118 3108 1 1 BYTE(0x11)
# CHECK-NEXT: 1119 3109 100 1 . += 0x100
# CHECK-NEXT: 1219 3209 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.ddd)
# CHECK-NEXT: 1228 3218 34 8 .eh_frame
# CHECK-NEXT: 1228 3218 30 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.eh_frame+0x0)
# CHECK-NEXT: 125c 324c 1 4 .text
# CHECK-NEXT: 125c 324c 1 4 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.text)
# CHECK-NEXT: 125c 324c 0 1 _start
# CHECK-NEXT: 125c 324c 0 1 f(int)
# CHECK-NEXT: 0 0 8 1 .comment
# CHECK-NEXT: 0 0 8 1 <internal>:(.comment)
# CHECK-NEXT: 0 0 48 8 .symtab
# CHECK-NEXT: 0 0 48 8 <internal>:(.symtab)
# CHECK-NEXT: 0 0 48 1 .shstrtab
# CHECK-NEXT: 0 0 48 1 <internal>:(.shstrtab)
# CHECK-NEXT: 0 0 e 1 .strtab
# CHECK-NEXT: 0 0 e 1 <internal>:(.strtab)