const SectionAddrMap &Addrs) const;
bool evaluateAsAbsolute(int64_t &Res) const;
bool evaluateAsAbsolute(int64_t &Res, const MCAssembler &Asm) const;
+ bool evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const;
bool evaluateAsAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
bool evaluateKnownAbsolute(int64_t &Res, const MCAsmLayout &Layout) const;
void visitUsedSymbol(const MCSymbol &Sym) override;
MCAssembler &getAssembler() { return *Assembler; }
-
+ MCAssembler *getAssemblerPtr() override;
/// \name MCStreamer Interface
/// @{
/// requires.
unsigned NextWinCFIID = 0;
+ bool UseAssemblerInfoForParsing;
+
protected:
MCStreamer(MCContext &Ctx);
MCContext &getContext() const { return Context; }
+ virtual MCAssembler *getAssemblerPtr() { return nullptr; }
+
+ void setUseAssemblerInfoForParsing(bool v) { UseAssemblerInfoForParsing = v; }
+ bool getUseAssemblerInfoForParsing() { return UseAssemblerInfoForParsing; }
+
MCTargetStreamer *getTargetStreamer() {
return TargetStreamer.get();
}
Index = Value;
}
+ bool isUnset() const { return SymbolContents == SymContentsUnset; }
+
uint64_t getOffset() const {
assert((SymbolContents == SymContentsUnset ||
SymbolContents == SymContentsOffset) &&
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
InstPrinter->setCommentStream(CommentStream);
}
+ MCAssembler &getAssembler() { return *Assembler; }
+ MCAssembler *getAssemblerPtr() override { return Assembler.get(); }
+
inline void EmitEOL() {
// Dump Explicit Comments here.
emitExplicitComments();
raw_svector_ostream VecOS(Code);
// If we have no code emitter, don't emit code.
- if (!Assembler->getEmitterPtr())
+ if (!getAssembler().getEmitterPtr())
return;
- Assembler->getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
+ getAssembler().getEmitter().encodeInstruction(Inst, VecOS, Fixups, STI);
// If we are showing fixups, create symbolic markers in the encoded
// representation. We do this by making a per-bit map to the fixup item index,
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
MCFixup &F = Fixups[i];
const MCFixupKindInfo &Info =
- Assembler->getBackend().getFixupKindInfo(F.getKind());
+ getAssembler().getBackend().getFixupKindInfo(F.getKind());
for (unsigned j = 0; j != Info.TargetSize; ++j) {
unsigned Index = F.getOffset() * 8 + Info.TargetOffset + j;
assert(Index < Code.size() * 8 && "Invalid offset in fixup!");
for (unsigned i = 0, e = Fixups.size(); i != e; ++i) {
MCFixup &F = Fixups[i];
const MCFixupKindInfo &Info =
- Assembler->getBackend().getFixupKindInfo(F.getKind());
+ getAssembler().getBackend().getFixupKindInfo(F.getKind());
OS << " fixup " << char('A' + i) << " - " << "offset: " << F.getOffset()
<< ", value: " << *F.getValue() << ", kind: " << Info.Name << "\n";
}
bool IsPCRel = getBackendPtr()->getFixupKindInfo(Fixup.getKind()).Flags &
MCFixupKindInfo::FKF_IsPCRel;
- bool IsResolved;
+ bool IsResolved = false;
if (IsPCRel) {
if (Target.getSymB()) {
IsResolved = false;
return evaluateAsAbsolute(Res, &Asm, nullptr, nullptr);
}
+bool MCExpr::evaluateAsAbsolute(int64_t &Res, const MCAssembler *Asm) const {
+ return evaluateAsAbsolute(Res, Asm, nullptr, nullptr);
+}
+
bool MCExpr::evaluateKnownAbsolute(int64_t &Res,
const MCAsmLayout &Layout) const {
return evaluateAsAbsolute(Res, &Layout.getAssembler(), &Layout, nullptr,
return;
if (SA.getFragment() == SB.getFragment() && !SA.isVariable() &&
- !SB.isVariable()) {
+ !SA.isUnset() && !SB.isVariable() && !SB.isUnset()) {
Addend += (SA.getOffset() - SB.getOffset());
// Pointers to Thumb symbols need to have their low-bit set to allow
MCObjectStreamer::~MCObjectStreamer() {}
+// 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;
+}
+
void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
if (PendingLabels.empty())
return;
// Avoid fixups when possible.
int64_t AbsValue;
- if (Value->evaluateAsAbsolute(AbsValue, getAssembler())) {
+ if (Value->evaluateAsAbsolute(AbsValue, getAssemblerPtr())) {
if (!isUIntN(8 * Size, AbsValue) && !isIntN(8 * Size, AbsValue)) {
getContext().reportError(
Loc, "value evaluated as " + Twine(AbsValue) + " is out of range.");
void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) {
int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
+ if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
EmitULEB128IntValue(IntValue);
return;
}
void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value) {
int64_t IntValue;
- if (Value->evaluateAsAbsolute(IntValue, getAssembler())) {
+ if (Value->evaluateAsAbsolute(IntValue, getAssemblerPtr())) {
EmitSLEB128IntValue(IntValue);
return;
}
int64_t IntSubsection = 0;
if (Subsection &&
- !Subsection->evaluateAsAbsolute(IntSubsection, getAssembler()))
+ !Subsection->evaluateAsAbsolute(IntSubsection, getAssemblerPtr()))
report_fatal_error("Cannot evaluate subsection number");
if (IntSubsection < 0 || IntSubsection > 8192)
report_fatal_error("Subsection number out of range");
}
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
int64_t Res;
- if (AddrDelta->evaluateAsAbsolute(Res, getAssembler())) {
+ if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
MCDwarfLineAddr::Emit(this, Assembler->getDWARFLinetableParams(), LineDelta,
Res);
return;
const MCSymbol *Label) {
const MCExpr *AddrDelta = buildSymbolDiff(*this, Label, LastLabel);
int64_t Res;
- if (AddrDelta->evaluateAsAbsolute(Res, getAssembler())) {
+ if (AddrDelta->evaluateAsAbsolute(Res, getAssemblerPtr())) {
MCDwarfFrameEmitter::EmitAdvanceLoc(*this, Res);
return;
}
void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size,
int64_t Expr, SMLoc Loc) {
int64_t IntNumValues;
- if (!NumValues.evaluateAsAbsolute(IntNumValues, getAssembler())) {
+ if (!NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) {
getContext().reportError(Loc, "expected absolute expression");
return;
}
Bytes = Bytes.drop_front(Skip);
if (Count) {
int64_t Res;
- if (!Count->evaluateAsAbsolute(Res))
+ if (!Count->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
return Error(Loc, "expected absolute expression");
if (Res < 0)
return Warning(Loc, "negative count has no effect");
Lex();
}
- // Try to constant fold it up front, if possible.
+ // Try to constant fold it up front, if possible. Do not exploit
+ // assembler here.
int64_t Value;
if (Res->evaluateAsAbsolute(Value))
Res = MCConstantExpr::create(Value, getContext());
if (parseExpression(Expr))
return true;
- if (!Expr->evaluateAsAbsolute(Res))
+ if (!Expr->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
return Error(StartLoc, "expected absolute expression");
return false;
Lex();
if (parseExpression(AbsoluteExp, EndLoc))
return false;
- if (!AbsoluteExp->evaluateAsAbsolute(Value))
+ if (!AbsoluteExp->evaluateAsAbsolute(Value,
+ getStreamer().getAssemblerPtr()))
return Error(StrLoc, "expected absolute expression");
const char *StrChar = StrLoc.getPointer();
const char *EndChar = EndLoc.getPointer();
if (parseExpression(Offset))
return true;
- if (check(!Offset->evaluateAsAbsolute(OffsetValue), OffsetLoc,
- "expression is not a constant value") ||
+ if (check(!Offset->evaluateAsAbsolute(OffsetValue,
+ getStreamer().getAssemblerPtr()),
+ OffsetLoc, "expression is not a constant value") ||
check(OffsetValue < 0, OffsetLoc, "expression is negative") ||
parseToken(AsmToken::Comma, "expected comma") ||
check(getTok().isNot(AsmToken::Identifier), "expected relocation name"))
return true;
int64_t Count;
- if (!CountExpr->evaluateAsAbsolute(Count)) {
+ if (!CountExpr->evaluateAsAbsolute(Count, getStreamer().getAssemblerPtr())) {
return Error(CountLoc, "unexpected token in '" + Dir + "' directive");
}
void MCTargetStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {}
MCStreamer::MCStreamer(MCContext &Ctx)
- : Context(Ctx), CurrentWinFrameInfo(nullptr) {
+ : Context(Ctx), CurrentWinFrameInfo(nullptr),
+ UseAssemblerInfoForParsing(false) {
SectionStack.push_back(std::pair<MCSectionSubPair, MCSectionSubPair>());
}
--- /dev/null
+# RUN: not llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=ERR
+# RUN: not llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=ERR
+
+.text
+
+test2:
+ jmp baz
+# ERR: [[@LINE+1]]:5: error: expected absolute expression
+.if . - text2 == 1
+ nop
+.else
+ ret
+.endif
+ push fs
+
+# No additional errors.
+#
+# ERR-NOT: {{[0-9]+}}:{{[0-9]+}}: error:
--- /dev/null
+; 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.
+
+
+; CHECK: <inline asm>:1:17: error: expected absolute expression
+
+define i32 @main() local_unnamed_addr {
+ tail call void asm sideeffect "foo: nop; .if . - foo==1; nop;.endif", "~{dirflag},~{fpsr},~{flags}"()
+ ret i32 0
+}
--- /dev/null
+# RUN: not llvm-mc -triple x86_64-unknown-unknown %s 2>&1 | FileCheck %s --check-prefix=ASM-ERR
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s | llvm-objdump -j .data -s - | FileCheck %s --check-prefix=OBJDATA
+# RUN: llvm-mc -filetype=obj -triple x86_64-unknown-unknown %s | llvm-objdump -j .text -s - | FileCheck %s --check-prefix=OBJTEXT
+.data
+
+# OBJDATA: Contents of section .data
+# OBJDATA-NEXT: 0000 aa0506ff
+
+foo2:
+# ASM-ERR: [[@LINE+1]]:5: error: expected absolute expression
+.if . - foo2 == 0
+ .byte 0xaa
+.else
+ .byte 0x00
+.endif
+
+foo3:
+ .byte 5
+# ASM-ERR: [[@LINE+1]]:5: error: expected absolute expression
+.if . - foo3 == 1
+ .byte 6
+.else
+ .byte 7
+.endif
+
+.byte 0xff
+
+# nop is a fixed size instruction so this should pass.
+
+# OBJTEXT: Contents of section .text
+# OBJTEXT-NEXT: 0000 9090ff34 25
+
+.text
+
+text1:
+ nop
+# ASM-ERR: [[@LINE+1]]:5: error: expected absolute expression
+.if . - text1 == 1
+ nop
+.else
+ ret
+.endif
+ push gs
+
+# No additional errors.
+#
+# ASM-ERR-NOT: {{[0-9]+}}:{{[0-9]+}}: error:
# RUN: llvm-mc -triple i386-unknown-unknown %s 2> %t.err | FileCheck %s
# RUN: FileCheck --check-prefix=CHECK-WARNINGS %s < %t.err
-# RUN: llvm-mc -triple i386-unknown-unknown -filetype=obj -o %t.o %s 2> %t.err
-# RUN: FileCheck --check-prefix=OBJ-WARNINGS %s < %t.err
+# RUN: llvm-mc -triple i386-unknown-unknown -filetype=obj -o %t.o %s 2> %t.err2
+# RUN: FileCheck --check-prefix=OBJ-WARNINGS %s < %t.err2
# CHECK: TEST0:
# CHECK: .fill 1, 1, 0xa
Str->InitSections(true);
}
+ // Use Assembler information for parsing.
+ Str->setUseAssemblerInfoForParsing(true);
+
int Res = 1;
bool disassemble = false;
switch (Action) {