3 * by John Hodge (thePowersGang)
10 #include "bytecode_ops.h"
12 #include "bytecode_gen.h"
18 typedef struct sBC_Op tBC_Op;
45 // NOTE: These fields are invalid after compilation
48 const char **VariableNames; // Only type needs to be stored
49 int CurContextDepth; // Used to get the real var count
53 tBC_Op *OperationsEnd;
63 tBC_Op *Bytecode_int_AllocateOp(int Operation);
68 tBC_Op *Bytecode_int_AllocateOp(int Operation)
72 ret = malloc(sizeof(tBC_Op));
76 ret->Operation = Operation;
82 tBC_Function *Bytecode_CreateFunction(const char *Name, int ArgCount, char **ArgNames, int *ArgTypes)
87 ret = malloc(sizeof(tBC_Function) + ArgCount*sizeof(ret->Arguments[0]));
91 ret->LabelSpace = ret->LabelCount = 0;
94 ret->VariableCount = ret->VariableSpace = 0;
95 ret->VariableNames = NULL;
97 ret->OperationCount = 0;
98 ret->Operations = NULL;
99 ret->OperationsEnd = (void*)&ret->Operations;
101 ret->ArgumentCount = ArgCount;
102 for( i = 0; i < ArgCount; i ++ )
104 ret->Arguments[i].Name = strdup(ArgNames[i]);
105 ret->Arguments[i].Type = ArgTypes[i];
111 void Bytecode_DeleteFunction(tBC_Function *Fcn)
115 for( i = 0; i < Fcn->ArgumentCount; i ++ )
117 free(Fcn->Arguments[i].Name);
119 for( op = Fcn->Operations; op; )
121 tBC_Op *nextop = op->Next;
125 free(Fcn->VariableNames);
130 int StringList_GetString(tStringList *List, const char *String, int Length)
134 for(ent = List->Head; ent; ent = ent->Next, strIdx ++)
136 if(ent->Length == Length && memcmp(ent->Data, String, Length) == 0) break;
142 ent = malloc(sizeof(tString) + Length + 1);
145 ent->Length = Length;
147 memcpy(ent->Data, String, Length);
148 ent->Data[Length] = '\0';
151 List->Tail->Next = ent;
160 int Bytecode_int_Serialize(const tBC_Function *Function, void *Output, int *LabelOffsets, tStringList *Strings)
163 int len = 0, idx = 0;
166 void _put_byte(uint8_t byte)
168 uint8_t *buf = Output;
169 if(Output) buf[len] = byte;
173 void _put_dword(uint32_t value)
175 uint8_t *buf = Output;
177 buf[len+0] = value & 0xFF;
178 buf[len+1] = value >> 8;
179 buf[len+2] = value >> 16;
180 buf[len+3] = value >> 24;
185 void _put_qword(uint64_t value)
187 _put_dword(value & 0xFFFFFFFF);
188 _put_dword(value >> 32);
191 void _put_double(double value)
193 // TODO: Machine agnostic
195 *(double*)( (char*)Output + len ) = value;
197 len += sizeof(double);
200 void _put_string(const char *str, int len)
204 strIdx = StringList_GetString(Strings, str, len);
211 for( op = Function->Operations; op; op = op->Next, idx ++ )
213 // If first run, convert labels into byte offsets
216 for( i = 0; i < Function->LabelCount; i ++ )
218 if(LabelOffsets[i]) continue;
219 if(op != Function->Labels[i]) continue;
221 LabelOffsets[i] = len;
225 _put_byte(op->Operation);
226 switch(op->Operation)
228 // Relocate jumps (the value only matters if `Output` is non-NULL)
231 case BC_OP_JUMPIFNOT:
232 // TODO: Relocations?
233 _put_dword( LabelOffsets[op->Content.StringInt.Integer] );
235 // Special case for inline values
237 _put_qword(op->Content.Integer);
240 _put_double(op->Content.Real);
243 _put_string(op->Content.StringInt.String, op->Content.StringInt.Integer);
245 // Everthing else just gets handled nicely
247 if( op->Content.StringInt.String )
248 _put_string(op->Content.StringInt.String, strlen(op->Content.StringInt.String));
249 if( op->bUseInteger )
250 _put_dword(op->Content.StringInt.Integer);
258 char *Bytecode_SerialiseFunction(const tBC_Function *Function, int *Length, tStringList *Strings)
264 label_offsets = calloc( sizeof(int), Function->LabelCount );
265 if(!label_offsets) return NULL;
267 len = Bytecode_int_Serialize(Function, NULL, label_offsets, Strings);
271 Bytecode_int_Serialize(Function, code, label_offsets, Strings);
280 int Bytecode_AllocateLabel(tBC_Function *Handle)
284 if( Handle->LabelCount == Handle->LabelSpace ) {
286 Handle->LabelSpace += 20; // TODO: Don't hardcode increment
287 tmp = realloc(Handle->Labels, Handle->LabelSpace * sizeof(Handle->Labels[0]));
289 Handle->LabelSpace -= 20;
292 Handle->Labels = tmp;
294 ret = Handle->LabelCount ++;
295 Handle->Labels[ret] = 0;
299 void Bytecode_SetLabel(tBC_Function *Handle, int Label)
301 if(Label < 0) return ;
303 if(Label >= Handle->LabelCount) return ;
305 Handle->Labels[Label] = Handle->OperationsEnd;
309 void Bytecode_int_AppendOp(tBC_Function *Fcn, tBC_Op *Op)
312 if( Fcn->Operations )
313 Fcn->OperationsEnd->Next = Op;
315 Fcn->Operations = Op;
316 Fcn->OperationsEnd = Op;
319 void Bytecode_int_AddVariable(tBC_Function *Handle, const char *Name)
321 if(Handle->VariableCount == Handle->VariableSpace) {
323 Handle->VariableSpace += 10;
324 tmp = realloc(Handle->VariableNames, Handle->VariableSpace * sizeof(Handle->VariableNames[0]));
325 if(!tmp) return ; // TODO: Error
326 Handle->VariableNames = tmp;
328 Handle->VariableNames[Handle->VariableCount] = Name;
329 Handle->VariableCount ++;
330 // Get max count (used when executing to get the frame size)
331 if(Handle->VariableCount - Handle->CurContextDepth >= Handle->MaxVariableCount)
332 Handle->MaxVariableCount = Handle->VariableCount - Handle->CurContextDepth;
335 int Bytecode_int_GetVarIndex(tBC_Function *Handle, const char *Name)
338 // Get the start of this context
339 for( i = Handle->VariableCount; i --; )
341 if( Handle->VariableNames[i] == NULL ) break;
343 // Check for duplicate allocation
344 for( ; i < Handle->VariableCount; i ++ )
346 if( strcmp(Name, Handle->VariableNames[i]) == 0 )
352 #define DEF_BC_NONE(_op) { \
353 tBC_Op *op = Bytecode_int_AllocateOp(_op); \
354 op->Content.Integer = 0; \
355 op->bUseInteger = 0; \
356 Bytecode_int_AppendOp(Handle, op);\
359 #define DEF_BC_STRINT(_op, _str, _int) { \
360 tBC_Op *op = Bytecode_int_AllocateOp(_op);\
361 op->Content.StringInt.Integer = _int;\
362 op->Content.StringInt.String = _str;\
363 op->bUseInteger = 1;\
364 Bytecode_int_AppendOp(Handle, op);\
366 #define DEF_BC_STR(_op, _str) {\
367 tBC_Op *op = Bytecode_int_AllocateOp(_op);\
368 op->Content.StringInt.String = _str;\
369 op->bUseInteger = 0;\
370 Bytecode_int_AppendOp(Handle, op);\
374 void Bytecode_AppendJump(tBC_Function *Handle, int Label)
375 DEF_BC_STRINT(BC_OP_JUMP, NULL, Label)
376 void Bytecode_AppendCondJump(tBC_Function *Handle, int Label)
377 DEF_BC_STRINT(BC_OP_JUMPIF, NULL, Label)
378 void Bytecode_AppendReturn(tBC_Function *Handle)
379 DEF_BC_NONE(BC_OP_RETURN);
382 void Bytecode_AppendLoadVar(tBC_Function *Handle, const char *Name)
383 DEF_BC_STRINT(BC_OP_LOADVAR, NULL, Bytecode_int_GetVarIndex(Handle, Name))
384 // DEF_BC_STR(BC_OP_LOADVAR, Name)
385 void Bytecode_AppendSaveVar(tBC_Function *Handle, const char *Name) // (Obj->)?var =
386 DEF_BC_STRINT(BC_OP_SAVEVAR, NULL, Bytecode_int_GetVarIndex(Handle, Name))
387 // DEF_BC_STR(BC_OP_SAVEVAR, Name)
390 void Bytecode_AppendConstInt(tBC_Function *Handle, uint64_t Value)
392 tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADINT);
393 op->Content.Integer = Value;
394 Bytecode_int_AppendOp(Handle, op);
396 void Bytecode_AppendConstReal(tBC_Function *Handle, double Value)
398 tBC_Op *op = Bytecode_int_AllocateOp(BC_OP_LOADREAL);
399 op->Content.Real = Value;
400 Bytecode_int_AppendOp(Handle, op);
402 void Bytecode_AppendConstString(tBC_Function *Handle, const void *Data, size_t Length)
403 DEF_BC_STRINT(BC_OP_LOADSTR, Data, Length)
405 // --- Indexing / Scoping
406 void Bytecode_AppendSubNamespace(tBC_Function *Handle, const char *Name)
407 DEF_BC_STR(BC_OP_SCOPE, Name)
408 void Bytecode_AppendElement(tBC_Function *Handle, const char *Name)
409 DEF_BC_STR(BC_OP_ELEMENT, Name)
410 void Bytecode_AppendIndex(tBC_Function *Handle)
411 DEF_BC_NONE(BC_OP_INDEX)
413 void Bytecode_AppendCreateObj(tBC_Function *Handle, const char *Name, int ArgumentCount)
414 DEF_BC_STRINT(BC_OP_CREATEOBJ, Name, ArgumentCount)
415 void Bytecode_AppendMethodCall(tBC_Function *Handle, const char *Name, int ArgumentCount)
416 DEF_BC_STRINT(BC_OP_CALLMETHOD, Name, ArgumentCount)
417 void Bytecode_AppendFunctionCall(tBC_Function *Handle, const char *Name, int ArgumentCount)
418 DEF_BC_STRINT(BC_OP_CALLFUNCTION, Name, ArgumentCount)
420 void Bytecode_AppendBinOp(tBC_Function *Handle, int Operation)
421 DEF_BC_NONE(Operation)
422 void Bytecode_AppendUniOp(tBC_Function *Handle, int Operation)
423 DEF_BC_NONE(Operation)
424 void Bytecode_AppendCast(tBC_Function *Handle, int Type)
425 DEF_BC_STRINT(BC_OP_CAST, NULL, Type)
427 // Does some bookeeping to allocate variable slots at compile time
428 void Bytecode_AppendEnterContext(tBC_Function *Handle)
430 Handle->CurContextDepth ++;
431 Bytecode_int_AddVariable(Handle, NULL); // NULL to record the extent of this
433 DEF_BC_NONE(BC_OP_ENTERCONTEXT)
435 void Bytecode_AppendLeaveContext(tBC_Function *Handle)
438 for( i = Handle->VariableCount; i --; )
440 if( Handle->VariableNames[i] == NULL ) break;
442 Handle->CurContextDepth --;
444 DEF_BC_NONE(BC_OP_LEAVECONTEXT)
446 //void Bytecode_AppendImportNamespace(tBC_Function *Handle, const char *Name);
447 // DEF_BC_STRINT(BC_OP_IMPORTNS, Name, 0)
448 void Bytecode_AppendDefineVar(tBC_Function *Handle, const char *Name, int Type)
451 // Check for duplicates
452 if( Bytecode_int_GetVarIndex(Handle, Name) )
453 return ; // TODO: Error
456 Bytecode_int_AddVariable(Handle, Name);
458 DEF_BC_STRINT(BC_OP_DEFINEVAR, Name, Type)