parent
009b1c42aa
commit
33a8e4360f
|
@ -2403,9 +2403,10 @@ cleanup is performed in the case of either a <tt>longjmp</tt> or a thrown
|
|||
exception. Additionally, this is important for implementation of
|
||||
'<tt>catch</tt>' clauses in high-level languages that support them.</p>
|
||||
|
||||
<p>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.</p>
|
||||
<p>For the purposes of the SSA form, the definition of the value
|
||||
returned by the '<tt>invoke</tt>' 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.</p>
|
||||
|
||||
<h5>Example:</h5>
|
||||
<pre>
|
||||
|
@ -4518,6 +4519,11 @@ may be used as the label arguments.</p>
|
|||
block and the PHI instructions: i.e. PHI instructions must be first in
|
||||
a basic block.</p>
|
||||
|
||||
<p>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 '<tt>invoke</tt>'
|
||||
instruction's return value on the same edge).</p>
|
||||
|
||||
<h5>Semantics:</h5>
|
||||
|
||||
<p>At runtime, the '<tt>phi</tt>' instruction logically takes on the value
|
||||
|
@ -7104,7 +7110,7 @@ declare void @llvm.stackprotector( i8* <guard>, i8** <slot> )
|
|||
|
||||
<a href="mailto:sabre@nondot.org">Chris Lattner</a><br>
|
||||
<a href="http://llvm.org">The LLVM Compiler Infrastructure</a><br>
|
||||
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) $
|
||||
</address>
|
||||
|
||||
</body>
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
namespace llvm {
|
||||
class ConstantInt;
|
||||
class ConstantRange;
|
||||
class APInt;
|
||||
class DominatorTree;
|
||||
|
||||
enum SCEVTypes {
|
||||
|
|
|
@ -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<ConstantExpr>(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
|
||||
|
|
|
@ -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<Constant*, 8> Ops;
|
||||
for (User::op_iterator i = CE->op_begin(), e = CE->op_end(); i != e; ++i)
|
||||
Ops.push_back(cast<Constant>(*i));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <string>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
typedef std::vector<unsigned char> 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 <mach-o/stab.h>
|
||||
uint64_t n_value; // value for this symbol (or stab offset)
|
||||
|
||||
// Constants for the n_sect field
|
||||
// see <mach-o/nlist.h>
|
||||
enum { NO_SECT = 0 }; // symbol is not in any section
|
||||
|
||||
// Constants for the n_type field
|
||||
// see <mach-o/nlist.h>
|
||||
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 <mach-o/loader.h>
|
||||
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 <mach-o/loader.h> 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 <mach/shared_memory_server.h>
|
||||
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 <mach-o/vm_prot.h>
|
||||
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 <mach-o/loader.h>
|
||||
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<MachineRelocation> Relocations;
|
||||
|
||||
// Constants for the section types (low 8 bits of flags field)
|
||||
// see <mach-o/loader.h>
|
||||
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 <mach-o/loader.h>
|
||||
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 <mach-o/loader.h>
|
||||
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
|
||||
|
|
@ -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<MachineConstantPoolEntry> &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<MachineJumpTableEntry> &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<MachineBasicBlock*> &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
|
||||
|
|
@ -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 <vector>
|
||||
|
||||
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<MachineRelocation> 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<uintptr_t> CPLocations;
|
||||
|
||||
/// CPSections - This is a map of constant pool indices to the MachOSection
|
||||
/// containing the constant pool entry for that index.
|
||||
std::vector<unsigned> 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<uintptr_t> 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<uintptr_t> 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
|
||||
|
|
@ -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 <algorithm>
|
||||
#include <cstring>
|
||||
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<MachineRelocation> 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<uintptr_t> CPLocations;
|
||||
|
||||
/// CPSections - This is a map of constant pool indices to the MachOSection
|
||||
/// containing the constant pool entry for that index.
|
||||
std::vector<unsigned> 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<uintptr_t> 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<uintptr_t> 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<MachineConstantPoolEntry> &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<MachineJumpTableEntry> &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<MachineBasicBlock*> &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<MachOSection*>::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<MachOSection*>::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<MachOSection*>::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<MachOSection*>::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<GlobalValue*>::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<MachOSym>::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<MachOSym>::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<MachOSym>::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<MachineRelocation> &MRs) {
|
||||
typedef std::pair<const Constant*, intptr_t> CPair;
|
||||
std::vector<CPair> 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<UndefValue>(PC)) {
|
||||
continue;
|
||||
} else if (const ConstantVector *CP = dyn_cast<ConstantVector>(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<IntegerType>(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
|
||||
|
||||
|
|
|
@ -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 <mach-o/stab.h>
|
||||
uint64_t n_value; // value for this symbol (or stab offset)
|
||||
|
||||
// Constants for the n_sect field
|
||||
// see <mach-o/nlist.h>
|
||||
enum { NO_SECT = 0 }; // symbol is not in any section
|
||||
|
||||
// Constants for the n_type field
|
||||
// see <mach-o/nlist.h>
|
||||
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 <mach-o/loader.h>
|
||||
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<uint8_t> 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 <mach-o/loader.h> 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 <mach/shared_memory_server.h>
|
||||
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 <mach-o/vm_prot.h>
|
||||
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 <mach-o/loader.h>
|
||||
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<MachineRelocation> Relocations;
|
||||
|
||||
// Constants for the section types (low 8 bits of flags field)
|
||||
// see <mach-o/loader.h>
|
||||
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 <mach-o/loader.h>
|
||||
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<MachOSection*> SectionList;
|
||||
|
||||
/// SectionLookup - This is a mapping from section name to SectionList entry
|
||||
|
||||
std::map<std::string, MachOSection*> SectionLookup;
|
||||
|
||||
/// GVSection - This is a mapping from a GlobalValue to a MachOSection,
|
||||
/// to aid in emitting relocations.
|
||||
|
||||
std::map<GlobalValue*, MachOSection*> 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<GlobalValue*, intptr_t> 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 <mach-o/loader.h>
|
||||
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);
|
||||
|
||||
|
|
|
@ -312,93 +312,6 @@ namespace {
|
|||
static RegisterPass<RALinScan>
|
||||
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_);
|
||||
|
||||
|
|
|
@ -411,9 +411,11 @@ static void InvalidateKill(unsigned Reg,
|
|||
std::vector<MachineOperand*> &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.
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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<Instruction>(V)) {
|
||||
Opcode = I->getOpcode();
|
||||
|
|
|
@ -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<PointerType>(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
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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
|
||||
}
|
|
@ -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 ] ; <i64> [#uses=2]
|
||||
%tmp2791 = mul i64 %indvar2787, 44 ; <i64> [#uses=0]
|
||||
%ctg22996 = getelementptr i8* %in, i64 0 ; <i8*> [#uses=1]
|
||||
%conv = zext i32 undef to i64 ; <i64> [#uses=1]
|
||||
%conv11 = zext i32 undef to i64 ; <i64> [#uses=1]
|
||||
%tmp18 = load i32* undef ; <i32> [#uses=1]
|
||||
%conv19 = zext i32 %tmp18 to i64 ; <i64> [#uses=1]
|
||||
%tmp30 = load i32* undef ; <i32> [#uses=1]
|
||||
%conv31 = zext i32 %tmp30 to i64 ; <i64> [#uses=4]
|
||||
%ptrincdec3065 = load i8* null ; <i8> [#uses=1]
|
||||
%conv442709 = zext i8 %ptrincdec3065 to i64 ; <i64> [#uses=1]
|
||||
%shl45 = shl i64 %conv442709, 16 ; <i64> [#uses=1]
|
||||
%conv632707 = zext i8 undef to i64 ; <i64> [#uses=1]
|
||||
%or = or i64 %shl45, 0 ; <i64> [#uses=1]
|
||||
%or55 = or i64 %or, %conv632707 ; <i64> [#uses=1]
|
||||
%or64 = or i64 %or55, 0 ; <i64> [#uses=1]
|
||||
%shr85 = lshr i64 %conv31, 25 ; <i64> [#uses=0]
|
||||
%add = add i64 %conv11, 1508970993 ; <i64> [#uses=1]
|
||||
%add95 = add i64 %add, 0 ; <i64> [#uses=1]
|
||||
%add98 = add i64 %add95, 0 ; <i64> [#uses=1]
|
||||
%add99 = add i64 %add98, %or64 ; <i64> [#uses=1]
|
||||
%add134 = add i64 %add99, 0 ; <i64> [#uses=4]
|
||||
store i32 undef, i32* undef
|
||||
%shl187 = shl i64 %add134, 21 ; <i64> [#uses=0]
|
||||
%and203 = and i64 %add134, %conv31 ; <i64> [#uses=1]
|
||||
%xor208 = xor i64 0, %and203 ; <i64> [#uses=1]
|
||||
%add212 = add i64 0, %xor208 ; <i64> [#uses=1]
|
||||
%add213 = add i64 %add212, 0 ; <i64> [#uses=1]
|
||||
%add248 = add i64 %add213, 0 ; <i64> [#uses=3]
|
||||
%conv2852690 = zext i8 undef to i64 ; <i64> [#uses=1]
|
||||
%or277 = or i64 0, %conv2852690 ; <i64> [#uses=1]
|
||||
%or286 = or i64 %or277, 0 ; <i64> [#uses=1]
|
||||
%neg319 = xor i64 %add248, 4294967295 ; <i64> [#uses=1]
|
||||
%and321 = and i64 %neg319, %conv31 ; <i64> [#uses=1]
|
||||
%xor322 = xor i64 %and321, 0 ; <i64> [#uses=1]
|
||||
%add314 = add i64 %conv, 2870763221 ; <i64> [#uses=1]
|
||||
%add323 = add i64 %add314, %or286 ; <i64> [#uses=1]
|
||||
%add326 = add i64 %add323, %xor322 ; <i64> [#uses=1]
|
||||
%add327 = add i64 %add326, 0 ; <i64> [#uses=2]
|
||||
%add362 = add i64 %add327, %conv19 ; <i64> [#uses=4]
|
||||
%add365 = add i64 0, %add327 ; <i64> [#uses=3]
|
||||
%shl409 = shl i64 %add362, 26 ; <i64> [#uses=0]
|
||||
%and431 = and i64 %add362, %add248 ; <i64> [#uses=1]
|
||||
%neg433 = xor i64 %add362, -1 ; <i64> [#uses=1]
|
||||
%and435 = and i64 %add134, %neg433 ; <i64> [#uses=1]
|
||||
%xor436 = xor i64 %and431, %and435 ; <i64> [#uses=1]
|
||||
%add428 = add i64 %conv31, 3624381080 ; <i64> [#uses=1]
|
||||
%add437 = add i64 %add428, 0 ; <i64> [#uses=1]
|
||||
%add440 = add i64 %add437, %xor436 ; <i64> [#uses=1]
|
||||
%add441 = add i64 %add440, 0 ; <i64> [#uses=1]
|
||||
%shl443 = shl i64 %add365, 30 ; <i64> [#uses=1]
|
||||
%and445 = lshr i64 %add365, 2 ; <i64> [#uses=1]
|
||||
%shr446 = and i64 %and445, 1073741823 ; <i64> [#uses=1]
|
||||
%or447 = or i64 %shr446, %shl443 ; <i64> [#uses=1]
|
||||
%xor461 = xor i64 0, %or447 ; <i64> [#uses=1]
|
||||
%add473 = add i64 %xor461, 0 ; <i64> [#uses=1]
|
||||
%add479 = add i64 %add473, %add441 ; <i64> [#uses=3]
|
||||
%conv4932682 = zext i8 undef to i64 ; <i64> [#uses=1]
|
||||
%shl494 = shl i64 %conv4932682, 16 ; <i64> [#uses=1]
|
||||
%ptrincdec4903012 = load i8* null ; <i8> [#uses=1]
|
||||
%conv5032681 = zext i8 %ptrincdec4903012 to i64 ; <i64> [#uses=1]
|
||||
%shl504 = shl i64 %conv5032681, 8 ; <i64> [#uses=1]
|
||||
%ptrincdec5003009 = load i8* null ; <i8> [#uses=1]
|
||||
%conv5132680 = zext i8 %ptrincdec5003009 to i64 ; <i64> [#uses=1]
|
||||
%or495 = or i64 %shl494, 0 ; <i64> [#uses=1]
|
||||
%or505 = or i64 %or495, %conv5132680 ; <i64> [#uses=1]
|
||||
%or514 = or i64 %or505, %shl504 ; <i64> [#uses=1]
|
||||
store i32 undef, i32* undef
|
||||
%or540 = or i64 undef, 0 ; <i64> [#uses=0]
|
||||
%add542 = add i64 %add134, 310598401 ; <i64> [#uses=1]
|
||||
%add551 = add i64 %add542, %or514 ; <i64> [#uses=1]
|
||||
%add554 = add i64 %add551, 0 ; <i64> [#uses=1]
|
||||
%add555 = add i64 %add554, 0 ; <i64> [#uses=1]
|
||||
%or561 = or i64 undef, undef ; <i64> [#uses=1]
|
||||
%or567 = or i64 undef, undef ; <i64> [#uses=1]
|
||||
%and572 = lshr i64 %add479, 22 ; <i64> [#uses=1]
|
||||
%shr573 = and i64 %and572, 1023 ; <i64> [#uses=1]
|
||||
%or574 = or i64 %shr573, 0 ; <i64> [#uses=1]
|
||||
%xor568 = xor i64 %or567, %or574 ; <i64> [#uses=1]
|
||||
%xor575 = xor i64 %xor568, %or561 ; <i64> [#uses=1]
|
||||
%add587 = add i64 %xor575, 0 ; <i64> [#uses=1]
|
||||
%add593 = add i64 %add587, %add555 ; <i64> [#uses=1]
|
||||
%ptrincdec6043000 = load i8* null ; <i8> [#uses=1]
|
||||
%conv6172676 = zext i8 %ptrincdec6043000 to i64 ; <i64> [#uses=1]
|
||||
%shl618 = shl i64 %conv6172676, 8 ; <i64> [#uses=1]
|
||||
%ptrincdec6142997 = load i8* %ctg22996 ; <i8> [#uses=1]
|
||||
%conv6272675 = zext i8 %ptrincdec6142997 to i64 ; <i64> [#uses=1]
|
||||
%or619 = or i64 0, %conv6272675 ; <i64> [#uses=1]
|
||||
%or628 = or i64 %or619, %shl618 ; <i64> [#uses=1]
|
||||
%add656 = add i64 %add248, 607225278 ; <i64> [#uses=1]
|
||||
%add665 = add i64 %add656, %or628 ; <i64> [#uses=1]
|
||||
%add668 = add i64 %add665, 0 ; <i64> [#uses=1]
|
||||
%add669 = add i64 %add668, 0 ; <i64> [#uses=1]
|
||||
%and699 = and i64 %add479, %add365 ; <i64> [#uses=1]
|
||||
%xor700 = xor i64 0, %and699 ; <i64> [#uses=1]
|
||||
%add701 = add i64 0, %xor700 ; <i64> [#uses=1]
|
||||
%add707 = add i64 %add701, %add669 ; <i64> [#uses=4]
|
||||
%ptrincdec6242994 = load i8* null ; <i8> [#uses=1]
|
||||
%conv7122673 = zext i8 %ptrincdec6242994 to i64 ; <i64> [#uses=1]
|
||||
%shl713 = shl i64 %conv7122673, 24 ; <i64> [#uses=1]
|
||||
%conv7412670 = zext i8 undef to i64 ; <i64> [#uses=1]
|
||||
%or723 = or i64 0, %shl713 ; <i64> [#uses=1]
|
||||
%or733 = or i64 %or723, %conv7412670 ; <i64> [#uses=1]
|
||||
%or742 = or i64 %or733, 0 ; <i64> [#uses=2]
|
||||
%conv743 = trunc i64 %or742 to i32 ; <i32> [#uses=1]
|
||||
store i32 %conv743, i32* undef
|
||||
%xor762 = xor i64 undef, 0 ; <i64> [#uses=0]
|
||||
%add770 = add i64 %add362, 1426881987 ; <i64> [#uses=1]
|
||||
%add779 = add i64 %add770, %or742 ; <i64> [#uses=1]
|
||||
%add782 = add i64 %add779, 0 ; <i64> [#uses=1]
|
||||
%add783 = add i64 %add782, 0 ; <i64> [#uses=1]
|
||||
%shl785 = shl i64 %add707, 30 ; <i64> [#uses=1]
|
||||
%and787 = lshr i64 %add707, 2 ; <i64> [#uses=1]
|
||||
%shr788 = and i64 %and787, 1073741823 ; <i64> [#uses=1]
|
||||
%or789 = or i64 %shr788, %shl785 ; <i64> [#uses=1]
|
||||
%shl791 = shl i64 %add707, 19 ; <i64> [#uses=0]
|
||||
%xor803 = xor i64 0, %or789 ; <i64> [#uses=1]
|
||||
%and813 = and i64 %add593, %add479 ; <i64> [#uses=1]
|
||||
%xor814 = xor i64 0, %and813 ; <i64> [#uses=1]
|
||||
%add815 = add i64 %xor803, %xor814 ; <i64> [#uses=1]
|
||||
%add821 = add i64 %add815, %add783 ; <i64> [#uses=1]
|
||||
%add1160 = add i64 0, %add707 ; <i64> [#uses=0]
|
||||
%add1157 = add i64 undef, undef ; <i64> [#uses=0]
|
||||
%ptrincdec11742940 = load i8* null ; <i8> [#uses=1]
|
||||
%conv11872651 = zext i8 %ptrincdec11742940 to i64 ; <i64> [#uses=1]
|
||||
%shl1188 = shl i64 %conv11872651, 8 ; <i64> [#uses=1]
|
||||
%or1198 = or i64 0, %shl1188 ; <i64> [#uses=1]
|
||||
store i32 undef, i32* undef
|
||||
%add1226 = add i64 %or1198, 3248222580 ; <i64> [#uses=1]
|
||||
%add1235 = add i64 %add1226, 0 ; <i64> [#uses=1]
|
||||
%add1238 = add i64 %add1235, 0 ; <i64> [#uses=1]
|
||||
%add1239 = add i64 %add1238, 0 ; <i64> [#uses=1]
|
||||
br label %for.cond
|
||||
|
||||
for.cond: ; preds = %for.body, %while.body
|
||||
%add821.pn = phi i64 [ %add821, %while.body ], [ undef, %for.body ] ; <i64> [#uses=0]
|
||||
%add1239.pn = phi i64 [ %add1239, %while.body ], [ 0, %for.body ] ; <i64> [#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 ; <i64> [#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 ; <i32*> [#uses=1]
|
||||
%arrayidx9 = getelementptr i32* %arr, i64 2 ; <i32*> [#uses=2]
|
||||
%arrayidx13 = getelementptr i32* %arr, i64 3 ; <i32*> [#uses=2]
|
||||
%arrayidx25 = getelementptr i32* %arr, i64 6 ; <i32*> [#uses=1]
|
||||
%arrayidx29 = getelementptr i32* %arr, i64 7 ; <i32*> [#uses=1]
|
||||
br label %while.body
|
||||
|
||||
while.body: ; preds = %for.end, %bb.nph
|
||||
%tmp3 = load i32* %arr ; <i32> [#uses=2]
|
||||
%conv = zext i32 %tmp3 to i64 ; <i64> [#uses=1]
|
||||
%tmp10 = load i32* %arrayidx9 ; <i32> [#uses=1]
|
||||
%conv11 = zext i32 %tmp10 to i64 ; <i64> [#uses=1]
|
||||
%tmp14 = load i32* %arrayidx13 ; <i32> [#uses=3]
|
||||
%conv15 = zext i32 %tmp14 to i64 ; <i64> [#uses=2]
|
||||
%tmp18 = load i32* undef ; <i32> [#uses=2]
|
||||
%conv19 = zext i32 %tmp18 to i64 ; <i64> [#uses=1]
|
||||
%conv23 = zext i32 undef to i64 ; <i64> [#uses=1]
|
||||
%tmp26 = load i32* %arrayidx25 ; <i32> [#uses=1]
|
||||
%conv27 = zext i32 %tmp26 to i64 ; <i64> [#uses=1]
|
||||
%tmp30 = load i32* %arrayidx29 ; <i32> [#uses=2]
|
||||
%conv31 = zext i32 %tmp30 to i64 ; <i64> [#uses=5]
|
||||
%shl72 = shl i64 %conv31, 26 ; <i64> [#uses=1]
|
||||
%shr = lshr i64 %conv31, 6 ; <i64> [#uses=1]
|
||||
%or74 = or i64 %shl72, %shr ; <i64> [#uses=1]
|
||||
%shr85 = lshr i64 %conv31, 25 ; <i64> [#uses=0]
|
||||
%xor87 = xor i64 0, %or74 ; <i64> [#uses=1]
|
||||
%and902706 = and i32 %tmp30, %tmp3 ; <i32> [#uses=1]
|
||||
%and90 = zext i32 %and902706 to i64 ; <i64> [#uses=1]
|
||||
%xor94 = xor i64 0, %and90 ; <i64> [#uses=1]
|
||||
%add = add i64 %conv11, 1508970993 ; <i64> [#uses=1]
|
||||
%add95 = add i64 %add, %xor94 ; <i64> [#uses=1]
|
||||
%add98 = add i64 %add95, %xor87 ; <i64> [#uses=1]
|
||||
%add99 = add i64 %add98, 0 ; <i64> [#uses=2]
|
||||
%xor130 = zext i32 undef to i64 ; <i64> [#uses=1]
|
||||
%add134 = add i64 %add99, %conv27 ; <i64> [#uses=2]
|
||||
%add131 = add i64 %xor130, 0 ; <i64> [#uses=1]
|
||||
%add137 = add i64 %add131, %add99 ; <i64> [#uses=5]
|
||||
%conv1422700 = zext i8 undef to i64 ; <i64> [#uses=1]
|
||||
%shl143 = shl i64 %conv1422700, 24 ; <i64> [#uses=1]
|
||||
%ptrincdec1393051 = load i8* undef ; <i8> [#uses=1]
|
||||
%conv1512699 = zext i8 %ptrincdec1393051 to i64 ; <i64> [#uses=1]
|
||||
%shl152 = shl i64 %conv1512699, 16 ; <i64> [#uses=1]
|
||||
%conv1712697 = zext i8 undef to i64 ; <i64> [#uses=1]
|
||||
%or153 = or i64 %shl152, %shl143 ; <i64> [#uses=1]
|
||||
%or163 = or i64 %or153, %conv1712697 ; <i64> [#uses=1]
|
||||
%or172 = or i64 %or163, 0 ; <i64> [#uses=1]
|
||||
%and203 = and i64 %add134, %conv31 ; <i64> [#uses=1]
|
||||
%xor208 = xor i64 0, %and203 ; <i64> [#uses=1]
|
||||
%add200 = add i64 0, 2453635748 ; <i64> [#uses=1]
|
||||
%add209 = add i64 %add200, %or172 ; <i64> [#uses=1]
|
||||
%add212 = add i64 %add209, %xor208 ; <i64> [#uses=1]
|
||||
%add213 = add i64 %add212, 0 ; <i64> [#uses=2]
|
||||
%shl228 = shl i64 %add137, 10 ; <i64> [#uses=1]
|
||||
%and230 = lshr i64 %add137, 22 ; <i64> [#uses=1]
|
||||
%shr231 = and i64 %and230, 1023 ; <i64> [#uses=1]
|
||||
%or232 = or i64 %shr231, %shl228 ; <i64> [#uses=1]
|
||||
%xor226 = xor i64 0, %or232 ; <i64> [#uses=1]
|
||||
%xor233 = xor i64 %xor226, 0 ; <i64> [#uses=1]
|
||||
%and2362695 = zext i32 undef to i64 ; <i64> [#uses=1]
|
||||
%xor240 = and i64 %add137, %and2362695 ; <i64> [#uses=1]
|
||||
%and2432694 = and i32 %tmp18, %tmp14 ; <i32> [#uses=1]
|
||||
%and243 = zext i32 %and2432694 to i64 ; <i64> [#uses=1]
|
||||
%xor244 = xor i64 %xor240, %and243 ; <i64> [#uses=1]
|
||||
%add248 = add i64 %add213, %conv23 ; <i64> [#uses=2]
|
||||
%add245 = add i64 %xor233, %xor244 ; <i64> [#uses=1]
|
||||
%add251 = add i64 %add245, %add213 ; <i64> [#uses=1]
|
||||
%conv2752691 = zext i8 undef to i64 ; <i64> [#uses=1]
|
||||
%shl276 = shl i64 %conv2752691, 8 ; <i64> [#uses=0]
|
||||
%and317 = and i64 %add248, %add134 ; <i64> [#uses=1]
|
||||
%neg319 = xor i64 %add248, 4294967295 ; <i64> [#uses=1]
|
||||
%and321 = and i64 %neg319, %conv31 ; <i64> [#uses=1]
|
||||
%xor322 = xor i64 %and321, %and317 ; <i64> [#uses=1]
|
||||
%add314 = add i64 %conv, 2870763221 ; <i64> [#uses=1]
|
||||
%add323 = add i64 %add314, 0 ; <i64> [#uses=1]
|
||||
%add326 = add i64 %add323, %xor322 ; <i64> [#uses=1]
|
||||
%add327 = add i64 %add326, 0 ; <i64> [#uses=2]
|
||||
%and3502689 = xor i64 %add137, %conv15 ; <i64> [#uses=1]
|
||||
%xor354 = and i64 %add251, %and3502689 ; <i64> [#uses=1]
|
||||
%and357 = and i64 %add137, %conv15 ; <i64> [#uses=1]
|
||||
%xor358 = xor i64 %xor354, %and357 ; <i64> [#uses=1]
|
||||
%add362 = add i64 %add327, %conv19 ; <i64> [#uses=1]
|
||||
%add359 = add i64 0, %xor358 ; <i64> [#uses=1]
|
||||
%add365 = add i64 %add359, %add327 ; <i64> [#uses=1]
|
||||
%add770 = add i64 %add362, 1426881987 ; <i64> [#uses=1]
|
||||
%add779 = add i64 %add770, 0 ; <i64> [#uses=1]
|
||||
%add782 = add i64 %add779, 0 ; <i64> [#uses=1]
|
||||
%add783 = add i64 %add782, 0 ; <i64> [#uses=2]
|
||||
%add818 = add i64 %add783, %add365 ; <i64> [#uses=1]
|
||||
%add821 = add i64 0, %add783 ; <i64> [#uses=1]
|
||||
store i32 undef, i32* undef
|
||||
%add1046 = add i64 undef, undef ; <i64> [#uses=1]
|
||||
%add1160 = add i64 undef, undef ; <i64> [#uses=1]
|
||||
store i32 0, i32* undef
|
||||
%add1235 = add i64 0, %add818 ; <i64> [#uses=1]
|
||||
%add1238 = add i64 %add1235, 0 ; <i64> [#uses=1]
|
||||
%add1239 = add i64 %add1238, 0 ; <i64> [#uses=1]
|
||||
br label %for.cond
|
||||
|
||||
for.cond: ; preds = %for.body, %while.body
|
||||
%h.0 = phi i64 [ undef, %while.body ], [ %add2035, %for.body ] ; <i64> [#uses=1]
|
||||
%g.0 = phi i64 [ %add1046, %while.body ], [ undef, %for.body ] ; <i64> [#uses=1]
|
||||
%f.0 = phi i64 [ %add1160, %while.body ], [ undef, %for.body ] ; <i64> [#uses=1]
|
||||
%add821.pn = phi i64 [ %add821, %while.body ], [ undef, %for.body ] ; <i64> [#uses=0]
|
||||
%add1239.pn2648 = phi i64 [ %add1239, %while.body ], [ undef, %for.body ] ; <i64> [#uses=0]
|
||||
%d.0 = phi i64 [ undef, %while.body ], [ %add2038, %for.body ] ; <i64> [#uses=2]
|
||||
br i1 undef, label %for.end, label %for.body
|
||||
|
||||
for.body: ; preds = %for.cond
|
||||
%conv1390 = zext i32 undef to i64 ; <i64> [#uses=1]
|
||||
%add1375 = add i64 0, %h.0 ; <i64> [#uses=1]
|
||||
%add1384 = add i64 %add1375, 0 ; <i64> [#uses=1]
|
||||
%add1391 = add i64 %add1384, %conv1390 ; <i64> [#uses=1]
|
||||
%add1392 = add i64 %add1391, 0 ; <i64> [#uses=2]
|
||||
%or1411 = or i64 0, undef ; <i64> [#uses=1]
|
||||
%xor1405 = xor i64 0, %or1411 ; <i64> [#uses=1]
|
||||
%xor1412 = xor i64 %xor1405, 0 ; <i64> [#uses=1]
|
||||
%add1427 = add i64 %add1392, %d.0 ; <i64> [#uses=1]
|
||||
%add1424 = add i64 %xor1412, 0 ; <i64> [#uses=1]
|
||||
%add1430 = add i64 %add1424, %add1392 ; <i64> [#uses=5]
|
||||
%tmp1438 = load i32* undef ; <i32> [#uses=1]
|
||||
%conv1439 = zext i32 %tmp1438 to i64 ; <i64> [#uses=4]
|
||||
%shl1441 = shl i64 %conv1439, 25 ; <i64> [#uses=1]
|
||||
%shr1444 = lshr i64 %conv1439, 7 ; <i64> [#uses=1]
|
||||
%or1445 = or i64 %shl1441, %shr1444 ; <i64> [#uses=1]
|
||||
%shr1450 = lshr i64 %conv1439, 18 ; <i64> [#uses=1]
|
||||
%or1451 = or i64 0, %shr1450 ; <i64> [#uses=1]
|
||||
%shr1454 = lshr i64 %conv1439, 3 ; <i64> [#uses=1]
|
||||
%xor1452 = xor i64 %or1451, %shr1454 ; <i64> [#uses=1]
|
||||
%xor1455 = xor i64 %xor1452, %or1445 ; <i64> [#uses=1]
|
||||
%conv1464 = zext i32 undef to i64 ; <i64> [#uses=4]
|
||||
%shl1466 = shl i64 %conv1464, 15 ; <i64> [#uses=1]
|
||||
%shr1469 = lshr i64 %conv1464, 17 ; <i64> [#uses=1]
|
||||
%or1470 = or i64 %shl1466, %shr1469 ; <i64> [#uses=1]
|
||||
%shr1475 = lshr i64 %conv1464, 19 ; <i64> [#uses=1]
|
||||
%or1476 = or i64 0, %shr1475 ; <i64> [#uses=1]
|
||||
%shr1479 = lshr i64 %conv1464, 10 ; <i64> [#uses=1]
|
||||
%xor1477 = xor i64 %or1476, %shr1479 ; <i64> [#uses=1]
|
||||
%xor1480 = xor i64 %xor1477, %or1470 ; <i64> [#uses=1]
|
||||
%tmp1499 = load i32* null ; <i32> [#uses=1]
|
||||
%conv1500 = zext i32 %tmp1499 to i64 ; <i64> [#uses=1]
|
||||
%add1491 = add i64 %conv1500, 0 ; <i64> [#uses=1]
|
||||
%add1501 = add i64 %add1491, %xor1455 ; <i64> [#uses=1]
|
||||
%add1502 = add i64 %add1501, %xor1480 ; <i64> [#uses=1]
|
||||
%conv1504 = and i64 %add1502, 4294967295 ; <i64> [#uses=1]
|
||||
%tmp1541 = load i32* undef ; <i32> [#uses=1]
|
||||
%conv1542 = zext i32 %tmp1541 to i64 ; <i64> [#uses=1]
|
||||
%add1527 = add i64 %conv1542, %g.0 ; <i64> [#uses=1]
|
||||
%add1536 = add i64 %add1527, 0 ; <i64> [#uses=1]
|
||||
%add1543 = add i64 %add1536, %conv1504 ; <i64> [#uses=1]
|
||||
%add1544 = add i64 %add1543, 0 ; <i64> [#uses=1]
|
||||
%shl1546 = shl i64 %add1430, 30 ; <i64> [#uses=1]
|
||||
%and1548 = lshr i64 %add1430, 2 ; <i64> [#uses=1]
|
||||
%shr1549 = and i64 %and1548, 1073741823 ; <i64> [#uses=1]
|
||||
%or1550 = or i64 %shr1549, %shl1546 ; <i64> [#uses=1]
|
||||
%shl1552 = shl i64 %add1430, 19 ; <i64> [#uses=1]
|
||||
%or1556 = or i64 0, %shl1552 ; <i64> [#uses=1]
|
||||
%shl1559 = shl i64 %add1430, 10 ; <i64> [#uses=1]
|
||||
%or1563 = or i64 0, %shl1559 ; <i64> [#uses=1]
|
||||
%xor1557 = xor i64 %or1556, %or1563 ; <i64> [#uses=1]
|
||||
%xor1564 = xor i64 %xor1557, %or1550 ; <i64> [#uses=1]
|
||||
%add1576 = add i64 %xor1564, 0 ; <i64> [#uses=1]
|
||||
%add1582 = add i64 %add1576, %add1544 ; <i64> [#uses=3]
|
||||
store i32 undef, i32* undef
|
||||
%tmp1693 = load i32* undef ; <i32> [#uses=1]
|
||||
%conv1694 = zext i32 %tmp1693 to i64 ; <i64> [#uses=1]
|
||||
%add1679 = add i64 %conv1694, %f.0 ; <i64> [#uses=1]
|
||||
%add1688 = add i64 %add1679, 0 ; <i64> [#uses=1]
|
||||
%add1695 = add i64 %add1688, 0 ; <i64> [#uses=1]
|
||||
%add1696 = add i64 %add1695, 0 ; <i64> [#uses=1]
|
||||
%shl1698 = shl i64 %add1582, 30 ; <i64> [#uses=0]
|
||||
%shl1704 = shl i64 %add1582, 19 ; <i64> [#uses=0]
|
||||
%add1734 = add i64 0, %add1696 ; <i64> [#uses=1]
|
||||
%add1983 = add i64 0, %add1427 ; <i64> [#uses=1]
|
||||
%add1992 = add i64 %add1983, 0 ; <i64> [#uses=1]
|
||||
%add1999 = add i64 %add1992, 0 ; <i64> [#uses=1]
|
||||
%add2000 = add i64 %add1999, 0 ; <i64> [#uses=2]
|
||||
%and2030 = and i64 %add1734, %add1582 ; <i64> [#uses=1]
|
||||
%xor2031 = xor i64 0, %and2030 ; <i64> [#uses=1]
|
||||
%add2035 = add i64 %add2000, %add1430 ; <i64> [#uses=1]
|
||||
%add2032 = add i64 0, %xor2031 ; <i64> [#uses=1]
|
||||
%add2038 = add i64 %add2032, %add2000 ; <i64> [#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 ; <i32> [#uses=1]
|
||||
%conv2524 = add i32 %tmp14, %d.02641 ; <i32> [#uses=1]
|
||||
store i32 %conv2524, i32* %arrayidx13
|
||||
%exitcond2789 = icmp eq i64 undef, %num ; <i1> [#uses=1]
|
||||
br i1 %exitcond2789, label %while.end, label %while.body
|
||||
|
||||
while.end: ; preds = %for.end, %entry
|
||||
ret void
|
||||
}
|
|
@ -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 ; <i8*> [#uses=1]
|
||||
br i1 undef, label %foreachbody, label %foreachend
|
||||
|
||||
foreachbody: ; preds = %entry
|
||||
%tmp4 = getelementptr i8* %tmp, i32 undef ; <i8*> [#uses=1]
|
||||
%tmp5 = load i8* %tmp4 ; <i8> [#uses=0]
|
||||
unreachable
|
||||
|
||||
foreachend: ; preds = %entry
|
||||
ret i32 0
|
||||
}
|
||||
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue