1 #ifndef UTILS_H 2 #define UTILS_H 3 4 inline void break_optimization(void *arg) { 5 __asm__ __volatile__("" : : "r" (arg) : "memory"); 6 } 7 8 // Tests will instantiate this class to pad out bit sets to test out the 9 // various ways we can represent the bit set (32-bit inline, 64-bit inline, 10 // memory). Instantiating this class will trigger the instantiation of I 11 // templates with I virtual tables for classes deriving from T, I-2 of which 12 // will be of size sizeof(void*) * 5, 1 of which will be of size sizeof(void*) 13 // * 3, and 1 of which will be of size sizeof(void*) * 9. (Under the MS ABI 14 // each virtual table will be sizeof(void*) bytes smaller). Each category 15 // of virtual tables is aligned to a different power of 2, precluding the 16 // all-ones optimization. As a result, the bit vector for the base class will 17 // need to contain at least I*2 entries to accommodate all the derived virtual 18 // tables. 19 template <typename T, unsigned I> 20 struct Deriver : T { 21 Deriver() { 22 break_optimization(new Deriver<T, I-1>); 23 } 24 virtual void f() {} 25 virtual void g() {} 26 virtual void h() {} 27 }; 28 29 template <typename T> 30 struct Deriver<T, 0> : T { 31 virtual void f() {} 32 void g() {} 33 }; 34 35 template <typename T> 36 struct Deriver<T, 1> : T { 37 Deriver() { 38 break_optimization(new Deriver<T, 0>); 39 } 40 virtual void f() {} 41 virtual void g() {} 42 virtual void h() {} 43 virtual void i() {} 44 virtual void j() {} 45 virtual void k() {} 46 virtual void l() {} 47 }; 48 49 // Instantiate enough classes to force CFI checks for type T to use bit 50 // vectors of size 32 (if B32 defined), 64 (if B64 defined) or >64 (if BM 51 // defined). 52 template <typename T> 53 void create_derivers() { 54 #ifdef B32 55 break_optimization(new Deriver<T, 10>); 56 #endif 57 58 #ifdef B64 59 break_optimization(new Deriver<T, 25>); 60 #endif 61 62 #ifdef BM 63 break_optimization(new Deriver<T, 40>); 64 #endif 65 } 66 67 #endif 68