#include "tests/malloc.h" #include <stdio.h> #include <assert.h> typedef unsigned long long int ULong; typedef unsigned long int UWord; __attribute__((noinline)) static int my_ffsll ( ULong x ) { int i; for (i = 0; i < 64; i++) { if ((x & 1ULL) == 1ULL) break; x >>= 1; } return i+1; } /* Find length of string, assuming it is aligned and shorter than 8 characters. Little-endian only. */ __attribute__((noinline)) static int aligned_strlen(char *s) { /* This is for 64-bit platforms */ assert(sizeof(ULong) == 8); /* ..and only works for aligned input */ assert(((unsigned long)s & 0x7) == 0); /* read 8 bytes */ ULong val = *(ULong*)s; /* Subtract one from each byte */ ULong val2 = val - 0x0101010101010101ULL; /* Find lowest byte whose high bit changed */ val2 ^= val; val2 &= 0x8080808080808080ULL; return (my_ffsll(val2) / 8) - 1; } __attribute__((noinline)) void foo ( int x ) { __asm__ __volatile__("":::"memory"); } int main(int argc, char *argv[]) { char *buf = memalign16(5); buf[0] = 'a'; buf[1] = 'b'; buf[2] = 'c'; buf[3] = 'd'; buf[4] = '\0'; /* --partial-loads-ok=no: expect addr error (here) */ /* --partial-loads-ok=yes: expect no error */ if (aligned_strlen(buf) == 4) foo(44); /* --partial-loads-ok=no: expect addr error (here) */ /* --partial-loads-ok=yes: expect value error (in my_ffsll) */ buf[4] = 'x'; if (aligned_strlen(buf) == 0) foo(37); free(buf); /* Also, we need to check that a completely out-of-range, word-sized load gives an addressing error regardless of the start of --partial-loads-ok=. *And* that the resulting value is completely defined. */ UWord* words = malloc(3 * sizeof(UWord)); free(words); /* Should ALWAYS give an addr error. */ UWord w = words[1]; /* Should NEVER give an error (you might expect a value one, but no.) */ if (w == 0x31415927) { fprintf(stderr, "Elvis is alive and well and living in Milton Keynes.\n"); } return 0; }