updated to trunk code

--HG--
branch : sourcemod-1.1.0
extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/branches/sourcemod-1.1.0%401936
This commit is contained in:
David Anderson 2008-03-13 17:04:25 +00:00
parent 50760d853f
commit a64894bbe4
7 changed files with 238 additions and 30 deletions

View File

@ -36,7 +36,7 @@ else
CPPFLAGS += $(OPT_CPP_FLAGS) CPPFLAGS += $(OPT_CPP_FLAGS)
endif endif
CFLAGS += -DLINUX -DNDEBUG -DHAVE_STDINT_H -DAMX_ANSIONLY -DENABLE_BINRELOC CFLAGS += -DLINUX -DNDEBUG -DHAVE_STDINT_H -DAMX_ANSIONLY -DENABLE_BINRELOC -m32
CPPFLAGS += -Wno-deprecated -fno-exceptions -fno-rtti CPPFLAGS += -Wno-deprecated -fno-exceptions -fno-rtti
OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o) OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
@ -53,7 +53,7 @@ all:
$(MAKE) spcomp $(MAKE) spcomp
spcomp: $(OBJ_LINUX) spcomp: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -ldl -lm -o$(BIN_DIR)/$(BINARY) $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -m32 -ldl -lm -o$(BIN_DIR)/$(BINARY)
debug: debug:
$(MAKE) all DEBUG=true $(MAKE) all DEBUG=true

View File

@ -4136,6 +4136,8 @@ static int newfunc(char *firstname,int firsttag,int fpublic,int fstatic,int stoc
/* "declargs()" found the ")"; if a ";" appears after this, it was a /* "declargs()" found the ")"; if a ";" appears after this, it was a
* prototype */ * prototype */
if (matchtoken(';')) { if (matchtoken(';')) {
if (sym->usage & uPUBLIC)
error(10);
sym->usage|=uFORWARD; sym->usage|=uFORWARD;
if (!sc_needsemicolon) if (!sc_needsemicolon)
error(10); /* old style prototypes used with optional semicolumns */ error(10); /* old style prototypes used with optional semicolumns */

View File

@ -1207,7 +1207,7 @@ static int hier14(value *lval1)
} /* if */ } /* if */
} /* if */ } /* if */
if (lval3.sym->dim.array.level!=level) if (lval3.sym->dim.array.level!=level)
return error(48); /* array dimensions must match */ return error(47); /* array dimensions must match */
else if (ltlength<val || exactmatch && ltlength>val || val==0) else if (ltlength<val || exactmatch && ltlength>val || val==0)
return error(47); /* array sizes must match */ return error(47); /* array sizes must match */
else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE)) else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE))
@ -1217,6 +1217,7 @@ static int hier14(value *lval1)
symbol *sym1 = lval3.sym; symbol *sym1 = lval3.sym;
symbol *sym2 = lval2.sym; symbol *sym2 = lval2.sym;
int i; int i;
error(23);
assert(sym1!=NULL && sym2!=NULL); assert(sym1!=NULL && sym2!=NULL);
/* ^^^ sym2 must be valid, because only variables can be /* ^^^ sym2 must be valid, because only variables can be
* multi-dimensional (there are no multi-dimensional literals), * multi-dimensional (there are no multi-dimensional literals),
@ -1328,7 +1329,9 @@ static int hier13(value *lval)
array1= (lval->ident==iARRAY || lval->ident==iREFARRAY); array1= (lval->ident==iARRAY || lval->ident==iREFARRAY);
array2= (lval2.ident==iARRAY || lval2.ident==iREFARRAY); array2= (lval2.ident==iARRAY || lval2.ident==iREFARRAY);
if (array1 && !array2) { if (array1 && !array2) {
char *ptr=(lval->sym->name!=NULL) ? lval->sym->name : "-unknown-"; const char *ptr = "-unknown-";
if (lval->sym != NULL && lval->sym->name != NULL)
ptr = lval->sym->name;
error(33,ptr); /* array must be indexed */ error(33,ptr); /* array must be indexed */
} else if (!array1 && array2) { } else if (!array1 && array2) {
char *ptr=(lval2.sym->name!=NULL) ? lval2.sym->name : "-unknown-"; char *ptr=(lval2.sym->name!=NULL) ? lval2.sym->name : "-unknown-";
@ -1569,7 +1572,7 @@ static int hier2(value *lval)
if (level>sym->dim.array.level+1) { if (level>sym->dim.array.level+1) {
error(28,sym->name); /* invalid subscript */ error(28,sym->name); /* invalid subscript */
} else if (level==sym->dim.array.level+1) { } else if (level==sym->dim.array.level+1) {
lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1; lval->constval=(idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1;
} else { } else {
lval->constval=array_levelsize(sym,level); lval->constval=array_levelsize(sym,level);
} }
@ -2365,7 +2368,7 @@ static int nesting=0;
*/ */
} else { } else {
arglist[argpos]=ARG_DONE; /* flag argument as "present" */ arglist[argpos]=ARG_DONE; /* flag argument as "present" */
if (arg[argidx].numtags==1) /* set the expected tag, if any */ if (arg[argidx].ident!=0 && arg[argidx].numtags==1) /* set the expected tag, if any */
lval.cmptag=arg[argidx].tags[0]; lval.cmptag=arg[argidx].tags[0];
lvalue=hier14(&lval); lvalue=hier14(&lval);
assert(sc_status==statFIRST || arg[argidx].tags!=NULL); assert(sc_status==statFIRST || arg[argidx].tags!=NULL);

View File

@ -32,7 +32,10 @@ endif
GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1) GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fPIC -fno-exceptions -fno-rtti -msse -DHAVE_STDINT_H CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \
-Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \
-Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fno-exceptions -fno-rtti \
-DHAVE_STDINT_H -m32
ifeq "$(GCC_VERSION)" "4" ifeq "$(GCC_VERSION)" "4"
CFLAGS += $(GCC4_FLAGS) CFLAGS += $(GCC4_FLAGS)
@ -52,7 +55,7 @@ all:
ln -sf $(BIN_DIR)/$(BINARY) $(BINARY) ln -sf $(BIN_DIR)/$(BINARY) $(BINARY)
binary: $(OBJ_LINUX) binary: $(OBJ_LINUX)
$(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY) $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
debug: debug:
$(MAKE) all DEBUG=true $(MAKE) all DEBUG=true

View File

@ -25,7 +25,7 @@ EXPORTFUNC int GiveEnginePointer2(SourcePawn::ISourcePawnEngine *engine_p, unsig
{ {
engine = engine_p; engine = engine_p;
if (api_version > SOURCEPAWN_ENGINE_API_VERSION) if (api_version > SOURCEPAWN_ENGINE_API_VERSION || api_version < 2)
{ {
return SP_ERROR_PARAM; return SP_ERROR_PARAM;
} }

View File

@ -1278,12 +1278,99 @@ inline void WriteOp_Retn(JitWriter *jit)
IA32_Return(jit); IA32_Return(jit);
} }
void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
{
ctx->profiler->OnFunctionBegin(ctx->context, name);
}
void ProfCallGate_End(sp_context_t *ctx)
{
ctx->profiler->OnFunctionEnd();
}
const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
{
uint32_t max, iter;
sp_fdbg_symbol_t *sym;
sp_fdbg_arraydim_t *arr;
uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
max = plugin->debug.syms_num;
for (iter = 0; iter < max; iter++)
{
sym = (sp_fdbg_symbol_t *)cursor;
if (sym->ident == SP_SYM_FUNCTION
&& sym->codestart <= offs
&& sym->codeend > offs)
{
return plugin->debug.stringbase + sym->name;
}
if (sym->dimcount > 0)
{
cursor += sizeof(sp_fdbg_symbol_t);
arr = (sp_fdbg_arraydim_t *)cursor;
cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
continue;
}
cursor += sizeof(sp_fdbg_symbol_t);
}
return NULL;
}
inline void WriteOp_Call(JitWriter *jit) inline void WriteOp_Call(JitWriter *jit)
{ {
cell_t offs = jit->read_cell(); cell_t offs;
jitoffs_t jmp;
CompData *data;
data = (CompData *)jit->data;
offs = jit->read_cell();
jitoffs_t jmp = IA32_Call_Imm32(jit, 0); if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false)); {
const char *name;
/* Find the function name */
if ((name = find_func_name(data->plugin, offs)) == NULL)
{
name = "unknown";
}
//push name
//push [esi+context]
//call ProfCallGate_Begin
//add esp, 8
IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)name);
IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
jmp = IA32_Call_Imm32(jit, 0);
IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_Begin);
IA32_Add_Rm_Imm8(jit, REG_ESP, 8, MOD_REG);
//call <addr>
//push eax
jmp = IA32_Call_Imm32(jit, 0);
IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
IA32_Push_Reg(jit, REG_EAX);
//push [esi+context]
//call ProfCallGate_End
//add esp, 4
//pop eax
IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
jmp = IA32_Call_Imm32(jit, 0);
IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_End);
IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
IA32_Pop_Reg(jit, REG_EAX);
}
else
{
jmp = IA32_Call_Imm32(jit, 0);
IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
}
} }
inline void WriteOp_Bounds(JitWriter *jit) inline void WriteOp_Bounds(JitWriter *jit)
@ -1653,9 +1740,25 @@ inline void WriteOp_Sysreq_N(JitWriter *jit)
jitoffs_t call = IA32_Call_Imm32(jit, 0); jitoffs_t call = IA32_Call_Imm32(jit, 0);
if (!data->debug) if (!data->debug)
{ {
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback); if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
} else { {
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug); IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile);
}
else
{
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
}
}
else
{
if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
{
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug_Profile);
}
else
{
IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
}
} }
/* check for errors */ /* check for errors */
@ -2122,7 +2225,9 @@ inline void WriteOp_FloatCompare(JitWriter *jit)
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params) cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
{ {
sp_native_t *native = &ctx->natives[native_idx]; sp_native_t *native;
native = &ctx->natives[native_idx];
ctx->n_idx = native_idx; ctx->n_idx = native_idx;
@ -2136,12 +2241,27 @@ cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
return native->pfn(ctx->context, params); return native->pfn(ctx->context, params);
} }
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params) cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
{ {
sp_context_t *ctx = pCtx->GetContext(); cell_t val;
ctx->n_err = SP_ERROR_INVALID_NATIVE; sp_native_t *native;
return 0; native = &ctx->natives[native_idx];
ctx->n_idx = native_idx;
/* Technically both aren't needed, I guess */
if (native->status == SP_NATIVE_UNBOUND)
{
ctx->n_err = SP_ERROR_INVALID_NATIVE;
return 0;
}
ctx->profiler->OnNativeBegin(ctx->context, native);
val = native->pfn(ctx->context, params);
ctx->profiler->OnNativeEnd();
return val;
} }
cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params) cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
@ -2170,7 +2290,7 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
} }
cell_t result = NativeCallback(ctx, native_idx, params); cell_t result = NativeCallback(ctx, native_idx, params);
if (ctx->n_err != SP_ERROR_NONE) if (ctx->n_err != SP_ERROR_NONE)
{ {
return result; return result;
@ -2180,7 +2300,9 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
{ {
ctx->n_err = SP_ERROR_STACKLEAK; ctx->n_err = SP_ERROR_STACKLEAK;
return result; return result;
} else if (save_hp != ctx->hp) { }
else if (save_hp != ctx->hp)
{
ctx->n_err = SP_ERROR_HEAPLEAK; ctx->n_err = SP_ERROR_HEAPLEAK;
return result; return result;
} }
@ -2188,6 +2310,60 @@ cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *param
return result; return result;
} }
cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
{
cell_t save_sp = ctx->sp;
cell_t save_hp = ctx->hp;
ctx->n_idx = native_idx;
if (ctx->hp < ctx->heap_base)
{
ctx->n_err = SP_ERROR_HEAPMIN;
return 0;
}
if (ctx->hp + STACK_MARGIN > ctx->sp)
{
ctx->n_err = SP_ERROR_STACKLOW;
return 0;
}
if ((uint32_t)ctx->sp >= ctx->mem_size)
{
ctx->n_err = SP_ERROR_STACKMIN;
return 0;
}
cell_t result = NativeCallback_Profile(ctx, native_idx, params);
if (ctx->n_err != SP_ERROR_NONE)
{
return result;
}
if (save_sp != ctx->sp)
{
ctx->n_err = SP_ERROR_STACKLEAK;
return result;
}
else if (save_hp != ctx->hp)
{
ctx->n_err = SP_ERROR_HEAPLEAK;
return result;
}
return result;
}
static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
{
sp_context_t *ctx = pCtx->GetContext();
ctx->n_err = SP_ERROR_INVALID_NATIVE;
return 0;
}
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative) jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
{ {
if (jit->outptr) if (jit->outptr)
@ -2204,7 +2380,9 @@ jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize); assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize);
/* Do the lookup in the native dictionary. */ /* Do the lookup in the native dictionary. */
return *(jitoffs_t *)(data->rebase + pcode_offs); return *(jitoffs_t *)(data->rebase + pcode_offs);
} else { }
else
{
return 0; return 0;
} }
} }
@ -2380,7 +2558,8 @@ jit_rewind:
/* the total codesize is now known! */ /* the total codesize is now known! */
codemem = writer.get_outputpos(); codemem = writer.get_outputpos();
writer.outbase = (jitcode_t)engine->ExecAlloc(codemem); writer.outbase = (jitcode_t)engine->AllocatePageMemory(codemem);
engine->SetReadWrite(writer.outbase);
writer.outptr = writer.outbase; writer.outptr = writer.outbase;
/* go back for third pass */ /* go back for third pass */
goto jit_rewind; goto jit_rewind;
@ -2398,6 +2577,8 @@ jit_rewind:
} }
/* Write these last because error jumps should be unpredicted, and thus forward */ /* Write these last because error jumps should be unpredicted, and thus forward */
WriteErrorRoutines(data, jit); WriteErrorRoutines(data, jit);
engine->SetReadExecute(writer.outbase);
} }
/************* /*************
@ -2420,6 +2601,7 @@ jit_rewind:
ctx->heap_base = plugin->data_size; ctx->heap_base = plugin->data_size;
ctx->hp = ctx->heap_base; ctx->hp = ctx->heap_base;
ctx->sp = ctx->mem_size - sizeof(cell_t); ctx->sp = ctx->mem_size - sizeof(cell_t);
ctx->prof_flags = data->profile;
const char *strbase = plugin->info.stringbase; const char *strbase = plugin->info.stringbase;
uint32_t max, iter; uint32_t max, iter;
@ -2605,22 +2787,25 @@ rewind:
if (jw.outbase == NULL) if (jw.outbase == NULL)
{ {
/* Second pass: Actually write */ /* Second pass: Actually write */
jw.outbase = (jitcode_t)engine->ExecAlloc(jw.get_outputpos()); jw.outbase = (jitcode_t)engine->AllocatePageMemory(jw.get_outputpos());
if (!jw.outbase) if (!jw.outbase)
{ {
return NULL; return NULL;
} }
engine->SetReadWrite(jw.outbase);
jw.outptr = jw.outbase; jw.outptr = jw.outbase;
goto rewind; goto rewind;
} }
engine->SetReadExecute(jw.outbase);
return (SPVM_NATIVE_FUNC)jw.outbase; return (SPVM_NATIVE_FUNC)jw.outbase;
} }
void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func) void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
{ {
engine->ExecFree((void *)func); engine->FreePageMemory((void *)func);
} }
const char *JITX86::GetVMName() const char *JITX86::GetVMName()
@ -2637,7 +2822,7 @@ int JITX86::ContextExecute(sp_context_t *ctx, uint32_t code_idx, cell_t *result)
void JITX86::FreeContext(sp_context_t *ctx) void JITX86::FreeContext(sp_context_t *ctx)
{ {
engine->ExecFree(ctx->codebase); engine->FreePageMemory(ctx->codebase);
delete [] ctx->memory; delete [] ctx->memory;
delete [] ctx->files; delete [] ctx->files;
delete [] ctx->lines; delete [] ctx->lines;
@ -2720,7 +2905,7 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
{ {
CompData *data = (CompData *)co; CompData *data = (CompData *)co;
if (strcmp(key, "debug") == 0) if (strcmp(key, SP_JITCONF_DEBUG) == 0)
{ {
if ((atoi(val) == 1) || !strcmp(val, "yes")) if ((atoi(val) == 1) || !strcmp(val, "yes"))
{ {
@ -2735,6 +2920,18 @@ bool JITX86::SetCompilationOption(ICompilation *co, const char *key, const char
} }
return true; return true;
} }
else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
{
data->profile = atoi(val);
/** Callbacks must be profiled to profile functions! */
if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
{
data->profile |= SP_PROF_CALLBACKS;
}
return true;
}
return false; return false;
} }

View File

@ -67,13 +67,14 @@ class CompData : public ICompilation
{ {
public: public:
CompData() : plugin(NULL), CompData() : plugin(NULL),
debug(false), inline_level(0), rebase(NULL), debug(false), profile(0), inline_level(0), rebase(NULL),
error_set(SP_ERROR_NONE), func_idx(0) error_set(SP_ERROR_NONE), func_idx(0)
{ {
}; };
public: public:
sp_plugin_t *plugin; /* plugin handle */ sp_plugin_t *plugin; /* plugin handle */
bool debug; /* whether to compile debug mode */ bool debug; /* whether to compile debug mode */
int profile; /* profiling flags */
int inline_level; /* inline optimization level */ int inline_level; /* inline optimization level */
jitcode_t rebase; /* relocation map */ jitcode_t rebase; /* relocation map */
int error_set; /* error code to halt process */ int error_set; /* error code to halt process */
@ -121,6 +122,8 @@ public:
cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params); cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params); cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false); jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
#define AMX_REG_PRI REG_EAX #define AMX_REG_PRI REG_EAX