OSDN Git Service

Update Go library to r60.
[pf3gnuchains/gcc-fork.git] / libgo / runtime / go-reflect-chan.c
1 /* go-reflect-chan.c -- channel reflection support for Go.
2
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.  */
6
7 #include <stdlib.h>
8 #include <stdint.h>
9
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"
16
17 /* This file implements support for reflection on channels.  These
18    functions are called from reflect/value.go.  */
19
20 extern uintptr_t makechan (const struct __go_type_descriptor *, uint32_t)
21   asm ("libgo_reflect.reflect.makechan");
22
23 uintptr_t
24 makechan (const struct __go_type_descriptor *typ, uint32_t size)
25 {
26   struct __go_channel *channel;
27   void *ret;
28
29   channel = __go_new_channel (typ, size);
30
31   ret = __go_alloc (sizeof (void *));
32   __builtin_memcpy (ret, &channel, sizeof (void *));
33   return (uintptr_t) ret;
34 }
35
36 extern _Bool chansend (struct __go_channel_type *, uintptr_t, uintptr_t, _Bool)
37   asm ("libgo_reflect.reflect.chansend");
38
39 _Bool
40 chansend (struct __go_channel_type *ct, uintptr_t ch, uintptr_t val_i,
41           _Bool nb)
42 {
43   struct __go_channel *channel = (struct __go_channel *) ch;
44   uintptr_t element_size;
45   void *pv;
46
47   __go_assert (ct->__common.__code == GO_CHAN);
48   __go_assert (__go_type_descriptors_equal (ct->__element_type,
49                                             channel->element_type));
50
51   if (channel == NULL)
52     __go_panic_msg ("send to nil channel");
53
54   if (__go_is_pointer_type (channel->element_type))
55     pv = &val_i;
56   else
57     pv = (void *) val_i;
58
59   element_size = channel->element_type->__size;
60   if (element_size <= sizeof (uint64_t))
61     {
62       union
63       {
64         char b[sizeof (uint64_t)];
65         uint64_t v;
66       } u;
67
68       __builtin_memset (u.b, 0, sizeof (uint64_t));
69 #ifndef WORDS_BIGENDIAN
70       __builtin_memcpy (u.b, pv, element_size);
71 #else
72       __builtin_memcpy (u.b + sizeof (uint64_t) - element_size, pv,
73                         element_size);
74 #endif
75       if (nb)
76         return __go_send_nonblocking_small (channel, u.v);
77       else
78         {
79           __go_send_small (channel, u.v, 0);
80           return 1;
81         }
82     }
83   else
84     {
85       if (nb)
86         return __go_send_nonblocking_big (channel, pv);
87       else
88         {
89           __go_send_big (channel, pv, 0);
90           return 1;
91         }
92     }
93 }
94
95 struct chanrecv_ret
96 {
97   uintptr_t val;
98   _Bool selected;
99   _Bool received;
100 };
101
102 extern struct chanrecv_ret chanrecv (struct __go_channel_type *, uintptr_t,
103                                      _Bool)
104   asm ("libgo_reflect.reflect.chanrecv");
105
106 struct chanrecv_ret
107 chanrecv (struct __go_channel_type *ct, uintptr_t ch, _Bool nb)
108 {
109   struct __go_channel *channel = (struct __go_channel *) ch;
110   void *pv;
111   uintptr_t element_size;
112   struct chanrecv_ret ret;
113
114   __go_assert (ct->__common.__code == GO_CHAN);
115   __go_assert (__go_type_descriptors_equal (ct->__element_type,
116                                             channel->element_type));
117
118   element_size = channel->element_type->__size;
119
120   if (__go_is_pointer_type (channel->element_type))
121     pv = &ret.val;
122   else
123     {
124       pv = __go_alloc (element_size);
125       ret.val = (uintptr_t) pv;
126     }
127
128   if (element_size <= sizeof (uint64_t))
129     {
130       union
131       {
132         char b[sizeof (uint64_t)];
133         uint64_t v;
134       } u;
135
136       if (!nb)
137         {
138           u.v = __go_receive_small_closed (channel, 0, &ret.received);
139           ret.selected = 1;
140         }
141       else
142         {
143           struct __go_receive_nonblocking_small s;
144
145           s = __go_receive_nonblocking_small (channel);
146           ret.selected = s.__success || s.__closed;
147           ret.received = s.__success;
148           u.v = s.__val;
149         }
150
151 #ifndef WORDS_BIGENDIAN
152       __builtin_memcpy (pv, u.b, element_size);
153 #else
154       __builtin_memcpy (pv, u.b + sizeof (uint64_t) - element_size,
155                         element_size);
156 #endif
157     }
158   else
159     {
160       if (!nb)
161         {
162           ret.received = __go_receive_big (channel, pv, 0);
163           ret.selected = 1;
164         }
165       else
166         {
167           _Bool got;
168           _Bool closed;
169
170           got = __go_receive_nonblocking_big (channel, pv, &closed);
171           ret.selected = got || closed;
172           ret.received = got;
173         }
174     }
175
176   return ret;
177 }
178
179 extern void chanclose (uintptr_t) asm ("libgo_reflect.reflect.chanclose");
180
181 void
182 chanclose (uintptr_t ch)
183 {
184   struct __go_channel *channel = (struct __go_channel *) ch;
185
186   __go_builtin_close (channel);
187 }
188
189 extern int32_t chanlen (uintptr_t) asm ("libgo_reflect.reflect.chanlen");
190
191 int32_t
192 chanlen (uintptr_t ch)
193 {
194   struct __go_channel *channel = (struct __go_channel *) ch;
195
196   return (int32_t) __go_chan_len (channel);
197 }
198
199 extern int32_t chancap (uintptr_t) asm ("libgo_reflect.reflect.chancap");
200
201 int32_t
202 chancap (uintptr_t ch)
203 {
204   struct __go_channel *channel = (struct __go_channel *) ch;
205
206   return (int32_t) __go_chan_cap (channel);
207 }