static void print_binary(const slang_operation *op, const char *oper, int indent) { assert(op->num_children == 2); #if 0 printf("binary at %p locals=%p outer=%p\n", (void *) op, (void *) op->locals, (void *) op->locals->outer_scope); #endif slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("%s at %p locals=%p outer=%p\n", oper, (void *) op, (void *) op->locals, (void *) op->locals->outer_scope); slang_print_tree(&op->children[1], indent + 3); }
static void print_variable(const slang_variable *v, int indent) { spaces(indent); printf("VAR "); print_type(&v->type); printf(" %s (at %p)", (char *) v->a_name, (void *) v); if (v->initializer) { printf(" :=\n"); slang_print_tree(v->initializer, indent + 3); } else { printf(";\n"); } }
static void print_generic2(const slang_operation *op, const char *oper, const char *s, int indent) { GLuint i; if (oper) { spaces(indent); printf("%s %s at %p locals=%p outer=%p\n", oper, s, (void *) op, (void *) op->locals, (void *) op->locals->outer_scope); } for (i = 0; i < op->num_children; i++) { spaces(indent); printf("//child %u of %u:\n", i, op->num_children); slang_print_tree(&op->children[i], indent); } }
void slang_print_function(const slang_function *f, GLboolean body) { GLuint i; #if 0 if (_mesa_strcmp((char *) f->header.a_name, "main") != 0) return; #endif printf("FUNCTION %s ( scope=%p\n", (char *) f->header.a_name, (void *) f->parameters); for (i = 0; i < f->param_count; i++) { print_variable(f->parameters->variables[i], 3); } printf(") param scope = %p\n", (void *) f->parameters); if (body && f->body) slang_print_tree(f->body, 0); }
void slang_print_tree(const slang_operation *op, int indent) { GLuint i; switch (op->type) { case SLANG_OPER_NONE: spaces(indent); printf("SLANG_OPER_NONE\n"); break; case SLANG_OPER_BLOCK_NO_NEW_SCOPE: spaces(indent); printf("{ locals=%p outer=%p\n", (void*)op->locals, (void*)op->locals->outer_scope); print_generic(op, NULL, indent+3); spaces(indent); printf("}\n"); break; case SLANG_OPER_BLOCK_NEW_SCOPE: spaces(indent); printf("{{ // new scope locals=%p outer=%p: ", (void *) op->locals, (void *) op->locals->outer_scope); for (i = 0; i < op->locals->num_variables; i++) { printf("%s ", (char *) op->locals->variables[i]->a_name); } printf("\n"); print_generic(op, NULL, indent+3); spaces(indent); printf("}}\n"); break; case SLANG_OPER_VARIABLE_DECL: assert(op->num_children == 0 || op->num_children == 1); { slang_variable *v; v = _slang_variable_locate(op->locals, op->a_id, GL_TRUE); if (v) { const slang_variable_scope *scope; spaces(indent); printf("DECL (locals=%p outer=%p) ", (void*)op->locals, (void*) op->locals->outer_scope); print_type(&v->type); printf(" %s (%p)", (char *) op->a_id, (void *) find_var(op->locals, op->a_id)); scope = find_scope(op->locals, op->a_id); printf(" (in scope %p) ", (void *) scope); assert(scope); if (op->num_children == 1) { printf(" :=\n"); slang_print_tree(&op->children[0], indent + 3); } else if (v->initializer) { printf(" := INITIALIZER\n"); slang_print_tree(v->initializer, indent + 3); } else { printf(";\n"); } /* spaces(indent); printf("TYPE: "); print_type(&v->type); spaces(indent); printf("ADDR: %d size: %d\n", v->address, v->size); */ } else { spaces(indent); printf("DECL %s (anonymous variable!!!!)\n", (char *) op->a_id); } } break; case SLANG_OPER_ASM: spaces(indent); printf("ASM: %s at %p locals=%p outer=%p\n", (char *) op->a_id, (void *) op, (void *) op->locals, (void *) op->locals->outer_scope); print_generic(op, "ASM", indent+3); break; case SLANG_OPER_BREAK: spaces(indent); printf("BREAK\n"); break; case SLANG_OPER_CONTINUE: spaces(indent); printf("CONTINUE\n"); break; case SLANG_OPER_DISCARD: spaces(indent); printf("DISCARD\n"); break; case SLANG_OPER_RETURN: spaces(indent); printf("RETURN\n"); if (op->num_children > 0) slang_print_tree(&op->children[0], indent + 3); break; case SLANG_OPER_LABEL: spaces(indent); printf("LABEL %s\n", (char *) op->a_id); break; case SLANG_OPER_EXPRESSION: spaces(indent); printf("EXPR: locals=%p outer=%p\n", (void *) op->locals, (void *) op->locals->outer_scope); /*print_generic(op, "SLANG_OPER_EXPRESSION", indent);*/ slang_print_tree(&op->children[0], indent + 3); break; case SLANG_OPER_IF: spaces(indent); printf("IF\n"); slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("THEN\n"); slang_print_tree(&op->children[1], indent + 3); spaces(indent); printf("ELSE\n"); slang_print_tree(&op->children[2], indent + 3); spaces(indent); printf("ENDIF\n"); break; case SLANG_OPER_WHILE: assert(op->num_children == 2); spaces(indent); printf("WHILE LOOP: locals = %p\n", (void *) op->locals); indent += 3; spaces(indent); printf("WHILE cond:\n"); slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("WHILE body:\n"); slang_print_tree(&op->children[1], indent + 3); indent -= 3; spaces(indent); printf("END WHILE LOOP\n"); break; case SLANG_OPER_DO: spaces(indent); printf("DO LOOP: locals = %p\n", (void *) op->locals); indent += 3; spaces(indent); printf("DO body:\n"); slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("DO cond:\n"); slang_print_tree(&op->children[1], indent + 3); indent -= 3; spaces(indent); printf("END DO LOOP\n"); break; case SLANG_OPER_FOR: spaces(indent); printf("FOR LOOP: locals = %p\n", (void *) op->locals); indent += 3; spaces(indent); printf("FOR init:\n"); slang_print_tree(&op->children[0], indent + 3); spaces(indent); printf("FOR condition:\n"); slang_print_tree(&op->children[1], indent + 3); spaces(indent); printf("FOR step:\n"); slang_print_tree(&op->children[2], indent + 3); spaces(indent); printf("FOR body:\n"); slang_print_tree(&op->children[3], indent + 3); indent -= 3; spaces(indent); printf("ENDFOR\n"); /* print_generic(op, "FOR", indent + 3); */ break; case SLANG_OPER_VOID: spaces(indent); printf("(oper-void)\n"); break; case SLANG_OPER_LITERAL_BOOL: spaces(indent); printf("LITERAL ("); for (i = 0; i < op->literal_size; i++) printf("%s ", op->literal[0] ? "TRUE" : "FALSE"); printf(")\n"); break; case SLANG_OPER_LITERAL_INT: spaces(indent); printf("LITERAL ("); for (i = 0; i < op->literal_size; i++) printf("%d ", (int) op->literal[i]); printf(")\n"); break; case SLANG_OPER_LITERAL_FLOAT: spaces(indent); printf("LITERAL ("); for (i = 0; i < op->literal_size; i++) printf("%f ", op->literal[i]); printf(")\n"); break; case SLANG_OPER_IDENTIFIER: { const slang_variable_scope *scope; spaces(indent); if (op->var && op->var->a_name) { scope = find_scope(op->locals, op->var->a_name); printf("VAR %s (in scope %p)\n", (char *) op->var->a_name, (void *) scope); assert(scope); } else { scope = find_scope(op->locals, op->a_id); printf("VAR' %s (in scope %p) locals=%p outer=%p\n", (char *) op->a_id, (void *) scope, (void *) op->locals, (void *) op->locals->outer_scope); assert(scope); } } break; case SLANG_OPER_SEQUENCE: print_generic(op, "COMMA-SEQ", indent+3); break; case SLANG_OPER_ASSIGN: spaces(indent); printf("ASSIGNMENT locals=%p outer=%p\n", (void *) op->locals, (void *) op->locals->outer_scope); print_binary(op, ":=", indent); break; case SLANG_OPER_ADDASSIGN: spaces(indent); printf("ASSIGN\n"); print_binary(op, "+=", indent); break; case SLANG_OPER_SUBASSIGN: spaces(indent); printf("ASSIGN\n"); print_binary(op, "-=", indent); break; case SLANG_OPER_MULASSIGN: spaces(indent); printf("ASSIGN\n"); print_binary(op, "*=", indent); break; case SLANG_OPER_DIVASSIGN: spaces(indent); printf("ASSIGN\n"); print_binary(op, "/=", indent); break; /*SLANG_OPER_MODASSIGN,*/ /*SLANG_OPER_LSHASSIGN,*/ /*SLANG_OPER_RSHASSIGN,*/ /*SLANG_OPER_ORASSIGN,*/ /*SLANG_OPER_XORASSIGN,*/ /*SLANG_OPER_ANDASSIGN,*/ case SLANG_OPER_SELECT: spaces(indent); printf("SLANG_OPER_SELECT n=%d\n", op->num_children); assert(op->num_children == 3); slang_print_tree(&op->children[0], indent+3); spaces(indent); printf("?\n"); slang_print_tree(&op->children[1], indent+3); spaces(indent); printf(":\n"); slang_print_tree(&op->children[2], indent+3); break; case SLANG_OPER_LOGICALOR: print_binary(op, "||", indent); break; case SLANG_OPER_LOGICALXOR: print_binary(op, "^^", indent); break; case SLANG_OPER_LOGICALAND: print_binary(op, "&&", indent); break; /*SLANG_OPER_BITOR*/ /*SLANG_OPER_BITXOR*/ /*SLANG_OPER_BITAND*/ case SLANG_OPER_EQUAL: print_binary(op, "==", indent); break; case SLANG_OPER_NOTEQUAL: print_binary(op, "!=", indent); break; case SLANG_OPER_LESS: print_binary(op, "<", indent); break; case SLANG_OPER_GREATER: print_binary(op, ">", indent); break; case SLANG_OPER_LESSEQUAL: print_binary(op, "<=", indent); break; case SLANG_OPER_GREATEREQUAL: print_binary(op, ">=", indent); break; /*SLANG_OPER_LSHIFT*/ /*SLANG_OPER_RSHIFT*/ case SLANG_OPER_ADD: print_binary(op, "+", indent); break; case SLANG_OPER_SUBTRACT: print_binary(op, "-", indent); break; case SLANG_OPER_MULTIPLY: print_binary(op, "*", indent); break; case SLANG_OPER_DIVIDE: print_binary(op, "/", indent); break; /*SLANG_OPER_MODULUS*/ case SLANG_OPER_PREINCREMENT: spaces(indent); printf("PRE++\n"); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_PREDECREMENT: spaces(indent); printf("PRE--\n"); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_PLUS: spaces(indent); printf("SLANG_OPER_PLUS\n"); break; case SLANG_OPER_MINUS: spaces(indent); printf("SLANG_OPER_MINUS\n"); break; /*SLANG_OPER_COMPLEMENT*/ case SLANG_OPER_NOT: spaces(indent); printf("NOT\n"); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_SUBSCRIPT: spaces(indent); printf("SLANG_OPER_SUBSCRIPT locals=%p outer=%p\n", (void *) op->locals, (void *) op->locals->outer_scope); print_generic(op, NULL, indent+3); break; case SLANG_OPER_CALL: #if 0 slang_function *fun = _slang_function_locate(A->space.funcs, oper->a_id, oper->children, oper->num_children, &A->space, A->atoms); #endif spaces(indent); printf("CALL %s(\n", (char *) op->a_id); for (i = 0; i < op->num_children; i++) { slang_print_tree(&op->children[i], indent+3); if (i + 1 < op->num_children) { spaces(indent + 3); printf(",\n"); } } spaces(indent); printf(")\n"); break; case SLANG_OPER_METHOD: spaces(indent); printf("METHOD CALL %s.%s\n", (char *) op->a_obj, (char *) op->a_id); break; case SLANG_OPER_FIELD: spaces(indent); printf("FIELD %s of\n", (char*) op->a_id); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_POSTINCREMENT: spaces(indent); printf("POST++\n"); slang_print_tree(&op->children[0], indent+3); break; case SLANG_OPER_POSTDECREMENT: spaces(indent); printf("POST--\n"); slang_print_tree(&op->children[0], indent+3); break; default: printf("unknown op->type %d\n", (int) op->type); } }
/** * Adapt the arguments for a function call to match the parameters of * the given function. * This is for: * 1. converting/casting argument types to match parameters * 2. breaking up vector/matrix types into individual components to * satisfy constructors. */ GLboolean _slang_adapt_call(slang_operation *callOper, const slang_function *fun, const slang_name_space * space, slang_atom_pool * atoms, slang_info_log *log) { const GLboolean haveRetValue = _slang_function_has_return_value(fun); const int numParams = fun->param_count - haveRetValue; int i; int dbg = 0; if (dbg) printf("Adapt %d args to %d parameters\n", callOper->num_children, numParams); /* Only try adapting for constructors */ if (fun->kind != SLANG_FUNC_CONSTRUCTOR) return GL_FALSE; if (callOper->num_children != numParams) { /* number of arguments doesn't match number of parameters */ if (fun->kind == SLANG_FUNC_CONSTRUCTOR) { /* For constructor calls, we can try to unroll vector/matrix args * into individual floats/ints and try to match the function params. */ for (i = 0; i < numParams; i++) { slang_typeinfo argType; GLint argSz, j; /* Get type of arg[i] */ if (!slang_typeinfo_construct(&argType)) return GL_FALSE; if (!_slang_typeof_operation_(&callOper->children[i], space, &argType, atoms, log)) { slang_typeinfo_destruct(&argType); return GL_FALSE; } /* paramSz = _slang_sizeof_type_specifier(¶mVar->type.specifier); assert(paramSz == 1); */ argSz = _slang_sizeof_type_specifier(&argType.spec); if (argSz > 1) { slang_operation origArg; /* break up arg[i] into components */ if (dbg) printf("Break up arg %d from 1 to %d elements\n", i, argSz); slang_operation_construct(&origArg); slang_operation_copy(&origArg, &callOper->children[i]); /* insert argSz-1 new children/args */ for (j = 0; j < argSz - 1; j++) { (void) slang_operation_insert(&callOper->num_children, &callOper->children, i); } /* replace arg[i+j] with subscript/index oper */ for (j = 0; j < argSz; j++) { callOper->children[i + j].type = SLANG_OPER_SUBSCRIPT; callOper->children[i + j].num_children = 2; callOper->children[i + j].children = slang_operation_new(2); slang_operation_copy(&callOper->children[i + j].children[0], &origArg); callOper->children[i + j].children[1].type = SLANG_OPER_LITERAL_INT; callOper->children[i + j].children[1].literal[0] = j; } } } /* for i */ } else { /* non-constructor function: number of args must match number * of function params. */ return GL_FALSE; /* caller will record an error msg */ } } if (callOper->num_children < numParams) { /* still not enough args for all params */ return GL_FALSE; } else if (callOper->num_children > numParams) { /* now too many arguments */ /* XXX this isn't always an error, see spec */ return GL_FALSE; } /* * Second phase, argument casting. * Example: * void foo(int i, bool b) {} * x = foo(3.15, 9); * Gets translated into: * x = foo(int(3.15), bool(9)) */ for (i = 0; i < numParams; i++) { slang_typeinfo argType; slang_variable *paramVar = fun->parameters->variables[i]; /* Get type of arg[i] */ if (!slang_typeinfo_construct(&argType)) return GL_FALSE; if (!_slang_typeof_operation_(&callOper->children[i], space, &argType, atoms, log)) { slang_typeinfo_destruct(&argType); return GL_FALSE; } /* see if arg type matches parameter type */ if (!slang_type_specifier_equal(&argType.spec, ¶mVar->type.specifier)) { /* need to adapt arg type to match param type */ const char *constructorName = slang_type_specifier_type_to_string(paramVar->type.specifier.type); slang_operation *child = slang_operation_new(1); slang_operation_copy(child, &callOper->children[i]); child->locals->outer_scope = callOper->children[i].locals; callOper->children[i].type = SLANG_OPER_CALL; callOper->children[i].a_id = slang_atom_pool_atom(atoms, constructorName); callOper->children[i].num_children = 1; callOper->children[i].children = child; } slang_typeinfo_destruct(&argType); } if (dbg) { printf("===== New call to %s with adapted arguments ===============\n", (char*) fun->header.a_name); slang_print_tree(callOper, 5); } return GL_TRUE; }