X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fmesa%2Fshader%2Fslang%2Fslang_emit.c;h=c9ecbd275b8bf6d9da8a37747c2dec4185952d90;hp=ea446fa5d49bc689025abcc74778c33a62e10e10;hb=cd8614b0287dc5a69725ec4ee0208fad61f7789e;hpb=2e28c1fda24988241ef7abb91b7d896e38f5df26 diff --git a/src/mesa/shader/slang/slang_emit.c b/src/mesa/shader/slang/slang_emit.c index ea446fa5d49..c9ecbd275b8 100644 --- a/src/mesa/shader/slang/slang_emit.c +++ b/src/mesa/shader/slang/slang_emit.c @@ -38,7 +38,6 @@ #include "main/imports.h" #include "main/context.h" -#include "main/macros.h" #include "shader/program.h" #include "shader/prog_instruction.h" #include "shader/prog_parameter.h" @@ -62,6 +61,8 @@ typedef struct GLuint MaxInstructions; /**< size of prog->Instructions[] buffer */ + GLboolean UnresolvedFunctions; + /* code-gen options */ GLboolean EmitHighLevelInstructions; GLboolean EmitCondCodes; @@ -79,8 +80,8 @@ new_subroutine(slang_emit_info *emitInfo, GLuint *id) emitInfo->Subroutines = (struct gl_program **) _mesa_realloc(emitInfo->Subroutines, - n * sizeof(struct gl_program), - (n + 1) * sizeof(struct gl_program)); + n * sizeof(struct gl_program *), + (n + 1) * sizeof(struct gl_program *)); emitInfo->Subroutines[n] = ctx->Driver.NewProgram(ctx, emitInfo->prog->Target, 0); emitInfo->Subroutines[n]->Parameters = emitInfo->prog->Parameters; emitInfo->NumSubroutines++; @@ -164,7 +165,7 @@ _slang_var_swizzle(GLint size, GLint comp) { switch (size) { case 1: - return MAKE_SWIZZLE4(comp, comp, comp, comp); + return MAKE_SWIZZLE4(comp, SWIZZLE_NIL, SWIZZLE_NIL, SWIZZLE_NIL); case 2: return MAKE_SWIZZLE4(SWIZZLE_X, SWIZZLE_Y, SWIZZLE_NIL, SWIZZLE_NIL); case 3: @@ -193,6 +194,9 @@ alloc_node_storage(slang_emit_info *emitInfo, slang_ir_node *n, if (!n->Store) { assert(defaultSize > 0); n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, defaultSize); + if (!n->Store) { + return GL_FALSE; + } } /* now allocate actual register(s). I.e. set n->Store->Index >= 0 */ @@ -429,6 +433,9 @@ new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode) _mesa_realloc_instructions(prog->Instructions, prog->NumInstructions, emitInfo->MaxInstructions); + if (!prog->Instructions) { + return NULL; + } } inst = prog->Instructions + prog->NumInstructions; @@ -446,15 +453,17 @@ new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode) static struct prog_instruction * emit_arl_load(slang_emit_info *emitInfo, - enum register_file file, GLint index, GLuint swizzle) + gl_register_file file, GLint index, GLuint swizzle) { struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ARL); - inst->SrcReg[0].File = file; - inst->SrcReg[0].Index = index; - inst->SrcReg[0].Swizzle = swizzle; - inst->DstReg.File = PROGRAM_ADDRESS; - inst->DstReg.Index = 0; - inst->DstReg.WriteMask = WRITEMASK_X; + if (inst) { + inst->SrcReg[0].File = file; + inst->SrcReg[0].Index = index; + inst->SrcReg[0].Swizzle = fix_swizzle(swizzle); + inst->DstReg.File = PROGRAM_ADDRESS; + inst->DstReg.Index = 0; + inst->DstReg.WriteMask = WRITEMASK_X; + } return inst; } @@ -541,6 +550,9 @@ emit_instruction(slang_emit_info *emitInfo, &srcRelAddr, NULL, NULL); + if (!inst) { + return NULL; + } src[i] = &newSrc[i]; } @@ -763,7 +775,9 @@ static struct prog_instruction * emit_comment(slang_emit_info *emitInfo, const char *comment) { struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP); - inst_comment(inst, comment); + if (inst) { + inst_comment(inst, comment); + } return inst; } @@ -790,7 +804,9 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n) emit(emitInfo, n->Children[0]->Children[0]); /* A */ emit(emitInfo, n->Children[0]->Children[1]); /* B */ emit(emitInfo, n->Children[1]); /* C */ - alloc_node_storage(emitInfo, n, -1); /* dest */ + if (!alloc_node_storage(emitInfo, n, -1)) { /* dest */ + return NULL; + } inst = emit_instruction(emitInfo, OPCODE_MAD, @@ -811,7 +827,9 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n) emit(emitInfo, n->Children[0]); /* A */ emit(emitInfo, n->Children[1]->Children[0]); /* B */ emit(emitInfo, n->Children[1]->Children[1]); /* C */ - alloc_node_storage(emitInfo, n, -1); /* dest */ + if (!alloc_node_storage(emitInfo, n, -1)) { /* dest */ + return NULL; + } inst = emit_instruction(emitInfo, OPCODE_MAD, @@ -837,7 +855,9 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n) } /* result storage */ - alloc_node_storage(emitInfo, n, -1); + if (!alloc_node_storage(emitInfo, n, -1)) { + return NULL; + } inst = emit_instruction(emitInfo, info->InstOpcode, @@ -872,7 +892,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) emit(emitInfo, n->Children[1]); if (n->Children[0]->Store->Size != n->Children[1]->Store->Size) { + /* XXX this error should have been caught in slang_codegen.c */ slang_info_log_error(emitInfo->log, "invalid operands to == or !="); + n->Store = NULL; return NULL; } @@ -902,6 +924,7 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) slang_ir_storage tempStore; if (!alloc_local_temp(emitInfo, &tempStore, 4)) { + n->Store = NULL; return NULL; /* out of temps */ } @@ -927,6 +950,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[0]->Store, n->Children[1]->Store, NULL); + if (!inst) { + return NULL; + } inst_comment(inst, "Compare values"); /* Compute val = DOT(temp, temp) (reduction) */ @@ -936,6 +962,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) &tempStore, &tempStore, NULL); + if (!inst) { + return NULL; + } inst->SrcReg[0].Swizzle = inst->SrcReg[1].Swizzle = swizzle; /*override*/ inst_comment(inst, "Reduce vec to bool"); @@ -951,6 +980,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) n->Store, &zero, NULL); + if (!inst) { + return NULL; + } inst_comment(inst, "Invert true/false"); } } @@ -980,6 +1012,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) &srcStore0, &srcStore1, NULL); + if (!inst) { + return NULL; + } inst_comment(inst, "Begin struct/array comparison"); } else { @@ -989,12 +1024,18 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) &srcStore0, &srcStore1, NULL); + if (!inst) { + return NULL; + } /* ADD accTemp, accTemp, sneTemp; # like logical-OR */ inst = emit_instruction(emitInfo, OPCODE_ADD, &accTemp, /* dest */ &accTemp, &sneTemp, NULL); + if (!inst) { + return NULL; + } } } @@ -1004,6 +1045,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) &accTemp, &accTemp, NULL); + if (!inst) { + return NULL; + } inst_comment(inst, "End struct/array comparison"); if (n->Opcode == IR_EQUAL) { @@ -1015,6 +1059,9 @@ emit_compare(slang_emit_info *emitInfo, slang_ir_node *n) n->Store, &zero, NULL); + if (!inst) { + return NULL; + } inst_comment(inst, "Invert true/false"); } @@ -1088,7 +1135,9 @@ emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n) * the intermediate result. Use a temp register instead. */ _mesa_bzero(&tmpNode, sizeof(tmpNode)); - alloc_node_storage(emitInfo, &tmpNode, n->Store->Size); + if (!alloc_node_storage(emitInfo, &tmpNode, n->Store->Size)) { + return NULL; + } /* tmp = max(ch[0], ch[1]) */ inst = emit_instruction(emitInfo, OPCODE_MAX, @@ -1096,6 +1145,9 @@ emit_clamp(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[0]->Store, n->Children[1]->Store, NULL); + if (!inst) { + return NULL; + } /* n->dest = min(tmp, ch[2]) */ inst = emit_instruction(emitInfo, OPCODE_MIN, @@ -1130,7 +1182,9 @@ emit_negation(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[0]->Store, NULL, NULL); - inst->SrcReg[0].NegateBase = NEGATE_XYZW; + if (inst) { + inst->SrcReg[0].Negate = NEGATE_XYZW; + } return inst; } @@ -1186,6 +1240,9 @@ emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n) * really just a NOP to attach the label to. */ inst = new_instruction(emitInfo, OPCODE_BGNSUB); + if (!inst) { + return NULL; + } inst_comment(inst, n->Label->Name); } @@ -1197,10 +1254,16 @@ emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n) inst = prev_instruction(emitInfo); if (inst && inst->Opcode != OPCODE_RET) { inst = new_instruction(emitInfo, OPCODE_RET); + if (!inst) { + return NULL; + } } if (emitInfo->EmitBeginEndSub) { inst = new_instruction(emitInfo, OPCODE_ENDSUB); + if (!inst) { + return NULL; + } inst_comment(inst, n->Label->Name); } @@ -1210,6 +1273,9 @@ emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n) /* emit the function call */ inst = new_instruction(emitInfo, OPCODE_CAL); + if (!inst) { + return NULL; + } /* The branch target is just the subroutine number (changed later) */ inst->BranchTarget = subroutineId; inst_comment(inst, n->Label->Name); @@ -1230,7 +1296,9 @@ emit_return(slang_emit_info *emitInfo, slang_ir_node *n) assert(n->Opcode == IR_RETURN); assert(n->Label); inst = new_instruction(emitInfo, OPCODE_RET); - inst->DstReg.CondMask = COND_TR; /* always return */ + if (inst) { + inst->DstReg.CondMask = COND_TR; /* always return */ + } return inst; } @@ -1244,6 +1312,9 @@ emit_kill(slang_emit_info *emitInfo) * Note that ARB-KILL depends on sign of vector operand. */ inst = new_instruction(emitInfo, OPCODE_KIL_NV); + if (!inst) { + return NULL; + } inst->DstReg.CondMask = COND_TR; /* always kill */ assert(emitInfo->prog->Target == GL_FRAGMENT_PROGRAM_ARB); @@ -1259,16 +1330,33 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) { struct prog_instruction *inst; gl_inst_opcode opcode; + GLboolean shadow = GL_FALSE; - if (n->Opcode == IR_TEX) { + switch (n->Opcode) { + case IR_TEX: opcode = OPCODE_TEX; - } - else if (n->Opcode == IR_TEXB) { + break; + case IR_TEX_SH: + opcode = OPCODE_TEX; + shadow = GL_TRUE; + break; + case IR_TEXB: opcode = OPCODE_TXB; - } - else { - assert(n->Opcode == IR_TEXP); + break; + case IR_TEXB_SH: + opcode = OPCODE_TXB; + shadow = GL_TRUE; + break; + case IR_TEXP: + opcode = OPCODE_TXP; + break; + case IR_TEXP_SH: opcode = OPCODE_TXP; + shadow = GL_TRUE; + break; + default: + _mesa_problem(NULL, "Bad IR TEX code"); + return NULL; } if (n->Children[0]->Opcode == IR_ELEMENT) { @@ -1299,6 +1387,11 @@ emit_tex(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[1]->Store, NULL, NULL); + if (!inst) { + return NULL; + } + + inst->TexShadow = shadow; /* Store->Index is the uniform/sampler index */ assert(n->Children[0]->Store->Index >= 0); @@ -1335,7 +1428,8 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) inst = emit(emitInfo, n->Children[1]); if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) { - if (!emitInfo->log->text) { + if (!emitInfo->log->text && !emitInfo->UnresolvedFunctions) { + /* XXX this error should have been caught in slang_codegen.c */ slang_info_log_error(emitInfo->log, "invalid assignment"); } return NULL; @@ -1358,6 +1452,7 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) #if PEEPHOLE_OPTIMIZATIONS if (inst && + (n->Children[1]->Opcode != IR_SWIZZLE) && _slang_is_temp(emitInfo->vt, n->Children[1]->Store) && (inst->DstReg.File == n->Children[1]->Store->File) && (inst->DstReg.Index == n->Children[1]->Store->Index) && @@ -1374,13 +1469,9 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) * becomes: * MUL a, x, y; */ - if (n->Children[1]->Opcode != IR_SWIZZLE) - _slang_free_temp(emitInfo->vt, n->Children[1]->Store); - *n->Children[1]->Store = *n->Children[0]->Store; /* fixup the previous instruction (which stored the RHS result) */ assert(n->Children[0]->Store->Index >= 0); - storage_to_dst_reg(&inst->DstReg, n->Children[0]->Store); return inst; } @@ -1401,6 +1492,9 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) &srcStore, NULL, NULL); + if (!inst) { + return NULL; + } inst_comment(inst, "IR_COPY block"); srcStore.Index++; dstStore.Index++; @@ -1416,6 +1510,9 @@ emit_copy(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[1]->Store, NULL, NULL); + if (!inst) { + return NULL; + } dstAnnot = storage_annotation(n->Children[0], emitInfo->prog); srcAnnot = storage_annotation(n->Children[1], emitInfo->prog); inst->Comment = instruction_annotation(inst->Opcode, dstAnnot, @@ -1477,6 +1574,9 @@ emit_cond(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[0]->Store, NULL, NULL); + if (!inst) { + return NULL; + } inst->CondUpdate = GL_TRUE; inst_comment(inst, "COND expr"); _slang_free_temp(emitInfo->vt, n->Store); @@ -1539,6 +1639,9 @@ emit_not(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[0]->Store, &zero, NULL); + if (!inst) { + return NULL; + } inst_comment(inst, "NOT"); free_node_storage(emitInfo->vt, n->Children[0]); @@ -1578,8 +1681,10 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n) if (emitInfo->EmitHighLevelInstructions) { if (emitInfo->EmitCondCodes) { /* IF condcode THEN ... */ - struct prog_instruction *ifInst; - ifInst = new_instruction(emitInfo, OPCODE_IF); + struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_IF); + if (!ifInst) { + return NULL; + } ifInst->DstReg.CondMask = COND_NE; /* if cond is non-zero */ /* only test the cond code (1 of 4) that was updated by the * previous instruction. @@ -1587,17 +1692,25 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n) ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); } else { + struct prog_instruction *inst; + /* IF src[0] THEN ... */ - emit_instruction(emitInfo, OPCODE_IF, - NULL, /* dst */ - n->Children[0]->Store, /* op0 */ - NULL, - NULL); + inst = emit_instruction(emitInfo, OPCODE_IF, + NULL, /* dst */ + n->Children[0]->Store, /* op0 */ + NULL, + NULL); + if (!inst) { + return NULL; + } } } else { /* conditional jump to else, or endif */ struct prog_instruction *ifInst = new_instruction(emitInfo, OPCODE_BRA); + if (!ifInst) { + return NULL; + } ifInst->DstReg.CondMask = COND_EQ; /* BRA if cond is zero */ inst_comment(ifInst, "if zero"); ifInst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); @@ -1610,16 +1723,22 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n) /* have else body */ elseInstLoc = prog->NumInstructions; if (emitInfo->EmitHighLevelInstructions) { - (void) new_instruction(emitInfo, OPCODE_ELSE); + struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ELSE); + if (!inst) { + return NULL; + } + prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions - 1; } else { /* jump to endif instruction */ - struct prog_instruction *inst; - inst = new_instruction(emitInfo, OPCODE_BRA); + struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BRA); + if (!inst) { + return NULL; + } inst_comment(inst, "else"); inst->DstReg.CondMask = COND_TR; /* always branch */ + prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions; } - prog->Instructions[ifInstLoc].BranchTarget = prog->NumInstructions; emit(emitInfo, n->Children[2]); } else { @@ -1628,11 +1747,20 @@ emit_if(slang_emit_info *emitInfo, slang_ir_node *n) } if (emitInfo->EmitHighLevelInstructions) { - (void) new_instruction(emitInfo, OPCODE_ENDIF); + struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_ENDIF); + if (!inst) { + return NULL; + } } - if (n->Children[2]) { - prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions; + if (elseInstLoc) { + /* point ELSE instruction BranchTarget at ENDIF */ + if (emitInfo->EmitHighLevelInstructions) { + prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions - 1; + } + else { + prog->Instructions[elseInstLoc].BranchTarget = prog->NumInstructions; + } } return NULL; } @@ -1649,7 +1777,10 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n) /* emit OPCODE_BGNLOOP */ beginInstLoc = prog->NumInstructions; if (emitInfo->EmitHighLevelInstructions) { - (void) new_instruction(emitInfo, OPCODE_BGNLOOP); + struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_BGNLOOP); + if (!inst) { + return NULL; + } } /* body */ @@ -1667,10 +1798,16 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n) if (emitInfo->EmitHighLevelInstructions) { /* emit OPCODE_ENDLOOP */ endInst = new_instruction(emitInfo, OPCODE_ENDLOOP); + if (!endInst) { + return NULL; + } } else { /* emit unconditional BRA-nch */ endInst = new_instruction(emitInfo, OPCODE_BRA); + if (!endInst) { + return NULL; + } endInst->DstReg.CondMask = COND_TR; /* always true */ } /* ENDLOOP's BranchTarget points to the BGNLOOP inst */ @@ -1683,7 +1820,7 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n) /* Done emitting loop code. Now walk over the loop's linked list of * BREAK and CONT nodes, filling in their BranchTarget fields (which - * will point to the ENDLOOP+1 or BGNLOOP instructions, respectively). + * will point to the corresponding ENDLOOP instruction. */ for (ir = n->List; ir; ir = ir->List) { struct prog_instruction *inst = prog->Instructions + ir->InstLocation; @@ -1692,8 +1829,13 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n) ir->Opcode == IR_BREAK_IF_TRUE) { assert(inst->Opcode == OPCODE_BRK || inst->Opcode == OPCODE_BRA); - /* go to instruction after end of loop */ - inst->BranchTarget = endInstLoc + 1; + /* go to instruction at end of loop */ + if (emitInfo->EmitHighLevelInstructions) { + inst->BranchTarget = endInstLoc; + } + else { + inst->BranchTarget = endInstLoc + 1; + } } else { assert(ir->Opcode == IR_CONT || @@ -1740,7 +1882,9 @@ emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n) } n->InstLocation = emitInfo->prog->NumInstructions; inst = new_instruction(emitInfo, opcode); - inst->DstReg.CondMask = COND_TR; /* always true */ + if (inst) { + inst->DstReg.CondMask = COND_TR; /* always true */ + } return inst; } @@ -1776,8 +1920,10 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n) */ const GLuint condWritemask = inst->DstReg.WriteMask; inst = new_instruction(emitInfo, opcode); - inst->DstReg.CondMask = COND_NE; - inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); + if (inst) { + inst->DstReg.CondMask = COND_NE; + inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); + } return inst; } else { @@ -1792,13 +1938,22 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n) n->Children[0]->Store, NULL, NULL); + if (!inst) { + return NULL; + } n->InstLocation = emitInfo->prog->NumInstructions; inst = new_instruction(emitInfo, opcode); + if (!inst) { + return NULL; + } inst = new_instruction(emitInfo, OPCODE_ENDIF); + if (!inst) { + return NULL; + } emitInfo->prog->Instructions[ifInstLoc].BranchTarget - = emitInfo->prog->NumInstructions; + = emitInfo->prog->NumInstructions - 1; return inst; } } @@ -1806,13 +1961,34 @@ emit_cont_break_if_true(slang_emit_info *emitInfo, slang_ir_node *n) const GLuint condWritemask = inst->DstReg.WriteMask; assert(emitInfo->EmitCondCodes); inst = new_instruction(emitInfo, OPCODE_BRA); - inst->DstReg.CondMask = COND_NE; - inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); + if (inst) { + inst->DstReg.CondMask = COND_NE; + inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask); + } return inst; } } +/** + * Return the size of a swizzle mask given that some swizzle components + * may be NIL/undefined. For example: + * swizzle_size(".zzxx") = 4 + * swizzle_size(".xy??") = 2 + * swizzle_size(".w???") = 1 + */ +static GLuint +swizzle_size(GLuint swizzle) +{ + GLuint i; + for (i = 0; i < 4; i++) { + if (GET_SWZ(swizzle, i) == SWIZZLE_NIL) + return i; + } + return 4; +} + + static struct prog_instruction * emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) { @@ -1820,14 +1996,25 @@ emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n) inst = emit(emitInfo, n->Children[0]); -#if 0 - assert(n->Store->Parent); - /* Apply this node's swizzle to parent's storage */ - GLuint swizzle = n->Store->Swizzle; - _slang_copy_ir_storage(n->Store, n->Store->Parent); - n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle); + if (!n->Store->Parent) { + /* this covers a case such as "(b ? p : q).x" */ + n->Store->Parent = n->Children[0]->Store; + assert(n->Store->Parent); + } + + { + const GLuint swizzle = n->Store->Swizzle; + /* new storage is parent storage with updated Swizzle + Size fields */ + _slang_copy_ir_storage(n->Store, n->Store->Parent); + /* Apply this node's swizzle to parent's storage */ + n->Store->Swizzle = _slang_swizzle_swizzle(n->Store->Swizzle, swizzle); + /* Update size */ + n->Store->Size = swizzle_size(n->Store->Swizzle); + } + assert(!n->Store->Parent); -#endif + assert(n->Store->Index >= 0); + return inst; } @@ -1924,6 +2111,9 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n) indexStore, /* the index */ &elemSizeStore, NULL); + if (!inst) { + return NULL; + } indexStore = indexTemp; } @@ -1950,6 +2140,9 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n) indexStore, /* the index */ &indirectArray, /* indirect array base */ NULL); + if (!inst) { + return NULL; + } indexStore = indexTemp; } @@ -2107,6 +2300,7 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n) if (index < 0) { /* error */ char s[100]; + /* XXX isn't this really an out of memory/resources error? */ _mesa_snprintf(s, sizeof(s), "Undefined variable '%s'", (char *) n->Var->a_name); slang_info_log_error(emitInfo->log, s); @@ -2120,6 +2314,10 @@ emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n) /* mark var as used */ _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name); } + else if (n->Store->File == PROGRAM_INPUT) { + assert(n->Store->Index >= 0); + emitInfo->prog->InputsRead |= (1 << n->Store->Index); + } if (n->Store->Index < 0) { /* probably ran out of registers */ @@ -2142,6 +2340,14 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) return NULL; } + if (n->Comment) { + inst = new_instruction(emitInfo, OPCODE_NOP); + if (inst) { + inst->Comment = _mesa_strdup(n->Comment); + } + inst = NULL; + } + switch (n->Opcode) { case IR_SEQ: /* sequence of two sub-trees */ @@ -2224,6 +2430,7 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_POW: /* trinary operators */ case IR_LRP: + case IR_CMP: return emit_arith(emitInfo, n); case IR_EQUAL: @@ -2235,6 +2442,9 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n) case IR_TEX: case IR_TEXB: case IR_TEXP: + case IR_TEX_SH: + case IR_TEXB_SH: + case IR_TEXP_SH: return emit_tex(emitInfo, n); case IR_NEG: return emit_negation(emitInfo, n); @@ -2424,7 +2634,9 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt, maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4; } if (prog->Parameters->NumParameters > maxUniforms) { - slang_info_log_error(log, "Constant/uniform register limit exceeded"); + slang_info_log_error(log, "Constant/uniform register limit exceeded " + "(max=%u vec4)", maxUniforms); + return GL_FALSE; } @@ -2434,6 +2646,9 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt, if (withEnd) { struct prog_instruction *inst; inst = new_instruction(&emitInfo, OPCODE_END); + if (!inst) { + return GL_FALSE; + } } _slang_resolve_subroutines(&emitInfo);