1#include "tests/malloc.h"
2#include <stdio.h>
3#include <assert.h>
4
5typedef  unsigned long long int  ULong;
6typedef  unsigned long int       UWord;
7
8__attribute__((noinline))
9static 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))
23static 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
46int
47main(int argc, char *argv[])
48{
49    char *buf = memalign16(5);
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}
87