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