Initial struct marshalling.
authorScott Wood <scott@thor.buserror.net>
Mon, 12 May 2008 01:50:46 +0000 (20:50 -0500)
committerScott Wood <scott@thor.buserror.net>
Mon, 12 May 2008 01:50:46 +0000 (20:50 -0500)
Signed-off-by: Scott Wood <scott@thor.buserror.net>
doc/orb/marshalling
idlcomp/idlc.h
idlcomp/languages/c++/c++.h
idlcomp/languages/c++/main.cc
idlcomp/languages/c++/marshall.cc

index 286eff4115b71229c264405d93f84e60165aa156..e62ae48fe7a2a9cf584e31ab63bf8cf072c559b7 100644 (file)
@@ -39,12 +39,16 @@ objlist array.
 
 Virtual structs are prefaced with a header, which consists of
 the following, in order:
-1. 128-bit GUID of the most derived vstruct type
-2. 160-bit SHA-1 of the vstruct type info
-3. 32-bit objlist-offset of an introspection object
-4. 32-bit length of vstruct, including header, and all referenced
+1. 32-bit length of vstruct, including header, and all referenced
 data chunks, which must be contiguously appended to the vstruct body
-5. 32-bit reserved field
+2. 32-bit offset of start of actual struct
+3. 128-bit GUID of the most derived vstruct type
+5. 32-bit objlist-offset of the vstruct's object handles, the first
+of which is introspection object
+6. 32-bit length of vstruct objlist in handles
+7. 32-bit offset of an area within the vstruct where the objlist can
+be copied.
+8. 32-bit reserved field
 
 The requirement for all referenced data chunks to be contiguous with
 the vstruct means that scatter-gather and zero-copy cannot be done;
@@ -54,8 +58,15 @@ later be accessed through introspection, or be passed to another
 process that does know the derived type).  For this reason, vstructs
 should generally not be used to pass large chunks of data.
 
-The introspection object reference may be NULL; in this case, the
-SHA-1 field is ignored.
+Likewise, object handles must be preserved even if they are only
+referenced in an unknown-type portion of the vstruct.  To facilitate
+this, all handles referenced from the vstruct must be contiguous in
+the objlist (even if this means duplications), and there must be an
+area in the vstruct blob where unmarshalling code can copy the
+translated objlist.
+
+The introspection object reference at the beginning of the vstruct
+objlist may be NULL.
 
 Op1: Get Interface List
 -----------------------
index a4ca39ab0f7ebd7fa12faa4051006dc55d994843..414d14a7a08d9b2cd1c7719a09e9bc22aa828001 100644 (file)
@@ -966,7 +966,6 @@ class Array : public RefCountable<Array>
 
        // lower is [0], upper is [1]
        StrListRef dcons[2];
-       Con cons[2];
        
        // Strings for error reporting on each constant.  If the constant
        // is symbolic, then this is the fully qualified symbol name. 
@@ -977,6 +976,8 @@ class Array : public RefCountable<Array>
        StringRef strs[2];
        
 public:
+       Con cons[2];
+
        // ca is not valid until after final_analysis() is called.
        CompiledArray ca;
 
@@ -1003,8 +1004,6 @@ class Datum : public Symbol, public Def {
        bool const_init; // Datum's constant has been initialized; this is
                         // true after a successful verify_const().
        CompiledBasicType *cbt;
-       
-       ArrayRef array;
 
        int chain_traversed;
 
@@ -1036,6 +1035,7 @@ class Datum : public Symbol, public Def {
        }
 
 public:
+       ArrayRef array;
        CompiledDatum def;
        TypeRef type;
 
index 9abbebd5cc573da4cf96099dcd0a23dc7ee7c65e..771cba1ccf97f09a77fb876623cb68d9bb6a0233 100644 (file)
@@ -99,7 +99,11 @@ class CPPFile : public LangCallback {
        //// Marshalling methods
        
        void output_marshall_pass(Struct *sym, int pass);
+       void output_marshall_method(Struct *sym);
+       void output_marshall_inline_method(Struct *sym);
+       void marshall_members(Struct *sym);
 
+       void output_marshall_array(Datum *d);
        void output_marshall(Struct *sym, Datum *d);
        void output_marshall(Interface *sym, Datum *d);
        void output_marshall(Enum *sym, Datum *d);
@@ -108,7 +112,7 @@ class CPPFile : public LangCallback {
        void output_marshall(CompiledBasicType &cbt, Datum *d);
 
        void align_type(Symbol *sym);
-       void grow_buf(Symbol *sym);
+       void grow_buf();
 
        // Output the downcast and implicit upcast methods for
        // the given interface/superinterface pair.
index 4368bca4d95bbddb9e56ced6a98dad3c490bfbcd..3e921e5eb94f9a236381ca76535380faed9fa9b2 100644 (file)
@@ -1,5 +1,8 @@
 // idlcomp/languages/c++/main.cc -- C++ IDL binding
 //
+// A lot of the complexity in here would just go away if C++ could handle
+// out-of-order declarations.
+//
 // This software is copyright (c) 2006 Scott Wood <scott@buserror.net>.
 // 
 // This software is provided 'as-is', without any express or implied warranty.
@@ -258,8 +261,13 @@ void cpp_output_type(ostream &file, Type *t, bool array, bool is_mutable)
 
        cpp_output_name(file, t);
 
-       if (array)
+       if (array) {
+               Struct *str = dynamic_cast<Struct *>(t);
+               if (str)
+                       file << " *";
+               
                file << ", ::System::RunTime::ORBMM>";
+       }
 
        file << ' ';
 }
@@ -306,7 +314,7 @@ int CPPFile::output_datum(Struct *ns, Datum *d, int offset)
                                !d->def.flags.field.Immutable);
 
                Struct *dtype = dynamic_cast<Struct *>(*d->type);
-               if (dtype && !dtype->is_inline())
+               if (dtype && !dtype->is_inline() && !d->is_array())
                        file << '*';
        } else {
                cpp_output_type(file, d->def.basictype,
@@ -636,6 +644,10 @@ void CPPFile::output(Struct *sym, int pass, void *arg2)
 {
        switch (pass) {
                case trav_nsdecl:
+                       // If indent level is not zero, this is a nested struct or interface.
+                       if (indent.indent_level == 0)
+                               output_pass(sym, trav_forward);
+
                        if (sym->is_virtual()) {
                                output_nsdecl_begin(sym);
                                output_nsdecl_children(sym);
@@ -720,12 +732,14 @@ void CPPFile::output(Struct *sym, int pass, void *arg2)
                                        output_struct_ctor(sym, true);
                        }
                        
-                       output_marshall_pass(sym, trav_full);
-
                        upscope();
                        file << indent << "};\n";
-       
+
                        ns_out(sym);
+
+                       all_ns_in(sym, true, "MARSHALL_");
+                       output_marshall_pass(sym, trav_full);
+                       all_ns_out(sym, true);
                        
                        output_aliases_and_types(sym);
                        
@@ -1011,7 +1025,6 @@ void CPPFile::output(BitField *sym, int pass, void *arg2)
        }
 }
 
-
 void CPPFile::output(Enum *sym, int pass, void *arg2)
 {
        switch (pass) {
index 46621fed92db8b5e371042d83961a3cdb43f5821..8ab02e0bbc786189a1483316571ba0db55496dbb 100644 (file)
@@ -1,6 +1,6 @@
 // C++ Marshalling
 //
-// This software is copyright (c) 2007 Scott Wood <scott@buserror.net>.
+// This software is copyright (c) 2008 Scott Wood <scott@buserror.net>.
 // 
 // This software is provided 'as-is', without any express or implied warranty.
 // In no event will the authors or contributors be held liable for any damages
@@ -31,60 +31,150 @@ void CPPFile::output_ifaceinfo(Interface *iface)
             << indent << "};\n";
 }
 
-void CPPFile::output_marshall(CompiledBasicType &cbt, Datum *d)
-{
-       printf("marshall cbt\n");
-}
-
 void CPPFile::align_type(Symbol *sym)
 {
-       file << indent << "_ctx.buf.align_to(__alignof__(";
+       file << '\n'
+            << indent << "ctx.buf.align_to(__alignof__(";
        cpp_output_name(file, sym);
        file << "));\n";
 }
 
-void CPPFile::grow_buf(Symbol *sym)
+void CPPFile::grow_buf()
+{
+       file << indent << "ptr = ctx.buf.grow_by(len);\n";
+}
+
+void CPPFile::marshall_members(Struct *sym)
+{
+       for (Struct::entries_iterator i = sym->entries_begin();
+            i != sym->entries_end(); ++i)
+       {
+               Datum *member = *i;
+               
+               if (member->type)
+                       member->type->output_lang(this, trav_marshall, member);
+               else
+                       output_marshall(member->def.basictype, member);
+       }
+}
+
+void CPPFile::output_marshall_array(Datum *d)
+{
+       file << '\n' 
+            << indent << "ctx.buf.align_to(__alignof__(*data->" << **d->name << ".ptr));\n"
+            << indent << "len = data->" << **d->name
+                      << ".count * sizeof(*data->" << **d->name << ".ptr);\n";
+
+       grow_buf();
+
+       file << indent << "memcpy(ptr, data->" << **d->name << ".ptr, len);\n";
+}
+
+void CPPFile::output_marshall_method(Struct *sym)
 {
-       file << indent << "_ptr = _ctx.buf.grow_by(sizeof(";
+       file << indent << "__attribute__((weak)) __attribute__((unused))\n"
+            << indent << "void *_marshall(::System::RunTime::MarshCtx &ctx, ";
        cpp_output_name(file, sym);
-       file << "));\n";
+       file << " *data, ";
+       cpp_output_name(file, sym);
+       file << " **link)\n"
+            << indent << "{\n";
+
+       indent.indent_level++;
+
+       file << indent;
+       cpp_output_name(file, sym);
+       file << " *sptr;\n"
+            << indent << "void *ptr;\n"
+            << indent << "size_t len;\n"
+            << indent << "__attribute__((unused)) size_t i = 0;\n";
+
+       align_type(sym);
+       file << indent << "*link = (";
+       cpp_output_name(file, sym);
+       file << " *)ctx.buf.count;\n";
+       file << indent << "len = sizeof(*data);\n";
+       grow_buf();
+       
+       file << indent << "memcpy(ptr, data, len);\n"
+            << indent << "sptr = (";
+       cpp_output_name(file, sym);
+       file << " *)ptr;\n";
+
+       marshall_members(sym);
+       indent.indent_level--;
+
+       file << indent << "\treturn 0;\n"
+            << indent << "}\n\n";
 }
 
-void CPPFile::output_marshall(Struct *sym, Datum *d)
+void CPPFile::output_marshall_inline_method(Struct *sym)
 {
-       bool is_inline = !d || d->is_inline();
+       file << indent << "__attribute__((weak)) __attribute__((unused))\n"
+            << indent << "void *_marshall_inline(::System::RunTime::MarshCtx &ctx, ";
+       cpp_output_name(file, sym);
+       file << " *data, ";
+       cpp_output_name(file, sym);
+       file << " *sptr)\n"
+            << indent << "{\n";
 
-       if (d && !d->is_inline())       {
-               extra_newline();
-               file << indent << "if (" << **d->name << ")\n"
-                    << indent << '\t' << **d->name << "->_marshall(_ctx);\n";
+       indent.indent_level++;
 
-               return;
-       }
+       file << indent << "__attribute__((unused)) void *ptr;\n"
+            << indent << "__attribute__((unused)) size_t len;\n"
+            << indent << "__attribute__((unused)) size_t i = 0;\n";
 
-       if (!d) {
-               extra_newline();
-               align_type(sym);
-               grow_buf(sym);
+       marshall_members(sym);
+       indent.indent_level--;
+
+       file << indent << "\treturn 0;\n"
+            << indent << "}\n";
+}
+
+void CPPFile::output_marshall(Struct *sym, Datum *d)
+{
+       bool array = d->is_array(), inl = d->is_inline();
+       const char *index = "";
+       
+       file << '\n';
+
+       if (array) {
+               file << indent << "for (size_t i = 0; i < ";
                
-               file << indent << "memcpy(_ptr, this, sizeof(*this));\n";
+               if (inl)
+                       file << d->array->cons[0].con.ucon;
+               else
+                       file << "data->" << **d->name << ".count";
+               
+               file << "; i++) {\n";
+
+               indent.indent_level++;
+               index = "[i]";
        }
        
-       if (sym->is_plain_data()) {
-               printf("plain data\n");
-               return;
+       if (!inl) {
+               file << indent << "if (data->" << **d->name << index << ")\n";
+               indent.indent_level++;
        }
        
-       for (Struct::entries_iterator i = sym->entries_begin();
-            i != sym->entries_end(); ++i)
-       {
-               extra_newline();
-               Datum *d = *i;
-               
-               if (d->type)
-                       d->type->output_lang(this, trav_marshall, d);
-               else
-                       output_marshall(d->def.basictype, d);
+       file << indent;
+       cpp_output_name(file, sym);
+       file << "_ns::_marshall";
+       
+       if (inl)
+               file << "_inline(ctx, &";
+       else
+               file << "(ctx, ";
+       
+       file << "data->" << **d->name << index
+            << ", &sptr->" << **d->name << index << ");\n";
+
+       if (!inl)
+               indent.indent_level--;
+
+       if (array) {
+               indent.indent_level--;
+               file << indent << "}\n";
        }
 }
 
@@ -95,17 +185,34 @@ void CPPFile::output_marshall(Interface *sym, Datum *d)
 
 void CPPFile::output_marshall(Enum *sym, Datum *d)
 {
-       printf("marshall enum\n");
+       if (!d->is_array() || d->is_inline())
+               return;
+
+       output_marshall_array(d);
 }
 
 void CPPFile::output_marshall(BitField *sym, Datum *d)
 {
-       printf("marshall bitfield\n");
+       if (!d->is_array() || d->is_inline())
+               return;
+
+       output_marshall_array(d);
 }
 
 void CPPFile::output_marshall(BasicType *sym, Datum *d)
 {
-       printf("marshall basictype\n");
+       if (!d->is_array() || d->is_inline())
+               return;
+
+       output_marshall_array(d);
+}
+
+void CPPFile::output_marshall(CompiledBasicType &cbt, Datum *d)
+{
+       if (!d->is_array() || d->is_inline())
+               return;
+
+       output_marshall_array(d);
 }
 
 void CPPFile::output_marshall_pass(Struct *sym, int pass)
@@ -114,30 +221,39 @@ void CPPFile::output_marshall_pass(Struct *sym, int pass)
                case trav_nsdecl:
                        extra_newline();
                        
-                       file << indent << "int _marshall(::System::RunTime::MarshCtx &_ctx);\n";
-                       file << indent << "void _unmarshall(::System::RunTime::MarshCtx &_ctx);\n";
-                       break;
-
-               case trav_full:
-                       extra_newline();
+                       file << indent << "void *_marshall(::System::RunTime::MarshCtx &ctx,\n"
+                            << indent << "              ";
+                       cpp_output_name(file, sym);
+                       file << " *data, ";
+                       cpp_output_name(file, sym);
+                       file << " **link);\n";
 
-                       file << indent << "int _marshall(::System::RunTime::MarshCtx &_ctx)\n"
-                            << indent << "{\n"
-                            << indent << "\tvoid *_ptr;\n";
+                       file << indent << "void *_marshall_inline(::System::RunTime::MarshCtx &ctx,\n"
+                            << indent << "              ";
+                       cpp_output_name(file, sym);
+                       file << " *data, ";
+                       cpp_output_name(file, sym);
+                       file << " *sptr);\n";
 
-                       indent.indent_level++;
-                       output_marshall(sym, NULL);
-                       indent.indent_level--;
+                       file << indent << "void _unmarshall(::System::RunTime::MarshCtx &ctx,\n"
+                            << indent << "                 ";
+                       cpp_output_name(file, sym);
+                       file << " *data);\n";
+                       break;
 
-                       file << indent << "\treturn 0;\n"
-                            << indent << "}\n\n";
+               case trav_full:
+                       output_marshall_method(sym);
+                       output_marshall_inline_method(sym);
 
-                       file << indent << "void _unmarshall(::System::RunTime::Array<uint8_t, ::System::RunTime::ORBMM> buf,\n"
+#if 0
+                       file << indent << "__attribute__((weak)) __attribute__((unused))\n"
+                            << indent << "void _unmarshall(::System::RunTime::Array<uint8_t, ::System::RunTime::ORBMM> buf,\n"
                             << indent << "                 ::System::RunTime::Array< ::System::_i_Object *, ::System::RunTime::ORBMM> objlist,\n"
                             << indent << "                 ::System::RunTime::ParamInfoBlock::Segment *segs,\n"
                             << indent << "                 int nsegs)\n"
                             << indent << "{\n"
                             << indent << "}\n";
+#endif
 
                        break;
        }