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 "common/gen_debug.h"
28 #include "compiler/nir/nir.h"
30 __attribute__((weak
)) void nir_print_instr(const nir_instr
*instr
, FILE *fp
) {}
33 dump_assembly(void *assembly
, struct disasm_info
*disasm
)
35 const struct gen_device_info
*devinfo
= disasm
->devinfo
;
36 const char *last_annotation_string
= NULL
;
37 const void *last_annotation_ir
= NULL
;
39 foreach_list_typed(struct inst_group
, group
, link
, &disasm
->group_list
) {
40 struct exec_node
*next_node
= exec_node_get_next(&group
->link
);
41 if (exec_node_is_tail_sentinel(next_node
))
44 struct inst_group
*next
=
45 exec_node_data(struct inst_group
, next_node
, link
);
47 int start_offset
= group
->offset
;
48 int end_offset
= next
->offset
;
50 if (group
->block_start
) {
51 fprintf(stderr
, " START B%d", group
->block_start
->num
);
52 foreach_list_typed(struct bblock_link
, predecessor_link
, link
,
53 &group
->block_start
->parents
) {
54 struct bblock_t
*predecessor_block
= predecessor_link
->block
;
55 fprintf(stderr
, " <-B%d", predecessor_block
->num
);
57 fprintf(stderr
, " (%u cycles)\n", group
->block_start
->cycle_count
);
60 if (last_annotation_ir
!= group
->ir
) {
61 last_annotation_ir
= group
->ir
;
62 if (last_annotation_ir
) {
64 nir_print_instr(group
->ir
, stderr
);
65 fprintf(stderr
, "\n");
69 if (last_annotation_string
!= group
->annotation
) {
70 last_annotation_string
= group
->annotation
;
71 if (last_annotation_string
)
72 fprintf(stderr
, " %s\n", last_annotation_string
);
75 brw_disassemble(devinfo
, assembly
, start_offset
, end_offset
, stderr
);
78 fputs(group
->error
, stderr
);
81 if (group
->block_end
) {
82 fprintf(stderr
, " END B%d", group
->block_end
->num
);
83 foreach_list_typed(struct bblock_link
, successor_link
, link
,
84 &group
->block_end
->children
) {
85 struct bblock_t
*successor_block
= successor_link
->block
;
86 fprintf(stderr
, " ->B%d", successor_block
->num
);
88 fprintf(stderr
, "\n");
91 fprintf(stderr
, "\n");
95 disasm_initialize(const struct gen_device_info
*devinfo
,
96 const struct cfg_t
*cfg
)
98 struct disasm_info
*disasm
= ralloc(NULL
, struct disasm_info
);
99 exec_list_make_empty(&disasm
->group_list
);
100 disasm
->devinfo
= devinfo
;
102 disasm
->cur_block
= 0;
103 disasm
->use_tail
= false;
108 disasm_new_inst_group(struct disasm_info
*disasm
, unsigned next_inst_offset
)
110 struct inst_group
*tail
= rzalloc(disasm
, struct inst_group
);
111 tail
->offset
= next_inst_offset
;
112 exec_list_push_tail(&disasm
->group_list
, &tail
->link
);
117 disasm_annotate(struct disasm_info
*disasm
,
118 struct backend_instruction
*inst
, unsigned offset
)
120 const struct gen_device_info
*devinfo
= disasm
->devinfo
;
121 const struct cfg_t
*cfg
= disasm
->cfg
;
123 struct inst_group
*group
;
124 if (!disasm
->use_tail
) {
125 group
= disasm_new_inst_group(disasm
, offset
);
126 disasm
->use_tail
= false;
128 group
= exec_node_data(struct inst_group
,
129 exec_list_get_tail_raw(&disasm
->group_list
), link
);
132 if ((INTEL_DEBUG
& DEBUG_ANNOTATION
) != 0) {
133 group
->ir
= inst
->ir
;
134 group
->annotation
= inst
->annotation
;
137 if (bblock_start(cfg
->blocks
[disasm
->cur_block
]) == inst
) {
138 group
->block_start
= cfg
->blocks
[disasm
->cur_block
];
141 /* There is no hardware DO instruction on Gen6+, so since DO always
142 * starts a basic block, we need to set the .block_start of the next
143 * instruction's annotation with a pointer to the bblock started by
146 * There's also only complication from emitting an annotation without
147 * a corresponding hardware instruction to disassemble.
149 if (devinfo
->gen
>= 6 && inst
->opcode
== BRW_OPCODE_DO
) {
150 disasm
->use_tail
= true;
153 if (bblock_end(cfg
->blocks
[disasm
->cur_block
]) == inst
) {
154 group
->block_end
= cfg
->blocks
[disasm
->cur_block
];
160 disasm_insert_error(struct disasm_info
*disasm
, unsigned offset
,
163 foreach_list_typed(struct inst_group
, cur
, link
, &disasm
->group_list
) {
164 struct exec_node
*next_node
= exec_node_get_next(&cur
->link
);
165 if (exec_node_is_tail_sentinel(next_node
))
168 struct inst_group
*next
=
169 exec_node_data(struct inst_group
, next_node
, link
);
171 if (next
->offset
<= offset
)
174 if (offset
+ sizeof(brw_inst
) != next
->offset
) {
175 struct inst_group
*new = ralloc(disasm
, struct inst_group
);
176 memcpy(new, cur
, sizeof(struct inst_group
));
179 cur
->error_length
= 0;
180 cur
->block_end
= NULL
;
182 new->offset
= offset
+ sizeof(brw_inst
);
183 new->block_start
= NULL
;
185 exec_node_insert_after(&cur
->link
, &new->link
);
189 ralloc_strcat(&cur
->error
, error
);
191 cur
->error
= ralloc_strdup(disasm
, error
);