Index: llvm/trunk/include/llvm/MC/MCFragment.h =================================================================== --- llvm/trunk/include/llvm/MC/MCFragment.h +++ llvm/trunk/include/llvm/MC/MCFragment.h @@ -346,9 +346,13 @@ /// Value - Value to use for filling bytes. int8_t Value; + /// Loc - Source location of the directive that this fragment was created for. + SMLoc Loc; + public: - MCOrgFragment(const MCExpr &Offset, int8_t Value, MCSection *Sec = nullptr) - : MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value) {} + MCOrgFragment(const MCExpr &Offset, int8_t Value, SMLoc Loc, + MCSection *Sec = nullptr) + : MCFragment(FT_Org, false, 0, Sec), Offset(&Offset), Value(Value), Loc(Loc) {} /// \name Accessors /// @{ @@ -357,6 +361,8 @@ uint8_t getValue() const { return Value; } + SMLoc getLoc() const { return Loc; } + /// @} static bool classof(const MCFragment *F) { Index: llvm/trunk/include/llvm/MC/MCObjectStreamer.h =================================================================== --- llvm/trunk/include/llvm/MC/MCObjectStreamer.h +++ llvm/trunk/include/llvm/MC/MCObjectStreamer.h @@ -112,7 +112,8 @@ unsigned MaxBytesToEmit = 0) override; void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0) override; - void emitValueToOffset(const MCExpr *Offset, unsigned char Value) override; + void emitValueToOffset(const MCExpr *Offset, unsigned char Value, + SMLoc Loc) override; void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, unsigned Column, unsigned Flags, unsigned Isa, unsigned Discriminator, Index: llvm/trunk/include/llvm/MC/MCStreamer.h =================================================================== --- llvm/trunk/include/llvm/MC/MCStreamer.h +++ llvm/trunk/include/llvm/MC/MCStreamer.h @@ -684,7 +684,8 @@ /// \param Offset - The offset to reach. This may be an expression, but the /// expression must be associated with the current section. /// \param Value - The value to use when filling bytes. - virtual void emitValueToOffset(const MCExpr *Offset, unsigned char Value = 0); + virtual void emitValueToOffset(const MCExpr *Offset, unsigned char Value, + SMLoc Loc); /// @} Index: llvm/trunk/lib/MC/MCAsmStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCAsmStreamer.cpp +++ llvm/trunk/lib/MC/MCAsmStreamer.cpp @@ -209,7 +209,8 @@ unsigned MaxBytesToEmit = 0) override; void emitValueToOffset(const MCExpr *Offset, - unsigned char Value = 0) override; + unsigned char Value, + SMLoc Loc) override; void EmitFileDirective(StringRef Filename) override; unsigned EmitDwarfFileDirective(unsigned FileNo, StringRef Directory, @@ -1011,7 +1012,8 @@ } void MCAsmStreamer::emitValueToOffset(const MCExpr *Offset, - unsigned char Value) { + unsigned char Value, + SMLoc Loc) { // FIXME: Verify that Offset is associated with the current section. OS << ".org "; Offset->print(OS, MAI); Index: llvm/trunk/lib/MC/MCAssembler.cpp =================================================================== --- llvm/trunk/lib/MC/MCAssembler.cpp +++ llvm/trunk/lib/MC/MCAssembler.cpp @@ -278,22 +278,29 @@ case MCFragment::FT_Org: { const MCOrgFragment &OF = cast(F); MCValue Value; - if (!OF.getOffset().evaluateAsValue(Value, Layout)) - report_fatal_error("expected assembly-time absolute expression"); + if (!OF.getOffset().evaluateAsValue(Value, Layout)) { + getContext().reportError(OF.getLoc(), + "expected assembly-time absolute expression"); + return 0; + } - // FIXME: We need a way to communicate this error. uint64_t FragmentOffset = Layout.getFragmentOffset(&OF); int64_t TargetLocation = Value.getConstant(); if (const MCSymbolRefExpr *A = Value.getSymA()) { uint64_t Val; - if (!Layout.getSymbolOffset(A->getSymbol(), Val)) - report_fatal_error("expected absolute expression"); + if (!Layout.getSymbolOffset(A->getSymbol(), Val)) { + getContext().reportError(OF.getLoc(), "expected absolute expression"); + return 0; + } TargetLocation += Val; } int64_t Size = TargetLocation - FragmentOffset; - if (Size < 0 || Size >= 0x40000000) - report_fatal_error("invalid .org offset '" + Twine(TargetLocation) + - "' (at offset '" + Twine(FragmentOffset) + "')"); + if (Size < 0 || Size >= 0x40000000) { + getContext().reportError( + OF.getLoc(), "invalid .org offset '" + Twine(TargetLocation) + + "' (at offset '" + Twine(FragmentOffset) + "')"); + return 0; + } return Size; } @@ -660,7 +667,8 @@ // Layout until everything fits. while (layoutOnce(Layout)) - continue; + if (getContext().hadError()) + return; DEBUG_WITH_TYPE("mc-dump", { llvm::errs() << "assembler backend - post-relaxation\n--\n"; @@ -912,7 +920,9 @@ void MCAssembler::finishLayout(MCAsmLayout &Layout) { // The layout is done. Mark every fragment as valid. for (unsigned int i = 0, n = Layout.getSectionOrder().size(); i != n; ++i) { - Layout.getFragmentOffset(&*Layout.getSectionOrder()[i]->rbegin()); + MCSection &Section = *Layout.getSectionOrder()[i]; + Layout.getFragmentOffset(&*Section.rbegin()); + computeFragmentSize(Layout, *Section.rbegin()); } getBackend().finishLayout(*this, Layout); } Index: llvm/trunk/lib/MC/MCObjectStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCObjectStreamer.cpp +++ llvm/trunk/lib/MC/MCObjectStreamer.cpp @@ -440,8 +440,9 @@ } void MCObjectStreamer::emitValueToOffset(const MCExpr *Offset, - unsigned char Value) { - insert(new MCOrgFragment(*Offset, Value)); + unsigned char Value, + SMLoc Loc) { + insert(new MCOrgFragment(*Offset, Value, Loc)); } // Associate DTPRel32 fixup with data and resize data area Index: llvm/trunk/lib/MC/MCParser/AsmParser.cpp =================================================================== --- llvm/trunk/lib/MC/MCParser/AsmParser.cpp +++ llvm/trunk/lib/MC/MCParser/AsmParser.cpp @@ -2965,6 +2965,7 @@ /// ::= .org expression [ , expression ] bool AsmParser::parseDirectiveOrg() { const MCExpr *Offset; + SMLoc OffsetLoc = Lexer.getLoc(); if (checkForValidSection() || parseExpression(Offset)) return true; @@ -2976,7 +2977,7 @@ if (parseToken(AsmToken::EndOfStatement)) return addErrorSuffix(" in '.org' directive"); - getStreamer().emitValueToOffset(Offset, FillExpr); + getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc); return false; } @@ -5502,7 +5503,7 @@ "invalid reassignment of non-absolute variable '" + Name + "'"); } else if (Name == ".") { - Parser.getStreamer().emitValueToOffset(Value, 0); + Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc); return false; } else Sym = Parser.getContext().getOrCreateSymbol(Name); Index: llvm/trunk/lib/MC/MCStreamer.cpp =================================================================== --- llvm/trunk/lib/MC/MCStreamer.cpp +++ llvm/trunk/lib/MC/MCStreamer.cpp @@ -820,7 +820,8 @@ unsigned MaxBytesToEmit) {} void MCStreamer::EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit) {} -void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value) {} +void MCStreamer::emitValueToOffset(const MCExpr *Offset, unsigned char Value, + SMLoc Loc) {} void MCStreamer::EmitBundleAlignMode(unsigned AlignPow2) {} void MCStreamer::EmitBundleLock(bool AlignToEnd) {} void MCStreamer::FinishImpl() {} Index: llvm/trunk/test/MC/AArch64/error-location-during-layout.s =================================================================== --- llvm/trunk/test/MC/AArch64/error-location-during-layout.s +++ llvm/trunk/test/MC/AArch64/error-location-during-layout.s @@ -0,0 +1,14 @@ +// RUN: not llvm-mc -triple aarch64--none-eabi -filetype obj < %s -o /dev/null 2>&1 | FileCheck %s + + .section a + .space 8 +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: invalid .org offset '4' (at offset '8') + .org 4 + + .section b +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: expected absolute expression + .org undef + + .section c +// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: expected assembly-time absolute expression + .org -undef Index: llvm/trunk/test/MC/AArch64/error-location-post-layout.s =================================================================== --- llvm/trunk/test/MC/AArch64/error-location-post-layout.s +++ llvm/trunk/test/MC/AArch64/error-location-post-layout.s @@ -0,0 +1,14 @@ +// RUN: not llvm-mc -triple aarch64--none-eabi -filetype obj < %s -o /dev/null 2>&1 | FileCheck %s + +// Note: These errors are not always emitted in the order in which the relevant +// source appears, this file is carefully ordered so that that is the case. + +// CHECK: :0: error: expression could not be evaluated + .set v1, -undef + + .comm common, 4 +// CHECK: :0: error: Common symbol 'common' cannot be used in assignment expr + .set v3, common + +// CHECK: :0: error: symbol 'undef' could not be evaluated in a subtraction expression + .set v2, a-undef Index: llvm/trunk/test/MC/AArch64/error-location.s =================================================================== --- llvm/trunk/test/MC/AArch64/error-location.s +++ llvm/trunk/test/MC/AArch64/error-location.s @@ -34,16 +34,6 @@ // CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: invalid fixup for 32-bit load/store instruction ldr w0, [x1, :gottprel_lo12:undef] -// CHECK: :0: error: expression could not be evaluated - .set v1, -undef - - .comm common, 4 -// CHECK: :0: error: Common symbol 'common' cannot be used in assignment expr - .set v3, common - -// CHECK: :0: error: symbol 'undef' could not be evaluated in a subtraction expression - .set v2, a-undef - w: Index: llvm/trunk/test/MC/ARM/error-location-post-layout.s =================================================================== --- llvm/trunk/test/MC/ARM/error-location-post-layout.s +++ llvm/trunk/test/MC/ARM/error-location-post-layout.s @@ -0,0 +1,14 @@ +@ RUN: not llvm-mc -triple armv7a--none-eabi -filetype obj < %s -o /dev/null 2>&1 | FileCheck %s + +@ Note: These errors are not always emitted in the order in which the relevant +@ source appears, this file is carefully ordered so that that is the case. + +@ CHECK: :0: error: expression could not be evaluated + .set v1, -undef + + .comm common, 4 +@ CHECK: :0: error: Common symbol 'common' cannot be used in assignment expr + .set v3, common + +@ CHECK: :0: error: symbol 'undef' could not be evaluated in a subtraction expression + .set v2, a-undef Index: llvm/trunk/test/MC/ARM/error-location.s =================================================================== --- llvm/trunk/test/MC/ARM/error-location.s +++ llvm/trunk/test/MC/ARM/error-location.s @@ -16,16 +16,6 @@ @ CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Cannot represent a difference across sections .word x_a - y_a -@ CHECK: :0: error: expression could not be evaluated - .set v1, -undef - - .comm common, 4 -@ CHECK: :0: error: Common symbol 'common' cannot be used in assignment expr - .set v3, common - -@ CHECK: :0: error: symbol 'undef' could not be evaluated in a subtraction expression - .set v2, a-undef - w: Index: llvm/trunk/test/MC/AsmParser/dot-symbol-assignment-backwards.s =================================================================== --- llvm/trunk/test/MC/AsmParser/dot-symbol-assignment-backwards.s +++ llvm/trunk/test/MC/AsmParser/dot-symbol-assignment-backwards.s @@ -7,6 +7,6 @@ . = . + 10 .byte 2 -# CHECK: LLVM ERROR: invalid .org offset '24' (at offset '28') +# CHECK: error: invalid .org offset '24' (at offset '28') . = 0x18 .byte 3