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"
39 #include "slang_assemble_assignment.h"
43 static void slang_assembly_construct (slang_assembly
*assem
)
45 assem
->type
= slang_asm_none
;
48 static void slang_assembly_destruct (slang_assembly
*assem
)
52 /* slang_assembly_file */
54 void slang_assembly_file_construct (slang_assembly_file
*file
)
60 void slang_assembly_file_destruct (slang_assembly_file
*file
)
64 for (i
= 0; i
< file
->count
; i
++)
65 slang_assembly_destruct (file
->code
+ i
);
66 slang_alloc_free (file
->code
);
69 static int slang_assembly_file_push_new (slang_assembly_file
*file
)
71 file
->code
= (slang_assembly
*) slang_alloc_realloc (file
->code
, file
->count
* sizeof (
72 slang_assembly
), (file
->count
+ 1) * sizeof (slang_assembly
));
73 if (file
->code
!= NULL
)
75 slang_assembly_construct (file
->code
+ file
->count
);
82 static int slang_assembly_file_push_general (slang_assembly_file
*file
, slang_assembly_type type
,
83 GLfloat literal
, GLuint label
, GLuint size
)
85 slang_assembly
*assem
;
86 if (!slang_assembly_file_push_new (file
))
88 assem
= file
->code
+ file
->count
- 1;
90 assem
->literal
= literal
;
91 assem
->param
[0] = label
;
92 assem
->param
[1] = size
;
96 int slang_assembly_file_push (slang_assembly_file
*file
, slang_assembly_type type
)
98 return slang_assembly_file_push_general (file
, type
, (GLfloat
) 0, 0, 0);
101 int slang_assembly_file_push_label (slang_assembly_file
*file
, slang_assembly_type type
,
104 return slang_assembly_file_push_general (file
, type
, (GLfloat
) 0, label
, 0);
107 int slang_assembly_file_push_label2 (slang_assembly_file
*file
, slang_assembly_type type
,
108 GLuint label1
, GLuint label2
)
110 return slang_assembly_file_push_general (file
, type
, (GLfloat
) 0, label1
, label2
);
113 int slang_assembly_file_push_literal (slang_assembly_file
*file
, slang_assembly_type type
,
116 return slang_assembly_file_push_general (file
, type
, literal
, 0, 0);
119 /* utility functions */
121 static int sizeof_variable (slang_type_specifier
*spec
, slang_type_qualifier qual
,
122 slang_operation
*array_size
, slang_assembly_name_space
*space
, unsigned int *size
)
124 slang_storage_aggregate agg
;
126 slang_storage_aggregate_construct (&agg
);
127 if (!_slang_aggregate_variable (&agg
, spec
, array_size
, space
->funcs
, space
->structs
))
129 slang_storage_aggregate_destruct (&agg
);
132 *size
+= _slang_sizeof_aggregate (&agg
);
133 if (qual
== slang_qual_out
|| qual
== slang_qual_inout
)
135 slang_storage_aggregate_destruct (&agg
);
139 static int sizeof_variable2 (slang_variable
*var
, slang_assembly_name_space
*space
,
142 var
->address
= *size
;
143 if (var
->type
.qualifier
== slang_qual_out
|| var
->type
.qualifier
== slang_qual_inout
)
145 return sizeof_variable (&var
->type
.specifier
, var
->type
.qualifier
, var
->array_size
, space
,
149 static int sizeof_variables (slang_variable_scope
*vars
, unsigned int start
, unsigned int stop
,
150 slang_assembly_name_space
*space
, unsigned int *size
)
154 for (i
= start
; i
< stop
; i
++)
155 if (!sizeof_variable2 (vars
->variables
+ i
, space
, size
))
160 static int collect_locals (slang_operation
*op
, slang_assembly_name_space
*space
,
165 if (!sizeof_variables (op
->locals
, 0, op
->locals
->num_variables
, space
, size
))
167 for (i
= 0; i
< op
->num_children
; i
++)
168 if (!collect_locals (op
->children
+ i
, space
, size
))
173 /* _slang_locate_function() */
175 slang_function
*_slang_locate_function (const char *name
, slang_operation
*params
,
176 unsigned int num_params
, slang_assembly_name_space
*space
)
180 for (i
= 0; i
< space
->funcs
->num_functions
; i
++)
183 slang_function
*f
= space
->funcs
->functions
+ i
;
185 if (slang_string_compare (name
, f
->header
.name
) != 0)
187 if (f
->param_count
!= num_params
)
189 for (j
= 0; j
< num_params
; j
++)
191 slang_assembly_typeinfo ti
;
192 slang_assembly_typeinfo_construct (&ti
);
193 if (!_slang_typeof_operation (params
+ j
, space
, &ti
))
195 slang_assembly_typeinfo_destruct (&ti
);
198 if (!slang_type_specifier_equal (&ti
.spec
, &f
->parameters
->variables
[j
].type
.specifier
))
200 slang_assembly_typeinfo_destruct (&ti
);
203 slang_assembly_typeinfo_destruct (&ti
);
204 /* "out" and "inout" formal parameter requires the actual parameter to be l-value */
205 if (!ti
.can_be_referenced
&&
206 (f
->parameters
->variables
[j
].type
.qualifier
== slang_qual_out
||
207 f
->parameters
->variables
[j
].type
.qualifier
== slang_qual_inout
))
213 if (space
->funcs
->outer_scope
!= NULL
)
215 slang_assembly_name_space my_space
= *space
;
216 my_space
.funcs
= space
->funcs
->outer_scope
;
217 return _slang_locate_function (name
, params
, num_params
, &my_space
);
222 /* _slang_assemble_function() */
224 int _slang_assemble_function (slang_assembly_file
*file
, slang_function
*fun
,
225 slang_assembly_name_space
*space
)
227 unsigned int param_size
, local_size
;
228 unsigned int skip
, cleanup
;
229 slang_assembly_flow_control flow
;
230 slang_assembly_local_info info
;
231 slang_assembly_stack_info stk
;
233 fun
->address
= file
->count
;
235 if (fun
->body
== NULL
)
237 /* TODO: jump to the actual function body */
241 /* calculate return value and parameters size */
243 if (fun
->header
.type
.specifier
.type
!= slang_spec_void
)
244 if (!sizeof_variable (&fun
->header
.type
.specifier
, slang_qual_none
, NULL
, space
,
247 info
.ret_size
= param_size
;
248 if (!sizeof_variables (fun
->parameters
, 0, fun
->param_count
, space
, ¶m_size
))
251 /* calculate local variables size, take into account the four-byte return address and
252 temporaries for various tasks */
253 info
.addr_tmp
= param_size
+ 4;
254 info
.swizzle_tmp
= param_size
+ 4 + 4;
255 local_size
= param_size
+ 4 + 4 + 16;
256 if (!sizeof_variables (fun
->parameters
, fun
->param_count
, fun
->parameters
->num_variables
, space
,
259 if (!collect_locals (fun
->body
, space
, &local_size
))
262 /* allocate local variable storage */
263 if (!slang_assembly_file_push_label (file
, slang_asm_local_alloc
, local_size
- param_size
- 4))
266 /* mark a new frame for function variable storage */
267 if (!slang_assembly_file_push_label (file
, slang_asm_enter
, local_size
))
270 /* skip the cleanup jump */
272 if (!slang_assembly_file_push_new (file
))
274 file
->code
[skip
].type
= slang_asm_jump
;
276 /* all "return" statements will be directed here */
277 flow
.function_end
= file
->count
;
278 cleanup
= file
->count
;
279 if (!slang_assembly_file_push_new (file
))
281 file
->code
[cleanup
].type
= slang_asm_jump
;
283 /* execute the function body */
284 file
->code
[skip
].param
[0] = file
->count
;
285 if (!_slang_assemble_operation (file
, fun
->body
, 0, &flow
, space
, &info
, &stk
))
288 /* this is the end of the function - restore the old function frame */
289 file
->code
[cleanup
].param
[0] = file
->count
;
290 if (!slang_assembly_file_push (file
, slang_asm_leave
))
293 /* free local variable storage */
294 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, local_size
- param_size
- 4))
297 /* jump out of the function */
298 if (!slang_assembly_file_push (file
, slang_asm_return
))
303 int _slang_cleanup_stack (slang_assembly_file
*file
, slang_operation
*op
, int ref
,
304 slang_assembly_name_space
*space
)
306 slang_assembly_typeinfo ti
;
309 slang_assembly_typeinfo_construct (&ti
);
310 if (!_slang_typeof_operation (op
, space
, &ti
))
312 slang_assembly_typeinfo_destruct (&ti
);
315 if (ti
.spec
.type
== slang_spec_void
)
322 if (!sizeof_variable (&ti
.spec
, slang_qual_none
, NULL
, space
, &size
))
324 slang_assembly_typeinfo_destruct (&ti
);
328 slang_assembly_typeinfo_destruct (&ti
);
331 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, size
))
337 /* _slang_assemble_operation() */
339 /* XXX: general swizzle! */
340 static int dereference_aggregate (slang_assembly_file
*file
, const slang_storage_aggregate
*agg
,
341 unsigned int index
, unsigned int *size
, slang_assembly_local_info
*info
)
345 for (i
= agg
->count
; i
> 0; i
--)
347 const slang_storage_array
*arr
= agg
->arrays
+ i
- 1;
350 for (j
= arr
->length
; j
> 0; j
--)
352 if (arr
->type
== slang_stor_aggregate
)
354 if (!dereference_aggregate (file
, arr
->aggregate
, index
, size
, info
))
360 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, info
->addr_tmp
,
363 if (!slang_assembly_file_push (file
, slang_asm_addr_deref
))
365 if (!slang_assembly_file_push_label (file
, slang_asm_addr_push
, *size
))
367 if (!slang_assembly_file_push (file
, slang_asm_addr_add
))
371 case slang_stor_bool
:
372 if (!slang_assembly_file_push (file
, slang_asm_bool_deref
))
376 if (!slang_assembly_file_push (file
, slang_asm_int_deref
))
379 case slang_stor_float
:
380 if (!slang_assembly_file_push (file
, slang_asm_float_deref
))
390 /* XXX: general swizzle! */
391 int dereference (slang_assembly_file
*file
, slang_operation
*op
,
392 slang_assembly_name_space
*space
, slang_assembly_local_info
*info
)
394 slang_assembly_typeinfo ti
;
396 slang_storage_aggregate agg
;
399 slang_assembly_typeinfo_construct (&ti
);
400 if (!_slang_typeof_operation (op
, space
, &ti
))
402 slang_assembly_typeinfo_destruct (&ti
);
406 slang_storage_aggregate_construct (&agg
);
407 if (!_slang_aggregate_variable (&agg
, &ti
.spec
, NULL
, space
->funcs
, space
->structs
))
409 slang_storage_aggregate_destruct (&agg
);
410 slang_assembly_typeinfo_destruct (&ti
);
414 size
= _slang_sizeof_aggregate (&agg
);
415 result
= dereference_aggregate (file
, &agg
, 0, &size
, info
);
417 slang_storage_aggregate_destruct (&agg
);
418 slang_assembly_typeinfo_destruct (&ti
);
422 static int call_function (slang_assembly_file
*file
, slang_function
*fun
, slang_operation
*params
,
423 unsigned int param_count
, int assignment
, slang_assembly_name_space
*space
,
424 slang_assembly_local_info
*info
)
427 slang_assembly_stack_info stk
;
429 /* make room for the return value, if any */
430 if (fun
->header
.type
.specifier
.type
!= slang_spec_void
)
432 unsigned int ret_size
= 0;
433 if (!sizeof_variable (&fun
->header
.type
.specifier
, slang_qual_none
, NULL
, space
, &ret_size
))
435 if (!slang_assembly_file_push_label (file
, slang_asm_local_alloc
, ret_size
))
439 /* push the actual parameters on the stack */
440 for (i
= 0; i
< param_count
; i
++)
442 slang_assembly_flow_control flow
;
444 if (fun
->parameters
->variables
[i
].type
.qualifier
== slang_qual_inout
||
445 fun
->parameters
->variables
[i
].type
.qualifier
== slang_qual_out
)
447 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, info
->addr_tmp
, 4))
449 /* TODO: optimize the "out" parameter case */
450 /* TODO: inspect stk */
451 if (!_slang_assemble_operation (file
, params
+ i
, 1, &flow
, space
, info
, &stk
))
453 if (!slang_assembly_file_push (file
, slang_asm_addr_copy
))
455 if (!slang_assembly_file_push (file
, slang_asm_addr_deref
))
457 if (i
== 0 && assignment
)
459 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, info
->addr_tmp
,
462 if (!slang_assembly_file_push (file
, slang_asm_addr_deref
))
465 if (!dereference (file
, params
, space
, info
))
470 /* TODO: for "out" and "inout" parameters also push the address (first) */
471 /* TODO: optimize the "out" parameter case */
472 /* TODO: inspect stk */
473 if (!_slang_assemble_operation (file
, params
+ i
, 0, &flow
, space
, info
, &stk
))
478 /* call the function */
479 if (!slang_assembly_file_push_label (file
, slang_asm_call
, fun
->address
))
482 /* pop the parameters from the stack */
483 for (i
= param_count
; i
> 0; i
--)
485 unsigned int j
= i
- 1;
486 if (fun
->parameters
->variables
[j
].type
.qualifier
== slang_qual_inout
||
487 fun
->parameters
->variables
[j
].type
.qualifier
== slang_qual_out
)
489 if (!_slang_assemble_assignment (file
, params
+ j
, space
, info
))
491 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
496 if (!_slang_cleanup_stack (file
, params
+ j
, 0, space
))
504 int call_function_name (slang_assembly_file
*file
, const char *name
, slang_operation
*params
,
505 unsigned int param_count
, int assignment
, slang_assembly_name_space
*space
,
506 slang_assembly_local_info
*info
)
508 slang_function
*fun
= _slang_locate_function (name
, params
, param_count
, space
);
511 return call_function (file
, fun
, params
, param_count
, assignment
, space
, info
);
514 static int call_function_name_dummyint (slang_assembly_file
*file
, const char *name
,
515 slang_operation
*params
, slang_assembly_name_space
*space
, slang_assembly_local_info
*info
)
517 slang_operation p2
[2];
521 if (!slang_operation_construct_a (p2
+ 1))
523 p2
[1].type
= slang_oper_literal_int
;
524 result
= call_function_name (file
, name
, p2
, 2, 0, space
, info
);
525 slang_operation_destruct (p2
+ 1);
529 static int call_asm_instruction (slang_assembly_file
*file
, const char *name
)
534 slang_assembly_type code1
, code2
;
536 { "float_to_int", slang_asm_float_to_int
, slang_asm_int_copy
},
537 { "int_to_float", slang_asm_int_to_float
, slang_asm_float_copy
},
538 { "float_copy", slang_asm_float_copy
, slang_asm_none
},
539 { "int_copy", slang_asm_int_copy
, slang_asm_none
},
540 { "bool_copy", slang_asm_bool_copy
, slang_asm_none
},
541 { "float_add", slang_asm_float_add
, slang_asm_float_copy
},
542 { "float_multiply", slang_asm_float_multiply
, slang_asm_float_copy
},
543 { "float_divide", slang_asm_float_divide
, slang_asm_float_copy
},
544 { "float_negate", slang_asm_float_negate
, slang_asm_float_copy
},
545 { "float_less", slang_asm_float_less
, slang_asm_bool_copy
},
546 { "float_equal", slang_asm_float_equal
, slang_asm_bool_copy
},
547 { NULL
, slang_asm_none
, slang_asm_none
}
551 for (i
= 0; inst
[i
].name
!= NULL
; i
++)
552 if (slang_string_compare (name
, inst
[i
].name
) == 0)
554 if (inst
[i
].name
== NULL
)
557 if (!slang_assembly_file_push_label2 (file
, inst
[i
].code1
, 4, 0))
559 if (inst
[i
].code2
!= slang_asm_none
)
560 if (!slang_assembly_file_push_label2 (file
, inst
[i
].code2
, 4, 0))
563 /* clean-up the stack from the remaining dst address */
564 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
570 /* XXX: general swizzle! */
571 static int equality_aggregate (slang_assembly_file
*file
, const slang_storage_aggregate
*agg
,
572 unsigned int *index
, unsigned int size
, slang_assembly_local_info
*info
, unsigned int z_label
)
576 for (i
= 0; i
< agg
->count
; i
++)
578 const slang_storage_array
*arr
= agg
->arrays
+ i
;
581 for (j
= 0; j
< arr
->length
; j
++)
583 if (arr
->type
== slang_stor_aggregate
)
585 if (!equality_aggregate (file
, arr
->aggregate
, index
, size
, info
, z_label
))
590 if (!slang_assembly_file_push_label2 (file
, slang_asm_float_equal
, size
+ *index
,
594 if (!slang_assembly_file_push_label (file
, slang_asm_jump_if_zero
, z_label
))
601 /* XXX: general swizzle! */
602 static int equality (slang_assembly_file
*file
, slang_operation
*op
,
603 slang_assembly_name_space
*space
, slang_assembly_local_info
*info
, int equal
)
605 slang_assembly_typeinfo ti
;
607 slang_storage_aggregate agg
;
608 unsigned int index
, size
;
609 unsigned int skip_jump
, true_label
, true_jump
, false_label
, false_jump
;
611 /* get type of operation */
612 slang_assembly_typeinfo_construct (&ti
);
613 if (!_slang_typeof_operation (op
, space
, &ti
))
615 slang_assembly_typeinfo_destruct (&ti
);
619 /* convert it to an aggregate */
620 slang_storage_aggregate_construct (&agg
);
621 if (!(result
= _slang_aggregate_variable (&agg
, &ti
.spec
, NULL
, space
->funcs
, space
->structs
)))
624 /* compute the size of the agregate - there are two such aggregates on the stack */
625 size
= _slang_sizeof_aggregate (&agg
);
627 /* jump to the actual data-comparison code */
628 skip_jump
= file
->count
;
629 if (!(result
= slang_assembly_file_push (file
, slang_asm_jump
)))
632 /* pop off the stack the compared data and push 1 */
633 true_label
= file
->count
;
634 if (!(result
= slang_assembly_file_push_label (file
, slang_asm_local_free
, size
* 2)))
636 if (!(result
= slang_assembly_file_push_literal (file
, slang_asm_bool_push
, 1.0f
)))
638 true_jump
= file
->count
;
639 if (!(result
= slang_assembly_file_push (file
, slang_asm_jump
)))
642 false_label
= file
->count
;
643 if (!(result
= slang_assembly_file_push_label (file
, slang_asm_local_free
, size
* 2)))
645 if (!(result
= slang_assembly_file_push_literal (file
, slang_asm_bool_push
, 0.0f
)))
647 false_jump
= file
->count
;
648 if (!(result
= slang_assembly_file_push (file
, slang_asm_jump
)))
651 file
->code
[skip_jump
].param
[0] = file
->count
;
653 /* compare the data on stack, it will eventually jump either to true or false label */
655 if (!(result
= equality_aggregate (file
, &agg
, &index
, size
, info
,
656 equal
? false_label
: true_label
)))
658 if (!(result
= slang_assembly_file_push_label (file
, slang_asm_jump
,
659 equal
? true_label
: false_label
)))
662 file
->code
[true_jump
].param
[0] = file
->count
;
663 file
->code
[false_jump
].param
[0] = file
->count
;
667 slang_storage_aggregate_destruct (&agg
);
668 slang_assembly_typeinfo_destruct (&ti
);
672 int _slang_assemble_operation (slang_assembly_file
*file
, slang_operation
*op
, int reference
,
673 slang_assembly_flow_control
*flow
, slang_assembly_name_space
*space
,
674 slang_assembly_local_info
*info
, slang_assembly_stack_info
*stk
)
678 stk
->swizzle_mask
= 0;
681 if (!slang_assembly_file_push_new (file
))
686 case slang_oper_block_no_new_scope
:
687 case slang_oper_block_new_scope
:
690 for (i
= 0; i
< op
->num_children
; i
++)
692 slang_assembly_stack_info stk
;
693 if (!_slang_assemble_operation (file
, op
->children
+ i
, 0, flow
, space
, info
, &stk
))
695 /* TODO: pass-in stk to cleanup */
696 if (!_slang_cleanup_stack (file
, op
->children
+ i
, 0, space
))
701 case slang_oper_variable_decl
:
705 for (i
= 0; i
< op
->num_children
; i
++)
707 /* TODO: perform initialization of op->children[i] */
708 /* TODO: clean-up stack */
715 for (i
= 0; i
< op
->num_children
; i
++)
717 slang_assembly_stack_info stk
;
718 if (!_slang_assemble_operation (file
, op
->children
+ i
, i
== 0, flow
, space
, info
,
721 /* TODO: inspect stk */
723 if (!call_asm_instruction (file
, op
->identifier
))
727 case slang_oper_break
:
728 file
->code
[assem
].type
= slang_asm_jump
;
729 file
->code
[assem
].param
[0] = flow
->loop_end
;
731 case slang_oper_continue
:
732 file
->code
[assem
].type
= slang_asm_jump
;
733 file
->code
[assem
].param
[0] = flow
->loop_start
;
735 case slang_oper_discard
:
736 file
->code
[assem
].type
= slang_asm_discard
;
737 if (!slang_assembly_file_push (file
, slang_asm_exit
))
740 case slang_oper_return
:
741 if (info
->ret_size
!= 0)
743 slang_assembly_stack_info stk
;
744 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, 0, info
->ret_size
))
746 if (!_slang_assemble_operation (file
, op
->children
, 0, flow
, space
, info
, &stk
))
748 /* TODO: inspect stk */
749 if (!_slang_assemble_assignment (file
, op
->children
, space
, info
))
751 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
754 if (!slang_assembly_file_push_label (file
, slang_asm_jump
, flow
->function_end
))
757 case slang_oper_expression
:
759 slang_assembly_stack_info stk
;
760 if (!_slang_assemble_operation (file
, op
->children
, reference
, flow
, space
, info
, &stk
))
762 /* TODO: inspect stk */
766 if (!_slang_assemble_if (file
, op
, flow
, space
, info
))
769 case slang_oper_while
:
770 if (!_slang_assemble_while (file
, op
, flow
, space
, info
))
774 if (!_slang_assemble_do (file
, op
, flow
, space
, info
))
778 if (!_slang_assemble_for (file
, op
, flow
, space
, info
))
781 case slang_oper_void
:
783 case slang_oper_literal_bool
:
784 file
->code
[assem
].type
= slang_asm_bool_push
;
785 file
->code
[assem
].literal
= op
->literal
;
787 case slang_oper_literal_int
:
788 file
->code
[assem
].type
= slang_asm_int_push
;
789 file
->code
[assem
].literal
= op
->literal
;
791 case slang_oper_literal_float
:
792 file
->code
[assem
].type
= slang_asm_float_push
;
793 file
->code
[assem
].literal
= op
->literal
;
795 case slang_oper_identifier
:
799 var
= _slang_locate_variable (op
->locals
, op
->identifier
, 1);
803 if (!sizeof_variable (&var
->type
.specifier
, slang_qual_none
, var
->array_size
, space
,
806 if (var
->initializer
!= NULL
)
808 assert (!"var->initializer, oper_identifier");
814 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
,
819 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
, var
->address
,
824 if (!slang_assembly_file_push (file
, slang_asm_addr_copy
))
826 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
828 if (!dereference (file
, op
, space
, info
))
834 case slang_oper_sequence
:
836 slang_assembly_stack_info stk
;
837 if (!_slang_assemble_operation (file
, op
->children
, 0, flow
, space
, info
, &stk
))
839 /* TODO: pass-in stk to cleanup */
840 if (!_slang_cleanup_stack (file
, op
->children
, 0, space
))
842 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
,
845 /* TODO: inspect stk */
848 case slang_oper_assign
:
849 if (!_slang_assemble_assign (file
, op
, "=", reference
, space
, info
))
852 case slang_oper_addassign
:
853 if (!_slang_assemble_assign (file
, op
, "+=", reference
, space
, info
))
856 case slang_oper_subassign
:
857 if (!_slang_assemble_assign (file
, op
, "-=", reference
, space
, info
))
860 case slang_oper_mulassign
:
861 if (!_slang_assemble_assign (file
, op
, "*=", reference
, space
, info
))
864 /*case slang_oper_modassign:*/
865 /*case slang_oper_lshassign:*/
866 /*case slang_oper_rshassign:*/
867 /*case slang_oper_orassign:*/
868 /*case slang_oper_xorassign:*/
869 /*case slang_oper_andassign:*/
870 case slang_oper_divassign
:
871 if (!_slang_assemble_assign (file
, op
, "/=", reference
, space
, info
))
874 case slang_oper_select
:
875 if (!_slang_assemble_select (file
, op
, flow
, space
, info
))
878 case slang_oper_logicalor
:
879 if (!_slang_assemble_logicalor (file
, op
, flow
, space
, info
))
882 case slang_oper_logicaland
:
883 if (!_slang_assemble_logicaland (file
, op
, flow
, space
, info
))
886 case slang_oper_logicalxor
:
887 if (!call_function_name (file
, "^^", op
->children
, 2, 0, space
, info
))
890 /*case slang_oper_bitor:*/
891 /*case slang_oper_bitxor:*/
892 /*case slang_oper_bitand:*/
893 case slang_oper_less
:
894 if (!call_function_name (file
, "<", op
->children
, 2, 0, space
, info
))
897 case slang_oper_greater
:
898 if (!call_function_name (file
, ">", op
->children
, 2, 0, space
, info
))
901 case slang_oper_lessequal
:
902 if (!call_function_name (file
, "<=", op
->children
, 2, 0, space
, info
))
905 case slang_oper_greaterequal
:
906 if (!call_function_name (file
, ">=", op
->children
, 2, 0, space
, info
))
909 /*case slang_oper_lshift:*/
910 /*case slang_oper_rshift:*/
912 if (!call_function_name (file
, "+", op
->children
, 2, 0, space
, info
))
915 case slang_oper_subtract
:
916 if (!call_function_name (file
, "-", op
->children
, 2, 0, space
, info
))
919 case slang_oper_multiply
:
920 if (!call_function_name (file
, "*", op
->children
, 2, 0, space
, info
))
923 /*case slang_oper_modulus:*/
924 case slang_oper_divide
:
925 if (!call_function_name (file
, "/", op
->children
, 2, 0, space
, info
))
928 case slang_oper_equal
:
930 slang_assembly_stack_info stk
;
931 if (!_slang_assemble_operation (file
, op
->children
, 0, flow
, space
, info
, &stk
))
933 /* TODO: inspect stk */
934 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
, &stk
))
936 /* TODO: inspect stk */
937 if (!equality (file
, op
->children
, space
, info
, 1))
941 case slang_oper_notequal
:
943 slang_assembly_stack_info stk
;
944 if (!_slang_assemble_operation (file
, op
->children
, 0, flow
, space
, info
, &stk
))
946 /* TODO: inspect stk */
947 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
, &stk
))
949 /* TODO: inspect stk */
950 if (!equality (file
, op
->children
, space
, info
, 0))
954 case slang_oper_preincrement
:
955 if (!_slang_assemble_assign (file
, op
, "++", reference
, space
, info
))
958 case slang_oper_predecrement
:
959 if (!_slang_assemble_assign (file
, op
, "--", reference
, space
, info
))
962 case slang_oper_plus
:
963 if (!call_function_name (file
, "+", op
->children
, 1, 0, space
, info
))
966 case slang_oper_minus
:
967 if (!call_function_name (file
, "-", op
->children
, 1, 0, space
, info
))
970 /*case slang_oper_complement:*/
972 if (!call_function_name (file
, "!", op
->children
, 1, 0, space
, info
))
975 case slang_oper_subscript
:
977 slang_assembly_stack_info _stk
;
978 slang_assembly_typeinfo ti_arr
, ti_elem
;
979 unsigned int arr_size
= 0, elem_size
= 0;
980 if (!_slang_assemble_operation (file
, op
->children
, reference
, flow
, space
, info
,
983 if (!_slang_assemble_operation (file
, op
->children
+ 1, 0, flow
, space
, info
, &_stk
))
985 slang_assembly_typeinfo_construct (&ti_arr
);
986 if (!_slang_typeof_operation (op
->children
, space
, &ti_arr
))
988 slang_assembly_typeinfo_destruct (&ti_arr
);
991 if (!sizeof_variable (&ti_arr
.spec
, slang_qual_none
, NULL
, space
, &arr_size
))
993 slang_assembly_typeinfo_destruct (&ti_arr
);
996 slang_assembly_typeinfo_construct (&ti_elem
);
997 if (!_slang_typeof_operation (op
, space
, &ti_elem
))
999 slang_assembly_typeinfo_destruct (&ti_arr
);
1000 slang_assembly_typeinfo_destruct (&ti_elem
);
1003 if (!sizeof_variable (&ti_elem
.spec
, slang_qual_none
, NULL
, space
, &elem_size
))
1005 slang_assembly_typeinfo_destruct (&ti_arr
);
1006 slang_assembly_typeinfo_destruct (&ti_elem
);
1009 if (!slang_assembly_file_push (file
, slang_asm_int_to_addr
))
1011 slang_assembly_typeinfo_destruct (&ti_arr
);
1012 slang_assembly_typeinfo_destruct (&ti_elem
);
1015 if (!slang_assembly_file_push_label (file
, slang_asm_addr_push
, elem_size
))
1017 slang_assembly_typeinfo_destruct (&ti_arr
);
1018 slang_assembly_typeinfo_destruct (&ti_elem
);
1021 if (!slang_assembly_file_push (file
, slang_asm_addr_multiply
))
1023 slang_assembly_typeinfo_destruct (&ti_arr
);
1024 slang_assembly_typeinfo_destruct (&ti_elem
);
1029 if (!slang_assembly_file_push (file
, slang_asm_addr_add
))
1031 slang_assembly_typeinfo_destruct (&ti_arr
);
1032 slang_assembly_typeinfo_destruct (&ti_elem
);
1039 for (i
= 0; i
< elem_size
; i
+= 4)
1041 if (!slang_assembly_file_push_label2 (file
, slang_asm_float_move
,
1042 arr_size
- elem_size
+ i
+ 4, i
+ 4))
1044 slang_assembly_typeinfo_destruct (&ti_arr
);
1045 slang_assembly_typeinfo_destruct (&ti_elem
);
1049 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
, 4))
1051 slang_assembly_typeinfo_destruct (&ti_arr
);
1052 slang_assembly_typeinfo_destruct (&ti_elem
);
1055 if (!slang_assembly_file_push_label (file
, slang_asm_local_free
,
1056 arr_size
- elem_size
))
1058 slang_assembly_typeinfo_destruct (&ti_arr
);
1059 slang_assembly_typeinfo_destruct (&ti_elem
);
1063 slang_assembly_typeinfo_destruct (&ti_arr
);
1064 slang_assembly_typeinfo_destruct (&ti_elem
);
1067 case slang_oper_call
:
1069 slang_function
*fun
= _slang_locate_function (op
->identifier
, op
->children
,
1070 op
->num_children
, space
);
1073 if (!_slang_assemble_constructor (file
, op
, flow
, space
, info
))
1078 if (!call_function (file
, fun
, op
->children
, op
->num_children
, 0, space
, info
))
1083 case slang_oper_field
:
1085 slang_assembly_typeinfo ti_after
, ti_before
;
1086 slang_assembly_stack_info _stk
;
1087 slang_assembly_typeinfo_construct (&ti_after
);
1088 if (!_slang_typeof_operation (op
, space
, &ti_after
))
1090 slang_assembly_typeinfo_destruct (&ti_after
);
1093 slang_assembly_typeinfo_construct (&ti_before
);
1094 if (!_slang_typeof_operation (op
->children
, space
, &ti_before
))
1096 slang_assembly_typeinfo_destruct (&ti_after
);
1097 slang_assembly_typeinfo_destruct (&ti_before
);
1100 if (!reference
&& ti_after
.is_swizzled
)
1102 if (!slang_assembly_file_push_label2 (file
, slang_asm_local_addr
,
1103 info
->swizzle_tmp
, 16))
1105 slang_assembly_typeinfo_destruct (&ti_after
);
1106 slang_assembly_typeinfo_destruct (&ti_before
);
1110 if (!_slang_assemble_operation (file
, op
->children
, reference
, flow
, space
, info
,
1113 slang_assembly_typeinfo_destruct (&ti_after
);
1114 slang_assembly_typeinfo_destruct (&ti_before
);
1117 /* TODO: inspect stk */
1118 if (ti_after
.is_swizzled
)
1122 if (ti_after
.swz
.num_components
== 1)
1124 if (!slang_assembly_file_push_label (file
, slang_asm_addr_push
,
1125 ti_after
.swz
.swizzle
[0] * 4))
1127 slang_assembly_typeinfo_destruct (&ti_after
);
1128 slang_assembly_typeinfo_destruct (&ti_before
);
1131 if (!slang_assembly_file_push (file
, slang_asm_addr_add
))
1133 slang_assembly_typeinfo_destruct (&ti_after
);
1134 slang_assembly_typeinfo_destruct (&ti_before
);
1141 for (i
= 0; i
< ti_after
.swz
.num_components
; i
++)
1142 stk
->swizzle_mask
|= 1 << ti_after
.swz
.swizzle
[i
];
1147 if (!_slang_assemble_constructor_from_swizzle (file
, &ti_after
.swz
,
1148 &ti_after
.spec
, &ti_before
.spec
, info
))
1150 slang_assembly_typeinfo_destruct (&ti_after
);
1151 slang_assembly_typeinfo_destruct (&ti_before
);
1160 /* TODO: struct field address */
1164 /* TODO: struct field value */
1167 slang_assembly_typeinfo_destruct (&ti_after
);
1168 slang_assembly_typeinfo_destruct (&ti_before
);
1171 case slang_oper_postincrement
:
1172 if (!call_function_name_dummyint (file
, "++", op
->children
, space
, info
))
1174 if (!dereference (file
, op
, space
, info
))
1177 case slang_oper_postdecrement
:
1178 if (!call_function_name_dummyint (file
, "--", op
->children
, space
, info
))
1180 if (!dereference (file
, op
, space
, info
))
1197 void xxx_first (slang_assembly_file
*file
)
1199 slang_assembly_file_push (file
, slang_asm_jump
);
1202 void xxx_prolog (slang_assembly_file
*file
, unsigned int addr
)
1204 file
->code
[0].param
[0] = file
->count
;
1205 slang_assembly_file_push_label (file
, slang_asm_call
, addr
);
1206 slang_assembly_file_push (file
, slang_asm_exit
);