📄 slang_assemble.c
字号:
if (relocate)
{
if (!PLAB (A->file, slang_asm_addr_push, field_offset))
return GL_FALSE;
}
if (ref == slang_ref_force)
{
if (relocate)
{
if (!PUSH (A->file, slang_asm_addr_add))
return GL_FALSE;
}
}
else
{
GLuint free_b = 0;
if (relocate)
{
GLuint i;
/*
* Move the selected element to the end of the master expression.
* Do it in reverse order to avoid overwriting itself.
*/
for (i = field_size; i > 0; i -= 4)
if (!PLAB2 (A->file, slang_asm_float_move, struct_size - field_size + i, i))
return GL_FALSE;
free_b += 4;
}
if (shrink)
{
/* free the rest of the master expression */
free_b += struct_size - field_size;
}
if (free_b)
{
if (!PLAB (A->file, slang_asm_local_free, free_b))
return GL_FALSE;
}
}
}
return GL_TRUE;
}
GLboolean _slang_assemble_operation (slang_assemble_ctx *A, slang_operation *op, slang_ref_type ref)
{
/* set default results */
A->ref = /*(ref == slang_ref_freelance) ? slang_ref_force : */ref;
A->swz.num_components = 0;
switch (op->type)
{
case slang_oper_block_no_new_scope:
case slang_oper_block_new_scope:
{
GLuint i;
for (i = 0; i < op->num_children; i++)
{
if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid/*slang_ref_freelance*/))
return GL_FALSE;
if (!_slang_cleanup_stack (A, &op->children[i]))
return GL_FALSE;
}
}
break;
case slang_oper_variable_decl:
{
GLuint i;
slang_operation assign;
GLboolean result;
/* Construct assignment expression placeholder. */
if (!slang_operation_construct (&assign))
return GL_FALSE;
assign.type = slang_oper_assign;
assign.children = (slang_operation *) slang_alloc_malloc (2 * sizeof (slang_operation));
if (assign.children == NULL)
{
slang_operation_destruct (&assign);
return GL_FALSE;
}
for (assign.num_children = 0; assign.num_children < 2; assign.num_children++)
if (!slang_operation_construct (&assign.children[assign.num_children]))
{
slang_operation_destruct (&assign);
return GL_FALSE;
}
result = GL_TRUE;
for (i = 0; i < op->num_children; i++)
{
slang_variable *var;
var = _slang_locate_variable (op->children[i].locals, op->children[i].a_id, GL_TRUE);
if (var == NULL)
{
result = GL_FALSE;
break;
}
if (var->initializer == NULL)
continue;
if (!slang_operation_copy (&assign.children[0], &op->children[i]) ||
!slang_operation_copy (&assign.children[1], var->initializer) ||
!_slang_assemble_assign (A, &assign, "=", slang_ref_forbid) ||
!_slang_cleanup_stack (A, &assign))
{
result = GL_FALSE;
break;
}
}
slang_operation_destruct (&assign);
if (!result)
return GL_FALSE;
}
break;
case slang_oper_asm:
{
GLuint i;
if (!_slang_assemble_operation (A, &op->children[0], slang_ref_force))
return GL_FALSE;
for (i = 1; i < op->num_children; i++)
if (!_slang_assemble_operation (A, &op->children[i], slang_ref_forbid))
return GL_FALSE;
if (!call_asm_instruction (A, op->a_id))
return GL_FALSE;
}
break;
case slang_oper_break:
if (!PLAB (A->file, slang_asm_jump, A->flow.loop_end))
return GL_FALSE;
break;
case slang_oper_continue:
if (!PLAB (A->file, slang_asm_jump, A->flow.loop_start))
return GL_FALSE;
break;
case slang_oper_discard:
if (!PUSH (A->file, slang_asm_discard))
return GL_FALSE;
if (!PUSH (A->file, slang_asm_exit))
return GL_FALSE;
break;
case slang_oper_return:
if (A->local.ret_size != 0)
{
/* push the result's address */
if (!PLAB2 (A->file, slang_asm_local_addr, 0, A->local.ret_size))
return GL_FALSE;
if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
return GL_FALSE;
A->swz.num_components = 0;
/* assign the operation to the function result (it was reserved on the stack) */
if (!_slang_assemble_assignment (A, op->children))
return GL_FALSE;
if (!PLAB (A->file, slang_asm_local_free, 4))
return GL_FALSE;
}
if (!PLAB (A->file, slang_asm_jump, A->flow.function_end))
return GL_FALSE;
break;
case slang_oper_expression:
if (ref == slang_ref_force)
return GL_FALSE;
if (!_slang_assemble_operation (A, &op->children[0], ref))
return GL_FALSE;
break;
case slang_oper_if:
if (!_slang_assemble_if (A, op))
return GL_FALSE;
break;
case slang_oper_while:
if (!_slang_assemble_while (A, op))
return GL_FALSE;
break;
case slang_oper_do:
if (!_slang_assemble_do (A, op))
return GL_FALSE;
break;
case slang_oper_for:
if (!_slang_assemble_for (A, op))
return GL_FALSE;
break;
case slang_oper_void:
break;
case slang_oper_literal_bool:
if (ref == slang_ref_force)
return GL_FALSE;
if (!PLIT (A->file, slang_asm_bool_push, op->literal))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_literal_int:
if (ref == slang_ref_force)
return GL_FALSE;
if (!PLIT (A->file, slang_asm_int_push, op->literal))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_literal_float:
if (ref == slang_ref_force)
return GL_FALSE;
if (!PLIT (A->file, slang_asm_float_push, op->literal))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_identifier:
{
slang_variable *var;
GLuint size;
/* find the variable and calculate its size */
var = _slang_locate_variable (op->locals, op->a_id, GL_TRUE);
if (var == NULL)
return GL_FALSE;
size = 0;
if (!sizeof_variable (A, &var->type.specifier, slang_qual_none, var->array_len, &size))
return GL_FALSE;
/* prepare stack for dereferencing */
if (ref == slang_ref_forbid)
if (!PLAB2 (A->file, slang_asm_local_addr, A->local.addr_tmp, 4))
return GL_FALSE;
/* push the variable's address */
if (var->global)
{
if (!PLAB (A->file, slang_asm_global_addr, var->address))
return GL_FALSE;
}
else
{
if (!PLAB2 (A->file, slang_asm_local_addr, var->address, size))
return GL_FALSE;
}
/* perform the dereference */
if (ref == slang_ref_forbid)
{
if (!PUSH (A->file, slang_asm_addr_copy))
return GL_FALSE;
if (!PLAB (A->file, slang_asm_local_free, 4))
return GL_FALSE;
if (!_slang_dereference (A, op))
return GL_FALSE;
}
}
break;
case slang_oper_sequence:
if (ref == slang_ref_force)
return GL_FALSE;
if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
return GL_FALSE;
if (!_slang_cleanup_stack (A, &op->children[0]))
return GL_FALSE;
if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_assign:
if (!_slang_assemble_assign (A, op, "=", ref))
return GL_FALSE;
break;
case slang_oper_addassign:
if (!_slang_assemble_assign (A, op, "+=", ref))
return GL_FALSE;
A->ref = ref;
break;
case slang_oper_subassign:
if (!_slang_assemble_assign (A, op, "-=", ref))
return GL_FALSE;
A->ref = ref;
break;
case slang_oper_mulassign:
if (!_slang_assemble_assign (A, op, "*=", ref))
return GL_FALSE;
A->ref = ref;
break;
/*case slang_oper_modassign:*/
/*case slang_oper_lshassign:*/
/*case slang_oper_rshassign:*/
/*case slang_oper_orassign:*/
/*case slang_oper_xorassign:*/
/*case slang_oper_andassign:*/
case slang_oper_divassign:
if (!_slang_assemble_assign (A, op, "/=", ref))
return GL_FALSE;
A->ref = ref;
break;
case slang_oper_select:
if (!_slang_assemble_select (A, op))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_logicalor:
if (!_slang_assemble_logicalor (A, op))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_logicaland:
if (!_slang_assemble_logicaland (A, op))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_logicalxor:
if (!_slang_assemble_function_call_name (A, "^^", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
/*case slang_oper_bitor:*/
/*case slang_oper_bitxor:*/
/*case slang_oper_bitand:*/
case slang_oper_less:
if (!_slang_assemble_function_call_name (A, "<", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_greater:
if (!_slang_assemble_function_call_name (A, ">", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_lessequal:
if (!_slang_assemble_function_call_name (A, "<=", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_greaterequal:
if (!_slang_assemble_function_call_name (A, ">=", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
/*case slang_oper_lshift:*/
/*case slang_oper_rshift:*/
case slang_oper_add:
if (!_slang_assemble_function_call_name (A, "+", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_subtract:
if (!_slang_assemble_function_call_name (A, "-", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_multiply:
if (!_slang_assemble_function_call_name (A, "*", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
/*case slang_oper_modulus:*/
case slang_oper_divide:
if (!_slang_assemble_function_call_name (A, "/", op->children, 2, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_equal:
if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
return GL_FALSE;
if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
return GL_FALSE;
if (!equality (A, op->children, GL_TRUE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_notequal:
if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
return GL_FALSE;
if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
return GL_FALSE;
if (!equality (A, op->children, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_preincrement:
if (!_slang_assemble_assign (A, op, "++", ref))
return GL_FALSE;
A->ref = ref;
break;
case slang_oper_predecrement:
if (!_slang_assemble_assign (A, op, "--", ref))
return GL_FALSE;
A->ref = ref;
break;
case slang_oper_plus:
if (!_slang_dereference (A, op))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_minus:
if (!_slang_assemble_function_call_name (A, "-", op->children, 1, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
/*case slang_oper_complement:*/
case slang_oper_not:
if (!_slang_assemble_function_call_name (A, "!", op->children, 1, GL_FALSE))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_subscript:
{
slang_assembly_typeinfo ti_arr, ti_elem;
if (!slang_assembly_typeinfo_construct (&ti_arr))
return GL_FALSE;
if (!slang_assembly_typeinfo_construct (&ti_elem))
{
slang_assembly_typeinfo_destruct (&ti_arr);
return GL_FALSE;
}
if (!handle_subscript (A, &ti_elem, &ti_arr, op, ref))
{
slang_assembly_typeinfo_destruct (&ti_arr);
slang_assembly_typeinfo_destruct (&ti_elem);
return GL_FALSE;
}
slang_assembly_typeinfo_destruct (&ti_arr);
slang_assembly_typeinfo_destruct (&ti_elem);
}
break;
case slang_oper_call:
{
slang_function *fun;
fun = _slang_locate_function (A->space.funcs, op->a_id, op->children, op->num_children,
&A->space, A->atoms);
if (fun == NULL)
{
if (!_slang_assemble_constructor (A, op))
return GL_FALSE;
}
else
{
if (!_slang_assemble_function_call (A, fun, op->children, op->num_children, GL_FALSE))
return GL_FALSE;
}
A->ref = slang_ref_forbid;
}
break;
case slang_oper_field:
{
slang_assembly_typeinfo ti_after, ti_before;
if (!slang_assembly_typeinfo_construct (&ti_after))
return GL_FALSE;
if (!slang_assembly_typeinfo_construct (&ti_before))
{
slang_assembly_typeinfo_destruct (&ti_after);
return GL_FALSE;
}
if (!handle_field (A, &ti_after, &ti_before, op, ref))
{
slang_assembly_typeinfo_destruct (&ti_after);
slang_assembly_typeinfo_destruct (&ti_before);
return GL_FALSE;
}
slang_assembly_typeinfo_destruct (&ti_after);
slang_assembly_typeinfo_destruct (&ti_before);
}
break;
case slang_oper_postincrement:
if (!assemble_function_call_name_dummyint (A, "++", op->children))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
case slang_oper_postdecrement:
if (!assemble_function_call_name_dummyint (A, "--", op->children))
return GL_FALSE;
A->ref = slang_ref_forbid;
break;
default:
return GL_FALSE;
}
return GL_TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -