]> git.buserror.net Git - polintos/scott/priv.git/blob - idlcomp/vtable-sample.h
Initial checkin from Perforce.
[polintos/scott/priv.git] / idlcomp / vtable-sample.h
1 #include <orb.h>
2
3 struct IFaceTable {
4         unsigned char *guid;
5         ptrdiff_t offset;
6 };
7
8 namespace System {
9         struct _i_Object {
10                 static const unsigned char guid[];
11
12                 struct info_type {
13                         // The concrete field is used by the ORB to locate the
14                         // object ID (stored one word before the concrete pointer). 
15                         // The concrete field is zero except where multiple
16                         // inheritance causes there to be multiple table pointers in
17                         // the object.  When that happens, the concrete field is the
18                         // number of bytes (either 0 or negative) to add to the
19                         // pointer to yield a pointer to the most derived interface
20                         // (of which there can be only one).
21
22                         ptrdiff_t concrete;
23                         
24                         // This is a pointer to the most derived interface's
25                         // interface table, for use by a downcast method that does
26                         // not know the real type yet.
27                         
28                         ::System::RunTime::IFaceTable *concrete_IFaceTable;
29                 
30                         // A list of interfaces follows.  Each entry in the list
31                         // consists of a pointer to the GUID for the entry's
32                         // interface, followed by an offset to add to a pointer of
33                         // this interface to obtain a pointer to this entry's
34                         // interface.  This list is scanned during downcast()
35                         // operations.  The entries are used directly (no scanning)
36                         // for upcast operations, and the first entry (which must be
37                         // the for this interface) is used by the ORB to verify the
38                         // GUID of objects passed.
39                         //
40                         // The offsets must be dynamic, because an interface can
41                         // only have one pointer regardless of how many times it is
42                         // inherited by an interface's parents, and thus the pointer
43                         // adjustment will not be the same for all pointers of the
44                         // same inner interface.
45                         //
46                         // For now, this table is ordered by the for_all_supers
47                         // traversal, but eventually it'd be nice to sort it
48                         // by GUID pointer (and yes, that change will break ABI
49                         // compatibility).
50
51                         ::System::RunTime::IFaceTable System_IDLIDL_Object;
52                         
53                         // This is a NULL pointer to mark the end of the GUID
54                         // list.
55                         unsigned char *end;
56                         
57                         // Finally, the method pointers are provided.
58                         // There are currently no methods in System::Object.
59                         
60                         struct methods {
61                         } methods;
62                 };
63                 
64                 const info_type *info;
65         };
66         
67         class Object {
68                 _i_Object *_ptr;
69         
70         public:
71                 Object()
72                 {
73                         _ptr = NULL;
74                 }
75         
76                 Object(_i_Object *other)
77                 {
78                         _ptr = other;
79                 }
80                 
81                 operator _i_Object *()
82                 {
83                         return _ptr;
84                 }
85         };
86         
87
88         namespace RunTime {
89                 template<typename T> struct Array {
90                         T *ptr;
91                         size_t count;
92                 
93                         bool valid_index(size_t index)
94                         {
95                                 return index >= 0 && index < count;
96                         }
97                         
98                         T &operator[](size_t index)
99                         {
100 #ifndef NO_ARRAY_BOUNDS_CHECK
101                                 if (!valid_index(index))
102                                         throw SomeException();
103 #endif
104                 
105                                 return ptr[index];
106                         }
107                 };
108
109                 uintptr_t downcast(::System::_i_Object *obj, unsigned char *new_guid)
110                 {
111                         IFaceTable *tbl = obj->info->concrete_IFaceTable;
112                         int index = 0, found_index = -1;
113                         
114                         while (tbl->guid != new_guid) {
115                                 if (!tbl->guid)
116                                         return NULL;
117
118                                 tbl++;
119                         }
120                         
121                         uintptr_t ptr = (uintptr_t)obj;
122                         
123                         ptr += obj->info->concrete;
124                         ptr += tbl->offset;
125                         
126                         return ptr;
127                 };
128         };
129
130         struct NotifierInfo {
131         };
132 };
133
134 namespace System { 
135 namespace IO {
136         struct NotifierInfo : public ::System::NotifierInfo {
137                 uint64_t len;
138                 
139                 // Yuck.  Hack to work around broken enum-scoping and 
140                 // undefined enum-width.
141                 struct result {
142                         static const uint32_t Success = 0;
143                         static const uint32_t NoMoreData = 1;
144                         static const uint32_t NoMoreSpace = 2;
145                         static const uint32_t IOError = 3;
146                         static const uint32_t BadHandle = 4;
147                         static const uint32_t PipeClosed = 5;
148                         
149                         // Double yuck... Is there any sane way to avoid exposing
150                         // a leading underscore to the user, without potential conflicts
151                         // with enum values?  Perhaps "enumval" could be made a reserved
152                         // word...
153                         uint32_t _val;
154                 } result;
155         };
156
157         // Note the absence of "virtual"...  We don't want to use the
158         // compiler's virtual table implementation, as we can't rely on it
159         // to be compatible with any other language or compiler (or even
160         // other versions of itself), and we also need the object ID to be
161         // at a specific offset from the pointer.  We manage all virtual
162         // table operations (including RTTI) ourselves.  Note that it is
163         // an error if the compiler emits a virtual table (or anything
164         // else not asked for) for any reason.
165
166         // Unfortunately, this could deprive some compilers of optimization
167         // information (such as for inlining when the concrete type is known
168         // and the implementation is present in the same compilation unit).
169         // A compiler which explicitly supports our standard vtable layout
170         // could use alternate stub code that makes use of such support.
171         
172         struct _i_IStream {
173                 static const unsigned char guid[];
174         
175                 struct info_type {
176                         // The info struct from the closest superinterface
177                         // which shares this pointer is included first.
178                         ::System::_i_Object::info_type parent;
179
180                         struct iface_table {
181                                 IFaceTable System_IDLIDL_IO_IDLIDL_IStream;
182                                 IFaceTable System_IDLIDL_Object;
183                                 unsigned char *_end;
184                         } iface_table;
185
186                         struct methods {
187                                 void (*read)(::System::IO::_i_IStream *_this, 
188                                              Array<char> *buf, uint64_t *len);
189                                 
190                                 void (*read_async)(::System::IO::_i_IStream *_this,
191                                                    Array<unsigned char> *buf,
192                                                    ::System::Notifier *notifier);
193                         } methods;
194                 } info;
195         };
196         
197         class IStream {
198                 _i_IStream *_ptr;
199         
200         public:
201                 void read(unsigned char &*buf, size_t &_count_buf, uint64_t &len)
202                 {
203                         _ptr->info->methods.read(this, buf, _count_buf, len);
204                 };
205
206                 void read_async(unsigned char *buf, size_t _count_buf,
207                                 ::System::Notifier *notifier)
208                 {
209                         _ptr->info->methods.read_async(this, buf, _count_buf, notifier);
210                 };
211                 
212                 IStream()
213                 {
214                         _ptr = NULL;
215                 }
216         
217                 IStream(_i_IStream *other)
218                 {
219                         _ptr = other;
220                 }
221                 
222                 operator _i_IStream *()
223                 {
224                         return _ptr;
225                 }
226
227                 // Returns NULL if the downcast fails.  Upcasts never fail. 
228                 // "downcast" is (will be) a reserved word in IDL, or at least
229                 // in the C++ binding.
230
231                 static IStream downcast(::System::Object oldptr)
232                 {
233                         return IStream(reinterpret_cast<_i_IStream *>
234                                 (::System::RunTime::downcast(oldptr, _i_IStream::guid)));
235                 }
236                 
237                 operator ::System::Object()
238                 {
239                         uintptr_t ptr = reinterpret_cast<uintptr_t>(this);
240                         ptr += _ptr->info->System_IDLIDL_Object.offset;
241                         return ::System::Object(reinterpret_cast<::System::_i_Object *>(ptr));
242                 }
243         };
244
245         struct OStream {
246                 static const unsigned char guid[];
247         
248                 struct info_type {
249                         ::System::Object::info parent;
250
251                         struct guid_table {
252                                 unsigned char *System_IDLIDL_IO_IDLIDL_OStream;
253                                 unsigned char *System_IDLIDL_Object;
254                                 unsigned char *_end;
255                         } guids;
256                         
257                         struct cast_table {
258                                 int32_t System_IDLIDL_IO_IDLIDL_OStream;
259                                 int32_t System_IDLIDL_Object;
260                         } casts;
261
262                         struct methods {
263                                 void (*write)(::System::IO::_i_OStream *_this, unsigned char *buf,
264                                               size_t *_count_buf, uint64_t *len);
265                                 
266                                 void (*write_async)(::System::IO::_i_OStream *this, unsigned char *buf,
267                                                     size_t count_buf, ::System::Notifier *notifier);
268                         } methods;
269                 };
270                 
271                 const info_type info;
272                 
273                 void write(unsigned char *buf, size_t _count_buf, uint64_t &len)
274                 {
275                         info->methods.write(this, buf, _count_buf, len);
276                 };
277
278                 void write_async(unsigned char *buf, size_t _count_buf,
279                                  ::System::Notifier *notifier)
280                 {
281                         info->methods.write_async(this, buf, _count_buf, notifier);
282                 };
283                 
284                 static ::System::IO::OStream *downcast(::System::Object *obj)
285                 {
286                         return (::System::IO::OStream *)
287                                 ::System::RunTime::downcast(obj, ::System::IO::OStream::guid);
288                 }
289                 
290                 ::System::Object *upcast(::System::Object *type)
291                 {
292                         uintptr_t ptr = (uintptr_t)this;
293                         ptr += info->casts.System_IDLIDL_Object;
294                         return (::System::Object *)ptr;
295                 }
296         };
297
298
299         struct _i_IOStream {
300                 static const unsigned char guid[];
301         
302                 struct info_type {
303                         // Share a pointer with the left-most superinterface
304                         ::System::IO::_i_IStream::info parent;
305
306                         struct guid_table {
307                                 unsigned char *System_IDLIDL_IO_IDLIDL_IOStream;
308                                 unsigned char *System_IDLIDL_IO_IDLIDL_IStream;
309                                 unsigned char *System_IDLIDL_IO_IDLIDL_OStream;
310                                 unsigned char *System_IDLIDL_Object;
311                                 unsigned char *_end;
312                         } guids;
313                         
314                         struct cast_table {
315                                 int32_t System_IDLIDL_IO_IDLIDL_IOStream;
316                                 int32_t System_IDLIDL_IO_IDLIDL_IStream;
317                                 int32_t System_IDLIDL_IO_IDLIDL_OStream;
318                                 int32_t System_IDLIDL_Object;
319                         } casts;
320
321                         struct methods {
322                                 void (*read)(::System::IO::_i_IStream *_this, 
323                                              Array<char> *buf, uint64_t *len);
324                                 
325                                 void (*read_async)(::System::IO::_i_IStream *_this,
326                                                    Array<unsigned char> *buf,
327                                                    ::System::Notifier *notifier);
328
329                                 void (*write)(::System::IO::_i_OStream *_this, unsigned char *buf,
330                                               size_t *_count_buf, uint64_t *len);
331                                 
332                                 void (*write_async)(::System::IO::_i_OStream *this, unsigned char *buf,
333                                                     size_t count_buf, ::System::Notifier *notifier);
334                         } methods;
335                 }
336                 
337                 const info_type *info;
338                 
339                 ::System::_i_OStream::info *info_System_IDLIDL_OStream;
340         };
341         
342         class IOStream {
343                 _i_IOStream *_ptr;
344         
345         public:
346                 void read(unsigned char &*buf, size_t &_count_buf, uint64_t &len)
347                 {
348                         info->parent.methods.read(this, buf, _count_buf, len);
349                 };
350
351                 void read_async(unsigned char *buf, size_t _count_buf,
352                                 ::System::Notifier *notifier)
353                 {
354                         info->parent.methods.read_async(this, buf, _count_buf, notifier);
355                 };
356                 
357                 void write(unsigned char *buf, size_t _count_buf, uint64_t &len)
358                 {
359                         ::System::OStream *thisptr = upcast((::System::Ostream *)NULL);
360                         info_System_IDLIDL_OStream.methods.write(this, buf, _count_buf, len);
361                 };
362
363                 void write_async(unsigned char *buf, size_t _count_buf,
364                                  ::System::Notifier *notifier)
365                 {
366                         info_System_IDLIDL_OStream.methods.write_async
367                                 (this, buf, _count_buf, notifier);
368                 };
369                 
370                 static ::System::IO::OStream *downcast(::System::Object *obj)
371                 {
372                         return (::System::IO::OStream *)
373                                 ::System::RunTime::downcast(obj, ::System::IO::OStream::guid);
374                 }
375                 
376                 ::System::Object *upcast(::System::Object *type)
377                 {
378                         uintptr_t ptr = (uintptr_t)this;
379                         ptr += info->casts.System_IDLIDL_Object;
380                         return (::System::Object *)ptr;
381                 }
382         };
383
384
385
386
387
388         
389         struct OStream : public ::System::Object {
390                 void write(unsigned char *buf, size_t _count_buf, uint64_t &len) = 0;
391         };
392         
393         struct IOStream : public IStream, OStream {
394         };
395         
396         struct FStream : public IOStream {
397                 void set_file(File *f) = 0;
398                 void get_file(File &*f) = 0;
399                 File *get_file() {
400                         File *ret;
401                         get_file(ret);
402                         return ret;
403                 };
404         };
405         
406         
407         
408         
409
410
411         class PhysAddrSpace {
412         public:
413         };
414
415         struct Region {
416                 uint64_t start, len;
417         };
418         
419         class MapHandle {
420                 void **_vtable;
421         
422         public:
423                 _inproc_MapHandle(void **vtable) : _vtable(vtable)
424                 {
425                         
426                 }
427         
428                 void unmap(Region *regions, size_t count)
429                 {
430                 }
431         };
432
433         class _remote_MapHandle : public MapHandle {
434         public:
435                 void unmap(Region *regions, size_t count)
436                 {
437                         
438                 }
439         };
440
441         // If implemented here, user supplies:
442         class RealMapHandle : public MapHandle {
443                 void unmap(Region *regions, size_t count) {
444                         whatever
445                 }
446         };
447         
448         // This goes in a footer included in a non-header after the user's
449         // header, or perhaps in an idlc-generated .cc file (which would
450         // then need to know where the user's headers are located).
451         void _entries_RealMapHandle() {
452                 // -Wno-pmf-conversions please...
453                 typedef void (*unmap)(RealMapHandle *, Region *, size_t);
454         
455                 // x86:
456                 asm volatile(".global _entry_RealMapHandle\n"
457                              "_entry_RealMapHandle:"
458                              "pushl %%eax;"
459                              "pushl %%ecx;"
460                              "jmpl %0;" : : "i" ((unmap)&RealMapHandle::MapHandle));
461
462                 // alpha:
463                 // Need to make sure that the branch is within range, or
464                 // else use jmp.
465                 asm volatile(".global _entry_RealMapHandle\n"
466                              "_entry_RealMapHandle:"
467                              "ldq $a1, 0(%sp);"
468                              "ldq $a2, 8(%sp);"
469                              "br %0;" : : "i" ((unmap)&RealMapHandle::MapHandle));
470         }
471         
472         // FIXME: probably use sections here instead of a global
473         // constructor.  This way, initialization can be ordered,
474         // and it'd be easier to extract a list of implemented
475         // classes from the binary.
476         
477         class _init_RealMapHandle() {
478         public:
479                 _init_RealMapHandle()
480                 {
481                         // register
482                 }
483                 
484                 ~_init_RealMapHandle()
485                 {
486                         // deregister -- or don't bother because it's
487                         // the end of the program and it'll be unregistered
488                         // automatically anyway?
489                 }
490         };
491         
492         _init_RealMapHandle _initinstance_RealMapHandle;
493         
494         // If not implemented here...
495         
496         class RealMapHandle : public MapHandle {
497                 void unmap(Region *regions, size_t count) {
498                         asm volatile("
499                 }
500         };
501         
502         
503         
504         
505         class Mappable {
506         public:
507                 uint64_t get_size() = 0;
508                 void get_size(uint64_t &size) = 0;
509                 
510                 uint64_t get_block_size() = 0;
511                 void get_block_size(uint64_t &block_size) = 0;
512
513                 
514         };
515 }}