diff options
Diffstat (limited to 'validation/linear')
| -rw-r--r-- | validation/linear/bitfield-expand-deref.c | 27 | ||||
| -rw-r--r-- | validation/linear/call-basic.c | 57 | ||||
| -rw-r--r-- | validation/linear/call-builtin.c | 17 | ||||
| -rw-r--r-- | validation/linear/call-casted-pointer.c | 31 | ||||
| -rw-r--r-- | validation/linear/call-complex-pointer.c | 32 | ||||
| -rw-r--r-- | validation/linear/call-direct.c | 17 | ||||
| -rw-r--r-- | validation/linear/call-indirect.c | 15 | ||||
| -rw-r--r-- | validation/linear/call-inline.c | 18 | ||||
| -rw-r--r-- | validation/linear/degen-function.c | 13 | ||||
| -rw-r--r-- | validation/linear/deref-ptr-ptr.c | 26 | ||||
| -rw-r--r-- | validation/linear/unexamined-base-type.c | 36 |
11 files changed, 289 insertions, 0 deletions
diff --git a/validation/linear/bitfield-expand-deref.c b/validation/linear/bitfield-expand-deref.c new file mode 100644 index 00000000..7748725f --- /dev/null +++ b/validation/linear/bitfield-expand-deref.c @@ -0,0 +1,27 @@ +struct s { + int a:8; + int b:8; +}; + +int foo(void) +{ + struct s x = { .a = 12, .b = 34, }; + + return x.b; +} + +int bar(int a) +{ + struct s x = { .a = 12, .b = a, }; + + return x.b; +} + +/* + * check-name: bitfield expand deref + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-excludes: ret\..*\$12 + * check-output-contains: ret\..*\$34 + */ diff --git a/validation/linear/call-basic.c b/validation/linear/call-basic.c new file mode 100644 index 00000000..60517e2e --- /dev/null +++ b/validation/linear/call-basic.c @@ -0,0 +1,57 @@ +extern int fun(int a); + +int symbol(int a) +{ + fun(a); +} + +int pointer0(int a, int (*fun)(int)) +{ + fun(a); +} + +int pointer1(int a, int (*fun)(int)) +{ + (*fun)(a); +} + +int builtin(int a) +{ + __builtin_popcount(a); +} + +/* + * check-name: basic function calls + * check-command: test-linearize -Wno-decl $file + * + * check-output-start +symbol: +.L0: + <entry-point> + call.32 %r2 <- fun, %arg1 + ret.32 %r2 + + +pointer0: +.L2: + <entry-point> + call.32 %r5 <- %arg2, %arg1 + ret.32 %r5 + + +pointer1: +.L4: + <entry-point> + call.32 %r8 <- %arg2, %arg1 + ret.32 %r8 + + +builtin: +.L6: + <entry-point> + call.32 %r11 <- __builtin_popcount, %arg1 + ret.32 %r11 + + + * check-output-end + */ diff --git a/validation/linear/call-builtin.c b/validation/linear/call-builtin.c new file mode 100644 index 00000000..b1511359 --- /dev/null +++ b/validation/linear/call-builtin.c @@ -0,0 +1,17 @@ +typedef unsigned int u32; + +u32 ff(u32 a) { return __builtin_popcount(a); } + +u32 f0(u32 a) { return (__builtin_popcount)(a); } +u32 f1(u32 a) { return (*__builtin_popcount)(a); } // C99,C11 6.5.3.2p4 +u32 f2(u32 a) { return (**__builtin_popcount)(a); } // C99,C11 6.5.3.2p4 +u32 f3(u32 a) { return (***__builtin_popcount)(a); } // C99,C11 6.5.3.2p4 + +/* + * check-name: builtin calls + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-excludes: load + * check-output-pattern(5): call\..*__builtin_.*, %arg1 + */ diff --git a/validation/linear/call-casted-pointer.c b/validation/linear/call-casted-pointer.c new file mode 100644 index 00000000..610d6748 --- /dev/null +++ b/validation/linear/call-casted-pointer.c @@ -0,0 +1,31 @@ +typedef int (*fun_t)(void*); + +int foo(void *a, void *fun) +{ + return ((fun_t)fun)(a); +} + +int bar(void *a, void *fun) +{ + return ((int (*)(void *))fun)(a); +} + +int qux(void *a, void *fun) +{ + return (*(fun_t)fun)(a); +} + +int quz(void *a, void *fun) +{ + return (*(int (*)(void *))fun)(a); +} + +/* + * check-name: call via casted function pointer + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-excludes: load + * check-output-pattern(4): ptrcast\..* %arg2 + * check-output-pattern(4): call\..* %arg1 + */ diff --git a/validation/linear/call-complex-pointer.c b/validation/linear/call-complex-pointer.c new file mode 100644 index 00000000..ea8232f1 --- /dev/null +++ b/validation/linear/call-complex-pointer.c @@ -0,0 +1,32 @@ +int foo(int p, int (*f0)(int), int (*f1)(int), int arg) +{ + return (p ? f0 : f1)(arg); +} + +/* + * check-name: call-complex-pointer + * check-command: test-linearize -m64 -Wno-decl $file + * + * check-output-start +foo: +.L0: + <entry-point> + cbr %arg1, .L2, .L3 + +.L2: + phisrc.64 %phi1 <- %arg2 + br .L4 + +.L3: + ptrcast.64 %r5 <- (64) %arg3 + phisrc.64 %phi2 <- %r5 + br .L4 + +.L4: + phi.64 %r6 <- %phi1, %phi2 + call.32 %r7 <- %r6, %arg4 + ret.32 %r7 + + + * check-output-end + */ diff --git a/validation/linear/call-direct.c b/validation/linear/call-direct.c new file mode 100644 index 00000000..52f86306 --- /dev/null +++ b/validation/linear/call-direct.c @@ -0,0 +1,17 @@ +extern int fun(void); + +int ff(void) { return fun(); } + +int f0(void) { return (fun)(); } +int f1(void) { return (*fun)(); } // C99,C11 6.5.3.2p4 +int f2(void) { return (**fun)(); } // C99,C11 6.5.3.2p4 +int f3(void) { return (***fun)(); } // C99,C11 6.5.3.2p4 + +/* + * check-name: direct calls + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-excludes: load + * check-output-pattern(5): call\..* fun + */ diff --git a/validation/linear/call-indirect.c b/validation/linear/call-indirect.c new file mode 100644 index 00000000..1275910c --- /dev/null +++ b/validation/linear/call-indirect.c @@ -0,0 +1,15 @@ +int gg(int (*fun)(void)) { return fun(); } + +int g0(int (*fun)(void)) { return (fun)(); } +int g1(int (*fun)(void)) { return (*fun)(); } // C99,C11 6.5.3.2p4 +int g2(int (*fun)(void)) { return (**fun)(); } // C99,C11 6.5.3.2p4 +int g3(int (*fun)(void)) { return (***fun)(); } // C99,C11 6.5.3.2p4 + +/* + * check-name: indirect calls + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-excludes: load + * check-output-pattern(5): call\..* %arg1 + */ diff --git a/validation/linear/call-inline.c b/validation/linear/call-inline.c new file mode 100644 index 00000000..a33f0a1c --- /dev/null +++ b/validation/linear/call-inline.c @@ -0,0 +1,18 @@ +static inline int fun(void) { return 42; } + +int fi(void) { return fun(); } + +int i0(void) { return (fun)(); } +int i1(void) { return (*fun)(); } // C99,C11 6.5.3.2p4 +int i2(void) { return (**fun)(); } // C99,C11 6.5.3.2p4 +int i3(void) { return (***fun)(); } // C99,C11 6.5.3.2p4 + +/* + * check-name: inline calls + * check-command: test-linearize -Wno-decl $file + * + * check-output-ignore + * check-output-excludes: load + * check-output-excludes: call + * check-output-pattern(5): ret\..* \\$42 + */ diff --git a/validation/linear/degen-function.c b/validation/linear/degen-function.c index 6dd3123b..4fb2d564 100644 --- a/validation/linear/degen-function.c +++ b/validation/linear/degen-function.c @@ -4,6 +4,7 @@ typedef int (*fun_t)(int); fun_t fa(void) { return &fun; } fun_t f0(void) { return fun; } +fun_t f1(void) { return *fun; } /* * check-name: degen-function @@ -34,5 +35,17 @@ f0: ret.64 %r3 +f1: +.L4: + <entry-point> + symaddr.64 %r5 <- fun + phisrc.64 %phi3(return) <- %r5 + br .L5 + +.L5: + phi.64 %r6 <- %phi3(return) + ret.64 %r5 + + * check-output-end */ diff --git a/validation/linear/deref-ptr-ptr.c b/validation/linear/deref-ptr-ptr.c new file mode 100644 index 00000000..963acd36 --- /dev/null +++ b/validation/linear/deref-ptr-ptr.c @@ -0,0 +1,26 @@ +char *foo(char **pfmt) +{ + return ++*pfmt; +} + +/* + * check-name: deref-ptr-ptr + * check-command: test-linearize -m64 -Wno-decl $file + * + * check-output-excludes: load[^.] + * check-output-contains: load\. + * check-output-excludes: store[^.] + * check-output-contains: store\. + * + * check-output-start +foo: +.L0: + <entry-point> + load.64 %r2 <- 0[%arg1] + add.64 %r3 <- %r2, $1 + store.64 %r3 -> 0[%arg1] + ret.64 %r3 + + + * check-output-end + */ diff --git a/validation/linear/unexamined-base-type.c b/validation/linear/unexamined-base-type.c new file mode 100644 index 00000000..96aee3f0 --- /dev/null +++ b/validation/linear/unexamined-base-type.c @@ -0,0 +1,36 @@ +# define __force __attribute__((force)) + +struct s { + int a; +}; + +static int foo(struct s *s) +{ + return (*((typeof(s->a) __force *) &s->a)) & 1; +} + +static void bar(struct s *d, struct s *s1, struct s *s2) +{ + *d = *s1, *d = *s2; +} + +/* + * check-name: unexamined base type + * check-command: test-linearize -Wno-decl $file + * check-description: + * Test case for missing examine in evaluate_dereference()'s + * target base type. In this case, the loaded value has a + * a null size, giving the wrongly generated code for foo(): + * ptrcast.64 %r3 <- (64) %arg1 + * load %r4 <- 0[%r3] + * ^^^ !! WRONG !! + * cast.32 %r5 <- (0) %r4 + * ^^^ !! WRONG !! + * and.32 %r6 <- %r5, $1 + * ret.32 %r6 + * + * check-output-ignore + * check-output-excludes: load[^.] + * check-output-excludes: cast\..*(0) + * check-output-excludes: store[^.] + */ |
