File ‹fnptr.c›
/*
* Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
* Copyright (c) 2022 Apple Inc. All rights reserved.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
typedef unsigned word_t;
typedef unsigned (* unop_u_ptr_t)(word_t object);
unsigned odd_disp(unsigned);
unsigned even_disp(unsigned);
static const unop_u_ptr_t odd_even_dispatcher[2] = {
odd_disp,
even_disp
};
unsigned call_even_disp(word_t n) {
/* return even_disp(n);*/
unsigned f = 0;
if (n > 22) {
f = 1;
}
return (odd_even_dispatcher[f])(n - 1);
}
unsigned call1_even_disp(word_t n) {
return call_even_disp(n);
}
unsigned odd_disp(word_t n) {
return call1_even_disp(n - 1);
}
unsigned even_disp(word_t n) {
return call1_even_disp(n + 1);
}
/*
unsigned even_disp(word_t n) {
if (n==0) {
return 1;
} else {
return (odd_even_dispatcher[0])(n - 1);
}
}
unsigned odd_disp(word_t n) {
if (n==0) {
return 0;
} else {
if (n > 42) {
return (odd_even_dispatcher[1])(n - 1);
} else {
return (call_even_disp(n - 1));
}
}
}
*/
void loop(void) {loop();}
unsigned binop_u(unsigned, unsigned);
typedef typeof(binop_u) binop_u_t;
int binop(int, int);
int unop(int);
typedef typeof(binop) binop_t;
typedef typeof(unop) unop_t;
int gi = 0;
unsigned gu = 2;
typedef struct object {
binop_t * binop;
unop_t * unop;
} object_t;
typedef struct object_u {
binop_u_t * binop_u;
unop_u_ptr_t unop_u;
} object_u_t;
int const_arg(const int c) {
while (1) {
if (c <= 0) {
return (c + 1);
} else {
return (c + 2);
}
}
}
int fac(int n) {
if (n <= 0) {
return 0;
} else {
return (fac (n - 1));
}
}
unsigned odd(unsigned);
unsigned even(unsigned n) {
unsigned m = n;
if (n==0) {
return 1;
} else {
return odd(n - 1);
}
}
unsigned odd(unsigned m) {
unsigned n = m;
if (m==0) {
return 0;
} else {
return even(m - 1);
}
}
int call_fac(int n) {
return fac(n);
};
int silly(int n) {
if (n <= 0) {
exit(1);
}
return 0;
}
int call_silly(int n) {
return (silly(n));
}
int add(int n, int m) {
int k = gi;
return n + m;
}
int minus(int n, int m) {
return n - m;
}
int mul(int n, int m) {
return n * m;
}
int inc(int n) {
return n + 1;
}
int dec(int n) {
return n - 1;
}
unsigned uinc(unsigned n) {
return n + 1;
}
unsigned udec(unsigned n) {
return n - 1;
}
unsigned add_u(unsigned n, unsigned m) {
return n + m;
}
unsigned add_gu(unsigned n, unsigned m) {
return n + m + gu;
}
unsigned call_add_u(unsigned n, unsigned m) {
return add_u(n, m);
}
void inc_gu(void) {
gu = gu + 1;
}
unsigned inc_u(unsigned n) {
return n + gu;
}
static const binop_t* add_p = add;
static const binop_u_t* add_u_p = add_u;
int call_add(int i, int j) {
return add (i, j);
}
int indirect_call_add(int i, int j) {
int k = 0;
k = add_p(i, j);
return k;
}
unsigned indirect_call_add_u(unsigned i, unsigned j) {
return add_u_p(i, j);
}
enum type {ZERO, ONE, TWO, THREE, FOUR, TYPE_MAX};
static const object_t dispatcher[TYPE_MAX] = {
[ZERO] = {.binop = add, .unop = inc},
[ONE] = {.binop = minus, .unop = dec},
[TWO] = {.binop = mul, .unop = dec},
[THREE] = {.binop = minus, .unop = inc},
[FOUR] = {.binop = 0, .unop = 0}
};
int call_binop(unsigned char i, int n, int m) {
int r = 0;
if (dispatcher[i].binop != 0) {
r = dispatcher[i].binop(n, m);
}
return (r);
};
static const object_u_t dispatcher_u[2] = {
{.binop_u = add_u, .unop_u = inc_u},
{.binop_u = add_gu, .unop_u = inc_u}
};
unsigned call_binop_u(int i, unsigned n, unsigned m) {
unsigned r = 0;
r = dispatcher_u[i].binop_u(n, m);
return (r);
};
int parameter_call(binop_t *p, int n, int m) {
return(p(n,m));
}
int parameter_call_add(int n, int m) {
return parameter_call(add, n, m);
}
int nested_parameter_call(binop_t *q, int n, int m) {
return(parameter_call(q, n, m));
}
unsigned f(unsigned x) { return x + 1; }
unsigned g(unsigned);
void callthem(void)
{
g((int)f);
g((int)&f);
}
unsigned global1, global2;
void callable1(void)
{
global1++;
}
void callable2(void)
{
global2++;
}
int voidcaller(void (*pfn)(void))
{
pfn();
return 2;
}
int callvoidcaller(void)
{
return voidcaller(callable1);
}
int intcallable1(void)
{
return 3;
}
int intcallable2(void)
{
return 4;
}
int intcaller(int (*ipfn)(void))
{
return ipfn();
}
int callintcaller(void)
{
return intcaller(intcallable2);
}
int call_object_binop_return(object_t * p, int x, int y)
{
__attribute__((calls(add, minus, mul))) return p->binop(x,y);
}
int call_object_binop_assign(object_t * p, int x, int y)
{
int t1 __attribute__((calls(minus, mul))) = p->binop(x,y);
int t2 __attribute__((calls(minus, mul))) = p->binop(x,y);
return (t1 + t2);
}
int call_object_binop_emb(object_t * p, int x, int y)
{
int t __attribute__((calls(add, minus))) = add ( p->binop(x,y), p->binop(x,y)) ;
return (t + x + y);
}
typedef enum {
Success,
Error
} Return;
typedef unsigned (*myop_t_ptr)(unsigned arg1);
typedef struct object1 object1_t;
struct object1 {
myop_t_ptr unop;
};
unsigned call_object0(const object1_t * p)
{
unsigned n = 0;
[[calls(odd, even, odd_disp, even_disp)]] n = p->unop(0);
return n;
}
unsigned call_object1(const object1_t * p)
{
Return n = 0;
[[calls(odd, even, odd_disp, even_disp)]] n = p->unop(0);
return n;
}
void touch_types (void) {
object1_t x;
}