2011-10-08 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / libgo / runtime / go-reflect-chan.c
blob6f6693b6b54a61d3abba059a70a7cd3359e18d50
1 /* go-reflect-chan.c -- channel reflection support for Go.
3 Copyright 2009 The Go Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style
5 license that can be found in the LICENSE file. */
7 #include <stdlib.h>
8 #include <stdint.h>
10 #include "config.h"
11 #include "go-alloc.h"
12 #include "go-assert.h"
13 #include "go-panic.h"
14 #include "go-type.h"
15 #include "channel.h"
17 /* This file implements support for reflection on channels. These
18 functions are called from reflect/value.go. */
20 extern uintptr_t makechan (const struct __go_type_descriptor *, uint32_t)
21 asm ("libgo_reflect.reflect.makechan");
23 uintptr_t
24 makechan (const struct __go_type_descriptor *typ, uint32_t size)
26 struct __go_channel *channel;
27 void *ret;
29 channel = __go_new_channel (typ, size);
31 ret = __go_alloc (sizeof (void *));
32 __builtin_memcpy (ret, &channel, sizeof (void *));
33 return (uintptr_t) ret;
36 extern _Bool chansend (struct __go_channel_type *, uintptr_t, uintptr_t, _Bool)
37 asm ("libgo_reflect.reflect.chansend");
39 _Bool
40 chansend (struct __go_channel_type *ct, uintptr_t ch, uintptr_t val_i,
41 _Bool nb)
43 struct __go_channel *channel = (struct __go_channel *) ch;
44 uintptr_t element_size;
45 void *pv;
47 __go_assert (ct->__common.__code == GO_CHAN);
49 if (__go_is_pointer_type (ct->__element_type))
50 pv = &val_i;
51 else
52 pv = (void *) val_i;
54 element_size = ct->__element_type->__size;
55 if (element_size <= sizeof (uint64_t))
57 union
59 char b[sizeof (uint64_t)];
60 uint64_t v;
61 } u;
63 __builtin_memset (u.b, 0, sizeof (uint64_t));
64 #ifndef WORDS_BIGENDIAN
65 __builtin_memcpy (u.b, pv, element_size);
66 #else
67 __builtin_memcpy (u.b + sizeof (uint64_t) - element_size, pv,
68 element_size);
69 #endif
70 if (nb)
71 return __go_send_nonblocking_small (channel, u.v);
72 else
74 __go_send_small (channel, u.v, 0);
75 return 1;
78 else
80 if (nb)
81 return __go_send_nonblocking_big (channel, pv);
82 else
84 __go_send_big (channel, pv, 0);
85 return 1;
90 struct chanrecv_ret
92 uintptr_t val;
93 _Bool selected;
94 _Bool received;
97 extern struct chanrecv_ret chanrecv (struct __go_channel_type *, uintptr_t,
98 _Bool)
99 asm ("libgo_reflect.reflect.chanrecv");
101 struct chanrecv_ret
102 chanrecv (struct __go_channel_type *ct, uintptr_t ch, _Bool nb)
104 struct __go_channel *channel = (struct __go_channel *) ch;
105 void *pv;
106 uintptr_t element_size;
107 struct chanrecv_ret ret;
109 __go_assert (ct->__common.__code == GO_CHAN);
111 element_size = ct->__element_type->__size;
113 if (__go_is_pointer_type (ct->__element_type))
114 pv = &ret.val;
115 else
117 pv = __go_alloc (element_size);
118 ret.val = (uintptr_t) pv;
121 if (element_size <= sizeof (uint64_t))
123 union
125 char b[sizeof (uint64_t)];
126 uint64_t v;
127 } u;
129 if (!nb)
131 u.v = __go_receive_small_closed (channel, 0, &ret.received);
132 ret.selected = 1;
134 else
136 struct __go_receive_nonblocking_small s;
138 s = __go_receive_nonblocking_small (channel);
139 ret.selected = s.__success || s.__closed;
140 ret.received = s.__success;
141 u.v = s.__val;
144 #ifndef WORDS_BIGENDIAN
145 __builtin_memcpy (pv, u.b, element_size);
146 #else
147 __builtin_memcpy (pv, u.b + sizeof (uint64_t) - element_size,
148 element_size);
149 #endif
151 else
153 if (!nb)
155 ret.received = __go_receive_big (channel, pv, 0);
156 ret.selected = 1;
158 else
160 _Bool got;
161 _Bool closed;
163 got = __go_receive_nonblocking_big (channel, pv, &closed);
164 ret.selected = got || closed;
165 ret.received = got;
169 return ret;
172 extern void chanclose (uintptr_t) asm ("libgo_reflect.reflect.chanclose");
174 void
175 chanclose (uintptr_t ch)
177 struct __go_channel *channel = (struct __go_channel *) ch;
179 __go_builtin_close (channel);
182 extern int32_t chanlen (uintptr_t) asm ("libgo_reflect.reflect.chanlen");
184 int32_t
185 chanlen (uintptr_t ch)
187 struct __go_channel *channel = (struct __go_channel *) ch;
189 return (int32_t) __go_chan_len (channel);
192 extern int32_t chancap (uintptr_t) asm ("libgo_reflect.reflect.chancap");
194 int32_t
195 chancap (uintptr_t ch)
197 struct __go_channel *channel = (struct __go_channel *) ch;
199 return (int32_t) __go_chan_cap (channel);