From ed94ee97c9872c957efa4790c4ea073f371262a6 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Sun, 11 May 2008 20:50:46 -0500 Subject: [PATCH] Initial struct marshalling. Signed-off-by: Scott Wood --- doc/orb/marshalling | 25 +++- idlcomp/idlc.h | 6 +- idlcomp/languages/c++/c++.h | 6 +- idlcomp/languages/c++/main.cc | 25 +++- idlcomp/languages/c++/marshall.cc | 224 +++++++++++++++++++++++------- 5 files changed, 215 insertions(+), 71 deletions(-) diff --git a/doc/orb/marshalling b/doc/orb/marshalling index 286eff4..e62ae48 100644 --- a/doc/orb/marshalling +++ b/doc/orb/marshalling @@ -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 ----------------------- diff --git a/idlcomp/idlc.h b/idlcomp/idlc.h index a4ca39a..414d14a 100644 --- a/idlcomp/idlc.h +++ b/idlcomp/idlc.h @@ -966,7 +966,6 @@ class Array : public RefCountable // 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 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; diff --git a/idlcomp/languages/c++/c++.h b/idlcomp/languages/c++/c++.h index 9abbebd..771cba1 100644 --- a/idlcomp/languages/c++/c++.h +++ b/idlcomp/languages/c++/c++.h @@ -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. diff --git a/idlcomp/languages/c++/main.cc b/idlcomp/languages/c++/main.cc index 4368bca..3e921e5 100644 --- a/idlcomp/languages/c++/main.cc +++ b/idlcomp/languages/c++/main.cc @@ -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 . // // 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(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(*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) { diff --git a/idlcomp/languages/c++/marshall.cc b/idlcomp/languages/c++/marshall.cc index 46621fe..8ab02e0 100644 --- a/idlcomp/languages/c++/marshall.cc +++ b/idlcomp/languages/c++/marshall.cc @@ -1,6 +1,6 @@ // C++ Marshalling // -// This software is copyright (c) 2007 Scott Wood . +// This software is copyright (c) 2008 Scott Wood . // // 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 buf,\n" +#if 0 + file << indent << "__attribute__((weak)) __attribute__((unused))\n" + << indent << "void _unmarshall(::System::RunTime::Array 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; } -- 2.39.2