protected:
explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {}
+ bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
+ bool InSet) const;
public:
/// @name Accessors
/// @{
--- /dev/null
+//===-- llvm/MC/MCObjectFormat.h - Object Format Info -----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCOBJECTFORMAT_H
+#define LLVM_MC_MCOBJECTFORMAT_H
+
+namespace llvm {
+class MCSymbol;
+
+class MCObjectFormat {
+public:
+ /// isAbsolute - Check if A - B is an absolute value
+ ///
+ /// \param InSet - True if this expression is in a set. For example:
+ /// a:
+ /// ...
+ /// b:
+ /// tmp = a - b
+ /// .long tmp
+ /// \param A - LHS
+ /// \param B - RHS
+ virtual bool isAbsolute(bool InSet, const MCSymbol &A,
+ const MCSymbol &B) const = 0;
+};
+
+class MCELFObjectFormat : public MCObjectFormat {
+public:
+ virtual bool isAbsolute(bool InSet, const MCSymbol &A,
+ const MCSymbol &B) const;
+};
+
+class MCMachOObjectFormat : public MCObjectFormat {
+public:
+ virtual bool isAbsolute(bool InSet, const MCSymbol &A,
+ const MCSymbol &B) const;
+};
+
+class MCCOFFObjectFormat : public MCObjectFormat {
+public:
+ virtual bool isAbsolute(bool InSet, const MCSymbol &A,
+ const MCSymbol &B) const;
+};
+
+} // End llvm namespace
+
+#endif
class MCDataFragment;
class MCFixup;
class MCInst;
+class MCObjectFormat;
class MCObjectWriter;
class MCSection;
template<typename T>
/// TheTarget - The Target that this machine was created for.
const Target &TheTarget;
- unsigned HasAbsolutizedSet : 1;
unsigned HasReliableSymbolDifference : 1;
unsigned HasScatteredSymbols : 1;
const Target &getTarget() const { return TheTarget; }
+ virtual const MCObjectFormat &getObjectFormat() const = 0;
+
/// createObjectWriter - Create a new MCObjectWriter instance for use by the
/// assembler backend to emit the final object file.
virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0;
- /// hasAbsolutizedSet - Check whether this target "absolutizes"
- /// assignments. That is, given code like:
- /// a:
- /// ...
- /// b:
- /// tmp = a - b
- /// .long tmp
- /// will the value of 'tmp' be a relocatable expression, or the assembly time
- /// value of L0 - L1. This distinction is only relevant for platforms that
- /// support scattered symbols, since in the absence of scattered symbols (a -
- /// b) cannot change after assembly.
- bool hasAbsolutizedSet() const { return HasAbsolutizedSet; }
-
/// hasReliableSymbolDifference - Check whether this target implements
/// accurate relocations for differences between symbols. If not, differences
/// between symbols will always be relocatable expressions and any references
/// This should always be true (since it results in fewer relocations with no
/// loss of functionality), but is currently supported as a way to maintain
/// exact object compatibility with Darwin 'as' (on non-x86_64). It should
- /// eventually should be eliminated. See also \see hasAbsolutizedSet.
+ /// eventually should be eliminated.
bool hasReliableSymbolDifference() const {
return HasReliableSymbolDifference;
}
MCMachOStreamer.cpp
MCNullStreamer.cpp
MCObjectStreamer.cpp
+ MCObjectFormat.cpp
MCObjectWriter.cpp
MCSection.cpp
MCSectionCOFF.cpp
const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(ESize);
if (BE->EvaluateAsRelocatable(Res, &Layout)) {
- uint64_t AddressA = 0;
- uint64_t AddressB = 0;
- const MCSymbol &SymA = Res.getSymA()->getSymbol();
- const MCSymbol &SymB = Res.getSymB()->getSymbol();
-
- if (SymA.isDefined()) {
- MCSymbolData &A = Layout.getAssembler().getSymbolData(SymA);
- AddressA = Layout.getSymbolAddress(&A);
- }
-
- if (SymB.isDefined()) {
- MCSymbolData &B = Layout.getAssembler().getSymbolData(SymB);
- AddressB = Layout.getSymbolAddress(&B);
- }
-
- Size = AddressA - AddressB;
+ const llvm::MCSymbolRefExpr *A = Res.getSymA();
+ const llvm::MCSymbolRefExpr *B = Res.getSymA();
+ assert(!A || !A->getSymbol().isDefined());
+ assert(!B || !B->getSymbol().isDefined());
+ Size = Res.getConstant();
}
} else if (ESize->getKind() == MCExpr::Constant) {
Size = static_cast<const MCConstantExpr *>(ESize)->getValue();
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCObjectFormat.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCValue.h"
#include "llvm/Support/Debug.h"
return true;
}
-static bool EvaluateSymbolicAdd(const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
+static bool EvaluateSymbolicAdd(const MCAsmLayout *Layout, bool InSet,
+ const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
const MCSymbolRefExpr *RHS_B, int64_t RHS_Cst,
MCValue &Res) {
// We can't add or subtract two symbols.
if (!A)
return false;
}
+
+ // Absolutize symbol differences between defined symbols when we have a
+ // layout object and the target requests it.
+
+ if (Layout && A && B) {
+ const MCSymbol &SA = A->getSymbol();
+ const MCSymbol &SB = B->getSymbol();
+ const MCObjectFormat &F =
+ Layout->getAssembler().getBackend().getObjectFormat();
+ if (SA.isDefined() && SB.isDefined() && F.isAbsolute(InSet, SA, SB)) {
+ const MCAssembler &Asm = Layout->getAssembler();
+ MCSymbolData &AD = Asm.getSymbolData(A->getSymbol());
+ MCSymbolData &BD = Asm.getSymbolData(B->getSymbol());
+ Res = MCValue::get(+ Layout->getSymbolAddress(&AD)
+ - Layout->getSymbolAddress(&BD)
+ + LHS.getConstant()
+ + RHS_Cst);
+ return true;
+ }
+ }
+
+
Res = MCValue::get(A, B, LHS.getConstant() + RHS_Cst);
return true;
}
bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
const MCAsmLayout *Layout) const {
+ return EvaluateAsRelocatableImpl(Res, Layout, false);
+}
+
+bool MCExpr::EvaluateAsRelocatableImpl(MCValue &Res,
+ const MCAsmLayout *Layout,
+ bool InSet) const {
++stats::MCExprEvaluate;
switch (getKind()) {
const MCSymbol &Sym = SRE->getSymbol();
// Evaluate recursively if this is a variable.
- if (Sym.isVariable()) {
- if (!Sym.getVariableValue()->EvaluateAsRelocatable(Res, Layout))
- return false;
-
- // Absolutize symbol differences between defined symbols when we have a
- // layout object and the target requests it.
- if (Layout && Res.getSymB() &&
- Layout->getAssembler().getBackend().hasAbsolutizedSet() &&
- Res.getSymA()->getSymbol().isDefined() &&
- Res.getSymB()->getSymbol().isDefined()) {
- MCSymbolData &A =
- Layout->getAssembler().getSymbolData(Res.getSymA()->getSymbol());
- MCSymbolData &B =
- Layout->getAssembler().getSymbolData(Res.getSymB()->getSymbol());
- Res = MCValue::get(+ Layout->getSymbolAddress(&A)
- - Layout->getSymbolAddress(&B)
- + Res.getConstant());
- }
-
- return true;
- }
+ if (Sym.isVariable())
+ return Sym.getVariableValue()->EvaluateAsRelocatableImpl(Res, Layout,
+ true);
Res = MCValue::get(SRE, 0, 0);
return true;
const MCUnaryExpr *AUE = cast<MCUnaryExpr>(this);
MCValue Value;
- if (!AUE->getSubExpr()->EvaluateAsRelocatable(Value, Layout))
+ if (!AUE->getSubExpr()->EvaluateAsRelocatableImpl(Value, Layout, InSet))
return false;
switch (AUE->getOpcode()) {
const MCBinaryExpr *ABE = cast<MCBinaryExpr>(this);
MCValue LHSValue, RHSValue;
- if (!ABE->getLHS()->EvaluateAsRelocatable(LHSValue, Layout) ||
- !ABE->getRHS()->EvaluateAsRelocatable(RHSValue, Layout))
+ if (!ABE->getLHS()->EvaluateAsRelocatableImpl(LHSValue, Layout, InSet) ||
+ !ABE->getRHS()->EvaluateAsRelocatableImpl(RHSValue, Layout, InSet))
return false;
// We only support a few operations on non-constant expressions, handle
return false;
case MCBinaryExpr::Sub:
// Negate RHS and add.
- return EvaluateSymbolicAdd(LHSValue,
+ return EvaluateSymbolicAdd(Layout, InSet, LHSValue,
RHSValue.getSymB(), RHSValue.getSymA(),
-RHSValue.getConstant(),
Res);
case MCBinaryExpr::Add:
- return EvaluateSymbolicAdd(LHSValue,
+ return EvaluateSymbolicAdd(Layout, InSet, LHSValue,
RHSValue.getSymA(), RHSValue.getSymB(),
RHSValue.getConstant(),
Res);
--- /dev/null
+//===- lib/MC/MCObjectFormat.cpp - MCObjectFormat implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCObjectFormat.h"
+#include "llvm/MC/MCSymbol.h"
+
+using namespace llvm;
+
+bool MCELFObjectFormat::isAbsolute(bool IsSet, const MCSymbol &A,
+ const MCSymbol &B) const {
+ // On ELF A - B is absolute if A and B are in the same section.
+ return &A.getSection() == &B.getSection();
+}
+
+bool MCMachOObjectFormat::isAbsolute(bool IsSet, const MCSymbol &A,
+ const MCSymbol &B) const {
+ // On MachO A - B is absolute only if in a set.
+ return IsSet;
+}
+
+bool MCCOFFObjectFormat::isAbsolute(bool IsSet, const MCSymbol &A,
+ const MCSymbol &B) const {
+ // On COFF A - B is absolute if A and B are in the same section.
+ return &A.getSection() == &B.getSection();
+}
TargetAsmBackend::TargetAsmBackend(const Target &T)
: TheTarget(T),
- HasAbsolutizedSet(false),
HasReliableSymbolDifference(false),
HasScatteredSymbols(false)
{
#include "llvm/MC/ELFObjectWriter.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectFormat.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSectionMachO.h"
// FIXME: This should be in a separate file.
// ELF is an ELF of course...
class ELFARMAsmBackend : public ARMAsmBackend {
+ MCELFObjectFormat Format;
+
public:
Triple::OSType OSType;
ELFARMAsmBackend(const Target &T, Triple::OSType _OSType)
: ARMAsmBackend(T), OSType(_OSType) {
- HasAbsolutizedSet = true;
HasScatteredSymbols = true;
}
+ virtual const MCObjectFormat &getObjectFormat() const {
+ return Format;
+ }
+
void ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF,
uint64_t Value) const;
// FIXME: This should be in a separate file.
class DarwinARMAsmBackend : public ARMAsmBackend {
+ MCMachOObjectFormat Format;
+
public:
DarwinARMAsmBackend(const Target &T)
: ARMAsmBackend(T) {
- HasAbsolutizedSet = true;
HasScatteredSymbols = true;
assert(0 && "DarwinARMAsmBackend::DarwinARMAsmBackend() unimplemented");
}
+ virtual const MCObjectFormat &getObjectFormat() const {
+ return Format;
+ }
+
void ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF,
uint64_t Value) const;
#include "llvm/MC/ELFObjectWriter.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCExpr.h"
+#include "llvm/MC/MCObjectFormat.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSectionCOFF.h"
#include "llvm/MC/MCSectionELF.h"
namespace {
class ELFX86AsmBackend : public X86AsmBackend {
+ MCELFObjectFormat Format;
+
public:
Triple::OSType OSType;
ELFX86AsmBackend(const Target &T, Triple::OSType _OSType)
: X86AsmBackend(T), OSType(_OSType) {
- HasAbsolutizedSet = true;
HasScatteredSymbols = true;
HasReliableSymbolDifference = true;
}
+ virtual const MCObjectFormat &getObjectFormat() const {
+ return Format;
+ }
+
virtual bool doesSectionRequireSymbols(const MCSection &Section) const {
const MCSectionELF &ES = static_cast<const MCSectionELF&>(Section);
return ES.getFlags() & MCSectionELF::SHF_MERGE;
class WindowsX86AsmBackend : public X86AsmBackend {
bool Is64Bit;
+ MCCOFFObjectFormat Format;
+
public:
WindowsX86AsmBackend(const Target &T, bool is64Bit)
: X86AsmBackend(T)
HasScatteredSymbols = true;
}
+ virtual const MCObjectFormat &getObjectFormat() const {
+ return Format;
+ }
+
unsigned getPointerSize() const {
if (Is64Bit)
return 8;
};
class DarwinX86AsmBackend : public X86AsmBackend {
+ MCMachOObjectFormat Format;
+
public:
DarwinX86AsmBackend(const Target &T)
: X86AsmBackend(T) {
- HasAbsolutizedSet = true;
HasScatteredSymbols = true;
}
+ virtual const MCObjectFormat &getObjectFormat() const {
+ return Format;
+ }
+
bool isVirtualSection(const MCSection &Section) const {
const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
return (SMO.getType() == MCSectionMachO::S_ZEROFILL ||
--- /dev/null
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o - | elf-dump | FileCheck %s
+
+ .global zed
+foo:
+ nop
+bar:
+ nop
+zed:
+ mov zed+(bar-foo), %eax
+
+// CHECK: # Relocation 0
+// CHECK-NEXT: (('r_offset', 5)
+// CHECK-NEXT: ('r_sym', 6)
+// CHECK-NEXT: ('r_type', 11)
+// CHECK-NEXT: ('r_addend', 1)
--- /dev/null
+// RUN: not llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s 2> %t
+// RUN: FileCheck -input-file %t %s
+
+.global zed
+ .data
+foo:
+ .text
+ nop
+bar:
+ nop
+zed:
+// CHECK: expected relocatable expression
+ mov zed+(bar-foo), %eax