diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2010-10-20 16:46:08 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2010-10-20 16:46:08 +0000 |
commit | 64e6719ee870f88db445feac0a1d5f597a7549e3 (patch) | |
tree | 0701b0c42d477bb3305df12b21f92ac944bf5842 /lib | |
parent | 9f608b191956a761f5cbe2b3f0056206d04bd5b2 (diff) | |
download | external_llvm-64e6719ee870f88db445feac0a1d5f597a7549e3.zip external_llvm-64e6719ee870f88db445feac0a1d5f597a7549e3.tar.gz external_llvm-64e6719ee870f88db445feac0a1d5f597a7549e3.tar.bz2 |
Handle _GLOBAL_OFFSET_TABLE_ correctly.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116932 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Target/X86/X86MCCodeEmitter.cpp | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/lib/Target/X86/X86MCCodeEmitter.cpp b/lib/Target/X86/X86MCCodeEmitter.cpp index 62f434d..47e91a8 100644 --- a/lib/Target/X86/X86MCCodeEmitter.cpp +++ b/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) || |