^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include "block-range.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include "annotate.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <assert.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <stdlib.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) struct rb_root root;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) u64 blocks;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) } block_ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static void block_range__debug(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * XXX still paranoid for now; see if we can make this depend on
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * DEBUG=1 builds.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #if 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) struct rb_node *rb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) u64 old = 0; /* NULL isn't executable */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) for (rb = rb_first(&block_ranges.root); rb; rb = rb_next(rb)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) struct block_range *entry = rb_entry(rb, struct block_range, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) assert(old < entry->start);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) assert(entry->start <= entry->end); /* single instruction block; jump to a jump */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) old = entry->end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) struct block_range *block_range__find(u64 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) struct rb_node **p = &block_ranges.root.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) struct rb_node *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) struct block_range *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) while (*p != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) entry = rb_entry(parent, struct block_range, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) if (addr < entry->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) p = &parent->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) else if (addr > entry->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) p = &parent->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) return entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) static inline void rb_link_left_of_node(struct rb_node *left, struct rb_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct rb_node **p = &node->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) node = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) p = &node->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) rb_link_node(left, node, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) static inline void rb_link_right_of_node(struct rb_node *right, struct rb_node *node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) struct rb_node **p = &node->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) while (*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) node = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) p = &node->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) rb_link_node(right, node, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * block_range__create
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * @start: branch target starting this basic block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) * @end: branch ending this basic block
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * Create all the required block ranges to precisely span the given range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) struct block_range_iter block_range__create(u64 start, u64 end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) struct rb_node **p = &block_ranges.root.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct rb_node *n, *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) struct block_range *next, *entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) struct block_range_iter iter = { NULL, NULL };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) while (*p != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) entry = rb_entry(parent, struct block_range, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (start < entry->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) p = &parent->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) else if (start > entry->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) p = &parent->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * Didn't find anything.. there's a hole at @start, however @end might
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * be inside/behind the next range.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if (!*p) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if (!entry) /* tree empty */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) goto do_whole;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * If the last node is before, advance one to find the next.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) n = parent;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (entry->end < start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) n = rb_next(n);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (!n)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) goto do_whole;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) next = rb_entry(n, struct block_range, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) if (next->start <= end) { /* add head: [start...][n->start...] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct block_range *head = malloc(sizeof(struct block_range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if (!head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) *head = (struct block_range){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) .start = start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) .end = next->start - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) .is_target = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) .is_branch = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) rb_link_left_of_node(&head->node, &next->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) rb_insert_color(&head->node, &block_ranges.root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) block_range__debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) iter.start = head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) goto do_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) do_whole:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * The whole [start..end] range is non-overlapping.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) entry = malloc(sizeof(struct block_range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (!entry)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) *entry = (struct block_range){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) .start = start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) .end = end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) .is_target = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) .is_branch = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) rb_link_node(&entry->node, parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) rb_insert_color(&entry->node, &block_ranges.root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) block_range__debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) iter.start = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) iter.end = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * We found a range that overlapped with ours, split if needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) if (entry->start < start) { /* split: [e->start...][start...] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct block_range *head = malloc(sizeof(struct block_range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (!head)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) *head = (struct block_range){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) .start = entry->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) .end = start - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) .is_target = entry->is_target,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) .is_branch = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) .coverage = entry->coverage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) .entry = entry->entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) entry->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) entry->is_target = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) entry->entry = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) rb_link_left_of_node(&head->node, &entry->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) rb_insert_color(&head->node, &block_ranges.root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) block_range__debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) } else if (entry->start == start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) entry->is_target = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) iter.start = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) do_tail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) * At this point we've got: @iter.start = [@start...] but @end can still be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * inside or beyond it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) entry = iter.start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) * If @end is inside @entry, split.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (end < entry->end) { /* split: [...end][...e->end] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) struct block_range *tail = malloc(sizeof(struct block_range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if (!tail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) *tail = (struct block_range){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) .start = end + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) .end = entry->end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) .is_target = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) .is_branch = entry->is_branch,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) .coverage = entry->coverage,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) .taken = entry->taken,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) .pred = entry->pred,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) entry->end = end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) entry->is_branch = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) entry->taken = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) entry->pred = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) rb_link_right_of_node(&tail->node, &entry->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) rb_insert_color(&tail->node, &block_ranges.root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) block_range__debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) iter.end = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) * If @end matches @entry, done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) if (end == entry->end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) entry->is_branch = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) iter.end = entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) next = block_range__next(entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if (!next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) goto add_tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) * If @end is in beyond @entry but not inside @next, add tail.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (end < next->start) { /* add tail: [...e->end][...end] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct block_range *tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) add_tail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) tail = malloc(sizeof(struct block_range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) if (!tail)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) *tail = (struct block_range){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) .start = entry->end + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) .end = end,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) .is_target = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) .is_branch = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) rb_link_right_of_node(&tail->node, &entry->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) rb_insert_color(&tail->node, &block_ranges.root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) block_range__debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) iter.end = tail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) goto done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) * If there is a hole between @entry and @next, fill it.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (entry->end + 1 != next->start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) struct block_range *hole = malloc(sizeof(struct block_range));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) if (!hole)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) *hole = (struct block_range){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .start = entry->end + 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .end = next->start - 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .is_target = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .is_branch = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) rb_link_left_of_node(&hole->node, &next->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) rb_insert_color(&hole->node, &block_ranges.root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) block_range__debug();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) entry = next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) assert(iter.start->start == start && iter.start->is_target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) assert(iter.end->end == end && iter.end->is_branch);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) block_ranges.blocks++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return iter;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) * Compute coverage as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) * br->coverage / br->sym->max_coverage
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) * This ensures each symbol has a 100% spot, to reflect that each symbol has a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) * most covered section.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) * Returns [0-1] for coverage and -1 if we had no data what so ever or the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * symbol does not exist.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) double block_range__coverage(struct block_range *br)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct symbol *sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) if (!br) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) if (block_ranges.blocks)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) sym = br->sym;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (!sym)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) return (double)br->coverage / symbol__annotation(sym)->max_coverage;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) }