static inline
bi_instr * bi_${opcode.replace('.', '_').lower()}${to_suffix(ops[opcode])}(${signature(ops[opcode], modifiers)})
{
- bi_instr *I = rzalloc(b->shader, bi_instr);
+<%
+ op = ops[opcode]
+ nr_dests = "nr_dests" if op["variable_dests"] else op["dests"]
+ nr_srcs = "nr_srcs" if op["variable_srcs"] else src_count(op)
+%>
+ size_t size = sizeof(bi_instr) + sizeof(bi_index) * (${nr_dests} + ${nr_srcs});
+ bi_instr *I = (bi_instr *) rzalloc_size(b->shader, size);
+
I->op = BI_OPCODE_${opcode.replace('.', '_').upper()};
+ I->nr_dests = ${nr_dests};
+ I->nr_srcs = ${nr_srcs};
+ I->dest = (bi_index *) (&I[1]);
+ I->src = I->dest + ${nr_dests};
-% if ops[opcode]["variable_dests"]:
- I->nr_dests = nr_dests;
-% else:
- I->nr_dests = ${ops[opcode]["dests"]};
-% for dest in range(ops[opcode]["dests"]):
+% if not op["variable_dests"]:
+% for dest in range(op["dests"]):
I->dest[${dest}] = dest${dest};
% endfor
%endif
-% if ops[opcode]["variable_srcs"]:
- I->nr_srcs = nr_srcs;
-% else:
- I->nr_srcs = ${src_count(ops[opcode])};
-% for src in range(src_count(ops[opcode])):
+% if not op["variable_srcs"]:
+% for src in range(src_count(op)):
I->src[${src}] = src${src};
% endfor
% endif
}
/* Helper to compare for logical equality of instructions. Need to skip over
- * the link, guaranteed to be first. After that we can compare raw data. */
+ * the pointers, guaranteed to be first. After that we can compare raw data.
+ */
static inline bool
bit_instr_equal(bi_instr *A, bi_instr *B)
{
- return memcmp((uint8_t *) A + sizeof(struct list_head),
- (uint8_t *) B + sizeof(struct list_head),
- sizeof(bi_instr) - sizeof(struct list_head)) == 0;
+ size_t skip = sizeof(struct list_head) + 2 * sizeof(bi_index *);
+
+ if (memcmp((uint8_t *) A + skip, (uint8_t *) B + skip, sizeof(bi_instr) - skip))
+ return false;
+
+ if (memcmp(A->dest, B->dest, sizeof(bi_index) * A->nr_dests))
+ return false;
+
+ if (memcmp(A->src, B->src, sizeof(bi_index) * A->nr_srcs))
+ return false;
+
+ return true;
}
static inline bool
}
/*
- * Temporary stopgap to check that source/destination counts are correct. This
- * validation pass will go away later this series when we dynamically allocate
- * sources and destinations.
+ * Validate that all destinations of the instruction are present.
*/
static bool
-bi_validate_src_dest_count(bi_context *ctx)
+bi_validate_dest(bi_context *ctx)
{
bool succ = true;
bi_foreach_instr_global(ctx, I) {
- for (unsigned s = I->nr_srcs; s < ARRAY_SIZE(I->src); ++s) {
- if (!bi_is_null(I->src[s])) {
- succ = false;
- fprintf(stderr,
- "unexpected source %u, expected %u sources\n",
- s, I->nr_srcs);
- bi_print_instr(I, stderr);
- fprintf(stderr, "\n");
- }
- }
-
- for (unsigned d = 0; d < ARRAY_SIZE(I->dest); ++d) {
- if ((d < I->nr_dests) == bi_is_null(I->dest[d])) {
+ bi_foreach_dest(I, d) {
+ if (bi_is_null(I->dest[d])) {
succ = false;
- fprintf(stderr,
- "unexpected dest %u, expected %u sources\n",
- d, I->nr_dests);
+ fprintf(stderr, "expected dest %u", d);
bi_print_instr(I, stderr);
fprintf(stderr, "\n");
}
fail = true;
}
- if (!bi_validate_src_dest_count(ctx)) {
- fprintf(stderr, "Unexpected source/dest count after %s\n", after);
+ if (!bi_validate_dest(ctx)) {
+ fprintf(stderr, "Unexpected source/dest after %s\n", after);
fail = true;
}
typedef struct {
/* Must be first */
struct list_head link;
+ bi_index *dest;
+ bi_index *src;
enum bi_opcode op;
uint8_t nr_srcs;
uint8_t nr_dests;
- /* Data flow */
- bi_index dest[BI_MAX_DESTS];
- bi_index src[BI_MAX_SRCS];
-
/* For a branch */
struct bi_block *branch_target;