summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/X86/X86MCCodeEmitter.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2010-10-20 16:46:08 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2010-10-20 16:46:08 +0000
commit89f6613e76efa6738ba91de65348e0f3fdeb60be (patch)
treed162c6aa203ec62c767b6dcfec5aff253490fdf3 /llvm/lib/Target/X86/X86MCCodeEmitter.cpp
parent3317d985fe0c59be983734bdbcc7e7c88ec26d57 (diff)
downloadbcm5719-llvm-89f6613e76efa6738ba91de65348e0f3fdeb60be.tar.gz
bcm5719-llvm-89f6613e76efa6738ba91de65348e0f3fdeb60be.zip
Handle _GLOBAL_OFFSET_TABLE_ correctly.
llvm-svn: 116932
Diffstat (limited to 'llvm/lib/Target/X86/X86MCCodeEmitter.cpp')
-rw-r--r--llvm/lib/Target/X86/X86MCCodeEmitter.cpp27
1 files changed, 27 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/X86MCCodeEmitter.cpp
index 62f434d0fd1..47e91a8159c 100644
--- a/llvm/lib/Target/X86/X86MCCodeEmitter.cpp
+++ b/llvm/lib/Target/X86/X86MCCodeEmitter.cpp
@@ -18,6 +18,7 @@
#include "llvm/MC/MCCodeEmitter.h"
#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCSymbol.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -193,6 +194,25 @@ static bool Is32BitMemOperand(const MCInst &MI, unsigned Op) {
return false;
}
+/// StartsWithGlobalOffsetTable - Return true for the simple cases where this
+/// expression starts with _GLOBAL_OFFSET_TABLE_. This is a needed to support
+/// PIC on ELF i386 as that symbol is magic. We check only simple case that
+/// are know to be used: _GLOBAL_OFFSET_TABLE_ by itself or at the start
+/// of a binary expression.
+static bool StartsWithGlobalOffsetTable(const MCExpr *Expr) {
+ if (Expr->getKind() == MCExpr::Binary) {
+ const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Expr);
+ Expr = BE->getLHS();
+ }
+
+ if (Expr->getKind() != MCExpr::SymbolRef)
+ return false;
+
+ const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
+ const MCSymbol &S = Ref->getSymbol();
+ return S.getName() == "_GLOBAL_OFFSET_TABLE_";
+}
+
void X86MCCodeEmitter::
EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
unsigned &CurByte, raw_ostream &OS,
@@ -209,6 +229,13 @@ EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
// If we have an immoffset, add it to the expression.
const MCExpr *Expr = DispOp.getExpr();
+ if (StartsWithGlobalOffsetTable(Expr)) {
+ // FIXME: We should probably change the FixupKind to a special one so that
+ // other parts of MC don't have to check the symbol name.
+ assert(ImmOffset == 0);
+ ImmOffset = CurByte;
+ }
+
// If the fixup is pc-relative, we need to bias the value to be relative to
// the start of the field, not the end of the field.
if (FixupKind == MCFixupKind(X86::reloc_pcrel_4byte) ||
OpenPOWER on IntegriCloud