mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 09:10:11 +01:00
Fix issues related to the 'continue' statement.
IR_LOOP now has two children: the body code, and the tail code.
Tail code is the "i++" part of a for-loop, or the expression at the end
of a "do {} while(expr);" loop.
"continue" translates into: "execute tail code; CONT;"
Also, the test for infinite do/while loops was incorrect.
This commit is contained in:
parent
81767eead9
commit
d1934c2065
3 changed files with 126 additions and 52 deletions
|
|
@ -414,7 +414,7 @@ _slang_free_ir_tree(slang_ir_node *n)
|
||||||
return;
|
return;
|
||||||
for (i = 0; i < 3; i++)
|
for (i = 0; i < 3; i++)
|
||||||
_slang_free_ir_tree(n->Children[i]);
|
_slang_free_ir_tree(n->Children[i]);
|
||||||
/* Do not free n->BranchNode since it's a child elsewhere */
|
/* Do not free n->List since it's a child elsewhere */
|
||||||
free(n);
|
free(n);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
@ -515,8 +515,8 @@ new_break(slang_ir_node *loopNode)
|
||||||
assert(loopNode->Opcode == IR_LOOP);
|
assert(loopNode->Opcode == IR_LOOP);
|
||||||
if (n) {
|
if (n) {
|
||||||
/* insert this node at head of linked list */
|
/* insert this node at head of linked list */
|
||||||
n->BranchNode = loopNode->BranchNode;
|
n->List = loopNode->List;
|
||||||
loopNode->BranchNode = n;
|
loopNode->List = n;
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
@ -534,8 +534,8 @@ new_break_if(slang_ir_node *loopNode, slang_ir_node *cond, GLboolean breakTrue)
|
||||||
n = new_node1(breakTrue ? IR_BREAK_IF_TRUE : IR_BREAK_IF_FALSE, cond);
|
n = new_node1(breakTrue ? IR_BREAK_IF_TRUE : IR_BREAK_IF_FALSE, cond);
|
||||||
if (n) {
|
if (n) {
|
||||||
/* insert this node at head of linked list */
|
/* insert this node at head of linked list */
|
||||||
n->BranchNode = loopNode->BranchNode;
|
n->List = loopNode->List;
|
||||||
loopNode->BranchNode = n;
|
loopNode->List = n;
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
@ -553,23 +553,8 @@ new_cont_if(slang_ir_node *loopNode, slang_ir_node *cond, GLboolean contTrue)
|
||||||
n = new_node1(contTrue ? IR_CONT_IF_TRUE : IR_CONT_IF_FALSE, cond);
|
n = new_node1(contTrue ? IR_CONT_IF_TRUE : IR_CONT_IF_FALSE, cond);
|
||||||
if (n) {
|
if (n) {
|
||||||
/* insert this node at head of linked list */
|
/* insert this node at head of linked list */
|
||||||
n->BranchNode = loopNode->BranchNode;
|
n->List = loopNode->List;
|
||||||
loopNode->BranchNode = n;
|
loopNode->List = n;
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static slang_ir_node *
|
|
||||||
new_cont(slang_ir_node *loopNode)
|
|
||||||
{
|
|
||||||
slang_ir_node *n = new_node0(IR_CONT);
|
|
||||||
assert(loopNode);
|
|
||||||
assert(loopNode->Opcode == IR_LOOP);
|
|
||||||
if (n) {
|
|
||||||
/* insert this node at head of linked list */
|
|
||||||
n->BranchNode = loopNode->BranchNode;
|
|
||||||
loopNode->BranchNode = n;
|
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
@ -1369,7 +1354,8 @@ _slang_gen_while(slang_assemble_ctx * A, const slang_operation *oper)
|
||||||
loop->Children[0] = new_seq(breakIf, body);
|
loop->Children[0] = new_seq(breakIf, body);
|
||||||
|
|
||||||
/* Do infinite loop detection */
|
/* Do infinite loop detection */
|
||||||
if (!loop->BranchNode && isConst && constTrue) {
|
/* loop->List is head of linked list of break/continue nodes */
|
||||||
|
if (!loop->List && isConst && constTrue) {
|
||||||
/* infinite loop detected */
|
/* infinite loop detected */
|
||||||
A->CurLoop = prevLoop; /* clean-up */
|
A->CurLoop = prevLoop; /* clean-up */
|
||||||
slang_info_log_error(A->log, "Infinite loop detected!");
|
slang_info_log_error(A->log, "Infinite loop detected!");
|
||||||
|
|
@ -1392,30 +1378,33 @@ _slang_gen_do(slang_assemble_ctx * A, const slang_operation *oper)
|
||||||
/*
|
/*
|
||||||
* LOOP:
|
* LOOP:
|
||||||
* body code (child[0])
|
* body code (child[0])
|
||||||
* BREAK if !expr (child[1])
|
* tail code:
|
||||||
|
* BREAK if !expr (child[1])
|
||||||
*/
|
*/
|
||||||
slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body;
|
slang_ir_node *prevLoop, *loop, *cond;
|
||||||
GLboolean isConst, constTrue;
|
GLboolean isConst, constTrue;
|
||||||
|
|
||||||
/* Check if loop condition is a constant */
|
|
||||||
isConst = _slang_is_constant_cond(&oper->children[0], &constTrue);
|
|
||||||
|
|
||||||
loop = new_loop(NULL);
|
loop = new_loop(NULL);
|
||||||
|
|
||||||
/* save old, push new loop */
|
/* save old, push new loop */
|
||||||
prevLoop = A->CurLoop;
|
prevLoop = A->CurLoop;
|
||||||
A->CurLoop = loop;
|
A->CurLoop = loop;
|
||||||
|
|
||||||
body = _slang_gen_operation(A, &oper->children[0]);
|
/* loop body: */
|
||||||
cond = new_cond(_slang_gen_operation(A, &oper->children[1]));
|
loop->Children[0] = _slang_gen_operation(A, &oper->children[0]);
|
||||||
|
|
||||||
|
/* Check if loop condition is a constant */
|
||||||
|
isConst = _slang_is_constant_cond(&oper->children[1], &constTrue);
|
||||||
if (isConst && constTrue) {
|
if (isConst && constTrue) {
|
||||||
/* while(nonzero constant), no conditional break */
|
/* do { } while(1) ==> no conditional break */
|
||||||
breakIf = NULL;
|
loop->Children[1] = NULL; /* no tail code */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
|
cond = new_cond(_slang_gen_operation(A, &oper->children[1]));
|
||||||
|
loop->Children[1] = new_break_if(A->CurLoop, cond, GL_FALSE);
|
||||||
}
|
}
|
||||||
loop->Children[0] = new_seq(body, breakIf);
|
|
||||||
|
/* XXX we should do infinite loop detection, as above */
|
||||||
|
|
||||||
/* pop loop, restore prev */
|
/* pop loop, restore prev */
|
||||||
A->CurLoop = prevLoop;
|
A->CurLoop = prevLoop;
|
||||||
|
|
@ -1431,11 +1420,12 @@ static slang_ir_node *
|
||||||
_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
|
_slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* init (child[0])
|
* init code (child[0])
|
||||||
* LOOP:
|
* LOOP:
|
||||||
* BREAK if !expr (child[1])
|
* BREAK if !expr (child[1])
|
||||||
* body code (child[3])
|
* body code (child[3])
|
||||||
* incr code (child[2]) // XXX continue here
|
* tail code:
|
||||||
|
* incr code (child[2]) // XXX continue here
|
||||||
*/
|
*/
|
||||||
slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr;
|
slang_ir_node *prevLoop, *loop, *cond, *breakIf, *body, *init, *incr;
|
||||||
|
|
||||||
|
|
@ -1450,8 +1440,9 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
|
||||||
breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
|
breakIf = new_break_if(A->CurLoop, cond, GL_FALSE);
|
||||||
body = _slang_gen_operation(A, &oper->children[3]);
|
body = _slang_gen_operation(A, &oper->children[3]);
|
||||||
incr = _slang_gen_operation(A, &oper->children[2]);
|
incr = _slang_gen_operation(A, &oper->children[2]);
|
||||||
loop->Children[0] = new_seq(breakIf,
|
|
||||||
new_seq(body, incr));
|
loop->Children[0] = new_seq(breakIf, body);
|
||||||
|
loop->Children[1] = incr; /* tail code */
|
||||||
|
|
||||||
/* pop loop, restore prev */
|
/* pop loop, restore prev */
|
||||||
A->CurLoop = prevLoop;
|
A->CurLoop = prevLoop;
|
||||||
|
|
@ -1460,6 +1451,25 @@ _slang_gen_for(slang_assemble_ctx * A, const slang_operation *oper)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static slang_ir_node *
|
||||||
|
_slang_gen_continue(slang_assemble_ctx * A, const slang_operation *oper)
|
||||||
|
{
|
||||||
|
slang_ir_node *n, *loopNode;
|
||||||
|
assert(oper->type == SLANG_OPER_CONTINUE);
|
||||||
|
loopNode = A->CurLoop;
|
||||||
|
assert(loopNode);
|
||||||
|
assert(loopNode->Opcode == IR_LOOP);
|
||||||
|
n = new_node0(IR_CONT);
|
||||||
|
if (n) {
|
||||||
|
n->Parent = loopNode;
|
||||||
|
/* insert this node at head of linked list */
|
||||||
|
n->List = loopNode->List;
|
||||||
|
loopNode->List = n;
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the given operation is of a specific type.
|
* Determine if the given operation is of a specific type.
|
||||||
*/
|
*/
|
||||||
|
|
@ -2364,7 +2374,7 @@ _slang_gen_operation(slang_assemble_ctx * A, slang_operation *oper)
|
||||||
if (!A->CurLoop) {
|
if (!A->CurLoop) {
|
||||||
slang_info_log_error(A->log, "'continue' not in loop");
|
slang_info_log_error(A->log, "'continue' not in loop");
|
||||||
}
|
}
|
||||||
return new_cont(A->CurLoop);
|
return _slang_gen_continue(A, oper);
|
||||||
case SLANG_OPER_DISCARD:
|
case SLANG_OPER_DISCARD:
|
||||||
return new_node0(IR_KILL);
|
return new_node0(IR_KILL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -316,6 +316,7 @@ slang_print_ir(const slang_ir_node *n, int indent)
|
||||||
printf("ELSE\n");
|
printf("ELSE\n");
|
||||||
slang_print_ir(n->Children[2], indent+3);
|
slang_print_ir(n->Children[2], indent+3);
|
||||||
}
|
}
|
||||||
|
spaces(indent);
|
||||||
printf("ENDIF\n");
|
printf("ENDIF\n");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -335,6 +336,11 @@ slang_print_ir(const slang_ir_node *n, int indent)
|
||||||
case IR_LOOP:
|
case IR_LOOP:
|
||||||
printf("LOOP\n");
|
printf("LOOP\n");
|
||||||
slang_print_ir(n->Children[0], indent+3);
|
slang_print_ir(n->Children[0], indent+3);
|
||||||
|
if (n->Children[1]) {
|
||||||
|
spaces(indent);
|
||||||
|
printf("TAIL:\n");
|
||||||
|
slang_print_ir(n->Children[1], indent+3);
|
||||||
|
}
|
||||||
spaces(indent);
|
spaces(indent);
|
||||||
printf("ENDLOOP\n");
|
printf("ENDLOOP\n");
|
||||||
break;
|
break;
|
||||||
|
|
@ -685,6 +691,19 @@ instruction_annotation(gl_inst_opcode opcode, char *dstAnnot,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Emit an instruction that's just a comment.
|
||||||
|
*/
|
||||||
|
static struct prog_instruction *
|
||||||
|
emit_comment(slang_emit_info *emitInfo, const char *s)
|
||||||
|
{
|
||||||
|
struct prog_instruction *inst = new_instruction(emitInfo, OPCODE_NOP);
|
||||||
|
if (inst) {
|
||||||
|
inst->Comment = _mesa_strdup(s);
|
||||||
|
}
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate code for a simple arithmetic instruction.
|
* Generate code for a simple arithmetic instruction.
|
||||||
|
|
@ -1005,9 +1024,16 @@ static struct prog_instruction *
|
||||||
emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
|
emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
|
||||||
{
|
{
|
||||||
assert(n->Label);
|
assert(n->Label);
|
||||||
|
#if 0
|
||||||
|
/* XXX this fails in loop tail code - investigate someday */
|
||||||
assert(_slang_label_get_location(n->Label) < 0);
|
assert(_slang_label_get_location(n->Label) < 0);
|
||||||
_slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
|
_slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
|
||||||
emitInfo->prog);
|
emitInfo->prog);
|
||||||
|
#else
|
||||||
|
if (_slang_label_get_location(n->Label) < 0)
|
||||||
|
_slang_label_set_location(n->Label, emitInfo->prog->NumInstructions,
|
||||||
|
emitInfo->prog);
|
||||||
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1097,7 +1123,9 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
|
|
||||||
assert(n->Children[1]->Store->Index >= 0);
|
assert(n->Children[1]->Store->Index >= 0);
|
||||||
|
|
||||||
|
#if 0
|
||||||
assert(!n->Store);
|
assert(!n->Store);
|
||||||
|
#endif
|
||||||
n->Store = n->Children[0]->Store;
|
n->Store = n->Children[0]->Store;
|
||||||
|
|
||||||
#if PEEPHOLE_OPTIMIZATIONS
|
#if PEEPHOLE_OPTIMIZATIONS
|
||||||
|
|
@ -1316,9 +1344,11 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
{
|
{
|
||||||
struct gl_program *prog = emitInfo->prog;
|
struct gl_program *prog = emitInfo->prog;
|
||||||
struct prog_instruction *beginInst, *endInst;
|
struct prog_instruction *beginInst, *endInst;
|
||||||
GLuint beginInstLoc, endInstLoc;
|
GLuint beginInstLoc, tailInstLoc, endInstLoc;
|
||||||
slang_ir_node *ir;
|
slang_ir_node *ir;
|
||||||
|
|
||||||
|
slang_print_ir(n, 10);
|
||||||
|
|
||||||
/* emit OPCODE_BGNLOOP */
|
/* emit OPCODE_BGNLOOP */
|
||||||
beginInstLoc = prog->NumInstructions;
|
beginInstLoc = prog->NumInstructions;
|
||||||
if (emitInfo->EmitHighLevelInstructions) {
|
if (emitInfo->EmitHighLevelInstructions) {
|
||||||
|
|
@ -1328,6 +1358,14 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
/* body */
|
/* body */
|
||||||
emit(emitInfo, n->Children[0]);
|
emit(emitInfo, n->Children[0]);
|
||||||
|
|
||||||
|
/* tail */
|
||||||
|
tailInstLoc = prog->NumInstructions;
|
||||||
|
if (n->Children[1]) {
|
||||||
|
if (emitInfo->EmitComments)
|
||||||
|
emit_comment(emitInfo, "Loop tail code:");
|
||||||
|
emit(emitInfo, n->Children[1]);
|
||||||
|
}
|
||||||
|
|
||||||
endInstLoc = prog->NumInstructions;
|
endInstLoc = prog->NumInstructions;
|
||||||
if (emitInfo->EmitHighLevelInstructions) {
|
if (emitInfo->EmitHighLevelInstructions) {
|
||||||
/* emit OPCODE_ENDLOOP */
|
/* emit OPCODE_ENDLOOP */
|
||||||
|
|
@ -1338,7 +1376,7 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
endInst = new_instruction(emitInfo, OPCODE_BRA);
|
endInst = new_instruction(emitInfo, OPCODE_BRA);
|
||||||
endInst->DstReg.CondMask = COND_TR; /* always true */
|
endInst->DstReg.CondMask = COND_TR; /* always true */
|
||||||
}
|
}
|
||||||
/* end instruction's BranchTarget points to top of loop */
|
/* ENDLOOP's BranchTarget points to the BGNLOOP inst */
|
||||||
endInst->BranchTarget = beginInstLoc;
|
endInst->BranchTarget = beginInstLoc;
|
||||||
|
|
||||||
if (emitInfo->EmitHighLevelInstructions) {
|
if (emitInfo->EmitHighLevelInstructions) {
|
||||||
|
|
@ -1351,7 +1389,7 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
* BREAK and CONT nodes, filling in their BranchTarget fields (which
|
* BREAK and CONT nodes, filling in their BranchTarget fields (which
|
||||||
* will point to the ENDLOOP+1 or BGNLOOP instructions, respectively).
|
* will point to the ENDLOOP+1 or BGNLOOP instructions, respectively).
|
||||||
*/
|
*/
|
||||||
for (ir = n->BranchNode; ir; ir = ir->BranchNode) {
|
for (ir = n->List; ir; ir = ir->List) {
|
||||||
struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
|
struct prog_instruction *inst = prog->Instructions + ir->InstLocation;
|
||||||
assert(inst->BranchTarget < 0);
|
assert(inst->BranchTarget < 0);
|
||||||
if (ir->Opcode == IR_BREAK ||
|
if (ir->Opcode == IR_BREAK ||
|
||||||
|
|
@ -1372,8 +1410,8 @@ emit_loop(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
inst->Opcode == OPCODE_CONT0 ||
|
inst->Opcode == OPCODE_CONT0 ||
|
||||||
inst->Opcode == OPCODE_CONT1 ||
|
inst->Opcode == OPCODE_CONT1 ||
|
||||||
inst->Opcode == OPCODE_BRA);
|
inst->Opcode == OPCODE_BRA);
|
||||||
/* to go instruction at top of loop */
|
/* go to instruction at tail of loop */
|
||||||
inst->BranchTarget = beginInstLoc;
|
inst->BranchTarget = endInstLoc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1389,13 +1427,28 @@ emit_cont_break(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
{
|
{
|
||||||
gl_inst_opcode opcode;
|
gl_inst_opcode opcode;
|
||||||
struct prog_instruction *inst;
|
struct prog_instruction *inst;
|
||||||
n->InstLocation = emitInfo->prog->NumInstructions;
|
|
||||||
|
if (n->Opcode == IR_CONT) {
|
||||||
|
/* we need to execute the loop's tail code before doing CONT */
|
||||||
|
assert(n->Parent);
|
||||||
|
assert(n->Parent->Opcode == IR_LOOP);
|
||||||
|
if (n->Parent->Children[1]) {
|
||||||
|
/* emit tail code */
|
||||||
|
if (emitInfo->EmitComments) {
|
||||||
|
emit_comment(emitInfo, "continue - tail code:");
|
||||||
|
}
|
||||||
|
emit(emitInfo, n->Parent->Children[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* opcode selection */
|
||||||
if (emitInfo->EmitHighLevelInstructions) {
|
if (emitInfo->EmitHighLevelInstructions) {
|
||||||
opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
|
opcode = (n->Opcode == IR_CONT) ? OPCODE_CONT : OPCODE_BRK;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
opcode = OPCODE_BRA;
|
opcode = OPCODE_BRA;
|
||||||
}
|
}
|
||||||
|
n->InstLocation = emitInfo->prog->NumInstructions;
|
||||||
inst = new_instruction(emitInfo, opcode);
|
inst = new_instruction(emitInfo, opcode);
|
||||||
inst->DstReg.CondMask = COND_TR; /* always true */
|
inst->DstReg.CondMask = COND_TR; /* always true */
|
||||||
return inst;
|
return inst;
|
||||||
|
|
@ -1456,7 +1509,7 @@ emit_cont_break_if(slang_emit_info *emitInfo, slang_ir_node *n,
|
||||||
inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ;
|
inst->DstReg.CondMask = breakTrue ? COND_NE : COND_EQ;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* BRK0, BRK1, CONT0, CONT1 */
|
/* BRK0, BRK1, CONT0, CONT1 uses SrcReg[0] as the condition */
|
||||||
storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
|
storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
|
||||||
}
|
}
|
||||||
return inst;
|
return inst;
|
||||||
|
|
@ -1607,7 +1660,9 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
assert(n->Children[1]);
|
assert(n->Children[1]);
|
||||||
emit(emitInfo, n->Children[0]);
|
emit(emitInfo, n->Children[0]);
|
||||||
inst = emit(emitInfo, n->Children[1]);
|
inst = emit(emitInfo, n->Children[1]);
|
||||||
|
#if 0
|
||||||
assert(!n->Store);
|
assert(!n->Store);
|
||||||
|
#endif
|
||||||
n->Store = n->Children[1]->Store;
|
n->Store = n->Children[1]->Store;
|
||||||
return inst;
|
return inst;
|
||||||
|
|
||||||
|
|
@ -1623,10 +1678,11 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
assert(n->Store);
|
assert(n->Store);
|
||||||
assert(n->Store->File != PROGRAM_UNDEFINED);
|
assert(n->Store->File != PROGRAM_UNDEFINED);
|
||||||
assert(n->Store->Size > 0);
|
assert(n->Store->Size > 0);
|
||||||
assert(n->Store->Index < 0);
|
/*assert(n->Store->Index < 0);*/
|
||||||
if (!n->Var || n->Var->isTemp) {
|
if (!n->Var || n->Var->isTemp) {
|
||||||
/* a nameless/temporary variable, will be freed after first use */
|
/* a nameless/temporary variable, will be freed after first use */
|
||||||
if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {
|
/*NEW*/
|
||||||
|
if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) {
|
||||||
slang_info_log_error(emitInfo->log,
|
slang_info_log_error(emitInfo->log,
|
||||||
"Ran out of registers, too many temporaries");
|
"Ran out of registers, too many temporaries");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1654,8 +1710,7 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
|
||||||
_mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE),
|
_mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE),
|
||||||
(n->Var ? (char *) n->Var->a_name : "anonymous"),
|
(n->Var ? (char *) n->Var->a_name : "anonymous"),
|
||||||
n->Store->Size);
|
n->Store->Size);
|
||||||
inst = new_instruction(emitInfo, OPCODE_NOP);
|
inst = emit_comment(emitInfo, s);
|
||||||
inst->Comment = _mesa_strdup(s);
|
|
||||||
return inst;
|
return inst;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -1828,7 +1883,7 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
|
||||||
|
|
||||||
emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
|
emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
|
||||||
emitInfo.EmitCondCodes = 0; /* XXX temporary! */
|
emitInfo.EmitCondCodes = 0; /* XXX temporary! */
|
||||||
emitInfo.EmitComments = ctx->Shader.EmitComments;
|
emitInfo.EmitComments = 1 + ctx->Shader.EmitComments;
|
||||||
|
|
||||||
(void) emit(&emitInfo, n);
|
(void) emit(&emitInfo, n);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,9 @@ typedef enum
|
||||||
IR_COND, /* conditional expression/predicate */
|
IR_COND, /* conditional expression/predicate */
|
||||||
|
|
||||||
IR_IF, /* high-level IF/then/else */
|
IR_IF, /* high-level IF/then/else */
|
||||||
|
/* Children[0] = conditional expression */
|
||||||
|
/* Children[1] = if-true part */
|
||||||
|
/* Children[2] = if-else part, or NULL */
|
||||||
|
|
||||||
IR_BEGIN_SUB, /* begin subroutine */
|
IR_BEGIN_SUB, /* begin subroutine */
|
||||||
IR_END_SUB, /* end subroutine */
|
IR_END_SUB, /* end subroutine */
|
||||||
|
|
@ -60,13 +63,18 @@ typedef enum
|
||||||
IR_CALL, /* call subroutine */
|
IR_CALL, /* call subroutine */
|
||||||
|
|
||||||
IR_LOOP, /* high-level loop-begin / loop-end */
|
IR_LOOP, /* high-level loop-begin / loop-end */
|
||||||
|
/* Children[0] = loop body */
|
||||||
|
/* Children[1] = loop tail code, or NULL */
|
||||||
|
|
||||||
IR_CONT, /* continue loop */
|
IR_CONT, /* continue loop */
|
||||||
|
/* n->Parent = ptr to parent IR_LOOP Node */
|
||||||
IR_BREAK, /* break loop */
|
IR_BREAK, /* break loop */
|
||||||
|
|
||||||
IR_BREAK_IF_TRUE,
|
IR_BREAK_IF_TRUE,
|
||||||
IR_BREAK_IF_FALSE,
|
IR_BREAK_IF_FALSE,
|
||||||
IR_CONT_IF_TRUE,
|
IR_CONT_IF_TRUE,
|
||||||
IR_CONT_IF_FALSE,
|
IR_CONT_IF_FALSE,
|
||||||
|
/* Children[0] = the condition expression */
|
||||||
|
|
||||||
IR_MOVE,
|
IR_MOVE,
|
||||||
|
|
||||||
|
|
@ -161,7 +169,8 @@ typedef struct slang_ir_node_
|
||||||
GLuint Writemask; /**< If Opcode == IR_MOVE */
|
GLuint Writemask; /**< If Opcode == IR_MOVE */
|
||||||
GLfloat Value[4]; /**< If Opcode == IR_FLOAT */
|
GLfloat Value[4]; /**< If Opcode == IR_FLOAT */
|
||||||
slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */
|
slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */
|
||||||
struct slang_ir_node_ *BranchNode; /**< Used for branching instructions */
|
struct slang_ir_node_ *List; /**< For various linked lists */
|
||||||
|
struct slang_ir_node_ *Parent; /**< Pointer to logical parent (ie. loop) */
|
||||||
slang_label *Label; /**< Used for branches */
|
slang_label *Label; /**< Used for branches */
|
||||||
} slang_ir_node;
|
} slang_ir_node;
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue