2 * Mesa 3-D graphics library
5 * Copyright (C) 2005 Brian Paul All Rights Reserved.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 * \file slang_assemble.c
27 * slang intermediate code assembler
32 #include "slang_utility.h"
33 #include "slang_assemble.h"
34 #include "slang_compile.h"
35 #include "slang_storage.h"
36 #include "slang_assemble_constructor.h"
37 #include "slang_assemble_typeinfo.h"
38 #include "slang_assemble_conditional.h"
42 static void slang_assembly_construct (slang_assembly
*asm)
44 asm->type
= slang_asm_none
;
47 static void slang_assembly_destruct (slang_assembly
*asm)
51 /* slang_assembly_file */
53 void slang_assembly_file_construct (slang_assembly_file
*file
)
59 void slang_assembly_file_destruct (slang_assembly_file
*file
)
63 for (i
= 0; i
< file
->count
; i
++)
64 slang_assembly_destruct (file
->code
+ i
);
65 slang_alloc_free (file
->code
);
68 static int slang_assembly_file_push_new (slang_assembly_file
*file
)
70 file
->code
= (slang_assembly
*) slang_alloc_realloc (file
->code
, file
->count
* sizeof (
71 slang_assembly
), (file
->count
+ 1) * sizeof (slang_assembly
));
72 if (file
->code
!= NULL
)
74 slang_assembly_construct (file
->code
+ file
->count
);
81 static int slang_assembly_file_push_general (slang_assembly_file
*file
, slang_assembly_type type
,
82 GLfloat literal
, GLuint label
, GLuint size
)
85 if (!slang_assembly_file_push_new (file
))
87 asm = file
->code
+ file
->count
- 1;
89 asm->literal
= literal
;
90 asm->param
[0] = label
;
95 int slang_assembly_file_push (slang_assembly_file
*file
, slang_assembly_type type
)
97 return slang_assembly_file_push_general (file
, type
, (GLfloat
) 0, 0, 0);
100 int slang_assembly_file_push_label (slang_assembly_file
*file
, slang_assembly_type type
,
103 return slang_assembly_file_push_general (file
, type
, (GLfloat
) 0, label
, 0);
106 int slang_assembly_file_push_label2 (slang_assembly_file
*file
, slang_assembly_type type
,
107 GLuint label1
, GLuint label2
)
109 return slang_assembly_file_push_general (file
, type
, (GLfloat
) 0, label1
, label2
);
112 int slang_assembly_file_push_literal (slang_assembly_file
*file
, slang_assembly_type type
,
115 return slang_assembly_file_push_general (file
, type
, literal
, 0, 0);
118 /* utility functions */
120 static int sizeof_variable (slang_type_specifier
*spec
, slang_operation
*array_size
,
121 slang_assembly_name_space
*space
, unsigned int *size
)
123 slang_storage_aggregate agg
;
125 slang_storage_aggregate_construct (&agg
);
126 if (!_slang_aggregate_variable (&agg
, spec
, array_size
, space
->funcs
, space
->structs
))
128 slang_storage_aggregate_destruct (&agg
);
131 *size
+= _slang_sizeof_aggregate (&agg
);
132 slang_storage_aggregate_destruct (&agg
);
136 static int sizeof_variable2 (slang_variable
*var
, slang_assembly_name_space
*space
,
139 var
->address
= *size
;
140 return sizeof_variable (&var
->type
.specifier
, var
->array_size
, space
, size
);
143 static int sizeof_variables (slang_variable_scope
*vars
, unsigned int start
, unsigned int stop
,
144 slang_assembly_name_space
*space
, unsigned int *size
)
148 for (i
= start
; i
< stop
; i
++)
149 if (!sizeof_variable2 (vars
->variables
+ i
, space
, size
))
154 static int collect_locals (slang_operation
*op
, slang_assembly_name_space
*space
,
159 if (!sizeof_variables (op
->locals
, 0, op
->locals
->num_variables
, space
, size
))
161 for (i
= 0; i
< op
->num_children
; i
++)
162 if (!collect_locals (op
->children
+ i
, space
, size
))
167 /* _slang_locate_function() */
169 slang_function
*_slang_locate_function (const char *name
, slang_operation
*params
,
170 unsigned int num_params
, slang_assembly_name_space
*space
)
174 for (i
= 0; i
< space
->funcs
->num_functions
; i
++)
177 slang_function
*f
= space
->funcs
->functions
+ i
;
179 if (slang_string_compare (name
, f
->header
.name
) != 0)
181 if (f
->param_count
!= num_params
)
183 for (j
= 0; j
< num_params
; j
++)
185 slang_assembly_typeinfo ti
;
186 slang_assembly_typeinfo_construct (&ti
);
187 if (!_slang_typeof_operation (params
+ j
, space
, &ti
))
189 slang_assembly_typeinfo_destruct (&ti
);
192 if (!slang_type_specifier_equal (&ti
.spec
, &f
->parameters
->variables
[j
].type
.specifier
))
194 slang_assembly_typeinfo_destruct (&ti
);
197 slang_assembly_typeinfo_destruct (&ti
);
198 /* "out" and "inout" formal parameter requires the actual parameter to be l-value */
199 if (!ti
.can_be_referenced
&&
200 f
->parameters
->variables
[j
].type
.qualifier
!= slang_qual_out
&&
201 f
->parameters
->variables
[j
].type
.qualifier
!= slang_qual_inout
)
207 if (space
->funcs
->outer_scope
!= NULL
)
209 slang_assembly_name_space my_space
= *space
;
210 my_space
.funcs
= space
->funcs
->outer_scope
;
211 return _slang_locate_function (name
, params
, num_params
, &my_space
);
216 /* _slang_assemble_function() */
218 int _slang_assemble_function (slang_assembly_file
*file
, slang_function
*fun
,
219 slang_assembly_name_space
*space
)
221 unsigned int param_size
, local_size
;
222 unsigned int skip
, cleanup
;
223 slang_assembly_flow_control flow
;
224 slang_assembly_local_info info
;
225 slang_assembly_stack_info stk
;
227 fun
->address
= file
->count
;
229 if (fun
->body
== NULL
)
231 /* TODO: jump to the actual function body */
235 /* calculate return value and parameters size */
237 if (fun
->header
.type
.specifier
.type
!= slang_spec_void
)
238 if (!sizeof_variable (&fun
->header
.type
.specifier
, NULL
, space
, ¶m_size
))
240 info
.ret_size
= param_size
;
241 if (!sizeof_variables (fun
->parameters
, 0, fun
->param_count
, space
, ¶m_size
))
244 /* calculate local variables size, take into account the four-byte return address and
245 temporaries for various tasks */
246 info
.addr_tmp
= param_size
+ 4;
247 info
.swizzle_tmp
= param_size
+ 4 + 4;
248 local_size
= param_size
+ 4 + 4 + 16;
249 if (!sizeof_variables (fun
->parameters
, fun
->param_count
, fun
->parameters
->num_variables
, space
,
252 if (!collect_locals (fun
->body
, space
, &local_size
))
255 /* allocate local variable storage */
256 if (!slang_assembly_file_push_label (file
, slang_asm_local_alloc
, local_size
- param_size
- 4))
259 /* mark a new frame for function variable storage */
260 if (!slang_assembly_file_push_label (file
, slang_asm_enter
, local_size
))
263 /* skip the cleanup jump */
265 if (!slang_assembly_file_push_new (file
))
267 file
->code
[skip
].type
= slang_asm_jump
;
269 /* all "return" statements will be directed here */
270 flow
.function_end
= file
->count
;
271 cleanup
= file
->count
;
272 if (!slang_assembly_file_push_new (file
))
274 file
->code
[cleanup
].type
= slang_asm_jump
;
276 /* execute the function body */
277 file
->code
[skip
].param
[0] = file
->count
;
278 if (!_slang_assemble_operation (file
, fun
->body
, 0, &flow
, space
, &info
, &stk
))
281 /* this is the end of the function - restore the old function frame */
282 file
->code
[cleanup
].param
[0] = file
->count
;
283 if (!slang_assembly_file_push (file
, slang_asm_leave
))
286 /* free local variable storage */
287 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, local_size
- param_size
- 4))
290 /* jump out of the function */
291 if (!slang_assembly_file_push (file
, slang_asm_return
))
296 int _slang_cleanup_stack (slang_assembly_file
*file
, slang_operation
*op
, int ref
,
297 slang_assembly_name_space
*space
)
299 slang_assembly_typeinfo ti
;
302 slang_assembly_typeinfo_construct (&ti
);
303 if (!_slang_typeof_operation (op
, space
, &ti
))
305 slang_assembly_typeinfo_destruct (&ti
);
308 if (ti
.spec
.type
== slang_spec_void
)
315 if (!sizeof_variable (&ti
.spec
, NULL
, space
, &size
))
317 slang_assembly_typeinfo_destruct (&ti
);
321 slang_assembly_typeinfo_destruct (&ti
);
324 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, size
))
330 /* _slang_assemble_operation() */
332 /* XXX: general swizzle! */
333 static int dereference_aggregate (slang_assembly_file
*file
, const slang_storage_aggregate
*agg
,
334 unsigned int index
, unsigned int *size
, slang_assembly_local_info
*info
)
338 for (i
= agg
->count
; i
> 0; i
--)
340 const slang_storage_array
*arr
= agg
->arrays
+ i
- 1;
343 for (j
= arr
->length
; j
> 0; j
--)
345 if (arr
->type
== slang_stor_aggregate
)
347 if (!dereference_aggregate (file
, arr
->aggregate
, index
, size
, info
))
353 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, info
->addr_tmp
,
356 if (!slang_assembly_file_push (file
, slang_asm_addr_deref
))
358 if (!slang_assembly_file_push_label (file
, slang_asm_addr_push
, *size
))
360 if (!slang_assembly_file_push (file
, slang_asm_addr_add
))
364 case slang_stor_bool
:
365 if (!slang_assembly_file_push (file
, slang_asm_bool_deref
))
369 if (!slang_assembly_file_push (file
, slang_asm_int_deref
))
372 case slang_stor_float
:
373 if (!slang_assembly_file_push (file
, slang_asm_float_deref
))
383 /* XXX: general swizzle! */
384 static int dereference (slang_assembly_file
*file
, slang_operation
*op
,
385 slang_assembly_name_space
*space
, slang_assembly_local_info
*info
)
387 slang_assembly_typeinfo ti
;
389 slang_storage_aggregate agg
;
392 slang_assembly_typeinfo_construct (&ti
);
393 if (!_slang_typeof_operation (op
, space
, &ti
))
395 slang_assembly_typeinfo_destruct (&ti
);
399 slang_storage_aggregate_construct (&agg
);
400 if (!_slang_aggregate_variable (&agg
, &ti
.spec
, NULL
, space
->funcs
, space
->structs
))
402 slang_storage_aggregate_destruct (&agg
);
403 slang_assembly_typeinfo_destruct (&ti
);
407 size
= _slang_sizeof_aggregate (&agg
);
408 result
= dereference_aggregate (file
, &agg
, 0, &size
, info
);
410 slang_storage_aggregate_destruct (&agg
);
411 slang_assembly_typeinfo_destruct (&ti
);
415 static int call_function (slang_assembly_file
*file
, slang_function
*fun
, slang_operation
*params
,
416 unsigned int param_count
, int assignment
, slang_assembly_name_space
*space
,
417 slang_assembly_local_info
*info
)
419 unsigned int ret_size
, i
;
420 slang_assembly_stack_info stk
;
422 /* make room for the return value, if any */
424 if (!sizeof_variable (&fun
->header
.type
.specifier
, NULL
, space
, &ret_size
))
428 if (!slang_assembly_file_push_label (file
, slang_asm_local_alloc
, ret_size
))
432 /* push the actual parameters on the stack */
433 for (i
= 0; i
< param_count
; i
++)
435 slang_assembly_flow_control flow
;
437 if (i
== 0 && assignment
)
439 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, info
->addr_tmp
, 4))
441 /* TODO: optimize the "out" parameter case */
442 /* TODO: inspect stk */
443 if (!_slang_assemble_operation (file
, params
, 1, &flow
, space
, info
, &stk
))
445 if (!slang_assembly_file_push (file
, slang_asm_addr_copy
))
447 if (!slang_assembly_file_push (file
, slang_asm_addr_deref
))
449 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, info
->addr_tmp
, 4))
451 if (!slang_assembly_file_push (file
, slang_asm_addr_deref
))
453 if (!dereference (file
, params
, space
, info
))
458 /* TODO: for "out" and "inout" parameters also push the address (first) */
459 /* TODO: optimize the "out" parameter case */
460 /* TODO: inspect stk */
461 if (!_slang_assemble_operation (file
, params
+ i
, 0, &flow
, space
, info
, &stk
))
466 /* call the function */
467 if (!slang_assembly_file_push_label (file
, slang_asm_call
, fun
->address
))
470 /* pop the parameters from the stack */
471 for (i
= param_count
; i
> 0; i
--)
473 /* XXX: copy inout/out params back to the actual variables */
474 if (!_slang_cleanup_stack (file
, params
+ i
- 1, 0, space
))
481 static int call_function_name (slang_assembly_file
*file
, const char *name
, slang_operation
*params
,
482 unsigned int param_count
, int assignment
, slang_assembly_name_space
*space
,
483 slang_assembly_local_info
*info
)
485 slang_function
*fun
= _slang_locate_function (name
, params
, param_count
, space
);
488 return call_function (file
, fun
, params
, param_count
, assignment
, space
, info
);
491 static int call_function_name_dummyint (slang_assembly_file
*file
, const char *name
,
492 slang_operation
*params
, slang_assembly_name_space
*space
, slang_assembly_local_info
*info
)
494 slang_operation p2
[2];
498 if (!slang_operation_construct_a (p2
+ 1))
500 p2
[1].type
= slang_oper_literal_int
;
501 result
= call_function_name (file
, name
, p2
, 2, 0, space
, info
);
502 slang_operation_destruct (p2
+ 1);
506 static int call_asm_instruction (slang_assembly_file
*file
, const char *name
)
511 slang_assembly_type code1
, code2
;
513 { "float_to_int", slang_asm_float_to_int
, slang_asm_int_copy
},
514 { "int_to_float", slang_asm_int_to_float
, slang_asm_float_copy
},
515 { "float_copy", slang_asm_float_copy
, slang_asm_none
},
516 { "int_copy", slang_asm_int_copy
, slang_asm_none
},
517 { "bool_copy", slang_asm_bool_copy
, slang_asm_none
},
518 { "float_add", slang_asm_float_add
, slang_asm_float_copy
},
519 { "float_multiply", slang_asm_float_multiply
, slang_asm_float_copy
},
520 { "float_divide", slang_asm_float_divide
, slang_asm_float_copy
},
521 { "float_negate", slang_asm_float_negate
, slang_asm_float_copy
},
522 { "float_less", slang_asm_float_less
, slang_asm_bool_copy
},
523 { "float_equal", slang_asm_float_equal
, slang_asm_bool_copy
},
524 { NULL
, slang_asm_none
, slang_asm_none
}
528 for (i
= 0; inst
[i
].name
!= NULL
; i
++)
529 if (slang_string_compare (name
, inst
[i
].name
) == 0)
531 if (inst
[i
].name
== NULL
)
534 if (!slang_assembly_file_push_label2 (file
, inst
[i
].code1
, 4, 0))
536 if (inst
[i
].code2
!= slang_asm_none
)
537 if (!slang_assembly_file_push_label2 (file
, inst
[i
].code2
, 4, 0))
540 /* clean-up the stack from the remaining dst address */
541 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
546 /* XXX: general swizzle! */
547 static int assign_aggregate (slang_assembly_file
*file
, const slang_storage_aggregate
*agg
,
548 unsigned int *index
, unsigned int size
, slang_assembly_local_info
*info
)
552 for (i
= 0; i
< agg
->count
; i
++)
554 const slang_storage_array
*arr
= agg
->arrays
+ i
;
557 for (j
= 0; j
< arr
->length
; j
++)
559 if (arr
->type
== slang_stor_aggregate
)
561 if (!assign_aggregate (file
, arr
->aggregate
, index
, size
, info
))
568 case slang_stor_bool
:
569 if (!slang_assembly_file_push_label2 (file
, slang_asm_bool_copy
,
570 size
- *index
, *index
))
574 if (!slang_assembly_file_push_label2 (file
, slang_asm_int_copy
,
575 size
- *index
, *index
))
578 case slang_stor_float
:
579 if (!slang_assembly_file_push_label2 (file
, slang_asm_float_copy
,
580 size
- *index
, *index
))
590 /* XXX: general swizzle! */
591 static int assignment (slang_assembly_file
*file
, slang_operation
*op
,
592 slang_assembly_name_space
*space
, slang_assembly_local_info
*info
)
594 slang_assembly_typeinfo ti
;
596 slang_storage_aggregate agg
;
597 unsigned int index
, size
;
599 slang_assembly_typeinfo_construct (&ti
);
600 if (!_slang_typeof_operation (op
, space
, &ti
))
602 slang_assembly_typeinfo_destruct (&ti
);
606 slang_storage_aggregate_construct (&agg
);
607 if (!_slang_aggregate_variable (&agg
, &ti
.spec
, NULL
, space
->funcs
, space
->structs
))
609 slang_storage_aggregate_destruct (&agg
);
610 slang_assembly_typeinfo_destruct (&ti
);
615 size
= _slang_sizeof_aggregate (&agg
);
616 result
= assign_aggregate (file
, &agg
, &index
, size
, info
);
618 slang_storage_aggregate_destruct (&agg
);
619 slang_assembly_typeinfo_destruct (&ti
);
622 /* XXX: general swizzle! */
623 static int equality_aggregate (slang_assembly_file
*file
, const slang_storage_aggregate
*agg
,
624 unsigned int *index
, unsigned int size
, slang_assembly_local_info
*info
, unsigned int z_label
)
628 for (i
= 0; i
< agg
->count
; i
++)
630 const slang_storage_array
*arr
= agg
->arrays
+ i
;
633 for (j
= 0; j
< arr
->length
; j
++)
635 if (arr
->type
== slang_stor_aggregate
)
637 if (!equality_aggregate (file
, arr
->aggregate
, index
, size
, info
, z_label
))
642 if (!slang_assembly_file_push_label2 (file
, slang_asm_float_equal
, size
+ *index
,
646 if (!slang_assembly_file_push_label (file
, slang_asm_jump_if_zero
, z_label
))
653 /* XXX: general swizzle! */
654 static int equality (slang_assembly_file
*file
, slang_operation
*op
,
655 slang_assembly_name_space
*space
, slang_assembly_local_info
*info
, int equal
)
657 slang_assembly_typeinfo ti
;
659 slang_storage_aggregate agg
;
660 unsigned int index
, size
;
661 unsigned int skip_jump
, true_label
, true_jump
, false_label
, false_jump
;
663 /* get type of operation */
664 slang_assembly_typeinfo_construct (&ti
);
665 if (!_slang_typeof_operation (op
, space
, &ti
))
667 slang_assembly_typeinfo_destruct (&ti
);
671 /* convert it to an aggregate */
672 slang_storage_aggregate_construct (&agg
);
673 if (!(result
= _slang_aggregate_variable (&agg
, &ti
.spec
, NULL
, space
->funcs
, space
->structs
)))
676 /* compute the size of the agregate - there are two such aggregates on the stack */
677 size
= _slang_sizeof_aggregate (&agg
);
679 /* jump to the actual data-comparison code */
680 skip_jump
= file
->count
;
681 if (!(result
= slang_assembly_file_push (file
, slang_asm_jump
)))
684 /* pop off the stack the compared data and push 1 */
685 true_label
= file
->count
;
686 if (!(result
= slang_assembly_file_push_label (file
, slang_asm_local_free
, size
* 2)))
688 if (!(result
= slang_assembly_file_push_literal (file
, slang_asm_bool_push
, 1.0f
)))
690 true_jump
= file
->count
;
691 if (!(result
= slang_assembly_file_push (file
, slang_asm_jump
)))
694 false_label
= file
->count
;
695 if (!(result
= slang_assembly_file_push_label (file
, slang_asm_local_free
, size
* 2)))
697 if (!(result
= slang_assembly_file_push_literal (file
, slang_asm_bool_push
, 0.0f
)))
699 false_jump
= file
->count
;
700 if (!(result
= slang_assembly_file_push (file
, slang_asm_jump
)))
703 file
->code
[skip_jump
].param
[0] = file
->count
;
705 /* compare the data on stack, it will eventually jump either to true or false label */
707 if (!(result
= equality_aggregate (file
, &agg
, &index
, size
, info
,
708 equal
? false_label
: true_label
)))
710 if (!(result
= slang_assembly_file_push_label (file
, slang_asm_jump
,
711 equal
? true_label
: false_label
)))
714 file
->code
[true_jump
].param
[0] = file
->count
;
715 file
->code
[false_jump
].param
[0] = file
->count
;
719 slang_storage_aggregate_destruct (&agg
);
720 slang_assembly_typeinfo_destruct (&ti
);
724 int _slang_assemble_operation (slang_assembly_file
*file
, slang_operation
*op
, int reference
,
725 slang_assembly_flow_control
*flow
, slang_assembly_name_space
*space
,
726 slang_assembly_local_info
*info
, slang_assembly_stack_info
*stk
)
730 stk
->swizzle_mask
= 0;
733 if (!slang_assembly_file_push_new (file
))
738 case slang_oper_block_no_new_scope
:
739 case slang_oper_block_new_scope
:
742 for (i
= 0; i
< op
->num_children
; i
++)
744 slang_assembly_stack_info stk
;
745 if (!_slang_assemble_operation (file
, op
->children
+ i
, 0, flow
, space
, info
, &stk
))
747 /* TODO: pass-in stk to cleanup */
748 if (!_slang_cleanup_stack (file
, op
->children
+ i
, 0, space
))
753 case slang_oper_variable_decl
:
757 for (i
= 0; i
< op
->num_children
; i
++)
759 /* TODO: perform initialization of op->children[i] */
760 /* TODO: clean-up stack */
767 for (i
= 0; i
< op
->num_children
; i
++)
769 slang_assembly_stack_info stk
;
770 if (!_slang_assemble_operation (file
, op
->children
+ i
, i
== 0, flow
, space
, info
,
773 /* TODO: inspect stk */
775 if (!call_asm_instruction (file
, op
->identifier
))
779 case slang_oper_break
:
780 file
->code
[asm].type
= slang_asm_jump
;
781 file
->code
[asm].param
[0] = flow
->loop_end
;
783 case slang_oper_continue
:
784 file
->code
[asm].type
= slang_asm_jump
;
785 file
->code
[asm].param
[0] = flow
->loop_start
;
787 case slang_oper_discard
:
788 file
->code
[asm].type
= slang_asm_discard
;
789 if (!slang_assembly_file_push (file
, slang_asm_exit
))
792 case slang_oper_return
:
793 if (info
->ret_size
!= 0)
795 slang_assembly_stack_info stk
;
796 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, 0, info
->ret_size
))
798 if (!_slang_assemble_operation (file
, op
->children
, 0, flow
, space
, info
, &stk
))
800 /* TODO: inspect stk */
801 if (!assignment (file
, op
->children
, space
, info
))
803 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
806 if (!slang_assembly_file_push_label (file
, slang_asm_jump
, flow
->function_end
))
809 case slang_oper_expression
:
811 slang_assembly_stack_info stk
;
812 if (!_slang_assemble_operation (file
, op
->children
, reference
, flow
, space
, info
, &stk
))
814 /* TODO: inspect stk */
818 if (!_slang_assemble_if (file
, op
, flow
, space
, info
))
821 case slang_oper_while
:
822 if (!_slang_assemble_while (file
, op
, flow
, space
, info
))
826 if (!_slang_assemble_do (file
, op
, flow
, space
, info
))
830 if (!_slang_assemble_for (file
, op
, flow
, space
, info
))
833 case slang_oper_void
:
835 case slang_oper_literal_bool
:
836 file
->code
[asm].type
= slang_asm_bool_push
;
837 file
->code
[asm].literal
= op
->literal
;
839 case slang_oper_literal_int
:
840 file
->code
[asm].type
= slang_asm_int_push
;
841 file
->code
[asm].literal
= op
->literal
;
843 case slang_oper_literal_float
:
844 file
->code
[asm].type
= slang_asm_float_push
;
845 file
->code
[asm].literal
= op
->literal
;
847 case slang_oper_identifier
:
851 var
= _slang_locate_variable (op
->locals
, op
->identifier
, 1);
855 if (!sizeof_variable (&var
->type
.specifier
, var
->array_size
, space
, &size
))
857 if (var
->initializer
!= NULL
)
859 assert (!"var->initializer, oper_identifier");
865 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
,
870 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, var
->address
,
875 if (!slang_assembly_file_push (file
, slang_asm_addr_copy
))
877 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
879 if (!dereference (file
, op
, space
, info
))
885 case slang_oper_sequence
:
887 slang_assembly_stack_info stk
;
888 if (!_slang_assemble_operation (file
, op
->children
, 0, flow
, space
, info
, &stk
))
890 /* TODO: pass-in stk to cleanup */
891 if (!_slang_cleanup_stack (file
, op
->children
, 0, space
))
893 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
,
896 /* TODO: inspect stk */
899 case slang_oper_assign
:
901 slang_assembly_stack_info stk
;
903 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, info
->addr_tmp
,
906 if (!_slang_assemble_operation (file
, op
->children
, 1, flow
, space
, info
, &stk
))
908 /* TODO: inspect stk */
909 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
, &stk
))
911 /* TODO: inspect stk */
912 if (!assignment (file
, op
->children
, space
, info
))
916 if (!slang_assembly_file_push (file
, slang_asm_addr_copy
))
918 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
920 if (!dereference (file
, op
->children
, space
, info
))
925 case slang_oper_addassign
:
926 /* TODO: posprawdzaj czy zadzia³a dereferencja */
927 if (!call_function_name (file
, "+=", op
->children
, 2, 1, space
, info
))
931 /* TODO: stack is address */
935 if (!dereference (file
, op
->children
, space
, info
))
937 /* TODO: stack is operation type */
940 case slang_oper_subassign
:
941 /* TODO: posprawdzaj czy zadzia³a dereferencja */
942 if (!call_function_name (file
, "-=", op
->children
, 2, 1, space
, info
))
946 /* TODO: stack is address */
950 if (!dereference (file
, op
->children
, space
, info
))
952 /* TODO: stack is operation type */
955 case slang_oper_mulassign
:
956 /* TODO: posprawdzaj czy zadzia³a dereferencja */
957 if (!call_function_name (file
, "*=", op
->children
, 2, 1, space
, info
))
961 /* TODO: stack is address */
965 if (!dereference (file
, op
->children
, space
, info
))
967 /* TODO: stack is operation type */
970 /*case slang_oper_modassign:*/
971 /*case slang_oper_lshassign:*/
972 /*case slang_oper_rshassign:*/
973 /*case slang_oper_orassign:*/
974 /*case slang_oper_xorassign:*/
975 /*case slang_oper_andassign:*/
976 case slang_oper_divassign
:
977 /* TODO: posprawdzaj czy zadzia³a dereferencja */
978 if (!call_function_name (file
, "/=", op
->children
, 2, 1, space
, info
))
982 /* TODO: stack is address */
986 if (!dereference (file
, op
->children
, space
, info
))
988 /* TODO: stack is operation type */
991 case slang_oper_select
:
992 if (!_slang_assemble_select (file
, op
, flow
, space
, info
))
995 case slang_oper_logicalor
:
996 if (!_slang_assemble_logicalor (file
, op
, flow
, space
, info
))
999 case slang_oper_logicaland
:
1000 if (!_slang_assemble_logicaland (file
, op
, flow
, space
, info
))
1003 case slang_oper_logicalxor
:
1004 if (!call_function_name (file
, "^^", op
->children
, 2, 0, space
, info
))
1007 /*case slang_oper_bitor:*/
1008 /*case slang_oper_bitxor:*/
1009 /*case slang_oper_bitand:*/
1010 case slang_oper_less
:
1011 if (!call_function_name (file
, "<", op
->children
, 2, 0, space
, info
))
1014 case slang_oper_greater
:
1015 if (!call_function_name (file
, ">", op
->children
, 2, 0, space
, info
))
1018 case slang_oper_lessequal
:
1019 if (!call_function_name (file
, "<=", op
->children
, 2, 0, space
, info
))
1022 case slang_oper_greaterequal
:
1023 if (!call_function_name (file
, ">=", op
->children
, 2, 0, space
, info
))
1026 /*case slang_oper_lshift:*/
1027 /*case slang_oper_rshift:*/
1028 case slang_oper_add
:
1029 if (!call_function_name (file
, "+", op
->children
, 2, 0, space
, info
))
1032 case slang_oper_subtract
:
1033 if (!call_function_name (file
, "-", op
->children
, 2, 0, space
, info
))
1036 case slang_oper_multiply
:
1037 if (!call_function_name (file
, "*", op
->children
, 2, 0, space
, info
))
1040 /*case slang_oper_modulus:*/
1041 case slang_oper_divide
:
1042 if (!call_function_name (file
, "/", op
->children
, 2, 0, space
, info
))
1045 case slang_oper_equal
:
1047 slang_assembly_stack_info stk
;
1048 if (!_slang_assemble_operation (file
, op
->children
, 0, flow
, space
, info
, &stk
))
1050 /* TODO: inspect stk */
1051 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
, &stk
))
1053 /* TODO: inspect stk */
1054 if (!equality (file
, op
->children
, space
, info
, 1))
1058 case slang_oper_notequal
:
1060 slang_assembly_stack_info stk
;
1061 if (!_slang_assemble_operation (file
, op
->children
, 0, flow
, space
, info
, &stk
))
1063 /* TODO: inspect stk */
1064 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
, &stk
))
1066 /* TODO: inspect stk */
1067 if (!equality (file
, op
->children
, space
, info
, 0))
1071 case slang_oper_preincrement
:
1072 /* TODO: posprawdzaj czy zadzia³a dereferencja */
1073 if (!call_function_name (file
, "++", op
->children
, 1, 1, space
, info
))
1077 /* TODO: stack is address */
1081 /* TODO: dereference */
1082 /* TODO: stack is operation type */
1085 case slang_oper_predecrement
:
1086 /* TODO: posprawdzaj czy zadzia³a dereferencja */
1087 if (!call_function_name (file
, "--", op
->children
, 1, 1, space
, info
))
1091 /* TODO: stack is address */
1095 /* TODO: dereference */
1096 /* TODO: stack is operation type */
1099 case slang_oper_plus
:
1100 if (!call_function_name (file
, "+", op
->children
, 1, 0, space
, info
))
1103 case slang_oper_minus
:
1104 if (!call_function_name (file
, "-", op
->children
, 1, 0, space
, info
))
1107 /*case slang_oper_complement:*/
1108 case slang_oper_not
:
1109 if (!call_function_name (file
, "!", op
->children
, 1, 0, space
, info
))
1112 case slang_oper_subscript
:
1114 slang_assembly_stack_info _stk
;
1115 slang_assembly_typeinfo ti_arr
, ti_elem
;
1116 unsigned int arr_size
= 0, elem_size
= 0;
1117 if (!_slang_assemble_operation (file
, op
->children
, reference
, flow
, space
, info
,
1120 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
, &_stk
))
1122 slang_assembly_typeinfo_construct (&ti_arr
);
1123 if (!_slang_typeof_operation (op
->children
, space
, &ti_arr
))
1125 slang_assembly_typeinfo_destruct (&ti_arr
);
1128 if (!sizeof_variable (&ti_arr
.spec
, NULL
, space
, &arr_size
))
1130 slang_assembly_typeinfo_destruct (&ti_arr
);
1133 slang_assembly_typeinfo_construct (&ti_elem
);
1134 if (!_slang_typeof_operation (op
, space
, &ti_elem
))
1136 slang_assembly_typeinfo_destruct (&ti_arr
);
1137 slang_assembly_typeinfo_destruct (&ti_elem
);
1140 if (!sizeof_variable (&ti_elem
.spec
, NULL
, space
, &elem_size
))
1142 slang_assembly_typeinfo_destruct (&ti_arr
);
1143 slang_assembly_typeinfo_destruct (&ti_elem
);
1146 if (!slang_assembly_file_push (file
, slang_asm_int_to_addr
))
1148 slang_assembly_typeinfo_destruct (&ti_arr
);
1149 slang_assembly_typeinfo_destruct (&ti_elem
);
1152 if (!slang_assembly_file_push_label (file
, slang_asm_addr_push
, elem_size
))
1154 slang_assembly_typeinfo_destruct (&ti_arr
);
1155 slang_assembly_typeinfo_destruct (&ti_elem
);
1158 if (!slang_assembly_file_push (file
, slang_asm_addr_multiply
))
1160 slang_assembly_typeinfo_destruct (&ti_arr
);
1161 slang_assembly_typeinfo_destruct (&ti_elem
);
1166 if (!slang_assembly_file_push (file
, slang_asm_addr_add
))
1168 slang_assembly_typeinfo_destruct (&ti_arr
);
1169 slang_assembly_typeinfo_destruct (&ti_elem
);
1176 for (i
= 0; i
< elem_size
; i
+= 4)
1178 if (!slang_assembly_file_push_label2 (file
, slang_asm_float_move
,
1179 arr_size
- elem_size
+ i
+ 4, i
+ 4))
1181 slang_assembly_typeinfo_destruct (&ti_arr
);
1182 slang_assembly_typeinfo_destruct (&ti_elem
);
1186 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
1188 slang_assembly_typeinfo_destruct (&ti_arr
);
1189 slang_assembly_typeinfo_destruct (&ti_elem
);
1192 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
,
1193 arr_size
- elem_size
))
1195 slang_assembly_typeinfo_destruct (&ti_arr
);
1196 slang_assembly_typeinfo_destruct (&ti_elem
);
1200 slang_assembly_typeinfo_destruct (&ti_arr
);
1201 slang_assembly_typeinfo_destruct (&ti_elem
);
1204 case slang_oper_call
:
1206 slang_function
*fun
= _slang_locate_function (op
->identifier
, op
->children
,
1207 op
->num_children
, space
);
1210 if (!_slang_assemble_constructor (file
, op
, flow
, space
, info
))
1215 if (!call_function (file
, fun
, op
->children
, op
->num_children
, 0, space
, info
))
1220 case slang_oper_field
:
1222 slang_assembly_typeinfo ti_after
, ti_before
;
1223 slang_assembly_stack_info _stk
;
1224 slang_assembly_typeinfo_construct (&ti_after
);
1225 if (!_slang_typeof_operation (op
, space
, &ti_after
))
1227 slang_assembly_typeinfo_destruct (&ti_after
);
1230 slang_assembly_typeinfo_construct (&ti_before
);
1231 if (!_slang_typeof_operation (op
->children
, space
, &ti_before
))
1233 slang_assembly_typeinfo_destruct (&ti_after
);
1234 slang_assembly_typeinfo_destruct (&ti_before
);
1237 if (!reference
&& ti_after
.is_swizzled
)
1239 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
,
1240 info
->swizzle_tmp
, 16))
1242 slang_assembly_typeinfo_destruct (&ti_after
);
1243 slang_assembly_typeinfo_destruct (&ti_before
);
1247 if (!_slang_assemble_operation (file
, op
->children
, reference
, flow
, space
, info
,
1250 slang_assembly_typeinfo_destruct (&ti_after
);
1251 slang_assembly_typeinfo_destruct (&ti_before
);
1254 /* TODO: inspect stk */
1255 if (ti_after
.is_swizzled
)
1259 if (ti_after
.swz
.num_components
== 1)
1261 if (!slang_assembly_file_push_label (file
, slang_asm_addr_push
,
1262 ti_after
.swz
.swizzle
[0] * 4))
1264 slang_assembly_typeinfo_destruct (&ti_after
);
1265 slang_assembly_typeinfo_destruct (&ti_before
);
1268 if (!slang_assembly_file_push (file
, slang_asm_addr_add
))
1270 slang_assembly_typeinfo_destruct (&ti_after
);
1271 slang_assembly_typeinfo_destruct (&ti_before
);
1278 for (i
= 0; i
< ti_after
.swz
.num_components
; i
++)
1279 stk
->swizzle_mask
|= 1 << ti_after
.swz
.swizzle
[i
];
1284 if (!_slang_assemble_constructor_from_swizzle (file
, &ti_after
.swz
,
1285 &ti_after
.spec
, &ti_before
.spec
, info
))
1287 slang_assembly_typeinfo_destruct (&ti_after
);
1288 slang_assembly_typeinfo_destruct (&ti_before
);
1297 /* TODO: struct field address */
1301 /* TODO: struct field value */
1304 slang_assembly_typeinfo_destruct (&ti_after
);
1305 slang_assembly_typeinfo_destruct (&ti_before
);
1308 case slang_oper_postincrement
:
1309 if (!call_function_name_dummyint (file
, "++", op
->children
, space
, info
))
1311 if (!dereference (file
, op
, space
, info
))
1314 case slang_oper_postdecrement
:
1315 if (!call_function_name_dummyint (file
, "--", op
->children
, space
, info
))
1317 if (!dereference (file
, op
, space
, info
))
1334 void xxx_first (slang_assembly_file
*file
)
1336 slang_assembly_file_push (file
, slang_asm_jump
);
1339 void xxx_prolog (slang_assembly_file
*file
)
1341 file
->code
[0].param
[0] = file
->count
;
1343 /* allocate local storage for inout/out params */
1344 slang_assembly_file_push_literal (file
, slang_asm_int_push
, 777.777f
);
1345 slang_assembly_file_push_label (file
, slang_asm_enter
, 4);
1347 /* slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1348 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1349 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1350 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1351 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1352 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1353 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1354 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1355 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1356 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1357 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1358 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1359 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1360 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);
1361 slang_assembly_file_push_literal (file, slang_asm_int_push, 777.777f);*/
1362 slang_assembly_file_push_literal (file
, slang_asm_int_push
, 777.777f
);
1363 /* slang_assembly_file_push_literal (file, slang_asm_float_push, 16.16f);
1364 slang_assembly_file_push_literal (file, slang_asm_float_push, 15.15f);
1365 slang_assembly_file_push_literal (file, slang_asm_float_push, 14.14f);
1366 slang_assembly_file_push_literal (file, slang_asm_float_push, 13.13f);
1367 slang_assembly_file_push_literal (file, slang_asm_float_push, 12.12f);
1368 slang_assembly_file_push_literal (file, slang_asm_float_push, 11.11f);
1369 slang_assembly_file_push_literal (file, slang_asm_float_push, 10.10f);
1370 slang_assembly_file_push_literal (file, slang_asm_float_push, 9.9f);
1371 slang_assembly_file_push_literal (file, slang_asm_float_push, 8.8f);
1372 slang_assembly_file_push_literal (file, slang_asm_float_push, 7.7f);
1373 slang_assembly_file_push_literal (file, slang_asm_float_push, 6.6f);
1374 slang_assembly_file_push_literal (file, slang_asm_float_push, 5.5f);
1375 slang_assembly_file_push_literal (file, slang_asm_float_push, 4.4f);
1376 slang_assembly_file_push_literal (file, slang_asm_float_push, 3.3f);
1377 slang_assembly_file_push_literal (file, slang_asm_float_push, 2.2f);*/
1378 slang_assembly_file_push_literal (file
, slang_asm_float_push
, 1.1f
);
1380 slang_assembly_file_push_label (file
, slang_asm_call
, file
->count
+ 3);
1381 slang_assembly_file_push_label (file
, slang_asm_local_free
, 4);
1383 slang_assembly_file_push (file
, slang_asm_exit
);