Skip to content

.if constant expression folding works for .s but not for inline assembly due to UseAssemblerInfoForParsing #62520

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pskocik opened this issue May 3, 2023 · 5 comments · Fixed by #91082
Labels
mc Machine (object) code

Comments

@pskocik
Copy link

pskocik commented May 3, 2023

Example:

.text
start:
  nop
end:
.if (end - start) == 0
.err
.endif

compiles when saved as a .s file. But when the same is put into a .c file as:

__asm(
".text\n"
"start:\n"
"  nop\n"
"end:\n"
".if (end - start) == 0\n"
".err\n"
".endif\n"
);

it fails with error: expected absolute expression. GCC succeeds with both examples. #53728 is probably related.

@llvmbot
Copy link
Member

llvmbot commented Oct 2, 2023

@llvm/issue-subscribers-backend-x86

Example: ```s .text start: nop end: .if (end - start) == 0 .err .endif ```

compiles when saved as a .s file. But when the same is put into a .c file as:

__asm(
".text\n"
"start:\n"
"  nop\n"
"end:\n"
".if (end - start) == 0\n"
".err\n"
".endif\n"
);

it fails with error: expected absolute expression. GCC succeeds with both examples. #53728 is probably related.

@MaskRay
Copy link
Member

MaskRay commented May 4, 2024

it fails with error: expected absolute expression. GCC succeeds with both examples. #53728 is probably related.

clang -c -fno-integrated-as a.c works as well. I have some notes in https://maskray.me/blog/2023-06-18-port-llvm-xray-to-apple-systems

In the case of direct object emission, where LLVM IR is directly lowered to an object file bypassing assembly (e.g., using clang -c a.c instead of clang -c a.s or clang -c --save-temps a.c), the assembler information is not used at parse time (MCStreamer::UseAssemblerInfoForParsing). As a result, the assembly code .quad (Lxray_sleds_end0-lxray_sleds_start0)>>5 will be transformed into a fixup. Lxray_sleds_end0 is a pending label which will then be assigned to the next fragment when AsmPrinter emits new piece of data to the xray_instr_map section.


@niravhdave
Commit 6c0665e
(https://reviews.llvm.org/D45164) enabled certain constant expression
evaluation for MCObjectStreamer at parse time (e.g. .if directives,
see llvm/test/MC/AsmParser/assembler-expressions.s).

getUseAssemblerInfoForParsing was added to make clang -c handling
inline assembly similar to MCAsmStreamer (e.g. llvm-mc -filetype=asm),
where such expression folding (related to
AttemptToFoldSymbolOffsetDifference) is unavailable.

I believe this is overly conservative. We can make some parse-time
expression folding work for clang -c even if clang -S would still
report an error, a MCAsmStreamer issue (we cannot print .if
directives) that should not restrict the functionality of
MCObjectStreamer.

% cat b.cc
asm(R"(
.pushsection .text,"ax"
.globl _start; _start: ret
.if . -_start == 1
  ret
.endif
.popsection
)");
% gcc -S b.cc && gcc -c b.cc
% clang -S -fno-integrated-as b.cc     # succeeded

% clang -c b.cc     # succeeded with this patch
% clang -S b.cc     # still failed
<inline asm>:4:5: error: expected absolute expression
    4 | .if . -_start == 1
      |     ^
1 error generated.

@MaskRay MaskRay changed the title Label differences not treated as absolute expressions in C __asm blocks even though they are in .s files .if constant expression folding works for .s but not for inline assembly due to UseAssemblerInfoForParsing May 4, 2024
@musamaanjum
Copy link

I've hit the same bug. Clang gives an error with the following extended asm:

<inline asm>:7:8: error: expected absolute expression
    7 |         .ifne . - test_page - 4096
      |               ^
<inline asm>:8:2: error: test page is not one page long
    8 |         .error "test page is not one page long"
      |         ^
asm (
	".pushsection \".text\", \"ax\"\n\t"
	".balign 4096\n\t"
	"test_page: .globl test_page\n\t"
	".fill 4094,1,0xcc\n\t"
	"test_syscall_insn:\n\t"
	"syscall\n\t"
	".ifne . - test_page - 4096\n\t"
	".error \"test page is not one page long\"\n\t"
	".endif\n\t"
	".popsection"
    );

But clang builds fine if the asm is moved to the assembly file, or by generating the asm by GCC and then building the asm to binary by clang.

@MaskRay
Copy link
Member

MaskRay commented May 6, 2024

asm (
".pushsection ".text", "ax"\n\t"
".balign 4096\n\t"
"test_page: .globl test_page\n\t"
".fill 4094,1,0xcc\n\t"
"test_syscall_insn:\n\t"
"syscall\n\t"
".ifne . - test_page - 4096\n\t"
".error "test page is not one page long"\n\t"
".endif\n\t"
".popsection"
);

#91082 will make this code compile with clang -c but still not with clang -S -fintegrated-as.

I've also have experiments [MC] Enable getAssemblerPtr for MCAsmStreamer to hopefully make MCAsmStreamer fold more expressions similar to MCObjectStreamer, but there is a lot of complexity.

@MaskRay
Copy link
Member

MaskRay commented May 7, 2024

MaskRay added a commit that referenced this issue May 15, 2024
Commit 6c0665e
(https://reviews.llvm.org/D45164) enabled certain constant expression
evaluation for `MCObjectStreamer` at parse time (e.g. `.if` directives,
see llvm/test/MC/AsmParser/assembler-expressions.s).

`getUseAssemblerInfoForParsing` was added to make `clang -c` handling
inline assembly similar to `MCAsmStreamer` (e.g. `llvm-mc -filetype=asm`),
where such expression folding (related to
`AttemptToFoldSymbolOffsetDifference`) is unavailable.

I believe this is overly conservative. We can make some parse-time
expression folding work for `clang -c` even if `clang -S` would still
report an error, a MCAsmStreamer issue (we cannot print `.if`
directives) that should not restrict the functionality of
MCObjectStreamer.

```
% cat b.cc
asm(R"(
.pushsection .text,"ax"
.globl _start; _start: ret
.if . -_start == 1
  ret
.endif
.popsection
)");
% gcc -S b.cc && gcc -c b.cc
% clang -S -fno-integrated-as b.cc     # succeeded

% clang -c b.cc     # succeeded with this patch
% clang -S b.cc     # still failed
<inline asm>:4:5: error: expected absolute expression
    4 | .if . -_start == 1
      |     ^
1 error generated.
```

Close #62520
Link: https://discourse.llvm.org/t/rfc-clang-assembly-object-equivalence-for-files-with-inline-assembly/78841

Pull Request: #91082
@EugeneZelenko EugeneZelenko added mc Machine (object) code and removed backend:X86 llvm:asmparser labels May 15, 2024
MaskRay added a commit that referenced this issue May 20, 2024
Commit 6c0665e
(https://reviews.llvm.org/D45164) enabled certain constant expression
evaluation for `MCObjectStreamer` at parse time (e.g. `.if` directives,
see llvm/test/MC/AsmParser/assembler-expressions.s).

`getUseAssemblerInfoForParsing` was added to make `clang -c` handling
inline assembly similar to `MCAsmStreamer` (e.g. `llvm-mc -filetype=asm`),
where such expression folding (related to
`AttemptToFoldSymbolOffsetDifference`) is unavailable.

I believe this is overly conservative. We can make some parse-time
expression folding work for `clang -c` even if `clang -S` would still
report an error, a MCAsmStreamer issue (we cannot print `.if`
directives) that should not restrict the functionality of
MCObjectStreamer.

```
% cat b.cc
asm(R"(
.pushsection .text,"ax"
.globl _start; _start: ret
.if . -_start == 1
  ret
.endif
.popsection
)");
% gcc -S b.cc && gcc -c b.cc
% clang -S -fno-integrated-as b.cc     # succeeded

% clang -c b.cc     # succeeded with this patch
% clang -S b.cc     # still failed
<inline asm>:4:5: error: expected absolute expression
    4 | .if . -_start == 1
      |     ^
1 error generated.
```

However, removing `getUseAssemblerInfoForParsing` would make
MCDwarfFrameEmitter::Emit (for .eh_frame FDE) slow (~4% compile time
regression for sqlite3.c amalgamation) due to expensive
`AttemptToFoldSymbolOffsetDifference`. For now, make
`UseAssemblerInfoForParsing` false in MCDwarfFrameEmitter::Emit.

Close #62520
Link: https://discourse.llvm.org/t/rfc-clang-assembly-object-equivalence-for-files-with-inline-assembly/78841

Pull Request: #91082
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mc Machine (object) code
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants