2 * Copyright © 2014 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
26 #include "brw_disasm_info.h"
27 #include "dev/gen_debug.h"
28 #include "compiler/nir/nir.h"
30 __attribute__((weak
)) void nir_print_instr(UNUSED
const nir_instr
*instr
,
34 dump_assembly(void *assembly
, struct disasm_info
*disasm
,
35 const unsigned *block_latency
)
37 const struct gen_device_info
*devinfo
= disasm
->devinfo
;
38 const char *last_annotation_string
= NULL
;
39 const void *last_annotation_ir
= NULL
;
41 foreach_list_typed(struct inst_group
, group
, link
, &disasm
->group_list
) {
42 struct exec_node
*next_node
= exec_node_get_next(&group
->link
);
43 if (exec_node_is_tail_sentinel(next_node
))
46 struct inst_group
*next
=
47 exec_node_data(struct inst_group
, next_node
, link
);
49 int start_offset
= group
->offset
;
50 int end_offset
= next
->offset
;
52 if (group
->block_start
) {
53 fprintf(stderr
, " START B%d", group
->block_start
->num
);
54 foreach_list_typed(struct bblock_link
, predecessor_link
, link
,
55 &group
->block_start
->parents
) {
56 struct bblock_t
*predecessor_block
= predecessor_link
->block
;
57 fprintf(stderr
, " <-B%d", predecessor_block
->num
);
60 fprintf(stderr
, " (%u cycles)",
61 block_latency
[group
->block_start
->num
]);
62 fprintf(stderr
, "\n");
65 if (last_annotation_ir
!= group
->ir
) {
66 last_annotation_ir
= group
->ir
;
67 if (last_annotation_ir
) {
69 nir_print_instr(group
->ir
, stderr
);
70 fprintf(stderr
, "\n");
74 if (last_annotation_string
!= group
->annotation
) {
75 last_annotation_string
= group
->annotation
;
76 if (last_annotation_string
)
77 fprintf(stderr
, " %s\n", last_annotation_string
);
80 brw_disassemble(devinfo
, assembly
, start_offset
, end_offset
, stderr
);
83 fputs(group
->error
, stderr
);
86 if (group
->block_end
) {
87 fprintf(stderr
, " END B%d", group
->block_end
->num
);
88 foreach_list_typed(struct bblock_link
, successor_link
, link
,
89 &group
->block_end
->children
) {
90 struct bblock_t
*successor_block
= successor_link
->block
;
91 fprintf(stderr
, " ->B%d", successor_block
->num
);
93 fprintf(stderr
, "\n");
96 fprintf(stderr
, "\n");
100 disasm_initialize(const struct gen_device_info
*devinfo
,
101 const struct cfg_t
*cfg
)
103 struct disasm_info
*disasm
= ralloc(NULL
, struct disasm_info
);
104 exec_list_make_empty(&disasm
->group_list
);
105 disasm
->devinfo
= devinfo
;
107 disasm
->cur_block
= 0;
108 disasm
->use_tail
= false;
113 disasm_new_inst_group(struct disasm_info
*disasm
, unsigned next_inst_offset
)
115 struct inst_group
*tail
= rzalloc(disasm
, struct inst_group
);
116 tail
->offset
= next_inst_offset
;
117 exec_list_push_tail(&disasm
->group_list
, &tail
->link
);
122 disasm_annotate(struct disasm_info
*disasm
,
123 struct backend_instruction
*inst
, unsigned offset
)
125 const struct gen_device_info
*devinfo
= disasm
->devinfo
;
126 const struct cfg_t
*cfg
= disasm
->cfg
;
128 struct inst_group
*group
;
129 if (!disasm
->use_tail
) {
130 group
= disasm_new_inst_group(disasm
, offset
);
132 disasm
->use_tail
= false;
133 group
= exec_node_data(struct inst_group
,
134 exec_list_get_tail_raw(&disasm
->group_list
), link
);
137 if ((INTEL_DEBUG
& DEBUG_ANNOTATION
) != 0) {
138 group
->ir
= inst
->ir
;
139 group
->annotation
= inst
->annotation
;
142 if (bblock_start(cfg
->blocks
[disasm
->cur_block
]) == inst
) {
143 group
->block_start
= cfg
->blocks
[disasm
->cur_block
];
146 /* There is no hardware DO instruction on Gen6+, so since DO always
147 * starts a basic block, we need to set the .block_start of the next
148 * instruction's annotation with a pointer to the bblock started by
151 * There's also only complication from emitting an annotation without
152 * a corresponding hardware instruction to disassemble.
154 if (devinfo
->gen
>= 6 && inst
->opcode
== BRW_OPCODE_DO
) {
155 disasm
->use_tail
= true;
158 if (bblock_end(cfg
->blocks
[disasm
->cur_block
]) == inst
) {
159 group
->block_end
= cfg
->blocks
[disasm
->cur_block
];
165 disasm_insert_error(struct disasm_info
*disasm
, unsigned offset
,
168 foreach_list_typed(struct inst_group
, cur
, link
, &disasm
->group_list
) {
169 struct exec_node
*next_node
= exec_node_get_next(&cur
->link
);
170 if (exec_node_is_tail_sentinel(next_node
))
173 struct inst_group
*next
=
174 exec_node_data(struct inst_group
, next_node
, link
);
176 if (next
->offset
<= offset
)
179 if (offset
+ sizeof(brw_inst
) != next
->offset
) {
180 struct inst_group
*new = ralloc(disasm
, struct inst_group
);
181 memcpy(new, cur
, sizeof(struct inst_group
));
184 cur
->error_length
= 0;
185 cur
->block_end
= NULL
;
187 new->offset
= offset
+ sizeof(brw_inst
);
188 new->block_start
= NULL
;
190 exec_node_insert_after(&cur
->link
, &new->link
);
194 ralloc_strcat(&cur
->error
, error
);
196 cur
->error
= ralloc_strdup(disasm
, error
);