SpiderScript - Moved header to directory, ready to remove from tree
[tpg/acess2.git] / Usermode / Libraries / libspiderscript.so_src / bytecode_gen.c
index c718265..aad172d 100644 (file)
 // === STRUCTURES ===
 
 // === PROTOTYPES ===
-tBC_Op *Bytecode_int_AllocateOp(int Operation);
+tBC_Op *Bytecode_int_AllocateOp(int Operation, int ExtraBytes);
  int   Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name);
 
 // === GLOBALS ===
 
 // === CODE ===
-tBC_Op *Bytecode_int_AllocateOp(int Operation)
+tBC_Op *Bytecode_int_AllocateOp(int Operation, int ExtraBytes)
 {
        tBC_Op  *ret;
 
-       ret = malloc(sizeof(tBC_Op));
+       ret = malloc(sizeof(tBC_Op) + ExtraBytes);
        if(!ret)        return NULL;
 
        ret->Next = NULL;
        ret->Operation = Operation;
        ret->bUseInteger = 0;
+       ret->bUseString = (ExtraBytes > 0);
+       ret->CacheEnt = NULL;
 
        return ret;
 }
@@ -134,11 +136,49 @@ int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *Labe
                }
                len += 4;
        }
-       
+
+       void _put_index(uint32_t value)
+       {
+               if( !Output && !value ) {
+                       len += 5;
+                       return ;
+               }
+               if( value < 0x8000 ) {
+                       _put_byte(value >> 8);
+                       _put_byte(value & 0xFF);
+               }
+               else if( value < 0x400000 ) {
+                       _put_byte( (value >> 16) | 0x80 );
+                       _put_byte(value >> 8);
+                       _put_byte(value & 0xFF);
+               }
+               else {
+                       _put_byte( 0xC0 );
+                       _put_byte(value >> 24);
+                       _put_byte(value >> 16);
+                       _put_byte(value >> 8 );
+                       _put_byte(value & 0xFF);
+               }
+       }       
+
        void _put_qword(uint64_t value)
        {
-               _put_dword(value & 0xFFFFFFFF);
-               _put_dword(value >> 32);
+               if( value < 0x80 ) {    // 7 bits into 1 byte
+                       _put_byte(value);
+               }
+               else if( !(value >> (8+6)) ) {  // 14 bits packed into 2 bytes
+                       _put_byte( 0x80 | ((value >> 8) & 0x3F) );
+                       _put_byte( value & 0xFF );
+               }
+               else if( !(value >> (32+5)) ) { // 37 bits into 5 bytes
+                       _put_byte( 0xC0 | ((value >> 32) & 0x1F) );
+                       _put_dword(value & 0xFFFFFFFF);
+               }
+               else {
+                       _put_byte( 0xE0 );      // 64 (actually 68) bits into 9 bytes
+                       _put_dword(value & 0xFFFFFFFF);
+                       _put_dword(value >> 32);
+               }
        }
 
        void _put_double(double value)
@@ -158,7 +198,7 @@ int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *Labe
                }
        
                // TODO: Relocations    
-               _put_dword(strIdx);
+               _put_index(strIdx);
        }
 
        for( op = Function->Operations; op; op = op->Next, idx ++ )
@@ -183,7 +223,7 @@ int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *Labe
                case BC_OP_JUMPIF:
                case BC_OP_JUMPIFNOT:
                        // TODO: Relocations?
-                       _put_dword( LabelOffsets[op->Content.StringInt.Integer] );
+                       _put_index( LabelOffsets[op->Content.StringInt.Integer] );
                        break;
                // Special case for inline values
                case BC_OP_LOADINT:
@@ -197,10 +237,10 @@ int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *Labe
                        break;
                // Everthing else just gets handled nicely
                default:
-                       if( op->Content.StringInt.String )
+                       if( op->bUseString )
                                _put_string(op->Content.StringInt.String, strlen(op->Content.StringInt.String));
                        if( op->bUseInteger )
-                               _put_dword(op->Content.StringInt.Integer);
+                               _put_index(op->Content.StringInt.Integer);
                        break;
                }
        }
@@ -220,8 +260,9 @@ char *Bytecode_SerialiseFunction(const tBC_Function *Function, int *Length, tStr
        len = Bytecode_int_Serialize(Function, NULL, label_offsets, Strings);
 
        code = malloc(len);
-       
-       Bytecode_int_Serialize(Function, code, label_offsets, Strings);
+
+       // Update length to the correct length (may decrease due to encoding)   
+       len = Bytecode_int_Serialize(Function, code, label_offsets, Strings);
 
        free(label_offsets);
 
@@ -283,81 +324,107 @@ int Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name)
        // Get max count (used when executing to get the frame size)
        if(Handle->VariableCount - Handle->CurContextDepth >= Handle->MaxVariableCount)
                Handle->MaxVariableCount = Handle->VariableCount - Handle->CurContextDepth;
-       return Handle->VariableCount - 1;
+//     printf("_AddVariable: %s given %i\n", Name, Handle->VariableCount - Handle->CurContextDepth - 1);
+       return Handle->VariableCount - Handle->CurContextDepth - 1;
 }
 
 int Bytecode_int_GetVarIndex(tBC_Function *Handle, const char *Name)
 {
-        int    i;
+        int    i, context_depth = Handle->CurContextDepth;
        // Get the start of this context
        for( i = Handle->VariableCount; i --; )
        {
-               if( Handle->VariableNames[i] && strcmp(Name, Handle->VariableNames[i]) == 0 )
-                       return i;
+               if( !Handle->VariableNames[i] ) {
+                       context_depth --;
+                       continue ;
+               }
+               if( strcmp(Name, Handle->VariableNames[i]) == 0 )
+                       return i - context_depth;
        }
        return -1;
 }
 
 #define DEF_BC_NONE(_op) { \
-       tBC_Op *op = Bytecode_int_AllocateOp(_op); \
+       tBC_Op *op = Bytecode_int_AllocateOp(_op, 0); \
        op->Content.Integer = 0; \
        op->bUseInteger = 0; \
        Bytecode_int_AppendOp(Handle, op);\
 }
 
+#define DEF_BC_INT(_op, _int) {\
+       tBC_Op *op = Bytecode_int_AllocateOp(_op, 0);\
+       op->Content.StringInt.Integer = _int;\
+       op->bUseInteger = 1;\
+       op->bUseString = 0;\
+       Bytecode_int_AppendOp(Handle, op);\
+}
+
 #define DEF_BC_STRINT(_op, _str, _int) { \
-       tBC_Op *op = Bytecode_int_AllocateOp(_op);\
+       tBC_Op *op = Bytecode_int_AllocateOp(_op, strlen(_str));\
        op->Content.StringInt.Integer = _int;\
-       op->Content.StringInt.String = _str;\
+       strcpy(op->Content.StringInt.String, _str);\
        op->bUseInteger = 1;\
+       op->bUseString = 1;\
        Bytecode_int_AppendOp(Handle, op);\
 }
 #define DEF_BC_STR(_op, _str) {\
-       tBC_Op *op = Bytecode_int_AllocateOp(_op);\
-       op->Content.StringInt.String = _str;\
+       tBC_Op *op = Bytecode_int_AllocateOp(_op, strlen(_str));\
+       strcpy(op->Content.StringInt.String, _str);\
        op->bUseInteger = 0;\
        Bytecode_int_AppendOp(Handle, op);\
 }
 
 // --- Flow Control
 void Bytecode_AppendJump(tBC_Function *Handle, int Label)
-       DEF_BC_STRINT(BC_OP_JUMP, NULL, Label)
+       DEF_BC_INT(BC_OP_JUMP, Label)
 void Bytecode_AppendCondJump(tBC_Function *Handle, int Label)
-       DEF_BC_STRINT(BC_OP_JUMPIF, NULL, Label)
+       DEF_BC_INT(BC_OP_JUMPIF, Label)
+void Bytecode_AppendCondJumpNot(tBC_Function *Handle, int Label)
+       DEF_BC_INT(BC_OP_JUMPIFNOT, Label)
 void Bytecode_AppendReturn(tBC_Function *Handle)
        DEF_BC_NONE(BC_OP_RETURN);
 
 // --- Variables
 void Bytecode_AppendLoadVar(tBC_Function *Handle, const char *Name)
-       DEF_BC_STRINT(BC_OP_LOADVAR, NULL, Bytecode_int_GetVarIndex(Handle, Name))
+       DEF_BC_INT(BC_OP_LOADVAR, Bytecode_int_GetVarIndex(Handle, Name))
 //     DEF_BC_STR(BC_OP_LOADVAR, Name)
 void Bytecode_AppendSaveVar(tBC_Function *Handle, const char *Name)    // (Obj->)?var = 
-       DEF_BC_STRINT(BC_OP_SAVEVAR, NULL, Bytecode_int_GetVarIndex(Handle, Name))
+       DEF_BC_INT(BC_OP_SAVEVAR, Bytecode_int_GetVarIndex(Handle, Name))
 //     DEF_BC_STR(BC_OP_SAVEVAR, Name)
 
 // --- Constants
 void Bytecode_AppendConstInt(tBC_Function *Handle, uint64_t Value)
 {
-       tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADINT);
+       tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADINT, 0);
        op->Content.Integer = Value;
        Bytecode_int_AppendOp(Handle, op);
 }
 void Bytecode_AppendConstReal(tBC_Function *Handle, double Value)
 {
-       tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADREAL);
+       tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADREAL, 0);
        op->Content.Real = Value;
        Bytecode_int_AppendOp(Handle, op);
 }
 void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t Length)
-       DEF_BC_STRINT(BC_OP_LOADSTR, Data, Length)
+{
+       tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADSTR, Length+1);
+       op->Content.StringInt.Integer = Length;
+       memcpy(op->Content.StringInt.String, Data, Length);
+       op->Content.StringInt.String[Length] = 0;
+       Bytecode_int_AppendOp(Handle, op);
+}
+void Bytecode_AppendConstNull(tBC_Function *Handle)
+       DEF_BC_NONE(BC_OP_LOADNULL)
 
 // --- Indexing / Scoping
-void Bytecode_AppendSubNamespace(tBC_Function *Handle, const char *Name)
-       DEF_BC_STR(BC_OP_SCOPE, Name)
 void Bytecode_AppendElement(tBC_Function *Handle, const char *Name)
        DEF_BC_STR(BC_OP_ELEMENT, Name)
+void Bytecode_AppendSetElement(tBC_Function *Handle, const char *Name)
+       DEF_BC_STR(BC_OP_SETELEMENT, Name)
 void Bytecode_AppendIndex(tBC_Function *Handle)
        DEF_BC_NONE(BC_OP_INDEX)
+void Bytecode_AppendSetIndex(tBC_Function *Handle)
+       DEF_BC_NONE(BC_OP_SETINDEX);
 
 void Bytecode_AppendCreateObj(tBC_Function *Handle, const char *Name, int ArgumentCount)
        DEF_BC_STRINT(BC_OP_CREATEOBJ, Name, ArgumentCount)
@@ -371,7 +438,11 @@ void Bytecode_AppendBinOp(tBC_Function *Handle, int Operation)
 void Bytecode_AppendUniOp(tBC_Function *Handle, int Operation)
        DEF_BC_NONE(Operation)
 void Bytecode_AppendCast(tBC_Function *Handle, int Type)
-       DEF_BC_STRINT(BC_OP_CAST, NULL, Type)
+       DEF_BC_INT(BC_OP_CAST, Type)
+void Bytecode_AppendDuplicate(tBC_Function *Handle)
+       DEF_BC_NONE(BC_OP_DUPSTACK);
+void Bytecode_AppendDelete(tBC_Function *Handle)
+       DEF_BC_NONE(BC_OP_DELSTACK);
 
 // Does some bookeeping to allocate variable slots at compile time
 void Bytecode_AppendEnterContext(tBC_Function *Handle)
@@ -391,7 +462,7 @@ void Bytecode_AppendLeaveContext(tBC_Function *Handle)
        Handle->CurContextDepth --;
        Handle->VariableCount = i;
 
-       DEF_BC_NONE(BC_OP_LEAVECONTEXT)
+       DEF_BC_NONE(BC_OP_LEAVECONTEXT);
 }
 //void Bytecode_AppendImportNamespace(tBC_Function *Handle, const char *Name);
 //     DEF_BC_STRINT(BC_OP_IMPORTNS, Name, 0)
@@ -413,6 +484,7 @@ void Bytecode_AppendDefineVar(tBC_Function *Handle, const char *Name, int Type)
        #endif
 
        i = Bytecode_int_AddVariable(Handle, Name);
-       
+//     printf("Variable %s given slot %i\n", Name, i); 
+
        DEF_BC_STRINT(BC_OP_DEFINEVAR, Name, (Type&0xFFFF) | (i << 16))
 }

UCC git Repository :: git.ucc.asn.au