From dfd30187c685c2c5200ee795c64885c0a39dc2d0 Mon Sep 17 00:00:00 2001 From: "Michael J. Spencer" Date: Tue, 27 Jul 2010 06:46:15 +0000 Subject: [PATCH] Make MC use Windows COFF on Windows and add tests. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@109494 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/X86/X86AsmBackend.cpp | 21 ++ lib/Target/X86/X86TargetMachine.cpp | 2 + test/MC/COFF/basic-coff.ll | 136 +++++++ test/MC/COFF/dg.exp | 5 + test/Scripts/coff-dump.py | 543 ++++++++++++++++++++++++++++ test/Scripts/coff-dump.py.bat | 4 + 6 files changed, 711 insertions(+) create mode 100644 test/MC/COFF/basic-coff.ll create mode 100644 test/MC/COFF/dg.exp create mode 100644 test/Scripts/coff-dump.py create mode 100644 test/Scripts/coff-dump.py.bat diff --git a/lib/Target/X86/X86AsmBackend.cpp b/lib/Target/X86/X86AsmBackend.cpp index 2cf65c11f94..e572620826d 100644 --- a/lib/Target/X86/X86AsmBackend.cpp +++ b/lib/Target/X86/X86AsmBackend.cpp @@ -14,6 +14,7 @@ #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCObjectWriter.h" +#include "llvm/MC/MCSectionCOFF.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSectionMachO.h" #include "llvm/MC/MachObjectWriter.h" @@ -212,6 +213,24 @@ public: : ELFX86AsmBackend(T) {} }; +class WindowsX86AsmBackend : public X86AsmBackend { +public: + WindowsX86AsmBackend(const Target &T) + : X86AsmBackend(T) { + HasAbsolutizedSet = true; + HasScatteredSymbols = true; + } + + MCObjectWriter *createObjectWriter(raw_ostream &OS) const { + return createWinCOFFObjectWriter (OS); + } + + bool isVirtualSection(const MCSection &Section) const { + const MCSectionCOFF &SE = static_cast(Section); + return SE.getCharacteristics() & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA; + } +}; + class DarwinX86AsmBackend : public X86AsmBackend { public: DarwinX86AsmBackend(const Target &T) @@ -290,6 +309,8 @@ TargetAsmBackend *llvm::createX86_32AsmBackend(const Target &T, switch (Triple(TT).getOS()) { case Triple::Darwin: return new DarwinX86_32AsmBackend(T); + case Triple::Win32: + return new WindowsX86AsmBackend(T); default: return new ELFX86_32AsmBackend(T); } diff --git a/lib/Target/X86/X86TargetMachine.cpp b/lib/Target/X86/X86TargetMachine.cpp index 900b516441c..0552a8e6120 100644 --- a/lib/Target/X86/X86TargetMachine.cpp +++ b/lib/Target/X86/X86TargetMachine.cpp @@ -46,6 +46,8 @@ static MCStreamer *createMCStreamer(const Target &T, const std::string &TT, bool RelaxAll) { Triple TheTriple(TT); switch (TheTriple.getOS()) { + case Triple::Win32: + return createWinCOFFStreamer(Ctx, TAB, *_Emitter, _OS); default: return createMachOStreamer(Ctx, TAB, _OS, _Emitter, RelaxAll); } diff --git a/test/MC/COFF/basic-coff.ll b/test/MC/COFF/basic-coff.ll new file mode 100644 index 00000000000..2178bc8a52c --- /dev/null +++ b/test/MC/COFF/basic-coff.ll @@ -0,0 +1,136 @@ +; RUN: llc -filetype=obj %s -o %t +; RUN: coff-dump.py %abs_tmp | FileCheck %s + +; ModuleID = '-' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32" +target triple = "i686-pc-win32" + +@.str = private constant [12 x i8] c"Hello World\00" ; <[12 x i8]*> [#uses=1] + +define i32 @main() nounwind { +entry: + %call = tail call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([12 x i8]* @.str, i32 0, i32 0)) nounwind ; [#uses=0] + ret i32 0 +} + +declare i32 @printf(i8* nocapture, ...) nounwind + +; CHECK: { +; CHECK: MachineType = IMAGE_FILE_MACHINE_I386 (0x14C) +; CHECK: NumberOfSections = 2 +; CHECK: TimeDateStamp = {{[0-9]+}} +; CHECK: PointerToSymbolTable = 0x99 +; CHECK: NumberOfSymbols = 7 +; CHECK: SizeOfOptionalHeader = 0 +; CHECK: Characteristics = 0x0 +; CHECK: Sections = [ +; CHECK: 0 = { +; CHECK: Name = .text +; CHECK: VirtualSize = 0 +; CHECK: VirtualAddress = 0 +; CHECK: SizeOfRawData = 21 +; CHECK: PointerToRawData = 0x64 +; CHECK: PointerToRelocations = 0x79 +; CHECK: PointerToLineNumbers = 0x0 +; CHECK: NumberOfRelocations = 2 +; CHECK: NumberOfLineNumbers = 0 +; CHECK: Charateristics = 0x60500020 +; CHECK: IMAGE_SCN_CNT_CODE +; CHECK: IMAGE_SCN_ALIGN_16BYTES +; CHECK: IMAGE_SCN_MEM_EXECUTE +; CHECK: IMAGE_SCN_MEM_READ +; CHECK: SectionData = +; CHECK: 83 EC 04 C7 04 24 00 00 - 00 00 E8 00 00 00 00 31 |.....$.........1| +; CHECK: C0 83 C4 04 C3 |.....| +; CHECK: Relocations = [ +; CHECK: 0 = { +; CHECK: VirtualAddress = 0x6 +; CHECK: SymbolTableIndex = 5 +; CHECK: Type = IMAGE_REL_I386_DIR32 (6) +; CHECK: SymbolName = _main +; CHECK: } +; CHECK: 1 = { +; CHECK: VirtualAddress = 0xB +; CHECK: SymbolTableIndex = 6 +; CHECK: Type = IMAGE_REL_I386_REL32 (20) +; CHECK: SymbolName = L_.str +; CHECK: } +; CHECK: ] +; CHECK: } +; CHECK: 1 = { +; CHECK: Name = .data +; CHECK: VirtualSize = 0 +; CHECK: VirtualAddress = 0 +; CHECK: SizeOfRawData = 12 +; CHECK: PointerToRawData = 0x8D +; CHECK: PointerToRelocations = 0x0 +; CHECK: PointerToLineNumbers = 0x0 +; CHECK: NumberOfRelocations = 0 +; CHECK: NumberOfLineNumbers = 0 +; CHECK: Charateristics = 0xC0100040 +; CHECK: IMAGE_SCN_CNT_INITIALIZED_DATA +; CHECK: IMAGE_SCN_ALIGN_1BYTES +; CHECK: IMAGE_SCN_MEM_READ +; CHECK: IMAGE_SCN_MEM_WRITE +; CHECK: SectionData = +; CHECK: 48 65 6C 6C 6F 20 57 6F - 72 6C 64 00 |Hello World.| +; CHECK: Relocations = None +; CHECK: } +; CHECK: ] +; CHECK: Symbols = [ +; CHECK: 0 = { +; CHECK: Name = .text +; CHECK: Value = 0 +; CHECK: SectionNumber = 1 +; CHECK: SimpleType = IMAGE_SYM_TYPE_NULL (0) +; CHECK: ComplexType = IMAGE_SYM_DTYPE_NULL (0) +; CHECK: StorageClass = IMAGE_SYM_CLASS_STATIC (3) +; CHECK: NumberOfAuxSymbols = 1 +; CHECK: AuxillaryData = +; CHECK: 15 00 00 00 02 00 00 00 - 00 00 00 00 01 00 00 00 |................| +; CHECK: 00 00 |..| +; CHECK: } +; CHECK: 1 = { +; CHECK: Name = .data +; CHECK: Value = 0 +; CHECK: SectionNumber = 2 +; CHECK: SimpleType = IMAGE_SYM_TYPE_NULL (0) +; CHECK: ComplexType = IMAGE_SYM_DTYPE_NULL (0) +; CHECK: StorageClass = IMAGE_SYM_CLASS_STATIC (3) +; CHECK: NumberOfAuxSymbols = 1 +; CHECK: AuxillaryData = +; CHECK: 0C 00 00 00 00 00 00 00 - 00 00 00 00 02 00 00 00 |................| +; CHECK: 00 00 |..| +; CHECK: } +; CHECK: 2 = { +; CHECK: Name = _main +; CHECK: Value = 0 +; CHECK: SectionNumber = 1 +; CHECK: SimpleType = unknown (32) +; CHECK: ComplexType = IMAGE_SYM_DTYPE_NULL (0) +; CHECK: StorageClass = IMAGE_SYM_CLASS_EXTERNAL (2) +; CHECK: NumberOfAuxSymbols = 0 +; CHECK: AuxillaryData = +; CHECK: } +; CHECK: 3 = { +; CHECK: Name = L_.str +; CHECK: Value = 0 +; CHECK: SectionNumber = 2 +; CHECK: SimpleType = IMAGE_SYM_TYPE_NULL (0) +; CHECK: ComplexType = IMAGE_SYM_DTYPE_NULL (0) +; CHECK: StorageClass = IMAGE_SYM_CLASS_STATIC (3) +; CHECK: NumberOfAuxSymbols = 0 +; CHECK: AuxillaryData = +; CHECK: } +; CHECK: 4 = { +; CHECK: Name = _printf +; CHECK: Value = 0 +; CHECK: SectionNumber = 0 +; CHECK: SimpleType = IMAGE_SYM_TYPE_NULL (0) +; CHECK: ComplexType = IMAGE_SYM_DTYPE_NULL (0) +; CHECK: StorageClass = IMAGE_SYM_CLASS_EXTERNAL (2) +; CHECK: NumberOfAuxSymbols = 0 +; CHECK: AuxillaryData = +; CHECK: } +; CHECK: ] +; CHECK: } diff --git a/test/MC/COFF/dg.exp b/test/MC/COFF/dg.exp new file mode 100644 index 00000000000..7b7bd4e7380 --- /dev/null +++ b/test/MC/COFF/dg.exp @@ -0,0 +1,5 @@ +load_lib llvm.exp + +if { [llvm_supports_target X86] } { + RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll}]] +} diff --git a/test/Scripts/coff-dump.py b/test/Scripts/coff-dump.py new file mode 100644 index 00000000000..b3e16e5015c --- /dev/null +++ b/test/Scripts/coff-dump.py @@ -0,0 +1,543 @@ +#===-- coff-dump.py - COFF object file dump utility-------------------------===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +#===------------------------------------------------------------------------===# + +# +# COFF File Definition +# + +def string_table_entry (offset): + return ('ptr', '+ + PointerToSymbolTable * NumberOfSymbols 18 %s' % offset, ('scalar', 'cstr', '%s')) + +def secname(value): + if value[0] == '/': + return string_table_entry (value [1:].rstrip('\0')) + else: + return '%s' + +def symname(value): + parts = struct.unpack("<2L", value) + if parts [0] == 0: + return string_table_entry (parts [1]) + else: + return '%s' + +file = ('struct', [ + ('MachineType', ('enum', ' 0) + Input.seek (Stack [0]) + del Stack [0] + +def print_binary_data(size): + value = "" + while size > 0: + if size >= 16: + data = Input.read(16) + size -= 16 + else: + data = Input.read(size) + size = 0 + value += data + bytes = "" + text = "" + for index in xrange (16): + if index < len (data): + if index == 8: + bytes += "- " + ch = ord (data [index]) + bytes += "%02X " % ch + if ch >= 0x20 and ch <= 0x7F: + text += data [index] + else: + text += "." + else: + if index == 8: + bytes += " " + bytes += " " + + write ("%s|%s|\n" % (bytes, text)) + return value + +idlit = re.compile ("[a-zA-Z][a-zA-Z0-9_-]*") +numlit = re.compile ("[0-9]+") + +def read_value(expr): + + input = iter (expr.split ()) + + def eval(): + + token = input.next () + + if expr == 'cstr': + return read_cstr () + if expr == 'true': + return True + if expr == 'false': + return False + + if len (token) > 1 and token [0] in ('=', '@', '<', '!', '>'): + val = read(expr) + assert (len (val) == 1) + return val [0] + + if token == '+': + return eval () + eval () + if token == '-': + return eval () - eval () + if token == '*': + return eval () * eval () + if token == '/': + return eval () / eval () + + if idlit.match (token): + return Fields [token] + if numlit.match (token): + return int (token) + + raise RuntimeError ("unexpected token %s" % repr(token)) + + value = eval () + + try: + input.next () + except StopIteration: + return value + raise RuntimeError("unexpected input at end of expression") + +def write_value(format,value): + format_type = type (format) + if format_type is types.StringType: + write (format%value) + elif format_type is types.FunctionType: + write_value (format (value), value) + elif format_type is types.TupleType: + Fields ['this'] = value + handle_element (format) + else: + raise RuntimeError("unexpected type: %s" % repr(format_type)) + +def handle_scalar(entry): + iformat = entry [1] + oformat = entry [2] + + value = read_value (iformat) + + write_value (oformat, value) + + return value + +def handle_enum(entry): + iformat = entry [1] + oformat = entry [2] + definitions = entry [3] + + value = read_value (iformat) + + if type (definitions) is types.TupleType: + selector = read_value (definitions [0]) + definitions = definitions [1] [selector] + + description = definitions[value] if value in definitions else "unknown" + + write ("%s (" % description) + write_value (oformat, value) + write (")") + + return value + +def handle_flags(entry): + iformat = entry [1] + oformat = entry [2] + definitions = entry [3] + + value = read_value (iformat) + + write_value (oformat, value) + + indent () + for entry in definitions: + mask = entry [0] + name = entry [1] + if len (entry) == 3: + map = entry [2] + selection = value & mask + if selection in map: + write("\n%s" % map[selection]) + else: + write("\n%s <%d>" % (name, selection)) + elif len (entry) == 2: + if value & mask != 0: + write("\n%s" % name) + dedent () + + return value + +def handle_struct(entry): + global Fields + members = entry [1] + + newFields = {} + + write ("{\n"); + indent () + + for member in members: + name = member [0] + type = member [1] + + write("%s = "%name.ljust(24)) + + value = handle_element(type) + + write("\n") + + Fields [name] = value + newFields [name] = value + + dedent () + write ("}") + + return newFields + +def handle_array(entry): + length = entry [1] + element = entry [2] + + newItems = [] + + write ("[\n") + indent () + + value = read_value (length) + + for index in xrange (value): + write ("%d = "%index) + value = handle_element(element) + write ("\n") + newItems.append (value) + + dedent () + write ("]") + + return newItems + +def handle_byte_array(entry): + length = entry [1] + element = entry [2] + + newItems = [] + + write ("[\n") + indent () + + value = read_value (length) + end_of_array = Input.tell () + value + + index = 0 + while Input.tell () < end_of_array: + write ("%d = "%index) + value = handle_element(element) + write ("\n") + newItems.append (value) + index += 1 + + dedent () + write ("]") + + return newItems + +def handle_ptr(entry): + offset = entry[1] + element = entry [2] + + value = None + offset = read_value (offset) + + if offset != 0: + + push_pos (offset) + + value = handle_element (element) + + pop_pos () + + else: + write ("None") + + return value + +def handle_blob(entry): + length = entry [1] + + write ("\n") + indent () + + value = print_binary_data (read_value (length)) + + dedent () + + return value + +def handle_element(entry): + handlers = { + 'struct': handle_struct, + 'scalar': handle_scalar, + 'enum': handle_enum, + 'flags': handle_flags, + 'ptr': handle_ptr, + 'blob': handle_blob, + 'array': handle_array, + 'byte-array': handle_byte_array, + } + + if not entry [0] in handlers: + raise RuntimeError ("unexpected type '%s'" % str (entry[0])) + + return handlers [entry [0]] (entry) + +Input = open (sys.argv [1], "rb") +try: + handle_element (file) +finally: + Input.close () + Input = None diff --git a/test/Scripts/coff-dump.py.bat b/test/Scripts/coff-dump.py.bat new file mode 100644 index 00000000000..cc83eba1c44 --- /dev/null +++ b/test/Scripts/coff-dump.py.bat @@ -0,0 +1,4 @@ +@echo off + +%PYTHON_EXECUTABLE% %LLVM_SRC_ROOT%\test\Scripts\coff-dump.py %1 %2 %3 %4 %5 %6 %7 %8 %9 + -- 2.34.1