Hi Evan,
My apologies: I've been so excited on sharing the functionality that I
forgot to review my patch!
Evan Cheng wrote:> On Dec 10, 2007, at 9:52 AM, Nicolas Geoffray wrote:
>
>
>> Hi everyone,
>>
>> Here's a patch that enables exception handling when jitting.
I've
>> copy/pasted _many_code from lib/Codegen/DwarfWriter.cpp, so we may
>> need
>> to factorize it, but the functionality is there and I'm very happy
>> with
>> it :)
>>
>
> Very nice! I don't know enough about EH, someone else please review.
>
> It does look like it's in need of some refactoring. How much work is
it?
>
>
Anton or Duncan may know how much work it should be. DwarfWriter writes
on a file and only knows about label names, not label addresses. IMO the
refactoring is non-trivial.
>> +// the University of Illinois Open Source License. See LICENSE.TXT
>> for details.
>> +//
>> +//
>> ===-------------------------------------------------------------------
>> ---===//
>> +//
>> +//
>> ===-------------------------------------------------------------------
>> ---===//
>> +
>> +#ifndef LLVM_CODEGEN_DWARFEMITTER_H
>> +#define LLVM_CODEGEN_DWARFEMITTER_H
>> +
>> +#include "llvm/Support/DataTypes.h"
>> +#include <string>
>> +#include <vector>
>> +
>> +namespace llvm {
>> +
>> +class Function;
>> +class MachineCodeEmitter;
>> +class TargetData;
>> +class TargetMachine;
>> +class MachineFunction;
>> +class MachineModuleInfo;
>> +class MachineMove;
>> +class MRegisterInfo;
>> +
>> +class DwarfEmitter {
>> +protected:
>> + /// BufferBegin/BufferEnd - Pointers to the start and end of the
>> memory
>> + /// allocated for this code buffer.
>> + unsigned char *BufferBegin, *BufferEnd;
>> +
>> + /// CurBufferPtr - Pointer to the next byte of memory to fill
>> when emitting
>> + /// code. This is guranteed to be in the range
>> [BufferBegin,BufferEnd]. If
>> + /// this pointer is at BufferEnd, it will never move due to code
>> emission, and
>> + /// all code emission requests will be ignored (this is the
>> buffer overflow
>> + /// condition).
>> + unsigned char *CurBufferPtr;
>>
>
> I am not sure if it makes sense for this to maintain it's own
> buffers. Can it be modified to use MachineCodeEmitter?
>
>
You mean DwarfEmitter inherits MachineCodeEmitter? There are
MachineCodeEmitter functions that are really not related to
MachineCodeEmitter (eg addRelocation, getConstantPoolEntryAddress, etc).
>> +
>> + MachineModuleInfo* MMI;
>> +public:
>> + virtual ~DwarfEmitter() {}
>> +
>> + /// startFunction - This callback is invoked when the specified
>> function is
>> + /// about to be code generated. This initializes the
>> BufferBegin/End/Ptr
>> + /// fields.
>> + ///
>> + virtual void startFunction(MachineFunction &F) = 0;
>> +
>> + /// finishFunction - This callback is invoked when the specified
>> function has
>> + /// finished code generation. If a buffer overflow has
>> occurred, this method
>> + /// returns true (the callee is required to try again),
>> otherwise it returns
>> + /// false.
>> + ///
>> + virtual bool finishFunction(MachineFunction &F, unsigned char*
>> FnStart,
>> + unsigned char* FnEnd) = 0;
>> +
>> + /// EmitInt8 - This callback is invoked when a byte needs to be
>> written to the
>> + /// output stream.
>> + ///
>> + void EmitInt8(unsigned char B, bool print=true) {
>> +// if (print) printf(".byte 0x%x\n", B);
>> + if (CurBufferPtr != BufferEnd)
>> + *CurBufferPtr++ = B;
>> + }
>>
>
> Please use DOUT instead leaving debugging code around. What's the
> relationship between this module and MachineCodeEmitter? Does it make
> sense to move the common facility to MachineCodeEmitter?
>
>
That's one part I should have reviewed before sending you the patch.
Sure we can move all DwarEmitter functions to MachineCodeEmitter. That's
not a problem.
>> +
>> + /// EmitULEB128Bytes - This callback is invoked when a ULEB128
>> needs to be
>> + /// written to the output stream.
>> + void EmitULEB128Bytes(unsigned Value) {
>> +// printf(".uleb128 %d\n", Value);
>> + do {
>> + unsigned char Byte = Value & 0x7f;
>> + Value >>= 7;
>> + if (Value) Byte |= 0x80;
>> + EmitInt8(Byte, false);
>> + } while (Value);
>> + }
>> +
>> + /// EmitSLEB128Bytes - This callback is invoked when a SLEB128
>> needs to be
>> + /// written to the output stream.
>> + void EmitSLEB128Bytes(int Value) {
>> +// printf(".sleb128 %d\n", 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;
>> + EmitInt8(Byte, false);
>> + } while (IsMore);
>> + }
>> +
>> + void EmitString(const std::string &String) {
>> +// printf(".asciiz %s\n", String.c_str());
>> + for (unsigned i = 0, N = String.size(); i < N; ++i) {
>> + unsigned char C = String[i];
>> + EmitInt8(C, false);
>> + }
>> + EmitInt8(0, false);
>> + }
>> +
>> + void EmitInt32(int Value) {
>> +// printf(".long 0x%x\n", Value);
>> + if (CurBufferPtr+4 <= BufferEnd) {
>> + *((uint32_t*)CurBufferPtr) = Value;
>> + CurBufferPtr += 4;
>> + } else {
>> + CurBufferPtr = BufferEnd;
>> + }
>> + }
>> +
>> + /// EmitInt64 - Emit a long long directive and value.
>> + ///
>> + void EmitInt64(uint64_t Value) {
>> + if (CurBufferPtr+8 <= BufferEnd) {
>> + *((uint64_t*)CurBufferPtr) = Value;
>> + CurBufferPtr += 8;
>> + } else {
>> + CurBufferPtr = BufferEnd;
>> + }
>> + }
>> +
>> +
>> + /// emitAlignment - Move the CurBufferPtr pointer up the the
>> specified
>> + /// alignment (saturated to BufferEnd of course).
>> + void EmitAlignment(unsigned Alignment) {
>> +// printf(".align %x\n", 1 << Alignment);
>> + if (Alignment == 0) Alignment = 1;
>> + // Move the current buffer ptr up to the specified alignment.
>> + CurBufferPtr >> + (unsigned
char*)(((intptr_t)CurBufferPtr+Alignment-1) &
>> + ~(intptr_t)(Alignment-1));
>> + if (CurBufferPtr > BufferEnd)
>> + CurBufferPtr = BufferEnd;
>> + }
>>
>
> Comment says "emitAlignment". Function definition is
EmitAlignment.
> To be consistent with MachineModuleInfo, please use the former
> convention.
>
>
OK
>> +
>> + /// 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.
>> + void *allocateSpace(intptr_t Size, unsigned Alignment) {
>> + EmitAlignment(Alignment);
>> + void *Result = CurBufferPtr;
>> +
>> + // Allocate the space.
>> + CurBufferPtr += Size;
>> +
>> + // Check for buffer overflow.
>> + if (CurBufferPtr >= BufferEnd) {
>> + CurBufferPtr = BufferEnd;
>> + Result = 0;
>> + }
>> + return Result;
>> + }
>> +
>> + void setModuleInfo(MachineModuleInfo* M) {
>> + MMI = M;
>> + }
>> +};
>> +
>> +} // End llvm namespace
>> +
>> +#endif
>> Index: include/llvm/CodeGen/MachineCodeEmitter.h
>>
==================================================================>> ---
include/llvm/CodeGen/MachineCodeEmitter.h (revision 44794)
>> +++ include/llvm/CodeGen/MachineCodeEmitter.h (working copy)
>> @@ -22,10 +22,12 @@
>>
>> namespace llvm {
>>
>> +class DwarfEmitter;
>> class MachineBasicBlock;
>> class MachineConstantPool;
>> class MachineJumpTableInfo;
>> class MachineFunction;
>> +class MachineModuleInfo;
>> class MachineRelocation;
>> class Value;
>> class GlobalValue;
>> @@ -58,6 +60,7 @@
>> /// all code emission requests will be ignored (this is the
>> buffer overflow
>> /// condition).
>> unsigned char *CurBufferPtr;
>> +
>> public:
>> virtual ~MachineCodeEmitter() {}
>>
>> @@ -158,6 +161,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.
>> ///
>> @@ -193,6 +199,10 @@
>> /// emitted.
>> ///
>> virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock
>> *MBB) const= 0;
>> +
>> + virtual intptr_t getLabelAddress(uint64_t LabelID) const = 0;
>> +
>> + virtual void setModuleInfo(MachineModuleInfo* Info) = 0;
>> };
>>
>> } // End llvm namespace
>> Index: lib/CodeGen/LLVMTargetMachine.cpp
>>
==================================================================>> ---
lib/CodeGen/LLVMTargetMachine.cpp (revision 44794)
>> +++ lib/CodeGen/LLVMTargetMachine.cpp (working copy)
>> @@ -158,7 +158,8 @@
>> PM.add(createLowerGCPass());
>>
>> // FIXME: Implement the invoke/unwind instructions!
>> - PM.add(createLowerInvokePass(getTargetLowering()));
>> + if (!ExceptionHandling)
>> + PM.add(createLowerInvokePass(getTargetLowering()));
>>
>
> Is this right?
>
>
>From LowerInvoke.cpp: " This transformation is designed for use by code
generators which do not yet
support stack unwinding". Now the JIT does ;)
>> // Make sure that no unreachable blocks are instruction selected.
>> PM.add(createUnreachableBlockEliminationPass());
>> Index: lib/CodeGen/ELFWriter.cpp
>>
==================================================================>> ---
lib/CodeGen/ELFWriter.cpp (revision 44794)
>> +++ 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/MachOWriter.cpp
>>
==================================================================>> ---
lib/CodeGen/MachOWriter.cpp (revision 44794)
>> +++ 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 44794)
>> +++ lib/Target/PowerPC/PPCCodeEmitter.cpp (working copy)
>> @@ -38,6 +38,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 +87,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 +108,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/X86/X86CodeEmitter.cpp
>>
==================================================================>> ---
lib/Target/X86/X86CodeEmitter.cpp (revision 44794)
>> +++ lib/Target/X86/X86CodeEmitter.cpp (working copy)
>> @@ -55,6 +55,11 @@
>> }
>>
>> void emitInstruction(const MachineInstr &MI);
>> +
>> + void getAnalysisUsage(AnalysisUsage &AU) const {
>> + AU.addRequired<MachineModuleInfo>();
>> + MachineFunctionPass::getAnalysisUsage(AU);
>> + }
>>
>> private:
>> void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
>> @@ -96,11 +101,14 @@
>> 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&)MF.getTarget()).getInstrInfo();
>> TD = ((X86TargetMachine&)MF.getTarget()).getTargetData();
>> Is64BitMode >>
((X86TargetMachine&)MF.getTarget()).getSubtarget<X86Subtarget>
>> ().is64Bit();
>> -
>> +
>> do {
>> MCE.startFunction(MF);
>> for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
>> @@ -577,7 +585,8 @@
>> 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_USE:
>> case X86::IMPLICIT_DEF:
>> case X86::IMPLICIT_DEF_GR8:
>> Index: lib/ExecutionEngine/JIT/JITEmitter.cpp
>>
==================================================================>> ---
lib/ExecutionEngine/JIT/JITEmitter.cpp (revision 44794)
>> +++ lib/ExecutionEngine/JIT/JITEmitter.cpp (working copy)
>> @@ -17,19 +17,31 @@
>> #include "llvm/Constant.h"
>> #include "llvm/Module.h"
>> #include "llvm/Type.h"
>> +#include "llvm/ADT/DenseMap.h"
>> +#include "llvm/CodeGen/AsmPrinter.h"
>> +#include "llvm/CodeGen/DwarfEmitter.h"
>> #include "llvm/CodeGen/MachineCodeEmitter.h"
>> #include "llvm/CodeGen/MachineFunction.h"
>> #include "llvm/CodeGen/MachineConstantPool.h"
>> #include "llvm/CodeGen/MachineJumpTableInfo.h"
>> +#include "llvm/CodeGen/MachineLocation.h"
>> +#include "llvm/CodeGen/MachineModuleInfo.h"
>> #include "llvm/CodeGen/MachineRelocation.h"
>> +#include "llvm/ExecutionEngine/GenericValue.h"
>> #include "llvm/ExecutionEngine/JITMemoryManager.h"
>> +#include "llvm/Target/MRegisterInfo.h"
>> +#include "llvm/Target/TargetAsmInfo.h"
>> #include "llvm/Target/TargetData.h"
>> +#include "llvm/Target/TargetFrameInfo.h"
>> +#include "llvm/Target/TargetInstrInfo.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;
>>
>> @@ -37,7 +49,10 @@
>> STATISTIC(NumRelos, "Number of relocations applied");
>> static JIT *TheJIT = 0;
>>
>> +extern "C" void __register_frame(void*);
>> +extern "C" void __register_frame_table(void*);
>>
>
> Can you explain what these are?
>
>
Again, I've sent you the patch too fast. These functions are taken from
the g++ unwinder library (libgcc_s.so). Declaring them like I did is
really bad. I'm thinking of something like:
typedef void function_register_t(void*)
ExecutionEngine::registerFrameRegisteringFunction(function_register_t)
What do you think?
>> +
>> //
>> ===-------------------------------------------------------------------
>> ---===//
>> // JIT lazy compilation code.
>> //
>> @@ -275,6 +290,71 @@
>> // JITEmitter code.
>> //
>> namespace {
>> +
>> + class DwarfJITEmitter : public DwarfEmitter {
>> + JITMemoryManager *MemMgr;
>> + const TargetData& TD;
>> + TargetMachine &TM;
>> + MachineCodeEmitter& MCE;
>> + const MRegisterInfo* RI;
>> +
>> + public:
>> + DwarfJITEmitter(MachineCodeEmitter &mce, const TargetData&
td,
>> + TargetMachine& tm) : TD(td), TM(tm), MCE(mce)
{
>> + RI = TM.getRegisterInfo();
>> + MemMgr = JITMemoryManager::CreateDefaultMemManager();
>> + }
>> +
>> + 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);
>> +
>> + virtual void startFunction(MachineFunction& F) {
>> + MMI->BeginFunction(&F);
>> + }
>> +
>> + virtual bool finishFunction(MachineFunction& F,
>> + unsigned char* StartFunction,
>> + unsigned char* EndFunction) {
>> + uintptr_t ActualSize;
>> + BufferBegin = CurBufferPtr = MemMgr->startFunctionBody
>> (F.getFunction(),
>> +
>> ActualSize);
>> + BufferEnd = BufferBegin+ActualSize;
>> +
>> + 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[Personalities.size() -
>> 1], EHFramePtr,
>> + StartFunction, EndFunction,
>> ExceptionTable);
>> +
>> + unsigned char *FnEnd = CurBufferPtr;
>> + MemMgr->endFunctionBody(F.getFunction(), BufferBegin, FnEnd);
>> + MMI->EndFunction();
>> +
>> + __register_frame(Result);
>> +
>> + return false;
>> + }
>> +
>> + };
>> +
>> /// JITEmitter - The JIT implementation of the
>> MachineCodeEmitter, which is
>> /// used to output functions to memory for execution.
>> class JITEmitter : public MachineCodeEmitter {
>> @@ -311,6 +391,11 @@
>>
>> /// Resolver - This contains info about the currently resolved
>> functions.
>> JITResolver Resolver;
>> +
>> + DwarfJITEmitter *DE;
>> +
>> + std::vector<intptr_t> LabelLocations;
>> +
>> public:
>> JITEmitter(JIT &jit, JITMemoryManager *JMM) : Resolver(jit) {
>> MemMgr = JMM ? JMM :
>> JITMemoryManager::CreateDefaultMemManager();
>> @@ -318,9 +403,14 @@
>> MemMgr->AllocateGOT();
>> DOUT << "JIT is managing a GOT\n";
>> }
>> + if (ExceptionHandling)
>> + DE = new DwarfJITEmitter(*this, *jit.getTargetData(),
>> + jit.getTargetMachine());
>> +
>>
>
> Please don't add getTargetMachine() to jit. MachineCodeEmitter can
> keep a reference to MachineFunction or something like that.
>
>
OK
>> }
>> ~JITEmitter() {
>> delete MemMgr;
>> + if (ExceptionHandling) delete DE;
>> }
>>
>> JITResolver &getJITResolver() { return Resolver; }
>> @@ -359,11 +449,606 @@
>> 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) {
>> + if (ExceptionHandling) DE->setModuleInfo(Info);
>>
>
> Doesn't seem to need the check.
>
>
It's needed because DE is allocated only if ExceptionHandling is true.
>> + }
>> +
>> +
>> +
>> private:
>> void *getPointerToGlobal(GlobalValue *GV, void *Reference,
>> bool NoNeedStub);
>> };
>> }
>>
>> +void DwarfJITEmitter::EmitFrameMoves(intptr_t BaseLabelPtr,
>> + const
>> std::vector<MachineMove> &Moves) {
>> + unsigned PointerSize = TD.getPointerSize();
>> + int stackGrowth >> +
TM.getFrameInfo()->getStackGrowthDirection() =>> +
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)) {
>> + EmitInt8(dwarf::DW_CFA_advance_loc4);
>> + if (PointerSize == 8) {
>> + EmitInt64(LabelPtr - BaseLabelPtr);
>> + } else {
>> + 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) {
>> + EmitInt8(dwarf::DW_CFA_def_cfa_offset);
>> + } else {
>> + EmitInt8(dwarf::DW_CFA_def_cfa);
>> + EmitULEB128Bytes(RI->getDwarfRegNum(Src.getRegister(),
>> true));
>> + }
>> +
>> + int Offset = -Src.getOffset();
>> +
>> + EmitULEB128Bytes(Offset);
>> + } else {
>> + assert(0 && "Machine move no supported
yet.");
>> + }
>> + } else if (Src.isRegister() &&
>> + Src.getRegister() == MachineLocation::VirtualFP) {
>> + if (Dst.isRegister()) {
>> + EmitInt8(dwarf::DW_CFA_def_cfa_register);
>> + 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) {
>> + EmitInt8(dwarf::DW_CFA_offset_extended_sf);
>> + EmitULEB128Bytes(Reg);
>> + EmitSLEB128Bytes(Offset);
>> + } else if (Reg < 64) {
>> + EmitInt8(dwarf::DW_CFA_offset + Reg);
>> + EmitULEB128Bytes(Offset);
>> + } else {
>> + EmitInt8(dwarf::DW_CFA_offset_extended);
>> + EmitULEB128Bytes(Reg);
>> + 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* DwarfJITEmitter::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);
>>
>
> stable_sort instead? Does it matter?
>
>
I leave that to the DwarWriter.cpp coders. All the code here is taken
from that file.
Thanks,
Nicolas