3 * by John Hodge (thePowersGang)
10 #include "bytecode_ops.h"
12 #include "bytecode_gen.h"
21 tBC_Op *Bytecode_int_AllocateOp(int Operation, int ExtraBytes);
22 int Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name);
27 tBC_Op *Bytecode_int_AllocateOp(int Operation, int ExtraBytes)
31 ret = malloc(sizeof(tBC_Op) + ExtraBytes);
35 ret->Operation = Operation;
37 ret->bUseString = (ExtraBytes > 0);
43 tBC_Function *Bytecode_CreateFunction(tScript_Function *Fcn)
48 ret = malloc(sizeof(tBC_Function));
51 ret->LabelSpace = ret->LabelCount = 0;
54 ret->MaxVariableCount = 0;
55 ret->CurContextDepth = 0;
56 ret->VariableCount = ret->VariableSpace = 0;
57 ret->VariableNames = NULL;
59 ret->OperationCount = 0;
60 ret->Operations = NULL;
61 ret->OperationsEnd = (void*)&ret->Operations;
63 for( i = 0; i < Fcn->ArgumentCount; i ++ )
65 Bytecode_int_AddVariable(ret, Fcn->Arguments[i].Name);
71 void Bytecode_DeleteFunction(tBC_Function *Fcn)
74 for( op = Fcn->Operations; op; )
76 tBC_Op *nextop = op->Next;
80 free(Fcn->VariableNames);
85 int StringList_GetString(tStringList *List, const char *String, int Length)
89 for(ent = List->Head; ent; ent = ent->Next, strIdx ++)
91 if(ent->Length == Length && memcmp(ent->Data, String, Length) == 0) break;
97 ent = malloc(sizeof(tString) + Length + 1);
100 ent->Length = Length;
102 memcpy(ent->Data, String, Length);
103 ent->Data[Length] = '\0';
106 List->Tail->Next = ent;
115 int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *LabelOffsets, tStringList *Strings)
118 int len = 0, idx = 0;
121 void _put_byte(uint8_t byte)
123 uint8_t *buf = Output;
124 if(Output) buf[len] = byte;
128 void _put_dword(uint32_t value)
130 uint8_t *buf = Output;
132 buf[len+0] = value & 0xFF;
133 buf[len+1] = value >> 8;
134 buf[len+2] = value >> 16;
135 buf[len+3] = value >> 24;
140 void _put_index(uint32_t value)
142 if( !Output && !value ) {
146 if( value < 0x8000 ) {
147 _put_byte(value >> 8);
148 _put_byte(value & 0xFF);
150 else if( value < 0x400000 ) {
151 _put_byte( (value >> 16) | 0x80 );
152 _put_byte(value >> 8);
153 _put_byte(value & 0xFF);
157 _put_byte(value >> 24);
158 _put_byte(value >> 16);
159 _put_byte(value >> 8 );
160 _put_byte(value & 0xFF);
164 void _put_qword(uint64_t value)
166 if( value < 0x80 ) { // 7 bits into 1 byte
169 else if( !(value >> (8+6)) ) { // 14 bits packed into 2 bytes
170 _put_byte( 0x80 | ((value >> 8) & 0x3F) );
171 _put_byte( value & 0xFF );
173 else if( !(value >> (32+5)) ) { // 37 bits into 5 bytes
174 _put_byte( 0xC0 | ((value >> 32) & 0x1F) );
175 _put_dword(value & 0xFFFFFFFF);
178 _put_byte( 0xE0 ); // 64 (actually 68) bits into 9 bytes
179 _put_dword(value & 0xFFFFFFFF);
180 _put_dword(value >> 32);
184 void _put_double(double value)
186 // TODO: Machine agnostic
188 *(double*)( (char*)Output + len ) = value;
190 len += sizeof(double);
193 void _put_string(const char *str, int len)
197 strIdx = StringList_GetString(Strings, str, len);
204 for( op = Function->Operations; op; op = op->Next, idx ++ )
206 // If first run, convert labels into byte offsets
209 for( i = 0; i < Function->LabelCount; i ++ )
211 if(LabelOffsets[i]) continue;
212 if(op != Function->Labels[i]) continue;
214 LabelOffsets[i] = len;
218 _put_byte(op->Operation);
219 switch(op->Operation)
221 // Relocate jumps (the value only matters if `Output` is non-NULL)
224 case BC_OP_JUMPIFNOT:
225 // TODO: Relocations?
226 _put_index( LabelOffsets[op->Content.StringInt.Integer] );
228 // Special case for inline values
230 _put_qword(op->Content.Integer);
233 _put_double(op->Content.Real);
236 _put_string(op->Content.StringInt.String, op->Content.StringInt.Integer);
238 // Everthing else just gets handled nicely
241 _put_string(op->Content.StringInt.String, strlen(op->Content.StringInt.String));
242 if( op->bUseInteger )
243 _put_index(op->Content.StringInt.Integer);
251 char *Bytecode_SerialiseFunction(const tBC_Function *Function, int *Length, tStringList *Strings)
257 label_offsets = calloc( sizeof(int), Function->LabelCount );
258 if(!label_offsets) return NULL;
260 len = Bytecode_int_Serialize(Function, NULL, label_offsets, Strings);
264 // Update length to the correct length (may decrease due to encoding)
265 len = Bytecode_int_Serialize(Function, code, label_offsets, Strings);
274 int Bytecode_AllocateLabel(tBC_Function *Handle)
278 if( Handle->LabelCount == Handle->LabelSpace ) {
280 Handle->LabelSpace += 20; // TODO: Don't hardcode increment
281 tmp = realloc(Handle->Labels, Handle->LabelSpace * sizeof(Handle->Labels[0]));
283 Handle->LabelSpace -= 20;
286 Handle->Labels = tmp;
288 ret = Handle->LabelCount ++;
289 Handle->Labels[ret] = 0;
293 void Bytecode_SetLabel(tBC_Function *Handle, int Label)
295 if(Label < 0) return ;
297 if(Label >= Handle->LabelCount) return ;
299 Handle->Labels[Label] = Handle->OperationsEnd;
303 void Bytecode_int_AppendOp(tBC_Function *Fcn, tBC_Op *Op)
306 if( Fcn->Operations )
307 Fcn->OperationsEnd->Next = Op;
309 Fcn->Operations = Op;
310 Fcn->OperationsEnd = Op;
313 int Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name)
315 if(Handle->VariableCount == Handle->VariableSpace) {
317 Handle->VariableSpace += 10;
318 tmp = realloc(Handle->VariableNames, Handle->VariableSpace * sizeof(Handle->VariableNames[0]));
319 if(!tmp) return -1; // TODO: Error
320 Handle->VariableNames = tmp;
322 Handle->VariableNames[Handle->VariableCount] = Name;
323 Handle->VariableCount ++;
324 // Get max count (used when executing to get the frame size)
325 if(Handle->VariableCount - Handle->CurContextDepth >= Handle->MaxVariableCount)
326 Handle->MaxVariableCount = Handle->VariableCount - Handle->CurContextDepth;
327 // printf("_AddVariable: %s given %i\n", Name, Handle->VariableCount - Handle->CurContextDepth - 1);
328 return Handle->VariableCount - Handle->CurContextDepth - 1;
331 int Bytecode_int_GetVarIndex(tBC_Function *Handle, const char *Name)
333 int i, context_depth = Handle->CurContextDepth;
334 // Get the start of this context
335 for( i = Handle->VariableCount; i --; )
337 if( !Handle->VariableNames[i] ) {
341 if( strcmp(Name, Handle->VariableNames[i]) == 0 )
342 return i - context_depth;
347 #define DEF_BC_NONE(_op) { \
348 tBC_Op *op = Bytecode_int_AllocateOp(_op, 0); \
349 op->Content.Integer = 0; \
350 op->bUseInteger = 0; \
351 Bytecode_int_AppendOp(Handle, op);\
354 #define DEF_BC_INT(_op, _int) {\
355 tBC_Op *op = Bytecode_int_AllocateOp(_op, 0);\
356 op->Content.StringInt.Integer = _int;\
357 op->bUseInteger = 1;\
359 Bytecode_int_AppendOp(Handle, op);\
362 #define DEF_BC_STRINT(_op, _str, _int) { \
363 tBC_Op *op = Bytecode_int_AllocateOp(_op, strlen(_str));\
364 op->Content.StringInt.Integer = _int;\
365 strcpy(op->Content.StringInt.String, _str);\
366 op->bUseInteger = 1;\
368 Bytecode_int_AppendOp(Handle, op);\
370 #define DEF_BC_STR(_op, _str) {\
371 tBC_Op *op = Bytecode_int_AllocateOp(_op, strlen(_str));\
372 strcpy(op->Content.StringInt.String, _str);\
373 op->bUseInteger = 0;\
374 Bytecode_int_AppendOp(Handle, op);\
378 void Bytecode_AppendJump(tBC_Function *Handle, int Label)
379 DEF_BC_INT(BC_OP_JUMP, Label)
380 void Bytecode_AppendCondJump(tBC_Function *Handle, int Label)
381 DEF_BC_INT(BC_OP_JUMPIF, Label)
382 void Bytecode_AppendCondJumpNot(tBC_Function *Handle, int Label)
383 DEF_BC_INT(BC_OP_JUMPIFNOT, Label)
384 void Bytecode_AppendReturn(tBC_Function *Handle)
385 DEF_BC_NONE(BC_OP_RETURN);
388 void Bytecode_AppendLoadVar(tBC_Function *Handle, const char *Name)
389 DEF_BC_INT(BC_OP_LOADVAR, Bytecode_int_GetVarIndex(Handle, Name))
390 // DEF_BC_STR(BC_OP_LOADVAR, Name)
391 void Bytecode_AppendSaveVar(tBC_Function *Handle, const char *Name) // (Obj->)?var =
392 DEF_BC_INT(BC_OP_SAVEVAR, Bytecode_int_GetVarIndex(Handle, Name))
393 // DEF_BC_STR(BC_OP_SAVEVAR, Name)
396 void Bytecode_AppendConstInt(tBC_Function *Handle, uint64_t Value)
398 tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADINT, 0);
399 op->Content.Integer = Value;
400 Bytecode_int_AppendOp(Handle, op);
402 void Bytecode_AppendConstReal(tBC_Function *Handle, double Value)
404 tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADREAL, 0);
405 op->Content.Real = Value;
406 Bytecode_int_AppendOp(Handle, op);
408 void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t Length)
410 tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADSTR, Length+1);
411 op->Content.StringInt.Integer = Length;
412 memcpy(op->Content.StringInt.String, Data, Length);
413 op->Content.StringInt.String[Length] = 0;
414 Bytecode_int_AppendOp(Handle, op);
416 void Bytecode_AppendConstNull(tBC_Function *Handle)
417 DEF_BC_NONE(BC_OP_LOADNULL)
419 // --- Indexing / Scoping
420 void Bytecode_AppendElement(tBC_Function *Handle, const char *Name)
421 DEF_BC_STR(BC_OP_ELEMENT, Name)
422 void Bytecode_AppendSetElement(tBC_Function *Handle, const char *Name)
423 DEF_BC_STR(BC_OP_SETELEMENT, Name)
424 void Bytecode_AppendIndex(tBC_Function *Handle)
425 DEF_BC_NONE(BC_OP_INDEX)
426 void Bytecode_AppendSetIndex(tBC_Function *Handle)
427 DEF_BC_NONE(BC_OP_SETINDEX);
429 void Bytecode_AppendCreateObj(tBC_Function *Handle, const char *Name, int ArgumentCount)
430 DEF_BC_STRINT(BC_OP_CREATEOBJ, Name, ArgumentCount)
431 void Bytecode_AppendMethodCall(tBC_Function *Handle, const char *Name, int ArgumentCount)
432 DEF_BC_STRINT(BC_OP_CALLMETHOD, Name, ArgumentCount)
433 void Bytecode_AppendFunctionCall(tBC_Function *Handle, const char *Name, int ArgumentCount)
434 DEF_BC_STRINT(BC_OP_CALLFUNCTION, Name, ArgumentCount)
436 void Bytecode_AppendBinOp(tBC_Function *Handle, int Operation)
437 DEF_BC_NONE(Operation)
438 void Bytecode_AppendUniOp(tBC_Function *Handle, int Operation)
439 DEF_BC_NONE(Operation)
440 void Bytecode_AppendCast(tBC_Function *Handle, int Type)
441 DEF_BC_INT(BC_OP_CAST, Type)
442 void Bytecode_AppendDuplicate(tBC_Function *Handle)
443 DEF_BC_NONE(BC_OP_DUPSTACK);
444 void Bytecode_AppendDelete(tBC_Function *Handle)
445 DEF_BC_NONE(BC_OP_DELSTACK);
447 // Does some bookeeping to allocate variable slots at compile time
448 void Bytecode_AppendEnterContext(tBC_Function *Handle)
450 Handle->CurContextDepth ++;
451 Bytecode_int_AddVariable(Handle, NULL); // NULL to record the extent of this
453 DEF_BC_NONE(BC_OP_ENTERCONTEXT)
455 void Bytecode_AppendLeaveContext(tBC_Function *Handle)
458 for( i = Handle->VariableCount; i --; )
460 if( Handle->VariableNames[i] == NULL ) break;
462 Handle->CurContextDepth --;
463 Handle->VariableCount = i;
465 DEF_BC_NONE(BC_OP_LEAVECONTEXT);
467 //void Bytecode_AppendImportNamespace(tBC_Function *Handle, const char *Name);
468 // DEF_BC_STRINT(BC_OP_IMPORTNS, Name, 0)
469 void Bytecode_AppendDefineVar(tBC_Function *Handle, const char *Name, int Type)
473 // Get the start of this context
474 for( i = Handle->VariableCount; i --; )
476 if( Handle->VariableNames[i] == NULL ) break;
478 // Check for duplicate allocation
479 for( i ++; i < Handle->VariableCount; i ++ )
481 if( strcmp(Name, Handle->VariableNames[i]) == 0 )
486 i = Bytecode_int_AddVariable(Handle, Name);
487 // printf("Variable %s given slot %i\n", Name, i);
489 DEF_BC_STRINT(BC_OP_DEFINEVAR, Name, (Type&0xFFFF) | (i << 16))