4 * Copyright (C) 2008 Vincent Geddes
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 #include "st-compiler.h"
28 #include "st-object.h"
29 #include "st-symbol.h"
30 #include "st-dictionary.h"
31 #include "st-method.h"
34 #include "st-universe.h"
35 #include "st-behavior.h"
36 #include "st-character.h"
37 #include "st-unicode.h"
43 #define DEFAULT_CODE_SIZE 50
45 #define CSTRING(string) ((char *) st_byte_array_bytes (string))
55 st_compiler_error
*error
;
57 st_uint max_stack_depth
;
59 bool references_super
;
61 /* names of temporaries, in order of appearance */
63 /* names of instvars, in order they were defined */
65 /* literal frame for the compiled code */
74 static st_uint sizes
[255] = { 0, };
77 // setup global data for compiler
81 static bool initialized
= false;
87 /* The size (in bytes) of each bytecode instruction
90 sizes
[PUSH_INSTVAR
] = 2;
91 sizes
[PUSH_LITERAL_CONST
] = 2;
92 sizes
[PUSH_LITERAL_VAR
] = 2;
96 sizes
[PUSH_FALSE
] = 1;
97 sizes
[PUSH_INTEGER
] = 2;
98 sizes
[STORE_LITERAL_VAR
] = 2;
99 sizes
[STORE_TEMP
] = 2;
100 sizes
[STORE_INSTVAR
] = 2;
101 sizes
[STORE_POP_LITERAL_VAR
] = 2;
102 sizes
[STORE_POP_TEMP
] = 2;
103 sizes
[STORE_POP_INSTVAR
] = 2;
104 sizes
[RETURN_STACK_TOP
] = 1;
105 sizes
[BLOCK_RETURN
] = 1;
106 sizes
[POP_STACK_TOP
] = 1;
107 sizes
[DUPLICATE_STACK_TOP
] = 1;
108 sizes
[PUSH_ACTIVE_CONTEXT
] = 1;
109 sizes
[BLOCK_COPY
] = 2;
110 sizes
[JUMP_TRUE
] = 3;
111 sizes
[JUMP_FALSE
] = 3;
114 sizes
[SEND_SUPER
] = 3;
115 sizes
[SEND_PLUS
] = 1;
116 sizes
[SEND_MINUS
] = 1;
126 sizes
[SEND_BITSHIFT
] = 1;
127 sizes
[SEND_BITAND
] = 1;
128 sizes
[SEND_BITOR
] = 1;
129 sizes
[SEND_BITXOR
] = 1;
131 sizes
[SEND_AT_PUT
] = 1;
132 sizes
[SEND_SIZE
] = 1;
133 sizes
[SEND_VALUE
] = 1;
134 sizes
[SEND_VALUE_ARG
] = 1;
135 sizes
[SEND_IDENTITY_EQ
] = 1;
136 sizes
[SEND_CLASS
] = 1;
138 sizes
[SEND_NEW_ARG
] = 1;
141 static int size_message (Generator
*gt
, st_node
*node
);
142 static int size_expression (Generator
*gt
, st_node
*node
);
143 static int size_statements (Generator
*gt
, st_node
*node
);
146 static void generate_expression (Generator
*gt
, st_node
*node
);
147 static void generate_statements (Generator
*gt
, st_node
*statements
);
150 generation_error (Generator
*gt
, const char *message
, st_node
*node
)
153 strncpy (gt
->error
->message
, message
, 255);
154 gt
->error
->line
= node
->line
;
155 gt
->error
->column
= 0;
158 longjmp (gt
->jmploc
, 0);
162 get_temporaries (Generator
*gt
,
165 st_node
*temporaries
)
167 st_list
*temps
= NULL
;
169 for (st_node
*n
= arguments
; n
; n
= n
->next
) {
171 for (st_list
*l
= instvars
; l
; l
= l
->next
) {
172 if (streq (n
->variable
.name
, (char *) l
->data
))
173 generation_error (gt
, "name is already defined", arguments
);
175 temps
= st_list_prepend (temps
, (st_pointer
) n
->variable
.name
);
178 for (st_node
*n
= temporaries
; n
; n
= n
->next
) {
180 for (st_list
*l
= instvars
; l
; l
= l
->next
) {
181 if (streq (n
->variable
.name
, (char *) l
->data
))
182 generation_error (gt
, "name is already defined", temporaries
);
184 temps
= st_list_prepend (temps
, (st_pointer
) n
->variable
.name
);
187 return st_list_reverse (temps
);
195 gt
= st_new0 (Generator
);
200 gt
->temporaries
= NULL
;
202 gt
->max_stack_depth
= 0;
203 gt
->references_super
= false;
205 gt
->code
= st_malloc (DEFAULT_CODE_SIZE
);
206 gt
->alloc
= DEFAULT_CODE_SIZE
;
213 generator_destroy (Generator
*gt
)
215 st_list_destroy (gt
->instvars
);
216 st_list_destroy (gt
->temporaries
);
217 st_list_destroy (gt
->literals
);
224 create_literals_array (Generator
*gt
)
227 st_oop literals
= st_nil
;
229 if (gt
->references_super
)
230 gt
->literals
= st_list_append (gt
->literals
, (st_pointer
) gt
->class);
232 count
= st_list_length (gt
->literals
);
235 literals
= st_object_new_arrayed (st_array_class
, count
);
238 for (st_list
*l
= gt
->literals
; l
; l
= l
->next
) {
239 st_array_at_put (literals
, i
, (st_oop
) l
->data
);
248 create_bytecode_array (Generator
*gt
)
256 bytecode
= st_object_new_arrayed (st_byte_array_class
, gt
->size
);
257 bytes
= st_byte_array_bytes (bytecode
);
258 memcpy (bytes
, gt
->code
, gt
->size
);
264 emit (Generator
*gt
, st_uchar code
)
266 if (++gt
->size
> gt
->alloc
) {
267 gt
->alloc
+= gt
->alloc
;
268 gt
->code
= st_realloc (gt
->code
, gt
->alloc
);
271 gt
->code
[gt
->size
- 1] = code
;
276 find_instvar (Generator
*gt
, char *name
)
279 for (st_list
*l
= gt
->instvars
; l
; l
= l
->next
) {
281 if (streq (name
, (char *) l
->data
))
289 find_temporary (Generator
*gt
, char *name
)
293 for (st_list
*l
= gt
->temporaries
; l
; l
= l
->next
) {
295 if (streq (name
, (char *) l
->data
))
303 find_literal_const (Generator
*gt
, st_oop literal
)
306 for (st_list
*l
= gt
->literals
; l
; l
= l
->next
) {
308 if (st_object_equal (literal
, (st_oop
) l
->data
))
312 gt
->literals
= st_list_append (gt
->literals
, (void *) literal
);
317 find_literal_var (Generator
*gt
, char *name
)
321 assoc
= st_dictionary_association_at (st_globals
, st_symbol_new (name
));
326 for (st_list
*l
= gt
->literals
; l
; l
= l
->next
) {
327 if (st_object_equal (assoc
, (st_oop
) l
->data
))
331 gt
->literals
= st_list_append (gt
->literals
, (st_pointer
) assoc
);
336 jump_offset (Generator
*gt
, int offset
)
338 st_assert (offset
<= INT16_MAX
);
343 emit (gt
, offset
& 0xFF);
345 emit (gt
, (offset
>> 8) & 0xFF);
350 assign_temp (Generator
*gt
, int index
, bool pop
)
352 st_assert (index
<= 255);
355 emit (gt
, STORE_POP_TEMP
);
357 emit (gt
, STORE_TEMP
);
358 emit (gt
, (st_uchar
) index
);
362 assign_instvar (Generator
*gt
, int index
, bool pop
)
364 st_assert (index
<= 255);
367 emit (gt
, STORE_POP_INSTVAR
);
369 emit (gt
, STORE_INSTVAR
);
370 emit (gt
, (st_uchar
) index
);
374 assign_literal_var (Generator
*gt
, int index
, bool pop
)
376 st_assert (index
<= 255);
379 emit (gt
, STORE_POP_LITERAL_VAR
);
381 emit (gt
, STORE_LITERAL_VAR
);
382 emit (gt
, (st_uchar
) index
);
386 push (Generator
*gt
, st_uchar code
, st_uchar index
)
391 gt
->max_stack_depth
++;
396 push_special (Generator
*gt
, st_uchar code
)
399 gt
->max_stack_depth
++;
403 size_assign (Generator
*gt
, st_node
*node
)
405 return size_expression (gt
, node
->assign
.expression
) + 2;
409 generate_assign (Generator
*gt
, st_node
*node
, bool pop
)
413 generate_expression (gt
, node
->assign
.expression
);
415 index
= find_temporary (gt
, node
->assign
.assignee
->variable
.name
);
417 assign_temp (gt
, index
, pop
);
421 index
= find_instvar (gt
, node
->assign
.assignee
->variable
.name
);
423 assign_instvar (gt
, index
, pop
);
427 index
= find_literal_var (gt
, node
->assign
.assignee
->variable
.name
);
429 assign_literal_var (gt
, index
, pop
);
433 generation_error (gt
, "unknown variable", node
);
437 size_return (Generator
*gt
, st_node
*node
)
441 size
+= size_expression (gt
, node
->retrn
.expression
);
443 size
+= sizes
[RETURN_STACK_TOP
];
449 generate_return (Generator
*gt
, st_node
*node
)
451 generate_expression (gt
, node
->retrn
.expression
);
453 emit (gt
, RETURN_STACK_TOP
);
457 get_block_temporaries (Generator
*gt
, st_node
*temporaries
)
459 st_list
*temps
= NULL
;
461 for (st_node
*node
= temporaries
; node
; node
= node
->next
) {
463 for (st_list
*l
= gt
->instvars
; l
; l
= l
->next
) {
464 if (streq (node
->variable
.name
, (char *) l
->data
))
465 generation_error (gt
, "name is already defined", node
);
468 for (st_list
*l
= gt
->temporaries
; l
; l
= l
->next
) {
469 if (streq (node
->variable
.name
, (char *) l
->data
))
470 generation_error (gt
, "name already used in method", node
);
473 temps
= st_list_prepend (temps
, (st_pointer
) node
->variable
.name
);
477 return st_list_reverse (temps
);
482 size_block (Generator
*gt
, st_node
*node
)
486 size
+= sizes
[BLOCK_COPY
];
488 size
+= sizes
[STORE_POP_TEMP
] * st_node_list_length (node
->block
.arguments
);
489 size
+= size_statements (gt
, node
->block
.statements
);
490 size
+= sizes
[BLOCK_RETURN
];
496 generate_block (Generator
*gt
, st_node
*node
)
501 in_block
= gt
->in_block
;
504 emit (gt
, BLOCK_COPY
);
505 emit (gt
, st_node_list_length (node
->block
.arguments
));
507 // get size of block code and then jump around that code
508 size
= 2 * st_node_list_length (node
->block
.arguments
);
509 size
+= size_statements (gt
, node
->block
.statements
);
510 size
+= sizes
[BLOCK_RETURN
];
511 jump_offset (gt
, size
);
513 /* Store all block arguments into the temporary frame.
514 Note that upon a block activation, the stack pointer sits
515 above the last argument to to the block */
517 st_uint i
= st_node_list_length (node
->block
.arguments
);
519 l
= st_node_list_at (node
->block
.arguments
, i
- 1);
520 index
= find_temporary (gt
, l
->variable
.name
);
521 st_assert (index
>= 0);
522 assign_temp (gt
, index
, true);
525 generate_statements (gt
, node
->block
.statements
);
527 emit (gt
, BLOCK_RETURN
);
529 if (in_block
== false)
530 gt
->in_block
= false;
534 generation_func_1 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
539 block
= node
->message
.arguments
;
540 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
541 generation_error (gt
, "argument of ifTrue: message must be a 0-argument block", block
);
543 generate_expression (gt
, node
->message
.receiver
);
545 size
= size_statements (gt
, block
->block
.statements
);
547 if (!node
->message
.is_statement
)
550 size
+= sizes
[POP_STACK_TOP
];
552 if (subpattern_index
== 0)
553 emit (gt
, JUMP_FALSE
);
555 emit (gt
, JUMP_TRUE
);
556 emit (gt
, size
& 0xFF);
557 emit (gt
, (size
>> 8) & 0xFF);
559 generate_statements (gt
, block
->block
.statements
);
561 if (!node
->message
.is_statement
) {
567 emit (gt
, POP_STACK_TOP
);
573 size_func_1 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
578 block
= node
->message
.arguments
;
579 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
580 generation_error (gt
, "argument of ifTrue: message must be a 0-argument block", block
);
583 size
+= size_expression (gt
, node
->message
.receiver
);
584 size
+= sizes
[JUMP_TRUE
];
585 size
+= size_statements (gt
, node
->message
.arguments
->block
.statements
);
587 if (!node
->message
.is_statement
) {
589 size
+= sizes
[PUSH_NIL
];
591 size
+= sizes
[POP_STACK_TOP
];
599 generation_func_2 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
603 st_node
*true_block
, *false_block
;
605 true_block
= node
->message
.arguments
;
606 if (true_block
->type
!= ST_BLOCK_NODE
|| true_block
->block
.arguments
!= NULL
)
607 generation_error (gt
, "first argument of ifTrue:ifFalse message must be a 0-argument block", true_block
);
608 false_block
= node
->message
.arguments
->next
;
609 if (false_block
->type
!= ST_BLOCK_NODE
|| false_block
->block
.arguments
!= NULL
)
610 generation_error (gt
, "second argument of ifTrue:ifFalse message must be a 0-argument block", false_block
);
612 generate_expression (gt
, node
->message
.receiver
);
614 // add 3 for size of jump instr at end of true block
615 size
= size_statements (gt
, true_block
->block
.statements
);
618 if (subpattern_index
== 0)
619 emit (gt
, JUMP_FALSE
);
621 emit (gt
, JUMP_TRUE
);
622 emit (gt
, size
& 0xFF);
623 emit (gt
, (size
>> 8) & 0xFF);
626 generate_statements (gt
, true_block
->block
.statements
);
628 size
= size_statements (gt
, false_block
->block
.statements
);
630 emit (gt
, size
& 0xFF);
631 emit (gt
, (size
>> 8) & 0xFF);
633 generate_statements (gt
, false_block
->block
.statements
);
635 if (node
->message
.is_statement
)
636 emit (gt
, POP_STACK_TOP
);
640 size_func_2 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
644 st_node
*true_block
, *false_block
;
646 true_block
= node
->message
.arguments
;
647 if (true_block
->type
!= ST_BLOCK_NODE
|| true_block
->block
.arguments
!= NULL
)
648 generation_error (gt
, "first argument of ifTrue:ifFalse message must be a 0-argument block", true_block
);
649 false_block
= node
->message
.arguments
->next
;
650 if (false_block
->type
!= ST_BLOCK_NODE
|| false_block
->block
.arguments
!= NULL
)
651 generation_error (gt
, "second argument of ifTrue:ifFalse message must be a 0-argument block", false_block
);
653 size
+= size_expression (gt
, node
->message
.receiver
);
654 size
+= sizes
[JUMP_TRUE
];
657 size
+= size_statements (gt
, node
->message
.arguments
->block
.statements
);
659 size
+= size_statements (gt
, node
->message
.arguments
->next
->block
.statements
);
661 if (node
->message
.is_statement
)
662 size
+= sizes
[POP_STACK_TOP
];
668 generation_func_3 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
673 block
= node
->message
.receiver
;
674 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
675 generation_error (gt
, st_strdup_printf ("receiver of %s message must be a zero argument block",
676 subpattern_index
== 0 ? "#whileTrue" : "#whileFalse"), block
);
678 generate_statements (gt
, block
->block
.statements
);
680 // jump around jump statement
681 if (subpattern_index
== 0)
682 emit (gt
, JUMP_FALSE
);
684 emit (gt
, JUMP_TRUE
);
689 size
= size_statements (gt
, block
->block
.statements
);
690 size
+= sizes
[JUMP_FALSE
];
695 emit (gt
, size
& 0xFF);
696 emit (gt
, (size
>> 8) & 0xFF);
698 if (!node
->message
.is_statement
)
703 size_func_3 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
708 block
= node
->message
.receiver
;
709 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
710 generation_error (gt
, st_strdup_printf ("receiver of %s message must be a zero argument block",
711 subpattern_index
== 0 ? "#whileTrue" : "#whileFalse"), block
);
713 size
+= size_statements (gt
, node
->message
.receiver
->block
.statements
);
714 size
+= sizes
[JUMP_TRUE
];
717 if (!node
->message
.is_statement
)
718 size
+= sizes
[PUSH_NIL
];
724 generation_func_4 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
729 block
= node
->message
.receiver
;
730 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
731 generation_error (gt
, st_strdup_printf ("receiver of %s message must be a zero argument block",
732 subpattern_index
== 0 ? "#whileTrue:" : "#whileFalse:"), block
);
734 block
= node
->message
.arguments
;
735 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
736 generation_error (gt
, st_strdup_printf ("argument of %s message must be a zero argument block",
737 subpattern_index
== 0 ? "#whileTrue:" : "#whileFalse:"), block
);
739 generate_statements (gt
, node
->message
.receiver
->block
.statements
);
741 if (subpattern_index
== 0)
742 emit (gt
, JUMP_FALSE
);
744 emit (gt
, JUMP_TRUE
);
746 size
= size_statements (gt
, node
->message
.arguments
->block
.statements
);
747 // include size of POP and JUMP statement
748 size
+= sizes
[POP_STACK_TOP
] + sizes
[JUMP
];
750 emit (gt
, size
& 0xFF);
751 emit (gt
, (size
>> 8) & 0xFF);
754 generate_statements (gt
, node
->message
.arguments
->block
.statements
);
756 size
+= size_statements (gt
, node
->message
.receiver
->block
.statements
);
759 emit (gt
, POP_STACK_TOP
);
762 emit (gt
, size
& 0xFF);
763 emit (gt
, (size
>> 8) & 0xFF);
765 if (!node
->message
.is_statement
)
771 size_func_4 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
776 block
= node
->message
.receiver
;
777 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
778 generation_error (gt
, st_strdup_printf ("receiver of %s message must be a zero argument block",
779 subpattern_index
== 0 ? "#whileTrue:" : "#whileFalse:"), block
);
781 block
= node
->message
.arguments
;
782 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
783 generation_error (gt
, st_strdup_printf ("argument of %s message must be a zero argument block",
784 subpattern_index
== 0 ? "#whileTrue:" : "#whileFalse:"), block
);
786 size
+= size_statements (gt
, node
->message
.receiver
->block
.statements
);
787 size
+= sizes
[JUMP_TRUE
];
788 size
+= size_statements (gt
, node
->message
.arguments
->block
.statements
);
789 size
+= sizes
[POP_STACK_TOP
] + sizes
[JUMP
];
791 if (!node
->message
.is_statement
)
792 size
+= sizes
[PUSH_NIL
];
798 generation_func_5 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
803 block
= node
->message
.arguments
;
804 if (block
->type
!= ST_BLOCK_NODE
|| block
->block
.arguments
!= NULL
)
805 generation_error (gt
, st_strdup_printf ("argument of %s message must be a zero argument block",
806 subpattern_index
== 0 ? "#and:" : "#or:"), block
);
808 generate_expression (gt
, node
->message
.receiver
);
810 size
= size_statements (gt
, block
->block
.statements
);
811 // size of JUMP instr after block statements
814 if (subpattern_index
== 0)
815 emit (gt
, JUMP_FALSE
);
817 emit (gt
, JUMP_TRUE
);
818 emit (gt
, size
& 0xFF);
819 emit (gt
, (size
>> 8) & 0xFF);
821 generate_statements (gt
, block
->block
.statements
);
827 if (subpattern_index
== 0)
828 emit (gt
, PUSH_FALSE
);
830 emit (gt
, PUSH_TRUE
);
832 if (node
->message
.is_statement
)
833 emit (gt
, POP_STACK_TOP
);
838 size_func_5 (Generator
*gt
, st_node
*node
, st_uint subpattern_index
)
842 size
+= size_expression (gt
, node
->message
.receiver
);
843 size
+= sizes
[JUMP_TRUE
];
844 size
+= size_statements (gt
, node
->message
.arguments
->block
.statements
);
846 size
+= sizes
[PUSH_TRUE
];
848 if (node
->message
.is_statement
)
849 size
+= sizes
[POP_STACK_TOP
];
854 typedef void (* CodeGenerationFunc
) (Generator
*gt
, st_node
*message
, st_uint subpattern_index
);
855 typedef int (* CodeSizeFunc
) (Generator
*gt
, st_node
*message
, st_uint subpattern_index
);
857 static const struct generators
{
859 const char *const pattern
[3];
860 CodeGenerationFunc generation_func
;
861 CodeSizeFunc size_func
;
865 { { "ifTrue:", "ifFalse", NULL
},
866 generation_func_1
, size_func_1
},
867 { { "ifTrue:ifFalse:", "ifFalse:ifTrue:", NULL
},
868 generation_func_2
, size_func_2
},
869 { { "whileTrue", "whileFalse", NULL
},
870 generation_func_3
, size_func_3
},
871 { { "whileTrue:", "whileFalse:", NULL
},
872 generation_func_4
, size_func_4
},
873 { { "and:", "or:", NULL
},
874 generation_func_5
, size_func_5
},
878 size_message_send (Generator
*gt
, st_node
*node
)
883 args
= node
->message
.arguments
;
884 for (; args
; args
= args
->next
)
885 size
+= size_expression (gt
, args
);
887 /* check if message is a special */
888 for (int i
= 0; i
< ST_N_ELEMENTS (st_specials
); i
++) {
889 if (!node
->message
.super_send
&& node
->message
.selector
== st_specials
[i
]) {
899 if (node
->message
.is_statement
)
900 size
+= sizes
[POP_STACK_TOP
];
906 generate_message_send (Generator
*gt
, st_node
*node
)
909 st_uint argcount
= 0;
911 /* generate arguments */
912 args
= node
->message
.arguments
;
913 for (; args
; args
= args
->next
) {
914 generate_expression (gt
, args
);
918 /* check if message is a special */
919 for (int i
= 0; i
< ST_N_ELEMENTS (st_specials
); i
++) {
920 if (!node
->message
.super_send
&& node
->message
.selector
== st_specials
[i
]) {
921 emit (gt
, SEND_PLUS
+ i
);
926 if (node
->message
.super_send
)
927 emit (gt
, SEND_SUPER
);
931 emit (gt
, (st_uchar
) argcount
);
933 int index
= find_literal_const (gt
, node
->message
.selector
);
934 emit (gt
, (st_uchar
) index
);
938 if (node
->message
.is_statement
)
939 emit (gt
, POP_STACK_TOP
);
944 size_cascade (Generator
*gt
, st_node
*node
)
949 size
+= size_expression (gt
, node
->cascade
.receiver
);
950 size
+= sizes
[DUPLICATE_STACK_TOP
];
952 for (st_list
*l
= node
->cascade
.messages
; l
; l
= l
->next
) {
954 size
+= size_message_send (gt
, (st_node
*) l
->data
);
956 if (l
->next
|| node
->cascade
.is_statement
)
957 size
+= sizes
[POP_STACK_TOP
];
959 if (l
->next
&& l
->next
->next
)
960 size
+= sizes
[DUPLICATE_STACK_TOP
];
967 generate_cascade (Generator
*gt
, st_node
*node
)
971 generate_expression (gt
, node
->cascade
.receiver
);
972 emit (gt
, DUPLICATE_STACK_TOP
);
974 for (st_list
*l
= node
->cascade
.messages
; l
; l
= l
->next
) {
976 generate_message_send (gt
, (st_node
*) l
->data
);
978 if (l
->next
|| node
->cascade
.is_statement
)
979 emit (gt
, POP_STACK_TOP
);
981 if (l
->next
&& l
->next
->next
)
982 emit (gt
, DUPLICATE_STACK_TOP
);
987 size_message (Generator
*gt
, st_node
*node
)
989 const char *selector
;
993 selector
= CSTRING (node
->message
.selector
);
995 for (i
= 0; i
< ST_N_ELEMENTS (generators
); i
++) {
996 for (j
= 0; j
< ST_N_ELEMENTS (generators
[i
].pattern
); j
++) {
997 if (generators
[i
].pattern
[j
] && strcmp (generators
[i
].pattern
[j
], selector
) == 0) {
998 size
+= generators
[i
].size_func (gt
, node
, j
);
1004 size
+= size_expression (gt
, node
->message
.receiver
);
1005 size
+= size_message_send (gt
, node
);
1011 generate_message (Generator
*gt
, st_node
*node
)
1013 const char *selector
;
1016 selector
= CSTRING (node
->message
.selector
);
1018 for (i
= 0; i
< ST_N_ELEMENTS (generators
); i
++) {
1019 for (j
= 0; j
< ST_N_ELEMENTS (generators
[i
].pattern
); j
++) {
1020 if (generators
[i
].pattern
[j
] && strcmp (generators
[i
].pattern
[j
], selector
) == 0) {
1021 generators
[i
].generation_func (gt
, node
, j
);
1027 generate_expression (gt
, node
->message
.receiver
);
1028 generate_message_send (gt
, node
);
1032 size_expression (Generator
*gt
, st_node
*node
)
1037 switch (node
->type
) {
1038 case ST_VARIABLE_NODE
:
1040 const char *name
= node
->variable
.name
;
1042 if (streq (name
, "self") || streq (name
, "super")) {
1043 size
+= sizes
[PUSH_SELF
];
1045 } else if (streq (name
, "true")) {
1046 size
+= sizes
[PUSH_TRUE
];
1048 } else if (streq (name
, "false")) {
1049 size
+= sizes
[PUSH_FALSE
];
1051 } else if (streq (name
, "nil")) {
1052 size
+= sizes
[PUSH_NIL
];
1054 } else if (streq (name
, "thisContext")) {
1055 size
+= sizes
[PUSH_ACTIVE_CONTEXT
];
1059 index
= find_temporary (gt
, node
->variable
.name
);
1064 index
= find_instvar (gt
, node
->variable
.name
);
1069 index
= find_literal_var (gt
, node
->variable
.name
);
1074 generation_error (gt
, "unknown variable", node
);
1076 case ST_LITERAL_NODE
:
1078 /* use optimized PUSH_INTEGER for smis in the range of -127..127 */
1079 if (st_object_is_smi (node
->literal
.value
) &&
1080 ((st_smi_value (node
->literal
.value
) >= -127) &&
1081 (st_smi_value (node
->literal
.value
) <= 127))) {
1082 size
+= sizes
[PUSH_INTEGER
];
1084 size
+= sizes
[PUSH_LITERAL_CONST
];
1089 case ST_ASSIGN_NODE
:
1090 size
+= size_assign (gt
, node
);
1094 size
+= size_block (gt
, node
);
1097 case ST_MESSAGE_NODE
:
1099 size
+= size_message (gt
, node
);
1102 case ST_CASCADE_NODE
:
1104 size
+= size_cascade (gt
, node
);
1108 st_assert_not_reached ();
1115 generate_expression (Generator
*gt
, st_node
*node
)
1119 switch (node
->type
) {
1120 case ST_VARIABLE_NODE
:
1122 const char *name
= node
->variable
.name
;
1124 if (streq (name
, "self")) {
1125 push_special (gt
, PUSH_SELF
);
1127 } else if (streq (name
, "super")) {
1128 gt
->references_super
= true;
1129 push_special (gt
, PUSH_SELF
);
1131 } else if (streq (name
, "true")) {
1132 push_special (gt
, PUSH_TRUE
);
1134 } else if (streq (name
, "false")) {
1135 push_special (gt
, PUSH_FALSE
);
1137 } else if (streq (name
, "nil")) {
1138 push_special (gt
, PUSH_NIL
);
1140 } else if (streq (name
, "thisContext")) {
1141 push_special (gt
, PUSH_ACTIVE_CONTEXT
);
1145 index
= find_temporary (gt
, node
->variable
.name
);
1147 push (gt
, PUSH_TEMP
, index
);
1150 index
= find_instvar (gt
, node
->variable
.name
);
1152 push (gt
, PUSH_INSTVAR
, index
);
1155 index
= find_literal_var (gt
, node
->variable
.name
);
1157 push (gt
, PUSH_LITERAL_VAR
, index
);
1160 generation_error (gt
, "unknown variable", node
);
1163 case ST_LITERAL_NODE
:
1165 /* use optimized PUSH_INTEGER for smis in the range of -127..127 */
1166 if (st_object_is_smi (node
->literal
.value
) &&
1167 ((st_smi_value (node
->literal
.value
) >= -127) &&
1168 (st_smi_value (node
->literal
.value
) <= 127))) {
1169 emit (gt
, PUSH_INTEGER
);
1170 emit (gt
, st_smi_value (node
->literal
.value
));
1172 index
= find_literal_const (gt
, node
->literal
.value
);
1173 push (gt
, PUSH_LITERAL_CONST
, index
);
1177 case ST_ASSIGN_NODE
:
1178 generate_assign (gt
, node
, false);
1182 generate_block (gt
, node
);
1185 case ST_MESSAGE_NODE
:
1186 generate_message (gt
, node
);
1189 case ST_CASCADE_NODE
:
1190 generate_cascade (gt
, node
);
1194 st_assert_not_reached ();
1199 size_statements (Generator
*gt
, st_node
*statements
)
1203 if (statements
== NULL
)
1204 size
+= sizes
[PUSH_NIL
];
1206 for (st_node
*node
= statements
; node
; node
= node
->next
) {
1208 switch (node
->type
) {
1210 case ST_VARIABLE_NODE
:
1211 case ST_LITERAL_NODE
:
1214 * don't generate anything since we would end up with a constant
1215 * expression with no side-effects.
1217 * However, in a block with no explicit return, the value of the last statement is the implicit
1218 * value of the block.
1220 if (node
->next
== NULL
)
1221 size
+= size_expression (gt
, node
);
1225 case ST_ASSIGN_NODE
:
1227 size
+= size_assign (gt
, node
);
1231 case ST_RETURN_NODE
:
1233 st_assert (node
->next
== NULL
);
1234 size
+= size_return (gt
, node
);
1237 case ST_MESSAGE_NODE
:
1239 size
+= size_message (gt
, node
);
1242 case ST_CASCADE_NODE
:
1244 size
+= size_cascade (gt
, node
);
1248 st_assert_not_reached ();
1256 generate_statements (Generator
*gt
, st_node
*statements
)
1258 if (statements
== NULL
) {
1259 emit (gt
, PUSH_NIL
);
1262 for (st_node
*node
= statements
; node
; node
= node
->next
) {
1264 switch (node
->type
) {
1266 case ST_VARIABLE_NODE
:
1267 case ST_LITERAL_NODE
:
1270 * don't generate anything in this case since we would end up with a constant
1271 * expression with no side-effects.
1273 * However, in a block with no explicit return, the value of the last statement is the implicit
1274 * value of the block.
1276 if (node
->next
== NULL
)
1277 generate_expression (gt
, node
);
1280 case ST_ASSIGN_NODE
:
1282 /* don't use STORE_POP if this is the last statement */
1283 if (node
->next
== NULL
)
1284 generate_assign (gt
, node
, false);
1286 generate_assign (gt
, node
, true);
1289 case ST_RETURN_NODE
:
1291 st_assert (node
->next
== NULL
);
1292 generate_return (gt
, node
);
1295 case ST_MESSAGE_NODE
:
1297 generate_message (gt
, node
);
1300 case ST_CASCADE_NODE
:
1302 generate_cascade (gt
, node
);
1306 st_assert_not_reached ();
1313 generate_method_statements (Generator
*gt
, st_node
*statements
)
1315 for (st_node
*node
= statements
; node
; node
= node
->next
) {
1317 switch (node
->type
) {
1319 case ST_VARIABLE_NODE
:
1320 case ST_LITERAL_NODE
:
1324 case ST_ASSIGN_NODE
:
1326 generate_assign (gt
, node
, true);
1329 case ST_RETURN_NODE
:
1331 st_assert (node
->next
== NULL
);
1332 generate_return (gt
, node
);
1335 case ST_MESSAGE_NODE
:
1337 generate_message (gt
, node
);
1340 case ST_CASCADE_NODE
:
1342 generate_cascade (gt
, node
);
1346 st_assert_not_reached ();
1350 emit (gt
, PUSH_SELF
);
1351 emit (gt
, RETURN_STACK_TOP
);
1355 collect_temporaries (Generator
*gt
, st_node
*node
)
1357 st_list
*temps
= NULL
;
1362 if (node
->type
== ST_BLOCK_NODE
)
1363 temps
= st_list_concat (get_block_temporaries (gt
, node
->block
.arguments
),
1364 get_block_temporaries (gt
, node
->block
.temporaries
));
1366 switch (node
->type
) {
1368 temps
= st_list_concat (temps
, collect_temporaries (gt
, node
->block
.statements
));
1370 case ST_ASSIGN_NODE
:
1371 temps
= st_list_concat (temps
, collect_temporaries (gt
, node
->assign
.expression
));
1373 case ST_RETURN_NODE
:
1374 temps
= st_list_concat (temps
, collect_temporaries (gt
, node
->retrn
.expression
));
1376 case ST_MESSAGE_NODE
:
1377 temps
= st_list_concat (temps
, collect_temporaries (gt
, node
->message
.receiver
));
1378 temps
= st_list_concat (temps
, collect_temporaries (gt
, node
->message
.arguments
));
1381 case ST_CASCADE_NODE
:
1382 temps
= st_list_concat (temps
, collect_temporaries (gt
, node
->cascade
.receiver
));
1383 for (st_list
*l
= node
->cascade
.messages
; l
; l
= l
->next
)
1384 temps
= st_list_concat (temps
, collect_temporaries (gt
, (st_node
*) l
->data
));
1388 case ST_METHOD_NODE
:
1389 case ST_VARIABLE_NODE
:
1390 case ST_LITERAL_NODE
:
1394 temps
= st_list_concat (temps
, collect_temporaries (gt
, node
->next
));
1400 st_generate_method (st_oop
class, st_node
*node
, st_compiler_error
*error
)
1405 st_assert (class != st_nil
);
1406 st_assert (node
!= NULL
&& node
->type
== ST_METHOD_NODE
);
1410 gt
= generator_new ();
1413 if (setjmp (gt
->jmploc
))
1417 gt
->instvars
= st_behavior_all_instance_variables (class);
1418 gt
->temporaries
= get_temporaries (gt
, gt
->instvars
, node
->method
.arguments
, node
->method
.temporaries
);
1420 /* collect all block-level temporaries */
1421 gt
->temporaries
= st_list_concat (gt
->temporaries
, collect_temporaries (gt
, node
->method
.statements
));
1423 // generate bytecode
1424 generate_method_statements (gt
, node
->method
.statements
);
1426 method
= st_object_new (st_compiled_method_class
);
1428 ST_METHOD_HEADER (method
) = st_smi_new (0);
1433 argcount
= st_node_list_length (node
->method
.arguments
);
1434 tempcount
= st_list_length (gt
->temporaries
) - st_node_list_length (node
->method
.arguments
);
1436 st_method_set_arg_count (method
, argcount
);
1437 st_method_set_temp_count (method
, tempcount
);
1438 st_method_set_large_context (method
, (gt
->max_stack_depth
+ argcount
+ tempcount
) > 12);
1440 if (node
->method
.primitive
>= 0) {
1441 st_method_set_flags (method
, ST_METHOD_PRIMITIVE
);
1443 st_method_set_flags (method
, ST_METHOD_NORMAL
);
1446 st_method_set_primitive_index (method
, node
->method
.primitive
);
1448 ST_METHOD_LITERALS (method
) = create_literals_array (gt
);
1449 ST_METHOD_BYTECODE (method
) = create_bytecode_array (gt
);
1450 ST_METHOD_SELECTOR (method
) = node
->method
.selector
;
1452 generator_destroy (gt
);
1458 generator_destroy (gt
);
1467 #define FORMAT(ip) (formats[sizes[*ip]-1])
1470 print_bytecodes (st_oop literals
, st_uchar
*codes
, int len
)
1472 static const char * const formats
[] = {
1475 "<%02x %02x %02x> ",
1478 st_uchar
*ip
= codes
;
1482 printf ("%3li ", ip
- codes
);
1484 switch ((Code
) *ip
) {
1487 printf (FORMAT (ip
), ip
[0], ip
[1]);
1488 printf ("pushTemp: %i", ip
[1]);
1493 printf (FORMAT (ip
), ip
[0], ip
[1]);
1494 printf ("pushInstvar: %i", ip
[1]);
1498 case PUSH_LITERAL_CONST
:
1499 printf (FORMAT (ip
), ip
[0], ip
[1]);
1500 printf ("pushConst: %i", ip
[1]);
1504 case PUSH_LITERAL_VAR
:
1505 printf (FORMAT (ip
), ip
[0], ip
[1]);
1506 printf ("pushLit: %i", ip
[1]);
1511 printf (FORMAT (ip
), ip
[0]);
1512 printf ("push: self");
1517 printf (FORMAT (ip
), ip
[0]);
1518 printf ("pushConst: true");
1523 printf (FORMAT (ip
), ip
[0]);
1524 printf ("pushConst: false");
1529 printf (FORMAT (ip
), ip
[0]);
1530 printf ("pushConst: nil");
1535 printf (FORMAT (ip
), ip
[0], ip
[1]);
1536 printf ("pushConst: %i", (signed char) ip
[1]);
1540 case PUSH_ACTIVE_CONTEXT
:
1541 printf (FORMAT (ip
), ip
[0]);
1542 printf ("push: thisContext");
1547 printf (FORMAT (ip
), ip
[0], ip
[1]);
1548 printf ("storeTemp: %i", ip
[1]);
1553 printf (FORMAT (ip
), ip
[0], ip
[1]);
1554 printf ("storeInstvar: %i", ip
[1]);
1558 case STORE_LITERAL_VAR
:
1559 printf (FORMAT (ip
), ip
[0], ip
[1]);
1560 printf ("storeLiteral: %i", ip
[1]);
1564 case STORE_POP_TEMP
:
1565 printf (FORMAT (ip
), ip
[0], ip
[1]);
1566 printf ("popIntoTemp: %i", ip
[1]);
1570 case STORE_POP_INSTVAR
:
1571 printf (FORMAT (ip
), ip
[0], ip
[1]);
1572 printf ("popIntoInstvar: %i", ip
[1]);
1576 case STORE_POP_LITERAL_VAR
:
1577 printf (FORMAT (ip
), ip
[0], ip
[1]);
1578 printf ("popIntoLiteral: %i", ip
[1]);
1583 printf (FORMAT (ip
), ip
[0], ip
[1]);
1584 printf ("blockCopy: %i", ip
[1]);
1589 printf (FORMAT (ip
), ip
[0], ip
[1], ip
[2]);
1591 short offset
= ((ip
[1] << 8) | ip
[2]);
1592 printf ("jump: %li", (offset
>= 0 ? 3 : 0) + (ip
- codes
) + offset
);
1597 printf (FORMAT (ip
), ip
[0], ip
[1], ip
[2]);
1598 printf ("jumpTrue: %li", 3 + (ip
- codes
) + ((ip
[1] << 8) | ip
[2]));
1603 printf (FORMAT (ip
), ip
[0], ip
[1], ip
[2]);
1604 printf ("jumpFalse: %li", 3 + (ip
- codes
) + ((ip
[1] << 8) | ip
[2]));
1609 printf (FORMAT (ip
), ip
[0]);
1614 case DUPLICATE_STACK_TOP
:
1615 printf (FORMAT (ip
), ip
[0]);
1620 case RETURN_STACK_TOP
:
1621 printf (FORMAT (ip
), ip
[0]);
1622 printf ("returnTop");
1630 printf (FORMAT (ip
), ip
[0]);
1631 printf ("blockReturn");
1639 selector
= st_array_at (literals
, ip
[2] + 1);
1641 printf (FORMAT (ip
), ip
[0], ip
[1], ip
[2]);
1643 printf ("send: #%s", (char *) st_byte_array_bytes (selector
));
1651 selector
= st_array_at (literals
, ip
[2] + 1);
1653 printf (FORMAT (ip
), ip
[0], ip
[1], ip
[2]);
1655 printf ("sendSuper: #%s", (char *) st_byte_array_bytes (selector
));
1679 case SEND_VALUE_ARG
:
1680 case SEND_IDENTITY_EQ
:
1685 printf (FORMAT (ip
), ip
[0]);
1686 printf ("sendSpecial: #%s", st_byte_array_bytes (st_specials
[ip
[0] - SEND_PLUS
]));
1697 print_literal (st_oop lit
)
1699 if (st_object_is_smi (lit
)) {
1701 printf ("%li", st_smi_value (lit
));
1703 } else if (st_object_is_symbol (lit
)) {
1705 printf ("#%s", (char *) st_byte_array_bytes (lit
));
1707 } else if (st_object_class (lit
) == st_string_class
) {
1709 printf ("'%s'", (char *) st_byte_array_bytes (lit
));
1711 } else if (st_object_class (lit
) == st_character_class
) {
1713 char outbuf
[6] = { 0 };
1714 st_unichar_to_utf8 (st_character_value (lit
), outbuf
);
1715 printf ("$%s", outbuf
);
1721 print_literals (st_oop literals
)
1723 if (literals
== st_nil
)
1726 printf ("literals: ");
1728 for (int i
= 1; i
<= st_smi_value (ST_ARRAYED_OBJECT (literals
)->size
); i
++) {
1730 st_oop lit
= st_array_at (literals
, i
);
1732 print_literal (lit
);
1741 st_print_method (st_oop method
)
1744 st_uchar
*bytecodes
;
1747 printf ("flags: %i; ", st_method_get_flags (method
));
1748 printf ("arg-count: %i; ", st_method_get_arg_count (method
));
1749 printf ("temp-count: %i; ", st_method_get_temp_count (method
));
1750 printf ("large-context: %i; ", st_method_get_large_context (method
));
1751 printf ("primitive: %i;\n", st_method_get_primitive_index (method
));
1755 literals
= ST_METHOD_LITERALS (method
);
1756 bytecodes
= st_method_bytecode_bytes (method
);
1757 size
= ST_ARRAYED_OBJECT (ST_METHOD_BYTECODE (method
))->size
;
1759 print_bytecodes (literals
, bytecodes
, size
);
1761 print_literals (literals
);