📄 slang_codegen.c
字号:
/* Replace the function call with the inlined block (or new CALL stmt) */ slang_operation_destruct(oper); *oper = *inlined; _slang_free(inlined);#if 0 assert(inlined->locals); printf("*** Inlined code for call to %s:\n", (char*) fun->header.a_name); slang_print_tree(oper, 10); printf("\n");#endif n = _slang_gen_operation(A, oper); /*_slang_label_delete(A->curFuncEndLabel);*/ A->curFuncEndLabel = prevFuncEndLabel; return n;}static slang_asm_info *slang_find_asm_info(const char *name){ GLuint i; for (i = 0; AsmInfo[i].Name; i++) { if (_mesa_strcmp(AsmInfo[i].Name, name) == 0) { return AsmInfo + i; } } return NULL;}/** * Return the default swizzle mask for accessing a variable of the * given size (in floats). If size = 1, comp is used to identify * which component [0..3] of the register holds the variable. */static GLuint_slang_var_swizzle(GLint size, GLint comp){ switch (size) { case 1: return MAKE_SWIZZLE4(comp, comp, comp, comp); case 2: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL); case 3: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_NIL); default: return SWIZZLE_XYZW; }}/** * Some write-masked assignments are simple, but others are hard. * Simple example: * vec3 v; * v.xy = vec2(a, b); * Hard example: * vec3 v; * v.zy = vec2(a, b); * this gets transformed/swizzled into: * v.zy = vec2(a, b).*yx* (* = don't care) * This function helps to determine simple vs. non-simple. */static GLboolean_slang_simple_writemask(GLuint writemask, GLuint swizzle){ switch (writemask) { case WRITEMASK_X: return GET_SWZ(swizzle, 0) == SWIZZLE_X; case WRITEMASK_Y: return GET_SWZ(swizzle, 1) == SWIZZLE_Y; case WRITEMASK_Z: return GET_SWZ(swizzle, 2) == SWIZZLE_Z; case WRITEMASK_W: return GET_SWZ(swizzle, 3) == SWIZZLE_W; case WRITEMASK_XY: return (GET_SWZ(swizzle, 0) == SWIZZLE_X) && (GET_SWZ(swizzle, 1) == SWIZZLE_Y); case WRITEMASK_XYZ: return (GET_SWZ(swizzle, 0) == SWIZZLE_X) && (GET_SWZ(swizzle, 1) == SWIZZLE_Y) && (GET_SWZ(swizzle, 2) == SWIZZLE_Z); case WRITEMASK_XYZW: return swizzle == SWIZZLE_NOOP; default: return GL_FALSE; }}/** * Convert the given swizzle into a writemask. In some cases this * is trivial, in other cases, we'll need to also swizzle the right * hand side to put components in the right places. * \param swizzle the incoming swizzle * \param writemaskOut returns the writemask * \param swizzleOut swizzle to apply to the right-hand-side * \return GL_FALSE for simple writemasks, GL_TRUE for non-simple */static GLbooleanswizzle_to_writemask(slang_assemble_ctx *A, GLuint swizzle, GLuint *writemaskOut, GLuint *swizzleOut){ GLuint mask = 0x0, newSwizzle[4]; GLint i, size; /* make new dst writemask, compute size */ for (i = 0; i < 4; i++) { const GLuint swz = GET_SWZ(swizzle, i); if (swz == SWIZZLE_NIL) { /* end */ break; } assert(swz >= 0 && swz <= 3); if (swizzle != SWIZZLE_XXXX && swizzle != SWIZZLE_YYYY && swizzle != SWIZZLE_ZZZZ && swizzle != SWIZZLE_WWWW && (mask & (1 << swz))) { /* a channel can't be specified twice (ex: ".xyyz") */ slang_info_log_error(A->log, "Invalid writemask '%s'", _mesa_swizzle_string(swizzle, 0, 0)); return GL_FALSE; } mask |= (1 << swz); } assert(mask <= 0xf); size = i; /* number of components in mask/swizzle */ *writemaskOut = mask; /* make new src swizzle, by inversion */ for (i = 0; i < 4; i++) { newSwizzle[i] = i; /*identity*/ } for (i = 0; i < size; i++) { const GLuint swz = GET_SWZ(swizzle, i); newSwizzle[swz] = i; } *swizzleOut = MAKE_SWIZZLE4(newSwizzle[0], newSwizzle[1], newSwizzle[2], newSwizzle[3]); if (_slang_simple_writemask(mask, *swizzleOut)) { if (size >= 1) assert(GET_SWZ(*swizzleOut, 0) == SWIZZLE_X); if (size >= 2) assert(GET_SWZ(*swizzleOut, 1) == SWIZZLE_Y); if (size >= 3) assert(GET_SWZ(*swizzleOut, 2) == SWIZZLE_Z); if (size >= 4) assert(GET_SWZ(*swizzleOut, 3) == SWIZZLE_W); return GL_TRUE; } else return GL_FALSE;}/** * Recursively traverse 'oper' to produce a swizzle mask in the event * of any vector subscripts and swizzle suffixes. * Ex: for "vec4 v", "v[2].x" resolves to v.z */static GLuintresolve_swizzle(const slang_operation *oper){ if (oper->type == SLANG_OPER_FIELD) { /* writemask from .xyzw suffix */ slang_swizzle swz; if (_slang_is_swizzle((char*) oper->a_id, 4, &swz)) { GLuint swizzle = MAKE_SWIZZLE4(swz.swizzle[0], swz.swizzle[1], swz.swizzle[2], swz.swizzle[3]); GLuint child_swizzle = resolve_swizzle(&oper->children[0]); GLuint s = _slang_swizzle_swizzle(child_swizzle, swizzle); return s; } else return SWIZZLE_XYZW; } else if (oper->type == SLANG_OPER_SUBSCRIPT && oper->children[1].type == SLANG_OPER_LITERAL_INT) { /* writemask from [index] */ GLuint child_swizzle = resolve_swizzle(&oper->children[0]); GLuint i = (GLuint) oper->children[1].literal[0]; GLuint swizzle; GLuint s; switch (i) { case 0: swizzle = SWIZZLE_XXXX; break; case 1: swizzle = SWIZZLE_YYYY; break; case 2: swizzle = SWIZZLE_ZZZZ; break; case 3: swizzle = SWIZZLE_WWWW; break; default: swizzle = SWIZZLE_XYZW; } s = _slang_swizzle_swizzle(child_swizzle, swizzle); return s; } else { return SWIZZLE_XYZW; }}/** * As above, but produce a writemask. */static GLuintresolve_writemask(slang_assemble_ctx *A, const slang_operation *oper){ GLuint swizzle = resolve_swizzle(oper); GLuint writemask, swizzleOut; swizzle_to_writemask(A, swizzle, &writemask, &swizzleOut); return writemask;}/** * Recursively descend through swizzle nodes to find the node's storage info. */static slang_ir_storage *get_store(const slang_ir_node *n){ if (n->Opcode == IR_SWIZZLE) { return get_store(n->Children[0]); } return n->Store;}/** * Generate IR tree for an asm instruction/operation such as: * __asm vec4_dot __retVal.x, v1, v2; */static slang_ir_node *_slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper, slang_operation *dest){ const slang_asm_info *info; slang_ir_node *kids[3], *n; GLuint j, firstOperand; assert(oper->type == SLANG_OPER_ASM); info = slang_find_asm_info((char *) oper->a_id); if (!info) { _mesa_problem(NULL, "undefined __asm function %s\n", (char *) oper->a_id); assert(info); } assert(info->NumParams <= 3); if (info->NumParams == oper->num_children) { /* Storage for result is not specified. * Children[0], [1], [2] are the operands. */ firstOperand = 0; } else { /* Storage for result (child[0]) is specified. * Children[1], [2], [3] are the operands. */ firstOperand = 1; } /* assemble child(ren) */ kids[0] = kids[1] = kids[2] = NULL; for (j = 0; j < info->NumParams; j++) { kids[j] = _slang_gen_operation(A, &oper->children[firstOperand + j]); if (!kids[j]) return NULL; } n = new_node3(info->Opcode, kids[0], kids[1], kids[2]); if (firstOperand) { /* Setup n->Store to be a particular location. Otherwise, storage * for the result (a temporary) will be allocated later. */ GLuint writemask = WRITEMASK_XYZW; slang_operation *dest_oper; slang_ir_node *n0; dest_oper = &oper->children[0]; writemask = resolve_writemask(A, dest_oper); n0 = _slang_gen_operation(A, dest_oper); if (!n0) return NULL; assert(!n->Store); n->Store = n0->Store; assert(n->Store->File != PROGRAM_UNDEFINED || n->Store->Parent); _slang_free(n0); } return n;}static voidprint_funcs(struct slang_function_scope_ *scope, const char *name){ GLuint i; for (i = 0; i < scope->num_functions; i++) { slang_function *f = &scope->functions[i]; if (!name || strcmp(name, (char*) f->header.a_name) == 0) printf(" %s (%d args)\n", name, f->param_count); } if (scope->outer_scope) print_funcs(scope->outer_scope, name);}/** * Find a function of the given name, taking 'numArgs' arguments. * This is the function we'll try to call when there is no exact match * between function parameters and call arguments. * * XXX we should really create a list of candidate functions and try * all of them... */static slang_function *_slang_find_function_by_argc(slang_function_scope *scope, const char *name, int numArgs){ while (scope) { GLuint i; for (i = 0; i < scope->num_functions; i++) { slang_function *f = &scope->functions[i]; if (strcmp(name, (char*) f->header.a_name) == 0) { int haveRetValue = _slang_function_has_return_value(f); if (numArgs == f->param_count - haveRetValue) return f; } } scope = scope->outer_scope; } return NULL;}static slang_function *_slang_find_function_by_max_argc(slang_function_scope *scope, const char *name){ slang_function *maxFunc = NULL; GLuint maxArgs = 0; while (scope) { GLuint i; for (i = 0; i < scope->num_functions; i++) { slang_function *f = &scope->functions[i]; if (strcmp(name, (char*) f->header.a_name) == 0) { if (f->param_count > maxArgs) { maxArgs = f->param_count; maxFunc = f; } } } scope = scope->outer_scope; } return maxFunc;}/** * Generate a new slang_function which is a constructor for a user-defined * struct type. */static slang_function *_slang_make_constructor(slang_assemble_ctx *A, slang_struct *str){ const GLint numFields = str->fields->num_variables; slang_function *fun = (slang_function *) _mesa_malloc(sizeof(slang_function)); if (!fun) return NULL; slang_function_construct(fun); /* function header (name, return type) */ fun->kind = SLANG_FUNC_CONSTRUCTOR; fun->header.a_name = str->a_name; fun->header.type.qualifier = SLANG_QUAL_NONE; fun->header.type.specifier.type = SLANG_SPEC_STRUCT; fun->header.type.specifier._struct = str; /* function parameters (= struct's fields) */ { GLint i; for (i = 0; i < numFields; i++) { /* printf("Field %d: %s\n", i, (char*) str->fields->variables[i]->a_name); */ slang_variable *p = slang_variable_scope_grow(fun->parameters); *p = *str->fields->variables[i]; /* copy the type */ p->type.qualifier = SLANG_QUAL_CONST; } fun->param_count = fun->parameters->num_variables; } /* Add __retVal to params */ { slang_variable *p = slang_variable_scope_grow(fun->parameters); slang_atom a_retVal = slang_atom_pool_atom(A->atoms, "__retVal"); assert(a_retVal); p->a_name = a_retVal; p->type = fun->header.type; p->type.qualifier = SLANG_QUAL_OUT; fun->param_count++; } /* function body is: * block: * declare T; * T.f1 = p1; * T.f2 = p2; * ... * T.fn = pn; * return T; */ { slang_variable_scope *scope; slang_variable *var; GLint i; fun->body = slang_operation_new(1); fun->body->type = SLANG_OPER_BLOCK_NEW_SCOPE; fun->body->num_children = numFields + 2; fun->body->children = slang_operation_new(numFields + 2); scope = fun->body->locals;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -