[LLVMdev] Exception handling in JIT

Nicolas Geoffray nicolas.geoffray at lip6.fr
Wed Dec 12 03:51:39 PST 2007


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



More information about the llvm-dev mailing list