bool EmitEHFrame;
bool EmitDebugFrame;
SmallVector<MCSymbol *, 2> PendingLabels;
+ struct PendingMCFixup {
+ const MCSymbol *Sym;
+ MCFixup Fixup;
+ MCDataFragment *DF;
+ PendingMCFixup(const MCSymbol *McSym, MCDataFragment *F, MCFixup McFixup)
+ : Sym(McSym), Fixup(McFixup), DF(F) {}
+ };
+ SmallVector<PendingMCFixup, 2> PendingFixups;
virtual void EmitInstToData(const MCInst &Inst, const MCSubtargetInfo&) = 0;
void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override;
void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override;
MCSymbol *EmitCFILabel() override;
void EmitInstructionImpl(const MCInst &Inst, const MCSubtargetInfo &STI);
+ void resolvePendingFixups();
protected:
MCObjectStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB,
PendingLabels.clear();
}
+// When fixup's offset is a forward declared label, e.g.:
+//
+// .reloc 1f, R_MIPS_JALR, foo
+// 1: nop
+//
+// postpone adding it to Fixups vector until the label is defined and its offset
+// is known.
+void MCObjectStreamer::resolvePendingFixups() {
+ for (PendingMCFixup &PendingFixup : PendingFixups) {
+ if (!PendingFixup.Sym || PendingFixup.Sym->isUndefined ()) {
+ getContext().reportError(PendingFixup.Fixup.getLoc(),
+ "unresolved relocation offset");
+ continue;
+ }
+ flushPendingLabels(PendingFixup.DF, PendingFixup.DF->getContents().size());
+ PendingFixup.Fixup.setOffset(PendingFixup.Sym->getOffset());
+ PendingFixup.DF->getFixups().push_back(PendingFixup.Fixup);
+ }
+ PendingFixups.clear();
+}
+
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
static Optional<uint64_t>
bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name,
const MCExpr *Expr, SMLoc Loc,
const MCSubtargetInfo &STI) {
- int64_t OffsetValue;
- if (!Offset.evaluateAsAbsolute(OffsetValue))
- llvm_unreachable("Offset is not absolute");
-
- if (OffsetValue < 0)
- llvm_unreachable("Offset is negative");
-
- MCDataFragment *DF = getOrCreateDataFragment(&STI);
- flushPendingLabels(DF, DF->getContents().size());
-
Optional<MCFixupKind> MaybeKind = Assembler->getBackend().getFixupKind(Name);
if (!MaybeKind.hasValue())
return true;
if (Expr == nullptr)
Expr =
MCSymbolRefExpr::create(getContext().createTempSymbol(), getContext());
- DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
+
+ MCDataFragment *DF = getOrCreateDataFragment(&STI);
+ flushPendingLabels(DF, DF->getContents().size());
+
+ int64_t OffsetValue;
+ if (Offset.evaluateAsAbsolute(OffsetValue)) {
+ if (OffsetValue < 0)
+ llvm_unreachable(".reloc offset is negative");
+ DF->getFixups().push_back(MCFixup::create(OffsetValue, Expr, Kind, Loc));
+ return false;
+ }
+
+ if (Offset.getKind() != llvm::MCExpr::SymbolRef)
+ llvm_unreachable(".reloc offset is not absolute nor a label");
+
+ const MCSymbolRefExpr &SRE = cast<MCSymbolRefExpr>(Offset);
+ if (SRE.getSymbol().isDefined()) {
+ DF->getFixups().push_back(MCFixup::create(SRE.getSymbol().getOffset(),
+ Expr, Kind, Loc));
+ return false;
+ }
+
+ PendingFixups.emplace_back(&SRE.getSymbol(), DF,
+ MCFixup::create(-1, Expr, Kind, Loc));
return false;
}
MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
flushPendingLabels();
+ resolvePendingFixups();
getAssembler().Finish();
}
bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
const MCExpr *Offset;
const MCExpr *Expr = nullptr;
-
- SMLoc OffsetLoc = Lexer.getTok().getLoc();
int64_t OffsetValue;
- // We can only deal with constant expressions at the moment.
+ SMLoc OffsetLoc = Lexer.getTok().getLoc();
if (parseExpression(Offset))
return true;
- 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"))
+ if ((Offset->evaluateAsAbsolute(OffsetValue,
+ getStreamer().getAssemblerPtr()) &&
+ check(OffsetValue < 0, OffsetLoc, "expression is negative")) ||
+ (check(Offset->getKind() != llvm::MCExpr::Constant &&
+ Offset->getKind() != llvm::MCExpr::SymbolRef,
+ OffsetLoc, "expected non-negative number or a label")) ||
+ (parseToken(AsmToken::Comma, "expected comma") ||
+ check(getTok().isNot(AsmToken::Identifier), "expected relocation name")))
return true;
SMLoc NameLoc = Lexer.getTok().getLoc();
--- /dev/null
+# RUN: not llvm-mc -triple mips-unknown-linux %s -show-encoding \
+# RUN: -target-abi=o32 -filetype=obj 2>&1 | FileCheck %s
+ .text
+ nop
+ .reloc foo, R_MIPS_32, .text # CHECK: :[[@LINE]]:2: error: unresolved relocation offset
+ nop
+ nop
+ .reloc bar, R_MIPS_32, .text # CHECK: :[[@LINE]]:2: error: unresolved relocation offset
+ nop
-# RUN: not llvm-mc -triple mips-unknown-linux < %s -show-encoding -target-abi=o32 \
-# RUN: 2>&1 | FileCheck %s
+# RUN: not llvm-mc -triple mips-unknown-linux < %s -show-encoding \
+# RUN: -target-abi=o32 2>&1 | FileCheck %s
.text
foo:
- .reloc 0, R_MIPS_32, .text+.text # CHECK: :[[@LINE]]:23: error: expression must be relocatable
+ .reloc foo+4, R_MIPS_32, .text # CHECK: :[[@LINE]]:9: error: expected non-negative number or a label
+ .reloc foo+foo, R_MIPS_32, .text # CHECK: :[[@LINE]]:9: error: expected non-negative number or a label
+ .reloc 0, R_MIPS_32, .text+.text # CHECK: :[[@LINE]]:23: error: expression must be relocatable
+ .reloc 0 R_MIPS_32, .text # CHECK: :[[@LINE]]:11: error: expected comma
+ .reloc 0, 0, R_MIPS_32, .text # CHECK: :[[@LINE]]:12: error: expected relocation name
+ .reloc -1, R_MIPS_32, .text # CHECK: :[[@LINE]]:9: error: expression is negative
+ .reloc 1b, R_MIPS_32, .text # CHECK: :[[@LINE]]:9: error: directional label undefined
+ .reloc 1f, R_MIPS_32, .text # CHECK: :[[@LINE]]:9: error: directional label undefined
nop
--- /dev/null
+# RUN: llvm-mc -triple mips-unknown-linux %s -show-encoding -target-abi=o32 \
+# RUN: | FileCheck --check-prefixes=ASM,ASM-32 %s
+# RUN: llvm-mc -triple mips64-unknown-linux %s -show-encoding -target-abi=n32 \
+# RUN: | FileCheck --check-prefixes=ASM,ASM-64 %s
+# RUN: llvm-mc -triple mips64-unknown-linux %s -show-encoding -target-abi=n64 \
+# RUN: | FileCheck --check-prefixes=ASM,ASM-64 %s
+# RUN: llvm-mc -triple mips-unknown-linux %s -show-encoding -target-abi=o32 \
+# RUN: -filetype=obj | llvm-readobj -r | FileCheck -check-prefix=OBJ-O32 %s
+# RUN: llvm-mc -triple mips64-unknown-linux %s -show-encoding -target-abi=n32 \
+# RUN: -filetype=obj | llvm-readobj -r | FileCheck -check-prefix=OBJ-N32 %s
+# RUN: llvm-mc -triple mips64-unknown-linux %s -show-encoding -target-abi=n64 \
+# RUN: -filetype=obj | llvm-readobj -r | FileCheck -check-prefix=OBJ-N64 %s
+
+ .text
+foo: # ASM-LABEL: foo:
+ nop
+1:
+ nop
+ .reloc 1b, R_MIPS_NONE, foo # ASM-32: .reloc ($tmp0), R_MIPS_NONE, foo
+ # ASM-64: .reloc .Ltmp0, R_MIPS_NONE, foo
+ nop
+ .reloc 1f, R_MIPS_32, foo # ASM-32: .reloc ($tmp1), R_MIPS_32, foo
+ # ASM-64: .reloc .Ltmp1, R_MIPS_32, foo
+1:
+ nop
+ .reloc 1f, R_MIPS_CALL16, foo # ASM-32: .reloc ($tmp2), R_MIPS_CALL16, foo
+ # ASM-64: .reloc .Ltmp2, R_MIPS_CALL16, foo
+1:
+ nop
+ .reloc 2f, R_MIPS_GOT_DISP, foo # ASM-32: .reloc ($tmp3), R_MIPS_GOT_DISP, foo
+ # ASM-64: .reloc .Ltmp3, R_MIPS_GOT_DISP, foo
+ nop
+
+ .reloc 3f, R_MIPS_GOT_PAGE, foo # ASM-32: .reloc ($tmp4), R_MIPS_GOT_PAGE, foo
+ # ASM-64: .reloc .Ltmp4, R_MIPS_GOT_PAGE, foo
+ nop
+bar:
+2:
+ nop
+3:
+ nop
+ .reloc bar, R_MIPS_GOT_OFST, foo # ASM: .reloc bar, R_MIPS_GOT_OFST, foo
+ nop
+ .reloc foo, R_MIPS_32, foo # ASM: .reloc foo, R_MIPS_32, foo
+ nop
+1:
+ nop
+
+# OBJ-O32-LABEL: Relocations [
+# OBJ-O32: 0x0 R_MIPS_32 .text 0x0
+# OBJ-O32-NEXT: 0x4 R_MIPS_NONE .text 0x0
+# OBJ-O32-NEXT: 0xC R_MIPS_32 .text 0x0
+# OBJ-O32-NEXT: 0x10 R_MIPS_CALL16 foo 0x0
+# OBJ-O32-NEXT: 0x1C R_MIPS_GOT_DISP foo 0x0
+# OBJ-O32-NEXT: 0x1C R_MIPS_GOT_OFST .text 0x0
+# OBJ-O32-NEXT: 0x20 R_MIPS_GOT_PAGE .text 0x0
+
+# OBJ-N32-LABEL: Relocations [
+# OBJ-N32: 0x4 R_MIPS_NONE .text 0x0
+# OBJ-N32-NEXT: 0x1C R_MIPS_GOT_OFST .text 0x0
+# OBJ-N32-NEXT: 0x0 R_MIPS_32 .text 0x0
+# OBJ-N32-NEXT: 0xC R_MIPS_32 .text 0x0
+# OBJ-N32-NEXT: 0x10 R_MIPS_CALL16 foo 0x0
+# OBJ-N32-NEXT: 0x1C R_MIPS_GOT_DISP foo 0x0
+# OBJ-N32-NEXT: 0x20 R_MIPS_GOT_PAGE .text 0x0
+
+# OBJ-N64-LABEL: Relocations [
+# OBJ-N64: 0x4 R_MIPS_NONE/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT: 0x1C R_MIPS_GOT_OFST/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT: 0x0 R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT: 0xC R_MIPS_32/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+# OBJ-N64-NEXT: 0x10 R_MIPS_CALL16/R_MIPS_NONE/R_MIPS_NONE foo 0x0
+# OBJ-N64-NEXT: 0x1C R_MIPS_GOT_DISP/R_MIPS_NONE/R_MIPS_NONE foo 0x0
+# OBJ-N64-NEXT: 0x20 R_MIPS_GOT_PAGE/R_MIPS_NONE/R_MIPS_NONE .text 0x0
+++ /dev/null
-# RUN: not llvm-mc -triple mips-unknown-linux < %s -show-encoding -target-abi=o32 \
-# RUN: 2>&1 | FileCheck %s
- .text
-foo:
- .reloc -1, R_MIPS_32, .text # CHECK: :[[@LINE]]:9: error: expression is negative
- nop