[MC] Remove UseAssemblerInfoForParsing

Commit 6c0665e22174d474050e85ca367424f6e02476be
(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: https://github.com/llvm/llvm-project/pull/91082
This commit is contained in:
Fangrui Song 2024-05-15 09:18:39 -07:00 committed by GitHub
parent 9bbefb7f60
commit 03c53c69a3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 16 additions and 40 deletions

View File

@ -576,9 +576,6 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts,
Str.get()->emitZeros(1);
}
// Assembly to object compilation should leverage assembly info.
Str->setUseAssemblerInfoForParsing(true);
bool Failed = false;
std::unique_ptr<MCAsmParser> Parser(

View File

@ -245,8 +245,6 @@ class MCStreamer {
/// requires.
unsigned NextWinCFIID = 0;
bool UseAssemblerInfoForParsing;
/// Is the assembler allowed to insert padding automatically? For
/// correctness reasons, we sometimes need to ensure instructions aren't
/// separated in unexpected ways. At the moment, this feature is only
@ -296,11 +294,10 @@ public:
MCContext &getContext() const { return Context; }
// MCObjectStreamer has an MCAssembler and allows more expression folding at
// parse time.
virtual MCAssembler *getAssemblerPtr() { return nullptr; }
void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; }
bool getUseAssemblerInfoForParsing() { return UseAssemblerInfoForParsing; }
MCTargetStreamer *getTargetStreamer() {
return TargetStreamer.get();
}

View File

@ -102,9 +102,6 @@ void AsmPrinter::emitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
std::unique_ptr<MCAsmParser> Parser(
createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
// Do not use assembler-level information for parsing inline assembly.
OutStreamer->setUseAssemblerInfoForParsing(false);
// We create a new MCInstrInfo here since we might be at the module level
// and not have a MachineFunction to initialize the TargetInstrInfo from and
// we only need MCInstrInfo for asm parsing. We create one unconditionally

View File

@ -40,14 +40,7 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context,
MCObjectStreamer::~MCObjectStreamer() = default;
// AssemblerPtr is used for evaluation of expressions and causes
// difference between asm and object outputs. Return nullptr to in
// inline asm mode to limit divergence to assembly inputs.
MCAssembler *MCObjectStreamer::getAssemblerPtr() {
if (getUseAssemblerInfoForParsing())
return Assembler.get();
return nullptr;
}
MCAssembler *MCObjectStreamer::getAssemblerPtr() { return Assembler.get(); }
void MCObjectStreamer::addPendingLabel(MCSymbol* S) {
MCSection *CurSection = getCurrentSectionOnly();

View File

@ -93,7 +93,7 @@ void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
MCStreamer::MCStreamer(MCContext &Ctx)
: Context(Ctx), CurrentWinFrameInfo(nullptr),
CurrentProcWinFrameInfoStartIndex(0), UseAssemblerInfoForParsing(false) {
CurrentProcWinFrameInfoStartIndex(0) {
SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
}

View File

@ -517,12 +517,9 @@ bool AMDGPUAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
DumpCodeInstEmitter = nullptr;
if (STM.dumpCode()) {
// For -dumpcode, get the assembler out of the streamer, even if it does
// not really want to let us have it. This only works with -filetype=obj.
bool SaveFlag = OutStreamer->getUseAssemblerInfoForParsing();
OutStreamer->setUseAssemblerInfoForParsing(true);
// For -dumpcode, get the assembler out of the streamer. This only works
// with -filetype=obj.
MCAssembler *Assembler = OutStreamer->getAssemblerPtr();
OutStreamer->setUseAssemblerInfoForParsing(SaveFlag);
if (Assembler)
DumpCodeInstEmitter = Assembler->getEmitterPtr();
}

View File

@ -114,12 +114,9 @@ void SPIRVAsmPrinter::emitEndOfAsmFile(Module &M) {
// Bound is an approximation that accounts for the maximum used register
// number and number of generated OpLabels
unsigned Bound = 2 * (ST->getBound() + 1) + NLabels;
bool FlagToRestore = OutStreamer->getUseAssemblerInfoForParsing();
OutStreamer->setUseAssemblerInfoForParsing(true);
if (MCAssembler *Asm = OutStreamer->getAssemblerPtr())
Asm->setBuildVersion(static_cast<MachO::PlatformType>(0), Major, Minor,
Bound, VersionTuple(Major, Minor, 0, Bound));
OutStreamer->setUseAssemblerInfoForParsing(FlagToRestore);
}
void SPIRVAsmPrinter::emitFunctionHeader() {

View File

@ -1,13 +1,17 @@
; RUN: not llc -mtriple x86_64-unknown-linux-gnu -o %t.s -filetype=asm %s 2>&1 | FileCheck %s
; RUN: not llc -mtriple x86_64-unknown-linux-gnu -o %t.o -filetype=obj %s 2>&1 | FileCheck %s
; Assembler-aware expression evaluation should be disabled in inline
; assembly to prevent differences in behavior between object and
; assembly output.
; RUN: not llc -mtriple=x86_64 %s -o /dev/null 2>&1 | FileCheck %s
; RUN: llc -mtriple=x86_64 -no-integrated-as < %s | FileCheck %s --check-prefix=GAS
; RUN: llc -mtriple=x86_64 -filetype=obj %s -o - | llvm-objdump -d - | FileCheck %s --check-prefix=DISASM
; GAS: nop; .if . - foo==1; nop;.endif
; CHECK: <inline asm>:1:17: error: expected absolute expression
; DISASM: <main>:
; DISASM-NEXT: nop
; DISASM-NEXT: nop
; DISASM-NEXT: xorl %eax, %eax
; DISASM-NEXT: retq
define i32 @main() local_unnamed_addr {
tail call void asm sideeffect "foo: nop; .if . - foo==1; nop;.endif", "~{dirflag},~{fpsr},~{flags}"()
ret i32 0

View File

@ -569,9 +569,6 @@ int main(int argc, char **argv) {
Str->initSections(true, *STI);
}
// Use Assembler information for parsing.
Str->setUseAssemblerInfoForParsing(true);
int Res = 1;
bool disassemble = false;
switch (Action) {

View File

@ -428,9 +428,6 @@ int llvm_ml_main(int Argc, char **Argv, const llvm::ToolContext &) {
Str->emitAssignment(Feat00Sym, MCConstantExpr::create(Feat00Flags, Ctx));
}
// Use Assembler information for parsing.
Str->setUseAssemblerInfoForParsing(true);
int Res = 1;
if (InputArgs.hasArg(OPT_as_lex)) {
// -as-lex; Lex only, and output a stream of tokens