#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"
}
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;
}
* 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;
}
* 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;
}
}
+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.
*/
}
}
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:
slang_operation_destruct(blockOper);
}
break;
-#endif
+
case SLANG_OPER_ASSIGN:
case SLANG_OPER_SUBSCRIPT:
/* special case:
&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++) {
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) {
n = _slang_gen_operation(A, oper);
- A->CurFunction->end_label = NULL;
+ A->CurFunction->end_label = NULL; /* XXX delete/free? */
A->CurFunction = prevFunc;
}
-
-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)
{
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;
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);
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 */
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 */
tree = new_seq(tree, assignx);
/* "end" label */
- endLab = new_label(endAtom);
+ endLab = new_label(endLabel);
tree = new_seq(tree, endLab);
/* tmp var value */
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 */
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");
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:
/* 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);
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");
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;
}
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);
{
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