1 #include "vm_generator.h"
3 #include <sun/tree/node_internal.h>
4 #include <sun/tree/node_type.h>
5 #include <sun/tree/tree.h>
6 #include <sun/vm/instruction.h>
7 #include <sun/vm/vm_internal.h>
10 #include <stdarg.h> //fixme
11 #include <stdbool.h> //fixme
12 #include <stdlib.h> //fixme
13 #include <stdio.h> //fixme
14 #include <string.h> //fixme
16 #define generator_assert_msg(t,m,...) if(!(t)) { fprintf(stderr,"%s:%u ERROR:"m"\n",__FILE__,__LINE__, ##__VA_ARGS__); exit(1); }
17 #define generator_assert(t) generator_assert_msg(t,"invalid")
19 struct VMGeneratorInstruction
{
20 SVMInstruction instruction
;
23 struct VMGeneratorOutputScope
{
25 size_t stringClumpSize
;
26 size_t stringClumpMaxSize
;
28 struct VMGeneratorInstruction
*instructions
;
29 size_t instructionCount
;
30 SVMPointer nextInstructionIdx
;
32 struct VMGeneratorInstruction
*resolvableDefinition
;
34 typedef struct VMGeneratorOutputScope VMGeneratorOutputScope
;
36 enum VMNodeMetadataIdentifierType
{
37 VMNodeMetadataIdentifierTypeUnknown
,
38 VMNodeMetadataIdentifierTypeNullType
,
39 VMNodeMetadataIdentifierTypeIntegerType
,
40 VMNodeMetadataIdentifierTypeFloatType
,
41 VMNodeMetadataIdentifierTypeStringType
,
42 //VMNodeMetadataIdentifierTypeUserType,
43 VMNodeMetadataIdentifierTypeVariable
,
44 VMNodeMetadataIdentifierTypeFunction
,
45 VMNodeMetadataIdentifierTypeParameter
,
47 typedef enum VMNodeMetadataIdentifierType VMNodeMetadataIdentifierType
;
49 struct VMNodeMetadata
{
52 bool holdsVariableScope
;
54 SLTNode
*scopedFunctionsHead
;
55 SLTNode
*scopedVariablesHead
;
56 SLTNode
*scopedParametersHead
;
57 SLTNode
*scopedBreaksHead
;
62 SLTNode
*scopedFunctionNext
;
66 SLTNode
*scopedVariableNext
;
70 SLTNode
*scopedParameterNext
;
74 SVMPointer breakInstruction
;
75 SLTNode
*scopedBreakNext
;
79 VMNodeMetadataIdentifierType type
;
80 SLTNode
*resolvedNode
;
84 SVMStackOffset offset
;
93 SVMPointer instruction
;
96 typedef struct VMNodeMetadata VMNodeMetadata
;
98 union VMGeneratorVisitor
{
99 VMGeneratorOutputScope
*generator
;
100 SLTNode
*currentScope
;
106 typedef union VMGeneratorVisitor VMGeneratorVisitor
;
109 #define sltGetNodeMetadata(node) ((VMNodeMetadata *)(node)->metadata)
113 static VMGeneratorOutputScope
*generatorCreate() {
114 VMGeneratorOutputScope
*scope
= malloc(sizeof(VMGeneratorOutputScope
)); // fixme these mallocs
115 memset(scope
, 0, sizeof(VMGeneratorOutputScope
));
117 scope
->instructionCount
= 2048;
118 scope
->instructions
= malloc(scope
->instructionCount
* sizeof(struct VMGeneratorInstruction
));
119 scope
->nextInstructionIdx
= 0;
121 scope
->stringClumpMaxSize
= 1024;
122 scope
->stringClump
= malloc(scope
->stringClumpMaxSize
);
123 scope
->stringClumpSize
= 0;
130 static size_t opcodeOperandCount(SVMOpcode opcode
) {
133 case SVMOpcodePOPJUMP
:
138 case SVMOpcodePUSHJUMP
:
169 generator_assert_msg(false, "invalid opcode %u", opcode
);
175 static SVMPointer
generatorNextInstruction(VMGeneratorOutputScope
*generator
) {
176 generator_assert(generator
->nextInstructionIdx
< generator
->instructionCount
);
177 SVMPointer idx
= generator
->nextInstructionIdx
;
181 static SVMPointer
generatorAddInstruction(VMGeneratorOutputScope
*generator
, SVMOpcode opcode
, ...) {
182 generator_assert(generator
->nextInstructionIdx
< generator
->instructionCount
);
184 SVMPointer idx
= generatorNextInstruction(generator
);
185 generator
->nextInstructionIdx
++;
186 struct VMGeneratorInstruction
*instruction
= &generator
->instructions
[idx
];
188 instruction
->instruction
.opcode
= opcode
;
190 size_t numOperands
= opcodeOperandCount(opcode
);
193 va_start(args
, opcode
);
194 for (size_t i
= 0; i
< numOperands
; ++i
) {
195 instruction
->instruction
.operands
[i
] = va_arg(args
, SVMOperand
);
202 static void generatorPatchOperand(VMGeneratorOutputScope
*generator
, SVMPointer instruction
, size_t idx
, SVMOperand value
) {
203 generator_assert(instruction
< generator
->instructionCount
);
204 generator_assert_msg(idx
< opcodeOperandCount(generator
->instructions
[instruction
].instruction
.opcode
), "invalid idx");
205 generator
->instructions
[instruction
].instruction
.operands
[idx
] = value
;
208 static SVMPointer
generatorAddString(VMGeneratorOutputScope
*generator
, const char *string
) {
209 char *ptr
= generator
->stringClump
;
211 while (ptr
< generator
->stringClump
+ generator
->stringClumpSize
) {
212 //printf("testing string: %s == %s\n", ptr, string);
213 if (strcmp(string
, ptr
) == 0) {
214 return ptr
- generator
->stringClump
;
216 ptr
+=strlen(ptr
) + 1;
219 size_t stringLength
= strlen(string
) + 1;
220 generator_assert_msg(ptr
+ stringLength
<= generator
->stringClump
+ generator
->stringClumpMaxSize
, "out of string space!!!");
223 generator
->stringClumpSize
+= stringLength
;
225 //printf("added string: %s\n", string);
227 return ptr
- generator
->stringClump
;
230 static SVMStackOffset
generatorResolveIdentifier(VMGeneratorOutputScope
*generator
, SLTNode
*node
) {
231 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
232 generator_assert_msg(metadata
->identifier
.type
!= VMNodeMetadataIdentifierTypeUnknown
, "could not resolve %s", node
->identifierStringValue
);
233 SVMStackOffset offset
= sltGetNodeMetadata(metadata
->identifier
.resolvedNode
)->stack
.offset
;
238 static SVMModule
*generatorFinalize(VMGeneratorOutputScope
*generator
) {
239 size_t memorySize
= sizeof(SVMModule
) + generator
->stringClumpSize
+ /*0 * sizeof(SVMModuleFunctionDetails) +*/ generator
->nextInstructionIdx
* sizeof(SVMInstruction
);
241 SVMModule
*module
= (SVMModule
*)malloc(memorySize
);
242 module
->header
[0] = 's';
243 module
->header
[1] = 'u';
244 module
->header
[2] = 'n';
245 module
->header
[3] = 'l';
246 module
->magic
= 1525;
247 module
->stringBlobLength
= generator
->stringClumpSize
;
248 module
->numFunctions
= 0; // FIXME
249 module
->numInstructions
= generator
->nextInstructionIdx
;
251 memcpy((void *)module
+ sizeof(SVMModule
), generator
->stringClump
, module
->stringBlobLength
);
252 // COPY FUNCTIONS HERE...
253 memcpy((void *)module
+ sizeof(SVMModule
) + module
->stringBlobLength
, generator
->instructions
, module
->numInstructions
* sizeof(SVMInstruction
));
261 static void addNodeMetadata(SLTNode
*node
, void *userParameter
) {
262 VMNodeMetadata
*metadata
= (VMNodeMetadata
*)malloc(sizeof(VMNodeMetadata
));// fixme
263 memset(metadata
, 0, sizeof(VMNodeMetadata
));
264 node
->metadata
= metadata
;
268 static void findStrings(SLTNode
*node
, void *userParameter
) {
269 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
270 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
272 switch (node
->type
) {
273 case SLTNodeTypeString
:
274 metadata
->string
.address
= generatorAddString(visitor
->generator
, node
->stringValue
);
277 case SLTNodeTypeFunctionCall
:
278 metadata
->string
.address
= generatorAddString(visitor
->generator
, node
->functionCallFunction
->identifierStringValue
);
287 static bool nodeTypeDefinesScope(SLTNodeType type
) {
289 case SLTNodeTypeModule
:
290 case SLTNodeTypeFunctionDefinition
:
291 case SLTNodeTypeTypeDefinition
:
292 case SLTNodeTypeForIteration
:
293 case SLTNodeTypeDoIteration
:
294 case SLTNodeTypeWhileIteration
:
295 case SLTNodeTypeStatementBlock
:
303 static bool nodeTypeHoldsVariables(SLTNodeType type
) {
305 case SLTNodeTypeModule
:
306 case SLTNodeTypeFunctionDefinition
:
314 static void beginScopeNode(SLTNode
*node
, void *userParameter
) {
315 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
316 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
318 metadata
->scope
.parentScope
= visitor
->currentScope
;
320 if (nodeTypeDefinesScope(node
->type
)) {
321 metadata
->scope
.definesScope
= true;
322 metadata
->scope
.holdsVariableScope
= nodeTypeHoldsVariables(node
->type
);
323 visitor
->currentScope
= node
;
327 static void endScopeNode(SLTNode
*node
, void *userParameter
) {
328 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
329 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
331 if (nodeTypeDefinesScope(node
->type
)) {
332 visitor
->currentScope
= metadata
->scope
.parentScope
;
336 static SLTNode
*findScope(SLTNode
*node
) {
337 while (sltGetNodeMetadata(node
)->scope
.definesScope
== false) {
338 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
339 node
= metadata
->scope
.parentScope
;
340 generator_assert_msg(node
!= NULL
, "failed to scope"); // FIXME
346 static SLTNode
*findContainingScope(SLTNode
*node
) {
348 node
= findScope(node
);
350 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
351 if (metadata
->scope
.holdsVariableScope
) {
355 node
= metadata
->scope
.parentScope
;
357 generator_assert_msg(node
!= NULL
, "failed to scope"); // FIXME
361 static void scopeDefinitions(SLTNode
*node
, void *userParameter
) {
362 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
363 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
365 switch (node
->type
) {
366 case SLTNodeTypeFunctionParameterDefinition
: {
367 //printf("def parameter %s\n", node->functionParameterDefinitionIdentifier->stringValue);
368 VMNodeMetadata
*scopeMetadata
= sltGetNodeMetadata(findContainingScope(node
));
369 metadata
->parameter
.scopedParameterNext
= scopeMetadata
->scope
.scopedParametersHead
;
370 scopeMetadata
->scope
.scopedParametersHead
= node
;
374 case SLTNodeTypeVariableDefinition
: {
375 //printf("def var %s\n", node->variableDefinitionIdentifier->stringValue);
376 VMNodeMetadata
*scopeMetadata
= sltGetNodeMetadata(findContainingScope(node
));
377 metadata
->variable
.scopedVariableNext
= scopeMetadata
->scope
.scopedVariablesHead
;
378 scopeMetadata
->scope
.scopedVariablesHead
= node
;
382 case SLTNodeTypeFunctionDefinition
: {
383 //printf("def func %s\n", node->functionDefinitionIdentifier->stringValue);
384 VMNodeMetadata
*scopeMetadata
= sltGetNodeMetadata(findScope((sltGetNodeMetadata(findScope(node
))->scope
.parentScope
))); // Functions define a scope...
385 metadata
->function
.scopedFunctionNext
= scopeMetadata
->scope
.scopedFunctionsHead
;
386 scopeMetadata
->scope
.scopedFunctionsHead
= node
;
395 static SLTNode
*resolveDefinition(VMNodeMetadataIdentifierType
*typeOut
, SLTNode
*node
, const char *name
) {
396 if (strcmp(name
, "void") == 0) { // FIXME, can de-duplicate these for speed earlier..
397 *typeOut
= VMNodeMetadataIdentifierTypeNullType
;
401 if (strcmp(name
, "int") == 0) {
402 *typeOut
= VMNodeMetadataIdentifierTypeIntegerType
;
406 if (strcmp(name
, "float") == 0) {
407 *typeOut
= VMNodeMetadataIdentifierTypeFloatType
;
411 if (strcmp(name
, "string") == 0) {
412 *typeOut
= VMNodeMetadataIdentifierTypeStringType
;
417 VMNodeMetadata
*scopeMetadata
= sltGetNodeMetadata(findScope(node
));
419 // Should do types here...
421 for (SLTNode
*n
= scopeMetadata
->scope
.scopedFunctionsHead
; n
!= NULL
; n
= sltGetNodeMetadata(n
)->function
.scopedFunctionNext
) {
422 if (strcmp(n
->functionDefinitionIdentifier
->identifierStringValue
, name
) == 0) {
423 *typeOut
= VMNodeMetadataIdentifierTypeFunction
;
424 //printf("GOT F %s\n", name);
429 for (SLTNode
*n
= scopeMetadata
->scope
.scopedVariablesHead
; n
!= NULL
; n
= sltGetNodeMetadata(n
)->variable
.scopedVariableNext
) {
430 if (strcmp(n
->variableDefinitionIdentifier
->identifierStringValue
, name
) == 0) {
431 *typeOut
= VMNodeMetadataIdentifierTypeVariable
;
432 //printf("GOT V %s\n", name);
437 for (SLTNode
*n
= scopeMetadata
->scope
.scopedParametersHead
; n
!= NULL
; n
= sltGetNodeMetadata(n
)->parameter
.scopedParameterNext
) {
438 if (strcmp(n
->functionParameterDefinitionIdentifier
->identifierStringValue
, name
) == 0) {
439 *typeOut
= VMNodeMetadataIdentifierTypeParameter
;
440 //printf("GOT P %s\n", name);
445 if (scopeMetadata
->scope
.parentScope
!= NULL
) {
446 node
= scopeMetadata
->scope
.parentScope
;
455 static void resolveDefinitions(SLTNode
*node
, void *userParameter
) {
456 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
457 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
459 switch (node
->type
) {
460 case SLTNodeTypeIdentifier
:
461 metadata
->identifier
.resolvedNode
= resolveDefinition(&metadata
->identifier
.type
, node
, node
->identifierStringValue
);
462 //printf("trying to get %s %x\n", node->stringValue, metadata->identifier.resolvedNode);
463 //metadata->variable.scopedVariableNext = metadata->scope.scopedVariablesHead;
464 //metadata->scope.scopedVariablesHead = node;
472 static void resolveDefinitionsNativeFunctions(SLTNode
*node
, void *userParameter
) {
473 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
474 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
476 switch (node
->type
) {
477 case SLTNodeTypeFunctionCall
:
478 if (sltGetNodeMetadata(node
->functionCallFunction
)->identifier
.resolvedNode
== NULL
) {
479 metadata
->functionCall
.instruction
= node
->functionCallFunction
->identifierStringKeyValue
;
480 metadata
->functionCall
.native
= true;
490 static void indexDefinitions(SLTNode
*node
, void *userParameter
) {
491 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
492 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
494 // Functions put their return value at the 0th stack position, modules start at -1
497 size_t parameterCount
= 0;
498 for (SLTNode
*parameter
= metadata
->scope
.scopedParametersHead
; parameter
!= NULL
; ++parameterCount
, parameter
= sltGetNodeMetadata(parameter
)->parameter
.scopedParameterNext
);
500 SLTNode
*parameter
= metadata
->scope
.scopedParametersHead
;
501 while (parameter
!= NULL
) {
502 sltGetNodeMetadata(parameter
)->stack
.offset
= node
->type
== SLTNodeTypeModule
? -idx
: (parameterCount
+ 1) - idx
; // Parameter positions are inverted...
504 parameter
= sltGetNodeMetadata(parameter
)->parameter
.scopedParameterNext
;
507 SLTNode
*variable
= metadata
->scope
.scopedVariablesHead
;
508 while (variable
!= NULL
) {
509 sltGetNodeMetadata(variable
)->stack
.offset
= node
->type
== SLTNodeTypeModule
? -idx
: idx
;
511 variable
= sltGetNodeMetadata(variable
)->variable
.scopedVariableNext
;
517 /*static void resolveTypes(SLTNode *node, void *userParameter) {
518 VMGeneratorVisitor *visitor = (VMGeneratorVisitor *)userParameter;
519 VMNodeMetadata *metadata = sltGetNodeMetadata(node);
521 switch (node->type) {
522 case SLTNodeTypeUnknown:
523 case SLTNodeTypeSequence:
524 generator_assert_msg(false, "unexpected: %s", sltNodeToString(node));// fixme
527 case SLTNodeTypeIdentifier:
530 case SLTNodeTypeBoolean:
531 case SLTNodeTypeInteger:
532 case SLTNodeTypeFloat:
533 case SLTNodeTypeString:
535 case SLTNodeTypeCompound:
537 case SLTNodeTypeArgument:
539 case SLTNodeTypeArrayAccess:
540 case SLTNodeTypeTypeAccess:
542 case SLTNodeTypeFunctionCall:
544 case SLTNodeTypeUnaryOperation:
545 case SLTNodeTypeBinaryOperation:
547 case SLTNodeTypeOperator:
549 case SLTNodeTypeAssignment:
551 case SLTNodeTypeReturn:
552 case SLTNodeTypeSleep:
554 case SLTNodeTypeForIteration:
555 case SLTNodeTypeDoIteration:
556 case SLTNodeTypeWhileIteration:
558 case SLTNodeTypeSelection:
560 case SLTNodeTypeStatementBlock:
562 case SLTNodeTypeVariableDefinition:
564 case SLTNodeTypeTypeDefinition:
565 case SLTNodeTypeTypeMemberDefinition:
567 case SLTNodeTypeFunctionDefinition:
568 case SLTNodeTypeFunctionParameterDefinition:
570 case SLTNodeTypeModule:
575 visitor.typeChanged = false;
582 if (node->dataType == SLTDataTypeUnknown) {
583 visitor->typeUnresolved = true;
587 static bool nodeTypeIsLoop(SLTNodeType type
) {
589 case SLTNodeTypeForIteration
:
590 case SLTNodeTypeDoIteration
:
591 case SLTNodeTypeWhileIteration
:
599 static SLTNode
*findLoopScope(SLTNode
*node
) {
601 node
= findScope(node
);
603 if (nodeTypeIsLoop(node
->type
)) {
607 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
608 node
= metadata
->scope
.parentScope
;
610 generator_assert_msg(node
!= NULL
, "failed to scope loop"); // FIXME
614 static void scopeIterationBreaks(SLTNode
*node
, void *userParameter
) {
615 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
616 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
618 switch (node
->type
) {
619 case SLTNodeTypeBreak
: {
620 VMNodeMetadata
*scopeMetadata
= sltGetNodeMetadata(findLoopScope(node
));
621 metadata
->breakStatement
.scopedBreakNext
= scopeMetadata
->scope
.scopedBreaksHead
;
622 scopeMetadata
->scope
.scopedBreaksHead
= node
;
632 static SVMPointer
generateValueInstructions(VMGeneratorOutputScope
*generator
, SLTNode
*node
, SVMOperand target
) {
633 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
635 switch (node
->type
) {
636 case SLTNodeTypeIdentifier
: {
637 SVMOperand source
= { .stackOffset
= generatorResolveIdentifier(generator
, node
) };
638 return generatorAddInstruction(generator
, SVMOpcodeMOV
, target
, source
);
641 case SLTNodeTypeBoolean
: {
642 SVMOperand source
= { .integerLiteral
= node
->booleanValue
? 1 : 0 };
643 return generatorAddInstruction(generator
, SVMOpcodeSET
, target
, source
);
646 case SLTNodeTypeInteger
: {
647 SVMOperand source
= { .integerLiteral
= FIXED(node
->integerValue
) };
648 return generatorAddInstruction(generator
, SVMOpcodeSET
, target
, source
);
651 case SLTNodeTypeRawInteger
: {
652 SVMOperand source
= { .__raw
= node
->integerValue
};
653 return generatorAddInstruction(generator
, SVMOpcodeSET
, target
, source
);
656 case SLTNodeTypeFloat
: {
657 SVMOperand source
= { .floatLiteral
= FIXED_FROM_FLOAT(node
->floatValue
) };
658 return generatorAddInstruction(generator
, SVMOpcodeSET
, target
, source
);
661 case SLTNodeTypeString
: {
662 SVMOperand source
= { .pointerLiteral
= metadata
->string
.address
}; // FIXME, string pool needed
663 return generatorAddInstruction(generator
, SVMOpcodeSET
, target
, source
);
666 case SLTNodeTypeKey
: {
667 SVMOperand source
= { .pointerLiteral
= node
->keyValue
};
668 return generatorAddInstruction(generator
, SVMOpcodeSET
, target
, source
);
672 generator_assert_msg(false, "unexpected: %s", sltNodeToString(node
));// fixme
677 static SVMPointer
generateExpressionInstructions(VMGeneratorOutputScope
*generator
, SLTNode
*node
, SVMOperand target
, SVMStackOffset workingStackOffset
) {
678 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
680 switch (node
->type
) {
681 case SLTNodeTypeBinaryOperation
: {
682 SVMOperand lhsOperand
= { .stackOffset
= workingStackOffset
};
683 generateExpressionInstructions(generator
, node
->binaryOperationLHS
, lhsOperand
, workingStackOffset
+ 1);
685 SVMOperand rhsOperand
= { .stackOffset
= workingStackOffset
+ 1 };
686 generateExpressionInstructions(generator
, node
->binaryOperationRHS
, rhsOperand
, workingStackOffset
+ 2);
688 switch (node
->binaryOperationOperator
->operatorType
) {
689 case SLTOperatorTypeAdd
:
690 return generatorAddInstruction(generator
, SVMOpcodeADD
, target
, lhsOperand
, rhsOperand
);
692 case SLTOperatorTypeSubtract
:
693 return generatorAddInstruction(generator
, SVMOpcodeSUB
, target
, lhsOperand
, rhsOperand
);
695 case SLTOperatorTypeMultiply
:
696 return generatorAddInstruction(generator
, SVMOpcodeMUL
, target
, lhsOperand
, rhsOperand
);
698 case SLTOperatorTypeDivide
:
699 return generatorAddInstruction(generator
, SVMOpcodeDIV
, target
, lhsOperand
, rhsOperand
);
701 case SLTOperatorTypeModulo
:
702 return generatorAddInstruction(generator
, SVMOpcodeMOD
, target
, lhsOperand
, rhsOperand
);
704 case SLTOperatorTypeBitwiseAnd
:
705 return generatorAddInstruction(generator
, SVMOpcodeBAND
, target
, lhsOperand
, rhsOperand
);
707 case SLTOperatorTypeBitwiseOr
:
708 return generatorAddInstruction(generator
, SVMOpcodeBOR
, target
, lhsOperand
, rhsOperand
);
710 case SLTOperatorTypeBitwiseXor
:
711 return generatorAddInstruction(generator
, SVMOpcodeBXOR
, target
, lhsOperand
, rhsOperand
);
713 case SLTOperatorTypeLogicalAnd
:
714 return generatorAddInstruction(generator
, SVMOpcodeAND
, target
, lhsOperand
, rhsOperand
);
716 case SLTOperatorTypeLogicalOr
:
717 return generatorAddInstruction(generator
, SVMOpcodeOR
, target
, lhsOperand
, rhsOperand
);
719 case SLTOperatorTypeEqual
:
720 return generatorAddInstruction(generator
, SVMOpcodeEQ
, target
, lhsOperand
, rhsOperand
);
722 case SLTOperatorTypeNotEqual
:
723 return generatorAddInstruction(generator
, SVMOpcodeNEQ
, target
, lhsOperand
, rhsOperand
);
725 case SLTOperatorTypeLessThan
:
726 return generatorAddInstruction(generator
, SVMOpcodeLT
, target
, lhsOperand
, rhsOperand
);
728 case SLTOperatorTypeLessThanEqual
:
729 return generatorAddInstruction(generator
, SVMOpcodeLTEQ
, target
, lhsOperand
, rhsOperand
);
731 case SLTOperatorTypeGreaterThan
:
732 return generatorAddInstruction(generator
, SVMOpcodeGT
, target
, lhsOperand
, rhsOperand
);
734 case SLTOperatorTypeGreaterThanEqual
:
735 return generatorAddInstruction(generator
, SVMOpcodeGTEQ
, target
, lhsOperand
, rhsOperand
);
738 generator_assert_msg(false, "invalid binary operator %s", sltOperatorTypeToString(node
->binaryOperationOperator
->operatorType
));
743 case SLTNodeTypeUnaryOperation
: {
744 SVMOperand operand
= { .stackOffset
= target
.stackOffset
};
745 generateExpressionInstructions(generator
, node
->unaryOperationOperand
, operand
, workingStackOffset
);
747 switch (node
->unaryOperationOperator
->operatorType
) {
748 //case SLTOperatorTypePositive:
751 case SLTOperatorTypeNegative
:
752 return generatorAddInstruction(generator
, SVMOpcodeINV
, target
, operand
);
754 case SLTOperatorTypeBitwiseNot
:
755 return generatorAddInstruction(generator
, SVMOpcodeBNOT
, target
, operand
);
757 case SLTOperatorTypeLogicalNot
:
758 return generatorAddInstruction(generator
, SVMOpcodeNOT
, target
, operand
);
761 generator_assert_msg(false, "invalid unary operator %s", sltOperatorTypeToString(node
->unaryOperationOperator
->operatorType
));
766 case SLTNodeTypeArrayAccess
:
767 generator_assert_msg(false, "not implemented: %s", sltNodeToString(node
));
770 case SLTNodeTypeFunctionCall
: {
771 //generator_assert_msg(sltGetNodeMetadata(node->functionCallFunction)->identifier.resolvedNode != NULL, "unresolved function: %s", node->functionCallFunction->stringValue);// fixme
773 SVMPointer r
= generatorNextInstruction(generator
);
775 SVMInteger parameterCount
= 0;
776 for (SLTNode
*n
= node
->functionCallArguments
; n
!= NULL
; n
= n
->sequenceNext
) {
778 SVMStackOffset parameterTarget
= workingStackOffset
+ parameterCount
;
779 SVMOperand target
= { .stackOffset
= parameterTarget
, };
780 generateExpressionInstructions(generator
, n
->sequenceNode
->argumentExpression
, target
, parameterTarget
);
783 // Offset the stack to make 0 where we're returning into...
784 SVMStackOffset stackOffset
= workingStackOffset
;// + parameterCount;
785 generatorAddInstruction(generator
, SVMOpcodeSTK
, stackOffset
);
788 if (metadata
->functionCall
.native
== false) {
789 metadata
->functionCall
.instruction
= generatorAddInstruction(generator
, SVMOpcodePUSHJUMP
, 999); // Silly marker, we patch this later...
791 metadata
->functionCall
.instruction
= generatorAddInstruction(generator
, SVMOpcodeCALL
, metadata
->functionCall
.instruction
, parameterCount
);
794 // Put the stack back
795 generatorAddInstruction(generator
, SVMOpcodeSTK
, -stackOffset
);
798 if (target
.stackOffset
!= workingStackOffset
) {
799 SVMOperand source
= { .stackOffset
= workingStackOffset
};
800 generatorAddInstruction(generator
, SVMOpcodeMOV
, target
, source
);
806 case SLTNodeTypeTypeAccess
:
807 generator_assert_msg(false, "not implemented: %s", sltNodeToString(node
));
810 case SLTNodeTypeCompound
:
811 return generateExpressionInstructions(generator
, node
->compoundSubexpression
, target
, workingStackOffset
);
814 return generateValueInstructions(generator
, node
, target
);
818 static SVMPointer
generateStatementInstructions(VMGeneratorOutputScope
*generator
, SLTNode
*node
, SVMStackOffset workingStackOffset
) {
819 switch (node
->type
) {
820 case SLTNodeTypeStatementBlock
: {
821 SVMPointer r
= generatorNextInstruction(generator
);
823 // FIXME, call the function thing...
824 // FIXME, open some kind of scope??
825 for (SLTNode
*n
= node
->statementBlockContents
; n
!= NULL
; n
= n
->sequenceNext
) {
826 generateStatementInstructions(generator
, n
->sequenceNode
, workingStackOffset
);
832 case SLTNodeTypeVariableDefinition
: {
833 SVMPointer r
= generatorNextInstruction(generator
);
835 if (node
->variableDefinitionDefaultExpression
!= NULL
) {
836 SVMOperand target
= { .stackOffset
= generatorResolveIdentifier(generator
, node
->variableDefinitionIdentifier
), };
837 generateExpressionInstructions(generator
, node
->variableDefinitionDefaultExpression
, target
, workingStackOffset
);
843 case SLTNodeTypeSelection
: {
844 SVMPointer r
= generatorNextInstruction(generator
);
846 SVMOperand valid
= { .stackOffset
= 0, };
847 generateExpressionInstructions(generator
, node
->selectionValidExpression
, valid
, workingStackOffset
+ 1);
848 generatorAddInstruction(generator
, SVMOpcodeNOT
, valid
, valid
); // Inverse for this check...
849 SVMPointer patchPre
= generatorAddInstruction(generator
, SVMOpcodeJT
, valid
, 999);
851 if (node
->selectionValidStatement
!= NULL
) {
852 generateStatementInstructions(generator
, node
->selectionValidStatement
, workingStackOffset
);
855 if (node
->selectionInvalidStatement
!= NULL
) {
856 SVMPointer patchPost
= generatorAddInstruction(generator
, SVMOpcodeJUMP
, 999);
858 SVMOperand target
= { .pointerLiteral
= generatorNextInstruction(generator
), };
859 generatorPatchOperand(generator
, patchPre
, 1, target
);
861 generateStatementInstructions(generator
, node
->selectionInvalidStatement
, workingStackOffset
);
863 target
.pointerLiteral
= generatorNextInstruction(generator
);
864 generatorPatchOperand(generator
, patchPost
, 0, target
);
866 SVMOperand target
= { .pointerLiteral
= generatorNextInstruction(generator
), };
867 generatorPatchOperand(generator
, patchPre
, 1, target
);
873 case SLTNodeTypeDoIteration
:
874 case SLTNodeTypeForIteration
:
875 case SLTNodeTypeWhileIteration
: {
876 if (node
->iterationInitialExpression
!= NULL
) {
877 //SVMOperand target = { .stackOffset = 0, };
878 //generateExpressionInstructions(generator, node->iterationInitialExpression, target, workingStackOffset); // FIXME, is this a statement??
879 generateStatementInstructions(generator
, node
->iterationInitialExpression
, workingStackOffset
);
882 SVMPointer r
= generatorNextInstruction(generator
);
885 if (node
->iterationPreValidExpression
!= NULL
) {
886 SVMOperand valid
= { .stackOffset
= 0, };
887 generateExpressionInstructions(generator
, node
->iterationPreValidExpression
, valid
, workingStackOffset
+ 1);
888 generatorAddInstruction(generator
, SVMOpcodeNOT
, valid
, valid
); // Inverse for this check...
889 patchPre
= generatorAddInstruction(generator
, SVMOpcodeJT
, valid
, 999);
892 if (node
->iterationStatement
!= NULL
) {
893 generateStatementInstructions(generator
, node
->iterationStatement
, workingStackOffset
);
896 if (node
->iterationLoopExpression
!= NULL
) {
897 //SVMOperand target = { .stackOffset = 0, };
898 //generateExpressionInstructions(generator, node->iterationLoopExpression, target, workingStackOffset); // FIXME, is this a statement??
899 generateStatementInstructions(generator
, node
->iterationLoopExpression
, workingStackOffset
);
902 if (node
->iterationPostValidExpression
!= NULL
) {
903 SVMOperand valid
= { .stackOffset
= 0, };
904 generateExpressionInstructions(generator
, node
->iterationPostValidExpression
, valid
, workingStackOffset
+ 1);
905 generatorAddInstruction(generator
, SVMOpcodeJT
, valid
, r
);
907 generatorAddInstruction(generator
, SVMOpcodeJUMP
, r
);
911 SVMOperand target
= { .pointerLiteral
= generatorNextInstruction(generator
), };
913 if (node
->iterationPreValidExpression
!= NULL
) {
914 generatorPatchOperand(generator
, patchPre
, 1, target
);
917 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
918 for (SLTNode
*v
= metadata
->scope
.scopedBreaksHead
; v
!= NULL
; v
= sltGetNodeMetadata(v
)->breakStatement
.scopedBreakNext
) {
919 generatorPatchOperand(generator
, sltGetNodeMetadata(v
)->breakStatement
.breakInstruction
, 0, target
);
925 case SLTNodeTypeAssignment
: {
926 SVMOperand target
= { .stackOffset
= generatorResolveIdentifier(generator
, node
->assignmentTarget
) };
927 return generateExpressionInstructions(generator
, node
->assignmentSource
, target
, workingStackOffset
);
930 case SLTNodeTypeReturn
: {
931 SVMPointer r
= generatorNextInstruction(generator
);
933 if (node
->returnExpression
!= NULL
) {
934 SVMOperand target
= { .stackOffset
= 0, }; // return is always at 0
935 generateExpressionInstructions(generator
, node
->returnExpression
, target
, workingStackOffset
);
937 generatorAddInstruction(generator
, SVMOpcodePOPJUMP
);
942 case SLTNodeTypeSleep
:
943 return generatorAddInstruction(generator
, SVMOpcodeSLEEP
);
945 case SLTNodeTypeBreak
: {
946 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
947 metadata
->breakStatement
.breakInstruction
= generatorAddInstruction(generator
, SVMOpcodeJUMP
, 999);
948 return metadata
->breakStatement
.breakInstruction
;
952 // generator_assert_msg(false, "not implemented as statement: %s", sltNodeToString(node));
953 SVMOperand target
= { .stackOffset
= 0, }; // FIXME!!!
954 return generateExpressionInstructions(generator
, node
, target
, workingStackOffset
);
959 static void generateFunctionDefinitionInstructions(VMGeneratorOutputScope
*generator
, SLTNode
*node
) {
960 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
962 // count parameters, these are first on the stack...
963 size_t numParameters
= 0;
964 for (SLTNode
*p
= metadata
->scope
.scopedParametersHead
; p
!= NULL
; ++numParameters
, p
= sltGetNodeMetadata(p
)->parameter
.scopedParameterNext
);
966 // next, count the variables
967 size_t numVariables
= 0;
968 for (SLTNode
*v
= metadata
->scope
.scopedVariablesHead
; v
!= NULL
; ++numVariables
, v
= sltGetNodeMetadata(v
)->variable
.scopedVariableNext
);
970 metadata
->function
.address
= generatorNextInstruction(generator
);
972 SVMStackOffset workingStackOffset
= 1 + numParameters
+ numVariables
;
973 if (node
->functionDefinitionBody
!= NULL
) {
974 generator_assert(node
->functionDefinitionBody
->type
== SLTNodeTypeSequence
);
975 for (SLTNode
*n
= node
->functionDefinitionBody
; n
!= NULL
; n
= n
->sequenceNext
) {
976 generateStatementInstructions(generator
, n
->sequenceNode
, workingStackOffset
);
981 generatorAddInstruction(generator
, SVMOpcodePOPJUMP
);
984 static size_t generateModuleInstructions(VMGeneratorOutputScope
*generator
, SLTNode
*node
) {
985 generator_assert(node
!= NULL
&& node
->type
== SLTNodeTypeModule
);
987 if (node
->moduleStatementsAndDefinitions
!= NULL
) {
988 SVMPointer start
= generatorAddInstruction(generator
, SVMOpcodeJUMP
, 999);
990 generator_assert(node
->moduleStatementsAndDefinitions
->type
== SLTNodeTypeSequence
);
992 // do functions first...
993 for (SLTNode
*n
= node
->moduleStatementsAndDefinitions
; n
!= NULL
; n
= n
->sequenceNext
) {
994 if (n
->sequenceNode
->type
== SLTNodeTypeFunctionDefinition
) {
995 generateFunctionDefinitionInstructions(generator
, n
->sequenceNode
);
999 // Patch to jump to the start...
1000 SVMOperand address
= { .pointerLiteral
= generatorNextInstruction(generator
) };
1001 generatorPatchOperand(generator
, start
, 0, address
);
1003 // then do variables
1004 for (SLTNode
*n
= node
->moduleStatementsAndDefinitions
; n
!= NULL
; n
= n
->sequenceNext
) {
1005 switch (n
->sequenceNode
->type
) {
1006 case SLTNodeTypeFunctionDefinition
:
1010 case SLTNodeTypeVariableDefinition
:
1011 generateStatementInstructions(generator
, n
->sequenceNode
, 0);
1015 //generator_assert_msg(false, "could not define %s", sltNodeTypeToString(n->sequenceNode->type));
1021 for (SLTNode
*n
= node
->moduleStatementsAndDefinitions
; n
!= NULL
; n
= n
->sequenceNext
) {
1022 switch (n
->sequenceNode
->type
) {
1023 case SLTNodeTypeVariableDefinition
:
1024 case SLTNodeTypeTypeDefinition
:
1025 case SLTNodeTypeFunctionDefinition
:
1030 generateStatementInstructions(generator
, n
->sequenceNode
, 0);
1042 static void patchFunctionCalls(SLTNode
*node
, void *userParameter
) {
1043 VMGeneratorVisitor
*visitor
= (VMGeneratorVisitor
*)userParameter
;
1044 VMNodeMetadata
*metadata
= sltGetNodeMetadata(node
);
1046 if (node
->type
== SLTNodeTypeFunctionCall
) {
1047 if (metadata
->functionCall
.native
== false) {
1048 generator_assert_msg(sltGetNodeMetadata(node
->functionCallFunction
)->identifier
.resolvedNode
->type
== SLTNodeTypeFunctionDefinition
, "%s", sltNodeToString(sltGetNodeMetadata(node
->functionCallFunction
)->identifier
.resolvedNode
));
1049 SVMOperand operand
= { .pointerLiteral
= sltGetNodeMetadata(sltGetNodeMetadata(node
->functionCallFunction
)->identifier
.resolvedNode
)->function
.address
};
1050 generatorPatchOperand(visitor
->generator
, metadata
->functionCall
.instruction
, 0, operand
);
1057 SVMModule
*slcGenerateVMInstructions(SLTNode
*moduleNode
) {
1058 VMGeneratorOutputScope
*generator
= generatorCreate();
1060 VMGeneratorVisitor visitor
;
1062 sltTreeIterate(moduleNode
, addNodeMetadata
, NULL
, NULL
);
1064 visitor
.generator
= generator
;
1065 sltTreeIterate(moduleNode
, findStrings
, NULL
, &visitor
);
1067 visitor
.currentScope
= NULL
;
1068 sltTreeIterate(moduleNode
, beginScopeNode
, endScopeNode
, &visitor
);
1070 visitor
.generator
= generator
;
1071 sltTreeIterate(moduleNode
, scopeDefinitions
, NULL
, &visitor
);
1072 sltTreeIterate(moduleNode
, resolveDefinitions
, resolveDefinitionsNativeFunctions
, &visitor
);
1073 sltTreeIterate(moduleNode
, indexDefinitions
, NULL
, &visitor
);
1075 sltTreeIterate(moduleNode
, scopeIterationBreaks
, NULL
, &visitor
);
1078 visitor.typeUnresolved = false;
1079 visitor.typeChanged = false;
1080 sltTreeIterate(moduleNode, resolveTypes, NULL, &visitor);
1081 } while (visitor.typeUnresolved && visitor.typeChanged);*/
1083 generateModuleInstructions(generator
, moduleNode
);
1085 visitor
.generator
= generator
;
1086 sltTreeIterate(moduleNode
, patchFunctionCalls
, NULL
, &visitor
);
1089 SVMModule
*module
= generatorFinalize(generator
);
1092 /*for (size_t i = 0; i < generator->nextInstructionIdx; ++i) {
1093 SVMOpcode opcode = generator->instructions[i].instruction.opcode;
1094 switch (opcodeOperandCount(opcode)) {
1097 printf("%u : %s\n", i, svmOpcodeToString(opcode));
1101 printf("%u : %s %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset);
1105 printf("%u : %s %d %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset, generator->instructions[i].instruction.p1.stackOffset);
1109 printf("%u : %s %d %d %d\n", i, svmOpcodeToString(opcode), generator->instructions[i].instruction.dst.stackOffset, generator->instructions[i].instruction.p1.stackOffset, generator->instructions[i].instruction.p2.stackOffset);