/// 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
/// @{
uint8_t getValue() const { return Value; }
+ SMLoc getLoc() const { return Loc; }
+
/// @}
static bool classof(const MCFragment *F) {
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,
/// \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);
/// @}
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,
}
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);
case MCFragment::FT_Org: {
const MCOrgFragment &OF = cast<MCOrgFragment>(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;
}
// 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";
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);
}
}
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
/// ::= .org expression [ , expression ]
bool AsmParser::parseDirectiveOrg() {
const MCExpr *Offset;
+ SMLoc OffsetLoc = Lexer.getLoc();
if (checkForValidSection() || parseExpression(Offset))
return true;
if (parseToken(AsmToken::EndOfStatement))
return addErrorSuffix(" in '.org' directive");
- getStreamer().emitValueToOffset(Offset, FillExpr);
+ getStreamer().emitValueToOffset(Offset, FillExpr, OffsetLoc);
return false;
}
"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);
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() {}
--- /dev/null
+// 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
--- /dev/null
+// 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: <unknown>:0: error: expression could not be evaluated
+ .set v1, -undef
+
+ .comm common, 4
+// CHECK: <unknown>:0: error: Common symbol 'common' cannot be used in assignment expr
+ .set v3, common
+
+// CHECK: <unknown>:0: error: symbol 'undef' could not be evaluated in a subtraction expression
+ .set v2, a-undef
// CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: invalid fixup for 32-bit load/store instruction
ldr w0, [x1, :gottprel_lo12:undef]
-// CHECK: <unknown>:0: error: expression could not be evaluated
- .set v1, -undef
-
- .comm common, 4
-// CHECK: <unknown>:0: error: Common symbol 'common' cannot be used in assignment expr
- .set v3, common
-
-// CHECK: <unknown>:0: error: symbol 'undef' could not be evaluated in a subtraction expression
- .set v2, a-undef
-
w:
--- /dev/null
+@ 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: <unknown>:0: error: expression could not be evaluated
+ .set v1, -undef
+
+ .comm common, 4
+@ CHECK: <unknown>:0: error: Common symbol 'common' cannot be used in assignment expr
+ .set v3, common
+
+@ CHECK: <unknown>:0: error: symbol 'undef' could not be evaluated in a subtraction expression
+ .set v2, a-undef
@ CHECK: :[[@LINE+1]]:{{[0-9]+}}: error: Cannot represent a difference across sections
.word x_a - y_a
-@ CHECK: <unknown>:0: error: expression could not be evaluated
- .set v1, -undef
-
- .comm common, 4
-@ CHECK: <unknown>:0: error: Common symbol 'common' cannot be used in assignment expr
- .set v3, common
-
-@ CHECK: <unknown>:0: error: symbol 'undef' could not be evaluated in a subtraction expression
- .set v2, a-undef
-
w:
. = . + 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