const MCFixup &Fixup, MCValue Target,
uint64_t &FixedValue) {
MCAsmBackend &Backend = Asm.getBackend();
- bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
- MCFixupKindInfo::FKF_IsPCRel;
+
+ // The WebAssembly backend should never generate FKF_IsPCRel fixups
+ assert(!(Backend.getFixupKindInfo(Fixup.getKind()).Flags &
+ MCFixupKindInfo::FKF_IsPCRel));
+
const auto &FixupSection = cast<MCSectionWasm>(*Fragment->getParent());
uint64_t C = Target.getConstant();
uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
return;
if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
- assert(RefB->getKind() == MCSymbolRefExpr::VK_None &&
- "Should not have constructed this");
-
- // Let A, B and C being the components of Target and R be the location of
- // the fixup. If the fixup is not pcrel, we want to compute (A - B + C).
- // If it is pcrel, we want to compute (A - B + C - R).
-
- // In general, Wasm has no relocations for -B. It can only represent (A + C)
- // or (A + C - R). If B = R + K and the relocation is not pcrel, we can
- // replace B to implement it: (A - R - K + C)
- if (IsPCRel) {
- Ctx.reportError(
- Fixup.getLoc(),
- "No relocation available to represent this relative expression");
- return;
- }
-
+ // To get here the A - B expression must have failed evaluateAsRelocatable.
+ // This means either A or B must be undefined and in WebAssembly we can't
+ // support either of those cases.
const auto &SymB = cast<MCSymbolWasm>(RefB->getSymbol());
-
- if (SymB.isUndefined()) {
- Ctx.reportError(Fixup.getLoc(),
- Twine("symbol '") + SymB.getName() +
- "' can not be undefined in a subtraction expression");
- return;
- }
-
- assert(!SymB.isAbsolute() && "Should have been folded");
- const MCSection &SecB = SymB.getSection();
- if (&SecB != &FixupSection) {
- Ctx.reportError(Fixup.getLoc(),
- "Cannot represent a difference across sections");
- return;
- }
-
- uint64_t SymBOffset = Layout.getSymbolOffset(SymB);
- uint64_t K = SymBOffset - FixupOffset;
- IsPCRel = true;
- C -= K;
+ Ctx.reportError(
+ Fixup.getLoc(),
+ Twine("symbol '") + SymB.getName() +
+ "': unsupported subtraction expression used in relocation.");
+ return;
}
// We either rejected the fixup or folded B into C at this point.
const MCSymbolRefExpr *RefA = Target.getSymA();
- const auto *SymA = RefA ? cast<MCSymbolWasm>(&RefA->getSymbol()) : nullptr;
+ const auto *SymA = cast<MCSymbolWasm>(&RefA->getSymbol());
- if (SymA && SymA->isVariable()) {
+ if (SymA->isVariable()) {
const MCExpr *Expr = SymA->getVariableValue();
const auto *Inner = cast<MCSymbolRefExpr>(Expr);
if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF)
FixedValue = 0;
unsigned Type = TargetObjectWriter->getRelocType(Target, Fixup);
- assert(!IsPCRel);
- assert(SymA);
// Absolute offset within a section or a function.
// Currently only supported for for metadata sections.
--- /dev/null
+// RUN: not llvm-mc -filetype=obj -triple wasm32 %s -o /dev/null 2>&1 | FileCheck %s
+
+ .section .data.foo,"",@
+foo:
+ .int8 1
+ .size foo, 1
+foo_other:
+ .int8 1
+ .size foo_other, 1
+
+ .section .data.bar,"",@
+bar:
+ .int8 1
+ .size bar, 1
+
+ .text
+ .section .text.main,"",@
+main:
+ .functype main () -> (i32)
+// Expressions involving symbols within the same sections can be evaluated
+// prior to writing the object file.
+// CHECK-NOT: foo
+ i32.const foo-foo_other+2
+ i32.const foo_other-foo-10
+
+// CHECK: 'bar': unsupported subtraction expression used in relocation
+ i32.const foo-bar
+// CHECK: 'undef_baz': unsupported subtraction expression used in relocation
+ i32.const foo-undef_baz
+// CHECK: 'foo': unsupported subtraction expression used in relocation
+ i32.const undef_baz-foo
+ end_function