diff --git a/compiler-init/amx.h b/compiler-init/amx.h index 6efdd35e..ca25a0da 100644 --- a/compiler-init/amx.h +++ b/compiler-init/amx.h @@ -34,9 +34,10 @@ #include #endif -#if defined HAVE_STDINT_H +#if defined __GNUC__ #include -#else + #define HAVE_STDINT_H +#elif !defined HAVE_STDINT_H #if defined __LCC__ || defined __DMC__ || defined LINUX || (defined __WATCOMC__ && __WATCOMC__ >= 1200) #if defined HAVE_INTTYPES_H #include @@ -459,4 +460,170 @@ int AMXAPI amx_UTF8Put(char *string, char **endptr, int maxchars, cell value); } #endif +typedef enum { + OP_NONE, /* invalid opcode */ + OP_LOAD_PRI, + OP_LOAD_ALT, + OP_LOAD_S_PRI, + OP_LOAD_S_ALT, + OP_LREF_PRI, + OP_LREF_ALT, + OP_LREF_S_PRI, + OP_LREF_S_ALT, + OP_LOAD_I, + OP_LODB_I, + OP_CONST_PRI, + OP_CONST_ALT, + OP_ADDR_PRI, + OP_ADDR_ALT, + OP_STOR_PRI, + OP_STOR_ALT, + OP_STOR_S_PRI, + OP_STOR_S_ALT, + OP_SREF_PRI, + OP_SREF_ALT, + OP_SREF_S_PRI, + OP_SREF_S_ALT, + OP_STOR_I, + OP_STRB_I, + OP_LIDX, + OP_LIDX_B, + OP_IDXADDR, + OP_IDXADDR_B, + OP_ALIGN_PRI, + OP_ALIGN_ALT, + OP_LCTRL, + OP_SCTRL, + OP_MOVE_PRI, + OP_MOVE_ALT, + OP_XCHG, + OP_PUSH_PRI, + OP_PUSH_ALT, + OP_PUSH_R, + OP_PUSH_C, + OP_PUSH, + OP_PUSH_S, + OP_POP_PRI, + OP_POP_ALT, + OP_STACK, + OP_HEAP, + OP_PROC, + OP_RET, + OP_RETN, + OP_CALL, + OP_CALL_PRI, + OP_JUMP, + OP_JREL, + OP_JZER, + OP_JNZ, + OP_JEQ, + OP_JNEQ, + OP_JLESS, + OP_JLEQ, + OP_JGRTR, + OP_JGEQ, + OP_JSLESS, + OP_JSLEQ, + OP_JSGRTR, + OP_JSGEQ, + OP_SHL, + OP_SHR, + OP_SSHR, + OP_SHL_C_PRI, + OP_SHL_C_ALT, + OP_SHR_C_PRI, + OP_SHR_C_ALT, + OP_SMUL, + OP_SDIV, + OP_SDIV_ALT, + OP_UMUL, + OP_UDIV, + OP_UDIV_ALT, + OP_ADD, + OP_SUB, + OP_SUB_ALT, + OP_AND, + OP_OR, + OP_XOR, + OP_NOT, + OP_NEG, + OP_INVERT, + OP_ADD_C, + OP_SMUL_C, + OP_ZERO_PRI, + OP_ZERO_ALT, + OP_ZERO, + OP_ZERO_S, + OP_SIGN_PRI, + OP_SIGN_ALT, + OP_EQ, + OP_NEQ, + OP_LESS, + OP_LEQ, + OP_GRTR, + OP_GEQ, + OP_SLESS, + OP_SLEQ, + OP_SGRTR, + OP_SGEQ, + OP_EQ_C_PRI, + OP_EQ_C_ALT, + OP_INC_PRI, + OP_INC_ALT, + OP_INC, + OP_INC_S, + OP_INC_I, + OP_DEC_PRI, + OP_DEC_ALT, + OP_DEC, + OP_DEC_S, + OP_DEC_I, + OP_MOVS, + OP_CMPS, + OP_FILL, + OP_HALT, + OP_BOUNDS, + OP_SYSREQ_PRI, + OP_SYSREQ_C, + OP_FILE, /* obsolete */ + OP_LINE, /* obsolete */ + OP_SYMBOL, /* obsolete */ + OP_SRANGE, /* obsolete */ + OP_JUMP_PRI, + OP_SWITCH, + OP_CASETBL, + OP_SWAP_PRI, + OP_SWAP_ALT, + OP_PUSH_ADR, + OP_NOP, + OP_SYSREQ_N, + OP_SYMTAG, /* obsolete */ + OP_BREAK, + OP_PUSH2_C, + OP_PUSH2, + OP_PUSH2_S, + OP_PUSH2_ADR, + OP_PUSH3_C, + OP_PUSH3, + OP_PUSH3_S, + OP_PUSH3_ADR, + OP_PUSH4_C, + OP_PUSH4, + OP_PUSH4_S, + OP_PUSH4_ADR, + OP_PUSH5_C, + OP_PUSH5, + OP_PUSH5_S, + OP_PUSH5_ADR, + OP_LOAD_BOTH, + OP_LOAD_S_BOTH, + OP_CONST, + OP_CONST_S, + /* ----- */ + OP_SYSREQ_D, + OP_SYSREQ_ND, + /* ----- */ + OP_NUM_OPCODES +} OPCODE; + #endif /* AMX_H_INCLUDED */ diff --git a/compiler-init/libpawnc.c b/compiler-init/libpawnc.c index ca42d1a9..c2aa9f27 100644 --- a/compiler-init/libpawnc.c +++ b/compiler-init/libpawnc.c @@ -221,6 +221,8 @@ char *pc_readasm(void *handle, char *string, int maxchars) #endif } +extern memfile_t *bin_file; + /* Should return a pointer, which is used as a "magic cookie" to all I/O * functions; return NULL for failure. */ @@ -234,6 +236,9 @@ void pc_closebin(void *handle,int deletefile) if (deletefile) { memfile_destroy((memfile_t *)handle); + bin_file = NULL; + } else { + bin_file = (memfile_t *)handle; } } diff --git a/compiler-init/osdefs.h b/compiler-init/osdefs.h index 299af953..7a6768c2 100644 --- a/compiler-init/osdefs.h +++ b/compiler-init/osdefs.h @@ -42,6 +42,7 @@ # define access _access # define chdir _chdir # define strdup _strdup +# define unlink _unlink # endif #endif diff --git a/compiler-init/pawncc.c b/compiler-init/pawncc.c index b8234b56..9e834d94 100644 --- a/compiler-init/pawncc.c +++ b/compiler-init/pawncc.c @@ -1,30 +1,389 @@ -/* Pawn compiler driver - * - * Function and variable definition and declaration, statement parser. - * - * Copyright (c) ITB CompuPhase, 2006 - * - * This software is provided "as-is", without any express or implied warranty. - * In no event will the authors be held liable for any damages arising from - * the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software in - * a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - * - * Version: $Id: Sc1.c 3114 2005-03-17 14:48:29Z thiadmer $ - */ -#include "sc.h" +#include +#include +#include +#include +#include "memfile.h" +#include "sp_file.h" +#include "amx.h" +#include "osdefs.h" + +#define NUM_SECTIONS 6 + +int pc_printf(const char *message,...); +int pc_compile(int argc, char **argv); +void sfwrite(const void *buf, size_t size, size_t count, FILE *fp); + +memfile_t *bin_file = NULL; +jmp_buf brkout; int main(int argc, char *argv[]) { - return pc_compile(argc,argv); + if (pc_compile(argc,argv) == 0) + { + FILE *fp; + AMX_HEADER *hdr; + sp_file_hdr_t shdr; + uint32_t curoffs = 0; + uint32_t lastsection = 0; + int err; + uint8_t i8; + uint32_t i; + const char *tables[NUM_SECTIONS] = {".code", ".data", ".publics", ".pubvars", ".natives", ".names"}; + uint32_t offsets[NUM_SECTIONS] = {0,0,0,0,0,0}; + sp_file_section_t sh; + + if (bin_file == NULL) + { + return 0; + } + + hdr = (AMX_HEADER *)bin_file->base; + shdr.version = SPFILE_VERSION; + shdr.magic = SPFILE_MAGIC; + + if ((fp=fopen(bin_file->name, "wb")) == NULL) + { + pc_printf("Error writing to file: %s", bin_file->name); + return 1; + } + + if ((err=setjmp(brkout))!=0) + { + goto write_error; + } + + shdr.sections = NUM_SECTIONS; + shdr.stringtab = sizeof(shdr) + (sizeof(sp_file_section_t) * shdr.sections); + + /** + * write the header + * unwritten values: + * imagesize + */ + sfwrite(&shdr, sizeof(shdr), 1, fp); + + curoffs = shdr.stringtab; + + /** + * write the sections + * unwritten values: + * dataoffs + * size + */ + for (i8=0; i8amx_version; + cod.flags = 0; + if (hdr->flags & AMX_FLAG_DEBUG) + { + cod.flags |= SP_FILE_DEBUG; + } + cod.code = sizeof(cod); + + /* write the code in our newer format */ + cbase = (unsigned char *)hdr + hdr->cod; + real_codesize = hdr->dat - hdr->cod; + tbase = (uint8_t *)malloc(real_codesize); + tptr = tbase; + for (cip = 0; cip < real_codesize;) + { +#define DBGPARAM(v) ( (v)=*(cell *)(cbase+(int)cip), cip+=sizeof(cell) ) + op=(uint8_t) *(ucell *)(cbase+(int)cip); + cip += sizeof(cell); + *tptr++ = op; + switch (op) + { + case OP_PUSH5_C: /* instructions with 5 parameters */ + case OP_PUSH5: + case OP_PUSH5_S: + case OP_PUSH5_ADR: + { + memcpy(tptr, cbase+(int)cip, sizeof(cell)*5); + cip += sizeof(cell)*5; + tptr += sizeof(cell)*5; + break; + } + case OP_PUSH4_C: /* instructions with 4 parameters */ + case OP_PUSH4: + case OP_PUSH4_S: + case OP_PUSH4_ADR: + { + memcpy(tptr, cbase+(int)cip, sizeof(cell)*4); + cip += sizeof(cell)*4; + tptr += sizeof(cell)*4; + break; + } + case OP_PUSH3_C: /* instructions with 3 parameters */ + case OP_PUSH3: + case OP_PUSH3_S: + case OP_PUSH3_ADR: + { + memcpy(tptr, cbase+(int)cip, sizeof(cell)*3); + cip += sizeof(cell)*3; + tptr += sizeof(cell)*3; + break; + } + case OP_PUSH2_C: /* instructions with 2 parameters */ + case OP_PUSH2: + case OP_PUSH2_S: + case OP_PUSH2_ADR: + case OP_LOAD_BOTH: + case OP_LOAD_S_BOTH: + case OP_CONST: + case OP_CONST_S: + case OP_SYSREQ_N: + { + memcpy(tptr, cbase+(int)cip, sizeof(cell)*2); + cip += sizeof(cell)*2; + tptr += sizeof(cell)*2; + break; + } + case OP_LOAD_PRI: /* instructions with 1 parameter */ + case OP_LOAD_ALT: + case OP_LOAD_S_PRI: + case OP_LOAD_S_ALT: + case OP_LREF_PRI: + case OP_LREF_ALT: + case OP_LREF_S_PRI: + case OP_LREF_S_ALT: + case OP_LODB_I: + case OP_CONST_PRI: + case OP_CONST_ALT: + case OP_ADDR_PRI: + case OP_ADDR_ALT: + case OP_STOR_PRI: + case OP_STOR_ALT: + case OP_STOR_S_PRI: + case OP_STOR_S_ALT: + case OP_SREF_PRI: + case OP_SREF_ALT: + case OP_SREF_S_PRI: + case OP_SREF_S_ALT: + case OP_STRB_I: + case OP_LIDX_B: + case OP_IDXADDR_B: + case OP_ALIGN_PRI: + case OP_ALIGN_ALT: + case OP_LCTRL: + case OP_SCTRL: + case OP_PUSH_R: + case OP_PUSH_C: + case OP_PUSH: + case OP_PUSH_S: + case OP_STACK: + case OP_HEAP: + case OP_JREL: + case OP_SHL_C_PRI: + case OP_SHL_C_ALT: + case OP_SHR_C_PRI: + case OP_SHR_C_ALT: + case OP_ADD_C: + case OP_SMUL_C: + case OP_ZERO: + case OP_ZERO_S: + case OP_EQ_C_PRI: + case OP_EQ_C_ALT: + case OP_INC: + case OP_INC_S: + case OP_DEC: + case OP_DEC_S: + case OP_MOVS: + case OP_CMPS: + case OP_FILL: + case OP_HALT: + case OP_BOUNDS: + case OP_PUSH_ADR: + case OP_CALL: /* opcodes that need relocation */ + case OP_JUMP: + case OP_JZER: + case OP_JNZ: + case OP_JEQ: + case OP_JNEQ: + case OP_JLESS: + case OP_JLEQ: + case OP_JGRTR: + case OP_JGEQ: + case OP_JSLESS: + case OP_JSLEQ: + case OP_JSGRTR: + case OP_JSGEQ: + case OP_SWITCH: + case OP_SYSREQ_C: + { + *(cell *)tptr = *(cell *)(cbase + (int)cip); + cip += sizeof(cell); + tptr += sizeof(cell); + break; + } + case OP_LOAD_I: /* instructions without parameters */ + case OP_STOR_I: + case OP_LIDX: + case OP_IDXADDR: + case OP_MOVE_PRI: + case OP_MOVE_ALT: + case OP_XCHG: + case OP_PUSH_PRI: + case OP_PUSH_ALT: + case OP_POP_PRI: + case OP_POP_ALT: + case OP_PROC: + case OP_RET: + case OP_RETN: + case OP_CALL_PRI: + case OP_SHL: + case OP_SHR: + case OP_SSHR: + case OP_SMUL: + case OP_SDIV: + case OP_SDIV_ALT: + case OP_UMUL: + case OP_UDIV: + case OP_UDIV_ALT: + case OP_ADD: + case OP_SUB: + case OP_SUB_ALT: + case OP_AND: + case OP_OR: + case OP_XOR: + case OP_NOT: + case OP_NEG: + case OP_INVERT: + case OP_ZERO_PRI: + case OP_ZERO_ALT: + case OP_SIGN_PRI: + case OP_SIGN_ALT: + case OP_EQ: + case OP_NEQ: + case OP_LESS: + case OP_LEQ: + case OP_GRTR: + case OP_GEQ: + case OP_SLESS: + case OP_SLEQ: + case OP_SGRTR: + case OP_SGEQ: + case OP_INC_PRI: + case OP_INC_ALT: + case OP_INC_I: + case OP_DEC_PRI: + case OP_DEC_ALT: + case OP_DEC_I: + case OP_SYSREQ_PRI: + case OP_JUMP_PRI: + case OP_SWAP_PRI: + case OP_SWAP_ALT: + case OP_NOP: + case OP_BREAK: + break; + case OP_CASETBL: + { + cell num; + int i; + DBGPARAM(*(cell *)tptr); + num = *(cell *)tptr; + tptr += sizeof(cell); + memcpy(tptr, cbase+(int)cip, (2*num+1)*sizeof(cell)); + tptr += (2*num+1) * sizeof(cell); + cip += (2*num+1) * sizeof(cell); + break; + } + default: + { + assert(0); + } +#undef DBGPARAM + } + } + cod.codesize = (uint32_t)(tptr - tbase); + sfwrite(&cod, sizeof(cod), 1, fp); + sfwrite(tbase, cod.codesize, 1, fp); + free(tbase); + + /* backtrack and write this section's header info */ + curoffs = (uint32_t)ftell(fp); + fseek(fp, offsets[0], SEEK_SET); + sfwrite(&lastsection, sizeof(lastsection), 1, fp); + cod.codesize += sizeof(cod); + sfwrite(&cod.codesize, sizeof(cod.codesize), 1, fp); + fseek(fp, curoffs, SEEK_SET); + lastsection = curoffs; + } + + if (strcmp(tables[1], ".data") == 0) + { + sp_file_data_t dat; + unsigned char *dbase; + + dat.datasize = hdr->hea - hdr->dat; + dat.memsize = hdr->stp; + dat.data = sizeof(dat); + dbase = (unsigned char *)hdr + hdr->dat; + + sfwrite(&dat, sizeof(dat), 1, fp); + if (dat.datasize) + { + sfwrite(dbase, dat.datasize, 1, fp); + } + + /* backtrack and write this section's header info */ + curoffs = ftell(fp); + fseek(fp, offsets[1], SEEK_SET); + sfwrite(&lastsection, sizeof(lastsection), 1, fp); + dat.datasize += sizeof(dat); + sfwrite(&dat.datasize, sizeof(dat.datasize),1, fp); + fseek(fp, curoffs, SEEK_SET); + lastsection = curoffs; + } + + fclose(fp); + + return 0; + +write_error: + pc_printf("Error writing to file: %s", bin_file->name); + unlink(bin_file->name); + fclose(fp); + + return 1; + } + + return 1; +} + +void sfwrite(const void *buf, size_t size, size_t count, FILE *fp) +{ + if (fwrite(buf, size, count, fp) != count) + { + longjmp(brkout, 1); + } } diff --git a/compiler-init/sc1.c b/compiler-init/sc1.c index 95913675..5ba72230 100644 --- a/compiler-init/sc1.c +++ b/compiler-init/sc1.c @@ -629,14 +629,10 @@ static void initglobals(void) warnnum=0; /* number of warnings */ optproccall=FALSE; /* sourcemod: do not support "procedure call" */ verbosity=1; /* verbosity level, no copyright banner */ - sc_debug=sSYMBOLIC; /* sourcemod: full debug stuff */ - pc_optimize=sOPTIMIZE_DEFAULT; /* sourcemod: full optimization */ + sc_debug=sCHKBOUNDS|sSYMBOLIC; /* sourcemod: full debug stuff */ + pc_optimize=sOPTIMIZE_DEFAULT; /* sourcemod: full optimization */ sc_packstr=FALSE; /* strings are unpacked by default */ - #if AMX_COMPACTMARGIN > 2 - sc_compress=TRUE; /* compress output bytecodes */ - #else - sc_compress=FALSE; - #endif + sc_compress=FALSE; /* always disable compact encoding! */ sc_needsemicolon=FALSE;/* semicolon required to terminate expressions? */ sc_dataalign=sizeof(cell); pc_stksize=sDEF_AMXSTACK;/* default stack size */ @@ -1132,7 +1128,7 @@ static void about(void) pc_printf("Options:\n"); pc_printf(" -A alignment in bytes of the data segment and the stack\n"); pc_printf(" -a output assembler code\n"); -#if AMX_COMPACTMARGIN > 2 +#if 0 /* not toggleable in SourceMod */ pc_printf(" -C[+/-] compact encoding for output file (default=%c)\n", sc_compress ? '+' : '-'); #endif pc_printf(" -c codepage name or number; e.g. 1252 for Windows Latin-1\n"); diff --git a/compiler-init/sc2.c b/compiler-init/sc2.c index 1a822f5f..5cc1735f 100644 --- a/compiler-init/sc2.c +++ b/compiler-init/sc2.c @@ -1076,10 +1076,12 @@ static int command(void) if (find_constval(&libname_tab,name,0)==NULL) curlibrary=append_constval(&libname_tab,name,0,0); } /* if */ +#if 0 /* more unused */ } else if (strcmp(str,"pack")==0) { cell val; preproc_expr(&val,NULL); /* default = packed/unpacked */ sc_packstr=(int)val; +#endif } else if (strcmp(str,"rational")==0) { char name[sNAMEMAX+1]; cell digits=0; diff --git a/compiler-init/sc6.c b/compiler-init/sc6.c index 9dd5a169..2ea5f2d4 100644 --- a/compiler-init/sc6.c +++ b/compiler-init/sc6.c @@ -47,7 +47,7 @@ typedef struct { char *name; int segment; /* sIN_CSEG=parse in cseg, sIN_DSEG=parse in dseg */ OPCODE_PROC func; -} OPCODE; +} OPCODEC; static cell codeindex; /* similar to "code_idx" */ static cell *lbltab; /* label table */ @@ -454,7 +454,7 @@ static cell do_case(FILE *fbin,char *params,cell opcode) return opcodes(0)+opargs(2); } -static OPCODE opcodelist[] = { +static OPCODEC opcodelist[] = { /* node for "invalid instruction" */ { 0, NULL, 0, noop }, /* opcodes in sorted order */ diff --git a/compiler-init/sp_file.h b/compiler-init/sp_file.h new file mode 100644 index 00000000..bd777ad0 --- /dev/null +++ b/compiler-init/sp_file.h @@ -0,0 +1,102 @@ +#ifndef _INCLUDE_SPFILE_H +#define _INCLUDE_SPFILE_H + +#include +#if defined __GNUC__ || defined HAVE_STDINT_ +#include +#else + #if !defined HAVE_STDINT_H + typedef unsigned __int64 uint64_t; + typedef __int64 int64_t; + typedef unsigned __int32 uint32_t; + typedef __int32 int32_t; + typedef unsigned __int16 uint16_t; + typedef __int16 int16_t; + typedef unsigned __int8 uint8_t; + typedef __int8 int8_t; + #define HAVE_STDINT_H + #endif +#endif + +#define SPFILE_MAGIC 0xDEADC0D3 +#define SPFILE_VERSION 0x0100 + +//:TODO: better compiler/nix support +#if defined __linux__ + #pragma pack(1) /* structures must be packed (byte-aligned) */ +#else + #pragma pack(push) + #pragma pack(1) /* structures must be packed (byte-aligned) */ +#endif + +typedef struct sp_file_section_s +{ + uint32_t nameoffs; /* rel offset into global string table */ + uint32_t dataoffs; + uint32_t size; +} sp_file_section_t; + +typedef struct sp_file_hdr_s +{ + uint32_t magic; + uint16_t version; + uint32_t imagesize; + uint8_t sections; + uint32_t stringtab; +} sp_file_hdr_t; + +typedef enum +{ + SP_FILE_NONE = 0, + SP_FILE_DEBUG = 1, +} sp_file_flags_t; + +/* section is ".code" */ +typedef struct sp_file_code_s +{ + uint32_t codesize; /* codesize in bytes */ + uint8_t cellsize; /* cellsize in bytes */ + uint8_t codeversion; /* version of opcodes supported */ + uint16_t flags; /* flags */ + uint32_t code; /* rel offset to code */ +} sp_file_code_t; + +/* section is .data */ +typedef struct sp_file_data_s +{ + uint32_t datasize; /* size of data section */ + uint32_t memsize; /* total mem required (includes data) */ + uint32_t data; /* file offset to data (helper) */ +} sp_file_data_t; + +/* section is .publics */ +typedef struct sp_file_publics_s +{ + uint32_t address; /* address rel to code section */ + uint32_t name; /* index into nametable */ +} sp_file_publics_t; + +/* section is .natives */ +typedef struct sp_file_natives_s +{ + uint32_t name; /* name of native at index */ +} sp_file_natives_t; + +/* section is .pubvars */ +typedef struct sp_file_pubvars_s +{ + uint32_t address; /* address rel to dat section */ + uint32_t name; /* index into nametable */ +} sp_file_pubvars_t; + +#if defined __linux__ + #pragma pack() /* reset default packing */ +#else + #pragma pack(pop) /* reset previous packing */ +#endif + + +/* section is .names */ +typedef char * sp_file_nametab_t; + +#endif //_INCLUDE_SPFILE_H diff --git a/compiler-init/spcomp.vcproj b/compiler-init/spcomp.vcproj index 092d3a57..9653b567 100644 --- a/compiler-init/spcomp.vcproj +++ b/compiler-init/spcomp.vcproj @@ -250,6 +250,10 @@ RelativePath=".\scvars.c" > + + + +