📄 slang_codegen.c
字号:
scope->outer_scope = fun->parameters; /* create local var 't' */ var = slang_variable_scope_grow(scope); var->a_name = slang_atom_pool_atom(A->atoms, "t"); var->type = fun->header.type; /* declare t */ { slang_operation *decl; decl = &fun->body->children[0]; decl->type = SLANG_OPER_VARIABLE_DECL; decl->locals = _slang_variable_scope_new(scope); decl->a_id = var->a_name; } /* assign params to fields of t */ for (i = 0; i < numFields; i++) { slang_operation *assign = &fun->body->children[1 + i]; assign->type = SLANG_OPER_ASSIGN; assign->locals = _slang_variable_scope_new(scope); assign->num_children = 2; assign->children = slang_operation_new(2); { slang_operation *lhs = &assign->children[0]; lhs->type = SLANG_OPER_FIELD; lhs->locals = _slang_variable_scope_new(scope); lhs->num_children = 1; lhs->children = slang_operation_new(1); lhs->a_id = str->fields->variables[i]->a_name; lhs->children[0].type = SLANG_OPER_IDENTIFIER; lhs->children[0].a_id = var->a_name; lhs->children[0].locals = _slang_variable_scope_new(scope);#if 0 lhs->children[1].num_children = 1; lhs->children[1].children = slang_operation_new(1); lhs->children[1].children[0].type = SLANG_OPER_IDENTIFIER; lhs->children[1].children[0].a_id = str->fields->variables[i]->a_name; lhs->children[1].children->locals = _slang_variable_scope_new(scope);#endif } { slang_operation *rhs = &assign->children[1]; rhs->type = SLANG_OPER_IDENTIFIER; rhs->locals = _slang_variable_scope_new(scope); rhs->a_id = str->fields->variables[i]->a_name; } } /* return t; */ { slang_operation *ret = &fun->body->children[numFields + 1]; ret->type = SLANG_OPER_RETURN; ret->locals = _slang_variable_scope_new(scope); ret->num_children = 1; ret->children = slang_operation_new(1); ret->children[0].type = SLANG_OPER_IDENTIFIER; ret->children[0].a_id = var->a_name; ret->children[0].locals = _slang_variable_scope_new(scope); } } /* slang_print_function(fun, 1); */ return fun;}/** * Find/create a function (constructor) for the given structure name. */static slang_function *_slang_locate_struct_constructor(slang_assemble_ctx *A, const char *name){ unsigned int i; for (i = 0; i < A->space.structs->num_structs; i++) { slang_struct *str = &A->space.structs->structs[i]; if (strcmp(name, (const char *) str->a_name) == 0) { /* found a structure type that matches the function name */ if (!str->constructor) { /* create the constructor function now */ str->constructor = _slang_make_constructor(A, str); } return str->constructor; } } return NULL;}static GLboolean_slang_is_vec_mat_type(const char *name){ static const char *vecmat_types[] = { "float", "int", "bool", "vec2", "vec3", "vec4", "ivec2", "ivec3", "ivec4", "bvec2", "bvec3", "bvec4", "mat2", "mat3", "mat4", "mat2x3", "mat2x4", "mat3x2", "mat3x4", "mat4x2", "mat4x3", NULL }; int i; for (i = 0; vecmat_types[i]; i++) if (_mesa_strcmp(name, vecmat_types[i]) == 0) return GL_TRUE; return GL_FALSE;}/** * Assemble a function call, given a particular function name. * \param name the function's name (operators like '*' are possible). */static slang_ir_node *_slang_gen_function_call_name(slang_assemble_ctx *A, const char *name, slang_operation *oper, slang_operation *dest){ slang_operation *params = oper->children; const GLuint param_count = oper->num_children; slang_atom atom; slang_function *fun; GLboolean error; slang_ir_node *n; atom = slang_atom_pool_atom(A->atoms, name); if (atom == SLANG_ATOM_NULL) return NULL; /* * First, try to find function by name and exact argument type matching. */ fun = _slang_locate_function(A->space.funcs, atom, params, param_count, &A->space, A->atoms, A->log, &error); if (error) { slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name); return NULL; } if (!fun) { /* Next, try locating a constructor function for a user-defined type */ fun = _slang_locate_struct_constructor(A, name); } /* * At this point, some heuristics are used to try to find a function * that matches the calling signature by means of casting or "unrolling" * of constructors. */ if (!fun && _slang_is_vec_mat_type(name)) { /* Next, if this call looks like a vec() or mat() constructor call, * try "unwinding" the args to satisfy a constructor. */ fun = _slang_find_function_by_max_argc(A->space.funcs, name); if (fun) { if (!_slang_adapt_call(oper, fun, &A->space, A->atoms, A->log)) { slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name); return NULL; } } } if (!fun && _slang_is_vec_mat_type(name)) { /* Next, try casting args to the types of the formal parameters */ int numArgs = oper->num_children; fun = _slang_find_function_by_argc(A->space.funcs, name, numArgs); if (!fun || !_slang_cast_func_params(oper, fun, &A->space, A->atoms, A->log)) { slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name); return NULL; } assert(fun); } if (!fun) { slang_info_log_error(A->log, "Function '%s' not found (check argument types)", name); return NULL; } n = _slang_gen_function_call(A, fun, oper, dest); if (n && !n->Store && !dest && fun->header.type.specifier.type != SLANG_SPEC_VOID) { /* setup n->Store for the result of the function call */ GLint size = _slang_sizeof_type_specifier(&fun->header.type.specifier); n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, size); /*printf("Alloc storage for function result, size %d \n", size);*/ } return n;}static GLboolean_slang_is_constant_cond(const slang_operation *oper, GLboolean *value){ if (oper->type == SLANG_OPER_LITERAL_FLOAT || oper->type == SLANG_OPER_LITERAL_INT || oper->type == SLANG_OPER_LITERAL_BOOL) { if (oper->literal[0]) *value = GL_TRUE; else *value = GL_FALSE; return GL_TRUE; } else if (oper->type == SLANG_OPER_EXPRESSION && oper->num_children == 1) { return _slang_is_constant_cond(&oper->children[0], value); } return GL_FALSE;}/** * Test if an operation is a scalar or boolean. */static GLboolean_slang_is_scalar_or_boolean(slang_assemble_ctx *A, slang_operation *oper){ slang_typeinfo type; GLint size; slang_typeinfo_construct(&type); _slang_typeof_operation(A, oper, &type); size = _slang_sizeof_type_specifier(&type.spec); slang_typeinfo_destruct(&type); return size == 1;}/** * Test if an operation is boolean. */static GLboolean_slang_is_boolean(slang_assemble_ctx *A, slang_operation *oper){ slang_typeinfo type; GLboolean isBool; slang_typeinfo_construct(&type); _slang_typeof_operation(A, oper, &type); isBool = (type.spec.type == SLANG_SPEC_BOOL); slang_typeinfo_destruct(&type); return isBool;}/** * Generate loop code using high-level IR_LOOP instruction */static slang_ir_node *_slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper){ /* * LOOP: * BREAK if !expr (child[0]) * body code (child[1]) */ slang_ir_node *prevLoop, *loop, *breakIf, *body; GLboolean isConst, constTrue; /* type-check expression */ if (!_slang_is_boolean(A, &oper->children[0])) { slang_info_log_error(A->log, "scalar/boolean expression expected for 'while'"); return NULL; } /* Check if loop condition is a constant */ isConst = _slang_is_constant_cond(&oper->children[0], &constTrue); if (isConst && !constTrue) { /* loop is never executed! */ return new_node0(IR_NOP); } loop = new_loop(NULL); /* save old, push new loop */ prevLoop = A->CurLoop; A->CurLoop = loop; if (isConst && constTrue) { /* while(nonzero constant), no conditional break */ breakIf = NULL; } else { slang_ir_node *cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[0]))); breakIf = new_break_if_true(A->CurLoop, cond); } body = _slang_gen_operation(A, &oper->children[1]); loop->Children[0] = new_seq(breakIf, body); /* Do infinite loop detection */ /* loop->List is head of linked list of break/continue nodes */ if (!loop->List && isConst && constTrue) { /* infinite loop detected */ A->CurLoop = prevLoop; /* clean-up */ slang_info_log_error(A->log, "Infinite loop detected!"); return NULL; } /* pop loop, restore prev */ A->CurLoop = prevLoop; return loop;}/** * Generate IR tree for a do-while loop using high-level LOOP, IF instructions. */static slang_ir_node *_slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper){ /* * LOOP: * body code (child[0]) * tail code: * BREAK if !expr (child[1]) */ slang_ir_node *prevLoop, *loop; GLboolean isConst, constTrue; /* type-check expression */ if (!_slang_is_boolean(A, &oper->children[1])) { slang_info_log_error(A->log, "scalar/boolean expression expected for 'do/while'"); return NULL; } loop = new_loop(NULL); /* save old, push new loop */ prevLoop = A->CurLoop; A->CurLoop = loop; /* loop body: */ loop->Children[0] = _slang_gen_operation(A, &oper->children[0]); /* Check if loop condition is a constant */ isConst = _slang_is_constant_cond(&oper->children[1], &constTrue); if (isConst && constTrue) { /* do { } while(1) ==> no conditional break */ loop->Children[1] = NULL; /* no tail code */ } else { slang_ir_node *cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1]))); loop->Children[1] = new_break_if_true(A->CurLoop, cond); } /* XXX we should do infinite loop detection, as above */ /* pop loop, restore prev */ A->CurLoop = prevLoop; return loop;}/** * Generate for-loop using high-level IR_LOOP instruction. */static slang_ir_node *_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper){ /* * init code (child[0]) * LOOP: * BREAK if !expr (child[1]) * body code (child[3]) * tail code: * incr code (child[2]) // XXX continue here */ slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr; init = _slang_gen_operation(A, &oper->children[0]); loop = new_loop(NULL); /* save old, push new loop */ prevLoop = A->CurLoop; A->CurLoop = loop; cond = new_cond(new_not(_slang_gen_operation(A, &oper->children[1]))); breakIf = new_break_if_true(A->CurLoop, cond); body = _slang_gen_operation(A, &oper->children[3]); incr = _slang_gen_operation(A, &oper->children[2]); loop->Children[0] = new_seq(breakIf, body); loop->Children[1] = incr; /* tail code */ /* pop loop, restore prev */ A->CurLoop = prevLoop; return new_seq(init, loop);}static slang_ir_node *_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper){ slang_ir_node *n, *loopNode; assert(oper->type == SLANG_OPER_CONTINUE); loopNode = A->CurLoop; assert(loopNode); assert(loopNode->Opcode == IR_LOOP); n = new_node0(IR_CONT); if (n) { n->Parent = loopNode; /* insert this node at head of linked list */ n->List = loopNode->List; loopNode->List = n; } return n;}/** * Determine if the given operation is of a specific type. */static GLbooleanis_operation_type(const slang_operation *oper, slang_operation_type type){ if (oper->type == type) return GL_TRUE; else if ((oper->type == SLANG_OPER_BLOCK_NEW_SCOPE || oper->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE) && oper->num_children == 1) return is_operation_type(&oper->children[0], type); else return GL_FALSE;}/** * Generate IR tree for an if/then/else conditional using high-level
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -