[llvm-commits] [llvm] r116932 - in /llvm/trunk: lib/Target/X86/X86MCCodeEmitter.cpp test/MC/ELF/global-offset.s
Rafael Espindola
rafael.espindola at gmail.com
Wed Oct 20 09:46:08 PDT 2010
Author: rafael
Date: Wed Oct 20 11:46:08 2010
New Revision: 116932
URL: http://llvm.org/viewvc/llvm-project?rev=116932&view=rev
Log:
Handle _GLOBAL_OFFSET_TABLE_ correctly.
Added:
llvm/trunk/test/MC/ELF/global-offset.s
Modified:
llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp
Modified: llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp?rev=116932&r1=116931&r2=116932&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86MCCodeEmitter.cpp Wed Oct 20 11:46:08 2010
@@ -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 @@
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 @@
// 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) ||
Added: llvm/trunk/test/MC/ELF/global-offset.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/ELF/global-offset.s?rev=116932&view=auto
==============================================================================
--- llvm/trunk/test/MC/ELF/global-offset.s (added)
+++ llvm/trunk/test/MC/ELF/global-offset.s Wed Oct 20 11:46:08 2010
@@ -0,0 +1,18 @@
+// RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s
+
+// We test that _GLOBAL_OFFSET_TABLE_ will account for the two bytes at the
+// start of the addl.
+
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+
+// CHECK: ('sh_name', 0x00000001) # '.text'
+// CHECK-NEXT: ('sh_type',
+// CHECK-NEXT: ('sh_flags',
+// CHECK-NEXT: ('sh_addr',
+// CHECK-NEXT: ('sh_offset',
+// CHECK-NEXT: ('sh_size',
+// CHECK-NEXT: ('sh_link',
+// CHECK-NEXT: ('sh_info',
+// CHECK-NEXT: ('sh_addralign',
+// CHECK-NEXT: ('sh_entsize',
+// CHECK-NEXT: ('_section_data', '81c30200 0000')
More information about the llvm-commits
mailing list