| 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!"); |