From afbf7c7e6b7613d8d219807adaf7d17971ac2e6d Mon Sep 17 00:00:00 2001 From: Brian Date: Fri, 23 Feb 2007 09:38:17 -0700 Subject: [PATCH] Re-implement branching with slang_labels. This eliminates the NOP instructions that had been used as placeholders for branch targets. Also, fix "return" statement bug. --- src/mesa/shader/slang/slang_codegen.c | 79 +++++++++++++------------ src/mesa/shader/slang/slang_compile_function.h | 11 ++-- src/mesa/shader/slang/slang_compile_operation.h | 9 +-- src/mesa/shader/slang/slang_emit.c | 54 +++++++++-------- src/mesa/shader/slang/slang_ir.h | 4 +- src/mesa/shader/slang/slang_link.c | 42 ------------- 6 files changed, 76 insertions(+), 123 deletions(-) diff --git a/src/mesa/shader/slang/slang_codegen.c b/src/mesa/shader/slang/slang_codegen.c index 51c8f27..3d9b236 100644 --- a/src/mesa/shader/slang/slang_codegen.c +++ b/src/mesa/shader/slang/slang_codegen.c @@ -39,6 +39,7 @@ #include "slang_codegen.h" #include "slang_compile.h" #include "slang_error.h" +#include "slang_label.h" #include "slang_simplify.h" #include "slang_emit.h" #include "slang_vartable.h" @@ -425,10 +426,11 @@ new_seq(slang_ir_node *left, slang_ir_node *right) } static slang_ir_node * -new_label(slang_atom labName) +new_label(slang_label *label) { slang_ir_node *n = new_node0(IR_LABEL); - n->Target = (char *) labName; /*_mesa_strdup(name);*/ + if (n) + n->Label = label; return n; } @@ -450,11 +452,11 @@ new_float_literal(const float v[4]) * XXX maybe pass an IR node as second param to indicate the jump target??? */ static slang_ir_node * -new_cjump(slang_atom target, GLuint zeroOrOne) +new_cjump(slang_label *dest, GLuint zeroOrOne) { slang_ir_node *n = new_node0(zeroOrOne ? IR_CJUMP1 : IR_CJUMP0); if (n) - n->Target = (char *) target; + n->Label = dest; return n; } @@ -463,11 +465,11 @@ new_cjump(slang_atom target, GLuint zeroOrOne) * XXX maybe pass an IR node as second param to indicate the jump target??? */ static slang_ir_node * -new_jump(slang_atom target) +new_jump(slang_label *dest) { slang_ir_node *n = new_node0(IR_JUMP); if (n) - n->Target = (char *) target; + n->Label = dest; return n; } @@ -599,6 +601,18 @@ slang_is_asm_function(const slang_function *fun) } +static GLboolean +_slang_is_noop(const slang_operation *oper) +{ + if (!oper || + oper->type == SLANG_OPER_VOID || + (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID)) + return GL_TRUE; + else + return GL_FALSE; +} + + /** * Produce inline code for a call to an assembly instruction. */ @@ -709,11 +723,11 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, } } break; -#if 1 /* XXX rely on default case below */ + case SLANG_OPER_RETURN: /* do return replacement here too */ assert(oper->num_children == 0 || oper->num_children == 1); - if (oper->num_children == 1) { + if (!_slang_is_noop(oper)) { /* replace: * return expr; * with: @@ -751,7 +765,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper, slang_operation_destruct(blockOper); } break; -#endif + case SLANG_OPER_ASSIGN: case SLANG_OPER_SUBSCRIPT: /* special case: @@ -992,8 +1006,7 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun, &inlined->children, inlined->num_children); lab->type = SLANG_OPER_LABEL; - lab->a_id = slang_atom_pool_atom(A->atoms, - (char *) A->CurFunction->end_label); + lab->label = A->CurFunction->end_label; } for (i = 0; i < totalArgs; i++) { @@ -1044,7 +1057,7 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun, if (!A->CurFunction->end_label) { char name[200]; sprintf(name, "__endOfFunc_%s_", (char *) A->CurFunction->header.a_name); - A->CurFunction->end_label = slang_atom_pool_gen(A->atoms, name); + A->CurFunction->end_label = _slang_label_new(name); } if (slang_is_asm_function(fun) && !dest) { @@ -1075,7 +1088,7 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun, n = _slang_gen_operation(A, oper); - A->CurFunction->end_label = NULL; + A->CurFunction->end_label = NULL; /* XXX delete/free? */ A->CurFunction = prevFunc; @@ -1198,19 +1211,6 @@ _slang_gen_asm(slang_assemble_ctx *A, slang_operation *oper, } - -static GLboolean -_slang_is_noop(const slang_operation *oper) -{ - if (!oper || - oper->type == SLANG_OPER_VOID || - (oper->num_children == 1 && oper->children[0].type == SLANG_OPER_VOID)) - return GL_TRUE; - else - return GL_FALSE; -} - - static void print_funcs(struct slang_function_scope_ *scope, const char *name) { @@ -1617,8 +1617,7 @@ _slang_gen_var_decl(slang_assemble_ctx *A, slang_variable *var) static slang_ir_node * _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) { - slang_atom altAtom = slang_atom_pool_gen(A->atoms, "__selectAlt"); - slang_atom endAtom = slang_atom_pool_gen(A->atoms, "__selectEnd"); + slang_label *altLabel, *endLabel; slang_ir_node *altLab, *endLab; slang_ir_node *tree, *tmpDecl, *tmpVar, *cond, *cjump, *jump; slang_ir_node *bodx, *body, *assignx, *assigny; @@ -1628,6 +1627,9 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) assert(oper->type == SLANG_OPER_SELECT); assert(oper->num_children == 3); + altLabel = _slang_label_new("selectAlt"); + endLabel = _slang_label_new("selectEnd"); + /* size of x or y's type */ slang_typeinfo_construct(&type); _slang_typeof_operation(A, &oper->children[1], &type); @@ -1643,7 +1645,7 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) tree = new_seq(tmpDecl, cond); /* jump if false to "alt" label */ - cjump = new_cjump(altAtom, 0); + cjump = new_cjump(altLabel, 0); tree = new_seq(tree, cjump); /* evaluate child 1 (x) and assign to tmp */ @@ -1654,11 +1656,11 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) tree = new_seq(tree, assigny); /* jump to "end" label */ - jump = new_jump(endAtom); + jump = new_jump(endLabel); tree = new_seq(tree, jump); /* "alt" label */ - altLab = new_label(altAtom); + altLab = new_label(altLabel); tree = new_seq(tree, altLab); /* evaluate child 2 (y) and assign to tmp */ @@ -1669,7 +1671,7 @@ _slang_gen_select(slang_assemble_ctx *A, slang_operation *oper) tree = new_seq(tree, assignx); /* "end" label */ - endLab = new_label(endAtom); + endLab = new_label(endLabel); tree = new_seq(tree, endLab); /* tmp var value */ @@ -1762,8 +1764,8 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) slang_operation_construct(&gotoOp); gotoOp.type = SLANG_OPER_GOTO; /* XXX don't call function? */ - gotoOp.a_id = slang_atom_pool_atom(A->atoms, - (char *) A->CurFunction->end_label); + gotoOp.label = A->CurFunction->end_label; + /* assemble the new code */ n = _slang_gen_operation(A, &gotoOp); /* destroy temp code */ @@ -1819,8 +1821,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper) jump->type = SLANG_OPER_GOTO; assert(A->CurFunction->end_label); /* XXX don't call function? */ - jump->a_id = slang_atom_pool_atom(A->atoms, - (char *) A->CurFunction->end_label); + jump->label = A->CurFunction->end_label; #if 0 /* debug */ printf("NEW RETURN:\n"); @@ -2439,9 +2440,9 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper) case SLANG_OPER_RETURN: return _slang_gen_return(A, oper); case SLANG_OPER_GOTO: - return new_jump((char*) oper->a_id); + return new_jump(oper->label); case SLANG_OPER_LABEL: - return new_label((char*) oper->a_id); + return new_label(oper->label); case SLANG_OPER_IDENTIFIER: return _slang_gen_variable(A, oper); case SLANG_OPER_IF: @@ -2716,7 +2717,7 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun) /* Create an end-of-function label */ if (!A->CurFunction->end_label) - A->CurFunction->end_label = slang_atom_pool_gen(A->atoms, "__endOfFunc_main_"); + A->CurFunction->end_label = _slang_label_new("__endOfFunc__main"); /* push new vartable scope */ _slang_push_var_table(A->vartable); diff --git a/src/mesa/shader/slang/slang_compile_function.h b/src/mesa/shader/slang/slang_compile_function.h index b60b4a2..09fbfd9 100644 --- a/src/mesa/shader/slang/slang_compile_function.h +++ b/src/mesa/shader/slang/slang_compile_function.h @@ -25,9 +25,6 @@ #ifndef SLANG_COMPILE_FUNCTION_H #define SLANG_COMPILE_FUNCTION_H -#if defined __cplusplus -extern "C" { -#endif struct slang_code_unit_; @@ -69,7 +66,11 @@ typedef struct slang_function_ slang_operation *body; /**< The instruction tree */ unsigned int address; /**< Address of this func in memory */ slang_fixup_table fixups; /**< Mem locations which need func's address */ +#if 0 slang_atom end_label; /**< The end-of-function label */ +#else + struct slang_label_ *end_label; +#endif } slang_function; extern int slang_function_construct(slang_function *); @@ -102,8 +103,4 @@ slang_function_scope_find_by_name(slang_function_scope *, slang_atom, int); extern slang_function * slang_function_scope_find(slang_function_scope *, slang_function *, int); -#ifdef __cplusplus -} -#endif - #endif /* SLANG_COMPILE_FUNCTION_H */ diff --git a/src/mesa/shader/slang/slang_compile_operation.h b/src/mesa/shader/slang/slang_compile_operation.h index a59f968..4adcd2a 100644 --- a/src/mesa/shader/slang/slang_compile_operation.h +++ b/src/mesa/shader/slang/slang_compile_operation.h @@ -25,10 +25,6 @@ #ifndef SLANG_COMPILE_OPERATION_H #define SLANG_COMPILE_OPERATION_H -#if defined __cplusplus -extern "C" { -#endif - /** * Types of slang operations. @@ -122,6 +118,7 @@ typedef struct slang_operation_ slang_variable_scope *locals; /**< local vars for scope */ struct slang_function_ *fun; /**< If type == SLANG_OPER_CALL */ struct slang_variable_ *var; /**< If type == slang_oper_identier */ + struct slang_label_ *label; /**< If type == SLANG_OPER_LABEL or GOTO */ } slang_operation; @@ -148,8 +145,4 @@ slang_operation_insert(GLuint *numChildren, slang_operation **children, GLuint pos); -#ifdef __cplusplus -} -#endif - #endif /* SLANG_COMPILE_OPERATION_H */ diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index 76b0375..6b950de 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -278,7 +278,7 @@ slang_print_ir(const slang_ir_node *n, int indent) slang_print_ir(n->Children[1], indent+3); break; case IR_LABEL: - printf("LABEL: %s\n", n->Target); + printf("LABEL: %s\n", n->Label->Name); break; case IR_COND: printf("COND\n"); @@ -848,38 +848,44 @@ emit_negation(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) static struct prog_instruction * -emit_label(const char *target, struct gl_program *prog) +emit_label(const slang_ir_node *n, struct gl_program *prog) { - struct prog_instruction *inst; - inst = new_instruction(prog, OPCODE_NOP); - inst->Comment = _mesa_strdup(target); - return inst; + assert(n->Label); + assert(_slang_label_get_location(n->Label) < 0); + _slang_label_set_location(n->Label, prog->NumInstructions, prog); + return NULL; } static struct prog_instruction * -emit_cjump(const char *target, struct gl_program *prog, GLuint zeroOrOne) +emit_cjump(slang_ir_node *n, struct gl_program *prog, GLuint zeroOrOne) { struct prog_instruction *inst; + assert(n->Opcode == IR_CJUMP0 || n->Opcode == IR_CJUMP1); inst = new_instruction(prog, OPCODE_BRA); if (zeroOrOne) inst->DstReg.CondMask = COND_NE; /* branch if non-zero */ else inst->DstReg.CondMask = COND_EQ; /* branch if equal to zero */ inst->DstReg.CondSwizzle = SWIZZLE_X; - inst->Comment = _mesa_strdup(target); + inst->BranchTarget = _slang_label_get_location(n->Label); + if (inst->BranchTarget < 0) { + _slang_label_add_reference(n->Label, prog->NumInstructions - 1); + } return inst; } static struct prog_instruction * -emit_jump(const char *target, struct gl_program *prog) +emit_jump(slang_ir_node *n, struct gl_program *prog) { struct prog_instruction *inst; inst = new_instruction(prog, OPCODE_BRA); inst->DstReg.CondMask = COND_TR; /* always branch */ - /*inst->DstReg.CondSwizzle = SWIZZLE_X;*/ - inst->Comment = _mesa_strdup(target); + inst->BranchTarget = _slang_label_get_location(n->Label); + if (inst->BranchTarget < 0) { + _slang_label_add_reference(n->Label, prog->NumInstructions - 1); + } return inst; } @@ -1522,13 +1528,13 @@ emit(slang_var_table *vt, slang_ir_node *n, struct gl_program *prog) return emit_not(vt, n, prog); case IR_LABEL: - return emit_label(n->Target, prog); + return emit_label(n, prog); case IR_JUMP: - return emit_jump(n->Target, prog); + return emit_jump(n, prog); case IR_CJUMP0: - return emit_cjump(n->Target, prog, 0); + return emit_cjump(n, prog, 0); case IR_CJUMP1: - return emit_cjump(n->Target, prog, 1); + return emit_cjump(n, prog, 1); case IR_KILL: return emit_kill(prog); @@ -1572,18 +1578,14 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt, { GLboolean success; - if (emit(vt, n, prog)) { - /* finish up by adding the END opcode to program */ - if (withEnd) { - struct prog_instruction *inst; - inst = new_instruction(prog, OPCODE_END); - } - success = GL_TRUE; - } - else { - /* record an error? */ - success = GL_FALSE; + (void) emit(vt, n, prog); + + /* finish up by adding the END opcode to program */ + if (withEnd) { + struct prog_instruction *inst; + inst = new_instruction(prog, OPCODE_END); } + success = GL_TRUE; printf("*********** End generate code (%u inst):\n", prog->NumInstructions); #if 0 diff --git a/src/mesa/shader/slang/slang_ir.h b/src/mesa/shader/slang/slang_ir.h index 0c827d9..ba8b613 100644 --- a/src/mesa/shader/slang/slang_ir.h +++ b/src/mesa/shader/slang/slang_ir.h @@ -35,6 +35,7 @@ #include "imports.h" #include "slang_compile.h" +#include "slang_label.h" #include "mtypes.h" @@ -153,7 +154,8 @@ typedef struct slang_ir_node_ slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */ slang_ir_storage *Store; /**< location of result of this operation */ GLint InstLocation; /**< Location of instruction emitted for this node */ - struct slang_ir_node_ *BranchNode; /**< Used for branch instructions */ + struct slang_ir_node_ *BranchNode; /**< Used for branching instructions */ + slang_label *Label; /**< Used for branches */ } slang_ir_node; diff --git a/src/mesa/shader/slang/slang_link.c b/src/mesa/shader/slang/slang_link.c index 23977b7..e2bb6ee 100644 --- a/src/mesa/shader/slang/slang_link.c +++ b/src/mesa/shader/slang/slang_link.c @@ -274,46 +274,6 @@ link_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog) /** - * XXX Temporary - */ -static void -_slang_resolve_branches(struct gl_program *prog) -{ - struct target { - const char *Name; - GLuint Pos; - }; - struct target targets[500]; - GLuint numTargets = 0; - GLuint i, j; - - for (i = 0; i < prog->NumInstructions; i++) { - struct prog_instruction *inst = prog->Instructions + i; - if (inst->Opcode == OPCODE_NOP && inst->Comment) { - targets[numTargets].Name = inst->Comment; - targets[numTargets].Pos = i; - numTargets++; - } - } - - for (i = 0; i < prog->NumInstructions; i++) { - struct prog_instruction *inst = prog->Instructions + i; - if (inst->Opcode == OPCODE_BRA && inst->BranchTarget < 0) { - for (j = 0; j < numTargets; j++) { - if (!strcmp(inst->Comment, targets[j].Name)) { - inst->BranchTarget = targets[j].Pos; - break; - } - } - if (j == numTargets) { - abort(); - } - } - } -} - - -/** * Resolve binding of generic vertex attributes. * For example, if the vertex shader declared "attribute vec4 foobar" we'll * allocate a generic vertex attribute for "foobar" and plug that value into @@ -574,11 +534,9 @@ _slang_link(GLcontext *ctx, } if (shProg->VertexProgram) { - _slang_resolve_branches(&shProg->VertexProgram->Base); _slang_resolve_samplers(shProg, &shProg->VertexProgram->Base); } if (shProg->FragmentProgram) { - _slang_resolve_branches(&shProg->FragmentProgram->Base); _slang_resolve_samplers(shProg, &shProg->FragmentProgram->Base); } -- 2.7.4