Skip to content

Commit 6c0665e

Browse files
committed
[MC] Change AsmParser to leverage Assembler during evaluation
Teach AsmParser to check with Assembler for when evaluating constant expressions. This improves the handing of preprocessor expressions that must be resolved at parse time. This idiom can be found as assembling-time assertion checks in source-level assemblers. Note that this relies on the MCStreamer to keep sufficient tabs on Section / Fragment information which the MCAsmStreamer does not. As a result the textual output may fail where the equivalent object generation would pass. This can most easily be resolved by folding the MCAsmStreamer and MCObjectStreamer together which is planned for in a separate patch. Currently, this feature is only enabled for assembly input, keeping IR compilation consistent between assembly and object generation. Reviewers: echristo, rnk, probinson, espindola, peter.smith Reviewed By: peter.smith Subscribers: eraman, peter.smith, arichardson, jyknight, hiraditya, llvm-commits Differential Revision: https://reviews.llvm.org/D45164 llvm-svn: 331218
1 parent 8fe04ad commit 6c0665e

File tree

17 files changed

+153
-23
lines changed

17 files changed

+153
-23
lines changed

clang/test/CodeGen/asm-parser-info.S

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// REQUIRES: x86-registered-target
2+
// RUN: %clang --target=x86_64-unknown-linux-gnu -c %s -o /dev/null
3+
4+
// Check that cc1as can use assembler info in object generation.
5+
.data
6+
7+
foo:
8+
.if . - foo == 0
9+
.byte 0xaa
10+
.else
11+
.byte 0x00
12+
.endif

clang/tools/driver/cc1as_main.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,9 @@ static bool ExecuteAssembler(AssemblerInvocation &Opts,
435435
Str.get()->InitSections(Opts.NoExecStack);
436436
}
437437

438+
// Assembly to object compilation should leverage assembly info.
439+
Str->setUseAssemblerInfoForParsing(true);
440+
438441
bool Failed = false;
439442

440443
std::unique_ptr<MCAsmParser> Parser(

llvm/include/llvm/MC/MCExpr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ class MCExpr {
9696
const SectionAddrMap &Addrs) const;
9797
bool evaluateAsAbsolute(int64_t &Res) const;
9898
bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
99+
bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const;
99100
bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
100101

101102
bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;

llvm/include/llvm/MC/MCObjectStreamer.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ class MCObjectStreamer : public MCStreamer {
8989
void visitUsedSymbol(const MCSymbol &Sym) override;
9090

9191
MCAssembler &getAssembler() { return *Assembler; }
92-
92+
MCAssembler *getAssemblerPtr() override;
9393
/// \name MCStreamer Interface
9494
/// @{
9595

llvm/include/llvm/MC/MCStreamer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ class MCStreamer {
211211
/// requires.
212212
unsigned NextWinCFIID = 0;
213213

214+
bool UseAssemblerInfoForParsing;
215+
214216
protected:
215217
MCStreamer(MCContext &Ctx);
216218

@@ -247,6 +249,11 @@ class MCStreamer {
247249

248250
MCContext &getContext() const { return Context; }
249251

252+
virtual MCAssembler *getAssemblerPtr() { return nullptr; }
253+
254+
void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; }
255+
bool getUseAssemblerInfoForParsing() { return UseAssemblerInfoForParsing; }
256+
250257
MCTargetStreamer *getTargetStreamer() {
251258
return TargetStreamer.get();
252259
}

llvm/include/llvm/MC/MCSymbol.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,8 @@ class MCSymbol {
316316
Index = Value;
317317
}
318318

319+
bool isUnset() const { return SymbolContents == SymContentsUnset; }
320+
319321
uint64_t getOffset() const {
320322
assert((SymbolContents == SymContentsUnset ||
321323
SymbolContents == SymContentsOffset) &&

llvm/lib/CodeGen/AsmPrinter/AsmPrinterInlineAsm.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ void AsmPrinter::EmitInlineAsm(StringRef Str, const MCSubtargetInfo &STI,
132132
std::unique_ptr<MCAsmParser> Parser(
133133
createMCAsmParser(SrcMgr, OutContext, *OutStreamer, *MAI, BufNum));
134134

135+
// Do not use assembler-level information for parsing inline assembly.
136+
OutStreamer->setUseAssemblerInfoForParsing(false);
137+
135138
// We create a new MCInstrInfo here since we might be at the module level
136139
// and not have a MachineFunction to initialize the TargetInstrInfo from and
137140
// we only need MCInstrInfo for asm parsing. We create one unconditionally

llvm/lib/MC/MCAsmStreamer.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ class MCAsmStreamer final : public MCStreamer {
7878
InstPrinter->setCommentStream(CommentStream);
7979
}
8080

81+
MCAssembler &getAssembler() { return *Assembler; }
82+
MCAssembler *getAssemblerPtr() override { return nullptr; }
83+
8184
inline void EmitEOL() {
8285
// Dump Explicit Comments here.
8386
emitExplicitComments();
@@ -1656,10 +1659,10 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
16561659
raw_svector_ostream VecOS(Code);
16571660

16581661
// If we have no code emitter, don't emit code.
1659-
if (!Assembler->getEmitterPtr())
1662+
if (!getAssembler().getEmitterPtr())
16601663
return;
16611664

1662-
Assembler->getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
1665+
getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
16631666

16641667
// If we are showing fixups, create symbolic markers in the encoded
16651668
// representation. We do this by making a per-bit map to the fixup item index,
@@ -1672,7 +1675,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
16721675
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
16731676
MCFixup &F = Fixups[i];
16741677
const MCFixupKindInfo &Info =
1675-
Assembler->getBackend().getFixupKindInfo(F.getKind());
1678+
getAssembler().getBackend().getFixupKindInfo(F.getKind());
16761679
for (unsigned j = 0; j != Info.TargetSize; ++j) {
16771680
unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
16781681
assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
@@ -1737,7 +1740,7 @@ void MCAsmStreamer::AddEncodingComment(const MCInst &Inst,
17371740
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
17381741
MCFixup &F = Fixups[i];
17391742
const MCFixupKindInfo &Info =
1740-
Assembler->getBackend().getFixupKindInfo(F.getKind());
1743+
getAssembler().getBackend().getFixupKindInfo(F.getKind());
17411744
OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
17421745
<< ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
17431746
}

llvm/lib/MC/MCExpr.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,10 @@ bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const {
441441
return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr);
442442
}
443443

444+
bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {
445+
return evaluateAsAbsolute(Res, Asm, nullptr, nullptr);
446+
}
447+
444448
bool MCExpr::evaluateKnownAbsolute(int64_t &Res,
445449
const MCAsmLayout &Layout) const {
446450
return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr,
@@ -494,7 +498,7 @@ static void AttemptToFoldSymbolOffsetDifference(
494498
return;
495499

496500
if (SA.getFragment() == SB.getFragment() && !SA.isVariable() &&
497-
!SB.isVariable()) {
501+
!SA.isUnset() && !SB.isVariable() && !SB.isUnset()) {
498502
Addend += (SA.getOffset() - SB.getOffset());
499503

500504
// Pointers to Thumb symbols need to have their low-bit set to allow

llvm/lib/MC/MCObjectStreamer.cpp

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@ MCObjectStreamer::MCObjectStreamer(MCContext &Context,
3535

3636
MCObjectStreamer::~MCObjectStreamer() {}
3737

38+
// AssemblerPtr is used for evaluation of expressions and causes
39+
// difference between asm and object outputs. Return nullptr to in
40+
// inline asm mode to limit divergence to assembly inputs.
41+
MCAssembler *MCObjectStreamer::getAssemblerPtr() {
42+
if (getUseAssemblerInfoForParsing())
43+
return Assembler.get();
44+
return nullptr;
45+
}
46+
3847
void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
3948
if (PendingLabels.empty())
4049
return;
@@ -155,7 +164,7 @@ void MCObjectStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size,
155164

156165
// Avoid fixups when possible.
157166
int64_t AbsValue;
158-
if (Value->evaluateAsAbsolute(AbsValue, getAssembler())) {
167+
if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
159168
if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
160169
getContext().reportError(
161170
Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
@@ -217,7 +226,7 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc, MCFragment *F) {
217226

218227
void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
219228
int64_t IntValue;
220-
if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
229+
if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
221230
EmitULEB128IntValue(IntValue);
222231
return;
223232
}
@@ -226,7 +235,7 @@ void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
226235

227236
void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) {
228237
int64_t IntValue;
229-
if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
238+
if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
230239
EmitSLEB128IntValue(IntValue);
231240
return;
232241
}
@@ -254,7 +263,7 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
254263

255264
int64_t IntSubsection = 0;
256265
if (Subsection &&
257-
!Subsection->evaluateAsAbsolute(IntSubsection, getAssembler()))
266+
!Subsection->evaluateAsAbsolute(IntSubsection, getAssemblerPtr()))
258267
report_fatal_error("Cannot evaluate subsection number");
259268
if (IntSubsection < 0 || IntSubsection > 8192)
260269
report_fatal_error("Subsection number out of range");
@@ -400,7 +409,7 @@ void MCObjectStreamer::EmitDwarfAdvanceLineAddr(int64_t LineDelta,
400409
}
401410
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
402411
int64_t Res;
403-
if (AddrDelta->evaluateAsAbsolute(Res, getAssembler())) {
412+
if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
404413
MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta,
405414
Res);
406415
return;
@@ -412,7 +421,7 @@ void MCObjectStreamer::EmitDwarfAdvanceFrameAddr(const MCSymbol *LastLabel,
412421
const MCSymbol *Label) {
413422
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
414423
int64_t Res;
415-
if (AddrDelta->evaluateAsAbsolute(Res, getAssembler())) {
424+
if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
416425
MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);
417426
return;
418427
}
@@ -608,7 +617,7 @@ void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue,
608617
void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
609618
int64_t Expr, SMLoc Loc) {
610619
int64_t IntNumValues;
611-
if (!NumValues.evaluateAsAbsolute(IntNumValues, getAssembler())) {
620+
if (!NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {
612621
getContext().reportError(Loc, "expected absolute expression");
613622
return;
614623
}

0 commit comments

Comments
 (0)