1 /* 2 * Copyright 2014 Intel Corporation 3 * 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: 10 * 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 13 * Software. 14 * 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 21 * IN THE SOFTWARE. 22 */ 23 24 #include "brw_cfg.h" 25 #include "brw_eu.h" 26 #include "intel_debug.h" 27 #include "intel_asm_annotation.h" 28 #include "compiler/nir/nir.h" 29 30 void 31 dump_assembly(void *assembly, int num_annotations, struct annotation *annotation, 32 const struct gen_device_info *devinfo) 33 { 34 const char *last_annotation_string = NULL; 35 const void *last_annotation_ir = NULL; 36 37 for (int i = 0; i < num_annotations; i++) { 38 int start_offset = annotation[i].offset; 39 int end_offset = annotation[i + 1].offset; 40 41 if (annotation[i].block_start) { 42 fprintf(stderr, " START B%d", annotation[i].block_start->num); 43 foreach_list_typed(struct bblock_link, predecessor_link, link, 44 &annotation[i].block_start->parents) { 45 struct bblock_t *predecessor_block = predecessor_link->block; 46 fprintf(stderr, " <-B%d", predecessor_block->num); 47 } 48 fprintf(stderr, " (%u cycles)\n", annotation[i].block_start->cycle_count); 49 } 50 51 if (last_annotation_ir != annotation[i].ir) { 52 last_annotation_ir = annotation[i].ir; 53 if (last_annotation_ir) { 54 fprintf(stderr, " "); 55 nir_print_instr(annotation[i].ir, stderr); 56 fprintf(stderr, "\n"); 57 } 58 } 59 60 if (last_annotation_string != annotation[i].annotation) { 61 last_annotation_string = annotation[i].annotation; 62 if (last_annotation_string) 63 fprintf(stderr, " %s\n", last_annotation_string); 64 } 65 66 brw_disassemble(devinfo, assembly, start_offset, end_offset, stderr); 67 68 if (annotation[i].error) { 69 fputs(annotation[i].error, stderr); 70 } 71 72 if (annotation[i].block_end) { 73 fprintf(stderr, " END B%d", annotation[i].block_end->num); 74 foreach_list_typed(struct bblock_link, successor_link, link, 75 &annotation[i].block_end->children) { 76 struct bblock_t *successor_block = successor_link->block; 77 fprintf(stderr, " ->B%d", successor_block->num); 78 } 79 fprintf(stderr, "\n"); 80 } 81 } 82 fprintf(stderr, "\n"); 83 } 84 85 static bool 86 annotation_array_ensure_space(struct annotation_info *annotation) 87 { 88 if (annotation->ann_size <= annotation->ann_count) { 89 int old_size = annotation->ann_size; 90 annotation->ann_size = MAX2(1024, annotation->ann_size * 2); 91 annotation->ann = reralloc(annotation->mem_ctx, annotation->ann, 92 struct annotation, annotation->ann_size); 93 if (!annotation->ann) 94 return false; 95 96 memset(annotation->ann + old_size, 0, 97 (annotation->ann_size - old_size) * sizeof(struct annotation)); 98 } 99 100 return true; 101 } 102 103 void annotate(const struct gen_device_info *devinfo, 104 struct annotation_info *annotation, const struct cfg_t *cfg, 105 struct backend_instruction *inst, unsigned offset) 106 { 107 if (annotation->mem_ctx == NULL) 108 annotation->mem_ctx = ralloc_context(NULL); 109 110 if (!annotation_array_ensure_space(annotation)) 111 return; 112 113 struct annotation *ann = &annotation->ann[annotation->ann_count++]; 114 ann->offset = offset; 115 if ((INTEL_DEBUG & DEBUG_ANNOTATION) != 0) { 116 ann->ir = inst->ir; 117 ann->annotation = inst->annotation; 118 } 119 120 if (bblock_start(cfg->blocks[annotation->cur_block]) == inst) { 121 ann->block_start = cfg->blocks[annotation->cur_block]; 122 } 123 124 /* There is no hardware DO instruction on Gen6+, so since DO always 125 * starts a basic block, we need to set the .block_start of the next 126 * instruction's annotation with a pointer to the bblock started by 127 * the DO. 128 * 129 * There's also only complication from emitting an annotation without 130 * a corresponding hardware instruction to disassemble. 131 */ 132 if (devinfo->gen >= 6 && inst->opcode == BRW_OPCODE_DO) { 133 annotation->ann_count--; 134 } 135 136 if (bblock_end(cfg->blocks[annotation->cur_block]) == inst) { 137 ann->block_end = cfg->blocks[annotation->cur_block]; 138 annotation->cur_block++; 139 } 140 } 141 142 void 143 annotation_finalize(struct annotation_info *annotation, 144 unsigned next_inst_offset) 145 { 146 if (!annotation->ann_count) 147 return; 148 149 if (annotation->ann_count == annotation->ann_size) { 150 annotation->ann = reralloc(annotation->mem_ctx, annotation->ann, 151 struct annotation, annotation->ann_size + 1); 152 } 153 annotation->ann[annotation->ann_count].offset = next_inst_offset; 154 } 155 156 void 157 annotation_insert_error(struct annotation_info *annotation, unsigned offset, 158 const char *error) 159 { 160 struct annotation *ann; 161 162 if (!annotation->ann_count) 163 return; 164 165 /* We may have to split an annotation, so ensure we have enough space 166 * allocated for that case up front. 167 */ 168 if (!annotation_array_ensure_space(annotation)) 169 return; 170 171 assume(annotation->ann_count > 0); 172 173 for (int i = 0; i < annotation->ann_count; i++) { 174 struct annotation *cur = &annotation->ann[i]; 175 struct annotation *next = &annotation->ann[i + 1]; 176 ann = cur; 177 178 if (next->offset <= offset) 179 continue; 180 181 if (offset + sizeof(brw_inst) != next->offset) { 182 memmove(next, cur, 183 (annotation->ann_count - i + 2) * sizeof(struct annotation)); 184 cur->error = NULL; 185 cur->error_length = 0; 186 cur->block_end = NULL; 187 next->offset = offset + sizeof(brw_inst); 188 next->block_start = NULL; 189 annotation->ann_count++; 190 } 191 break; 192 } 193 194 if (ann->error) 195 ralloc_strcat(&ann->error, error); 196 else 197 ann->error = ralloc_strdup(annotation->mem_ctx, error); 198 } 199