***/
-#include "imports.h"
-#include "context.h"
-#include "macros.h"
-#include "program.h"
-#include "prog_instruction.h"
-#include "prog_parameter.h"
-#include "prog_print.h"
+#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"
+#include "shader/prog_print.h"
#include "slang_builtin.h"
#include "slang_emit.h"
+#include "slang_mem.h"
#define PEEPHOLE_OPTIMIZATIONS 1
_slang_new_ir_storage(enum register_file file, GLint index, GLint size)
{
slang_ir_storage *st;
- st = (slang_ir_storage *) _mesa_calloc(sizeof(slang_ir_storage));
+ st = (slang_ir_storage *) _slang_alloc(sizeof(slang_ir_storage));
if (st) {
st->File = file;
st->Index = index;
if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
slang_info_log_error(emitInfo->log,
"Ran out of registers, too many temporaries");
+ _slang_free(n->Store);
+ n->Store = NULL;
return GL_FALSE;
}
return GL_TRUE;
/* Child[0] is the sampler (a uniform which'll indicate the texture unit) */
assert(n->Children[0]->Store);
+ /* Store->Index is the sampler index */
+ assert(n->Children[0]->Store->Index >= 0);
+ /* Store->Size is the texture target */
assert(n->Children[0]->Store->Size >= TEXTURE_1D_INDEX);
+ assert(n->Children[0]->Store->Size <= TEXTURE_RECT_INDEX);
inst->Sampler = n->Children[0]->Store->Index; /* i.e. uniform's index */
inst->TexSrcTarget = n->Children[0]->Store->Size;
/* lhs */
emit(emitInfo, n->Children[0]);
+ if (!n->Children[0]->Store || n->Children[0]->Store->Index < 0) {
+ /* an error should have been already recorded */
+ return NULL;
+ }
/* rhs */
assert(n->Children[1]);
inst = emit(emitInfo, n->Children[1]);
- if (!n->Children[1]->Store) {
- slang_info_log_error(emitInfo->log, "invalid assignment");
+ if (!n->Children[1]->Store || n->Children[1]->Store->Index < 0) {
+ if (!emitInfo->log->text) {
+ slang_info_log_error(emitInfo->log, "invalid assignment");
+ }
return NULL;
}
+
assert(n->Children[1]->Store->Index >= 0);
+ /*assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);*/
+
n->Store = n->Children[0]->Store;
#if PEEPHOLE_OPTIMIZATIONS
static struct prog_instruction *
emit_not(slang_emit_info *emitInfo, slang_ir_node *n)
{
+ static const struct {
+ gl_inst_opcode op, opNot;
+ } operators[] = {
+ { OPCODE_SLT, OPCODE_SGE },
+ { OPCODE_SLE, OPCODE_SGT },
+ { OPCODE_SGT, OPCODE_SLE },
+ { OPCODE_SGE, OPCODE_SLT },
+ { OPCODE_SEQ, OPCODE_SNE },
+ { OPCODE_SNE, OPCODE_SEQ },
+ { 0, 0 }
+ };
struct prog_instruction *inst;
+ GLuint i;
/* child expr */
- (void) emit(emitInfo, n->Children[0]);
- /* XXXX if child instr is SGT convert to SLE, if SEQ, SNE, etc */
+ inst = emit(emitInfo, n->Children[0]);
+#if PEEPHOLE_OPTIMIZATIONS
+ if (inst) {
+ /* if the prev instruction was a comparison instruction, invert it */
+ for (i = 0; operators[i].op; i++) {
+ if (inst->Opcode == operators[i].op) {
+ inst->Opcode = operators[i].opNot;
+ n->Store = n->Children[0]->Store;
+ return inst;
+ }
+ }
+ }
+#endif
+
+ /* else, invert using SEQ (v = v == 0) */
if (!n->Store)
if (!alloc_temp_storage(emitInfo, n, n->Children[0]->Store->Size))
return NULL;
const gl_inst_opcode opcode
= (n->Opcode == IR_CONT_IF_TRUE) ? OPCODE_CONT : OPCODE_BRK;
if (emitInfo->EmitCondCodes) {
+ /* Get the writemask from the previous instruction which set
+ * the condcodes. Use that writemask as the CondSwizzle.
+ */
+ const GLuint condWritemask = inst->DstReg.WriteMask;
inst = new_instruction(emitInfo, opcode);
inst->DstReg.CondMask = COND_NE;
+ inst->DstReg.CondSwizzle = writemask_to_swizzle(condWritemask);
return inst;
}
else {
}
}
else {
+ 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);
return inst;
}
}
}
if (n->Store->Index < 0) {
- printf("#### VAR %s not allocated!\n", (char*)n->Var->a_name);
+ /* probably ran out of registers */
+ return NULL;
}
- assert(n->Store->Index >= 0);
assert(n->Store->Size > 0);
break;
mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions,
mainP->NumInstructions,
total);
+ mainP->NumInstructions = total;
for (i = 0; i < emitInfo->NumSubroutines; i++) {
struct gl_program *sub = emitInfo->Subroutines[i];
_mesa_copy_instructions(mainP->Instructions + subroutineLoc[i],
sub->Parameters = NULL; /* prevent double-free */
_mesa_delete_program(ctx, sub);
}
- mainP->NumInstructions = total;
+
+ /* free subroutine list */
+ if (emitInfo->Subroutines) {
+ _mesa_free(emitInfo->Subroutines);
+ emitInfo->Subroutines = NULL;
+ }
+ emitInfo->NumSubroutines = 0;
/* Examine CAL instructions.
* At this point, the BranchTarget field of the CAL instructions is
emitInfo.NumSubroutines = 0;
emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
- emitInfo.EmitCondCodes = 0*ctx->Shader.EmitCondCodes;
+ emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;
emitInfo.EmitComments = ctx->Shader.EmitComments;
- emitInfo.EmitBeginEndSub = 0; /* XXX for compiler debug only */
+ emitInfo.EmitBeginEndSub = GL_TRUE;
if (!emitInfo.EmitCondCodes) {
emitInfo.EmitHighLevelInstructions = GL_TRUE;