Support for user-defined structures.

struct == and != operators not finished yet.  Struct assignment works though.
This commit is contained in:
Brian
2007-03-21 15:40:39 -06:00
parent 97c9b3ecc6
commit 2500d82d0d
3 changed files with 119 additions and 23 deletions
+53 -16
View File
@@ -78,6 +78,35 @@ is_sampler_type(const slang_fully_specified_type *t)
}
/**
* Return the offset (in floats or ints) of the named field within
* the given struct. Return -1 if field not found.
* If field is NULL, return the size of the struct instead.
*/
static GLint
_slang_field_offset(const slang_type_specifier *spec, slang_atom field)
{
GLint offset = 0;
GLuint i;
for (i = 0; i < spec->_struct->fields->num_variables; i++) {
const slang_variable *v = spec->_struct->fields->variables[i];
const GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier);
if (sz > 1) {
/* types larger than 1 float are register (4-float) aligned */
offset = (offset + 3) & ~3;
}
if (field && v->a_name == field) {
return offset;
}
offset += sz;
}
if (field)
return -1; /* field not found */
else
return offset; /* struct size */
}
GLuint
_slang_sizeof_type_specifier(const slang_type_specifier *spec)
{
@@ -122,20 +151,9 @@ _slang_sizeof_type_specifier(const slang_type_specifier *spec)
case SLANG_SPEC_SAMPLER2DSHADOW:
case SLANG_SPEC_SAMPLER2DRECT:
case SLANG_SPEC_SAMPLER2DRECTSHADOW:
return 1; /* special case */
return 1; /* a sampler is basically just an integer index */
case SLANG_SPEC_STRUCT:
{
GLuint sum = 0, i;
for (i = 0; i < spec->_struct->fields->num_variables; i++) {
slang_variable *v = spec->_struct->fields->variables[i];
GLuint sz = _slang_sizeof_type_specifier(&v->type.specifier);
/* XXX verify padding */
if (sz < 4)
sz = 4;
sum += sz;
}
return sum;
}
return _slang_field_offset(spec, 0); /* special use */
case SLANG_SPEC_ARRAY:
return _slang_sizeof_type_specifier(spec->_array);
default:
@@ -2034,6 +2052,7 @@ _slang_gen_field(slang_assemble_ctx * A, slang_operation *oper)
{
slang_typeinfo ti;
/* type of struct */
slang_typeinfo_construct(&ti);
_slang_typeof_operation(A, &oper->children[0], &ti);
@@ -2079,20 +2098,38 @@ _slang_gen_field(slang_assemble_ctx * A, slang_operation *oper)
/* oper->children[0] is the base */
/* oper->a_id is the field name */
slang_ir_node *base, *n;
GLint size = 4; /* XXX fix? */
slang_typeinfo field_ti;
GLint fieldSize, fieldOffset;
/* type of field */
slang_typeinfo_construct(&field_ti);
_slang_typeof_operation(A, oper, &field_ti);
fieldSize = _slang_sizeof_type_specifier(&field_ti.spec);
fieldOffset = _slang_field_offset(&ti.spec, oper->a_id);
if (fieldOffset < 0) {
slang_info_log_error(A->log,
"\"%s\" is not a member of struct \"%s\"",
(char *) oper->a_id,
(char *) ti.spec._struct->a_name);
return NULL;
}
assert(fieldSize >= 0);
base = _slang_gen_operation(A, &oper->children[0]);
if (!base) {
/* error previously found */
/* error msg should have already been logged */
return NULL;
}
n = new_node1(IR_FIELD, base);
if (n) {
n->Field = (char *) oper->a_id;
n->FieldOffset = fieldOffset;
assert(n->FieldOffset >= 0);
n->Store = _slang_new_ir_storage(base->Store->File,
base->Store->Index,
size);
fieldSize);
}
return n;
+65 -7
View File
@@ -770,6 +770,53 @@ emit_arith(slang_emit_info *emitInfo, slang_ir_node *n)
}
/**
* Emit code for == and != operators. These could normally be handled
* by emit_arith() except we need to be able to handle structure comparisons.
*/
static struct prog_instruction *
emit_compare(slang_emit_info *emitInfo, slang_ir_node *n)
{
struct prog_instruction *inst;
assert(n->Opcode == IR_SEQUAL || n->Opcode == IR_SNEQUAL);
/* gen code for children */
emit(emitInfo, n->Children[0]);
emit(emitInfo, n->Children[1]);
assert(n->Children[0]->Store->Size == n->Children[1]->Store->Size);
/* gen this instruction and src registers */
inst = new_instruction(emitInfo,
(n->Opcode == IR_SEQUAL) ? OPCODE_SEQ : OPCODE_SNE);
if (n->Children[0]->Store->Size > 4) {
/* struct compare */
_mesa_problem(NULL, "struct compare not implemented!");
return NULL;
}
else {
/* small/simple types */
storage_to_src_reg(&inst->SrcReg[0], n->Children[0]->Store);
storage_to_src_reg(&inst->SrcReg[1], n->Children[1]->Store);
}
/* free temps */
free_temp_storage(emitInfo->vt, n->Children[0]);
free_temp_storage(emitInfo->vt, n->Children[1]);
/* result storage */
if (!n->Store) {
if (!alloc_temp_storage(emitInfo, n, 1)) /* 1 bool */
return NULL;
}
storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);
return inst;
}
/**
* Generate code for an IR_CLAMP instruction.
*/
@@ -1337,7 +1384,6 @@ emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n)
return NULL;
}
if (n->Children[1]->Opcode == IR_FLOAT) {
/* Constant index */
const GLint arrayAddr = n->Children[0]->Store->Index;
@@ -1365,7 +1411,16 @@ emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n)
n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters);
}
else {
_mesa_problem(NULL, "structs/fields not supported yet");
GLint offset = n->FieldOffset / 4;
assert(n->Children[0]->Store->Index >= 0);
n->Store->Index = n->Children[0]->Store->Index + offset;
if (n->Store->Size == 1) {
GLint swz = n->FieldOffset % 4;
n->Store->Swizzle = MAKE_SWIZZLE4(swz, swz, swz, swz);
}
else {
n->Store->Swizzle = SWIZZLE_XYZW;
}
}
return NULL; /* no instruction */
}
@@ -1427,10 +1482,10 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
if (emitInfo->EmitComments) {
/* emit NOP with comment describing the variable's storage location */
char s[1000];
sprintf(s, "TEMP[%d]%s = %s (size %d)",
sprintf(s, "TEMP[%d]%s = variable %s (size %d)",
n->Store->Index,
_mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE),
(char *) n->Var->a_name,
(n->Var ? (char *) n->Var->a_name : "anonymous"),
n->Store->Size);
inst = new_instruction(emitInfo, OPCODE_NOP);
inst->Comment = _mesa_strdup(s);
@@ -1503,8 +1558,6 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
case IR_CROSS:
case IR_MIN:
case IR_MAX:
case IR_SEQUAL:
case IR_SNEQUAL:
case IR_SGE:
case IR_SGT:
case IR_SLE:
@@ -1515,6 +1568,11 @@ emit(slang_emit_info *emitInfo, slang_ir_node *n)
/* trinary operators */
case IR_LRP:
return emit_arith(emitInfo, n);
case IR_SEQUAL:
case IR_SNEQUAL:
return emit_compare(emitInfo, n);
case IR_CLAMP:
return emit_clamp(emitInfo, n);
case IR_TEX:
@@ -1600,7 +1658,7 @@ _slang_emit_code(slang_ir_node *n, slang_var_table *vt,
emitInfo.prog = prog;
emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;
emitInfo.EmitComments = ctx->Shader.EmitComments;
emitInfo.EmitComments = 1+ctx->Shader.EmitComments;
(void) emit(&emitInfo, n);
+1
View File
@@ -152,6 +152,7 @@ typedef struct slang_ir_node_
/** special fields depending on Opcode: */
const char *Field; /**< If Opcode == IR_FIELD */
int FieldOffset; /**< If Opcode == IR_FIELD */
GLuint Writemask; /**< If Opcode == IR_MOVE */
GLfloat Value[4]; /**< If Opcode == IR_FLOAT */
slang_variable *Var; /**< If Opcode == IR_VAR or IR_VAR_DECL */