Dan Hipschman : widl: Implement NDR for struct field alignment.

Alexandre Julliard julliard at wine.codeweavers.com
Mon Sep 10 10:17:51 CDT 2007


Module: wine
Branch: master
Commit: 62fb623e14498716730eea347a999256b9707803
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=62fb623e14498716730eea347a999256b9707803

Author: Dan Hipschman <dsh at linux.ucla.edu>
Date:   Tue Sep  4 11:04:37 2007 -0700

widl: Implement NDR for struct field alignment.

---

 dlls/rpcrt4/tests/server.c   |    9 +++++++++
 dlls/rpcrt4/tests/server.idl |   10 ++++++++++
 tools/widl/typegen.c         |   40 +++++++++++++++++++++++++++++++++++++++-
 3 files changed, 58 insertions(+), 1 deletions(-)

diff --git a/dlls/rpcrt4/tests/server.c b/dlls/rpcrt4/tests/server.c
index 32735a9..b6b2565 100644
--- a/dlls/rpcrt4/tests/server.c
+++ b/dlls/rpcrt4/tests/server.c
@@ -329,6 +329,12 @@ s_sum_toplev_conf_cond(int *x, int a, int b, int c)
   return sum;
 }
 
+double
+s_sum_aligns(aligns_t *a)
+{
+  return a->c + a->i + a->s + a->d;
+}
+
 void
 s_stop(void)
 {
@@ -374,6 +380,7 @@ basic_tests(void)
   static pvectors_t pvecs = {&vec1, &pvec2};
   static sp_inner_t spi = {42};
   static sp_t sp = {-13, &spi};
+  static aligns_t aligns = {3, 4, 5, 6.0};
   pints_t pints;
   ptypes_t ptypes;
   int i1, i2, i3, *pi2, *pi3, **ppi3;
@@ -447,6 +454,8 @@ basic_tests(void)
   ok(enum_ord(E2) == 2, "RPC enum_ord\n");
   ok(enum_ord(E3) == 3, "RPC enum_ord\n");
   ok(enum_ord(E4) == 4, "RPC enum_ord\n");
+
+  ok(sum_aligns(&aligns) == 18.0, "RPC sum_aligns\n");
 }
 
 static void
diff --git a/dlls/rpcrt4/tests/server.idl b/dlls/rpcrt4/tests/server.idl
index 59c9477..0a8c0d3 100644
--- a/dlls/rpcrt4/tests/server.idl
+++ b/dlls/rpcrt4/tests/server.idl
@@ -189,5 +189,15 @@ interface IServer
   int sum_toplev_conf_2n([size_is(n * 2)] int *x, int n);
   int sum_toplev_conf_cond([size_is(c ? a : b)] int *x, int a, int b, int c);
 
+  typedef struct
+  {
+    char c;
+    int i;
+    short s;
+    double d;
+  } aligns_t;
+
+  double sum_aligns(aligns_t *a);
+
   void stop(void);
 }
diff --git a/tools/widl/typegen.c b/tools/widl/typegen.c
index 2907706..0ec03d9 100644
--- a/tools/widl/typegen.c
+++ b/tools/widl/typegen.c
@@ -98,6 +98,8 @@ const char *string_of_type(unsigned char type)
     case RPC_FC_CARRAY: return "FC_CARRAY";
     case RPC_FC_CVARRAY: return "FC_CVARRAY";
     case RPC_FC_BOGUS_ARRAY: return "FC_BOGUS_ARRAY";
+    case RPC_FC_ALIGNM4: return "RPC_FC_ALIGNM4";
+    case RPC_FC_ALIGNM8: return "RPC_FC_ALIGNM8";
     default:
         error("string_of_type: unknown type 0x%02x\n", type);
         return NULL;
@@ -682,13 +684,25 @@ static size_t write_conf_or_var_desc(FILE *file, const func_t *func, const type_
 
 static size_t fields_memsize(const var_list_t *fields, unsigned int *align)
 {
+    int have_align = FALSE;
     size_t size = 0;
     const var_t *v;
 
     if (!fields) return 0;
     LIST_FOR_EACH_ENTRY( v, fields, const var_t, entry )
-        size += type_memsize(v->type, align);
+    {
+        unsigned int falign = 0;
+        size_t fsize = type_memsize(v->type, &falign);
+        if (!have_align)
+        {
+            *align = falign;
+            have_align = TRUE;
+        }
+        size = (size + (falign - 1)) & ~(falign - 1);
+        size += fsize;
+    }
 
+    size = (size + (*align - 1)) & ~(*align - 1);
     return size;
 }
 
@@ -1508,12 +1522,36 @@ static void write_struct_members(FILE *file, const type_t *type,
                                  unsigned int *corroff, unsigned int *typestring_offset)
 {
     const var_t *field;
+    unsigned short offset = 0;
 
     if (type->fields) LIST_FOR_EACH_ENTRY( field, type->fields, const var_t, entry )
     {
         type_t *ft = field->type;
         if (!ft->declarray || !is_conformant_array(ft))
+        {
+            unsigned int align = 0;
+            size_t size = type_memsize(ft, &align);
+            if ((align - 1) & offset)
+            {
+                unsigned char fc = 0;
+                switch (align)
+                {
+                case 4:
+                    fc = RPC_FC_ALIGNM4;
+                    break;
+                case 8:
+                    fc = RPC_FC_ALIGNM8;
+                    break;
+                default:
+                    error("write_struct_members: cannot align type %d", ft->type);
+                }
+                print_file(file, 2, "0x%x,\t/* %s */\n", fc, string_of_type(fc));
+                offset = (offset + (align - 1)) & ~(align - 1);
+                *typestring_offset += 1;
+            }
             write_member_type(file, ft, field, corroff, typestring_offset);
+            offset += size;
+        }
     }
 
     write_end(file, typestring_offset);




More information about the wine-cvs mailing list