1.1 --- a/sourcepawn/compiler/Makefile Tue Mar 04 23:18:16 2008 +0000
1.2 +++ b/sourcepawn/compiler/Makefile Thu Mar 13 17:04:25 2008 +0000
1.3 @@ -36,7 +36,7 @@
1.4 CPPFLAGS += $(OPT_CPP_FLAGS)
1.5 endif
1.6
1.7 -CFLAGS += -DLINUX -DNDEBUG -DHAVE_STDINT_H -DAMX_ANSIONLY -DENABLE_BINRELOC
1.8 +CFLAGS += -DLINUX -DNDEBUG -DHAVE_STDINT_H -DAMX_ANSIONLY -DENABLE_BINRELOC -m32
1.9 CPPFLAGS += -Wno-deprecated -fno-exceptions -fno-rtti
1.10
1.11 OBJ_LINUX := $(OBJECTS:%.cpp=$(BIN_DIR)/%.o)
1.12 @@ -53,7 +53,7 @@
1.13 $(MAKE) spcomp
1.14
1.15 spcomp: $(OBJ_LINUX)
1.16 - $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -ldl -lm -o$(BIN_DIR)/$(BINARY)
1.17 + $(CPP) $(INCLUDE) $(CFLAGS) $(CPPFLAGS) $(OBJ_LINUX) $(LINK) -m32 -ldl -lm -o$(BIN_DIR)/$(BINARY)
1.18
1.19 debug:
1.20 $(MAKE) all DEBUG=true
2.1 --- a/sourcepawn/compiler/sc1.c Tue Mar 04 23:18:16 2008 +0000
2.2 +++ b/sourcepawn/compiler/sc1.c Thu Mar 13 17:04:25 2008 +0000
2.3 @@ -4136,6 +4136,8 @@
2.4 /* "declargs()" found the ")"; if a ";" appears after this, it was a
2.5 * prototype */
2.6 if (matchtoken(';')) {
2.7 + if (sym->usage & uPUBLIC)
2.8 + error(10);
2.9 sym->usage|=uFORWARD;
2.10 if (!sc_needsemicolon)
2.11 error(10); /* old style prototypes used with optional semicolumns */
3.1 --- a/sourcepawn/compiler/sc3.c Tue Mar 04 23:18:16 2008 +0000
3.2 +++ b/sourcepawn/compiler/sc3.c Thu Mar 13 17:04:25 2008 +0000
3.3 @@ -1207,7 +1207,7 @@
3.4 } /* if */
3.5 } /* if */
3.6 if (lval3.sym->dim.array.level!=level)
3.7 - return error(48); /* array dimensions must match */
3.8 + return error(47); /* array dimensions must match */
3.9 else if (ltlength<val || exactmatch && ltlength>val || val==0)
3.10 return error(47); /* array sizes must match */
3.11 else if (lval3.ident!=iARRAYCELL && !matchtag(lval3.sym->x.tags.index,idxtag,TRUE))
3.12 @@ -1217,6 +1217,7 @@
3.13 symbol *sym1 = lval3.sym;
3.14 symbol *sym2 = lval2.sym;
3.15 int i;
3.16 + error(23);
3.17 assert(sym1!=NULL && sym2!=NULL);
3.18 /* ^^^ sym2 must be valid, because only variables can be
3.19 * multi-dimensional (there are no multi-dimensional literals),
3.20 @@ -1328,7 +1329,9 @@
3.21 array1= (lval->ident==iARRAY || lval->ident==iREFARRAY);
3.22 array2= (lval2.ident==iARRAY || lval2.ident==iREFARRAY);
3.23 if (array1 && !array2) {
3.24 - char *ptr=(lval->sym->name!=NULL) ? lval->sym->name : "-unknown-";
3.25 + const char *ptr = "-unknown-";
3.26 + if (lval->sym != NULL && lval->sym->name != NULL)
3.27 + ptr = lval->sym->name;
3.28 error(33,ptr); /* array must be indexed */
3.29 } else if (!array1 && array2) {
3.30 char *ptr=(lval2.sym->name!=NULL) ? lval2.sym->name : "-unknown-";
3.31 @@ -1569,7 +1572,7 @@
3.32 if (level>sym->dim.array.level+1) {
3.33 error(28,sym->name); /* invalid subscript */
3.34 } else if (level==sym->dim.array.level+1) {
3.35 - lval->constval= (idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1;
3.36 + lval->constval=(idxsym!=NULL && idxsym->dim.array.length>0) ? idxsym->dim.array.length : 1;
3.37 } else {
3.38 lval->constval=array_levelsize(sym,level);
3.39 }
3.40 @@ -2365,7 +2368,7 @@
3.41 */
3.42 } else {
3.43 arglist[argpos]=ARG_DONE; /* flag argument as "present" */
3.44 - if (arg[argidx].numtags==1) /* set the expected tag, if any */
3.45 + if (arg[argidx].ident!=0 && arg[argidx].numtags==1) /* set the expected tag, if any */
3.46 lval.cmptag=arg[argidx].tags[0];
3.47 lvalue=hier14(&lval);
3.48 assert(sc_status==statFIRST || arg[argidx].tags!=NULL);
4.1 --- a/sourcepawn/jit/x86/Makefile Tue Mar 04 23:18:16 2008 +0000
4.2 +++ b/sourcepawn/jit/x86/Makefile Thu Mar 13 17:04:25 2008 +0000
4.3 @@ -32,7 +32,10 @@
4.4
4.5 GCC_VERSION := $(shell $(CPP) -dumpversion >&1 | cut -b1)
4.6
4.7 -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
4.8 +CFLAGS += -D_LINUX -DNDEBUG -Dstricmp=strcasecmp -D_stricmp=strcasecmp -D_strnicmp=strncasecmp \
4.9 + -Dstrnicmp=strncasecmp -D_snprintf=snprintf -D_vsnprintf=vsnprintf -D_alloca=alloca \
4.10 + -Dstrcmpi=strcasecmp -Wall -Wno-non-virtual-dtor -Werror -fno-exceptions -fno-rtti \
4.11 + -DHAVE_STDINT_H -m32
4.12
4.13 ifeq "$(GCC_VERSION)" "4"
4.14 CFLAGS += $(GCC4_FLAGS)
4.15 @@ -52,7 +55,7 @@
4.16 ln -sf $(BIN_DIR)/$(BINARY) $(BINARY)
4.17
4.18 binary: $(OBJ_LINUX)
4.19 - $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
4.20 + $(CPP) $(INCLUDE) $(CFLAGS) $(OBJ_LINUX) $(LINK) -m32 -shared -ldl -lm -o$(BIN_DIR)/$(BINARY)
4.21
4.22 debug:
4.23 $(MAKE) all DEBUG=true
5.1 --- a/sourcepawn/jit/x86/dll_exports.cpp Tue Mar 04 23:18:16 2008 +0000
5.2 +++ b/sourcepawn/jit/x86/dll_exports.cpp Thu Mar 13 17:04:25 2008 +0000
5.3 @@ -25,7 +25,7 @@
5.4 {
5.5 engine = engine_p;
5.6
5.7 - if (api_version > SOURCEPAWN_ENGINE_API_VERSION)
5.8 + if (api_version > SOURCEPAWN_ENGINE_API_VERSION || api_version < 2)
5.9 {
5.10 return SP_ERROR_PARAM;
5.11 }
6.1 --- a/sourcepawn/jit/x86/jit_x86.cpp Tue Mar 04 23:18:16 2008 +0000
6.2 +++ b/sourcepawn/jit/x86/jit_x86.cpp Thu Mar 13 17:04:25 2008 +0000
6.3 @@ -1278,12 +1278,99 @@
6.4 IA32_Return(jit);
6.5 }
6.6
6.7 +void ProfCallGate_Begin(sp_context_t *ctx, const char *name)
6.8 +{
6.9 + ctx->profiler->OnFunctionBegin(ctx->context, name);
6.10 +}
6.11 +
6.12 +void ProfCallGate_End(sp_context_t *ctx)
6.13 +{
6.14 + ctx->profiler->OnFunctionEnd();
6.15 +}
6.16 +
6.17 +const char *find_func_name(sp_plugin_t *plugin, uint32_t offs)
6.18 +{
6.19 + uint32_t max, iter;
6.20 + sp_fdbg_symbol_t *sym;
6.21 + sp_fdbg_arraydim_t *arr;
6.22 + uint8_t *cursor = (uint8_t *)(plugin->debug.symbols);
6.23 +
6.24 + max = plugin->debug.syms_num;
6.25 + for (iter = 0; iter < max; iter++)
6.26 + {
6.27 + sym = (sp_fdbg_symbol_t *)cursor;
6.28 +
6.29 + if (sym->ident == SP_SYM_FUNCTION
6.30 + && sym->codestart <= offs
6.31 + && sym->codeend > offs)
6.32 + {
6.33 + return plugin->debug.stringbase + sym->name;
6.34 + }
6.35 +
6.36 + if (sym->dimcount > 0)
6.37 + {
6.38 + cursor += sizeof(sp_fdbg_symbol_t);
6.39 + arr = (sp_fdbg_arraydim_t *)cursor;
6.40 + cursor += sizeof(sp_fdbg_arraydim_t) * sym->dimcount;
6.41 + continue;
6.42 + }
6.43 +
6.44 + cursor += sizeof(sp_fdbg_symbol_t);
6.45 + }
6.46 +
6.47 + return NULL;
6.48 +}
6.49 +
6.50 inline void WriteOp_Call(JitWriter *jit)
6.51 {
6.52 - cell_t offs = jit->read_cell();
6.53 -
6.54 - jitoffs_t jmp = IA32_Call_Imm32(jit, 0);
6.55 - IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
6.56 + cell_t offs;
6.57 + jitoffs_t jmp;
6.58 + CompData *data;
6.59 +
6.60 + data = (CompData *)jit->data;
6.61 + offs = jit->read_cell();
6.62 +
6.63 + if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
6.64 + {
6.65 + const char *name;
6.66 +
6.67 + /* Find the function name */
6.68 + if ((name = find_func_name(data->plugin, offs)) == NULL)
6.69 + {
6.70 + name = "unknown";
6.71 + }
6.72 +
6.73 + //push name
6.74 + //push [esi+context]
6.75 + //call ProfCallGate_Begin
6.76 + //add esp, 8
6.77 + IA32_Push_Imm32(jit, (jit_int32_t)(intptr_t)name);
6.78 + IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
6.79 + jmp = IA32_Call_Imm32(jit, 0);
6.80 + IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_Begin);
6.81 + IA32_Add_Rm_Imm8(jit, REG_ESP, 8, MOD_REG);
6.82 +
6.83 + //call <addr>
6.84 + //push eax
6.85 + jmp = IA32_Call_Imm32(jit, 0);
6.86 + IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
6.87 + IA32_Push_Reg(jit, REG_EAX);
6.88 +
6.89 + //push [esi+context]
6.90 + //call ProfCallGate_End
6.91 + //add esp, 4
6.92 + //pop eax
6.93 + IA32_Push_Rm_Disp8(jit, AMX_REG_INFO, AMX_INFO_CONTEXT);
6.94 + jmp = IA32_Call_Imm32(jit, 0);
6.95 + IA32_Write_Jump32_Abs(jit, jmp, (void *)ProfCallGate_End);
6.96 + IA32_Add_Rm_Imm8(jit, REG_ESP, 4, MOD_REG);
6.97 + IA32_Pop_Reg(jit, REG_EAX);
6.98 + }
6.99 + else
6.100 + {
6.101 + jmp = IA32_Call_Imm32(jit, 0);
6.102 + IA32_Write_Jump32(jit, jmp, RelocLookup(jit, offs, false));
6.103 + }
6.104 }
6.105
6.106 inline void WriteOp_Bounds(JitWriter *jit)
6.107 @@ -1653,9 +1740,25 @@
6.108 jitoffs_t call = IA32_Call_Imm32(jit, 0);
6.109 if (!data->debug)
6.110 {
6.111 - IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
6.112 - } else {
6.113 - IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
6.114 + if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
6.115 + {
6.116 + IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Profile);
6.117 + }
6.118 + else
6.119 + {
6.120 + IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback);
6.121 + }
6.122 + }
6.123 + else
6.124 + {
6.125 + if ((data->profile & SP_PROF_NATIVES) == SP_PROF_NATIVES)
6.126 + {
6.127 + IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug_Profile);
6.128 + }
6.129 + else
6.130 + {
6.131 + IA32_Write_Jump32_Abs(jit, call, (void *)NativeCallback_Debug);
6.132 + }
6.133 }
6.134
6.135 /* check for errors */
6.136 @@ -2122,7 +2225,9 @@
6.137
6.138 cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
6.139 {
6.140 - sp_native_t *native = &ctx->natives[native_idx];
6.141 + sp_native_t *native;
6.142 +
6.143 + native = &ctx->natives[native_idx];
6.144
6.145 ctx->n_idx = native_idx;
6.146
6.147 @@ -2136,12 +2241,27 @@
6.148 return native->pfn(ctx->context, params);
6.149 }
6.150
6.151 -static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
6.152 +cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
6.153 {
6.154 - sp_context_t *ctx = pCtx->GetContext();
6.155 - ctx->n_err = SP_ERROR_INVALID_NATIVE;
6.156 -
6.157 - return 0;
6.158 + cell_t val;
6.159 + sp_native_t *native;
6.160 +
6.161 + native = &ctx->natives[native_idx];
6.162 +
6.163 + ctx->n_idx = native_idx;
6.164 +
6.165 + /* Technically both aren't needed, I guess */
6.166 + if (native->status == SP_NATIVE_UNBOUND)
6.167 + {
6.168 + ctx->n_err = SP_ERROR_INVALID_NATIVE;
6.169 + return 0;
6.170 + }
6.171 +
6.172 + ctx->profiler->OnNativeBegin(ctx->context, native);
6.173 + val = native->pfn(ctx->context, params);
6.174 + ctx->profiler->OnNativeEnd();
6.175 +
6.176 + return val;
6.177 }
6.178
6.179 cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
6.180 @@ -2170,7 +2290,7 @@
6.181 }
6.182
6.183 cell_t result = NativeCallback(ctx, native_idx, params);
6.184 -
6.185 +
6.186 if (ctx->n_err != SP_ERROR_NONE)
6.187 {
6.188 return result;
6.189 @@ -2180,7 +2300,9 @@
6.190 {
6.191 ctx->n_err = SP_ERROR_STACKLEAK;
6.192 return result;
6.193 - } else if (save_hp != ctx->hp) {
6.194 + }
6.195 + else if (save_hp != ctx->hp)
6.196 + {
6.197 ctx->n_err = SP_ERROR_HEAPLEAK;
6.198 return result;
6.199 }
6.200 @@ -2188,6 +2310,60 @@
6.201 return result;
6.202 }
6.203
6.204 +cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params)
6.205 +{
6.206 + cell_t save_sp = ctx->sp;
6.207 + cell_t save_hp = ctx->hp;
6.208 +
6.209 + ctx->n_idx = native_idx;
6.210 +
6.211 + if (ctx->hp < ctx->heap_base)
6.212 + {
6.213 + ctx->n_err = SP_ERROR_HEAPMIN;
6.214 + return 0;
6.215 + }
6.216 +
6.217 + if (ctx->hp + STACK_MARGIN > ctx->sp)
6.218 + {
6.219 + ctx->n_err = SP_ERROR_STACKLOW;
6.220 + return 0;
6.221 + }
6.222 +
6.223 + if ((uint32_t)ctx->sp >= ctx->mem_size)
6.224 + {
6.225 + ctx->n_err = SP_ERROR_STACKMIN;
6.226 + return 0;
6.227 + }
6.228 +
6.229 + cell_t result = NativeCallback_Profile(ctx, native_idx, params);
6.230 +
6.231 + if (ctx->n_err != SP_ERROR_NONE)
6.232 + {
6.233 + return result;
6.234 + }
6.235 +
6.236 + if (save_sp != ctx->sp)
6.237 + {
6.238 + ctx->n_err = SP_ERROR_STACKLEAK;
6.239 + return result;
6.240 + }
6.241 + else if (save_hp != ctx->hp)
6.242 + {
6.243 + ctx->n_err = SP_ERROR_HEAPLEAK;
6.244 + return result;
6.245 + }
6.246 +
6.247 + return result;
6.248 +}
6.249 +
6.250 +static cell_t InvalidNative(IPluginContext *pCtx, const cell_t *params)
6.251 +{
6.252 + sp_context_t *ctx = pCtx->GetContext();
6.253 + ctx->n_err = SP_ERROR_INVALID_NATIVE;
6.254 +
6.255 + return 0;
6.256 +}
6.257 +
6.258 jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative)
6.259 {
6.260 if (jit->outptr)
6.261 @@ -2204,7 +2380,9 @@
6.262 assert(pcode_offs >= 0 && (uint32_t)pcode_offs <= data->codesize);
6.263 /* Do the lookup in the native dictionary. */
6.264 return *(jitoffs_t *)(data->rebase + pcode_offs);
6.265 - } else {
6.266 + }
6.267 + else
6.268 + {
6.269 return 0;
6.270 }
6.271 }
6.272 @@ -2380,7 +2558,8 @@
6.273
6.274 /* the total codesize is now known! */
6.275 codemem = writer.get_outputpos();
6.276 - writer.outbase = (jitcode_t)engine->ExecAlloc(codemem);
6.277 + writer.outbase = (jitcode_t)engine->AllocatePageMemory(codemem);
6.278 + engine->SetReadWrite(writer.outbase);
6.279 writer.outptr = writer.outbase;
6.280 /* go back for third pass */
6.281 goto jit_rewind;
6.282 @@ -2398,6 +2577,8 @@
6.283 }
6.284 /* Write these last because error jumps should be unpredicted, and thus forward */
6.285 WriteErrorRoutines(data, jit);
6.286 +
6.287 + engine->SetReadExecute(writer.outbase);
6.288 }
6.289
6.290 /*************
6.291 @@ -2420,6 +2601,7 @@
6.292 ctx->heap_base = plugin->data_size;
6.293 ctx->hp = ctx->heap_base;
6.294 ctx->sp = ctx->mem_size - sizeof(cell_t);
6.295 + ctx->prof_flags = data->profile;
6.296
6.297 const char *strbase = plugin->info.stringbase;
6.298 uint32_t max, iter;
6.299 @@ -2605,22 +2787,25 @@
6.300 if (jw.outbase == NULL)
6.301 {
6.302 /* Second pass: Actually write */
6.303 - jw.outbase = (jitcode_t)engine->ExecAlloc(jw.get_outputpos());
6.304 + jw.outbase = (jitcode_t)engine->AllocatePageMemory(jw.get_outputpos());
6.305 if (!jw.outbase)
6.306 {
6.307 return NULL;
6.308 }
6.309 + engine->SetReadWrite(jw.outbase);
6.310 jw.outptr = jw.outbase;
6.311
6.312 goto rewind;
6.313 }
6.314 -
6.315 +
6.316 + engine->SetReadExecute(jw.outbase);
6.317 +
6.318 return (SPVM_NATIVE_FUNC)jw.outbase;
6.319 }
6.320
6.321 void JITX86::DestroyFakeNative(SPVM_NATIVE_FUNC func)
6.322 {
6.323 - engine->ExecFree((void *)func);
6.324 + engine->FreePageMemory((void *)func);
6.325 }
6.326
6.327 const char *JITX86::GetVMName()
6.328 @@ -2637,7 +2822,7 @@
6.329
6.330 void JITX86::FreeContext(sp_context_t *ctx)
6.331 {
6.332 - engine->ExecFree(ctx->codebase);
6.333 + engine->FreePageMemory(ctx->codebase);
6.334 delete [] ctx->memory;
6.335 delete [] ctx->files;
6.336 delete [] ctx->lines;
6.337 @@ -2720,7 +2905,7 @@
6.338 {
6.339 CompData *data = (CompData *)co;
6.340
6.341 - if (strcmp(key, "debug") == 0)
6.342 + if (strcmp(key, SP_JITCONF_DEBUG) == 0)
6.343 {
6.344 if ((atoi(val) == 1) || !strcmp(val, "yes"))
6.345 {
6.346 @@ -2735,6 +2920,18 @@
6.347 }
6.348 return true;
6.349 }
6.350 + else if (strcmp(key, SP_JITCONF_PROFILE) == 0)
6.351 + {
6.352 + data->profile = atoi(val);
6.353 +
6.354 + /** Callbacks must be profiled to profile functions! */
6.355 + if ((data->profile & SP_PROF_FUNCTIONS) == SP_PROF_FUNCTIONS)
6.356 + {
6.357 + data->profile |= SP_PROF_CALLBACKS;
6.358 + }
6.359 +
6.360 + return true;
6.361 + }
6.362
6.363 return false;
6.364 }
7.1 --- a/sourcepawn/jit/x86/jit_x86.h Tue Mar 04 23:18:16 2008 +0000
7.2 +++ b/sourcepawn/jit/x86/jit_x86.h Thu Mar 13 17:04:25 2008 +0000
7.3 @@ -67,13 +67,14 @@
7.4 {
7.5 public:
7.6 CompData() : plugin(NULL),
7.7 - debug(false), inline_level(0), rebase(NULL),
7.8 + debug(false), profile(0), inline_level(0), rebase(NULL),
7.9 error_set(SP_ERROR_NONE), func_idx(0)
7.10 {
7.11 };
7.12 public:
7.13 sp_plugin_t *plugin; /* plugin handle */
7.14 bool debug; /* whether to compile debug mode */
7.15 + int profile; /* profiling flags */
7.16 int inline_level; /* inline optimization level */
7.17 jitcode_t rebase; /* relocation map */
7.18 int error_set; /* error code to halt process */
7.19 @@ -121,6 +122,8 @@
7.20
7.21 cell_t NativeCallback(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
7.22 cell_t NativeCallback_Debug(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
7.23 +cell_t NativeCallback_Debug_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
7.24 +cell_t NativeCallback_Profile(sp_context_t *ctx, ucell_t native_idx, cell_t *params);
7.25 jitoffs_t RelocLookup(JitWriter *jit, cell_t pcode_offs, bool relative=false);
7.26
7.27 #define AMX_REG_PRI REG_EAX