#define LIST_IS_EMPTY(__list) \
((__list)->next == (__list))
-
+#ifndef container_of
+#define container_of(ptr, sample, member) \
+ (void *)((char *)(ptr) \
+ - ((char *)&(sample)->member - (char *)(sample)))
+#endif
+
+#define LIST_FOR_EACH_ENTRY(pos, head, member) \
+ for (pos = container_of((head)->next, pos, member); \
+ &pos->member != (head); \
+ pos = container_of(pos->member.next, pos, member))
+
+#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \
+ for (pos = container_of((head)->next, pos, member), \
+ storage = container_of(pos->member.next, pos, member); \
+ &pos->member != (head); \
+ pos = storage, storage = container_of(storage->member.next, storage, member))
#endif /*_U_DOUBLE_LIST_H_*/
if (v == NULL) {
return NULL;
}
- c_list_init(v);
+ LIST_INITHEAD(&v->head);
return v;
}
void c_node_init(struct c_node *node)
{
memset(node, 0, sizeof(struct c_node));
- c_list_init(&node->predecessors);
- c_list_init(&node->successors);
- c_list_init(&node->childs);
- c_list_init(&node->insts);
+ LIST_INITHEAD(&node->predecessors);
+ LIST_INITHEAD(&node->successors);
+ LIST_INITHEAD(&node->childs);
+ LIST_INITHEAD(&node->insts);
node->parent = NULL;
}
link = calloc(1, sizeof(struct c_node_link));
if (link == NULL)
return NULL;
- c_list_init(link);
+ LIST_INITHEAD(&link->head);
link->node = node;
return link;
}
free(pedge);
return -ENOMEM;
}
- c_list_add_tail(pedge, &predecessor->successors);
- c_list_add_tail(sedge, &successor->predecessors);
+ LIST_ADDTAIL(&pedge->head, &predecessor->successors);
+ LIST_ADDTAIL(&sedge->head, &successor->predecessors);
+
return 0;
}
int c_node_add_new_instruction_head(struct c_node *node, struct c_instruction *instruction)
{
- struct c_instruction *inst = calloc(1, sizeof(struct c_instruction));
+ struct c_instruction *inst = malloc(sizeof(struct c_instruction));
if (inst == NULL)
return -ENOMEM;
memcpy(inst, instruction, sizeof(struct c_instruction));
- c_list_add(inst, &node->insts);
+ LIST_ADD(&inst->head, &node->insts);
return 0;
}
int c_node_add_new_instruction(struct c_node *node, struct c_instruction *instruction)
{
- struct c_instruction *inst = calloc(1, sizeof(struct c_instruction));
+ struct c_instruction *inst = malloc(sizeof(struct c_instruction));
if (inst == NULL)
return -ENOMEM;
memcpy(inst, instruction, sizeof(struct c_instruction));
- c_list_add_tail(inst, &node->insts);
+ LIST_ADDTAIL(&inst->head, &node->insts);
return 0;
}
free(node);
return NULL;
}
- c_list_add_tail(node, &shader->nodes);
+ LIST_ADDTAIL(&node->head, &shader->nodes);
return node;
}
shader->type = type;
for (i = 0; i < C_FILE_COUNT; i++) {
shader->files[i].nvectors = 0;
- c_list_init(&shader->files[i].vectors);
+ LIST_INITHEAD(&shader->files[i].vectors);
}
- c_list_init(&shader->nodes);
+ LIST_INITHEAD(&shader->nodes);
c_node_init(&shader->entry);
c_node_init(&shader->end);
shader->entry.opcode = C_OPCODE_ENTRY;
v->sid = sid;
shader->files[v->file].nvectors++;
v->id = shader->nvectors++;
- c_list_add_tail(v, &shader->files[v->file].vectors);
+ LIST_ADDTAIL(&v->head, &shader->files[v->file].vectors);
return v;
out_err:
for (i = 0; i < 4; i++) {
return NULL;
}
-static void c_node_remove_link(struct c_node_link *head, struct c_node *node)
+static void c_node_remove_link(struct list_head *head, struct c_node *node)
{
struct c_node_link *link, *tmp;
- c_list_for_each_safe(link, tmp, head) {
+ LIST_FOR_EACH_ENTRY_SAFE(link, tmp, head, head) {
if (link->node == node) {
- c_list_del(link);
+ LIST_DEL(&link->head);
free(link);
}
}
struct c_instruction *i, *ni;
struct c_node_link *link, *tmp;
- c_list_for_each_safe(i, ni, &node->insts) {
- c_list_del(i);
+ LIST_FOR_EACH_ENTRY_SAFE(i, ni, &node->insts, head) {
+ LIST_DEL(&i->head);
free(i);
}
if (node->parent)
c_node_remove_link(&node->parent->childs, node);
node->parent = NULL;
- c_list_for_each_safe(link, tmp, &node->predecessors) {
+ LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->predecessors, head) {
c_node_remove_link(&link->node->successors, node);
- c_list_del(link);
+ LIST_DEL(&link->head);
free(link);
}
- c_list_for_each_safe(link, tmp, &node->successors) {
+ LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->successors, head) {
c_node_remove_link(&link->node->predecessors, node);
- c_list_del(link);
+ LIST_DEL(&link->head);
free(link);
}
- c_list_for_each_safe(link, tmp, &node->childs) {
+ LIST_FOR_EACH_ENTRY_SAFE(link, tmp, &node->childs, head) {
link->node->parent = NULL;
- c_list_del(link);
+ LIST_DEL(&link->head);
free(link);
}
}
for (i = 0; i < C_FILE_COUNT; i++) {
shader->files[i].nvectors = 0;
- c_list_for_each_safe(v, nv, &shader->files[i].vectors) {
- c_list_del(v);
+ LIST_FOR_EACH_ENTRY_SAFE(v, nv, &shader->files[i].vectors, head) {
+ LIST_DEL(&v->head);
free(v->channel[0]);
free(v->channel[1]);
free(v->channel[2]);
free(v);
}
}
- c_list_for_each_safe(n, nn, &shader->nodes) {
- c_list_del(n);
+ LIST_FOR_EACH_ENTRY_SAFE(n, nn, &shader->nodes, head) {
+ LIST_DEL(&n->head);
c_node_destroy(n);
}
memset(shader, 0, sizeof(struct c_shader));
if (entry == node || entry->visited)
return;
entry->visited = 1;
- c_list_for_each(link, &entry->successors) {
+ LIST_FOR_EACH_ENTRY(link, &entry->successors, head) {
c_shader_dfs_without_rec(link->node, node);
}
}
shader->entry.visited = 0;
shader->end.visited = 0;
- c_list_for_each(n, &shader->nodes) {
+ LIST_FOR_EACH_ENTRY(n, &shader->nodes, head) {
n->visited = 0;
}
c_shader_dfs_without_rec(&shader->entry, node);
if (node->done)
return 0;
node->done = 1;
- c_list_for_each(link, &node->predecessors) {
+ LIST_FOR_EACH_ENTRY(link, &node->predecessors, head) {
/* if we remove this predecessor can we reach the current node ? */
c_shader_dfs_without(shader, link->node);
if (node->visited == 0) {
nlink = c_node_link_new(node);
if (nlink == NULL)
return -ENOMEM;
- c_list_add_tail(nlink, &link->node->childs);
+ LIST_ADDTAIL(&nlink->head, &link->node->childs);
found = 1;
break;
}
node, node->opcode);
return -EINVAL;
}
- c_list_for_each(link, &node->predecessors) {
+ LIST_FOR_EACH_ENTRY(link, &node->predecessors, head) {
r = c_shader_build_dominator_tree_rec(shader, link->node);
if (r)
return r;
int c_shader_build_dominator_tree(struct c_shader *shader)
{
struct c_node *node;
- c_list_for_each(node, &shader->nodes) {
+ LIST_FOR_EACH_ENTRY(node, &shader->nodes, head) {
node->done = 0;
}
return c_shader_build_dominator_tree_rec(shader, &shader->end);
#ifndef R600_COMPILER_H
#define R600_COMPILER_H
+#include "util/u_double_list.h"
+
struct c_vector;
/* operand are the basic source/destination of each operation */
struct c_channel {
- struct c_channel *next;
- struct c_channel *prev;
+ struct list_head head;
unsigned vindex; /**< index in vector X,Y,Z,W (0,1,2,3) */
unsigned value; /**< immediate value 32bits */
struct c_vector *vector; /**< vector to which it belongs */
* operand into a same vector
*/
struct c_vector {
- struct c_vector *next;
- struct c_vector *prev;
+ struct list_head head;
unsigned id; /**< vector uniq id */
unsigned name; /**< semantic name */
unsigned file; /**< operand file C_FILE_* */
struct c_channel *channel[4]; /**< operands */
};
-#define c_list_init(e) do { (e)->next = e; (e)->prev = e; } while(0)
-#define c_list_add(e, h) do { (e)->next = (h)->next; (e)->prev = h; (h)->next = e; (e)->next->prev = e; } while(0)
-#define c_list_add_tail(e, h) do { (e)->next = h; (e)->prev = (h)->prev; (h)->prev = e; (e)->prev->next = e; } while(0)
-#define c_list_del(e) do { (e)->next->prev = (e)->prev; (e)->prev->next = (e)->next; c_list_init(e); } while(0)
-#define c_list_for_each(p, h) for (p = (h)->next; p != (h); p = p->next)
-#define c_list_for_each_from(p, s, h) for (p = s; p != (h); p = p->next)
-#define c_list_for_each_safe(p, n, h) for (p = (h)->next, n = p->next; p != (h); p = n, n = p->next)
-#define c_list_empty(h) ((h)->next == h)
-
-
#define C_PROGRAM_TYPE_VS 0
#define C_PROGRAM_TYPE_FS 1
#define C_PROGRAM_TYPE_COUNT 2
};
struct c_instruction {
- struct c_instruction *next, *prev;
+ struct list_head head;
unsigned nop;
struct c_op op[5];
};
struct c_node;
struct c_node_link {
- struct c_node_link *next;
- struct c_node_link *prev;
+ struct list_head head;
struct c_node *node;
};
* @childs: child nodes in the depth first walk tree
*/
struct c_node {
- struct c_node *next, *prev;
- struct c_node_link predecessors;
- struct c_node_link successors;
+ struct list_head head;
+ struct list_head predecessors;
+ struct list_head successors;
+ struct list_head childs;
struct c_node *parent;
- struct c_node_link childs;
- struct c_instruction insts;
+ struct list_head insts;
unsigned opcode;
unsigned visited;
unsigned done;
struct c_file {
unsigned nvectors;
- struct c_vector vectors;
+ struct list_head vectors;
};
struct c_shader {
unsigned nvectors;
struct c_file files[C_FILE_COUNT];
- struct c_node nodes;
+ struct list_head nodes;
struct c_node entry;
struct c_node end;
unsigned type;
unsigned j, k;
pindent(indent); fprintf(stderr, "# node %s\n", c_get_name(c_opcode_str, node->opcode));
- c_list_for_each(i, &node->insts) {
+ LIST_FOR_EACH_ENTRY(i, &node->insts, head) {
for (k = 0; k < i->nop; k++) {
pindent(indent);
fprintf(stderr, "%s", c_get_name(c_opcode_str, i->op[k].opcode));
struct c_node_link *link;
c_node_dump(node, indent);
- c_list_for_each(link, &node->childs) {
+ LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
c_shader_dump_rec(shader, link->node, indent + 1);
}
}
vi = c_shader_vector_new(shader, C_FILE_INPUT, C_SEMANTIC_VERTEXID, -1);
if (vi == NULL)
return -ENOMEM;
- c_list_for_each_safe(v, nv, &shader->files[C_FILE_INPUT].vectors) {
+ LIST_FOR_EACH_ENTRY_SAFE(v, nv, &shader->files[C_FILE_INPUT].vectors, head) {
if (v == vi)
continue;
vr = c_shader_vector_new(shader, C_FILE_RESOURCE, C_SEMANTIC_GENERIC, -1);
r = c_node_add_new_instruction_head(&shader->entry, &instruction);
if (r)
return r;
- c_list_del(v);
+ LIST_DEL(&v->head);
shader->files[C_FILE_INPUT].nvectors--;
- c_list_add_tail(v, &shader->files[C_FILE_TEMPORARY].vectors);
+ LIST_ADDTAIL(&v->head, &shader->files[C_FILE_TEMPORARY].vectors);
shader->files[C_FILE_TEMPORARY].nvectors++;
v->file = C_FILE_TEMPORARY;
}
free(rshader->gpr);
rshader->gpr = NULL;
}
- c_list_for_each_safe(n, nn, &rshader->nodes) {
- c_list_del(n);
- c_list_for_each_safe(vf, nvf, &n->vfetch) {
- c_list_del(vf);
+ LIST_FOR_EACH_ENTRY_SAFE(n, nn, &rshader->nodes, head) {
+ LIST_DEL(&n->head);
+ LIST_FOR_EACH_ENTRY_SAFE(vf, nvf, &n->vfetch, head) {
+ LIST_DEL(&vf->head);
free(vf);
}
- c_list_for_each_safe(alu, nalu, &n->alu) {
- c_list_del(alu);
+ LIST_FOR_EACH_ENTRY_SAFE(alu, nalu, &n->alu, head) {
+ LIST_DEL(&alu->head);
free(alu);
}
free(n);
memcpy(rshader->resource_format, resource_format,
rshader->nresource * sizeof(enum pipe_format));
- c_list_for_each(rnode, &rshader->nodes) {
- c_list_for_each(vfetch, &rnode->vfetch) {
+ LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
+ LIST_FOR_EACH_ENTRY(vfetch, &rnode->vfetch, head) {
const struct util_format_description *desc;
i = vfetch->cf_addr + 1;
rshader->bcode[i] &= C_SQ_VTX_WORD1_DST_SEL_X;
cid = 0;
rid = 0;
/* alloc input first */
- c_list_for_each(v, &rshader->cshader.files[C_FILE_INPUT].vectors) {
+ LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_INPUT].vectors, head) {
nv = c_vector_new();
if (nv == NULL) {
return -ENOMEM;
for (i = 0; i < C_FILE_COUNT; i++) {
if (i == C_FILE_INPUT || i == C_FILE_IMMEDIATE)
continue;
- c_list_for_each(v, &rshader->cshader.files[i].vectors) {
+ LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[i].vectors, head) {
switch (v->file) {
case C_FILE_OUTPUT:
case C_FILE_TEMPORARY:
if (rnode == NULL)
return NULL;
rnode->node = node;
- c_list_init(&rnode->vfetch);
- c_list_init(&rnode->alu);
- c_list_add_tail(rnode, &rshader->nodes);
+ LIST_INITHEAD(&rnode->vfetch);
+ LIST_INITHEAD(&rnode->alu);
+ LIST_ADDTAIL(&rnode->head, &rshader->nodes);
return rnode;
}
return 0;
if (instruction->op[0].opcode != C_OPCODE_VFETCH)
return 0;
- if (!c_list_empty(&node->alu)) {
+ if (!LIST_IS_EMPTY(&node->alu)) {
rnode = r600_shader_new_node(rshader, node->node);
if (rnode == NULL)
return -ENOMEM;
vfetch->dst[1].chan = C_SWIZZLE_Y;
vfetch->dst[2].chan = C_SWIZZLE_Z;
vfetch->dst[3].chan = C_SWIZZLE_W;
- c_list_add_tail(vfetch, &node->vfetch);
+ LIST_ADDTAIL(&vfetch->head, &node->vfetch);
node->nslot += 2;
return 0;
}
rnode = r600_shader_new_node(rshader, node);
if (rnode == NULL)
return -ENOMEM;
- c_list_for_each(instruction, &node->insts) {
+ LIST_FOR_EACH_ENTRY(instruction, &node->insts, head) {
switch (instruction->op[0].opcode) {
case C_OPCODE_VFETCH:
r = r600_shader_add_vfetch(rshader, rnode, instruction);
r = r600_node_translate(rshader, node);
if (r)
return r;
- c_list_for_each(link, &node->childs) {
+ LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
r = r600_shader_translate_rec(rshader, link->node);
if (r)
return r;
alu->alu[2].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
alu->alu[3].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
alu->alu[4].opcode = V_SQ_ALU_WORD1_OP2_SQ_OP2_INST_NOP;
- c_list_add_tail(alu, &node->alu);
+ LIST_ADDTAIL(&alu->head, &node->alu);
return alu;
}
struct r600_shader_alu *alu;
int i, j, r, comp, litteral_lastcomp = -1;
- if (!c_list_empty(&node->vfetch)) {
+ if (!LIST_IS_EMPTY(&node->vfetch)) {
rnode = r600_shader_new_node(rshader, node->node);
if (rnode == NULL) {
fprintf(stderr, "%s %d new node failed\n", __func__, __LINE__);
rshader->ncf = 0;
rshader->nslot = 0;
- c_list_for_each_safe(node, nnode, &rshader->nodes) {
- c_list_for_each_safe(alu, nalu, &node->alu) {
+ LIST_FOR_EACH_ENTRY_SAFE(node, nnode, &rshader->nodes, head) {
+ LIST_FOR_EACH_ENTRY_SAFE(alu, nalu, &node->alu, head) {
node->nslot += alu->nalu;
node->nslot += alu->nliteral >> 1;
}
node->nfetch = 0;
- c_list_for_each_safe(vfetch, nvfetch, &node->vfetch) {
+ LIST_FOR_EACH_ENTRY_SAFE(vfetch, nvfetch, &node->vfetch, head) {
node->nslot += 2;
node->nfetch += 1;
}
- if (!c_list_empty(&node->vfetch)) {
+ if (!LIST_IS_EMPTY(&node->vfetch)) {
/* fetch node need to be 16 bytes aligned*/
cf_addr += 1;
cf_addr &= 0xFFFFFFFEUL;
rshader->ncf++;
}
rshader->nslot = cf_addr;
- c_list_for_each_safe(node, nnode, &rshader->nodes) {
+ LIST_FOR_EACH_ENTRY_SAFE(node, nnode, &rshader->nodes, head) {
node->cf_addr += cf_id * 2;
}
rshader->ncf += rshader->cshader.files[C_FILE_OUTPUT].nvectors;
unsigned k;
int r;
- c_list_for_each(i, &node->insts) {
+ LIST_FOR_EACH_ENTRY(i, &node->insts, head) {
for (k = 0; k < i->nop; k++) {
switch (i->op[k].opcode) {
case C_OPCODE_SLT:
}
}
}
- c_list_for_each(link, &node->childs) {
+ LIST_FOR_EACH_ENTRY(link, &node->childs, head) {
r = r600_cshader_legalize_rec(shader, link->node);
if (r) {
return r;
rshader->bcode = malloc(rshader->ndw * 4);
if (rshader->bcode == NULL)
return -ENOMEM;
- c_list_for_each(rnode, &rshader->nodes) {
+ LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
id = rnode->cf_addr;
- c_list_for_each(vfetch, &rnode->vfetch) {
+ LIST_FOR_EACH_ENTRY(vfetch, &rnode->vfetch, head) {
r = r600_shader_vfetch_bytecode(rshader, rnode, vfetch, &id);
if (r)
return r;
}
- c_list_for_each(alu, &rnode->alu) {
+ LIST_FOR_EACH_ENTRY(alu, &rnode->alu, head) {
for (i = 0; i < alu->nalu; i++) {
r = r700_shader_alu_bytecode(rshader, rnode, &alu->alu[i], &id);
if (r)
}
}
id = 0;
- c_list_for_each(rnode, &rshader->nodes) {
+ LIST_FOR_EACH_ENTRY(rnode, &rshader->nodes, head) {
r = r700_shader_cf_node_bytecode(rshader, rnode, &id);
if (r)
return r;
}
- c_list_for_each(v, &rshader->cshader.files[C_FILE_OUTPUT].vectors) {
+ LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_OUTPUT].vectors, head) {
end = 0;
- if (v->next == &rshader->cshader.files[C_FILE_OUTPUT].vectors)
+ if (v->head.next == &rshader->cshader.files[C_FILE_OUTPUT].vectors)
end = 1;
r = r700_shader_cf_output_bytecode(rshader, v, &id, end);
if (r)
return r;
}
- c_list_for_each(v, &rshader->cshader.files[C_FILE_INPUT].vectors) {
+ LIST_FOR_EACH_ENTRY(v, &rshader->cshader.files[C_FILE_INPUT].vectors, head) {
rshader->input[rshader->ninput].gpr = rshader->ninput;
rshader->input[rshader->ninput].sid = v->sid;
rshader->input[rshader->ninput].name = v->name;
if (rpshader == NULL)
return NULL;
rpshader->type = type;
- c_list_init(&rshader->nodes);
+ LIST_INITHEAD(&rshader->nodes);
fprintf(stderr, "<<\n");
tgsi_dump(tokens, 0);
fprintf(stderr, "--------------------------------------------------------------\n");
};
struct r600_shader_vfetch {
- struct r600_shader_vfetch *next;
- struct r600_shader_vfetch *prev;
+ struct list_head head;
unsigned cf_addr;
struct r600_shader_operand src[2];
struct r600_shader_operand dst[4];
};
struct r600_shader_alu {
- struct r600_shader_alu *next;
- struct r600_shader_alu *prev;
+ struct list_head head;
unsigned nalu;
unsigned nliteral;
unsigned nconstant;
};
struct r600_shader_node {
- struct r600_shader_node *next;
- struct r600_shader_node *prev;
+ struct list_head head;
unsigned cf_id; /**< cf index (in dw) in byte code */
unsigned cf_addr; /**< instructions index (in dw) in byte code */
unsigned nslot; /**< number of slot (2 dw) needed by this node */
unsigned nfetch;
struct c_node *node; /**< compiler node from which this node originate */
- struct r600_shader_vfetch vfetch; /**< list of vfetch instructions */
- struct r600_shader_alu alu; /**< list of alu instructions */
+ struct list_head vfetch; /**< list of vfetch instructions */
+ struct list_head alu; /**< list of alu instructions */
};
struct r600_shader_io {
unsigned ncf; /**< total number of cf clauses */
unsigned nslot; /**< total number of slots (2 dw) */
unsigned flat_shade; /**< are we flat shading */
- struct r600_shader_node nodes; /**< list of node */
+ struct list_head nodes; /**< list of node */
struct r600_shader_io input[32];
struct r600_shader_io output[32];
/* TODO replace GPR by some better register allocator */