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 | 89f6613e76efa6738ba91de65348e0f3fdeb60be (patch) | |
tree | d162c6aa203ec62c767b6dcfec5aff253490fdf3 /llvm/lib/Target/X86/X86MCCodeEmitter.cpp | |
parent | 3317d985fe0c59be983734bdbcc7e7c88ec26d57 (diff) | |
download | bcm5719-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.cpp | 27 |
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) || |