From 8f7d12ccfd8feb258bdf4e582592bc00beacc7c6 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 17 Dec 2011 01:14:52 +0000 Subject: [PATCH] Add back the MC bits of 126425. Original patch by Nathan Jeffords. I added the asm parsing and testcase. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@146801 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/MC/MCStreamer.h | 5 +++++ lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp | 5 ++--- lib/MC/MCAsmStreamer.cpp | 6 ++++++ lib/MC/MCLoggingStreamer.cpp | 5 +++++ lib/MC/MCNullStreamer.cpp | 1 + lib/MC/MCParser/COFFAsmParser.cpp | 17 +++++++++++++++++ lib/MC/MCStreamer.cpp | 4 ++++ lib/MC/WinCOFFObjectWriter.cpp | 4 ++++ lib/MC/WinCOFFStreamer.cpp | 14 ++++++++++++++ lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp | 4 +++- lib/Target/X86/MCTargetDesc/X86FixupKinds.h | 2 ++ test/MC/COFF/secrel32.s | 14 ++++++++++++++ 12 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 test/MC/COFF/secrel32.s diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 1c1fe027989..9ba50b1a263 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -334,6 +334,11 @@ namespace llvm { /// EndCOFFSymbolDef - Marks the end of the symbol definition. virtual void EndCOFFSymbolDef() = 0; + /// EmitCOFFSecRel32 - Emits a COFF section relative relocation. + /// + /// @param Symbol - Symbol the section relative realocation should point to. + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); + /// EmitELFSize - Emit an ELF .size directive. /// /// This corresponds to an assembler statement such as: diff --git a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp index 605b775502b..c1669469899 100644 --- a/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp +++ b/lib/CodeGen/AsmPrinter/AsmPrinterDwarf.cpp @@ -144,9 +144,8 @@ void AsmPrinter::EmitReference(const GlobalValue *GV, unsigned Encoding)const{ void AsmPrinter::EmitSectionOffset(const MCSymbol *Label, const MCSymbol *SectionLabel) const { // On COFF targets, we have to emit the special .secrel32 directive. - if (const char *SecOffDir = MAI->getDwarfSectionOffsetDirective()) { - // FIXME: MCize. - OutStreamer.EmitRawText(SecOffDir + Twine(Label->getName())); + if (MAI->getDwarfSectionOffsetDirective()) { + OutStreamer.EmitCOFFSecRel32(Label); return; } diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index c785c032231..630a104b129 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -154,6 +154,7 @@ public: virtual void EmitCOFFSymbolStorageClass(int StorageClass); virtual void EmitCOFFSymbolType(int Type); virtual void EndCOFFSymbolDef(); + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); @@ -470,6 +471,11 @@ void MCAsmStreamer::EndCOFFSymbolDef() { EmitEOL(); } +void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { + OS << "\t.secrel32\t" << *Symbol << '\n'; + EmitEOL(); +} + void MCAsmStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { assert(MAI.hasDotTypeDotSizeDirective()); OS << "\t.size\t" << *Symbol << ", " << *Value << '\n'; diff --git a/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp index a7b79476767..d59b6d7acaf 100644 --- a/lib/MC/MCLoggingStreamer.cpp +++ b/lib/MC/MCLoggingStreamer.cpp @@ -122,6 +122,11 @@ public: return Child->EndCOFFSymbolDef(); } + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) { + LogCall("EmitCOFFSecRel32"); + return Child->EmitCOFFSecRel32(Symbol); + } + virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { LogCall("EmitELFSize"); return Child->EmitELFSize(Symbol, Value); diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp index d178b507a0f..ca74663693d 100644 --- a/lib/MC/MCNullStreamer.cpp +++ b/lib/MC/MCNullStreamer.cpp @@ -55,6 +55,7 @@ namespace { virtual void EmitCOFFSymbolStorageClass(int StorageClass) {} virtual void EmitCOFFSymbolType(int Type) {} virtual void EndCOFFSymbolDef() {} + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol) {} virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) {} virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, diff --git a/lib/MC/MCParser/COFFAsmParser.cpp b/lib/MC/MCParser/COFFAsmParser.cpp index 185b5168bd6..c4cdc3c9f96 100644 --- a/lib/MC/MCParser/COFFAsmParser.cpp +++ b/lib/MC/MCParser/COFFAsmParser.cpp @@ -45,6 +45,7 @@ class COFFAsmParser : public MCAsmParserExtension { AddDirectiveHandler<&COFFAsmParser::ParseDirectiveScl>(".scl"); AddDirectiveHandler<&COFFAsmParser::ParseDirectiveType>(".type"); AddDirectiveHandler<&COFFAsmParser::ParseDirectiveEndef>(".endef"); + AddDirectiveHandler<&COFFAsmParser::ParseDirectiveSecRel32>(".secrel32"); // Win64 EH directives. AddDirectiveHandler<&COFFAsmParser::ParseSEHDirectiveStartProc>( @@ -102,6 +103,7 @@ class COFFAsmParser : public MCAsmParserExtension { bool ParseDirectiveScl(StringRef, SMLoc); bool ParseDirectiveType(StringRef, SMLoc); bool ParseDirectiveEndef(StringRef, SMLoc); + bool ParseDirectiveSecRel32(StringRef, SMLoc); // Win64 EH directives. bool ParseSEHDirectiveStartProc(StringRef, SMLoc); @@ -217,6 +219,21 @@ bool COFFAsmParser::ParseDirectiveEndef(StringRef, SMLoc) { return false; } +bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) { + StringRef SymbolID; + if (getParser().ParseIdentifier(SymbolID)) + return true; + + if (getLexer().isNot(AsmToken::EndOfStatement)) + return TokError("unexpected token in directive"); + + MCSymbol *Symbol = getContext().GetOrCreateSymbol(SymbolID); + + Lex(); + getStreamer().EmitCOFFSecRel32(Symbol); + return false; +} + bool COFFAsmParser::ParseSEHDirectiveStartProc(StringRef, SMLoc) { StringRef SymbolID; if (getParser().ParseIdentifier(SymbolID)) diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 60a0a9d115d..74c3e39e3b9 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -558,6 +558,10 @@ void MCStreamer::EmitWin64EHEndProlog() { EmitLabel(CurFrame->PrologEnd); } +void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) { + assert(0 && "This file format doesn't support this directive"); +} + void MCStreamer::EmitFnStart() { errs() << "Not implemented yet\n"; abort(); diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp index 4052374c963..484443a69aa 100644 --- a/lib/MC/WinCOFFObjectWriter.cpp +++ b/lib/MC/WinCOFFObjectWriter.cpp @@ -716,6 +716,10 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm, else llvm_unreachable("unsupported relocation type"); break; + case X86::reloc_coff_secrel32: + Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_SREL32 + : COFF::IMAGE_REL_I386_SECREL; + break; default: llvm_unreachable("unsupported relocation type"); } diff --git a/lib/MC/WinCOFFStreamer.cpp b/lib/MC/WinCOFFStreamer.cpp index 7409daf3908..3678a589f4e 100644 --- a/lib/MC/WinCOFFStreamer.cpp +++ b/lib/MC/WinCOFFStreamer.cpp @@ -32,6 +32,9 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" + +#include "../Target/X86/MCTargetDesc/X86FixupKinds.h" + using namespace llvm; namespace { @@ -60,6 +63,7 @@ public: virtual void EmitCOFFSymbolStorageClass(int StorageClass); virtual void EmitCOFFSymbolType(int Type); virtual void EndCOFFSymbolDef(); + virtual void EmitCOFFSecRel32(MCSymbol const *Symbol); virtual void EmitELFSize(MCSymbol *Symbol, const MCExpr *Value); virtual void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment); @@ -293,6 +297,16 @@ void WinCOFFStreamer::EndCOFFSymbolDef() { CurSymbol = NULL; } +void WinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) +{ + MCDataFragment *DF = getOrCreateDataFragment(); + + DF->addFixup(MCFixup::Create(DF->getContents().size(), + MCSymbolRefExpr::Create (Symbol, getContext ()), + (MCFixupKind)X86::reloc_coff_secrel32)); + DF->getContents().resize(DF->getContents().size() + 4, 0); +} + void WinCOFFStreamer::EmitELFSize(MCSymbol *Symbol, const MCExpr *Value) { llvm_unreachable("not implemented"); } diff --git a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp index 87b2b055ab2..7cbda489b69 100644 --- a/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp +++ b/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp @@ -47,6 +47,7 @@ static unsigned getFixupKindLog2Size(unsigned Kind) { case X86::reloc_riprel_4byte_movq_load: case X86::reloc_signed_4byte: case X86::reloc_global_offset_table: + case X86::reloc_coff_secrel32: case FK_Data_4: return 2; case FK_PCRel_8: case FK_Data_8: return 3; @@ -76,7 +77,8 @@ public: { "reloc_riprel_4byte", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel }, { "reloc_riprel_4byte_movq_load", 0, 4 * 8, MCFixupKindInfo::FKF_IsPCRel}, { "reloc_signed_4byte", 0, 4 * 8, 0}, - { "reloc_global_offset_table", 0, 4 * 8, 0} + { "reloc_global_offset_table", 0, 4 * 8, 0}, + { "reloc_coff_secrel32", 0, 4 * 8, 0} }; if (Kind < FirstTargetFixupKind) diff --git a/lib/Target/X86/MCTargetDesc/X86FixupKinds.h b/lib/Target/X86/MCTargetDesc/X86FixupKinds.h index 17d242ab761..d6cb39ae9a7 100644 --- a/lib/Target/X86/MCTargetDesc/X86FixupKinds.h +++ b/lib/Target/X86/MCTargetDesc/X86FixupKinds.h @@ -23,6 +23,8 @@ enum Fixups { reloc_global_offset_table, // 32-bit, relative to the start // of the instruction. Used only // for _GLOBAL_OFFSET_TABLE_. + reloc_coff_secrel32, // PE-COFF section relative 32 + // (only valid for win32 COFF) // Marker LastTargetFixupKind, NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind diff --git a/test/MC/COFF/secrel32.s b/test/MC/COFF/secrel32.s new file mode 100644 index 00000000000..ce148db9000 --- /dev/null +++ b/test/MC/COFF/secrel32.s @@ -0,0 +1,14 @@ +// RUN: llvm-mc -filetype=obj -triple i686-pc-win32 %s | coff-dump.py | FileCheck %s + +// check that we produce the correct relocation for .secrel32 + +Lfoo: + .secrel32 Lfoo + +// CHECK: Relocations = [ +// CHECK-NEXT: 0 = { +// CHECK-NEXT: VirtualAddress = 0x0 +// CHECK-NEXT: SymbolTableIndex = 0 +// CHECK-NEXT: Type = IMAGE_REL_I386_SECREL (11) +// CHECK-NEXT: SymbolName = .text +// CHECK-NEXT: }