sourcepawn/jit/x86/jit_x86.h
author David Anderson <dvander@alliedmods.net>
Mon Aug 12 00:24:02 2013 +0100 (2013-08-12)
changeset 3993 d06d6dacfa18
parent 3992 f1e8cad30a64
child 4013 6201c1180e0e
permissions -rw-r--r--
Remove InfoVars, reassign DAT from EBP to ESI to preserve C++ stacktraces in JIT code (bug 5844 part 10, r=ds).
     1 /**
     2  * vim: set ts=4 sw=4 tw=99 et:
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #ifndef _INCLUDE_SOURCEPAWN_JIT_X86_H_
    33 #define _INCLUDE_SOURCEPAWN_JIT_X86_H_
    34 
    35 #include <sp_vm_types.h>
    36 #include <sp_vm_api.h>
    37 #include <KeCodeAllocator.h>
    38 #include <macro-assembler-x86.h>
    39 #include <ke_vector.h>
    40 #include "jit_shared.h"
    41 #include "BaseRuntime.h"
    42 #include "sp_vm_basecontext.h"
    43 #include "jit_function.h"
    44 #include "opcodes.h"
    45 
    46 using namespace SourcePawn;
    47 
    48 #define JIT_INLINE_ERRORCHECKS  (1<<0)
    49 #define JIT_INLINE_NATIVES      (1<<1)
    50 #define STACK_MARGIN            64      //8 parameters of safety, I guess
    51 #define JIT_FUNCMAGIC           0x214D4148  //magic function offset
    52 
    53 #define JITVARS_TRACKER         0    //important: don't change this to avoid trouble
    54 #define JITVARS_BASECTX         1    //important: don't change this aWOAWOGJQG I LIKE HAM
    55 #define JITVARS_PROFILER        2    //profiler
    56 #define JITVARS_PLUGIN          3    //sp_plugin_t
    57 
    58 #define sDIMEN_MAX              5    //this must mirror what the compiler has.
    59 
    60 #define GET_CONTEXT(c)  ((IPluginContext *)c->vm[JITVARS_BASECTX])
    61 
    62 typedef struct tracker_s
    63 {
    64   size_t size; 
    65   ucell_t *pBase; 
    66   ucell_t *pCur;
    67 } tracker_t;
    68 
    69 typedef struct funcinfo_s
    70 {
    71   unsigned int magic;
    72   unsigned int index;
    73 } funcinfo_t;
    74 
    75 typedef struct functracker_s
    76 {
    77   unsigned int num_functions;
    78   unsigned int code_size;
    79 } functracker_t;
    80 
    81 struct CallThunk
    82 {
    83   Label call;
    84   cell_t pcode_offset;
    85 
    86   CallThunk(cell_t pcode_offset)
    87     : pcode_offset(pcode_offset)
    88   {
    89   }
    90 };
    91 
    92 class CompData : public ICompilation
    93 {
    94 public:
    95   CompData() 
    96   : profile(0),
    97     inline_level(0)
    98   {
    99   };
   100   bool SetOption(const char *key, const char *val);
   101   void Abort();
   102 public:
   103   cell_t cur_func;            /* current func pcode offset */
   104   /* Options */
   105   int profile;                /* profiling flags */
   106   int inline_level;           /* inline optimization level */
   107   /* Per-compilation properties */
   108   unsigned int func_idx;      /* current function index */
   109 };
   110 
   111 class Compiler
   112 {
   113  public:
   114   Compiler(BaseRuntime *rt, cell_t pcode_offs);
   115   ~Compiler();
   116 
   117   JitFunction *emit(int *errp);
   118 
   119  private:
   120   bool setup(cell_t pcode_offs);
   121   bool emitOp(OPCODE op);
   122   cell_t readCell();
   123 
   124  private:
   125   Label *labelAt(size_t offset);
   126   bool emitCall();
   127   bool emitNativeCall(OPCODE op);
   128   bool emitSwitch();
   129   void emitGenArray(bool autozero);
   130   void emitCallThunks();
   131   void emitCheckAddress(Register reg);
   132   void emitErrorPath(Label *dest, int code);
   133   void emitErrorPaths();
   134 
   135   ExternalAddress cipAddr() {
   136     sp_context_t *ctx = rt_->GetBaseContext()->GetCtx();
   137     return ExternalAddress(&ctx->cip);
   138   }
   139   ExternalAddress hpAddr() {
   140     sp_context_t *ctx = rt_->GetBaseContext()->GetCtx();
   141     return ExternalAddress(&ctx->hp);
   142   }
   143   ExternalAddress frmAddr() {
   144     sp_context_t *ctx = rt_->GetBaseContext()->GetCtx();
   145     return ExternalAddress(&ctx->frm);
   146   }
   147 
   148  private:
   149   AssemblerX86 masm;
   150   BaseRuntime *rt_;
   151   const sp_plugin_t *plugin_;
   152   int error_;
   153   uint32_t pcode_start_;
   154   cell_t *code_start_;
   155   cell_t *cip_;
   156   cell_t *code_end_;
   157   Label *jump_map_;
   158 
   159   // Errors
   160   Label error_bounds_;
   161   Label error_heap_low_;
   162   Label error_heap_min_;
   163   Label error_stack_low_;
   164   Label error_stack_min_;
   165   Label error_divide_by_zero_;
   166   Label error_memaccess_;
   167   Label error_integer_overflow_;
   168   Label extern_error_;
   169 
   170   ke::Vector<CallThunk *> thunks_; //:TODO: free
   171 };
   172 
   173 class JITX86
   174 {
   175  public:
   176   JITX86();
   177 
   178  public:
   179   bool InitializeJIT();
   180   void ShutdownJIT();
   181   ICompilation *StartCompilation(BaseRuntime *runtime);
   182   ICompilation *StartCompilation();
   183   void SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx);
   184   void FreeContextVars(sp_context_t *ctx);
   185   SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
   186   void DestroyFakeNative(SPVM_NATIVE_FUNC func);
   187   JitFunction *CompileFunction(BaseRuntime *runtime, cell_t pcode_offs, int *err);
   188   ICompilation *ApplyOptions(ICompilation *_IN, ICompilation *_OUT);
   189   int InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result);
   190 
   191  public:
   192   ExternalAddress GetUniversalReturn() {
   193       return ExternalAddress(m_pJitReturn);
   194   }
   195   void *AllocCode(size_t size);
   196   void FreeCode(void *code);
   197 
   198  private:
   199   void *m_pJitEntry;         /* Entry function */
   200   void *m_pJitReturn;        /* Universal return address */
   201 };
   202 
   203 const Register pri = eax;
   204 const Register alt = edx;
   205 const Register stk = edi;
   206 const Register dat = esi;
   207 const Register tmp = ecx;
   208 const Register frm = ebx;
   209 
   210 extern Knight::KeCodeCache *g_pCodeCache;
   211 extern JITX86 g_Jit;
   212 
   213 #endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_