Fix function call bug 11731. Also, fix up IR_CALL/IR_FUNC confusion.

This commit is contained in:
Brian 2007-07-26 15:32:34 -06:00
parent a57c5a417b
commit 33814a55f8
4 changed files with 45 additions and 34 deletions

View file

@ -1,6 +1,6 @@
/*
* Mesa 3-D graphics library
* Version: 7.0.1
* Version: 7.1
*
* Copyright (C) 2005-2007 Brian Paul All Rights Reserved.
*
@ -37,13 +37,13 @@
#include "imports.h"
#include "macros.h"
#include "mtypes.h"
#include "program.h"
#include "prog_instruction.h"
#include "prog_parameter.h"
#include "prog_statevars.h"
#include "main/imports.h"
#include "main/macros.h"
#include "main/mtypes.h"
#include "shader/program.h"
#include "shader/prog_instruction.h"
#include "shader/prog_parameter.h"
#include "shader/prog_statevars.h"
#include "slang_typeinfo.h"
#include "slang_codegen.h"
#include "slang_compile.h"
@ -536,7 +536,7 @@ new_not(slang_ir_node *n)
static slang_ir_node *
new_inlined_function_call(slang_ir_node *code, slang_label *name)
{
slang_ir_node *n = new_node1(IR_FUNC, code);
slang_ir_node *n = new_node1(IR_CALL, code);
assert(name);
if (n)
n->Label = name;
@ -1202,17 +1202,29 @@ _slang_gen_function_call(slang_assemble_ctx *A, slang_function *fun,
/* non-assembly function */
inlined = slang_inline_function_call(A, fun, oper, dest);
if (inlined && _slang_find_node_type(inlined, SLANG_OPER_RETURN)) {
/* This inlined function has one or more 'return' statements.
slang_operation *callOper;
/* The function we're calling has one or more 'return' statements.
* So, we can't truly inline this function because we need to
* implement 'return' with RET (and CAL).
* Nevertheless, we performed "inlining" to make a new instance
* of the function body to deal with static register allocation.
*
* XXX check if there's one 'return' and if it's the very last
* statement in the function - we can optimize that case.
*/
assert(inlined->type == SLANG_OPER_BLOCK_NEW_SCOPE ||
inlined->type == SLANG_OPER_SEQUENCE);
inlined->type = SLANG_OPER_INLINED_CALL;
inlined->fun = fun;
inlined->label = _slang_label_new_unique((char*) fun->header.a_name);
if (_slang_function_has_return_value(fun) && !dest) {
assert(inlined->children[0].type == SLANG_OPER_VARIABLE_DECL);
assert(inlined->children[2].type == SLANG_OPER_IDENTIFIER);
callOper = &inlined->children[1];
}
else {
callOper = inlined;
}
callOper->type = SLANG_OPER_INLINED_CALL;
callOper->fun = fun;
callOper->label = _slang_label_new_unique((char*) fun->header.a_name);
}
}
@ -1949,8 +1961,7 @@ static slang_ir_node *
_slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
{
const GLboolean haveReturnValue
= (oper->num_children == 1 &&
oper->children[0].type != SLANG_OPER_VOID);
= (oper->num_children == 1 && oper->children[0].type != SLANG_OPER_VOID);
/* error checking */
assert(A->CurFunction);
@ -1960,7 +1971,7 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
return NULL;
}
else if (!haveReturnValue &&
A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
slang_info_log_error(A->log, "return statement requires an expression");
return NULL;
}

View file

@ -36,13 +36,13 @@
***/
#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"
@ -780,16 +780,18 @@ emit_label(slang_emit_info *emitInfo, const slang_ir_node *n)
/**
* Emit code for an inlined function call (subroutine).
* Emit code for a function call.
* Note that for each time a function is called, we emit the function's
* body code again because the set of available registers may be different.
*/
static struct prog_instruction *
emit_func(slang_emit_info *emitInfo, slang_ir_node *n)
emit_fcall(slang_emit_info *emitInfo, slang_ir_node *n)
{
struct gl_program *progSave;
struct prog_instruction *inst;
GLuint subroutineId;
assert(n->Opcode == IR_FUNC);
assert(n->Opcode == IR_CALL);
assert(n->Label);
/* save/push cur program */
@ -1687,10 +1689,10 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
case IR_KILL:
return emit_kill(emitInfo);
case IR_FUNC:
/* new variable scope for subroutines/function calls*/
case IR_CALL:
/* new variable scope for subroutines/function calls */
_slang_push_var_table(emitInfo->vt);
inst = emit_func(emitInfo, n);
inst = emit_fcall(emitInfo, n);
_slang_pop_var_table(emitInfo->vt);
return inst;
@ -1782,7 +1784,7 @@ _slang_resolve_subroutines(slang_emit_info *emitInfo)
emitInfo->NumSubroutines = 0;
/* Examine CAL instructions.
* At this point, the BranchTarget field of the CAL instructions is
* At this point, the BranchTarget field of the CAL instruction is
* the number/id of the subroutine to call (an index into the
* emitInfo->Subroutines list).
* Translate that into an actual instruction location now.

View file

@ -27,7 +27,7 @@
#include "context.h"
#include "slang_ir.h"
#include "slang_mem.h"
#include "prog_print.h"
#include "shader/prog_print.h"
static const slang_ir_info IrInfo[] = {
@ -311,7 +311,7 @@ _slang_print_ir_tree(const slang_ir_node *n, int indent)
printf("RETURN\n");
break;
case IR_CALL:
printf("CALL\n");
printf("CALL %s\n", n->Label->Name);
break;
case IR_LOOP:

View file

@ -62,8 +62,6 @@ typedef enum
IR_RETURN, /* return from subroutine */
IR_CALL, /* call subroutine */
IR_FUNC, /* inlined function code */
IR_LOOP, /* high-level loop-begin / loop-end */
/* Children[0] = loop body */
/* Children[1] = loop tail code, or NULL */