blob: 914a85df408064ae51714e2c8c1a8452ff22d97e [file] [log] [blame]
Index: include/llvm/Target/TargetOptions.h
===================================================================
--- include/llvm/Target/TargetOptions.h (revision 46321)
+++ include/llvm/Target/TargetOptions.h (working copy)
@@ -74,10 +74,15 @@
/// be emitted.
extern bool ExceptionHandling;
+ /// SizedMemoryCode - This flags indicates that memory for code is allocated by
+ /// an external allocator which requires the size to allocate
+ extern bool SizedMemoryCode;
+
/// PerformTailCallOpt - This flag is enabled when -tailcallopt is specified
/// on the commandline. When the flag is on, the target will perform tail call
/// optimization (pop the caller's stack) providing it supports it.
extern bool PerformTailCallOpt;
+
} // End llvm namespace
#endif
Index: include/llvm/ExecutionEngine/ExecutionEngine.h
===================================================================
--- include/llvm/ExecutionEngine/ExecutionEngine.h (revision 46321)
+++ include/llvm/ExecutionEngine/ExecutionEngine.h (working copy)
@@ -85,6 +85,11 @@
/// pointer is invoked to create it. If this returns null, the JIT will abort.
void* (*LazyFunctionCreator)(const std::string &);
+ /// ExceptionTableRegister - If Exception Handling is set, the JIT will
+ /// register dwarf tables with this function
+ typedef void (*EERegisterFn)(void*);
+ static EERegisterFn ExceptionTableRegister;
+
public:
/// lock - This lock is protects the ExecutionEngine, JIT, JITResolver and
/// JITEmitter classes. It must be held while changing the internal state of
@@ -247,6 +252,14 @@
LazyFunctionCreator = P;
}
+ static void InstallExceptionTableRegister(void (*F)(void*)) {
+ ExceptionTableRegister = F;
+ }
+
+ static void RegisterTable(void* res) {
+ ExceptionTableRegister(res);
+ }
+
protected:
explicit ExecutionEngine(ModuleProvider *P);
Index: include/llvm/ExecutionEngine/JITMemoryManager.h
===================================================================
--- include/llvm/ExecutionEngine/JITMemoryManager.h (revision 46321)
+++ include/llvm/ExecutionEngine/JITMemoryManager.h (working copy)
@@ -89,6 +89,17 @@
/// deallocateMemForFunction - Free JIT memory for the specified function.
/// This is never called when the JIT is currently emitting a function.
virtual void deallocateMemForFunction(const Function *F) = 0;
+
+ /// startExceptionTable - When we finished JITing the function, if exception
+ /// handling is set, we emit the exception table.
+ virtual unsigned char* startExceptionTable(const Function* F,
+ uintptr_t &ActualSize) = 0;
+
+ /// endExceptionTable - This method is called when the JIT is done emitting
+ /// the exception table.
+ virtual void endExceptionTable(const Function *F, unsigned char *TableStart,
+ unsigned char *TableEnd,
+ unsigned char* FrameRegister) = 0;
};
} // end namespace llvm.
Index: include/llvm/CodeGen/SizeEmitter.h
===================================================================
--- include/llvm/CodeGen/SizeEmitter.h (revision 0)
+++ include/llvm/CodeGen/SizeEmitter.h (revision 0)
@@ -0,0 +1,116 @@
+//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an abstract interface that is used by the machine code
+// emission framework to output the code. This allows machine code emission to
+// be separated from concerns such as resolution of call targets, and where the
+// machine code will be written (memory or disk, f.e.).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CODEGEN_SIZEEMITTER_H
+#define LLVM_CODEGEN_SIZEEMITTER_H
+
+#include "llvm/CodeGen/MachineCodeEmitter.h"
+#include "llvm/CodeGen/MachineFunction.h"
+
+namespace llvm {
+ /// SizeEmitter - The JIT implementation of the MachineCodeEmitter, which is
+ /// used to output functions to memory for execution.
+class SizeEmitter : public MachineCodeEmitter {
+ MachineFunction * Fn;
+ void* ConstantPoolBase;
+ void* JumpTableBase;
+ MachineConstantPool *ConstantPool;
+ MachineJumpTableInfo *JumpTable;
+ std::vector<intptr_t> LabelLocations;
+ MachineCodeEmitter* MCE;
+
+public:
+ SizeEmitter(MachineCodeEmitter* mce) {
+ CurBufferPtr = 0;
+ BufferBegin = 0;
+ BufferEnd = (unsigned char*)-1;
+ MCE = mce;
+ }
+
+ SizeEmitter(std::vector<intptr_t> locations) {
+ LabelLocations = locations;
+ CurBufferPtr = 0;
+ BufferBegin = 0;
+ BufferEnd = (unsigned char*)-1;
+ }
+
+ void initConstantPool(MachineConstantPool *MCP);
+
+ void initJumpTableInfo(MachineJumpTableInfo *MJTI);
+
+
+ virtual void startFunction(MachineFunction &F) {
+ CurBufferPtr = 0;
+ Fn = &F;
+
+ // Ensure the constant pool/jump table info is at least 4-byte aligned.
+ emitAlignment(16);
+
+ initConstantPool(F.getConstantPool());
+ initJumpTableInfo(F.getJumpTableInfo());
+
+ ConstantPoolBase = (void*)(((unsigned) ConstantPoolBase) + CurBufferPtr);
+ JumpTableBase = (void*)(((unsigned) JumpTableBase) + CurBufferPtr);
+ }
+
+ virtual bool finishFunction(MachineFunction &F) {
+ MCE->setCurrentPtr(CurBufferPtr);
+ return false;
+ }
+ virtual void startFunctionStub(unsigned StubSize, unsigned Alignment) {}
+ virtual void *finishFunctionStub(const Function *F) { return 0; }
+ virtual void addRelocation(const llvm::MachineRelocation&) { }
+ virtual void emitByte(unsigned char B) {
+ CurBufferPtr++;
+ }
+ virtual void emitWordLE(unsigned W) {
+ CurBufferPtr+=4;
+ }
+ virtual void emitWordBE(unsigned W) {
+ CurBufferPtr+=4;
+ }
+ virtual void emitInt32(int Value) {
+ CurBufferPtr += 4;
+ }
+ virtual void emitInt64(uint64_t Value) {
+ CurBufferPtr += 8;
+ }
+ virtual void emitAt(uintptr_t *Addr, uintptr_t Value) {
+ }
+
+
+
+ virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) {}
+ virtual intptr_t getConstantPoolEntryAddress(unsigned ConstantNum) const;
+
+ virtual intptr_t getJumpTableEntryAddress(unsigned Index) const;
+
+ virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const {
+ assert(0 && "Should not be in getMachineBasicBlockAddress of SizeEmitter");
+ }
+
+ virtual void EmitLabel(uint64_t) {}
+ virtual intptr_t getLabelAddress(uint64_t LabelID) const {
+ assert(LabelLocations.size() > (unsigned)LabelID &&
+ LabelLocations[LabelID] && "Label not emitted!");
+ return LabelLocations[LabelID];
+ }
+ virtual void setModuleInfo(llvm::MachineModuleInfo*) {}
+};
+
+} // end llvm namespace
+
+#endif
Index: include/llvm/CodeGen/MachineCodeEmitter.h
===================================================================
--- include/llvm/CodeGen/MachineCodeEmitter.h (revision 46321)
+++ include/llvm/CodeGen/MachineCodeEmitter.h (working copy)
@@ -18,6 +18,7 @@
#define LLVM_CODEGEN_MACHINECODEEMITTER_H
#include "llvm/Support/DataTypes.h"
+#include <string>
#include <vector>
namespace llvm {
@@ -26,6 +27,7 @@
class MachineConstantPool;
class MachineJumpTableInfo;
class MachineFunction;
+class MachineModuleInfo;
class MachineRelocation;
class Value;
class GlobalValue;
@@ -91,7 +93,7 @@
/// emitByte - This callback is invoked when a byte needs to be written to the
/// output stream.
///
- void emitByte(unsigned char B) {
+ virtual void emitByte(unsigned char B) {
if (CurBufferPtr != BufferEnd)
*CurBufferPtr++ = B;
}
@@ -99,7 +101,7 @@
/// emitWordLE - This callback is invoked when a 32-bit word needs to be
/// written to the output stream in little-endian format.
///
- void emitWordLE(unsigned W) {
+ virtual void emitWordLE(unsigned W) {
if (CurBufferPtr+4 <= BufferEnd) {
*CurBufferPtr++ = (unsigned char)(W >> 0);
*CurBufferPtr++ = (unsigned char)(W >> 8);
@@ -113,7 +115,7 @@
/// emitWordBE - This callback is invoked when a 32-bit word needs to be
/// written to the output stream in big-endian format.
///
- void emitWordBE(unsigned W) {
+ virtual void emitWordBE(unsigned W) {
if (CurBufferPtr+4 <= BufferEnd) {
*CurBufferPtr++ = (unsigned char)(W >> 24);
*CurBufferPtr++ = (unsigned char)(W >> 16);
@@ -136,6 +138,64 @@
CurBufferPtr = BufferEnd;
}
+ /// EmitULEB128Bytes - This callback is invoked when a ULEB128 needs to be
+ /// written to the output stream.
+ void emitULEB128Bytes(unsigned Value) {
+ do {
+ unsigned char Byte = Value & 0x7f;
+ Value >>= 7;
+ if (Value) Byte |= 0x80;
+ emitByte(Byte);
+ } while (Value);
+ }
+
+ /// emitSLEB128Bytes - This callback is invoked when a SLEB128 needs to be
+ /// written to the output stream.
+ void emitSLEB128Bytes(int Value) {
+ int Sign = Value >> (8 * sizeof(Value) - 1);
+ bool IsMore;
+
+ do {
+ unsigned char Byte = Value & 0x7f;
+ Value >>= 7;
+ IsMore = Value != Sign || ((Byte ^ Sign) & 0x40) != 0;
+ if (IsMore) Byte |= 0x80;
+ emitByte(Byte);
+ } while (IsMore);
+ }
+
+ void emitString(const std::string &String) {
+ for (unsigned i = 0, N = String.size(); i < N; ++i) {
+ unsigned char C = String[i];
+ emitByte(C);
+ }
+ emitByte(0);
+ }
+
+ virtual void emitInt32(int Value) {
+ if (CurBufferPtr+4 <= BufferEnd) {
+ *((uint32_t*)CurBufferPtr) = Value;
+ CurBufferPtr += 4;
+ } else {
+ CurBufferPtr = BufferEnd;
+ }
+ }
+
+ /// EmitInt64 - Emit a long long directive and value.
+ virtual void emitInt64(uint64_t Value) {
+ if (CurBufferPtr+8 <= BufferEnd) {
+ *((uint64_t*)CurBufferPtr) = Value;
+ CurBufferPtr += 8;
+ } else {
+ CurBufferPtr = BufferEnd;
+ }
+ }
+
+ virtual void emitAt(uintptr_t *Addr, uintptr_t Value) {
+ (*Addr) = Value;
+ }
+
+
/// allocateSpace - Allocate a block of space in the current output buffer,
/// returning null (and setting conditions to indicate buffer overflow) on
/// failure. Alignment is the alignment in bytes of the buffer desired.
@@ -159,6 +219,9 @@
/// start of the block is, and can implement getMachineBasicBlockAddress.
virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0;
+ virtual void EmitLabel(uint64_t LabelID) = 0;
+
+
/// getCurrentPCValue - This returns the address that the next emitted byte
/// will be output to.
///
@@ -194,6 +257,17 @@
/// emitted.
///
virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0;
+
+ /// getLabelAddress - Return the address of the specified LabelID, only usable
+ /// after the LabelID has been emitted.
+ ///
+ virtual intptr_t getLabelAddress(uint64_t LabelID) const = 0;
+
+ virtual void setModuleInfo(MachineModuleInfo* Info) = 0;
+
+ void setCurrentPtr(unsigned char* Ptr) {
+ CurBufferPtr = Ptr;
+ }
};
} // End llvm namespace
Index: lib/CodeGen/LLVMTargetMachine.cpp
===================================================================
--- lib/CodeGen/LLVMTargetMachine.cpp (revision 46321)
+++ lib/CodeGen/LLVMTargetMachine.cpp (working copy)
@@ -17,6 +17,7 @@
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Analysis/LoopPass.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/SizeEmitter.h"
#include "llvm/CodeGen/Collector.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
@@ -187,7 +188,8 @@
PM.add(createGCLoweringPass());
// FIXME: Implement the invoke/unwind instructions!
- PM.add(createLowerInvokePass(getTargetLowering()));
+ if (!ExceptionHandling)
+ PM.add(createLowerInvokePass(getTargetLowering()));
// Make sure that no unreachable blocks are instruction selected.
PM.add(createUnreachableBlockEliminationPass());
@@ -251,7 +253,13 @@
if (addPreEmitPass(PM, Fast) && PrintMachineCode)
PM.add(createMachineFunctionPrinterPass(cerr));
+
+ if (SizedMemoryCode) {
+ SizeEmitter * SE = new SizeEmitter(&MCE);
+ addSimpleCodeEmitter(PM, Fast, false, *SE);
+ }
+
addCodeEmitter(PM, Fast, PrintEmittedAsm, MCE);
PM.add(createCollectorMetadataDeleter());
Index: lib/CodeGen/ELFWriter.cpp
===================================================================
--- lib/CodeGen/ELFWriter.cpp (revision 46321)
+++ lib/CodeGen/ELFWriter.cpp (working copy)
@@ -98,6 +98,18 @@
return 0;
}
+ virtual intptr_t getLabelAddress(uint64_t Label) const {
+ assert(0 && "JT not implementated yet!");
+ return 0;
+ }
+
+ virtual void EmitLabel(uint64_t LabelID) {
+ }
+
+
+ virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { }
+
+
/// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
void startFunctionStub(unsigned StubSize, unsigned Alignment = 1) {
assert(0 && "JIT specific function called!");
Index: lib/CodeGen/SizeEmitter.cpp
===================================================================
--- lib/CodeGen/SizeEmitter.cpp (revision 0)
+++ lib/CodeGen/SizeEmitter.cpp (revision 0)
@@ -0,0 +1,77 @@
+#include "llvm/CodeGen/SizeEmitter.h"
+#include "llvm/Constant.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/Type.h"
+#include "llvm/CodeGen/MachineCodeEmitter.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineConstantPool.h"
+#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineRelocation.h"
+#include "llvm/ExecutionEngine/GenericValue.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetJITInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/MutexGuard.h"
+#include "llvm/System/Disassembler.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/System/Memory.h"
+#include <algorithm>
+using namespace llvm;
+
+
+void SizeEmitter::initConstantPool(MachineConstantPool *MCP) {
+ const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
+ if (Constants.empty()) return;
+
+ MachineConstantPoolEntry CPE = Constants.back();
+ unsigned Size = CPE.Offset;
+ const Type *Ty = CPE.isMachineConstantPoolEntry()
+ ? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
+ Size += Fn->getTarget().getTargetData()->getABITypeSize(Ty);
+ ConstantPoolBase = allocateSpace(Size, 1 << MCP->getConstantPoolAlignment());
+ ConstantPool = MCP;
+}
+
+void SizeEmitter::initJumpTableInfo(MachineJumpTableInfo *MJTI) {
+ const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
+ if (JT.empty()) return;
+
+ unsigned NumEntries = 0;
+ for (unsigned i = 0, e = JT.size(); i != e; ++i)
+ NumEntries += JT[i].MBBs.size();
+
+ unsigned EntrySize = MJTI->getEntrySize();
+
+ // Just allocate space for all the jump tables now. We will fix up the actual
+ // MBB entries in the tables after we emit the code for each block, since then
+ // we will know the final locations of the MBBs in memory.
+ JumpTable = MJTI;
+ JumpTableBase = allocateSpace(NumEntries * EntrySize, MJTI->getAlignment());
+}
+
+intptr_t SizeEmitter::getConstantPoolEntryAddress(unsigned ConstantNum) const {
+ assert(ConstantNum < ConstantPool->getConstants().size() &&
+ "Invalid ConstantPoolIndex!");
+ return (intptr_t)ConstantPoolBase +
+ ConstantPool->getConstants()[ConstantNum].Offset;
+}
+
+intptr_t SizeEmitter::getJumpTableEntryAddress(unsigned Index) const {
+ const std::vector<MachineJumpTableEntry> &JT = JumpTable->getJumpTables();
+ assert(Index < JT.size() && "Invalid jump table index!");
+
+ unsigned Offset = 0;
+ unsigned EntrySize = JumpTable->getEntrySize();
+
+ for (unsigned i = 0; i < Index; ++i)
+ Offset += JT[i].MBBs.size();
+
+ Offset *= EntrySize;
+
+ return (intptr_t)((char *)JumpTableBase + Offset);
+}
+
Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
===================================================================
--- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (revision 46321)
+++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (working copy)
@@ -148,6 +148,7 @@
SelectionDAG *DAG,
MachineBasicBlock *BB) {
TargetLowering &TLI = IS->getTargetLowering();
+ return createBURRListDAGScheduler(IS, DAG, BB);
if (TLI.getSchedulingPreference() == TargetLowering::SchedulingForLatency) {
return createTDListDAGScheduler(IS, DAG, BB);
Index: lib/CodeGen/MachOWriter.cpp
===================================================================
--- lib/CodeGen/MachOWriter.cpp (revision 46321)
+++ lib/CodeGen/MachOWriter.cpp (working copy)
@@ -125,6 +125,20 @@
return MBBLocations[MBB->getNumber()];
}
+ virtual intptr_t getLabelAddress(uint64_t Label) const {
+ assert(0 && "Implement me");
+ abort();
+ return 0;
+ }
+
+ virtual void EmitLabel(uint64_t LabelID) {
+ assert(0 && "Implement me");
+ abort();
+ }
+
+
+ virtual void setModuleInfo(llvm::MachineModuleInfo* MMI) { }
+
/// JIT SPECIFIC FUNCTIONS - DO NOT IMPLEMENT THESE HERE!
virtual void startFunctionStub(unsigned StubSize, unsigned Alignment = 1) {
assert(0 && "JIT specific function called!");
Index: lib/Target/PowerPC/PPCCodeEmitter.cpp
===================================================================
--- lib/Target/PowerPC/PPCCodeEmitter.cpp (revision 46321)
+++ lib/Target/PowerPC/PPCCodeEmitter.cpp (working copy)
@@ -20,6 +20,7 @@
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Compiler.h"
@@ -38,6 +39,11 @@
/// getMachineOpValue - evaluates the MachineOperand of a given MachineInstr
///
int getMachineOpValue(MachineInstr &MI, MachineOperand &MO);
+
+ void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<MachineModuleInfo>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
public:
static char ID;
@@ -82,6 +88,8 @@
assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
MF.getTarget().getRelocationModel() != Reloc::Static) &&
"JIT relocation model must be set to static or default!");
+
+ MCE.setModuleInfo(&getAnalysis<MachineModuleInfo>());
do {
MovePCtoLROffset = 0;
MCE.startFunction(MF);
@@ -101,6 +109,9 @@
default:
MCE.emitWordBE(getBinaryCodeForInstr(*I));
break;
+ case TargetInstrInfo::LABEL:
+ MCE.EmitLabel(MI.getOperand(0).getImm());
+ break;
case PPC::IMPLICIT_DEF_GPRC:
case PPC::IMPLICIT_DEF_G8RC:
case PPC::IMPLICIT_DEF_F8:
Index: lib/Target/PowerPC/PPCInstrInfo.td
===================================================================
--- lib/Target/PowerPC/PPCInstrInfo.td (revision 46321)
+++ lib/Target/PowerPC/PPCInstrInfo.td (working copy)
@@ -1179,6 +1179,8 @@
(BL_ELF texternalsym:$dst)>;
// Hi and Lo for Darwin Global Addresses.
+def : Pat<(PPChi texternalsym:$in, 0), (LIS texternalsym:$in)>;
+def : Pat<(PPClo texternalsym:$in, 0), (LI texternalsym:$in)>;
def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>;
def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>;
def : Pat<(PPChi tconstpool:$in, 0), (LIS tconstpool:$in)>;
Index: lib/Target/PowerPC/PPCJITInfo.cpp
===================================================================
--- lib/Target/PowerPC/PPCJITInfo.cpp (revision 46321)
+++ lib/Target/PowerPC/PPCJITInfo.cpp (working copy)
@@ -13,11 +13,15 @@
#define DEBUG_TYPE "jit"
#include "PPCJITInfo.h"
+#include "PPCRegisterInfo.h"
#include "PPCRelocations.h"
#include "PPCTargetMachine.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/Config/alloca.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Target/TargetOptions.h"
#include <set>
using namespace llvm;
@@ -52,24 +56,38 @@
if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range?
AtI[0] = BUILD_B(Offset, isCall); // b/bl target
} else if (!is64Bit) {
- AtI[0] = BUILD_LIS(12, To >> 16); // lis r12, hi16(address)
+ AtI[0] = BUILD_B(0, false); // thread safety
AtI[1] = BUILD_ORI(12, 12, To); // ori r12, r12, lo16(address)
AtI[2] = BUILD_MTCTR(12); // mtctr r12
AtI[3] = BUILD_BCTR(isCall); // bctr/bctrl
+ AtI[0] = BUILD_LIS(12, To >> 16); // lis r12, hi16(address)
} else {
- AtI[0] = BUILD_LIS(12, To >> 48); // lis r12, hi16(address)
+ AtI[0] = BUILD_B(0, false); // thread safety
AtI[1] = BUILD_ORI(12, 12, To >> 32); // ori r12, r12, lo16(address)
AtI[2] = BUILD_SLDI(12, 12, 32); // sldi r12, r12, 32
AtI[3] = BUILD_ORIS(12, 12, To >> 16); // oris r12, r12, hi16(address)
AtI[4] = BUILD_ORI(12, 12, To); // ori r12, r12, lo16(address)
AtI[5] = BUILD_MTCTR(12); // mtctr r12
AtI[6] = BUILD_BCTR(isCall); // bctr/bctrl
+ AtI[0] = BUILD_LIS(12, To >> 48); // lis r12, hi16(address)
}
}
extern "C" void PPC32CompilationCallback();
extern "C" void PPC64CompilationCallback();
+
+// This is needed for old/broken assemblers (for example, gas on
+// Darwin is pretty old and doesn't support these directives)
+#if defined(__APPLE__)
+# define CFI(x)
+#else
+// FIXME: Disable this until we really want to use it. Also, we will
+// need to add some workarounds for compilers, which support
+// only subset of these directives.
+# define CFI(x) x
+#endif
+
#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
!defined(__ppc64__)
// CompilationCallback stub - We can't use a C function with inline assembly in
@@ -155,19 +173,29 @@
// FIXME Layout
// 8 double registers - 64 bytes
// 8 int registers - 32 bytes
+ CFI(".cfi_startproc\n")
+ "stwu 1, -104(1)\n"
+ CFI(".cfi_adjust_cfa_offset 104\n")
"mflr 0\n"
- "stw 0, 4(1)\n"
- "stwu 1, -104(1)\n"
+ "stw 0, 108(1)\n"
+ CFI(".cfi_offset lr, 4\n")
// Save all int arg registers
- "stw 10, 100(1)\n" "stw 9, 96(1)\n"
- "stw 8, 92(1)\n" "stw 7, 88(1)\n"
- "stw 6, 84(1)\n" "stw 5, 80(1)\n"
- "stw 4, 76(1)\n" "stw 3, 72(1)\n"
+ "stw 10, 100(1)\n"
+ "stw 9, 96(1)\n"
+ "stw 8, 92(1)\n"
+ "stw 7, 88(1)\n"
+ "stw 6, 84(1)\n"
+ "stw 5, 80(1)\n"
+ "stw 4, 76(1)\n"
+ "stw 3, 72(1)\n"
// Save all call-clobbered FP regs.
"stfd 8, 64(1)\n"
- "stfd 7, 56(1)\n" "stfd 6, 48(1)\n"
- "stfd 5, 40(1)\n" "stfd 4, 32(1)\n"
- "stfd 3, 24(1)\n" "stfd 2, 16(1)\n"
+ "stfd 7, 56(1)\n"
+ "stfd 6, 48(1)\n"
+ "stfd 5, 40(1)\n"
+ "stfd 4, 32(1)\n"
+ "stfd 3, 24(1)\n"
+ "stfd 2, 16(1)\n"
"stfd 1, 8(1)\n"
// Arguments to Compilation Callback:
// r3 - our lr (address of the call instruction in stub plus 4)
@@ -180,21 +208,29 @@
"bl PPCCompilationCallbackC\n"
"mtctr 3\n"
// Restore all int arg registers
- "lwz 10, 100(1)\n" "lwz 9, 96(1)\n"
- "lwz 8, 92(1)\n" "lwz 7, 88(1)\n"
- "lwz 6, 84(1)\n" "lwz 5, 80(1)\n"
- "lwz 4, 76(1)\n" "lwz 3, 72(1)\n"
+ "lwz 10, 100(1)\n"
+ "lwz 9, 96(1)\n"
+ "lwz 8, 92(1)\n"
+ "lwz 7, 88(1)\n"
+ "lwz 6, 84(1)\n"
+ "lwz 5, 80(1)\n"
+ "lwz 4, 76(1)\n"
+ "lwz 3, 72(1)\n"
// Restore all FP arg registers
"lfd 8, 64(1)\n"
- "lfd 7, 56(1)\n" "lfd 6, 48(1)\n"
- "lfd 5, 40(1)\n" "lfd 4, 32(1)\n"
- "lfd 3, 24(1)\n" "lfd 2, 16(1)\n"
+ "lfd 7, 56(1)\n"
+ "lfd 6, 48(1)\n"
+ "lfd 5, 40(1)\n"
+ "lfd 4, 32(1)\n"
+ "lfd 3, 24(1)\n"
+ "lfd 2, 16(1)\n"
"lfd 1, 8(1)\n"
// Pop 3 frames off the stack and branch to target
"lwz 1, 104(1)\n"
"lwz 0, 4(1)\n"
"mtlr 0\n"
"bctr\n"
+ CFI(".cfi_endproc\n")
);
#else
void PPC32CompilationCallback() {
@@ -324,6 +360,31 @@
return is64Bit ? PPC64CompilationCallback : PPC32CompilationCallback;
}
+static const char* GetCommonFrame32() {
+ /*
+ // Size of common frame
+ MCE.emitWordBE(16);
+ // Common frame
+ MCE.emitWordBE(0);
+ MCE.emitByte(1);
+ MCE.emitByte('z');
+ MCE.emitByte('R');
+ MCE.emitByte(0);
+ MCE.emitByte(1);
+ MCE.emitByte(-4 & 0x7f);
+ MCE.emitByte(0x41);
+ MCE.emitByte(1);
+ MCE.emitByte(16);
+ MCE.emitByte(0xc);
+ MCE.emitByte(1);
+ MCE.emitByte(0);*/
+ static const char CF[] = {
+ 0, 0, 0, 16, 0, 0, 0, 0, 1, 'z', 'R', 0, 1, -4 & 0x7f,
+ 0x41, 1, 16, 0xc, 1, 0
+ };
+ return CF;
+}
+
void *PPCJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
// If this is just a call to an external function, emit a branch instead of a
// call. The code is the same except for one bit of the last instruction.
@@ -341,20 +402,25 @@
EmitBranchToAt(Addr, (intptr_t)Fn, false, is64Bit);
return MCE.finishFunctionStub(0);
}
-
- MCE.startFunctionStub(10*4);
+
+ if (ExceptionHandling && !is64Bit) {
+ MCE.startFunctionStub(10*4 + 44);
+ } else {
+ MCE.startFunctionStub(10*4);
+ }
+ intptr_t BeginAddr = (intptr_t)MCE.getCurrentPCValue();
if (is64Bit) {
+ MCE.emitWordBE(0x7d6802a6); // mflr r11
+ MCE.emitWordBE(0xf9610010); // std r11, 16(r1)
MCE.emitWordBE(0xf821ffb1); // stdu r1,-80(r1)
+ } else if (TM.getSubtargetImpl()->isMachoABI()){
MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0xf9610060); // std r11, 96(r1)
- } else if (TM.getSubtargetImpl()->isMachoABI()){
+ MCE.emitWordBE(0x91610008); // stw r11, 8(r1)
MCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1)
+ } else {
MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0x91610028); // stw r11, 40(r1)
- } else {
+ MCE.emitWordBE(0x91610004); // stw r11, 4(r1)
MCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1)
- MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0x91610024); // stw r11, 36(r1)
}
intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
MCE.emitWordBE(0);
@@ -365,6 +431,41 @@
MCE.emitWordBE(0);
MCE.emitWordBE(0);
EmitBranchToAt(Addr, (intptr_t)Fn, true, is64Bit);
+ intptr_t EndAddr = (intptr_t)MCE.getCurrentPCValue();
+
+ if (ExceptionHandling && !is64Bit) {
+ // Size of Eh section
+ MCE.emitWordBE(32);
+ // Eh section
+ MCE.emitWordBE(MCE.getCurrentPCValue() - (intptr_t)GetCommonFrame32());
+ MCE.emitWordBE(BeginAddr - MCE.getCurrentPCValue());
+ MCE.emitWordBE(EndAddr - BeginAddr);
+ MCE.emitByte(0);
+ MCE.emitByte(dwarf::DW_CFA_advance_loc4);
+ MCE.emitWordBE(8);
+ MCE.emitByte(dwarf::DW_CFA_def_cfa_offset);
+ MCE.emitByte(32);
+ MCE.emitByte(dwarf::DW_CFA_offset_extended_sf);
+ MCE.emitByte(TM.getRegisterInfo()->getDwarfRegNum(PPC::LR, true));
+ if (TM.getSubtargetImpl()->isMachoABI()){
+ MCE.emitByte(-2 & 0x7f);
+ } else {
+ MCE.emitByte(-1 & 0x7f);
+ }
+ MCE.emitByte(dwarf::DW_CFA_advance_loc4);
+ MCE.emitWordBE(4);
+ MCE.emitByte(dwarf::DW_CFA_def_cfa_register);
+ MCE.emitByte(1);
+ // Alignment
+ MCE.emitByte(0);
+ MCE.emitByte(0);
+
+ // Two zero for the unwind runtime
+ MCE.emitWordBE(0);
+ MCE.emitWordBE(0);
+
+ ExecutionEngine::RegisterTable((void*)EndAddr);
+ }
return MCE.finishFunctionStub(0);
}
Index: lib/Target/PowerPC/PPCISelLowering.cpp
===================================================================
--- lib/Target/PowerPC/PPCISelLowering.cpp (revision 46321)
+++ lib/Target/PowerPC/PPCISelLowering.cpp (working copy)
@@ -178,10 +178,12 @@
// We want to legalize GlobalAddress and ConstantPool nodes into the
// appropriate instructions to materialize the address.
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
+ setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
+ setOperationAction(ISD::ExternalSymbol , MVT::i64 , Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
@@ -1108,6 +1110,37 @@
return DAG.getLoad(PtrVT, DAG.getEntryNode(), Lo, NULL, 0);
}
+static SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
+ MVT::ValueType PtrVT = Op.getValueType();
+ ExternalSymbolSDNode *GSDB = dyn_cast<ExternalSymbolSDNode>(Op);
+ SDOperand GA = DAG.getTargetExternalSymbol(GSDB->getSymbol(), PtrVT);
+ SDOperand Zero = DAG.getConstant(0, PtrVT);
+
+ const TargetMachine &TM = DAG.getTarget();
+
+ SDOperand Hi = DAG.getNode(PPCISD::Hi, PtrVT, GA, Zero);
+ SDOperand Lo = DAG.getNode(PPCISD::Lo, PtrVT, GA, Zero);
+
+ // If this is a non-darwin platform, we don't support non-static relo models
+ // yet.
+ if (TM.getRelocationModel() == Reloc::Static ||
+ !TM.getSubtarget<PPCSubtarget>().isDarwin()) {
+ // Generate non-pic code that has direct accesses to globals.
+ // The address of the global is just (hi(&g)+lo(&g)).
+ return DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
+ }
+
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ // With PIC, the first instruction is actually "GR+hi(&G)".
+ Hi = DAG.getNode(ISD::ADD, PtrVT,
+ DAG.getNode(PPCISD::GlobalBaseReg, PtrVT), Hi);
+ }
+
+ Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
+
+ return Lo;
+}
+
static SDOperand LowerSETCC(SDOperand Op, SelectionDAG &DAG) {
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
@@ -1777,11 +1810,11 @@
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
// node so that legalize doesn't hack it.
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
- else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
- else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
+ //if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+ // Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
+ //if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
+ // Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
+ if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
// If this is an absolute destination address, use the munged value.
Callee = SDOperand(Dest, 0);
else {
@@ -3064,6 +3097,7 @@
default: assert(0 && "Wasn't expecting to be able to lower this!");
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
+ case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
Index: lib/Target/X86/X86CodeEmitter.cpp
===================================================================
--- lib/Target/X86/X86CodeEmitter.cpp (revision 46321)
+++ lib/Target/X86/X86CodeEmitter.cpp (working copy)
@@ -23,6 +23,7 @@
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineInstr.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/Function.h"
#include "llvm/ADT/Statistic.h"
@@ -61,6 +62,11 @@
void emitInstruction(const MachineInstr &MI,
const TargetInstrDesc *Desc);
+
+ void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<MachineModuleInfo>();
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
private:
void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
@@ -104,10 +110,13 @@
assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
MF.getTarget().getRelocationModel() != Reloc::Static) &&
"JIT relocation model must be set to static or default!");
+
+ MCE.setModuleInfo(&getAnalysis<MachineModuleInfo>());
+
II = ((X86TargetMachine&)TM).getInstrInfo();
TD = ((X86TargetMachine&)TM).getTargetData();
Is64BitMode = TM.getSubtarget<X86Subtarget>().is64Bit();
-
+
do {
MCE.startFunction(MF);
for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
@@ -596,13 +605,13 @@
// Remember the current PC offset, this is the PIC relocation
// base address.
switch (Opcode) {
-#ifndef NDEBUG
default:
assert(0 && "psuedo instructions should be removed before code emission");
case TargetInstrInfo::INLINEASM:
assert(0 && "JIT does not support inline asm!\n");
case TargetInstrInfo::LABEL:
- assert(0 && "JIT does not support meta labels!\n");
+ MCE.EmitLabel(MI.getOperand(0).getImm());
+ break;
case X86::IMPLICIT_DEF_GR8:
case X86::IMPLICIT_DEF_GR16:
case X86::IMPLICIT_DEF_GR32:
@@ -613,7 +622,6 @@
case X86::IMPLICIT_DEF_VR128:
case X86::FP_REG_KILL:
break;
-#endif
case X86::MOVPC32r: {
// This emits the "call" portion of this pseudo instruction.
MCE.emitByte(BaseOpcode);
@@ -627,7 +635,6 @@
}
CurOp = NumOps;
break;
-
case X86II::RawFrm:
MCE.emitByte(BaseOpcode);
Index: lib/Target/TargetMachine.cpp
===================================================================
--- lib/Target/TargetMachine.cpp (revision 46321)
+++ lib/Target/TargetMachine.cpp (working copy)
@@ -31,6 +31,7 @@
bool UseSoftFloat;
bool NoZerosInBSS;
bool ExceptionHandling;
+ bool SizedMemoryCode;
Reloc::Model RelocationModel;
CodeModel::Model CMModel;
bool PerformTailCallOpt;
Index: lib/ExecutionEngine/JIT/JITEmitter.cpp
===================================================================
--- lib/ExecutionEngine/JIT/JITEmitter.cpp (revision 46321)
+++ lib/ExecutionEngine/JIT/JITEmitter.cpp (working copy)
@@ -14,18 +14,23 @@
#define DEBUG_TYPE "jit"
#include "JIT.h"
+#include "JITDwarfEmitter.h"
#include "llvm/Constant.h"
#include "llvm/Module.h"
#include "llvm/Type.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRelocation.h"
+#include "llvm/CodeGen/SizeEmitter.h"
#include "llvm/ExecutionEngine/JITMemoryManager.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetJITInfo.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/MutexGuard.h"
#include "llvm/System/Disassembler.h"
@@ -344,6 +349,11 @@
/// Resolver - This contains info about the currently resolved functions.
JITResolver Resolver;
+
+ JITDwarfEmitter *DE;
+ std::vector<intptr_t> LabelLocations;
+ MachineModuleInfo* MMI;
+
public:
JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit) {
MemMgr = JMM ? JMM : JITMemoryManager::CreateDefaultMemManager();
@@ -351,9 +361,14 @@
MemMgr->AllocateGOT();
DOUT << "JIT is managing a GOT\n";
}
+
+ if (ExceptionHandling)
+ DE = new JITDwarfEmitter(jit);
}
+
~JITEmitter() {
delete MemMgr;
+ if (ExceptionHandling) delete DE;
}
JITResolver &getJITResolver() { return Resolver; }
@@ -361,6 +376,7 @@
virtual void startFunction(MachineFunction &F);
virtual bool finishFunction(MachineFunction &F);
+ void initConstantPool(MachineConstantPool *MCP);
void emitConstantPool(MachineConstantPool *MCP);
void initJumpTableInfo(MachineJumpTableInfo *MJTI);
void emitJumpTableInfo(MachineJumpTableInfo *MJTI);
@@ -392,6 +408,26 @@
void deallocateMemForFunction(Function *F) {
MemMgr->deallocateMemForFunction(F);
}
+
+ virtual void EmitLabel(uint64_t LabelID) {
+ if (LabelLocations.size() <= LabelID)
+ LabelLocations.resize((LabelID+1)*2);
+ LabelLocations[LabelID] = getCurrentPCValue();
+ }
+
+ virtual intptr_t getLabelAddress(uint64_t LabelID) const {
+ assert(LabelLocations.size() > (unsigned)LabelID &&
+ LabelLocations[LabelID] && "Label not emitted!");
+ return LabelLocations[LabelID];
+ }
+
+ virtual void setModuleInfo(MachineModuleInfo* Info) {
+ MMI = Info;
+ if (ExceptionHandling) DE->setModuleInfo(Info);
+ }
+
+
+
private:
void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
void *getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
@@ -442,19 +478,47 @@
void JITEmitter::startFunction(MachineFunction &F) {
- uintptr_t ActualSize;
- BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
- ActualSize);
- BufferEnd = BufferBegin+ActualSize;
+ MMI->BeginFunction(&F);
- // Ensure the constant pool/jump table info is at least 4-byte aligned.
- emitAlignment(16);
+ if (SizedMemoryCode) {
+ BufferBegin = CurBufferPtr;
+ BufferEnd = (unsigned char*) 0xffffffff;
+
+ // Ensure the constant pool/jump table info is at least 4-byte aligned.
+ emitAlignment(16);
- emitConstantPool(F.getConstantPool());
- initJumpTableInfo(F.getJumpTableInfo());
+ initConstantPool(F.getConstantPool());
+ initJumpTableInfo(F.getJumpTableInfo());
+
+
+ uintptr_t ActualSize = (uintptr_t)CurBufferPtr;
+ CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
+ ActualSize);
+
+ ConstantPoolBase = (void*)(((unsigned) ConstantPoolBase) + CurBufferPtr);
+ JumpTableBase = (void*)(((unsigned) JumpTableBase) + CurBufferPtr);
- // About to start emitting the machine code for the function.
- emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
+ emitConstantPool(F.getConstantPool());
+
+ } else {
+ uintptr_t ActualSize;
+ BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
+ ActualSize);
+ BufferEnd = BufferBegin+ActualSize;
+
+ // Ensure the constant pool/jump table info is at least 4-byte aligned.
+ emitAlignment(16);
+
+ initConstantPool(F.getConstantPool());
+ emitConstantPool(F.getConstantPool());
+ initJumpTableInfo(F.getJumpTableInfo());
+
+ // About to start emitting the machine code for the function.
+ emitAlignment(std::max(F.getFunction()->getAlignment(), 8U));
+
+ }
+
+
TheJIT->updateGlobalMapping(F.getFunction(), CurBufferPtr);
MBBLocations.clear();
@@ -553,10 +617,33 @@
<< sys::disassembleBuffer(FnStart, FnEnd-FnStart, (uintptr_t)FnStart);
#endif
+ if (ExceptionHandling) {
+ uintptr_t ActualSize;
+ if (SizedMemoryCode) {
+ SizeEmitter sz(LabelLocations);
+ DE->EmitDwarfTable(F, sz, FnStart, FnEnd);
+ ActualSize = sz.getCurrentPCValue();
+ }
+ SavedBufferBegin = BufferBegin;
+ SavedBufferEnd = BufferEnd;
+ SavedCurBufferPtr = CurBufferPtr;
+
+ BufferBegin = CurBufferPtr = MemMgr->startExceptionTable(F.getFunction(),
+ ActualSize);
+ BufferEnd = BufferBegin+ActualSize;
+ unsigned char* FrameRegister = DE->EmitDwarfTable(F, *this, FnStart, FnEnd);
+ MemMgr->endExceptionTable(F.getFunction(), BufferBegin, CurBufferPtr, FrameRegister);
+ BufferBegin = SavedBufferBegin;
+ BufferEnd = SavedBufferEnd;
+ CurBufferPtr = SavedCurBufferPtr;
+
+ TheJIT->RegisterTable(FrameRegister);
+ }
+ MMI->EndFunction();
return false;
}
-void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
+void JITEmitter::initConstantPool(MachineConstantPool *MCP) {
const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
if (Constants.empty()) return;
@@ -565,12 +652,15 @@
const Type *Ty = CPE.isMachineConstantPoolEntry()
? CPE.Val.MachineCPVal->getType() : CPE.Val.ConstVal->getType();
Size += TheJIT->getTargetData()->getABITypeSize(Ty);
-
+
ConstantPoolBase = allocateSpace(Size, 1 << MCP->getConstantPoolAlignment());
ConstantPool = MCP;
+}
+void JITEmitter::emitConstantPool(MachineConstantPool *MCP) {
if (ConstantPoolBase == 0) return; // Buffer overflow.
+ const std::vector<MachineConstantPoolEntry> &Constants = MCP->getConstants();
// Initialize the memory for all of the constant pool entries.
for (unsigned i = 0, e = Constants.size(); i != e; ++i) {
void *CAddr = (char*)ConstantPoolBase+Constants[i].Offset;
Index: lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp
===================================================================
--- lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp (revision 0)
+++ lib/ExecutionEngine/JIT/JITDwarfEmitter.cpp (revision 0)
@@ -0,0 +1,637 @@
+//===----- JITDwarfEmitter.cpp - Write dwarf tables into memory -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a JITDwarfEmitter object that is used by the JIT to
+// write dwarf tables to memory.
+//
+//===----------------------------------------------------------------------===//
+
+#include "JIT.h"
+#include "JITDwarfEmitter.h"
+#include "llvm/Function.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/CodeGen/MachineCodeEmitter.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineLocation.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/ExecutionEngine/JITMemoryManager.h"
+#include "llvm/Target/MRegisterInfo.h"
+#include "llvm/Target/TargetAsmInfo.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetMachine.h"
+
+using namespace llvm;
+
+JITDwarfEmitter::JITDwarfEmitter(JIT& theJit) : Jit(theJit) {}
+
+
+unsigned char* JITDwarfEmitter::EmitDwarfTable(MachineFunction& F,
+ MachineCodeEmitter& mce,
+ unsigned char* StartFunction,
+ unsigned char* EndFunction) {
+ const TargetMachine& TM = F.getTarget();
+ TD = TM.getTargetData();
+ needsIndirectEncoding = TM.getTargetAsmInfo()->getNeedsIndirectEncoding();
+ stackGrowthDirection = TM.getFrameInfo()->getStackGrowthDirection();
+ RI = TM.getRegisterInfo();
+ MCE = &mce;
+
+ unsigned char* ExceptionTable = EmitExceptionTable(&F, StartFunction,
+ EndFunction);
+
+ unsigned char* Result = 0;
+ unsigned char* EHFramePtr = 0;
+
+ const std::vector<Function *> Personalities = MMI->getPersonalities();
+ EHFramePtr = EmitCommonEHFrame(Personalities[MMI->getPersonalityIndex()]);
+
+ Result = EmitEHFrame(Personalities[MMI->getPersonalityIndex()], EHFramePtr,
+ StartFunction, EndFunction, ExceptionTable);
+
+ return Result;
+}
+
+
+void JITDwarfEmitter::EmitFrameMoves(intptr_t BaseLabelPtr,
+ const std::vector<MachineMove> &Moves) {
+ unsigned PointerSize = TD->getPointerSize();
+ int stackGrowth = stackGrowthDirection == TargetFrameInfo::StackGrowsUp ?
+ PointerSize : -PointerSize;
+ // TODO bool IsLocal = BaseLabel && strcmp(BaseLabel, "label") == 0;
+ bool IsLocal = BaseLabelPtr;
+
+ for (unsigned i = 0, N = Moves.size(); i < N; ++i) {
+ const MachineMove &Move = Moves[i];
+ unsigned LabelID = Move.getLabelID();
+
+ if (LabelID) {
+ LabelID = MMI->MappedLabel(LabelID);
+
+ // Throw out move if the label is invalid.
+ if (!LabelID) continue;
+ }
+
+ intptr_t LabelPtr = 0;
+ if (LabelID) LabelPtr = MCE->getLabelAddress(LabelID);
+
+ const MachineLocation &Dst = Move.getDestination();
+ const MachineLocation &Src = Move.getSource();
+
+ // Advance row if new location.
+ if (BaseLabelPtr && LabelID && (BaseLabelPtr != LabelPtr || !IsLocal)) {
+ MCE->emitByte(dwarf::DW_CFA_advance_loc4);
+ if (PointerSize == 8) {
+ MCE->emitInt64(LabelPtr - BaseLabelPtr);
+ } else {
+ MCE->emitInt32(LabelPtr - BaseLabelPtr);
+ }
+
+ BaseLabelPtr = LabelPtr;
+ IsLocal = true;
+ }
+
+ // If advancing cfa.
+ if (Dst.isRegister() && Dst.getRegister() == MachineLocation::VirtualFP) {
+ if (!Src.isRegister()) {
+ if (Src.getRegister() == MachineLocation::VirtualFP) {
+ MCE->emitByte(dwarf::DW_CFA_def_cfa_offset);
+ } else {
+ MCE->emitByte(dwarf::DW_CFA_def_cfa);
+ MCE->emitULEB128Bytes(RI->getDwarfRegNum(Src.getRegister(), true));
+ }
+
+ int Offset = -Src.getOffset();
+
+ MCE->emitULEB128Bytes(Offset);
+ } else {
+ assert(0 && "Machine move no supported yet.");
+ }
+ } else if (Src.isRegister() &&
+ Src.getRegister() == MachineLocation::VirtualFP) {
+ if (Dst.isRegister()) {
+ MCE->emitByte(dwarf::DW_CFA_def_cfa_register);
+ MCE->emitULEB128Bytes(RI->getDwarfRegNum(Dst.getRegister(), true));
+ } else {
+ assert(0 && "Machine move no supported yet.");
+ }
+ } else {
+ unsigned Reg = RI->getDwarfRegNum(Src.getRegister(), true);
+ int Offset = Dst.getOffset() / stackGrowth;
+
+ if (Offset < 0) {
+ MCE->emitByte(dwarf::DW_CFA_offset_extended_sf);
+ MCE->emitULEB128Bytes(Reg);
+ MCE->emitSLEB128Bytes(Offset);
+ } else if (Reg < 64) {
+ MCE->emitByte(dwarf::DW_CFA_offset + Reg);
+ MCE->emitULEB128Bytes(Offset);
+ } else {
+ MCE->emitByte(dwarf::DW_CFA_offset_extended);
+ MCE->emitULEB128Bytes(Reg);
+ MCE->emitULEB128Bytes(Offset);
+ }
+ }
+ }
+}
+
+/// SharedTypeIds - How many leading type ids two landing pads have in common.
+static unsigned SharedTypeIds(const LandingPadInfo *L,
+ const LandingPadInfo *R) {
+ const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
+ unsigned LSize = LIds.size(), RSize = RIds.size();
+ unsigned MinSize = LSize < RSize ? LSize : RSize;
+ unsigned Count = 0;
+
+ for (; Count != MinSize; ++Count)
+ if (LIds[Count] != RIds[Count])
+ return Count;
+
+ return Count;
+}
+
+
+/// PadLT - Order landing pads lexicographically by type id.
+static bool PadLT(const LandingPadInfo *L, const LandingPadInfo *R) {
+ const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
+ unsigned LSize = LIds.size(), RSize = RIds.size();
+ unsigned MinSize = LSize < RSize ? LSize : RSize;
+
+ for (unsigned i = 0; i != MinSize; ++i)
+ if (LIds[i] != RIds[i])
+ return LIds[i] < RIds[i];
+
+ return LSize < RSize;
+}
+
+struct KeyInfo {
+ static inline unsigned getEmptyKey() { return -1U; }
+ static inline unsigned getTombstoneKey() { return -2U; }
+ static unsigned getHashValue(const unsigned &Key) { return Key; }
+ static bool isEqual(unsigned LHS, unsigned RHS) { return LHS == RHS; }
+ static bool isPod() { return true; }
+};
+
+/// ActionEntry - Structure describing an entry in the actions table.
+struct ActionEntry {
+ int ValueForTypeID; // The value to write - may not be equal to the type id.
+ int NextAction;
+ struct ActionEntry *Previous;
+};
+
+/// PadRange - Structure holding a try-range and the associated landing pad.
+struct PadRange {
+ // The index of the landing pad.
+ unsigned PadIndex;
+ // The index of the begin and end labels in the landing pad's label lists.
+ unsigned RangeIndex;
+};
+
+typedef DenseMap<unsigned, PadRange, KeyInfo> RangeMapType;
+
+/// CallSiteEntry - Structure describing an entry in the call-site table.
+struct CallSiteEntry {
+ unsigned BeginLabel; // zero indicates the start of the function.
+ unsigned EndLabel; // zero indicates the end of the function.
+ unsigned PadLabel; // zero indicates that there is no landing pad.
+ unsigned Action;
+};
+
+unsigned char* JITDwarfEmitter::EmitExceptionTable(MachineFunction* MF,
+ unsigned char* StartFunction,
+ unsigned char* EndFunction) {
+ // Map all labels and get rid of any dead landing pads.
+ MMI->TidyLandingPads();
+
+ const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos();
+ const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
+ const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
+ if (PadInfos.empty()) return 0;
+
+ // Sort the landing pads in order of their type ids. This is used to fold
+ // duplicate actions.
+ SmallVector<const LandingPadInfo *, 64> LandingPads;
+ LandingPads.reserve(PadInfos.size());
+ for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
+ LandingPads.push_back(&PadInfos[i]);
+ std::sort(LandingPads.begin(), LandingPads.end(), PadLT);
+
+ // Negative type ids index into FilterIds, positive type ids index into
+ // TypeInfos. The value written for a positive type id is just the type
+ // id itself. For a negative type id, however, the value written is the
+ // (negative) byte offset of the corresponding FilterIds entry. The byte
+ // offset is usually equal to the type id, because the FilterIds entries
+ // are written using a variable width encoding which outputs one byte per
+ // entry as long as the value written is not too large, but can differ.
+ // This kind of complication does not occur for positive type ids because
+ // type infos are output using a fixed width encoding.
+ // FilterOffsets[i] holds the byte offset corresponding to FilterIds[i].
+ SmallVector<int, 16> FilterOffsets;
+ FilterOffsets.reserve(FilterIds.size());
+ int Offset = -1;
+ for(std::vector<unsigned>::const_iterator I = FilterIds.begin(),
+ E = FilterIds.end(); I != E; ++I) {
+ FilterOffsets.push_back(Offset);
+ Offset -= AsmPrinter::SizeULEB128(*I);
+ }
+
+ // Compute the actions table and gather the first action index for each
+ // landing pad site.
+ SmallVector<ActionEntry, 32> Actions;
+ SmallVector<unsigned, 64> FirstActions;
+ FirstActions.reserve(LandingPads.size());
+
+ int FirstAction = 0;
+ unsigned SizeActions = 0;
+ for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
+ const LandingPadInfo *LP = LandingPads[i];
+ const std::vector<int> &TypeIds = LP->TypeIds;
+ const unsigned NumShared = i ? SharedTypeIds(LP, LandingPads[i-1]) : 0;
+ unsigned SizeSiteActions = 0;
+
+ if (NumShared < TypeIds.size()) {
+ unsigned SizeAction = 0;
+ ActionEntry *PrevAction = 0;
+
+ if (NumShared) {
+ const unsigned SizePrevIds = LandingPads[i-1]->TypeIds.size();
+ assert(Actions.size());
+ PrevAction = &Actions.back();
+ SizeAction = AsmPrinter::SizeSLEB128(PrevAction->NextAction) +
+ AsmPrinter::SizeSLEB128(PrevAction->ValueForTypeID);
+ for (unsigned j = NumShared; j != SizePrevIds; ++j) {
+ SizeAction -= AsmPrinter::SizeSLEB128(PrevAction->ValueForTypeID);
+ SizeAction += -PrevAction->NextAction;
+ PrevAction = PrevAction->Previous;
+ }
+ }
+
+ // Compute the actions.
+ for (unsigned I = NumShared, M = TypeIds.size(); I != M; ++I) {
+ int TypeID = TypeIds[I];
+ assert(-1-TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
+ int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID;
+ unsigned SizeTypeID = AsmPrinter::SizeSLEB128(ValueForTypeID);
+
+ int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
+ SizeAction = SizeTypeID + AsmPrinter::SizeSLEB128(NextAction);
+ SizeSiteActions += SizeAction;
+
+ ActionEntry Action = {ValueForTypeID, NextAction, PrevAction};
+ Actions.push_back(Action);
+
+ PrevAction = &Actions.back();
+ }
+
+ // Record the first action of the landing pad site.
+ FirstAction = SizeActions + SizeSiteActions - SizeAction + 1;
+ } // else identical - re-use previous FirstAction
+
+ FirstActions.push_back(FirstAction);
+
+ // Compute this sites contribution to size.
+ SizeActions += SizeSiteActions;
+ }
+
+ // Compute the call-site table. Entries must be ordered by address.
+ SmallVector<CallSiteEntry, 64> CallSites;
+
+ RangeMapType PadMap;
+ for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
+ const LandingPadInfo *LandingPad = LandingPads[i];
+ for (unsigned j=0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
+ unsigned BeginLabel = LandingPad->BeginLabels[j];
+ assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
+ PadRange P = { i, j };
+ PadMap[BeginLabel] = P;
+ }
+ }
+
+ bool MayThrow = false;
+ unsigned LastLabel = 0;
+ for (MachineFunction::const_iterator I = MF->begin(), E = MF->end();
+ I != E; ++I) {
+ for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end();
+ MI != E; ++MI) {
+ if (MI->getOpcode() != TargetInstrInfo::LABEL) {
+ MayThrow |= MI->getDesc().isCall();
+ continue;
+ }
+
+ unsigned BeginLabel = MI->getOperand(0).getImm();
+ assert(BeginLabel && "Invalid label!");
+
+ if (BeginLabel == LastLabel)
+ MayThrow = false;
+
+ RangeMapType::iterator L = PadMap.find(BeginLabel);
+
+ if (L == PadMap.end())
+ continue;
+
+ PadRange P = L->second;
+ const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
+
+ assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
+ "Inconsistent landing pad map!");
+
+ // If some instruction between the previous try-range and this one may
+ // throw, create a call-site entry with no landing pad for the region
+ // between the try-ranges.
+ if (MayThrow) {
+ CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0};
+ CallSites.push_back(Site);
+ }
+
+ LastLabel = LandingPad->EndLabels[P.RangeIndex];
+ CallSiteEntry Site = {BeginLabel, LastLabel,
+ LandingPad->LandingPadLabel, FirstActions[P.PadIndex]};
+
+ assert(Site.BeginLabel && Site.EndLabel && Site.PadLabel &&
+ "Invalid landing pad!");
+
+ // Try to merge with the previous call-site.
+ if (CallSites.size()) {
+ CallSiteEntry &Prev = CallSites[CallSites.size()-1];
+ if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) {
+ // Extend the range of the previous entry.
+ Prev.EndLabel = Site.EndLabel;
+ continue;
+ }
+ }
+
+ // Otherwise, create a new call-site.
+ CallSites.push_back(Site);
+ }
+ }
+ // If some instruction between the previous try-range and the end of the
+ // function may throw, create a call-site entry with no landing pad for the
+ // region following the try-range.
+ if (MayThrow) {
+ CallSiteEntry Site = {LastLabel, 0, 0, 0};
+ CallSites.push_back(Site);
+ }
+
+ // Final tallies.
+ unsigned SizeSites = CallSites.size() * (sizeof(int32_t) + // Site start.
+ sizeof(int32_t) + // Site length.
+ sizeof(int32_t)); // Landing pad.
+ for (unsigned i = 0, e = CallSites.size(); i < e; ++i)
+ SizeSites += AsmPrinter::SizeULEB128(CallSites[i].Action);
+
+ unsigned SizeTypes = TypeInfos.size() * TD->getPointerSize();
+
+ unsigned TypeOffset = sizeof(int8_t) + // Call site format
+ // Call-site table length
+ AsmPrinter::SizeULEB128(SizeSites) +
+ SizeSites + SizeActions + SizeTypes;
+
+ unsigned TotalSize = sizeof(int8_t) + // LPStart format
+ sizeof(int8_t) + // TType format
+ AsmPrinter::SizeULEB128(TypeOffset) + // TType base offset
+ TypeOffset;
+
+ unsigned SizeAlign = (4 - TotalSize) & 3;
+
+ // Begin the exception table.
+ MCE->emitAlignment(4);
+ for (unsigned i = 0; i != SizeAlign; ++i) {
+ MCE->emitByte(0);
+ // Asm->EOL("Padding");
+ }
+
+ unsigned char* DwarfExceptionTable = (unsigned char*)MCE->getCurrentPCValue();
+
+ // Emit the header.
+ MCE->emitByte(dwarf::DW_EH_PE_omit);
+ // Asm->EOL("LPStart format (DW_EH_PE_omit)");
+ MCE->emitByte(dwarf::DW_EH_PE_absptr);
+ // Asm->EOL("TType format (DW_EH_PE_absptr)");
+ MCE->emitULEB128Bytes(TypeOffset);
+ // Asm->EOL("TType base offset");
+ MCE->emitByte(dwarf::DW_EH_PE_udata4);
+ // Asm->EOL("Call site format (DW_EH_PE_udata4)");
+ MCE->emitULEB128Bytes(SizeSites);
+ // Asm->EOL("Call-site table length");
+
+ // Emit the landing pad site information.
+ for (unsigned i = 0; i < CallSites.size(); ++i) {
+ CallSiteEntry &S = CallSites[i];
+ intptr_t BeginLabelPtr = 0;
+ intptr_t EndLabelPtr = 0;
+
+ if (!S.BeginLabel) {
+ BeginLabelPtr = (intptr_t)StartFunction;
+ if (TD->getPointerSize() == sizeof(int32_t))
+ MCE->emitInt32(0);
+ else
+ MCE->emitInt64(0);
+ } else {
+ BeginLabelPtr = MCE->getLabelAddress(S.BeginLabel);
+ if (TD->getPointerSize() == sizeof(int32_t))
+ MCE->emitInt32(BeginLabelPtr - (intptr_t)StartFunction);
+ else
+ MCE->emitInt64(BeginLabelPtr - (intptr_t)StartFunction);
+ }
+
+ // Asm->EOL("Region start");
+
+ if (!S.EndLabel) {
+ EndLabelPtr = (intptr_t)EndFunction;
+ if (TD->getPointerSize() == sizeof(int32_t))
+ MCE->emitInt32((intptr_t)EndFunction - BeginLabelPtr);
+ else
+ MCE->emitInt64((intptr_t)EndFunction - BeginLabelPtr);
+ } else {
+ EndLabelPtr = MCE->getLabelAddress(S.EndLabel);
+ if (TD->getPointerSize() == sizeof(int32_t))
+ MCE->emitInt32(EndLabelPtr - BeginLabelPtr);
+ else
+ MCE->emitInt64(EndLabelPtr - BeginLabelPtr);
+ }
+ //Asm->EOL("Region length");
+
+ if (!S.PadLabel) {
+ if (TD->getPointerSize() == sizeof(int32_t))
+ MCE->emitInt32(0);
+ else
+ MCE->emitInt64(0);
+ } else {
+ unsigned PadLabelPtr = MCE->getLabelAddress(S.PadLabel);
+ if (TD->getPointerSize() == sizeof(int32_t))
+ MCE->emitInt32(PadLabelPtr - (intptr_t)StartFunction);
+ else
+ MCE->emitInt64(PadLabelPtr - (intptr_t)StartFunction);
+ }
+ // Asm->EOL("Landing pad");
+
+ MCE->emitULEB128Bytes(S.Action);
+ // Asm->EOL("Action");
+ }
+
+ // Emit the actions.
+ for (unsigned I = 0, N = Actions.size(); I != N; ++I) {
+ ActionEntry &Action = Actions[I];
+
+ MCE->emitSLEB128Bytes(Action.ValueForTypeID);
+ //Asm->EOL("TypeInfo index");
+ MCE->emitSLEB128Bytes(Action.NextAction);
+ //Asm->EOL("Next action");
+ }
+
+ // Emit the type ids.
+ for (unsigned M = TypeInfos.size(); M; --M) {
+ GlobalVariable *GV = TypeInfos[M - 1];
+
+ if (GV) {
+ if (TD->getPointerSize() == sizeof(int32_t)) {
+ MCE->emitInt32((intptr_t)Jit.getOrEmitGlobalVariable(GV));
+ } else {
+ MCE->emitInt64((intptr_t)Jit.getOrEmitGlobalVariable(GV));
+ }
+ } else {
+ if (TD->getPointerSize() == sizeof(int32_t))
+ MCE->emitInt32(0);
+ else
+ MCE->emitInt64(0);
+ }
+ // Asm->EOL("TypeInfo");
+ }
+
+ // Emit the filter typeids.
+ for (unsigned j = 0, M = FilterIds.size(); j < M; ++j) {
+ unsigned TypeID = FilterIds[j];
+ MCE->emitULEB128Bytes(TypeID);
+ //Asm->EOL("Filter TypeInfo index");
+ }
+
+ MCE->emitAlignment(4);
+
+ return DwarfExceptionTable;
+}
+
+unsigned char* JITDwarfEmitter::EmitCommonEHFrame(const Function* Personality) {
+ unsigned PointerSize = TD->getPointerSize();
+ int stackGrowth = stackGrowthDirection == TargetFrameInfo::StackGrowsUp ?
+ PointerSize : -PointerSize;
+
+ unsigned char* StartCommonPtr = (unsigned char*)MCE->getCurrentPCValue();
+ // EH Common Frame header
+ MCE->allocateSpace(PointerSize, 0);
+ unsigned char* FrameCommonBeginPtr = (unsigned char*)MCE->getCurrentPCValue();
+ MCE->emitInt32((int)0);
+ MCE->emitByte(dwarf::DW_CIE_VERSION);
+ MCE->emitString(Personality ? "zPLR" : "zR");
+ MCE->emitULEB128Bytes(1);
+ MCE->emitSLEB128Bytes(stackGrowth);
+ MCE->emitByte(RI->getDwarfRegNum(RI->getRARegister(), true));
+
+ if (Personality) {
+ MCE->emitULEB128Bytes(7);
+
+ if (needsIndirectEncoding)
+ MCE->emitByte(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 |
+ dwarf::DW_EH_PE_indirect);
+ else
+ MCE->emitByte(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4);
+
+ if (PointerSize == 8)
+ MCE->emitInt64((intptr_t)Jit.getPointerToGlobal(Personality) -
+ MCE->getCurrentPCValue());
+ else
+ MCE->emitInt32((intptr_t)Jit.getPointerToGlobal(Personality) -
+ MCE->getCurrentPCValue());
+
+ MCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel);
+ MCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel);
+
+ } else {
+ MCE->emitULEB128Bytes(1);
+ MCE->emitULEB128Bytes(dwarf::DW_EH_PE_pcrel);
+ }
+
+ std::vector<MachineMove> Moves;
+ RI->getInitialFrameState(Moves);
+ EmitFrameMoves(0, Moves);
+ MCE->emitAlignment(4);
+
+ MCE->emitAt((uintptr_t*)StartCommonPtr,
+ (uintptr_t)((unsigned char*)MCE->getCurrentPCValue() -
+ FrameCommonBeginPtr));
+
+ return StartCommonPtr;
+}
+
+
+unsigned char* JITDwarfEmitter::EmitEHFrame(const Function* Personality,
+ unsigned char* StartCommonPtr,
+ unsigned char* StartFunction,
+ unsigned char* EndFunction,
+ unsigned char* ExceptionTable) {
+ unsigned PointerSize = TD->getPointerSize();
+
+ // EH frame header.
+ unsigned char* StartEHPtr = (unsigned char*)MCE->getCurrentPCValue();
+ MCE->allocateSpace(PointerSize, 0);
+ unsigned char* FrameBeginPtr = (unsigned char*)MCE->getCurrentPCValue();
+ // FDE CIE Offset
+ if (PointerSize == 8) {
+ MCE->emitInt64(FrameBeginPtr - StartCommonPtr);
+ MCE->emitInt64(StartFunction - (unsigned char*)MCE->getCurrentPCValue());
+ MCE->emitInt64(EndFunction - StartFunction);
+ } else {
+ MCE->emitInt32(FrameBeginPtr - StartCommonPtr);
+ MCE->emitInt32(StartFunction - (unsigned char*)MCE->getCurrentPCValue());
+ MCE->emitInt32(EndFunction - StartFunction);
+ }
+
+ // If there is a personality and landing pads then point to the language
+ // specific data area in the exception table.
+ if (MMI->getPersonalityIndex()) {
+ MCE->emitULEB128Bytes(4);
+
+ if (!MMI->getLandingPads().empty()) {
+ if (PointerSize == 8)
+ MCE->emitInt64(ExceptionTable - (unsigned char*)MCE->getCurrentPCValue());
+ else
+ MCE->emitInt32(ExceptionTable - (unsigned char*)MCE->getCurrentPCValue());
+ } else if (PointerSize == 8) {
+ MCE->emitInt64((int)0);
+ } else {
+ MCE->emitInt32((int)0);
+ }
+ } else {
+ MCE->emitULEB128Bytes(0);
+ }
+
+ // Indicate locations of function specific callee saved registers in
+ // frame.
+ EmitFrameMoves((intptr_t)StartFunction, MMI->getFrameMoves());
+
+ MCE->emitAlignment(4);
+
+ // Indicate the size of the table
+ MCE->emitAt((uintptr_t*)StartEHPtr,
+ (uintptr_t)((unsigned char*)MCE->getCurrentPCValue() -
+ StartEHPtr));
+
+ // Double zeroes for the unwind runtime
+ if (PointerSize == 8) {
+ MCE->emitInt64(0);
+ MCE->emitInt64(0);
+ } else {
+ MCE->emitInt32(0);
+ MCE->emitInt32(0);
+ }
+
+
+ return StartEHPtr;
+}
Index: lib/ExecutionEngine/JIT/JIT.cpp
===================================================================
--- lib/ExecutionEngine/JIT/JIT.cpp (revision 46321)
+++ lib/ExecutionEngine/JIT/JIT.cpp (working copy)
@@ -314,8 +314,15 @@
abort();
}
}
+
+ if (void *Addr = getPointerToGlobalIfAvailable(F)) {
+ return Addr;
+ }
if (F->isDeclaration()) {
+ if (void *Addr = getPointerToGlobalIfAvailable(F)) {
+ return Addr;
+ }
void *Addr = getPointerToNamedFunction(F->getName());
addGlobalMapping(F, Addr);
return Addr;
Index: lib/ExecutionEngine/JIT/JITDwarfEmitter.h
===================================================================
--- lib/ExecutionEngine/JIT/JITDwarfEmitter.h (revision 0)
+++ lib/ExecutionEngine/JIT/JITDwarfEmitter.h (revision 0)
@@ -0,0 +1,69 @@
+//===------ JITDwarfEmitter.h - Write dwarf tables into memory ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a JITDwarfEmitter object that is used by the JIT to
+// write dwarf tables to memory.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
+#define LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
+
+namespace llvm {
+
+class Function;
+class MachineCodeEmitter;
+class MachineFunction;
+class MachineModuleInfo;
+class MachineMove;
+class MRegisterInfo;
+class TargetData;
+class TargetMachine;
+
+class JITDwarfEmitter {
+ const TargetData* TD;
+ MachineCodeEmitter* MCE;
+ const MRegisterInfo* RI;
+ MachineModuleInfo* MMI;
+ JIT& Jit;
+ bool needsIndirectEncoding;
+ bool stackGrowthDirection;
+
+public:
+ JITDwarfEmitter(JIT& jit);
+
+ unsigned char* EmitExceptionTable(MachineFunction* MF,
+ unsigned char* StartFunction,
+ unsigned char* EndFunction);
+
+ void EmitFrameMoves(intptr_t BaseLabelPtr,
+ const std::vector<MachineMove> &Moves);
+
+ unsigned char* EmitCommonEHFrame(const Function* Personality);
+
+ unsigned char* EmitEHFrame(const Function* Personality,
+ unsigned char* StartBufferPtr,
+ unsigned char* StartFunction,
+ unsigned char* EndFunction,
+ unsigned char* ExceptionTable);
+
+
+ unsigned char* EmitDwarfTable(MachineFunction& F,
+ MachineCodeEmitter& MCE,
+ unsigned char* StartFunction,
+ unsigned char* EndFunction);
+
+ void setModuleInfo(MachineModuleInfo* Info) {
+ MMI = Info;
+ }
+};
+
+} // end namespace llvm
+
+#endif // LLVM_EXECUTION_ENGINE_JIT_DWARFEMITTER_H
Index: lib/ExecutionEngine/JIT/JITMemoryManager.cpp
===================================================================
--- lib/ExecutionEngine/JIT/JITMemoryManager.cpp (revision 46321)
+++ lib/ExecutionEngine/JIT/JITMemoryManager.cpp (working copy)
@@ -256,6 +256,7 @@
sys::MemoryBlock getNewMemoryBlock(unsigned size);
std::map<const Function*, MemoryRangeHeader*> FunctionBlocks;
+ std::map<const Function*, MemoryRangeHeader*> TableBlocks;
public:
DefaultJITMemoryManager();
~DefaultJITMemoryManager();
@@ -290,6 +291,28 @@
FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
}
+ /// startExceptionTable - Use startFunctionBody to allocate memory for the
+ /// function's exception table.
+ unsigned char* startExceptionTable(const Function* F, uintptr_t &ActualSize) {
+ return startFunctionBody(F, ActualSize);
+ }
+
+ /// endExceptionTable - The exception table of F is now allocated,
+ /// and takes the memory in the range [TableStart,TableEnd).
+ void endExceptionTable(const Function *F, unsigned char *TableStart,
+ unsigned char *TableEnd,
+ unsigned char* FrameRegister) {
+ assert(TableEnd > TableStart);
+ assert(TableStart == (unsigned char *)(CurBlock+1) &&
+ "Mismatched table start/end!");
+
+ uintptr_t BlockSize = TableEnd - (unsigned char *)CurBlock;
+ TableBlocks[F] = CurBlock;
+
+ // Release the memory at the end of this block that isn't needed.
+ FreeMemoryList =CurBlock->TrimAllocationToSize(FreeMemoryList, BlockSize);
+ }
+
unsigned char *getGOTBase() const {
return GOTBase;
}
@@ -315,6 +338,24 @@
// Finally, remove this entry from FunctionBlocks.
FunctionBlocks.erase(I);
+
+ I = TableBlocks.find(F);
+ if (I == TableBlocks.end()) return;
+
+ // Find the block that is allocated for this function.
+ MemRange = I->second;
+ assert(MemRange->ThisAllocated && "Block isn't allocated!");
+
+ // Fill the buffer with garbage!
+#ifndef NDEBUG
+ memset(MemRange+1, 0xCD, MemRange->BlockSize-sizeof(*MemRange));
+#endif
+
+ // Free the memory.
+ FreeMemoryList = MemRange->FreeBlock(FreeMemoryList);
+
+ // Finally, remove this entry from TableBlocks.
+ TableBlocks.erase(I);
}
};
}
Index: lib/ExecutionEngine/ExecutionEngine.cpp
===================================================================
--- lib/ExecutionEngine/ExecutionEngine.cpp (revision 46321)
+++ lib/ExecutionEngine/ExecutionEngine.cpp (working copy)
@@ -34,7 +34,9 @@
ExecutionEngine::EECtorFn ExecutionEngine::JITCtor = 0;
ExecutionEngine::EECtorFn ExecutionEngine::InterpCtor = 0;
+ExecutionEngine::EERegisterFn ExecutionEngine::ExceptionTableRegister = 0;
+
ExecutionEngine::ExecutionEngine(ModuleProvider *P) : LazyFunctionCreator(0) {
LazyCompilationDisabled = false;
Modules.push_back(P);
@@ -89,7 +91,7 @@
// If we are using the reverse mapping, add it too
if (!state.getGlobalAddressReverseMap(locked).empty()) {
const GlobalValue *&V = state.getGlobalAddressReverseMap(locked)[Addr];
- assert((V == 0 || GV == 0) && "GlobalMapping already established!");
+ // assert((V == 0 || GV == 0) && "GlobalMapping already established!");
V = GV;
}
}
@@ -125,7 +127,7 @@
// If we are using the reverse mapping, add it too
if (!state.getGlobalAddressReverseMap(locked).empty()) {
const GlobalValue *&V = state.getGlobalAddressReverseMap(locked)[Addr];
- assert((V == 0 || GV == 0) && "GlobalMapping already established!");
+ // assert((V == 0 || GV == 0) && "GlobalMapping already established!");
V = GV;
}
}
Index: lib/VMCore/AsmWriter.cpp
===================================================================
--- lib/VMCore/AsmWriter.cpp (revision 46321)
+++ lib/VMCore/AsmWriter.cpp (working copy)
@@ -1052,8 +1052,9 @@
case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break;
case GlobalValue::ExternalLinkage: break;
case GlobalValue::GhostLinkage:
- cerr << "GhostLinkage not allowed in AsmWriter!\n";
- abort();
+ //cerr << "GhostLinkage not allowed in AsmWriter!\n";
+ //abort();
+ break;
}
switch (F->getVisibility()) {
default: assert(0 && "Invalid visibility style!");