summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2010-10-16 18:23:53 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2010-10-16 18:23:53 +0000
commitf230df9af4012f9510de664b6d62b128e26a5861 (patch)
tree459a596099278874a963dabafad21e27da5046eb
parentcb2caf738023c0a03f5df1b909431129a16e2c54 (diff)
downloadllvm-f230df9af4012f9510de664b6d62b128e26a5861.tar.gz
llvm-f230df9af4012f9510de664b6d62b128e26a5861.tar.bz2
llvm-f230df9af4012f9510de664b6d62b128e26a5861.tar.xz
Add a MCObjectFormat class so that code common to all targets that use a
single object format can be shared. This also adds support for mov zed+(bar-foo), %eax on ELF and COFF targets. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116675 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/llvm/MC/MCExpr.h2
-rw-r--r--include/llvm/MC/MCObjectFormat.h52
-rw-r--r--include/llvm/Target/TargetAsmBackend.h19
-rw-r--r--lib/MC/CMakeLists.txt1
-rw-r--r--lib/MC/ELFObjectWriter.cpp21
-rw-r--r--lib/MC/MCExpr.cpp66
-rw-r--r--lib/MC/MCObjectFormat.cpp31
-rw-r--r--lib/MC/TargetAsmBackend.cpp1
-rw-r--r--lib/Target/ARM/ARMAsmBackend.cpp15
-rw-r--r--lib/Target/X86/X86AsmBackend.cpp21
-rw-r--r--test/MC/ELF/diff.s15
-rw-r--r--test/MC/ELF/diff2.s13
12 files changed, 194 insertions, 63 deletions
diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h
index 06f9cd3bc4..f85650fc90 100644
--- a/include/llvm/MC/MCExpr.h
+++ b/include/llvm/MC/MCExpr.h
@@ -43,6 +43,8 @@ private:
protected:
explicit MCExpr(ExprKind _Kind) : Kind(_Kind) {}
+ bool EvaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
+ bool InSet) const;
public:
/// @name Accessors
/// @{
diff --git a/include/llvm/MC/MCObjectFormat.h b/include/llvm/MC/MCObjectFormat.h
new file mode 100644
index 0000000000..80b7295f1f
--- /dev/null
+++ b/include/llvm/MC/MCObjectFormat.h
@@ -0,0 +1,52 @@
+//===-- 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
diff --git a/include/llvm/Target/TargetAsmBackend.h b/include/llvm/Target/TargetAsmBackend.h
index b0a7af6371..b424dea4a5 100644
--- a/include/llvm/Target/TargetAsmBackend.h
+++ b/include/llvm/Target/TargetAsmBackend.h
@@ -16,6 +16,7 @@ namespace llvm {
class MCDataFragment;
class MCFixup;
class MCInst;
+class MCObjectFormat;
class MCObjectWriter;
class MCSection;
template<typename T>
@@ -33,7 +34,6 @@ protected: // Can only create subclasses.
/// TheTarget - The Target that this machine was created for.
const Target &TheTarget;
- unsigned HasAbsolutizedSet : 1;
unsigned HasReliableSymbolDifference : 1;
unsigned HasScatteredSymbols : 1;
@@ -42,23 +42,12 @@ public:
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
@@ -68,7 +57,7 @@ public:
/// 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;
}
diff --git a/lib/MC/CMakeLists.txt b/lib/MC/CMakeLists.txt
index 60a3a3e3e3..5856e07168 100644
--- a/lib/MC/CMakeLists.txt
+++ b/lib/MC/CMakeLists.txt
@@ -18,6 +18,7 @@ add_llvm_library(LLVMMC
MCMachOStreamer.cpp
MCNullStreamer.cpp
MCObjectStreamer.cpp
+ MCObjectFormat.cpp
MCObjectWriter.cpp
MCSection.cpp
MCSectionCOFF.cpp
diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp
index d249c92dad..5a4f89d8d7 100644
--- a/lib/MC/ELFObjectWriter.cpp
+++ b/lib/MC/ELFObjectWriter.cpp
@@ -472,22 +472,11 @@ void ELFObjectWriterImpl::WriteSymbol(MCDataFragment *F, ELFSymbolData &MSD,
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();
diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp
index e9a6062fe7..3524b8035c 100644
--- a/lib/MC/MCExpr.cpp
+++ b/lib/MC/MCExpr.cpp
@@ -14,6 +14,7 @@
#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"
@@ -237,7 +238,8 @@ bool MCExpr::EvaluateAsAbsolute(int64_t &Res, const MCAsmLayout *Layout) const {
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.
@@ -255,12 +257,40 @@ static bool EvaluateSymbolicAdd(const MCValue &LHS,const MCSymbolRefExpr *RHS_A,
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()) {
@@ -276,27 +306,9 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
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;
@@ -306,7 +318,7 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
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()) {
@@ -339,8 +351,8 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
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
@@ -351,13 +363,13 @@ bool MCExpr::EvaluateAsRelocatable(MCValue &Res,
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);
diff --git a/lib/MC/MCObjectFormat.cpp b/lib/MC/MCObjectFormat.cpp
new file mode 100644
index 0000000000..07d361c8a4
--- /dev/null
+++ b/lib/MC/MCObjectFormat.cpp
@@ -0,0 +1,31 @@
+//===- 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();
+}
diff --git a/lib/MC/TargetAsmBackend.cpp b/lib/MC/TargetAsmBackend.cpp
index bbfddbe9e7..1f104105c1 100644
--- a/lib/MC/TargetAsmBackend.cpp
+++ b/lib/MC/TargetAsmBackend.cpp
@@ -12,7 +12,6 @@ using namespace llvm;
TargetAsmBackend::TargetAsmBackend(const Target &T)
: TheTarget(T),
- HasAbsolutizedSet(false),
HasReliableSymbolDifference(false),
HasScatteredSymbols(false)
{
diff --git a/lib/Target/ARM/ARMAsmBackend.cpp b/lib/Target/ARM/ARMAsmBackend.cpp
index df439a41b3..d113cf5b9e 100644
--- a/lib/Target/ARM/ARMAsmBackend.cpp
+++ b/lib/Target/ARM/ARMAsmBackend.cpp
@@ -14,6 +14,7 @@
#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"
@@ -66,14 +67,19 @@ namespace {
// 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;
@@ -98,14 +104,19 @@ void ELFARMAsmBackend::ApplyFixup(const MCFixup &Fixup, MCDataFragment &DF,
// 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;
diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp
index e641500abf..853d3ed159 100644
--- a/lib/Target/X86/X86AsmBackend.cpp
+++ b/lib/Target/X86/X86AsmBackend.cpp
@@ -14,6 +14,7 @@
#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"
@@ -186,15 +187,20 @@ bool X86AsmBackend::WriteNopData(uint64_t Count, MCObjectWriter *OW) const {
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;
@@ -242,6 +248,8 @@ public:
class WindowsX86AsmBackend : public X86AsmBackend {
bool Is64Bit;
+ MCCOFFObjectFormat Format;
+
public:
WindowsX86AsmBackend(const Target &T, bool is64Bit)
: X86AsmBackend(T)
@@ -249,6 +257,10 @@ public:
HasScatteredSymbols = true;
}
+ virtual const MCObjectFormat &getObjectFormat() const {
+ return Format;
+ }
+
unsigned getPointerSize() const {
if (Is64Bit)
return 8;
@@ -267,13 +279,18 @@ public:
};
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 ||
diff --git a/test/MC/ELF/diff.s b/test/MC/ELF/diff.s
new file mode 100644
index 0000000000..671652cf4a
--- /dev/null
+++ b/test/MC/ELF/diff.s
@@ -0,0 +1,15 @@
+// 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)
diff --git a/test/MC/ELF/diff2.s b/test/MC/ELF/diff2.s
new file mode 100644
index 0000000000..4a9fbd1d83
--- /dev/null
+++ b/test/MC/ELF/diff2.s
@@ -0,0 +1,13 @@
+// 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