211 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			211 lines
		
	
	
		
			5.5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // vim: set ts=8 sts=2 sw=2 tw=99 et:
 | |
| //
 | |
| // This file is part of SourcePawn.
 | |
| // 
 | |
| // SourcePawn is free software: you can redistribute it and/or modify
 | |
| // it under the terms of the GNU General Public License as published by
 | |
| // the Free Software Foundation, either version 3 of the License, or
 | |
| // (at your option) any later version.
 | |
| // 
 | |
| // SourcePawn is distributed in the hope that it will be useful,
 | |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | |
| // GNU General Public License for more details.
 | |
| // 
 | |
| // You should have received a copy of the GNU General Public License
 | |
| // along with SourcePawn.  If not, see <http://www.gnu.org/licenses/>.
 | |
| #ifndef _INCLUDE_SOURCEPAWN_JIT_X86_H_
 | |
| #define _INCLUDE_SOURCEPAWN_JIT_X86_H_
 | |
| 
 | |
| #include <sp_vm_types.h>
 | |
| #include <sp_vm_api.h>
 | |
| #include <KeCodeAllocator.h>
 | |
| #include <macro-assembler-x86.h>
 | |
| #include <am-vector.h>
 | |
| #include "jit_shared.h"
 | |
| #include "BaseRuntime.h"
 | |
| #include "sp_vm_basecontext.h"
 | |
| #include "jit_function.h"
 | |
| #include "opcodes.h"
 | |
| #include <am-thread-utils.h>
 | |
| 
 | |
| using namespace SourcePawn;
 | |
| 
 | |
| #define JIT_INLINE_ERRORCHECKS  (1<<0)
 | |
| #define JIT_INLINE_NATIVES      (1<<1)
 | |
| #define STACK_MARGIN            64      //8 parameters of safety, I guess
 | |
| #define JIT_FUNCMAGIC           0x214D4148  //magic function offset
 | |
| 
 | |
| #define JITVARS_PROFILER        2    //profiler
 | |
| 
 | |
| #define sDIMEN_MAX              5    //this must mirror what the compiler has.
 | |
| 
 | |
| typedef struct funcinfo_s
 | |
| {
 | |
|   unsigned int magic;
 | |
|   unsigned int index;
 | |
| } funcinfo_t;
 | |
| 
 | |
| typedef struct functracker_s
 | |
| {
 | |
|   unsigned int num_functions;
 | |
|   unsigned int code_size;
 | |
| } functracker_t;
 | |
| 
 | |
| struct CallThunk
 | |
| {
 | |
|   Label call;
 | |
|   cell_t pcode_offset;
 | |
| 
 | |
|   CallThunk(cell_t pcode_offset)
 | |
|     : pcode_offset(pcode_offset)
 | |
|   {
 | |
|   }
 | |
| };
 | |
| 
 | |
| class CompData : public ICompilation
 | |
| {
 | |
| public:
 | |
|   CompData() 
 | |
|   : profile(0),
 | |
|     inline_level(0)
 | |
|   {
 | |
|   };
 | |
|   bool SetOption(const char *key, const char *val);
 | |
|   void Abort();
 | |
| public:
 | |
|   cell_t cur_func;            /* current func pcode offset */
 | |
|   /* Options */
 | |
|   int profile;                /* profiling flags */
 | |
|   int inline_level;           /* inline optimization level */
 | |
|   /* Per-compilation properties */
 | |
|   unsigned int func_idx;      /* current function index */
 | |
| };
 | |
| 
 | |
| class Compiler
 | |
| {
 | |
|  public:
 | |
|   Compiler(BaseRuntime *rt, cell_t pcode_offs);
 | |
|   ~Compiler();
 | |
| 
 | |
|   JitFunction *emit(int *errp);
 | |
| 
 | |
|  private:
 | |
|   bool setup(cell_t pcode_offs);
 | |
|   bool emitOp(OPCODE op);
 | |
|   cell_t readCell();
 | |
| 
 | |
|  private:
 | |
|   Label *labelAt(size_t offset);
 | |
|   bool emitCall();
 | |
|   bool emitNativeCall(OPCODE op);
 | |
|   bool emitSwitch();
 | |
|   void emitGenArray(bool autozero);
 | |
|   void emitCallThunks();
 | |
|   void emitCheckAddress(Register reg);
 | |
|   void emitErrorPath(Label *dest, int code);
 | |
|   void emitErrorPaths();
 | |
|   void emitFloatCmp(ConditionCode cc);
 | |
| 
 | |
|   ExternalAddress cipAddr() {
 | |
|     sp_context_t *ctx = rt_->GetBaseContext()->GetCtx();
 | |
|     return ExternalAddress(&ctx->cip);
 | |
|   }
 | |
|   ExternalAddress hpAddr() {
 | |
|     sp_context_t *ctx = rt_->GetBaseContext()->GetCtx();
 | |
|     return ExternalAddress(&ctx->hp);
 | |
|   }
 | |
|   ExternalAddress frmAddr() {
 | |
|     sp_context_t *ctx = rt_->GetBaseContext()->GetCtx();
 | |
|     return ExternalAddress(&ctx->frm);
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   AssemblerX86 masm;
 | |
|   BaseRuntime *rt_;
 | |
|   const sp_plugin_t *plugin_;
 | |
|   int error_;
 | |
|   uint32_t pcode_start_;
 | |
|   cell_t *code_start_;
 | |
|   cell_t *cip_;
 | |
|   cell_t *code_end_;
 | |
|   Label *jump_map_;
 | |
|   ke::Vector<size_t> backward_jumps_;
 | |
| 
 | |
|   // Errors
 | |
|   Label error_bounds_;
 | |
|   Label error_heap_low_;
 | |
|   Label error_heap_min_;
 | |
|   Label error_stack_low_;
 | |
|   Label error_stack_min_;
 | |
|   Label error_divide_by_zero_;
 | |
|   Label error_memaccess_;
 | |
|   Label error_integer_overflow_;
 | |
|   Label extern_error_;
 | |
| 
 | |
|   ke::Vector<CallThunk *> thunks_; //:TODO: free
 | |
| };
 | |
| 
 | |
| class JITX86
 | |
| {
 | |
|  public:
 | |
|   JITX86();
 | |
| 
 | |
|  public:
 | |
|   bool InitializeJIT();
 | |
|   void ShutdownJIT();
 | |
|   ICompilation *StartCompilation(BaseRuntime *runtime);
 | |
|   ICompilation *StartCompilation();
 | |
|   void SetupContextVars(BaseRuntime *runtime, BaseContext *pCtx, sp_context_t *ctx);
 | |
|   void FreeContextVars(sp_context_t *ctx);
 | |
|   SPVM_NATIVE_FUNC CreateFakeNative(SPVM_FAKENATIVE_FUNC callback, void *pData);
 | |
|   void DestroyFakeNative(SPVM_NATIVE_FUNC func);
 | |
|   JitFunction *CompileFunction(BaseRuntime *runtime, cell_t pcode_offs, int *err);
 | |
|   ICompilation *ApplyOptions(ICompilation *_IN, ICompilation *_OUT);
 | |
|   int InvokeFunction(BaseRuntime *runtime, JitFunction *fn, cell_t *result);
 | |
| 
 | |
|   void RegisterRuntime(BaseRuntime *rt);
 | |
|   void DeregisterRuntime(BaseRuntime *rt);
 | |
|   void PatchAllJumpsForTimeout();
 | |
|   void UnpatchAllJumpsFromTimeout();
 | |
|   
 | |
|  public:
 | |
|   ExternalAddress GetUniversalReturn() {
 | |
|     return ExternalAddress(m_pJitReturn);
 | |
|   }
 | |
|   void *AllocCode(size_t size);
 | |
|   void FreeCode(void *code);
 | |
| 
 | |
|   uintptr_t FrameId() const {
 | |
|     return frame_id_;
 | |
|   }
 | |
|   bool RunningCode() const {
 | |
|     return level_ != 0;
 | |
|   }
 | |
|   ke::Mutex *Mutex() {
 | |
|     return &mutex_;
 | |
|   }
 | |
| 
 | |
|  private:
 | |
|   void *m_pJitEntry;         /* Entry function */
 | |
|   void *m_pJitReturn;        /* Universal return address */
 | |
|   void *m_pJitTimeout;       /* Universal timeout address */
 | |
|   ke::InlineList<BaseRuntime> runtimes_;
 | |
|   uintptr_t frame_id_;
 | |
|   uintptr_t level_;
 | |
|   ke::Mutex mutex_;
 | |
| };
 | |
| 
 | |
| const Register pri = eax;
 | |
| const Register alt = edx;
 | |
| const Register stk = edi;
 | |
| const Register dat = esi;
 | |
| const Register tmp = ecx;
 | |
| const Register frm = ebx;
 | |
| 
 | |
| extern Knight::KeCodeCache *g_pCodeCache;
 | |
| extern JITX86 g_Jit;
 | |
| 
 | |
| #endif //_INCLUDE_SOURCEPAWN_JIT_X86_H_
 | |
| 
 |