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
, int start_offset
, int end_offset
,
35 struct disasm_info
*disasm
, 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 void *mem_ctx
= ralloc_context(NULL
);
42 const struct brw_label
*root_label
=
43 brw_label_assembly(devinfo
, assembly
, start_offset
, end_offset
, mem_ctx
);
45 foreach_list_typed(struct inst_group
, group
, link
, &disasm
->group_list
) {
46 struct exec_node
*next_node
= exec_node_get_next(&group
->link
);
47 if (exec_node_is_tail_sentinel(next_node
))
50 struct inst_group
*next
=
51 exec_node_data(struct inst_group
, next_node
, link
);
53 int start_offset
= group
->offset
;
54 int end_offset
= next
->offset
;
56 if (group
->block_start
) {
57 fprintf(stderr
, " START B%d", group
->block_start
->num
);
58 foreach_list_typed(struct bblock_link
, predecessor_link
, link
,
59 &group
->block_start
->parents
) {
60 struct bblock_t
*predecessor_block
= predecessor_link
->block
;
61 fprintf(stderr
, " <-B%d", predecessor_block
->num
);
64 fprintf(stderr
, " (%u cycles)",
65 block_latency
[group
->block_start
->num
]);
66 fprintf(stderr
, "\n");
69 if (last_annotation_ir
!= group
->ir
) {
70 last_annotation_ir
= group
->ir
;
71 if (last_annotation_ir
) {
73 nir_print_instr(group
->ir
, stderr
);
74 fprintf(stderr
, "\n");
78 if (last_annotation_string
!= group
->annotation
) {
79 last_annotation_string
= group
->annotation
;
80 if (last_annotation_string
)
81 fprintf(stderr
, " %s\n", last_annotation_string
);
84 brw_disassemble(devinfo
, assembly
, start_offset
, end_offset
,
88 fputs(group
->error
, stderr
);
91 if (group
->block_end
) {
92 fprintf(stderr
, " END B%d", group
->block_end
->num
);
93 foreach_list_typed(struct bblock_link
, successor_link
, link
,
94 &group
->block_end
->children
) {
95 struct bblock_t
*successor_block
= successor_link
->block
;
96 fprintf(stderr
, " ->B%d", successor_block
->num
);
98 fprintf(stderr
, "\n");
101 fprintf(stderr
, "\n");
103 ralloc_free(mem_ctx
);
107 disasm_initialize(const struct gen_device_info
*devinfo
,
108 const struct cfg_t
*cfg
)
110 struct disasm_info
*disasm
= ralloc(NULL
, struct disasm_info
);
111 exec_list_make_empty(&disasm
->group_list
);
112 disasm
->devinfo
= devinfo
;
114 disasm
->cur_block
= 0;
115 disasm
->use_tail
= false;
120 disasm_new_inst_group(struct disasm_info
*disasm
, unsigned next_inst_offset
)
122 struct inst_group
*tail
= rzalloc(disasm
, struct inst_group
);
123 tail
->offset
= next_inst_offset
;
124 exec_list_push_tail(&disasm
->group_list
, &tail
->link
);
129 disasm_annotate(struct disasm_info
*disasm
,
130 struct backend_instruction
*inst
, unsigned offset
)
132 const struct gen_device_info
*devinfo
= disasm
->devinfo
;
133 const struct cfg_t
*cfg
= disasm
->cfg
;
135 struct inst_group
*group
;
136 if (!disasm
->use_tail
) {
137 group
= disasm_new_inst_group(disasm
, offset
);
139 disasm
->use_tail
= false;
140 group
= exec_node_data(struct inst_group
,
141 exec_list_get_tail_raw(&disasm
->group_list
), link
);
144 if ((INTEL_DEBUG
& DEBUG_ANNOTATION
) != 0) {
145 group
->ir
= inst
->ir
;
146 group
->annotation
= inst
->annotation
;
149 if (bblock_start(cfg
->blocks
[disasm
->cur_block
]) == inst
) {
150 group
->block_start
= cfg
->blocks
[disasm
->cur_block
];
153 /* There is no hardware DO instruction on Gen6+, so since DO always
154 * starts a basic block, we need to set the .block_start of the next
155 * instruction's annotation with a pointer to the bblock started by
158 * There's also only complication from emitting an annotation without
159 * a corresponding hardware instruction to disassemble.
161 if (devinfo
->gen
>= 6 && inst
->opcode
== BRW_OPCODE_DO
) {
162 disasm
->use_tail
= true;
165 if (bblock_end(cfg
->blocks
[disasm
->cur_block
]) == inst
) {
166 group
->block_end
= cfg
->blocks
[disasm
->cur_block
];
172 disasm_insert_error(struct disasm_info
*disasm
, unsigned offset
,
175 foreach_list_typed(struct inst_group
, cur
, link
, &disasm
->group_list
) {
176 struct exec_node
*next_node
= exec_node_get_next(&cur
->link
);
177 if (exec_node_is_tail_sentinel(next_node
))
180 struct inst_group
*next
=
181 exec_node_data(struct inst_group
, next_node
, link
);
183 if (next
->offset
<= offset
)
186 if (offset
+ sizeof(brw_inst
) != next
->offset
) {
187 struct inst_group
*new = ralloc(disasm
, struct inst_group
);
188 memcpy(new, cur
, sizeof(struct inst_group
));
191 cur
->error_length
= 0;
192 cur
->block_end
= NULL
;
194 new->offset
= offset
+ sizeof(brw_inst
);
195 new->block_start
= NULL
;
197 exec_node_insert_after(&cur
->link
, &new->link
);
201 ralloc_strcat(&cur
->error
, error
);
203 cur
->error
= ralloc_strdup(disasm
, error
);