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

📄 slang_codegen.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 5 页
字号:
   /* 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 + -