diff --git a/docs/LangRef.html b/docs/LangRef.html index 32441cc540a..f0a171be8af 100644 --- a/docs/LangRef.html +++ b/docs/LangRef.html @@ -2403,9 +2403,10 @@ cleanup is performed in the case of either a longjmp or a thrown exception. Additionally, this is important for implementation of 'catch' clauses in high-level languages that support them.

-

It is not valid to reference the return value of an invoke call from -anywhere not dominated by the normal label, since an unwind does not -provide a return value.

+

For the purposes of the SSA form, the definition of the value +returned by the 'invoke' instruction is deemed to occur on +the edge from the current block to the "normal" label. If the callee +unwinds then no return value is available.

Example:
@@ -4518,6 +4519,11 @@ may be used as the label arguments.

block and the PHI instructions: i.e. PHI instructions must be first in a basic block.

+

For the purposes of the SSA form, the use of each incoming value is +deemed to occur on the edge from the corresponding predecessor block +to the current block (but after any definition of an 'invoke' +instruction's return value on the same edge).

+
Semantics:

At runtime, the 'phi' instruction logically takes on the value @@ -7104,7 +7110,7 @@ declare void @llvm.stackprotector( i8* <guard>, i8** <slot> ) Chris Lattner
The LLVM Compiler Infrastructure
- Last modified: $Date: 2009-05-30 18:08:30 +0200 (Sat, 30 May 2009) $ + Last modified: $Date: 2009-06-03 12:20:10 +0200 (Wed, 03 Jun 2009) $ diff --git a/include/llvm/ADT/ilist.h b/include/llvm/ADT/ilist.h index 9eb70055284..b95e3e04e81 100644 --- a/include/llvm/ADT/ilist.h +++ b/include/llvm/ADT/ilist.h @@ -481,8 +481,8 @@ private: L2.setTail(0); // Remove [first, last) from its old position. - NodeTy *First = &*first, *Prev = getPrev(First); - NodeTy *Next = last.getNodePtrUnchecked(), *Last = getPrev(Next); + NodeTy *First = &*first, *Prev = this->getPrev(First); + NodeTy *Next = last.getNodePtrUnchecked(), *Last = this->getPrev(Next); if (Prev) this->setNext(Prev, Next); else @@ -491,7 +491,7 @@ private: // Splice [first, last) into its new position. NodeTy *PosNext = position.getNodePtrUnchecked(); - NodeTy *PosPrev = getPrev(PosNext); + NodeTy *PosPrev = this->getPrev(PosNext); // Fix head of list... if (PosPrev) @@ -504,7 +504,7 @@ private: this->setNext(Last, PosNext); this->setPrev(PosNext, Last); - transferNodesFromList(L2, First, PosNext); + this->transferNodesFromList(L2, First, PosNext); // Now that everything is set, restore the pointers to the list sentinels. L2.setTail(L2Sentinel); diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h index bf360f7e884..5fdf6d2c916 100644 --- a/include/llvm/Analysis/ConstantFolding.h +++ b/include/llvm/Analysis/ConstantFolding.h @@ -34,7 +34,7 @@ Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0); /// using the specified TargetData. If successful, the constant result is /// result is returned, if not, null is returned. Constant *ConstantFoldConstantExpression(ConstantExpr *CE, - const TargetData *TD); + const TargetData *TD = 0); /// ConstantFoldInstOperands - Attempt to constant fold an instruction with the /// specified operands. If successful, the constant result is returned, if not, diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h index 264447ef86a..1978055b1af 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpressions.h +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -19,7 +19,6 @@ namespace llvm { class ConstantInt; class ConstantRange; - class APInt; class DominatorTree; enum SCEVTypes { diff --git a/include/llvm/Support/TargetFolder.h b/include/llvm/Support/TargetFolder.h index 14f2c9b244f..172e4fe123d 100644 --- a/include/llvm/Support/TargetFolder.h +++ b/include/llvm/Support/TargetFolder.h @@ -9,8 +9,10 @@ // // This file defines the TargetFolder class, a helper for IRBuilder. // It provides IRBuilder with a set of methods for creating constants with -// target dependent folding. For general constant creation and folding, -// use ConstantExpr and the routines in llvm/Analysis/ConstantFolding.h. +// target dependent folding, in addition to the same target-independent +// folding that the ConstantFolder class provides. For general constant +// creation and folding, use ConstantExpr and the routines in +// llvm/Analysis/ConstantFolding.h. // //===----------------------------------------------------------------------===// @@ -26,18 +28,18 @@ class TargetData; /// TargetFolder - Create constants with target dependent folding. class TargetFolder { - const TargetData &TD; + const TargetData *TD; /// Fold - Fold the constant using target specific information. Constant *Fold(Constant *C) const { if (ConstantExpr *CE = dyn_cast(C)) - if (Constant *CF = ConstantFoldConstantExpression(CE, &TD)) + if (Constant *CF = ConstantFoldConstantExpression(CE, TD)) return CF; return C; } public: - TargetFolder(const TargetData &TheTD) : TD(TheTD) {} + explicit TargetFolder(const TargetData *TheTD) : TD(TheTD) {} //===--------------------------------------------------------------------===// // Binary Operators diff --git a/lib/Analysis/ConstantFolding.cpp b/lib/Analysis/ConstantFolding.cpp index e5ab3226ce4..261c635feb4 100644 --- a/lib/Analysis/ConstantFolding.cpp +++ b/lib/Analysis/ConstantFolding.cpp @@ -317,8 +317,6 @@ Constant *llvm::ConstantFoldInstruction(Instruction *I, const TargetData *TD) { /// result is returned, if not, null is returned. Constant *llvm::ConstantFoldConstantExpression(ConstantExpr *CE, const TargetData *TD) { - assert(TD && "ConstantFoldConstantExpression requires a valid TargetData."); - SmallVector Ops; for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i) Ops.push_back(cast(*i)); diff --git a/lib/CodeGen/LiveVariables.cpp b/lib/CodeGen/LiveVariables.cpp index c33d81e8a87..62288216912 100644 --- a/lib/CodeGen/LiveVariables.cpp +++ b/lib/CodeGen/LiveVariables.cpp @@ -242,20 +242,6 @@ void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr *MI) { } } - // There was an earlier def of a super-register. Add implicit def to that MI. - // - // A: EAX = ... - // B: ... = AX - // - // Add implicit def to A if there isn't a use of AX (or EAX) before B. - if (!PhysRegUse[Reg]) { - MachineInstr *Def = PhysRegDef[Reg]; - if (Def && !Def->modifiesRegister(Reg)) - Def->addOperand(MachineOperand::CreateReg(Reg, - true /*IsDef*/, - true /*IsImp*/)); - } - // Remember this use. PhysRegUse[Reg] = MI; for (const unsigned *SubRegs = TRI->getSubRegisters(Reg); diff --git a/lib/CodeGen/MachO.h b/lib/CodeGen/MachO.h new file mode 100644 index 00000000000..bd9bd61e9ed --- /dev/null +++ b/lib/CodeGen/MachO.h @@ -0,0 +1,423 @@ +//=== MachO.h - Mach-O structures and constants -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines MachO . +// +//===----------------------------------------------------------------------===// + +#ifndef MACHO_H +#define MACHO_H + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/CodeGen/MachineRelocation.h" +#include "llvm/Target/TargetAsmInfo.h" +#include +#include + +namespace llvm { + +typedef std::vector DataBuffer; + +/// MachOSym - This struct contains information about each symbol that is +/// added to logical symbol table for the module. This is eventually +/// turned into a real symbol table in the file. +struct MachOSym { + const GlobalValue *GV; // The global value this corresponds to. + std::string GVName; // The mangled name of the global value. + uint32_t n_strx; // index into the string table + uint8_t n_type; // type flag + uint8_t n_sect; // section number or NO_SECT + int16_t n_desc; // see + uint64_t n_value; // value for this symbol (or stab offset) + + // Constants for the n_sect field + // see + enum { NO_SECT = 0 }; // symbol is not in any section + + // Constants for the n_type field + // see + enum { N_UNDF = 0x0, // undefined, n_sect == NO_SECT + N_ABS = 0x2, // absolute, n_sect == NO_SECT + N_SECT = 0xe, // defined in section number n_sect + N_PBUD = 0xc, // prebound undefined (defined in a dylib) + N_INDR = 0xa // indirect + }; + // The following bits are OR'd into the types above. For example, a type + // of 0x0f would be an external N_SECT symbol (0x0e | 0x01). + enum { N_EXT = 0x01, // external symbol bit + N_PEXT = 0x10 // private external symbol bit + }; + + // Constants for the n_desc field + // see + enum { REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, + REFERENCE_FLAG_UNDEFINED_LAZY = 1, + REFERENCE_FLAG_DEFINED = 2, + REFERENCE_FLAG_PRIVATE_DEFINED = 3, + REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, + REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5 + }; + enum { N_NO_DEAD_STRIP = 0x0020, // symbol is not to be dead stripped + N_WEAK_REF = 0x0040, // symbol is weak referenced + N_WEAK_DEF = 0x0080 // coalesced symbol is a weak definition + }; + + MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, + const TargetAsmInfo *TAI); + + struct SymCmp { + // FIXME: this does not appear to be sorting 'f' after 'F' + bool operator()(const MachOSym &LHS, const MachOSym &RHS) { + return LHS.GVName < RHS.GVName; + } + }; + + + /// PartitionByLocal - Simple boolean predicate that returns true if Sym is + /// a local symbol rather than an external symbol. + + static inline bool PartitionByLocal(const MachOSym &Sym) { + return (Sym.n_type & (MachOSym::N_EXT | MachOSym::N_PEXT)) == 0; + } + + /// PartitionByDefined - Simple boolean predicate that returns true if Sym is + /// defined in this module. + + static inline bool PartitionByDefined(const MachOSym &Sym) { + // FIXME: Do N_ABS or N_INDR count as defined? + return (Sym.n_type & MachOSym::N_SECT) == MachOSym::N_SECT; + } + +}; // end struct MachOSym + +/// MachOHeader - This struct contains the header information about a +/// specific architecture type/subtype pair that is emitted to the file. + +struct MachOHeader { + uint32_t magic; // mach magic number identifier + uint32_t filetype; // type of file + uint32_t ncmds; // number of load commands + uint32_t sizeofcmds; // the size of all the load commands + uint32_t flags; // flags + uint32_t reserved; // 64-bit only + + /// HeaderData - The actual data for the header which we are building + /// up for emission to the file. + DataBuffer HeaderData; + + // Constants for the filetype field + // see for additional info on the various types + enum { MH_OBJECT = 1, // relocatable object file + MH_EXECUTE = 2, // demand paged executable file + MH_FVMLIB = 3, // fixed VM shared library file + MH_CORE = 4, // core file + MH_PRELOAD = 5, // preloaded executable file + MH_DYLIB = 6, // dynamically bound shared library + MH_DYLINKER = 7, // dynamic link editor + MH_BUNDLE = 8, // dynamically bound bundle file + MH_DYLIB_STUB = 9, // shared library stub for static linking only + MH_DSYM = 10 // companion file wiht only debug sections + }; + + // Constants for the flags field + enum { MH_NOUNDEFS = 1 << 0, + // the object file has no undefined references + MH_INCRLINK = 1 << 1, + // the object file is the output of an incremental link against + // a base file and cannot be link edited again + MH_DYLDLINK = 1 << 2, + // the object file is input for the dynamic linker and cannot be + // statically link edited again. + MH_BINDATLOAD = 1 << 3, + // the object file's undefined references are bound by the + // dynamic linker when loaded. + MH_PREBOUND = 1 << 4, + // the file has its dynamic undefined references prebound + MH_SPLIT_SEGS = 1 << 5, + // the file has its read-only and read-write segments split + // see + MH_LAZY_INIT = 1 << 6, + // the shared library init routine is to be run lazily via + // catching memory faults to its writable segments (obsolete) + MH_TWOLEVEL = 1 << 7, + // the image is using two-level namespace bindings + MH_FORCE_FLAT = 1 << 8, + // the executable is forcing all images to use flat namespace + // bindings. + MH_NOMULTIDEFS = 1 << 8, + // this umbrella guarantees no multiple definitions of symbols + // in its sub-images so the two-level namespace hints can + // always be used. + MH_NOFIXPREBINDING = 1 << 10, + // do not have dyld notify the prebidning agent about this + // executable. + MH_PREBINDABLE = 1 << 11, + // the binary is not prebound but can have its prebinding + // redone. only used when MH_PREBOUND is not set. + MH_ALLMODSBOUND = 1 << 12, + // indicates that this binary binds to all two-level namespace + // modules of its dependent libraries. Only used when + // MH_PREBINDABLE and MH_TWOLEVEL are both set. + MH_SUBSECTIONS_VIA_SYMBOLS = 1 << 13, + // safe to divide up the sections into sub-sections via symbols + // for dead code stripping. + MH_CANONICAL = 1 << 14, + // the binary has been canonicalized via the unprebind operation + MH_WEAK_DEFINES = 1 << 15, + // the final linked image contains external weak symbols + MH_BINDS_TO_WEAK = 1 << 16, + // the final linked image uses weak symbols + MH_ALLOW_STACK_EXECUTION = 1 << 17 + // When this bit is set, all stacks in the task will be given + // stack execution privilege. Only used in MH_EXECUTE filetype + }; + + MachOHeader() : magic(0), filetype(0), ncmds(0), sizeofcmds(0), flags(0), + reserved(0) { } + + /// cmdSize - This routine returns the size of the MachOSection as written + /// to disk, depending on whether the destination is a 64 bit Mach-O file. + unsigned cmdSize(bool is64Bit) const { + if (is64Bit) + return 8 * sizeof(uint32_t); + else + return 7 * sizeof(uint32_t); + } + + /// setMagic - This routine sets the appropriate value for the 'magic' + /// field based on pointer size and endianness. + void setMagic(bool isLittleEndian, bool is64Bit) { + if (isLittleEndian) + if (is64Bit) magic = 0xcffaedfe; + else magic = 0xcefaedfe; + else + if (is64Bit) magic = 0xfeedfacf; + else magic = 0xfeedface; + } + +}; // end struct MachOHeader + +/// MachOSegment - This struct contains the necessary information to +/// emit the load commands for each section in the file. +struct MachOSegment { + uint32_t cmd; // LC_SEGMENT or LC_SEGMENT_64 + uint32_t cmdsize; // Total size of this struct and section commands + std::string segname; // segment name + uint64_t vmaddr; // address of this segment + uint64_t vmsize; // size of this segment, may be larger than filesize + uint64_t fileoff; // offset in file + uint64_t filesize; // amount to read from file + uint32_t maxprot; // maximum VM protection + uint32_t initprot; // initial VM protection + uint32_t nsects; // number of sections in this segment + uint32_t flags; // flags + + // The following constants are getting pulled in by one of the + // system headers, which creates a neat clash with the enum. +#if !defined(VM_PROT_NONE) +#define VM_PROT_NONE 0x00 +#endif +#if !defined(VM_PROT_READ) +#define VM_PROT_READ 0x01 +#endif +#if !defined(VM_PROT_WRITE) +#define VM_PROT_WRITE 0x02 +#endif +#if !defined(VM_PROT_EXECUTE) +#define VM_PROT_EXECUTE 0x04 +#endif +#if !defined(VM_PROT_ALL) +#define VM_PROT_ALL 0x07 +#endif + + // Constants for the vm protection fields + // see + enum { SEG_VM_PROT_NONE = VM_PROT_NONE, + SEG_VM_PROT_READ = VM_PROT_READ, // read permission + SEG_VM_PROT_WRITE = VM_PROT_WRITE, // write permission + SEG_VM_PROT_EXECUTE = VM_PROT_EXECUTE, + SEG_VM_PROT_ALL = VM_PROT_ALL + }; + + // Constants for the cmd field + // see + enum { LC_SEGMENT = 0x01, // segment of this file to be mapped + LC_SEGMENT_64 = 0x19 // 64-bit segment of this file to be mapped + }; + + /// cmdSize - This routine returns the size of the MachOSection as written + /// to disk, depending on whether the destination is a 64 bit Mach-O file. + unsigned cmdSize(bool is64Bit) const { + if (is64Bit) + return 6 * sizeof(uint32_t) + 4 * sizeof(uint64_t) + 16; + else + return 10 * sizeof(uint32_t) + 16; // addresses only 32 bits + } + + MachOSegment(const std::string &seg, bool is64Bit) + : cmd(is64Bit ? LC_SEGMENT_64 : LC_SEGMENT), cmdsize(0), segname(seg), + vmaddr(0), vmsize(0), fileoff(0), filesize(0), maxprot(VM_PROT_ALL), + initprot(VM_PROT_ALL), nsects(0), flags(0) { } +}; + +/// MachOSection - This struct contains information about each section in a +/// particular segment that is emitted to the file. This is eventually +/// turned into the SectionCommand in the load command for a particlar +/// segment. + +struct MachOSection { + std::string sectname; // name of this section, + std::string segname; // segment this section goes in + uint64_t addr; // memory address of this section + uint64_t size; // size in bytes of this section + uint32_t offset; // file offset of this section + uint32_t align; // section alignment (power of 2) + uint32_t reloff; // file offset of relocation entries + uint32_t nreloc; // number of relocation entries + uint32_t flags; // flags (section type and attributes) + uint32_t reserved1; // reserved (for offset or index) + uint32_t reserved2; // reserved (for count or sizeof) + uint32_t reserved3; // reserved (64 bit only) + + /// A unique number for this section, which will be used to match symbols + /// to the correct section. + uint32_t Index; + + /// SectionData - The actual data for this section which we are building + /// up for emission to the file. + DataBuffer SectionData; + + /// RelocBuffer - A buffer to hold the mach-o relocations before we write + /// them out at the appropriate location in the file. + DataBuffer RelocBuffer; + + /// Relocations - The relocations that we have encountered so far in this + /// section that we will need to convert to MachORelocation entries when + /// the file is written. + std::vector Relocations; + + // Constants for the section types (low 8 bits of flags field) + // see + enum { S_REGULAR = 0, + // regular section + S_ZEROFILL = 1, + // zero fill on demand section + S_CSTRING_LITERALS = 2, + // section with only literal C strings + S_4BYTE_LITERALS = 3, + // section with only 4 byte literals + S_8BYTE_LITERALS = 4, + // section with only 8 byte literals + S_LITERAL_POINTERS = 5, + // section with only pointers to literals + S_NON_LAZY_SYMBOL_POINTERS = 6, + // section with only non-lazy symbol pointers + S_LAZY_SYMBOL_POINTERS = 7, + // section with only lazy symbol pointers + S_SYMBOL_STUBS = 8, + // section with only symbol stubs + // byte size of stub in the reserved2 field + S_MOD_INIT_FUNC_POINTERS = 9, + // section with only function pointers for initialization + S_MOD_TERM_FUNC_POINTERS = 10, + // section with only function pointers for termination + S_COALESCED = 11, + // section contains symbols that are coalesced + S_GB_ZEROFILL = 12, + // zero fill on demand section (that can be larger than 4GB) + S_INTERPOSING = 13, + // section with only pairs of function pointers for interposing + S_16BYTE_LITERALS = 14 + // section with only 16 byte literals + }; + + // Constants for the section flags (high 24 bits of flags field) + // see + enum { S_ATTR_PURE_INSTRUCTIONS = 1 << 31, + // section contains only true machine instructions + S_ATTR_NO_TOC = 1 << 30, + // section contains coalesced symbols that are not to be in a + // ranlib table of contents + S_ATTR_STRIP_STATIC_SYMS = 1 << 29, + // ok to strip static symbols in this section in files with the + // MY_DYLDLINK flag + S_ATTR_NO_DEAD_STRIP = 1 << 28, + // no dead stripping + S_ATTR_LIVE_SUPPORT = 1 << 27, + // blocks are live if they reference live blocks + S_ATTR_SELF_MODIFYING_CODE = 1 << 26, + // used with i386 code stubs written on by dyld + S_ATTR_DEBUG = 1 << 25, + // a debug section + S_ATTR_SOME_INSTRUCTIONS = 1 << 10, + // section contains some machine instructions + S_ATTR_EXT_RELOC = 1 << 9, + // section has external relocation entries + S_ATTR_LOC_RELOC = 1 << 8 + // section has local relocation entries + }; + + /// cmdSize - This routine returns the size of the MachOSection as written + /// to disk, depending on whether the destination is a 64 bit Mach-O file. + unsigned cmdSize(bool is64Bit) const { + if (is64Bit) + return 7 * sizeof(uint32_t) + 2 * sizeof(uint64_t) + 32; + else + return 9 * sizeof(uint32_t) + 32; // addresses only 32 bits + } + + MachOSection(const std::string &seg, const std::string §) + : sectname(sect), segname(seg), addr(0), size(0), offset(0), align(2), + reloff(0), nreloc(0), flags(0), reserved1(0), reserved2(0), + reserved3(0) { } + +}; // end struct MachOSection + + /// MachOSymTab - This struct contains information about the offsets and + /// size of symbol table information. + /// segment. + struct MachODySymTab { + uint32_t cmd; // LC_DYSYMTAB + uint32_t cmdsize; // sizeof( MachODySymTab ) + uint32_t ilocalsym; // index to local symbols + uint32_t nlocalsym; // number of local symbols + uint32_t iextdefsym; // index to externally defined symbols + uint32_t nextdefsym; // number of externally defined symbols + uint32_t iundefsym; // index to undefined symbols + uint32_t nundefsym; // number of undefined symbols + uint32_t tocoff; // file offset to table of contents + uint32_t ntoc; // number of entries in table of contents + uint32_t modtaboff; // file offset to module table + uint32_t nmodtab; // number of module table entries + uint32_t extrefsymoff; // offset to referenced symbol table + uint32_t nextrefsyms; // number of referenced symbol table entries + uint32_t indirectsymoff; // file offset to the indirect symbol table + uint32_t nindirectsyms; // number of indirect symbol table entries + uint32_t extreloff; // offset to external relocation entries + uint32_t nextrel; // number of external relocation entries + uint32_t locreloff; // offset to local relocation entries + uint32_t nlocrel; // number of local relocation entries + + // Constants for the cmd field + // see + enum { LC_DYSYMTAB = 0x0B // dynamic link-edit symbol table info + }; + + MachODySymTab() : cmd(LC_DYSYMTAB), cmdsize(20 * sizeof(uint32_t)), + ilocalsym(0), nlocalsym(0), iextdefsym(0), nextdefsym(0), + iundefsym(0), nundefsym(0), tocoff(0), ntoc(0), modtaboff(0), + nmodtab(0), extrefsymoff(0), nextrefsyms(0), indirectsymoff(0), + nindirectsyms(0), extreloff(0), nextrel(0), locreloff(0), nlocrel(0) { } + }; + +} // end namespace llvm + +#endif + diff --git a/lib/CodeGen/MachOCodeEmitter.cpp b/lib/CodeGen/MachOCodeEmitter.cpp new file mode 100644 index 00000000000..02b02de9ec3 --- /dev/null +++ b/lib/CodeGen/MachOCodeEmitter.cpp @@ -0,0 +1,207 @@ +//===-- MachOEmitter.cpp - Target-independent Mach-O Emitter code --------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "MachOCodeEmitter.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineJumpTableInfo.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/OutputBuffer.h" + +//===----------------------------------------------------------------------===// +// MachOCodeEmitter Implementation +//===----------------------------------------------------------------------===// + +namespace llvm { + +/// startFunction - This callback is invoked when a new machine function is +/// about to be emitted. + +void MachOCodeEmitter::startFunction(MachineFunction &MF) { + const TargetData *TD = TM.getTargetData(); + const Function *F = MF.getFunction(); + + // Align the output buffer to the appropriate alignment, power of 2. + unsigned FnAlign = F->getAlignment(); + unsigned TDAlign = TD->getPrefTypeAlignment(F->getType()); + unsigned Align = Log2_32(std::max(FnAlign, TDAlign)); + assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); + + // Get the Mach-O Section that this function belongs in. + MachOSection *MOS = MOW.getTextSection(); + + // FIXME: better memory management + MOS->SectionData.reserve(4096); + BufferBegin = &MOS->SectionData[0]; + BufferEnd = BufferBegin + MOS->SectionData.capacity(); + + // Upgrade the section alignment if required. + if (MOS->align < Align) MOS->align = Align; + + // Round the size up to the correct alignment for starting the new function. + if ((MOS->size & ((1 << Align) - 1)) != 0) { + MOS->size += (1 << Align); + MOS->size &= ~((1 << Align) - 1); + } + + // FIXME: Using MOS->size directly here instead of calculating it from the + // output buffer size (impossible because the code emitter deals only in raw + // bytes) forces us to manually synchronize size and write padding zero bytes + // to the output buffer for all non-text sections. For text sections, we do + // not synchonize the output buffer, and we just blow up if anyone tries to + // write non-code to it. An assert should probably be added to + // AddSymbolToSection to prevent calling it on the text section. + CurBufferPtr = BufferBegin + MOS->size; +} + +/// finishFunction - This callback is invoked after the function is completely +/// finished. + +bool MachOCodeEmitter::finishFunction(MachineFunction &MF) { + + // Get the Mach-O Section that this function belongs in. + MachOSection *MOS = MOW.getTextSection(); + + // Get a symbol for the function to add to the symbol table + // FIXME: it seems like we should call something like AddSymbolToSection + // in startFunction rather than changing the section size and symbol n_value + // here. + const GlobalValue *FuncV = MF.getFunction(); + MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index, TAI); + FnSym.n_value = MOS->size; + MOS->size = CurBufferPtr - BufferBegin; + + // Emit constant pool to appropriate section(s) + emitConstantPool(MF.getConstantPool()); + + // Emit jump tables to appropriate section + emitJumpTables(MF.getJumpTableInfo()); + + // If we have emitted any relocations to function-specific objects such as + // basic blocks, constant pools entries, or jump tables, record their + // addresses now so that we can rewrite them with the correct addresses + // later. + for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { + MachineRelocation &MR = Relocations[i]; + intptr_t Addr; + + if (MR.isBasicBlock()) { + Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); + MR.setConstantVal(MOS->Index); + MR.setResultPointer((void*)Addr); + } else if (MR.isJumpTableIndex()) { + Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); + MR.setConstantVal(MOW.getJumpTableSection()->Index); + MR.setResultPointer((void*)Addr); + } else if (MR.isConstantPoolIndex()) { + Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); + MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); + MR.setResultPointer((void*)Addr); + } else if (MR.isGlobalValue()) { + // FIXME: This should be a set or something that uniques + MOW.PendingGlobals.push_back(MR.getGlobalValue()); + } else { + assert(0 && "Unhandled relocation type"); + } + MOS->Relocations.push_back(MR); + } + Relocations.clear(); + + // Finally, add it to the symtab. + MOW.SymbolTable.push_back(FnSym); + + // Clear per-function data structures. + CPLocations.clear(); + CPSections.clear(); + JTLocations.clear(); + MBBLocations.clear(); + + return false; +} + +/// emitConstantPool - For each constant pool entry, figure out which section +/// the constant should live in, allocate space for it, and emit it to the +/// Section data buffer. +void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { + const std::vector &CP = MCP->getConstants(); + if (CP.empty()) return; + + // FIXME: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for mach-o jump tables!"); + + // Although there is no strict necessity that I am aware of, we will do what + // gcc for OS X does and put each constant pool entry in a section of constant + // objects of a certain size. That means that float constants go in the + // literal4 section, and double objects go in literal8, etc. + // + // FIXME: revisit this decision if we ever do the "stick everything into one + // "giant object for PIC" optimization. + for (unsigned i = 0, e = CP.size(); i != e; ++i) { + const Type *Ty = CP[i].getType(); + unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); + + MachOSection *Sec = MOW.getConstSection(CP[i].Val.ConstVal); + OutputBuffer SecDataOut(Sec->SectionData, is64Bit, isLittleEndian); + + CPLocations.push_back(Sec->SectionData.size()); + CPSections.push_back(Sec->Index); + + // FIXME: remove when we have unified size + output buffer + Sec->size += Size; + + // Allocate space in the section for the global. + // FIXME: need alignment? + // FIXME: share between here and AddSymbolToSection? + for (unsigned j = 0; j < Size; ++j) + SecDataOut.outbyte(0); + + MOW.InitMem(CP[i].Val.ConstVal, &Sec->SectionData[0], CPLocations[i], + TM.getTargetData(), Sec->Relocations); + } +} + +/// emitJumpTables - Emit all the jump tables for a given jump table info +/// record to the appropriate section. + +void MachOCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { + const std::vector &JT = MJTI->getJumpTables(); + if (JT.empty()) return; + + // FIXME: handle PIC codegen + assert(TM.getRelocationModel() != Reloc::PIC_ && + "PIC codegen not yet handled for mach-o jump tables!"); + + MachOSection *Sec = MOW.getJumpTableSection(); + unsigned TextSecIndex = MOW.getTextSection()->Index; + OutputBuffer SecDataOut(Sec->SectionData, is64Bit, isLittleEndian); + + for (unsigned i = 0, e = JT.size(); i != e; ++i) { + // For each jump table, record its offset from the start of the section, + // reserve space for the relocations to the MBBs, and add the relocations. + const std::vector &MBBs = JT[i].MBBs; + JTLocations.push_back(Sec->SectionData.size()); + for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { + MachineRelocation MR(MOW.GetJTRelocation(Sec->SectionData.size(), + MBBs[mi])); + MR.setResultPointer((void *)JTLocations[i]); + MR.setConstantVal(TextSecIndex); + Sec->Relocations.push_back(MR); + SecDataOut.outaddr(0); + } + } + // FIXME: remove when we have unified size + output buffer + Sec->size = Sec->SectionData.size(); +} + +} // end namespace llvm + diff --git a/lib/CodeGen/MachOCodeEmitter.h b/lib/CodeGen/MachOCodeEmitter.h new file mode 100644 index 00000000000..0a6e4e4d19e --- /dev/null +++ b/lib/CodeGen/MachOCodeEmitter.h @@ -0,0 +1,129 @@ +//===-- MachOEmitter.h - Target-independent Mach-O Emitter class ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef MACHOCODEEMITTER_H +#define MACHOCODEEMITTER_H + +#include "MachOWriter.h" +#include "llvm/CodeGen/MachineCodeEmitter.h" +#include + +namespace llvm { + +/// MachOCodeEmitter - This class is used by the MachOWriter to emit the code +/// for functions to the Mach-O file. + +class MachOCodeEmitter : public MachineCodeEmitter { + MachOWriter &MOW; + + /// Target machine description. + TargetMachine &TM; + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating what header values and flags to set. + bool is64Bit, isLittleEndian; + + const TargetAsmInfo *TAI; + + /// Relocations - These are the relocations that the function needs, as + /// emitted. + std::vector Relocations; + + /// CPLocations - This is a map of constant pool indices to offsets from the + /// start of the section for that constant pool index. + std::vector CPLocations; + + /// CPSections - This is a map of constant pool indices to the MachOSection + /// containing the constant pool entry for that index. + std::vector CPSections; + + /// JTLocations - This is a map of jump table indices to offsets from the + /// start of the section for that jump table index. + std::vector JTLocations; + + /// MBBLocations - This vector is a mapping from MBB ID's to their address. + /// It is filled in by the StartMachineBasicBlock callback and queried by + /// the getMachineBasicBlockAddress callback. + std::vector MBBLocations; + +public: + MachOCodeEmitter(MachOWriter &mow) : MOW(mow), TM(MOW.TM) + { + is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; + isLittleEndian = TM.getTargetData()->isLittleEndian(); + TAI = TM.getTargetAsmInfo(); + } + + virtual void startFunction(MachineFunction &MF); + virtual bool finishFunction(MachineFunction &MF); + + virtual void addRelocation(const MachineRelocation &MR) { + Relocations.push_back(MR); + } + + void emitConstantPool(MachineConstantPool *MCP); + void emitJumpTables(MachineJumpTableInfo *MJTI); + + virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { + assert(CPLocations.size() > Index && "CP not emitted!"); + return CPLocations[Index]; + } + virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { + assert(JTLocations.size() > Index && "JT not emitted!"); + return JTLocations[Index]; + } + + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { + if (MBBLocations.size() <= (unsigned)MBB->getNumber()) + MBBLocations.resize((MBB->getNumber()+1)*2); + MBBLocations[MBB->getNumber()] = getCurrentPCOffset(); + } + + virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { + assert(MBBLocations.size() > (unsigned)MBB->getNumber() && + MBBLocations[MBB->getNumber()] && "MBB not emitted!"); + return MBBLocations[MBB->getNumber()]; + } + + virtual uintptr_t getLabelAddress(uint64_t Label) const { + assert(0 && "get Label not implemented"); + abort(); + return 0; + } + + virtual void emitLabel(uint64_t LabelID) { + assert(0 && "emit Label not implemented"); + abort(); + } + + virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } + + /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! + virtual void startGVStub(const GlobalValue* F, unsigned StubSize, + unsigned Alignment = 1) { + assert(0 && "JIT specific function called!"); + abort(); + } + virtual void startGVStub(const GlobalValue* F, void *Buffer, + unsigned StubSize) { + assert(0 && "JIT specific function called!"); + abort(); + } + virtual void *finishGVStub(const GlobalValue* F) { + assert(0 && "JIT specific function called!"); + abort(); + return 0; + } + +}; // end class MachOCodeEmitter + +} // end namespace llvm + +#endif + diff --git a/lib/CodeGen/MachOWriter.cpp b/lib/CodeGen/MachOWriter.cpp index 43326272c1b..163df6994aa 100644 --- a/lib/CodeGen/MachOWriter.cpp +++ b/lib/CodeGen/MachOWriter.cpp @@ -23,6 +23,7 @@ //===----------------------------------------------------------------------===// #include "MachOWriter.h" +#include "MachOCodeEmitter.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" @@ -40,11 +41,12 @@ #include "llvm/Support/raw_ostream.h" #include #include -using namespace llvm; + +namespace llvm { /// AddMachOWriter - Concrete function to add the Mach-O writer to the function /// pass manager. -MachineCodeEmitter *llvm::AddMachOWriter(PassManagerBase &PM, +MachineCodeEmitter *AddMachOWriter(PassManagerBase &PM, raw_ostream &O, TargetMachine &TM) { MachOWriter *MOW = new MachOWriter(O, TM); @@ -52,300 +54,21 @@ MachineCodeEmitter *llvm::AddMachOWriter(PassManagerBase &PM, return &MOW->getMachineCodeEmitter(); } -//===----------------------------------------------------------------------===// -// MachOCodeEmitter Implementation -//===----------------------------------------------------------------------===// - -namespace llvm { - /// MachOCodeEmitter - This class is used by the MachOWriter to emit the code - /// for functions to the Mach-O file. - class MachOCodeEmitter : public MachineCodeEmitter { - MachOWriter &MOW; - - /// Target machine description. - TargetMachine &TM; - - /// is64Bit/isLittleEndian - This information is inferred from the target - /// machine directly, indicating what header values and flags to set. - bool is64Bit, isLittleEndian; - - /// Relocations - These are the relocations that the function needs, as - /// emitted. - std::vector Relocations; - - /// CPLocations - This is a map of constant pool indices to offsets from the - /// start of the section for that constant pool index. - std::vector CPLocations; - - /// CPSections - This is a map of constant pool indices to the MachOSection - /// containing the constant pool entry for that index. - std::vector CPSections; - - /// JTLocations - This is a map of jump table indices to offsets from the - /// start of the section for that jump table index. - std::vector JTLocations; - - /// MBBLocations - This vector is a mapping from MBB ID's to their address. - /// It is filled in by the StartMachineBasicBlock callback and queried by - /// the getMachineBasicBlockAddress callback. - std::vector MBBLocations; - - public: - MachOCodeEmitter(MachOWriter &mow) : MOW(mow), TM(MOW.TM) { - is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; - isLittleEndian = TM.getTargetData()->isLittleEndian(); - } - - virtual void startFunction(MachineFunction &MF); - virtual bool finishFunction(MachineFunction &MF); - - virtual void addRelocation(const MachineRelocation &MR) { - Relocations.push_back(MR); - } - - void emitConstantPool(MachineConstantPool *MCP); - void emitJumpTables(MachineJumpTableInfo *MJTI); - - virtual uintptr_t getConstantPoolEntryAddress(unsigned Index) const { - assert(CPLocations.size() > Index && "CP not emitted!"); - return CPLocations[Index]; - } - virtual uintptr_t getJumpTableEntryAddress(unsigned Index) const { - assert(JTLocations.size() > Index && "JT not emitted!"); - return JTLocations[Index]; - } - - virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) { - if (MBBLocations.size() <= (unsigned)MBB->getNumber()) - MBBLocations.resize((MBB->getNumber()+1)*2); - MBBLocations[MBB->getNumber()] = getCurrentPCOffset(); - } - - virtual uintptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const { - assert(MBBLocations.size() > (unsigned)MBB->getNumber() && - MBBLocations[MBB->getNumber()] && "MBB not emitted!"); - return MBBLocations[MBB->getNumber()]; - } - - virtual uintptr_t getLabelAddress(uint64_t Label) const { - assert(0 && "get Label not implemented"); - abort(); - return 0; - } - - virtual void emitLabel(uint64_t LabelID) { - assert(0 && "emit Label not implemented"); - abort(); - } - - - virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { } - - /// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE! - virtual void startGVStub(const GlobalValue* F, unsigned StubSize, - unsigned Alignment = 1) { - assert(0 && "JIT specific function called!"); - abort(); - } - virtual void startGVStub(const GlobalValue* F, void *Buffer, - unsigned StubSize) { - assert(0 && "JIT specific function called!"); - abort(); - } - virtual void *finishGVStub(const GlobalValue* F) { - assert(0 && "JIT specific function called!"); - abort(); - return 0; - } - }; -} - -/// startFunction - This callback is invoked when a new machine function is -/// about to be emitted. -void MachOCodeEmitter::startFunction(MachineFunction &MF) { - const TargetData *TD = TM.getTargetData(); - const Function *F = MF.getFunction(); - - // Align the output buffer to the appropriate alignment, power of 2. - unsigned FnAlign = F->getAlignment(); - unsigned TDAlign = TD->getPrefTypeAlignment(F->getType()); - unsigned Align = Log2_32(std::max(FnAlign, TDAlign)); - assert(!(Align & (Align-1)) && "Alignment is not a power of two!"); - - // Get the Mach-O Section that this function belongs in. - MachOWriter::MachOSection *MOS = MOW.getTextSection(); - - // FIXME: better memory management - MOS->SectionData.reserve(4096); - BufferBegin = &MOS->SectionData[0]; - BufferEnd = BufferBegin + MOS->SectionData.capacity(); - - // Upgrade the section alignment if required. - if (MOS->align < Align) MOS->align = Align; - - // Round the size up to the correct alignment for starting the new function. - if ((MOS->size & ((1 << Align) - 1)) != 0) { - MOS->size += (1 << Align); - MOS->size &= ~((1 << Align) - 1); - } - - // FIXME: Using MOS->size directly here instead of calculating it from the - // output buffer size (impossible because the code emitter deals only in raw - // bytes) forces us to manually synchronize size and write padding zero bytes - // to the output buffer for all non-text sections. For text sections, we do - // not synchonize the output buffer, and we just blow up if anyone tries to - // write non-code to it. An assert should probably be added to - // AddSymbolToSection to prevent calling it on the text section. - CurBufferPtr = BufferBegin + MOS->size; - - // Clear per-function data structures. - CPLocations.clear(); - CPSections.clear(); - JTLocations.clear(); - MBBLocations.clear(); -} - -/// finishFunction - This callback is invoked after the function is completely -/// finished. -bool MachOCodeEmitter::finishFunction(MachineFunction &MF) { - // Get the Mach-O Section that this function belongs in. - MachOWriter::MachOSection *MOS = MOW.getTextSection(); - - // Get a symbol for the function to add to the symbol table - // FIXME: it seems like we should call something like AddSymbolToSection - // in startFunction rather than changing the section size and symbol n_value - // here. - const GlobalValue *FuncV = MF.getFunction(); - MachOSym FnSym(FuncV, MOW.Mang->getValueName(FuncV), MOS->Index, TM); - FnSym.n_value = MOS->size; - MOS->size = CurBufferPtr - BufferBegin; - - // Emit constant pool to appropriate section(s) - emitConstantPool(MF.getConstantPool()); - - // Emit jump tables to appropriate section - emitJumpTables(MF.getJumpTableInfo()); - - // If we have emitted any relocations to function-specific objects such as - // basic blocks, constant pools entries, or jump tables, record their - // addresses now so that we can rewrite them with the correct addresses - // later. - for (unsigned i = 0, e = Relocations.size(); i != e; ++i) { - MachineRelocation &MR = Relocations[i]; - intptr_t Addr; - - if (MR.isBasicBlock()) { - Addr = getMachineBasicBlockAddress(MR.getBasicBlock()); - MR.setConstantVal(MOS->Index); - MR.setResultPointer((void*)Addr); - } else if (MR.isJumpTableIndex()) { - Addr = getJumpTableEntryAddress(MR.getJumpTableIndex()); - MR.setConstantVal(MOW.getJumpTableSection()->Index); - MR.setResultPointer((void*)Addr); - } else if (MR.isConstantPoolIndex()) { - Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex()); - MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]); - MR.setResultPointer((void*)Addr); - } else if (MR.isGlobalValue()) { - // FIXME: This should be a set or something that uniques - MOW.PendingGlobals.push_back(MR.getGlobalValue()); - } else { - assert(0 && "Unhandled relocation type"); - } - MOS->Relocations.push_back(MR); - } - Relocations.clear(); - - // Finally, add it to the symtab. - MOW.SymbolTable.push_back(FnSym); - return false; -} - -/// emitConstantPool - For each constant pool entry, figure out which section -/// the constant should live in, allocate space for it, and emit it to the -/// Section data buffer. -void MachOCodeEmitter::emitConstantPool(MachineConstantPool *MCP) { - const std::vector &CP = MCP->getConstants(); - if (CP.empty()) return; - - // FIXME: handle PIC codegen - assert(TM.getRelocationModel() != Reloc::PIC_ && - "PIC codegen not yet handled for mach-o jump tables!"); - - // Although there is no strict necessity that I am aware of, we will do what - // gcc for OS X does and put each constant pool entry in a section of constant - // objects of a certain size. That means that float constants go in the - // literal4 section, and double objects go in literal8, etc. - // - // FIXME: revisit this decision if we ever do the "stick everything into one - // "giant object for PIC" optimization. - for (unsigned i = 0, e = CP.size(); i != e; ++i) { - const Type *Ty = CP[i].getType(); - unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); - - MachOWriter::MachOSection *Sec = MOW.getConstSection(CP[i].Val.ConstVal); - OutputBuffer SecDataOut(Sec->SectionData, is64Bit, isLittleEndian); - - CPLocations.push_back(Sec->SectionData.size()); - CPSections.push_back(Sec->Index); - - // FIXME: remove when we have unified size + output buffer - Sec->size += Size; - - // Allocate space in the section for the global. - // FIXME: need alignment? - // FIXME: share between here and AddSymbolToSection? - for (unsigned j = 0; j < Size; ++j) - SecDataOut.outbyte(0); - - MOW.InitMem(CP[i].Val.ConstVal, &Sec->SectionData[0], CPLocations[i], - TM.getTargetData(), Sec->Relocations); - } -} - -/// emitJumpTables - Emit all the jump tables for a given jump table info -/// record to the appropriate section. -void MachOCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) { - const std::vector &JT = MJTI->getJumpTables(); - if (JT.empty()) return; - - // FIXME: handle PIC codegen - assert(TM.getRelocationModel() != Reloc::PIC_ && - "PIC codegen not yet handled for mach-o jump tables!"); - - MachOWriter::MachOSection *Sec = MOW.getJumpTableSection(); - unsigned TextSecIndex = MOW.getTextSection()->Index; - OutputBuffer SecDataOut(Sec->SectionData, is64Bit, isLittleEndian); - - for (unsigned i = 0, e = JT.size(); i != e; ++i) { - // For each jump table, record its offset from the start of the section, - // reserve space for the relocations to the MBBs, and add the relocations. - const std::vector &MBBs = JT[i].MBBs; - JTLocations.push_back(Sec->SectionData.size()); - for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) { - MachineRelocation MR(MOW.GetJTRelocation(Sec->SectionData.size(), - MBBs[mi])); - MR.setResultPointer((void *)JTLocations[i]); - MR.setConstantVal(TextSecIndex); - Sec->Relocations.push_back(MR); - SecDataOut.outaddr(0); - } - } - // FIXME: remove when we have unified size + output buffer - Sec->size = Sec->SectionData.size(); -} - //===----------------------------------------------------------------------===// // MachOWriter Implementation //===----------------------------------------------------------------------===// char MachOWriter::ID = 0; -MachOWriter::MachOWriter(raw_ostream &o, TargetMachine &tm) + +MachOWriter::MachOWriter(raw_ostream &o, TargetMachine &tm) : MachineFunctionPass(&ID), O(o), TM(tm) { is64Bit = TM.getTargetData()->getPointerSizeInBits() == 64; isLittleEndian = TM.getTargetData()->isLittleEndian(); + TAI = TM.getTargetAsmInfo(); + // Create the machine code emitter object for this target. + MCE = new MachOCodeEmitter(*this); } @@ -353,6 +76,55 @@ MachOWriter::~MachOWriter() { delete MCE; } +bool MachOWriter::doInitialization(Module &M) { + // Set the magic value, now that we know the pointer size and endianness + Header.setMagic(isLittleEndian, is64Bit); + + // Set the file type + // FIXME: this only works for object files, we do not support the creation + // of dynamic libraries or executables at this time. + Header.filetype = MachOHeader::MH_OBJECT; + + Mang = new Mangler(M); + return false; +} + +bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { + return false; +} + +/// doFinalization - Now that the module has been completely processed, emit +/// the Mach-O file to 'O'. +bool MachOWriter::doFinalization(Module &M) { + // FIXME: we don't handle debug info yet, we should probably do that. + + // Okay, the.text section has been completed, build the .data, .bss, and + // "common" sections next. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + EmitGlobal(I); + + // Emit the header and load commands. + EmitHeaderAndLoadCommands(); + + // Emit the various sections and their relocation info. + EmitSections(); + EmitRelocations(); + + // Write the symbol table and the string table to the end of the file. + O.write((char*)&SymT[0], SymT.size()); + O.write((char*)&StrT[0], StrT.size()); + + // We are done with the abstract symbols. + SectionList.clear(); + SymbolTable.clear(); + DynamicSymbolTable.clear(); + + // Release the name mangler object. + delete Mang; Mang = 0; + return false; +} + void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { const Type *Ty = GV->getType()->getElementType(); unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); @@ -368,7 +140,7 @@ void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { Align = Log2_32(Align); Sec->align = std::max(unsigned(Sec->align), Align); Sec->size = (Sec->size + Align - 1) & ~(Align-1); - + // Add alignment padding to buffer as well. // FIXME: remove when we have unified size + output buffer unsigned AlignedSize = Sec->size - OrigSize; @@ -377,7 +149,7 @@ void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { } // Globals without external linkage apparently do not go in the symbol table. if (!GV->hasLocalLinkage()) { - MachOSym Sym(GV, Mang->getValueName(GV), Sec->Index, TM); + MachOSym Sym(GV, Mang->getValueName(GV), Sec->Index, TAI); Sym.n_value = Sec->size; SymbolTable.push_back(Sym); } @@ -385,14 +157,14 @@ void MachOWriter::AddSymbolToSection(MachOSection *Sec, GlobalVariable *GV) { // Record the offset of the symbol, and then allocate space for it. // FIXME: remove when we have unified size + output buffer Sec->size += Size; - - // Now that we know what section the GlovalVariable is going to be emitted + + // Now that we know what section the GlovalVariable is going to be emitted // into, update our mappings. // FIXME: We may also need to update this when outputting non-GlobalVariable // GlobalValues such as functions. GVSection[GV] = Sec; GVOffset[GV] = Sec->SectionData.size(); - + // Allocate space in the section for the global. for (unsigned i = 0; i < Size; ++i) SecDataOut.outbyte(0); @@ -402,7 +174,7 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { const Type *Ty = GV->getType()->getElementType(); unsigned Size = TM.getTargetData()->getTypeAllocSize(Ty); bool NoInit = !GV->hasInitializer(); - + // If this global has a zero initializer, it is part of the .bss or common // section. if (NoInit || GV->getInitializer()->isNullValue()) { @@ -411,7 +183,8 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { // merged with other symbols. if (NoInit || GV->hasLinkOnceLinkage() || GV->hasWeakLinkage() || GV->hasCommonLinkage()) { - MachOSym ExtOrCommonSym(GV, Mang->getValueName(GV), MachOSym::NO_SECT,TM); + MachOSym ExtOrCommonSym(GV, Mang->getValueName(GV), + MachOSym::NO_SECT, TAI); // For undefined (N_UNDF) external (N_EXT) types, n_value is the size in // bytes of the symbol. ExtOrCommonSym.n_value = Size; @@ -425,11 +198,11 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { AddSymbolToSection(BSS, GV); return; } - + // Scalar read-only data goes in a literal section if the scalar is 4, 8, or // 16 bytes, or a cstring. Other read only data goes into a regular const // section. Read-write data goes in the data section. - MachOSection *Sec = GV->isConstant() ? getConstSection(GV->getInitializer()) : + MachOSection *Sec = GV->isConstant() ? getConstSection(GV->getInitializer()) : getDataSection(); AddSymbolToSection(Sec, GV); InitMem(GV->getInitializer(), &Sec->SectionData[0], GVOffset[GV], @@ -437,73 +210,25 @@ void MachOWriter::EmitGlobal(GlobalVariable *GV) { } -bool MachOWriter::runOnMachineFunction(MachineFunction &MF) { - // Nothing to do here, this is all done through the MCE object. - return false; -} - -bool MachOWriter::doInitialization(Module &M) { - // Set the magic value, now that we know the pointer size and endianness - Header.setMagic(isLittleEndian, is64Bit); - - // Set the file type - // FIXME: this only works for object files, we do not support the creation - // of dynamic libraries or executables at this time. - Header.filetype = MachOHeader::MH_OBJECT; - - Mang = new Mangler(M); - return false; -} - -/// doFinalization - Now that the module has been completely processed, emit -/// the Mach-O file to 'O'. -bool MachOWriter::doFinalization(Module &M) { - // FIXME: we don't handle debug info yet, we should probably do that. - - // Okay, the.text section has been completed, build the .data, .bss, and - // "common" sections next. - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) - EmitGlobal(I); - - // Emit the header and load commands. - EmitHeaderAndLoadCommands(); - - // Emit the various sections and their relocation info. - EmitSections(); - - // Write the symbol table and the string table to the end of the file. - O.write((char*)&SymT[0], SymT.size()); - O.write((char*)&StrT[0], StrT.size()); - - // We are done with the abstract symbols. - SectionList.clear(); - SymbolTable.clear(); - DynamicSymbolTable.clear(); - - // Release the name mangler object. - delete Mang; Mang = 0; - return false; -} void MachOWriter::EmitHeaderAndLoadCommands() { // Step #0: Fill in the segment load command size, since we need it to figure // out the rest of the header fields MachOSegment SEG("", is64Bit); SEG.nsects = SectionList.size(); - SEG.cmdsize = SEG.cmdSize(is64Bit) + + SEG.cmdsize = SEG.cmdSize(is64Bit) + SEG.nsects * SectionList[0]->cmdSize(is64Bit); - + // Step #1: calculate the number of load commands. We always have at least // one, for the LC_SEGMENT load command, plus two for the normal // and dynamic symbol tables, if there are any symbols. Header.ncmds = SymbolTable.empty() ? 1 : 3; - + // Step #2: calculate the size of the load commands Header.sizeofcmds = SEG.cmdsize; if (!SymbolTable.empty()) Header.sizeofcmds += SymTab.cmdsize + DySymTab.cmdsize; - + // Step #3: write the header to the file // Local alias to shortenify coming code. DataBuffer &FH = Header.HeaderData; @@ -518,7 +243,7 @@ void MachOWriter::EmitHeaderAndLoadCommands() { FHOut.outword(Header.flags); if (is64Bit) FHOut.outword(Header.reserved); - + // Step #4: Finish filling in the segment load command and write it out for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) @@ -526,7 +251,7 @@ void MachOWriter::EmitHeaderAndLoadCommands() { SEG.vmsize = SEG.filesize; SEG.fileoff = Header.cmdSize(is64Bit) + Header.sizeofcmds; - + FHOut.outword(SEG.cmd); FHOut.outword(SEG.cmdsize); FHOut.outstring(SEG.segname, 16); @@ -538,8 +263,8 @@ void MachOWriter::EmitHeaderAndLoadCommands() { FHOut.outword(SEG.initprot); FHOut.outword(SEG.nsects); FHOut.outword(SEG.flags); - - // Step #5: Finish filling in the fields of the MachOSections + + // Step #5: Finish filling in the fields of the MachOSections uint64_t currentAddr = 0; for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) { @@ -550,13 +275,13 @@ void MachOWriter::EmitHeaderAndLoadCommands() { // FIXME: do we need to do something with alignment here? currentAddr += MOS->size; } - + // Step #6: Emit the symbol table to temporary buffers, so that we know the // size of the string table when we write the next load command. This also // sorts and assigns indices to each of the symbols, which is necessary for // emitting relocations to externally-defined objects. BufferSymbolAndStringTable(); - + // Step #7: Calculate the number of relocations for each section and write out // the section commands for each section currentAddr += SEG.fileoff; @@ -568,7 +293,7 @@ void MachOWriter::EmitHeaderAndLoadCommands() { CalculateRelocations(*MOS); MOS->reloff = MOS->nreloc ? currentAddr : 0; currentAddr += MOS->nreloc * 8; - + // write the finalized section command to the output buffer FHOut.outstring(MOS->sectname, 16); FHOut.outstring(MOS->segname, 16); @@ -584,7 +309,7 @@ void MachOWriter::EmitHeaderAndLoadCommands() { if (is64Bit) FHOut.outword(MOS->reserved3); } - + // Step #8: Emit LC_SYMTAB/LC_DYSYMTAB load commands SymTab.symoff = currentAddr; SymTab.nsyms = SymbolTable.size(); @@ -620,94 +345,92 @@ void MachOWriter::EmitHeaderAndLoadCommands() { FHOut.outword(DySymTab.nextrel); FHOut.outword(DySymTab.locreloff); FHOut.outword(DySymTab.nlocrel); - + O.write((char*)&FH[0], FH.size()); } /// EmitSections - Now that we have constructed the file header and load /// commands, emit the data for each section to the file. + void MachOWriter::EmitSections() { for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) // Emit the contents of each section O.write((char*)&(*I)->SectionData[0], (*I)->size); +} +void MachOWriter::EmitRelocations() { for (std::vector::iterator I = SectionList.begin(), E = SectionList.end(); I != E; ++I) // Emit the relocation entry data for each section. O.write((char*)&(*I)->RelocBuffer[0], (*I)->RelocBuffer.size()); } -/// PartitionByLocal - Simple boolean predicate that returns true if Sym is -/// a local symbol rather than an external symbol. -bool MachOWriter::PartitionByLocal(const MachOSym &Sym) { - return (Sym.n_type & (MachOSym::N_EXT | MachOSym::N_PEXT)) == 0; -} - -/// PartitionByDefined - Simple boolean predicate that returns true if Sym is -/// defined in this module. -bool MachOWriter::PartitionByDefined(const MachOSym &Sym) { - // FIXME: Do N_ABS or N_INDR count as defined? - return (Sym.n_type & MachOSym::N_SECT) == MachOSym::N_SECT; -} - /// BufferSymbolAndStringTable - Sort the symbols we encountered and assign them /// each a string table index so that they appear in the correct order in the /// output file. + void MachOWriter::BufferSymbolAndStringTable() { // The order of the symbol table is: // 1. local symbols // 2. defined external symbols (sorted by name) // 3. undefined external symbols (sorted by name) - + // Before sorting the symbols, check the PendingGlobals for any undefined // globals that need to be put in the symbol table. + for (std::vector::iterator I = PendingGlobals.begin(), E = PendingGlobals.end(); I != E; ++I) { if (GVOffset[*I] == 0 && GVSection[*I] == 0) { - MachOSym UndfSym(*I, Mang->getValueName(*I), MachOSym::NO_SECT, TM); + MachOSym UndfSym(*I, Mang->getValueName(*I), MachOSym::NO_SECT, TAI); SymbolTable.push_back(UndfSym); GVOffset[*I] = -1; } } - + // Sort the symbols by name, so that when we partition the symbols by scope // of definition, we won't have to sort by name within each partition. - std::sort(SymbolTable.begin(), SymbolTable.end(), MachOSymCmp()); - // Parition the symbol table entries so that all local symbols come before + std::sort(SymbolTable.begin(), SymbolTable.end(), MachOSym::SymCmp()); + + // Parition the symbol table entries so that all local symbols come before // all symbols with external linkage. { 1 | 2 3 } - std::partition(SymbolTable.begin(), SymbolTable.end(), PartitionByLocal); - + + std::partition(SymbolTable.begin(), SymbolTable.end(), + MachOSym::PartitionByLocal); + // Advance iterator to beginning of external symbols and partition so that // all external symbols defined in this module come before all external // symbols defined elsewhere. { 1 | 2 | 3 } + for (std::vector::iterator I = SymbolTable.begin(), E = SymbolTable.end(); I != E; ++I) { - if (!PartitionByLocal(*I)) { - std::partition(I, E, PartitionByDefined); + if (!MachOSym::PartitionByLocal(*I)) { + std::partition(I, E, MachOSym::PartitionByDefined); break; } } - // Calculate the starting index for each of the local, extern defined, and + // Calculate the starting index for each of the local, extern defined, and // undefined symbols, as well as the number of each to put in the LC_DYSYMTAB // load command. + for (std::vector::iterator I = SymbolTable.begin(), E = SymbolTable.end(); I != E; ++I) { - if (PartitionByLocal(*I)) { + if (MachOSym::PartitionByLocal(*I)) { ++DySymTab.nlocalsym; ++DySymTab.iextdefsym; ++DySymTab.iundefsym; - } else if (PartitionByDefined(*I)) { + } else if (MachOSym::PartitionByDefined(*I)) { ++DySymTab.nextdefsym; ++DySymTab.iundefsym; } else { ++DySymTab.nundefsym; } } - + // Write out a leading zero byte when emitting string table, for n_strx == 0 // which means an empty string. + OutputBuffer StrTOut(StrT, is64Bit, isLittleEndian); StrTOut.outbyte(0); @@ -716,6 +439,7 @@ void MachOWriter::BufferSymbolAndStringTable() { // 2. strings for local symbols // Since this is the opposite order from the symbol table, which we have just // sorted, we can walk the symbol table backwards to output the string table. + for (std::vector::reverse_iterator I = SymbolTable.rbegin(), E = SymbolTable.rend(); I != E; ++I) { if (I->GVName == "") { @@ -739,7 +463,7 @@ void MachOWriter::BufferSymbolAndStringTable() { I->n_value += GVSection[GV]->addr; if (GV && (GVOffset[GV] == -1)) GVOffset[GV] = index; - + // Emit nlist to buffer SymTOut.outword(I->n_strx); SymTOut.outbyte(I->n_type); @@ -754,6 +478,7 @@ void MachOWriter::BufferSymbolAndStringTable() { /// and the offset into that section. From this information, create the /// appropriate target-specific MachORelocation type and add buffer it to be /// written out after we are finished writing out sections. + void MachOWriter::CalculateRelocations(MachOSection &MOS) { for (unsigned i = 0, e = MOS.Relocations.size(); i != e; ++i) { MachineRelocation &MR = MOS.Relocations[i]; @@ -763,19 +488,22 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { // This is a scattered relocation entry if it points to a global value with // a non-zero offset. + bool Scattered = false; bool Extern = false; // Since we may not have seen the GlobalValue we were interested in yet at // the time we emitted the relocation for it, fix it up now so that it // points to the offset into the correct section. + if (MR.isGlobalValue()) { GlobalValue *GV = MR.getGlobalValue(); MachOSection *MOSPtr = GVSection[GV]; intptr_t Offset = GVOffset[GV]; - + // If we have never seen the global before, it must be to a symbol // defined in another module (N_UNDF). + if (!MOSPtr) { // FIXME: need to append stub suffix Extern = true; @@ -787,9 +515,10 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { } MR.setResultPointer((void*)Offset); } - + // If the symbol is locally defined, pass in the address of the section and // the section index to the code which will generate the target relocation. + if (!Extern) { MachOSection &To = *SectionList[TargetSection - 1]; TargetAddr = To.addr; @@ -798,7 +527,7 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { OutputBuffer RelocOut(MOS.RelocBuffer, is64Bit, isLittleEndian); OutputBuffer SecOut(MOS.SectionData, is64Bit, isLittleEndian); - + MOS.nreloc += GetTargetRelocation(MR, MOS.Index, TargetAddr, TargetIndex, RelocOut, SecOut, Scattered, Extern); } @@ -806,21 +535,22 @@ void MachOWriter::CalculateRelocations(MachOSection &MOS) { // InitMem - Write the value of a Constant to the specified memory location, // converting it into bytes and relocations. + void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, - const TargetData *TD, + const TargetData *TD, std::vector &MRs) { typedef std::pair CPair; std::vector WorkList; - + WorkList.push_back(CPair(C,(intptr_t)Addr + Offset)); - + intptr_t ScatteredOffset = 0; - + while (!WorkList.empty()) { const Constant *PC = WorkList.back().first; intptr_t PA = WorkList.back().second; WorkList.pop_back(); - + if (isa(PC)) { continue; } else if (const ConstantVector *CP = dyn_cast(PC)) { @@ -847,7 +577,7 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, break; } } else if (PC->getType()->isSingleValueType()) { - uint8_t *ptr = (uint8_t *)PA; + unsigned char *ptr = (unsigned char *)PA; switch (PC->getType()->getTypeID()) { case Type::IntegerTyID: { unsigned NumBits = cast(PC->getType())->getBitWidth(); @@ -945,13 +675,15 @@ void MachOWriter::InitMem(const Constant *C, void *Addr, intptr_t Offset, } } +//===----------------------------------------------------------------------===// +// MachOSym Implementation +//===----------------------------------------------------------------------===// + MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, - TargetMachine &TM) : + const TargetAsmInfo *TAI) : GV(gv), n_strx(0), n_type(sect == NO_SECT ? N_UNDF : N_SECT), n_sect(sect), n_desc(0), n_value(0) { - const TargetAsmInfo *TAI = TM.getTargetAsmInfo(); - switch (GV->getLinkage()) { default: assert(0 && "Unexpected linkage type!"); @@ -974,3 +706,6 @@ MachOSym::MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, break; } } + +} // end namespace llvm + diff --git a/lib/CodeGen/MachOWriter.h b/lib/CodeGen/MachOWriter.h index 6ab66eee926..3af2b0af4b7 100644 --- a/lib/CodeGen/MachOWriter.h +++ b/lib/CodeGen/MachOWriter.h @@ -14,10 +14,8 @@ #ifndef MACHOWRITER_H #define MACHOWRITER_H -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" +#include "MachO.h" #include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineRelocation.h" #include "llvm/Target/TargetData.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetMachOWriterInfo.h" @@ -31,53 +29,6 @@ namespace llvm { class OutputBuffer; class raw_ostream; - /// MachOSym - This struct contains information about each symbol that is - /// added to logical symbol table for the module. This is eventually - /// turned into a real symbol table in the file. - struct MachOSym { - const GlobalValue *GV; // The global value this corresponds to. - std::string GVName; // The mangled name of the global value. - uint32_t n_strx; // index into the string table - uint8_t n_type; // type flag - uint8_t n_sect; // section number or NO_SECT - int16_t n_desc; // see - uint64_t n_value; // value for this symbol (or stab offset) - - // Constants for the n_sect field - // see - enum { NO_SECT = 0 }; // symbol is not in any section - - // Constants for the n_type field - // see - enum { N_UNDF = 0x0, // undefined, n_sect == NO_SECT - N_ABS = 0x2, // absolute, n_sect == NO_SECT - N_SECT = 0xe, // defined in section number n_sect - N_PBUD = 0xc, // prebound undefined (defined in a dylib) - N_INDR = 0xa // indirect - }; - // The following bits are OR'd into the types above. For example, a type - // of 0x0f would be an external N_SECT symbol (0x0e | 0x01). - enum { N_EXT = 0x01, // external symbol bit - N_PEXT = 0x10 // private external symbol bit - }; - - // Constants for the n_desc field - // see - enum { REFERENCE_FLAG_UNDEFINED_NON_LAZY = 0, - REFERENCE_FLAG_UNDEFINED_LAZY = 1, - REFERENCE_FLAG_DEFINED = 2, - REFERENCE_FLAG_PRIVATE_DEFINED = 3, - REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY = 4, - REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY = 5 - }; - enum { N_NO_DEAD_STRIP = 0x0020, // symbol is not to be dead stripped - N_WEAK_REF = 0x0040, // symbol is weak referenced - N_WEAK_DEF = 0x0080 // coalesced symbol is a weak definition - }; - - MachOSym(const GlobalValue *gv, std::string name, uint8_t sect, - TargetMachine &TM); - }; /// MachOWriter - This class implements the common target-independent code for /// writing Mach-O files. Targets should derive a class from this to @@ -98,7 +49,6 @@ namespace llvm { return "Mach-O Writer"; } - typedef std::vector DataBuffer; protected: /// Output stream to send the resultant object file to. /// @@ -114,326 +64,61 @@ namespace llvm { /// MCE - The MachineCodeEmitter object that we are exposing to emit machine /// code for functions to the .o file. + MachOCodeEmitter *MCE; /// is64Bit/isLittleEndian - This information is inferred from the target /// machine directly, indicating what header values and flags to set. + bool is64Bit, isLittleEndian; + // Target Asm Info + + const TargetAsmInfo *TAI; + + /// Header - An instance of MachOHeader that we will update while we build + /// the file, and then emit during finalization. + + MachOHeader Header; + /// doInitialization - Emit the file header and all of the global variables /// for the module to the Mach-O file. + bool doInitialization(Module &M); bool runOnMachineFunction(MachineFunction &MF); /// doFinalization - Now that the module has been completely processed, emit /// the Mach-O file to 'O'. + bool doFinalization(Module &M); - /// MachOHeader - This struct contains the header information about a - /// specific architecture type/subtype pair that is emitted to the file. - struct MachOHeader { - uint32_t magic; // mach magic number identifier - uint32_t filetype; // type of file - uint32_t ncmds; // number of load commands - uint32_t sizeofcmds; // the size of all the load commands - uint32_t flags; // flags - uint32_t reserved; // 64-bit only - - /// HeaderData - The actual data for the header which we are building - /// up for emission to the file. - DataBuffer HeaderData; - - // Constants for the filetype field - // see for additional info on the various types - enum { MH_OBJECT = 1, // relocatable object file - MH_EXECUTE = 2, // demand paged executable file - MH_FVMLIB = 3, // fixed VM shared library file - MH_CORE = 4, // core file - MH_PRELOAD = 5, // preloaded executable file - MH_DYLIB = 6, // dynamically bound shared library - MH_DYLINKER = 7, // dynamic link editor - MH_BUNDLE = 8, // dynamically bound bundle file - MH_DYLIB_STUB = 9, // shared library stub for static linking only - MH_DSYM = 10 // companion file wiht only debug sections - }; - - // Constants for the flags field - enum { MH_NOUNDEFS = 1 << 0, - // the object file has no undefined references - MH_INCRLINK = 1 << 1, - // the object file is the output of an incremental link against - // a base file and cannot be link edited again - MH_DYLDLINK = 1 << 2, - // the object file is input for the dynamic linker and cannot be - // statically link edited again. - MH_BINDATLOAD = 1 << 3, - // the object file's undefined references are bound by the - // dynamic linker when loaded. - MH_PREBOUND = 1 << 4, - // the file has its dynamic undefined references prebound - MH_SPLIT_SEGS = 1 << 5, - // the file has its read-only and read-write segments split - // see - MH_LAZY_INIT = 1 << 6, - // the shared library init routine is to be run lazily via - // catching memory faults to its writable segments (obsolete) - MH_TWOLEVEL = 1 << 7, - // the image is using two-level namespace bindings - MH_FORCE_FLAT = 1 << 8, - // the executable is forcing all images to use flat namespace - // bindings. - MH_NOMULTIDEFS = 1 << 8, - // this umbrella guarantees no multiple definitions of symbols - // in its sub-images so the two-level namespace hints can - // always be used. - MH_NOFIXPREBINDING = 1 << 10, - // do not have dyld notify the prebidning agent about this - // executable. - MH_PREBINDABLE = 1 << 11, - // the binary is not prebound but can have its prebinding - // redone. only used when MH_PREBOUND is not set. - MH_ALLMODSBOUND = 1 << 12, - // indicates that this binary binds to all two-level namespace - // modules of its dependent libraries. Only used when - // MH_PREBINDABLE and MH_TWOLEVEL are both set. - MH_SUBSECTIONS_VIA_SYMBOLS = 1 << 13, - // safe to divide up the sections into sub-sections via symbols - // for dead code stripping. - MH_CANONICAL = 1 << 14, - // the binary has been canonicalized via the unprebind operation - MH_WEAK_DEFINES = 1 << 15, - // the final linked image contains external weak symbols - MH_BINDS_TO_WEAK = 1 << 16, - // the final linked image uses weak symbols - MH_ALLOW_STACK_EXECUTION = 1 << 17 - // When this bit is set, all stacks in the task will be given - // stack execution privilege. Only used in MH_EXECUTE filetype - }; - - MachOHeader() : magic(0), filetype(0), ncmds(0), sizeofcmds(0), flags(0), - reserved(0) { } - - /// cmdSize - This routine returns the size of the MachOSection as written - /// to disk, depending on whether the destination is a 64 bit Mach-O file. - unsigned cmdSize(bool is64Bit) const { - if (is64Bit) - return 8 * sizeof(uint32_t); - else - return 7 * sizeof(uint32_t); - } - - /// setMagic - This routine sets the appropriate value for the 'magic' - /// field based on pointer size and endianness. - void setMagic(bool isLittleEndian, bool is64Bit) { - if (isLittleEndian) - if (is64Bit) magic = 0xcffaedfe; - else magic = 0xcefaedfe; - else - if (is64Bit) magic = 0xfeedfacf; - else magic = 0xfeedface; - } - }; - - /// Header - An instance of MachOHeader that we will update while we build - /// the file, and then emit during finalization. - MachOHeader Header; - - /// MachOSegment - This struct contains the necessary information to - /// emit the load commands for each section in the file. - struct MachOSegment { - uint32_t cmd; // LC_SEGMENT or LC_SEGMENT_64 - uint32_t cmdsize; // Total size of this struct and section commands - std::string segname; // segment name - uint64_t vmaddr; // address of this segment - uint64_t vmsize; // size of this segment, may be larger than filesize - uint64_t fileoff; // offset in file - uint64_t filesize; // amount to read from file - uint32_t maxprot; // maximum VM protection - uint32_t initprot; // initial VM protection - uint32_t nsects; // number of sections in this segment - uint32_t flags; // flags - - // The following constants are getting pulled in by one of the - // system headers, which creates a neat clash with the enum. -#if !defined(VM_PROT_NONE) -#define VM_PROT_NONE 0x00 -#endif -#if !defined(VM_PROT_READ) -#define VM_PROT_READ 0x01 -#endif -#if !defined(VM_PROT_WRITE) -#define VM_PROT_WRITE 0x02 -#endif -#if !defined(VM_PROT_EXECUTE) -#define VM_PROT_EXECUTE 0x04 -#endif -#if !defined(VM_PROT_ALL) -#define VM_PROT_ALL 0x07 -#endif - - // Constants for the vm protection fields - // see - enum { SEG_VM_PROT_NONE = VM_PROT_NONE, - SEG_VM_PROT_READ = VM_PROT_READ, // read permission - SEG_VM_PROT_WRITE = VM_PROT_WRITE, // write permission - SEG_VM_PROT_EXECUTE = VM_PROT_EXECUTE, - SEG_VM_PROT_ALL = VM_PROT_ALL - }; - - // Constants for the cmd field - // see - enum { LC_SEGMENT = 0x01, // segment of this file to be mapped - LC_SEGMENT_64 = 0x19 // 64-bit segment of this file to be mapped - }; - - /// cmdSize - This routine returns the size of the MachOSection as written - /// to disk, depending on whether the destination is a 64 bit Mach-O file. - unsigned cmdSize(bool is64Bit) const { - if (is64Bit) - return 6 * sizeof(uint32_t) + 4 * sizeof(uint64_t) + 16; - else - return 10 * sizeof(uint32_t) + 16; // addresses only 32 bits - } - - MachOSegment(const std::string &seg, bool is64Bit) - : cmd(is64Bit ? LC_SEGMENT_64 : LC_SEGMENT), cmdsize(0), segname(seg), - vmaddr(0), vmsize(0), fileoff(0), filesize(0), maxprot(VM_PROT_ALL), - initprot(VM_PROT_ALL), nsects(0), flags(0) { } - }; - - /// MachOSection - This struct contains information about each section in a - /// particular segment that is emitted to the file. This is eventually - /// turned into the SectionCommand in the load command for a particlar - /// segment. - struct MachOSection { - std::string sectname; // name of this section, - std::string segname; // segment this section goes in - uint64_t addr; // memory address of this section - uint64_t size; // size in bytes of this section - uint32_t offset; // file offset of this section - uint32_t align; // section alignment (power of 2) - uint32_t reloff; // file offset of relocation entries - uint32_t nreloc; // number of relocation entries - uint32_t flags; // flags (section type and attributes) - uint32_t reserved1; // reserved (for offset or index) - uint32_t reserved2; // reserved (for count or sizeof) - uint32_t reserved3; // reserved (64 bit only) - - /// A unique number for this section, which will be used to match symbols - /// to the correct section. - uint32_t Index; - - /// SectionData - The actual data for this section which we are building - /// up for emission to the file. - DataBuffer SectionData; - - /// RelocBuffer - A buffer to hold the mach-o relocations before we write - /// them out at the appropriate location in the file. - DataBuffer RelocBuffer; - - /// Relocations - The relocations that we have encountered so far in this - /// section that we will need to convert to MachORelocation entries when - /// the file is written. - std::vector Relocations; - - // Constants for the section types (low 8 bits of flags field) - // see - enum { S_REGULAR = 0, - // regular section - S_ZEROFILL = 1, - // zero fill on demand section - S_CSTRING_LITERALS = 2, - // section with only literal C strings - S_4BYTE_LITERALS = 3, - // section with only 4 byte literals - S_8BYTE_LITERALS = 4, - // section with only 8 byte literals - S_LITERAL_POINTERS = 5, - // section with only pointers to literals - S_NON_LAZY_SYMBOL_POINTERS = 6, - // section with only non-lazy symbol pointers - S_LAZY_SYMBOL_POINTERS = 7, - // section with only lazy symbol pointers - S_SYMBOL_STUBS = 8, - // section with only symbol stubs - // byte size of stub in the reserved2 field - S_MOD_INIT_FUNC_POINTERS = 9, - // section with only function pointers for initialization - S_MOD_TERM_FUNC_POINTERS = 10, - // section with only function pointers for termination - S_COALESCED = 11, - // section contains symbols that are coalesced - S_GB_ZEROFILL = 12, - // zero fill on demand section (that can be larger than 4GB) - S_INTERPOSING = 13, - // section with only pairs of function pointers for interposing - S_16BYTE_LITERALS = 14 - // section with only 16 byte literals - }; - - // Constants for the section flags (high 24 bits of flags field) - // see - enum { S_ATTR_PURE_INSTRUCTIONS = 1 << 31, - // section contains only true machine instructions - S_ATTR_NO_TOC = 1 << 30, - // section contains coalesced symbols that are not to be in a - // ranlib table of contents - S_ATTR_STRIP_STATIC_SYMS = 1 << 29, - // ok to strip static symbols in this section in files with the - // MY_DYLDLINK flag - S_ATTR_NO_DEAD_STRIP = 1 << 28, - // no dead stripping - S_ATTR_LIVE_SUPPORT = 1 << 27, - // blocks are live if they reference live blocks - S_ATTR_SELF_MODIFYING_CODE = 1 << 26, - // used with i386 code stubs written on by dyld - S_ATTR_DEBUG = 1 << 25, - // a debug section - S_ATTR_SOME_INSTRUCTIONS = 1 << 10, - // section contains some machine instructions - S_ATTR_EXT_RELOC = 1 << 9, - // section has external relocation entries - S_ATTR_LOC_RELOC = 1 << 8 - // section has local relocation entries - }; - - /// cmdSize - This routine returns the size of the MachOSection as written - /// to disk, depending on whether the destination is a 64 bit Mach-O file. - unsigned cmdSize(bool is64Bit) const { - if (is64Bit) - return 7 * sizeof(uint32_t) + 2 * sizeof(uint64_t) + 32; - else - return 9 * sizeof(uint32_t) + 32; // addresses only 32 bits - } - - MachOSection(const std::string &seg, const std::string §) - : sectname(sect), segname(seg), addr(0), size(0), offset(0), align(2), - reloff(0), nreloc(0), flags(0), reserved1(0), reserved2(0), - reserved3(0) { } - }; - private: /// SectionList - This is the list of sections that we have emitted to the /// file. Once the file has been completely built, the segment load command /// SectionCommands are constructed from this info. + std::vector SectionList; /// SectionLookup - This is a mapping from section name to SectionList entry + std::map SectionLookup; /// GVSection - This is a mapping from a GlobalValue to a MachOSection, /// to aid in emitting relocations. + std::map GVSection; /// GVOffset - This is a mapping from a GlobalValue to an offset from the /// start of the section in which the GV resides, to aid in emitting /// relocations. + std::map GVOffset; /// getSection - Return the section with the specified name, creating a new /// section if one does not already exist. + MachOSection *getSection(const std::string &seg, const std::string §, unsigned Flags = 0) { MachOSection *MOS = SectionLookup[seg+sect]; @@ -511,63 +196,11 @@ namespace llvm { nsyms(0), stroff(0), strsize(0) { } }; - /// MachOSymTab - This struct contains information about the offsets and - /// size of symbol table information. - /// segment. - struct MachODySymTab { - uint32_t cmd; // LC_DYSYMTAB - uint32_t cmdsize; // sizeof( MachODySymTab ) - uint32_t ilocalsym; // index to local symbols - uint32_t nlocalsym; // number of local symbols - uint32_t iextdefsym; // index to externally defined symbols - uint32_t nextdefsym; // number of externally defined symbols - uint32_t iundefsym; // index to undefined symbols - uint32_t nundefsym; // number of undefined symbols - uint32_t tocoff; // file offset to table of contents - uint32_t ntoc; // number of entries in table of contents - uint32_t modtaboff; // file offset to module table - uint32_t nmodtab; // number of module table entries - uint32_t extrefsymoff; // offset to referenced symbol table - uint32_t nextrefsyms; // number of referenced symbol table entries - uint32_t indirectsymoff; // file offset to the indirect symbol table - uint32_t nindirectsyms; // number of indirect symbol table entries - uint32_t extreloff; // offset to external relocation entries - uint32_t nextrel; // number of external relocation entries - uint32_t locreloff; // offset to local relocation entries - uint32_t nlocrel; // number of local relocation entries - - // Constants for the cmd field - // see - enum { LC_DYSYMTAB = 0x0B // dynamic link-edit symbol table info - }; - - MachODySymTab() : cmd(LC_DYSYMTAB), cmdsize(20 * sizeof(uint32_t)), - ilocalsym(0), nlocalsym(0), iextdefsym(0), nextdefsym(0), - iundefsym(0), nundefsym(0), tocoff(0), ntoc(0), modtaboff(0), - nmodtab(0), extrefsymoff(0), nextrefsyms(0), indirectsymoff(0), - nindirectsyms(0), extreloff(0), nextrel(0), locreloff(0), nlocrel(0) { } - }; - /// SymTab - The "stab" style symbol table information MachOSymTab SymTab; /// DySymTab - symbol table info for the dynamic link editor MachODySymTab DySymTab; - struct MachOSymCmp { - // FIXME: this does not appear to be sorting 'f' after 'F' - bool operator()(const MachOSym &LHS, const MachOSym &RHS) { - return LHS.GVName < RHS.GVName; - } - }; - - /// PartitionByLocal - Simple boolean predicate that returns true if Sym is - /// a local symbol rather than an external symbol. - static bool PartitionByLocal(const MachOSym &Sym); - - /// PartitionByDefined - Simple boolean predicate that returns true if Sym - /// is defined in this module. - static bool PartitionByDefined(const MachOSym &Sym); - protected: /// SymbolTable - This is the list of symbols we have emitted to the file. @@ -601,6 +234,7 @@ namespace llvm { void EmitGlobal(GlobalVariable *GV); void EmitHeaderAndLoadCommands(); void EmitSections(); + void EmitRelocations(); void BufferSymbolAndStringTable(); void CalculateRelocations(MachOSection &MOS); diff --git a/lib/CodeGen/RegAllocLinearScan.cpp b/lib/CodeGen/RegAllocLinearScan.cpp index ee118de4f49..85208887f48 100644 --- a/lib/CodeGen/RegAllocLinearScan.cpp +++ b/lib/CodeGen/RegAllocLinearScan.cpp @@ -312,93 +312,6 @@ namespace { static RegisterPass X("linearscan-regalloc", "Linear Scan Register Allocator"); -bool validateRegAlloc(MachineFunction *mf, LiveIntervals *lis, - VirtRegMap *vrm) { - - MachineRegisterInfo *mri = &mf->getRegInfo(); - const TargetRegisterInfo *tri = mf->getTarget().getRegisterInfo(); - bool allocationValid = true; - - - for (LiveIntervals::iterator itr = lis->begin(), end = lis->end(); - itr != end; ++itr) { - - LiveInterval *li = itr->second; - - if (TargetRegisterInfo::isPhysicalRegister(li->reg)) { - continue; - } - - if (vrm->hasPhys(li->reg)) { - const TargetRegisterClass *trc = mri->getRegClass(li->reg); - - if (lis->hasInterval(vrm->getPhys(li->reg))) { - if (li->overlaps(lis->getInterval(vrm->getPhys(li->reg)))) { - std::cerr << "vreg " << li->reg << " overlaps its assigned preg " - << vrm->getPhys(li->reg) << "(" << tri->getName(vrm->getPhys(li->reg)) << ")\n"; - } - } - - TargetRegisterClass::iterator fReg = - std::find(trc->allocation_order_begin(*mf), trc->allocation_order_end(*mf), - vrm->getPhys(li->reg)); - - if (fReg == trc->allocation_order_end(*mf)) { - std::cerr << "preg " << vrm->getPhys(li->reg) - << "(" << tri->getName(vrm->getPhys(li->reg)) << ") is not in the allocation set for vreg " - << li->reg << "\n"; - allocationValid &= false; - } - } - else { - std::cerr << "No preg for vreg " << li->reg << "\n"; - // What about conflicting loads/stores? - continue; - } - - for (LiveIntervals::iterator itr2 = next(itr); itr2 != end; ++itr2) { - - LiveInterval *li2 = itr2->second; - - if (li2->empty()) - continue; - - if (TargetRegisterInfo::isPhysicalRegister(li2->reg)) { - if (li->overlaps(*li2)) { - if (vrm->getPhys(li->reg) == li2->reg || - tri->areAliases(vrm->getPhys(li->reg), li2->reg)) { - std::cerr << "vreg " << li->reg << " overlaps preg " - << li2->reg << "(" << tri->getName(li2->reg) << ") which aliases " - << vrm->getPhys(li->reg) << "(" << tri->getName(vrm->getPhys(li->reg)) << ")\n"; - allocationValid &= false; - } - } - } - else { - - if (!vrm->hasPhys(li2->reg)) { - continue; - } - - if (li->overlaps(*li2)) { - if (vrm->getPhys(li->reg) == vrm->getPhys(li2->reg) || - tri->areAliases(vrm->getPhys(li->reg), vrm->getPhys(li2->reg))) { - std::cerr << "vreg " << li->reg << " (preg " << vrm->getPhys(li->reg) - << ") overlaps vreg " << li2->reg << " (preg " << vrm->getPhys(li2->reg) - << ") and " << vrm->getPhys(li->reg) << " aliases " << vrm->getPhys(li2->reg) << "\n"; - allocationValid &= false; - } - } - } - } - - } - - return allocationValid; - -} - - void RALinScan::ComputeRelatedRegClasses() { // First pass, add all reg classes to the union, and determine at least one // reg class that each register is in. @@ -526,10 +439,6 @@ bool RALinScan::runOnMachineFunction(MachineFunction &fn) { linearScan(); - if (NewSpillFramework) { - bool allocValid = validateRegAlloc(mf_, li_, vrm_); - } - // Rewrite spill code and update the PhysRegsUsed set. rewriter_->runOnMachineFunction(*mf_, *vrm_, li_); diff --git a/lib/CodeGen/VirtRegRewriter.cpp b/lib/CodeGen/VirtRegRewriter.cpp index b4c8bc12979..c31f622e249 100644 --- a/lib/CodeGen/VirtRegRewriter.cpp +++ b/lib/CodeGen/VirtRegRewriter.cpp @@ -411,9 +411,11 @@ static void InvalidateKill(unsigned Reg, std::vector &KillOps) { if (RegKills[Reg]) { KillOps[Reg]->setIsKill(false); - KillOps[Reg] = NULL; - RegKills.reset(Reg); - for (const unsigned *SR = TRI->getSubRegisters(Reg); *SR; ++SR) { + // KillOps[Reg] might be a def of a super-register. + unsigned KReg = KillOps[Reg]->getReg(); + KillOps[KReg] = NULL; + RegKills.reset(KReg); + for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) { if (RegKills[*SR]) { KillOps[*SR]->setIsKill(false); KillOps[*SR] = NULL; @@ -516,8 +518,18 @@ static void UpdateKills(MachineInstr &MI, const TargetRegisterInfo* TRI, // That can't be right. Register is killed but not re-defined and it's // being reused. Let's fix that. KillOps[Reg]->setIsKill(false); - KillOps[Reg] = NULL; - RegKills.reset(Reg); + // KillOps[Reg] might be a def of a super-register. + unsigned KReg = KillOps[Reg]->getReg(); + KillOps[KReg] = NULL; + RegKills.reset(KReg); + + // Must be a def of a super-register. Its other sub-regsters are no + // longer killed as well. + for (const unsigned *SR = TRI->getSubRegisters(KReg); *SR; ++SR) { + KillOps[*SR] = NULL; + RegKills.reset(*SR); + } + if (!MI.isRegTiedToDefOperand(i)) // Unless it's a two-address operand, this is the new kill. MO.setIsKill(); @@ -1090,6 +1102,8 @@ private: VRM.RemoveMachineInstrFromMaps(&NextMI); MBB.erase(&NextMI); ++NumModRefUnfold; + if (NextMII == MBB.end()) + break; } while (FoldsStackSlotModRef(*NextMII, SS, PhysReg, TII, TRI, VRM)); // Store the value back into SS. diff --git a/lib/System/Atomic.cpp b/lib/System/Atomic.cpp index cefd0bbf553..2827d889659 100644 --- a/lib/System/Atomic.cpp +++ b/lib/System/Atomic.cpp @@ -50,4 +50,4 @@ sys::cas_flag sys::CompareAndSwap(volatile sys::cas_flag* ptr, #else # error No compare-and-swap implementation for your platform! #endif -} \ No newline at end of file +} diff --git a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp index 047552f627d..09b8ce07d22 100644 --- a/lib/Target/ARM/ARMLoadStoreOptimizer.cpp +++ b/lib/Target/ARM/ARMLoadStoreOptimizer.cpp @@ -697,7 +697,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { // LDM/STM ops. for (unsigned i = 0, e = MBBII.size(); i < e; ++i) if (mergeBaseUpdateLSMultiple(MBB, MBBII[i], Advance, MBBI)) - NumMerges++; + ++NumMerges; NumMerges += MBBII.size(); // Try folding preceeding/trailing base inc/dec into those load/store @@ -705,7 +705,7 @@ bool ARMLoadStoreOpt::LoadStoreMultipleOpti(MachineBasicBlock &MBB) { for (unsigned i = 0; i != NumMemOps; ++i) if (!MemOps[i].Merged) if (mergeBaseUpdateLoadStore(MBB, MemOps[i].MBBI, TII,Advance,MBBI)) - NumMerges++; + ++NumMerges; // RS may be pointing to an instruction that's deleted. RS->skipTo(prior(MBBI)); diff --git a/lib/Target/X86/X86FastISel.cpp b/lib/Target/X86/X86FastISel.cpp index b3667be0d03..33332e4cf74 100644 --- a/lib/Target/X86/X86FastISel.cpp +++ b/lib/Target/X86/X86FastISel.cpp @@ -321,7 +321,7 @@ bool X86FastISel::X86FastEmitExtend(ISD::NodeType Opc, MVT DstVT, /// X86SelectAddress - Attempt to fill in an address from the given value. /// bool X86FastISel::X86SelectAddress(Value *V, X86AddressMode &AM, bool isCall) { - User *U; + User *U = NULL; unsigned Opcode = Instruction::UserOp1; if (Instruction *I = dyn_cast(V)) { Opcode = I->getOpcode(); diff --git a/lib/Transforms/Scalar/CodeGenPrepare.cpp b/lib/Transforms/Scalar/CodeGenPrepare.cpp index 342b1e563d0..42978e753d1 100644 --- a/lib/Transforms/Scalar/CodeGenPrepare.cpp +++ b/lib/Transforms/Scalar/CodeGenPrepare.cpp @@ -624,8 +624,11 @@ bool CodeGenPrepare::OptimizeMemoryInst(Instruction *MemoryInst, Value *Addr, // Add in the base register. if (AddrMode.BaseReg) { Value *V = AddrMode.BaseReg; - if (V->getType() != IntPtrTy) + if (isa(V->getType())) V = new PtrToIntInst(V, IntPtrTy, "sunkaddr", InsertPt); + if (V->getType() != IntPtrTy) + V = CastInst::CreateIntegerCast(V, IntPtrTy, /*isSigned=*/true, + "sunkaddr", InsertPt); if (Result) Result = BinaryOperator::CreateAdd(Result, V, "sunkaddr", InsertPt); else diff --git a/test/Archive/GNU.a b/test/Archive/GNU.a new file mode 100644 index 00000000000..4c09881eb39 Binary files /dev/null and b/test/Archive/GNU.a differ diff --git a/test/Archive/IsNAN.o b/test/Archive/IsNAN.o new file mode 100644 index 00000000000..7b3a12a69d7 Binary files /dev/null and b/test/Archive/IsNAN.o differ diff --git a/test/Archive/MacOSX.a b/test/Archive/MacOSX.a new file mode 100644 index 00000000000..77f88a2a7c8 Binary files /dev/null and b/test/Archive/MacOSX.a differ diff --git a/test/Archive/SVR4.a b/test/Archive/SVR4.a new file mode 100644 index 00000000000..3947813ac60 Binary files /dev/null and b/test/Archive/SVR4.a differ diff --git a/test/Archive/xpg4.a b/test/Archive/xpg4.a new file mode 100644 index 00000000000..b2bdb51188f Binary files /dev/null and b/test/Archive/xpg4.a differ diff --git a/test/CodeGen/ARM/str_pre-2.ll b/test/CodeGen/ARM/str_pre-2.ll new file mode 100644 index 00000000000..247465f3320 --- /dev/null +++ b/test/CodeGen/ARM/str_pre-2.ll @@ -0,0 +1,13 @@ +; RUN: llvm-as < %s | llc -mtriple=arm-linux-gnu | grep {str.*\\!} +; RUN: llvm-as < %s | llc -mtriple=arm-linux-gnu | grep {ldr.*\\\[.*\], #+4} +; XFAIL: * + +@b = external global i64* + +define i64 @t(i64 %a) nounwind readonly { +entry: + %0 = load i64** @b, align 4 + %1 = load i64* %0, align 4 + %2 = mul i64 %1, %a + ret i64 %2 +} diff --git a/test/CodeGen/X86/2009-06-02-RewriterBug.ll b/test/CodeGen/X86/2009-06-02-RewriterBug.ll new file mode 100644 index 00000000000..ea33b16f823 --- /dev/null +++ b/test/CodeGen/X86/2009-06-02-RewriterBug.ll @@ -0,0 +1,362 @@ +; RUN: llvm-as < %s | llc -mtriple=x86_64-undermydesk-freebsd8.0 -relocation-model=pic -disable-fp-elim +; PR4225 + +define void @sha256_block1(i32* nocapture %arr, i8* nocapture %in, i64 %num) nounwind { +entry: + br i1 undef, label %while.end, label %bb.nph + +bb.nph: ; preds = %entry + br label %while.body + +while.body: ; preds = %for.end, %bb.nph + %indvar2787 = phi i64 [ 0, %bb.nph ], [ %indvar.next2788, %for.end ] ; [#uses=2] + %tmp2791 = mul i64 %indvar2787, 44 ; [#uses=0] + %ctg22996 = getelementptr i8* %in, i64 0 ; [#uses=1] + %conv = zext i32 undef to i64 ; [#uses=1] + %conv11 = zext i32 undef to i64 ; [#uses=1] + %tmp18 = load i32* undef ; [#uses=1] + %conv19 = zext i32 %tmp18 to i64 ; [#uses=1] + %tmp30 = load i32* undef ; [#uses=1] + %conv31 = zext i32 %tmp30 to i64 ; [#uses=4] + %ptrincdec3065 = load i8* null ; [#uses=1] + %conv442709 = zext i8 %ptrincdec3065 to i64 ; [#uses=1] + %shl45 = shl i64 %conv442709, 16 ; [#uses=1] + %conv632707 = zext i8 undef to i64 ; [#uses=1] + %or = or i64 %shl45, 0 ; [#uses=1] + %or55 = or i64 %or, %conv632707 ; [#uses=1] + %or64 = or i64 %or55, 0 ; [#uses=1] + %shr85 = lshr i64 %conv31, 25 ; [#uses=0] + %add = add i64 %conv11, 1508970993 ; [#uses=1] + %add95 = add i64 %add, 0 ; [#uses=1] + %add98 = add i64 %add95, 0 ; [#uses=1] + %add99 = add i64 %add98, %or64 ; [#uses=1] + %add134 = add i64 %add99, 0 ; [#uses=4] + store i32 undef, i32* undef + %shl187 = shl i64 %add134, 21 ; [#uses=0] + %and203 = and i64 %add134, %conv31 ; [#uses=1] + %xor208 = xor i64 0, %and203 ; [#uses=1] + %add212 = add i64 0, %xor208 ; [#uses=1] + %add213 = add i64 %add212, 0 ; [#uses=1] + %add248 = add i64 %add213, 0 ; [#uses=3] + %conv2852690 = zext i8 undef to i64 ; [#uses=1] + %or277 = or i64 0, %conv2852690 ; [#uses=1] + %or286 = or i64 %or277, 0 ; [#uses=1] + %neg319 = xor i64 %add248, 4294967295 ; [#uses=1] + %and321 = and i64 %neg319, %conv31 ; [#uses=1] + %xor322 = xor i64 %and321, 0 ; [#uses=1] + %add314 = add i64 %conv, 2870763221 ; [#uses=1] + %add323 = add i64 %add314, %or286 ; [#uses=1] + %add326 = add i64 %add323, %xor322 ; [#uses=1] + %add327 = add i64 %add326, 0 ; [#uses=2] + %add362 = add i64 %add327, %conv19 ; [#uses=4] + %add365 = add i64 0, %add327 ; [#uses=3] + %shl409 = shl i64 %add362, 26 ; [#uses=0] + %and431 = and i64 %add362, %add248 ; [#uses=1] + %neg433 = xor i64 %add362, -1 ; [#uses=1] + %and435 = and i64 %add134, %neg433 ; [#uses=1] + %xor436 = xor i64 %and431, %and435 ; [#uses=1] + %add428 = add i64 %conv31, 3624381080 ; [#uses=1] + %add437 = add i64 %add428, 0 ; [#uses=1] + %add440 = add i64 %add437, %xor436 ; [#uses=1] + %add441 = add i64 %add440, 0 ; [#uses=1] + %shl443 = shl i64 %add365, 30 ; [#uses=1] + %and445 = lshr i64 %add365, 2 ; [#uses=1] + %shr446 = and i64 %and445, 1073741823 ; [#uses=1] + %or447 = or i64 %shr446, %shl443 ; [#uses=1] + %xor461 = xor i64 0, %or447 ; [#uses=1] + %add473 = add i64 %xor461, 0 ; [#uses=1] + %add479 = add i64 %add473, %add441 ; [#uses=3] + %conv4932682 = zext i8 undef to i64 ; [#uses=1] + %shl494 = shl i64 %conv4932682, 16 ; [#uses=1] + %ptrincdec4903012 = load i8* null ; [#uses=1] + %conv5032681 = zext i8 %ptrincdec4903012 to i64 ; [#uses=1] + %shl504 = shl i64 %conv5032681, 8 ; [#uses=1] + %ptrincdec5003009 = load i8* null ; [#uses=1] + %conv5132680 = zext i8 %ptrincdec5003009 to i64 ; [#uses=1] + %or495 = or i64 %shl494, 0 ; [#uses=1] + %or505 = or i64 %or495, %conv5132680 ; [#uses=1] + %or514 = or i64 %or505, %shl504 ; [#uses=1] + store i32 undef, i32* undef + %or540 = or i64 undef, 0 ; [#uses=0] + %add542 = add i64 %add134, 310598401 ; [#uses=1] + %add551 = add i64 %add542, %or514 ; [#uses=1] + %add554 = add i64 %add551, 0 ; [#uses=1] + %add555 = add i64 %add554, 0 ; [#uses=1] + %or561 = or i64 undef, undef ; [#uses=1] + %or567 = or i64 undef, undef ; [#uses=1] + %and572 = lshr i64 %add479, 22 ; [#uses=1] + %shr573 = and i64 %and572, 1023 ; [#uses=1] + %or574 = or i64 %shr573, 0 ; [#uses=1] + %xor568 = xor i64 %or567, %or574 ; [#uses=1] + %xor575 = xor i64 %xor568, %or561 ; [#uses=1] + %add587 = add i64 %xor575, 0 ; [#uses=1] + %add593 = add i64 %add587, %add555 ; [#uses=1] + %ptrincdec6043000 = load i8* null ; [#uses=1] + %conv6172676 = zext i8 %ptrincdec6043000 to i64 ; [#uses=1] + %shl618 = shl i64 %conv6172676, 8 ; [#uses=1] + %ptrincdec6142997 = load i8* %ctg22996 ; [#uses=1] + %conv6272675 = zext i8 %ptrincdec6142997 to i64 ; [#uses=1] + %or619 = or i64 0, %conv6272675 ; [#uses=1] + %or628 = or i64 %or619, %shl618 ; [#uses=1] + %add656 = add i64 %add248, 607225278 ; [#uses=1] + %add665 = add i64 %add656, %or628 ; [#uses=1] + %add668 = add i64 %add665, 0 ; [#uses=1] + %add669 = add i64 %add668, 0 ; [#uses=1] + %and699 = and i64 %add479, %add365 ; [#uses=1] + %xor700 = xor i64 0, %and699 ; [#uses=1] + %add701 = add i64 0, %xor700 ; [#uses=1] + %add707 = add i64 %add701, %add669 ; [#uses=4] + %ptrincdec6242994 = load i8* null ; [#uses=1] + %conv7122673 = zext i8 %ptrincdec6242994 to i64 ; [#uses=1] + %shl713 = shl i64 %conv7122673, 24 ; [#uses=1] + %conv7412670 = zext i8 undef to i64 ; [#uses=1] + %or723 = or i64 0, %shl713 ; [#uses=1] + %or733 = or i64 %or723, %conv7412670 ; [#uses=1] + %or742 = or i64 %or733, 0 ; [#uses=2] + %conv743 = trunc i64 %or742 to i32 ; [#uses=1] + store i32 %conv743, i32* undef + %xor762 = xor i64 undef, 0 ; [#uses=0] + %add770 = add i64 %add362, 1426881987 ; [#uses=1] + %add779 = add i64 %add770, %or742 ; [#uses=1] + %add782 = add i64 %add779, 0 ; [#uses=1] + %add783 = add i64 %add782, 0 ; [#uses=1] + %shl785 = shl i64 %add707, 30 ; [#uses=1] + %and787 = lshr i64 %add707, 2 ; [#uses=1] + %shr788 = and i64 %and787, 1073741823 ; [#uses=1] + %or789 = or i64 %shr788, %shl785 ; [#uses=1] + %shl791 = shl i64 %add707, 19 ; [#uses=0] + %xor803 = xor i64 0, %or789 ; [#uses=1] + %and813 = and i64 %add593, %add479 ; [#uses=1] + %xor814 = xor i64 0, %and813 ; [#uses=1] + %add815 = add i64 %xor803, %xor814 ; [#uses=1] + %add821 = add i64 %add815, %add783 ; [#uses=1] + %add1160 = add i64 0, %add707 ; [#uses=0] + %add1157 = add i64 undef, undef ; [#uses=0] + %ptrincdec11742940 = load i8* null ; [#uses=1] + %conv11872651 = zext i8 %ptrincdec11742940 to i64 ; [#uses=1] + %shl1188 = shl i64 %conv11872651, 8 ; [#uses=1] + %or1198 = or i64 0, %shl1188 ; [#uses=1] + store i32 undef, i32* undef + %add1226 = add i64 %or1198, 3248222580 ; [#uses=1] + %add1235 = add i64 %add1226, 0 ; [#uses=1] + %add1238 = add i64 %add1235, 0 ; [#uses=1] + %add1239 = add i64 %add1238, 0 ; [#uses=1] + br label %for.cond + +for.cond: ; preds = %for.body, %while.body + %add821.pn = phi i64 [ %add821, %while.body ], [ undef, %for.body ] ; [#uses=0] + %add1239.pn = phi i64 [ %add1239, %while.body ], [ 0, %for.body ] ; [#uses=0] + br i1 undef, label %for.end, label %for.body + +for.body: ; preds = %for.cond + br label %for.cond + +for.end: ; preds = %for.cond + %indvar.next2788 = add i64 %indvar2787, 1 ; [#uses=1] + br i1 undef, label %while.end, label %while.body + +while.end: ; preds = %for.end, %entry + ret void +} + +define void @sha256_block2(i32* nocapture %arr, i8* nocapture %in, i64 %num) nounwind { +entry: + br i1 undef, label %while.end, label %bb.nph + +bb.nph: ; preds = %entry + %arrayidx5 = getelementptr i32* %arr, i64 1 ; [#uses=1] + %arrayidx9 = getelementptr i32* %arr, i64 2 ; [#uses=2] + %arrayidx13 = getelementptr i32* %arr, i64 3 ; [#uses=2] + %arrayidx25 = getelementptr i32* %arr, i64 6 ; [#uses=1] + %arrayidx29 = getelementptr i32* %arr, i64 7 ; [#uses=1] + br label %while.body + +while.body: ; preds = %for.end, %bb.nph + %tmp3 = load i32* %arr ; [#uses=2] + %conv = zext i32 %tmp3 to i64 ; [#uses=1] + %tmp10 = load i32* %arrayidx9 ; [#uses=1] + %conv11 = zext i32 %tmp10 to i64 ; [#uses=1] + %tmp14 = load i32* %arrayidx13 ; [#uses=3] + %conv15 = zext i32 %tmp14 to i64 ; [#uses=2] + %tmp18 = load i32* undef ; [#uses=2] + %conv19 = zext i32 %tmp18 to i64 ; [#uses=1] + %conv23 = zext i32 undef to i64 ; [#uses=1] + %tmp26 = load i32* %arrayidx25 ; [#uses=1] + %conv27 = zext i32 %tmp26 to i64 ; [#uses=1] + %tmp30 = load i32* %arrayidx29 ; [#uses=2] + %conv31 = zext i32 %tmp30 to i64 ; [#uses=5] + %shl72 = shl i64 %conv31, 26 ; [#uses=1] + %shr = lshr i64 %conv31, 6 ; [#uses=1] + %or74 = or i64 %shl72, %shr ; [#uses=1] + %shr85 = lshr i64 %conv31, 25 ; [#uses=0] + %xor87 = xor i64 0, %or74 ; [#uses=1] + %and902706 = and i32 %tmp30, %tmp3 ; [#uses=1] + %and90 = zext i32 %and902706 to i64 ; [#uses=1] + %xor94 = xor i64 0, %and90 ; [#uses=1] + %add = add i64 %conv11, 1508970993 ; [#uses=1] + %add95 = add i64 %add, %xor94 ; [#uses=1] + %add98 = add i64 %add95, %xor87 ; [#uses=1] + %add99 = add i64 %add98, 0 ; [#uses=2] + %xor130 = zext i32 undef to i64 ; [#uses=1] + %add134 = add i64 %add99, %conv27 ; [#uses=2] + %add131 = add i64 %xor130, 0 ; [#uses=1] + %add137 = add i64 %add131, %add99 ; [#uses=5] + %conv1422700 = zext i8 undef to i64 ; [#uses=1] + %shl143 = shl i64 %conv1422700, 24 ; [#uses=1] + %ptrincdec1393051 = load i8* undef ; [#uses=1] + %conv1512699 = zext i8 %ptrincdec1393051 to i64 ; [#uses=1] + %shl152 = shl i64 %conv1512699, 16 ; [#uses=1] + %conv1712697 = zext i8 undef to i64 ; [#uses=1] + %or153 = or i64 %shl152, %shl143 ; [#uses=1] + %or163 = or i64 %or153, %conv1712697 ; [#uses=1] + %or172 = or i64 %or163, 0 ; [#uses=1] + %and203 = and i64 %add134, %conv31 ; [#uses=1] + %xor208 = xor i64 0, %and203 ; [#uses=1] + %add200 = add i64 0, 2453635748 ; [#uses=1] + %add209 = add i64 %add200, %or172 ; [#uses=1] + %add212 = add i64 %add209, %xor208 ; [#uses=1] + %add213 = add i64 %add212, 0 ; [#uses=2] + %shl228 = shl i64 %add137, 10 ; [#uses=1] + %and230 = lshr i64 %add137, 22 ; [#uses=1] + %shr231 = and i64 %and230, 1023 ; [#uses=1] + %or232 = or i64 %shr231, %shl228 ; [#uses=1] + %xor226 = xor i64 0, %or232 ; [#uses=1] + %xor233 = xor i64 %xor226, 0 ; [#uses=1] + %and2362695 = zext i32 undef to i64 ; [#uses=1] + %xor240 = and i64 %add137, %and2362695 ; [#uses=1] + %and2432694 = and i32 %tmp18, %tmp14 ; [#uses=1] + %and243 = zext i32 %and2432694 to i64 ; [#uses=1] + %xor244 = xor i64 %xor240, %and243 ; [#uses=1] + %add248 = add i64 %add213, %conv23 ; [#uses=2] + %add245 = add i64 %xor233, %xor244 ; [#uses=1] + %add251 = add i64 %add245, %add213 ; [#uses=1] + %conv2752691 = zext i8 undef to i64 ; [#uses=1] + %shl276 = shl i64 %conv2752691, 8 ; [#uses=0] + %and317 = and i64 %add248, %add134 ; [#uses=1] + %neg319 = xor i64 %add248, 4294967295 ; [#uses=1] + %and321 = and i64 %neg319, %conv31 ; [#uses=1] + %xor322 = xor i64 %and321, %and317 ; [#uses=1] + %add314 = add i64 %conv, 2870763221 ; [#uses=1] + %add323 = add i64 %add314, 0 ; [#uses=1] + %add326 = add i64 %add323, %xor322 ; [#uses=1] + %add327 = add i64 %add326, 0 ; [#uses=2] + %and3502689 = xor i64 %add137, %conv15 ; [#uses=1] + %xor354 = and i64 %add251, %and3502689 ; [#uses=1] + %and357 = and i64 %add137, %conv15 ; [#uses=1] + %xor358 = xor i64 %xor354, %and357 ; [#uses=1] + %add362 = add i64 %add327, %conv19 ; [#uses=1] + %add359 = add i64 0, %xor358 ; [#uses=1] + %add365 = add i64 %add359, %add327 ; [#uses=1] + %add770 = add i64 %add362, 1426881987 ; [#uses=1] + %add779 = add i64 %add770, 0 ; [#uses=1] + %add782 = add i64 %add779, 0 ; [#uses=1] + %add783 = add i64 %add782, 0 ; [#uses=2] + %add818 = add i64 %add783, %add365 ; [#uses=1] + %add821 = add i64 0, %add783 ; [#uses=1] + store i32 undef, i32* undef + %add1046 = add i64 undef, undef ; [#uses=1] + %add1160 = add i64 undef, undef ; [#uses=1] + store i32 0, i32* undef + %add1235 = add i64 0, %add818 ; [#uses=1] + %add1238 = add i64 %add1235, 0 ; [#uses=1] + %add1239 = add i64 %add1238, 0 ; [#uses=1] + br label %for.cond + +for.cond: ; preds = %for.body, %while.body + %h.0 = phi i64 [ undef, %while.body ], [ %add2035, %for.body ] ; [#uses=1] + %g.0 = phi i64 [ %add1046, %while.body ], [ undef, %for.body ] ; [#uses=1] + %f.0 = phi i64 [ %add1160, %while.body ], [ undef, %for.body ] ; [#uses=1] + %add821.pn = phi i64 [ %add821, %while.body ], [ undef, %for.body ] ; [#uses=0] + %add1239.pn2648 = phi i64 [ %add1239, %while.body ], [ undef, %for.body ] ; [#uses=0] + %d.0 = phi i64 [ undef, %while.body ], [ %add2038, %for.body ] ; [#uses=2] + br i1 undef, label %for.end, label %for.body + +for.body: ; preds = %for.cond + %conv1390 = zext i32 undef to i64 ; [#uses=1] + %add1375 = add i64 0, %h.0 ; [#uses=1] + %add1384 = add i64 %add1375, 0 ; [#uses=1] + %add1391 = add i64 %add1384, %conv1390 ; [#uses=1] + %add1392 = add i64 %add1391, 0 ; [#uses=2] + %or1411 = or i64 0, undef ; [#uses=1] + %xor1405 = xor i64 0, %or1411 ; [#uses=1] + %xor1412 = xor i64 %xor1405, 0 ; [#uses=1] + %add1427 = add i64 %add1392, %d.0 ; [#uses=1] + %add1424 = add i64 %xor1412, 0 ; [#uses=1] + %add1430 = add i64 %add1424, %add1392 ; [#uses=5] + %tmp1438 = load i32* undef ; [#uses=1] + %conv1439 = zext i32 %tmp1438 to i64 ; [#uses=4] + %shl1441 = shl i64 %conv1439, 25 ; [#uses=1] + %shr1444 = lshr i64 %conv1439, 7 ; [#uses=1] + %or1445 = or i64 %shl1441, %shr1444 ; [#uses=1] + %shr1450 = lshr i64 %conv1439, 18 ; [#uses=1] + %or1451 = or i64 0, %shr1450 ; [#uses=1] + %shr1454 = lshr i64 %conv1439, 3 ; [#uses=1] + %xor1452 = xor i64 %or1451, %shr1454 ; [#uses=1] + %xor1455 = xor i64 %xor1452, %or1445 ; [#uses=1] + %conv1464 = zext i32 undef to i64 ; [#uses=4] + %shl1466 = shl i64 %conv1464, 15 ; [#uses=1] + %shr1469 = lshr i64 %conv1464, 17 ; [#uses=1] + %or1470 = or i64 %shl1466, %shr1469 ; [#uses=1] + %shr1475 = lshr i64 %conv1464, 19 ; [#uses=1] + %or1476 = or i64 0, %shr1475 ; [#uses=1] + %shr1479 = lshr i64 %conv1464, 10 ; [#uses=1] + %xor1477 = xor i64 %or1476, %shr1479 ; [#uses=1] + %xor1480 = xor i64 %xor1477, %or1470 ; [#uses=1] + %tmp1499 = load i32* null ; [#uses=1] + %conv1500 = zext i32 %tmp1499 to i64 ; [#uses=1] + %add1491 = add i64 %conv1500, 0 ; [#uses=1] + %add1501 = add i64 %add1491, %xor1455 ; [#uses=1] + %add1502 = add i64 %add1501, %xor1480 ; [#uses=1] + %conv1504 = and i64 %add1502, 4294967295 ; [#uses=1] + %tmp1541 = load i32* undef ; [#uses=1] + %conv1542 = zext i32 %tmp1541 to i64 ; [#uses=1] + %add1527 = add i64 %conv1542, %g.0 ; [#uses=1] + %add1536 = add i64 %add1527, 0 ; [#uses=1] + %add1543 = add i64 %add1536, %conv1504 ; [#uses=1] + %add1544 = add i64 %add1543, 0 ; [#uses=1] + %shl1546 = shl i64 %add1430, 30 ; [#uses=1] + %and1548 = lshr i64 %add1430, 2 ; [#uses=1] + %shr1549 = and i64 %and1548, 1073741823 ; [#uses=1] + %or1550 = or i64 %shr1549, %shl1546 ; [#uses=1] + %shl1552 = shl i64 %add1430, 19 ; [#uses=1] + %or1556 = or i64 0, %shl1552 ; [#uses=1] + %shl1559 = shl i64 %add1430, 10 ; [#uses=1] + %or1563 = or i64 0, %shl1559 ; [#uses=1] + %xor1557 = xor i64 %or1556, %or1563 ; [#uses=1] + %xor1564 = xor i64 %xor1557, %or1550 ; [#uses=1] + %add1576 = add i64 %xor1564, 0 ; [#uses=1] + %add1582 = add i64 %add1576, %add1544 ; [#uses=3] + store i32 undef, i32* undef + %tmp1693 = load i32* undef ; [#uses=1] + %conv1694 = zext i32 %tmp1693 to i64 ; [#uses=1] + %add1679 = add i64 %conv1694, %f.0 ; [#uses=1] + %add1688 = add i64 %add1679, 0 ; [#uses=1] + %add1695 = add i64 %add1688, 0 ; [#uses=1] + %add1696 = add i64 %add1695, 0 ; [#uses=1] + %shl1698 = shl i64 %add1582, 30 ; [#uses=0] + %shl1704 = shl i64 %add1582, 19 ; [#uses=0] + %add1734 = add i64 0, %add1696 ; [#uses=1] + %add1983 = add i64 0, %add1427 ; [#uses=1] + %add1992 = add i64 %add1983, 0 ; [#uses=1] + %add1999 = add i64 %add1992, 0 ; [#uses=1] + %add2000 = add i64 %add1999, 0 ; [#uses=2] + %and2030 = and i64 %add1734, %add1582 ; [#uses=1] + %xor2031 = xor i64 0, %and2030 ; [#uses=1] + %add2035 = add i64 %add2000, %add1430 ; [#uses=1] + %add2032 = add i64 0, %xor2031 ; [#uses=1] + %add2038 = add i64 %add2032, %add2000 ; [#uses=1] + store i32 0, i32* undef + br label %for.cond + +for.end: ; preds = %for.cond + store i32 undef, i32* %arrayidx5 + store i32 undef, i32* %arrayidx9 + %d.02641 = trunc i64 %d.0 to i32 ; [#uses=1] + %conv2524 = add i32 %tmp14, %d.02641 ; [#uses=1] + store i32 %conv2524, i32* %arrayidx13 + %exitcond2789 = icmp eq i64 undef, %num ; [#uses=1] + br i1 %exitcond2789, label %while.end, label %while.body + +while.end: ; preds = %for.end, %entry + ret void +} diff --git a/test/CodeGen/X86/codegen-prepare-cast.ll b/test/CodeGen/X86/codegen-prepare-cast.ll new file mode 100644 index 00000000000..ae3eb5f6d68 --- /dev/null +++ b/test/CodeGen/X86/codegen-prepare-cast.ll @@ -0,0 +1,24 @@ +; RUN: llvm-as < %s | llc -march=x86-64 +; PR4297 + +target datalayout = +"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128" +target triple = "x86_64-unknown-linux-gnu" + %"byte[]" = type { i64, i8* } + %"char[][]" = type { i64, %"byte[]"* } +@.str = external constant [7 x i8] ; <[7 x i8]*> [#uses=1] + +define fastcc i32 @_Dmain(%"char[][]" %unnamed) { +entry: + %tmp = getelementptr [7 x i8]* @.str, i32 0, i32 0 ; [#uses=1] + br i1 undef, label %foreachbody, label %foreachend + +foreachbody: ; preds = %entry + %tmp4 = getelementptr i8* %tmp, i32 undef ; [#uses=1] + %tmp5 = load i8* %tmp4 ; [#uses=0] + unreachable + +foreachend: ; preds = %entry + ret i32 0 +} + diff --git a/test/CodeGen/X86/x86-store-gv-addr.ll b/test/CodeGen/X86/x86-store-gv-addr.ll new file mode 100644 index 00000000000..799340d35dd --- /dev/null +++ b/test/CodeGen/X86/x86-store-gv-addr.ll @@ -0,0 +1,10 @@ +; RUN: llvm-as < %s | llc -mtriple=x86_64-apple-darwin -relocation-model=static | not grep lea +; RUN: llvm-as < %s | llc -mtriple=x86_64-pc-linux-gnu -relocation-model=static | not grep lea + +@v = external global i32, align 8 +@v_addr = external global i32*, align 8 + +define void @t() nounwind optsize { + store i32* @v, i32** @v_addr, align 8 + unreachable +} diff --git a/utils/NewNightlyTest.pl b/utils/NewNightlyTest.pl index 9672632fa27..a40b3f11a2b 100755 --- a/utils/NewNightlyTest.pl +++ b/utils/NewNightlyTest.pl @@ -22,10 +22,7 @@ use Socket; # -noremoveresults Do not remove the WEBDIR after it has been built. # -nobuild Do not build llvm. If tests are enabled perform them # on the llvm build specified in the build directory -# -notest Do not even attempt to run the test programs. Implies -# -norunningtests. -# -norunningtests Do not run the Olden benchmark suite with -# LARGE_PROBLEM_SIZE enabled. +# -notest Do not even attempt to run the test programs. # -nodejagnu Do not run feature or regression tests # -parallel Run parallel jobs with GNU Make (see -parallel-jobs). # -parallel-jobs The number of parallel Make jobs to use (default is two). @@ -128,7 +125,6 @@ $CONFIGUREARGS=""; $nickname=""; $NOTEST=0; $USESVN=1; -$NORUNNINGTESTS=0; $MAKECMD="make"; $SUBMITSERVER = "llvm.org"; $SUBMITSCRIPT = "/nightlytest/NightlyTestAccept.php"; @@ -145,8 +141,8 @@ while (scalar(@ARGV) and ($_ = $ARGV[0], /^[-+]/)) { if (/^-nocvsstats$/) { $NOCVSSTATS = 1; next; } if (/^-noremove$/) { $NOREMOVE = 1; next; } if (/^-noremoveresults$/){ $NOREMOVERESULTS = 1; next; } - if (/^-notest$/) { $NOTEST = 1; $NORUNNINGTESTS = 1; next; } - if (/^-norunningtests$/) { $NORUNNINGTESTS = 1; next; } + if (/^-notest$/) { $NOTEST = 1; next; } + if (/^-norunningtests$/) { next; } # Backward compatibility, ignored. if (/^-parallel-jobs$/) { $PARALLELJOBS = "$ARGV[0]"; shift; next;} if (/^-parallel$/) { $MAKEOPTS = "$MAKEOPTS -j$PARALLELJOBS -l3.0"; next; } if (/^-release$/) { $MAKEOPTS = "$MAKEOPTS ENABLE_OPTIMIZED=1 ". @@ -252,7 +248,6 @@ if ($BUILDTYPE ne "release" && $BUILDTYPE ne "release-asserts") { my $Prefix = "$WebDir/$DATE"; my $BuildLog = "$Prefix-Build-Log.txt"; my $COLog = "$Prefix-CVS-Log.txt"; -my $OldenTestsLog = "$Prefix-Olden-tests.txt"; my $SingleSourceLog = "$Prefix-SingleSource-ProgramTest.txt.gz"; my $MultiSourceLog = "$Prefix-MultiSource-ProgramTest.txt.gz"; my $ExternalLog = "$Prefix-External-ProgramTest.txt.gz"; @@ -1006,38 +1001,6 @@ if (!$BuildError) { } #end if !$BuildError - -############################################################## -# -# If we built the tree successfully, runs of the Olden suite with -# LARGE_PROBLEM_SIZE on so that we can get some "running" statistics. -# -############################################################## -if (!$BuildError) { - if ( $VERBOSE ) { print "OLDEN TEST SUITE STAGE\n"; } - my ($NATTime, $CBETime, $LLCTime, $JITTime, $OptTime, $BytecodeSize, - $MachCodeSize) = ("","","","","","",""); - if (!$NORUNNINGTESTS) { - ChangeDir( "$BuildDir/llvm/projects/llvm-test/MultiSource/Benchmarks/Olden", - "Olden Test Directory"); - - # Clean out previous results... - system "$NICE $MAKECMD $MAKEOPTS clean > /dev/null 2>&1"; - - # Run the nightly test in this directory, with LARGE_PROBLEM_SIZE and - # GET_STABLE_NUMBERS enabled! - if( $VERBOSE ) { - print "$MAKECMD -k $MAKEOPTS $PROGTESTOPTS report.nightly.csv.out " . - "TEST=nightly LARGE_PROBLEM_SIZE=1 GET_STABLE_NUMBERS=1 " . - "> /dev/null 2>&1\n"; - } - system "$MAKECMD -k $MAKEOPTS $PROGTESTOPTS report.nightly.csv.out " . - "TEST=nightly LARGE_PROBLEM_SIZE=1 GET_STABLE_NUMBERS=1 " . - "> /dev/null 2>&1"; - system "cp report.nightly.csv $OldenTestsLog"; - } -} - ############################################################## # # Getting end timestamp