⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slang_codegen.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 5 页
字号:
                       substCount, substOld, substNew, GL_TRUE);      slang_substitute(A, &oper->children[1],                       substCount, substOld, substNew, GL_FALSE);      break;   case SLANG_OPER_FIELD:      /* XXX NEW - test */      slang_substitute(A, &oper->children[0],                       substCount, substOld, substNew, GL_TRUE);      break;   default:      {         GLuint i;         for (i = 0; i < oper->num_children; i++)             slang_substitute(A, &oper->children[i],                             substCount, substOld, substNew, GL_FALSE);      }   }}/** * Produce inline code for a call to an assembly instruction. * This is typically used to compile a call to a built-in function like this: * * vec4 mix(const vec4 x, const vec4 y, const vec4 a) * { *    __asm vec4_lrp __retVal, a, y, x; * } * * * A call to *     r = mix(p1, p2, p3); * * Becomes: * *              mov *             /   \ *            r   vec4_lrp *                 /  |  \ *                p3  p2  p1 * * We basically translate a SLANG_OPER_CALL into a SLANG_OPER_ASM. */static slang_operation *slang_inline_asm_function(slang_assemble_ctx *A,                          slang_function *fun, slang_operation *oper){   const GLuint numArgs = oper->num_children;   GLuint i;   slang_operation *inlined;   const GLboolean haveRetValue = _slang_function_has_return_value(fun);   slang_variable **substOld;   slang_operation **substNew;   ASSERT(slang_is_asm_function(fun));   ASSERT(fun->param_count == numArgs + haveRetValue);   /*   printf("Inline %s as %s\n",          (char*) fun->header.a_name,          (char*) fun->body->children[0].a_id);   */   /*    * We'll substitute formal params with actual args in the asm call.    */   substOld = (slang_variable **)      _slang_alloc(numArgs * sizeof(slang_variable *));   substNew = (slang_operation **)      _slang_alloc(numArgs * sizeof(slang_operation *));   for (i = 0; i < numArgs; i++) {      substOld[i] = fun->parameters->variables[i];      substNew[i] = oper->children + i;   }   /* make a copy of the code to inline */   inlined = slang_operation_new(1);   slang_operation_copy(inlined, &fun->body->children[0]);   if (haveRetValue) {      /* get rid of the __retVal child */      inlined->num_children--;      for (i = 0; i < inlined->num_children; i++) {         inlined->children[i] = inlined->children[i + 1];      }   }   /* now do formal->actual substitutions */   slang_substitute(A, inlined, numArgs, substOld, substNew, GL_FALSE);   _slang_free(substOld);   _slang_free(substNew);#if 0   printf("+++++++++++++ inlined asm function %s +++++++++++++\n",          (char *) fun->header.a_name);   slang_print_tree(inlined, 3);   printf("+++++++++++++++++++++++++++++++++++++++++++++++++++\n");#endif   return inlined;}/** * Inline the given function call operation. * Return a new slang_operation that corresponds to the inlined code. */static slang_operation *slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,			   slang_operation *oper, slang_operation *returnOper){   typedef enum {      SUBST = 1,      COPY_IN,      COPY_OUT   } ParamMode;   ParamMode *paramMode;   const GLboolean haveRetValue = _slang_function_has_return_value(fun);   const GLuint numArgs = oper->num_children;   const GLuint totalArgs = numArgs + haveRetValue;   slang_operation *args = oper->children;   slang_operation *inlined, *top;   slang_variable **substOld;   slang_operation **substNew;   GLuint substCount, numCopyIn, i;   slang_function *prevFunction;   slang_variable_scope *newScope = NULL;   /* save / push */   prevFunction = A->CurFunction;   A->CurFunction = fun;   /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */   assert(fun->param_count == totalArgs);   /* allocate temporary arrays */   paramMode = (ParamMode *)      _slang_alloc(totalArgs * sizeof(ParamMode));   substOld = (slang_variable **)      _slang_alloc(totalArgs * sizeof(slang_variable *));   substNew = (slang_operation **)      _slang_alloc(totalArgs * sizeof(slang_operation *));#if 0   printf("\nInline call to %s  (total vars=%d  nparams=%d)\n",	  (char *) fun->header.a_name,	  fun->parameters->num_variables, numArgs);#endif   if (haveRetValue && !returnOper) {      /* Create 3-child comma sequence for inlined code:       * child[0]:  declare __resultTmp       * child[1]:  inlined function body       * child[2]:  __resultTmp       */      slang_operation *commaSeq;      slang_operation *declOper = NULL;      slang_variable *resultVar;      commaSeq = slang_operation_new(1);      commaSeq->type = SLANG_OPER_SEQUENCE;      assert(commaSeq->locals);      commaSeq->locals->outer_scope = oper->locals->outer_scope;      commaSeq->num_children = 3;      commaSeq->children = slang_operation_new(3);      /* allocate the return var */      resultVar = slang_variable_scope_grow(commaSeq->locals);      /*      printf("Alloc __resultTmp in scope %p for retval of calling %s\n",             (void*)commaSeq->locals, (char *) fun->header.a_name);      */      resultVar->a_name = slang_atom_pool_atom(A->atoms, "__resultTmp");      resultVar->type = fun->header.type; /* XXX copy? */      resultVar->isTemp = GL_TRUE;      /* child[0] = __resultTmp declaration */      declOper = &commaSeq->children[0];      declOper->type = SLANG_OPER_VARIABLE_DECL;      declOper->a_id = resultVar->a_name;      declOper->locals->outer_scope = commaSeq->locals;      /* child[1] = function body */      inlined = &commaSeq->children[1];      inlined->locals->outer_scope = commaSeq->locals;      /* child[2] = __resultTmp reference */      returnOper = &commaSeq->children[2];      returnOper->type = SLANG_OPER_IDENTIFIER;      returnOper->a_id = resultVar->a_name;      returnOper->locals->outer_scope = commaSeq->locals;      top = commaSeq;   }   else {      top = inlined = slang_operation_new(1);      /* XXXX this may be inappropriate!!!! */      inlined->locals->outer_scope = oper->locals->outer_scope;   }   assert(inlined->locals);   /* Examine the parameters, look for inout/out params, look for possible    * substitutions, etc:    *    param type      behaviour    *     in             copy actual to local    *     const in       substitute param with actual    *     out            copy out    */   substCount = 0;   for (i = 0; i < totalArgs; i++) {      slang_variable *p = fun->parameters->variables[i];      /*      printf("Param %d: %s %s \n", i,             slang_type_qual_string(p->type.qualifier),	     (char *) p->a_name);      */      if (p->type.qualifier == SLANG_QUAL_INOUT ||	  p->type.qualifier == SLANG_QUAL_OUT) {	 /* an output param */         slang_operation *arg;         if (i < numArgs)            arg = &args[i];         else            arg = returnOper;	 paramMode[i] = SUBST;	 if (arg->type == SLANG_OPER_IDENTIFIER)            slang_resolve_variable(arg);         /* replace parameter 'p' with argument 'arg' */	 substOld[substCount] = p;	 substNew[substCount] = arg; /* will get copied */	 substCount++;      }      else if (p->type.qualifier == SLANG_QUAL_CONST) {	 /* a constant input param */	 if (args[i].type == SLANG_OPER_IDENTIFIER ||	     args[i].type == SLANG_OPER_LITERAL_FLOAT) {	    /* replace all occurances of this parameter variable with the	     * actual argument variable or a literal.	     */	    paramMode[i] = SUBST;            slang_resolve_variable(&args[i]);	    substOld[substCount] = p;	    substNew[substCount] = &args[i]; /* will get copied */	    substCount++;	 }	 else {	    paramMode[i] = COPY_IN;	 }      }      else {	 paramMode[i] = COPY_IN;      }      assert(paramMode[i]);   }   /* actual code inlining: */   slang_operation_copy(inlined, fun->body);   /*** XXX review this */   assert(inlined->type == SLANG_OPER_BLOCK_NO_NEW_SCOPE ||          inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE);   inlined->type = SLANG_OPER_BLOCK_NEW_SCOPE;#if 0   printf("======================= orig body code ======================\n");   printf("=== params scope = %p\n", (void*) fun->parameters);   slang_print_tree(fun->body, 8);   printf("======================= copied code =========================\n");   slang_print_tree(inlined, 8);#endif   /* do parameter substitution in inlined code: */   slang_substitute(A, inlined, substCount, substOld, substNew, GL_FALSE);#if 0   printf("======================= subst code ==========================\n");   slang_print_tree(inlined, 8);   printf("=============================================================\n");#endif   /* New prolog statements: (inserted before the inlined code)    * Copy the 'in' arguments.    */   numCopyIn = 0;   for (i = 0; i < numArgs; i++) {      if (paramMode[i] == COPY_IN) {	 slang_variable *p = fun->parameters->variables[i];	 /* declare parameter 'p' */	 slang_operation *decl = slang_operation_insert(&inlined->num_children,							&inlined->children,							numCopyIn);	 decl->type = SLANG_OPER_VARIABLE_DECL;         assert(decl->locals);         decl->locals->outer_scope = inlined->locals;	 decl->a_id = p->a_name;	 decl->num_children = 1;	 decl->children = slang_operation_new(1);         /* child[0] is the var's initializer */         slang_operation_copy(&decl->children[0], args + i);         /* add parameter 'p' to the local variable scope here */         {            slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);            pCopy->type = p->type;            pCopy->a_name = p->a_name;            pCopy->array_len = p->array_len;         }         newScope = inlined->locals;	 numCopyIn++;      }   }   /* Now add copies of the function's local vars to the new variable scope */   for (i = totalArgs; i < fun->parameters->num_variables; i++) {      slang_variable *p = fun->parameters->variables[i];      slang_variable *pCopy = slang_variable_scope_grow(inlined->locals);      pCopy->type = p->type;      pCopy->a_name = p->a_name;      pCopy->array_len = p->array_len;   }   /* New epilog statements:    * 1. Create end of function label to jump to from return statements.    * 2. Copy the 'out' parameter vars    */   {      slang_operation *lab = slang_operation_insert(&inlined->num_children,                                                    &inlined->children,                                                    inlined->num_children);      lab->type = SLANG_OPER_LABEL;      lab->label = A->curFuncEndLabel;   }   for (i = 0; i < totalArgs; i++) {      if (paramMode[i] == COPY_OUT) {	 const slang_variable *p = fun->parameters->variables[i];	 /* actualCallVar = outParam */	 /*if (i > 0 || !haveRetValue)*/	 slang_operation *ass = slang_operation_insert(&inlined->num_children,						       &inlined->children,						       inlined->num_children);	 ass->type = SLANG_OPER_ASSIGN;	 ass->num_children = 2;         ass->locals->outer_scope = inlined->locals;	 ass->children = slang_operation_new(2);	 ass->children[0] = args[i]; /*XXX copy */	 ass->children[1].type = SLANG_OPER_IDENTIFIER;	 ass->children[1].a_id = p->a_name;         ass->children[1].locals->outer_scope = ass->locals;      }   }   _slang_free(paramMode);   _slang_free(substOld);   _slang_free(substNew);   /* Update scoping to use the new local vars instead of the    * original function's vars.  This is especially important    * for nested inlining.    */   if (newScope)      slang_replace_scope(inlined, fun->parameters, newScope);#if 0   printf("Done Inline call to %s  (total vars=%d  nparams=%d)\n\n",	  (char *) fun->header.a_name,	  fun->parameters->num_variables, numArgs);   slang_print_tree(top, 0);#endif   /* pop */   A->CurFunction = prevFunction;   return top;}static slang_ir_node *_slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,                         slang_operation *oper, slang_operation *dest){   slang_ir_node *n;   slang_operation *inlined;   slang_label *prevFuncEndLabel;   char name[200];   prevFuncEndLabel = A->curFuncEndLabel;   sprintf(name, "__endOfFunc_%s_", (char *) fun->header.a_name);   A->curFuncEndLabel = _slang_label_new(name);   assert(A->curFuncEndLabel);   if (slang_is_asm_function(fun) && !dest) {      /* assemble assembly function - tree style */      inlined = slang_inline_asm_function(A, fun, oper);   }   else {      /* non-assembly function */      /* We always generate an "inline-able" block of code here.       * We may either:       *  1. insert the inline code       *  2. Generate a call to the "inline" code as a subroutine       */      slang_operation *ret = NULL;      inlined = slang_inline_function_call(A, fun, oper, dest);      if (!inlined)         return NULL;      ret = _slang_find_node_type(inlined, SLANG_OPER_RETURN);      if (ret) {         /* check if this is a "tail" return */         if (_slang_count_node_type(inlined, SLANG_OPER_RETURN) == 1 &&             _slang_is_tail_return(inlined)) {            /* The only RETURN is the last stmt in the function, no-op it             * and inline the function body.             */            ret->type = SLANG_OPER_NONE;         }         else {            slang_operation *callOper;            /* The function we're calling has one or more 'return' statements.             * So, we can't truly inline this function because we need to             * implement 'return' with RET (and CAL).             * Nevertheless, we performed "inlining" to make a new instance             * of the function body to deal with static register allocation.             *             * XXX check if there's one 'return' and if it's the very last             * statement in the function - we can optimize that case.             */            assert(inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE ||                   inlined->type == SLANG_OPER_SEQUENCE);            if (_slang_function_has_return_value(fun) && !dest) {               assert(inlined->children[0].type == SLANG_OPER_VARIABLE_DECL);               assert(inlined->children[2].type == SLANG_OPER_IDENTIFIER);               callOper = &inlined->children[1];            }            else {               callOper = inlined;            }            callOper->type = SLANG_OPER_NON_INLINED_CALL;            callOper->fun = fun;            callOper->label = _slang_label_new_unique((char*) fun->header.a_name);         }      }   }   if (!inlined)      return NULL;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -