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
)
36 const struct gen_device_info
*devinfo
= disasm
->devinfo
;
37 const char *last_annotation_string
= NULL
;
38 const void *last_annotation_ir
= NULL
;
40 foreach_list_typed(struct inst_group
, group
, link
, &disasm
->group_list
) {
41 struct exec_node
*next_node
= exec_node_get_next(&group
->link
);
42 if (exec_node_is_tail_sentinel(next_node
))
45 struct inst_group
*next
=
46 exec_node_data(struct inst_group
, next_node
, link
);
48 int start_offset
= group
->offset
;
49 int end_offset
= next
->offset
;
51 if (group
->block_start
) {
52 fprintf(stderr
, " START B%d", group
->block_start
->num
);
53 foreach_list_typed(struct bblock_link
, predecessor_link
, link
,
54 &group
->block_start
->parents
) {
55 struct bblock_t
*predecessor_block
= predecessor_link
->block
;
56 fprintf(stderr
, " <-B%d", predecessor_block
->num
);
58 fprintf(stderr
, " (%u cycles)\n", group
->block_start
->cycle_count
);
61 if (last_annotation_ir
!= group
->ir
) {
62 last_annotation_ir
= group
->ir
;
63 if (last_annotation_ir
) {
65 nir_print_instr(group
->ir
, stderr
);
66 fprintf(stderr
, "\n");
70 if (last_annotation_string
!= group
->annotation
) {
71 last_annotation_string
= group
->annotation
;
72 if (last_annotation_string
)
73 fprintf(stderr
, " %s\n", last_annotation_string
);
76 brw_disassemble(devinfo
, assembly
, start_offset
, end_offset
, stderr
);
79 fputs(group
->error
, stderr
);
82 if (group
->block_end
) {
83 fprintf(stderr
, " END B%d", group
->block_end
->num
);
84 foreach_list_typed(struct bblock_link
, successor_link
, link
,
85 &group
->block_end
->children
) {
86 struct bblock_t
*successor_block
= successor_link
->block
;
87 fprintf(stderr
, " ->B%d", successor_block
->num
);
89 fprintf(stderr
, "\n");
92 fprintf(stderr
, "\n");
96 disasm_initialize(const struct gen_device_info
*devinfo
,
97 const struct cfg_t
*cfg
)
99 struct disasm_info
*disasm
= ralloc(NULL
, struct disasm_info
);
100 exec_list_make_empty(&disasm
->group_list
);
101 disasm
->devinfo
= devinfo
;
103 disasm
->cur_block
= 0;
104 disasm
->use_tail
= false;
109 disasm_new_inst_group(struct disasm_info
*disasm
, unsigned next_inst_offset
)
111 struct inst_group
*tail
= rzalloc(disasm
, struct inst_group
);
112 tail
->offset
= next_inst_offset
;
113 exec_list_push_tail(&disasm
->group_list
, &tail
->link
);
118 disasm_annotate(struct disasm_info
*disasm
,
119 struct backend_instruction
*inst
, unsigned offset
)
121 const struct gen_device_info
*devinfo
= disasm
->devinfo
;
122 const struct cfg_t
*cfg
= disasm
->cfg
;
124 struct inst_group
*group
;
125 if (!disasm
->use_tail
) {
126 group
= disasm_new_inst_group(disasm
, offset
);
128 disasm
->use_tail
= false;
129 group
= exec_node_data(struct inst_group
,
130 exec_list_get_tail_raw(&disasm
->group_list
), link
);
133 if ((INTEL_DEBUG
& DEBUG_ANNOTATION
) != 0) {
134 group
->ir
= inst
->ir
;
135 group
->annotation
= inst
->annotation
;
138 if (bblock_start(cfg
->blocks
[disasm
->cur_block
]) == inst
) {
139 group
->block_start
= cfg
->blocks
[disasm
->cur_block
];
142 /* There is no hardware DO instruction on Gen6+, so since DO always
143 * starts a basic block, we need to set the .block_start of the next
144 * instruction's annotation with a pointer to the bblock started by
147 * There's also only complication from emitting an annotation without
148 * a corresponding hardware instruction to disassemble.
150 if (devinfo
->gen
>= 6 && inst
->opcode
== BRW_OPCODE_DO
) {
151 disasm
->use_tail
= true;
154 if (bblock_end(cfg
->blocks
[disasm
->cur_block
]) == inst
) {
155 group
->block_end
= cfg
->blocks
[disasm
->cur_block
];
161 disasm_insert_error(struct disasm_info
*disasm
, unsigned offset
,
164 foreach_list_typed(struct inst_group
, cur
, link
, &disasm
->group_list
) {
165 struct exec_node
*next_node
= exec_node_get_next(&cur
->link
);
166 if (exec_node_is_tail_sentinel(next_node
))
169 struct inst_group
*next
=
170 exec_node_data(struct inst_group
, next_node
, link
);
172 if (next
->offset
<= offset
)
175 if (offset
+ sizeof(brw_inst
) != next
->offset
) {
176 struct inst_group
*new = ralloc(disasm
, struct inst_group
);
177 memcpy(new, cur
, sizeof(struct inst_group
));
180 cur
->error_length
= 0;
181 cur
->block_end
= NULL
;
183 new->offset
= offset
+ sizeof(brw_inst
);
184 new->block_start
= NULL
;
186 exec_node_insert_after(&cur
->link
, &new->link
);
190 ralloc_strcat(&cur
->error
, error
);
192 cur
->error
= ralloc_strdup(disasm
, error
);