sewardj | ff62002 | 2012-03-27 09:39:22 +0000 | [diff] [blame] | 1 | #include "tests/malloc.h" |
sewardj | da04f3e | 2012-03-08 14:51:01 +0000 | [diff] [blame] | 2 | #include <stdio.h> |
| 3 | #include <assert.h> |
| 4 | |
| 5 | typedef unsigned long long int ULong; |
| 6 | typedef unsigned long int UWord; |
| 7 | |
| 8 | __attribute__((noinline)) |
| 9 | static int my_ffsll ( ULong x ) |
| 10 | { |
| 11 | int i; |
| 12 | for (i = 0; i < 64; i++) { |
| 13 | if ((x & 1ULL) == 1ULL) |
| 14 | break; |
| 15 | x >>= 1; |
| 16 | } |
| 17 | return i+1; |
| 18 | } |
| 19 | |
| 20 | /* Find length of string, assuming it is aligned and shorter than 8 |
| 21 | characters. Little-endian only. */ |
| 22 | __attribute__((noinline)) |
| 23 | static int aligned_strlen(char *s) |
| 24 | { |
| 25 | /* This is for 64-bit platforms */ |
| 26 | assert(sizeof(ULong) == 8); |
| 27 | /* ..and only works for aligned input */ |
| 28 | assert(((unsigned long)s & 0x7) == 0); |
| 29 | |
| 30 | /* read 8 bytes */ |
| 31 | ULong val = *(ULong*)s; |
| 32 | /* Subtract one from each byte */ |
| 33 | ULong val2 = val - 0x0101010101010101ULL; |
| 34 | /* Find lowest byte whose high bit changed */ |
| 35 | val2 ^= val; |
| 36 | val2 &= 0x8080808080808080ULL; |
| 37 | |
| 38 | return (my_ffsll(val2) / 8) - 1; |
| 39 | } |
| 40 | |
| 41 | __attribute__((noinline)) void foo ( int x ) |
| 42 | { |
| 43 | __asm__ __volatile__("":::"memory"); |
| 44 | } |
| 45 | |
| 46 | int |
| 47 | main(int argc, char *argv[]) |
| 48 | { |
sewardj | ff62002 | 2012-03-27 09:39:22 +0000 | [diff] [blame] | 49 | char *buf = memalign16(5); |
sewardj | da04f3e | 2012-03-08 14:51:01 +0000 | [diff] [blame] | 50 | buf[0] = 'a'; |
| 51 | buf[1] = 'b'; |
| 52 | buf[2] = 'c'; |
| 53 | buf[3] = 'd'; |
| 54 | buf[4] = '\0'; |
| 55 | |
| 56 | /* --partial-loads-ok=no: expect addr error (here) */ |
| 57 | /* --partial-loads-ok=yes: expect no error */ |
| 58 | if (aligned_strlen(buf) == 4) |
| 59 | foo(44); |
| 60 | |
| 61 | /* --partial-loads-ok=no: expect addr error (here) */ |
| 62 | /* --partial-loads-ok=yes: expect value error (in my_ffsll) */ |
| 63 | buf[4] = 'x'; |
| 64 | if (aligned_strlen(buf) == 0) |
| 65 | foo(37); |
| 66 | |
| 67 | free(buf); |
| 68 | |
| 69 | /* Also, we need to check that a completely out-of-range, |
| 70 | word-sized load gives an addressing error regardless of the |
| 71 | start of --partial-loads-ok=. *And* that the resulting |
| 72 | value is completely defined. */ |
| 73 | UWord* words = malloc(3 * sizeof(UWord)); |
| 74 | free(words); |
| 75 | |
| 76 | /* Should ALWAYS give an addr error. */ |
| 77 | UWord w = words[1]; |
| 78 | |
| 79 | /* Should NEVER give an error (you might expect a value one, but no.) */ |
| 80 | if (w == 0x31415927) { |
| 81 | fprintf(stderr, |
| 82 | "Elvis is alive and well and living in Milton Keynes.\n"); |
| 83 | } |
| 84 | |
| 85 | return 0; |
| 86 | } |