diff options
author | Uli Schlachter <psychon@znc.in> | 2011-08-24 12:47:16 +0200 |
---|---|---|
committer | Peter Harris <pharris@opentext.com> | 2011-08-24 10:28:49 -0400 |
commit | aa02096b8e7f94ad3c998a8d5af54963ee860b13 (patch) | |
tree | b32be331d88adc6c4ad489941aedf6569baa10de /src | |
parent | 4f25ee16443b29e1a25bd26a724e1e0a577e21ff (diff) |
Compute alignment correctly
The code previously assumed that everything has to be aligned to a 4 byte
boundary. This assumption is wrong as e.g. the STR struct from xproto shows.
Instead, each type has to be aligned to its natural alignment. So a char doesn't
need any alignment, a INT16 gets aligned to a 2-byte-boundary and a INT32 gets
the old 4 byte alignment.
I'm not 100% sure that this commit is correct, but some quick tests with awesome
and cairo-xcb went well.
This commit causes lots of dead assignments to xcb_align_to since only the last
field's alignment is actually used, but this simplified this patch a lot.
Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=34037
Signed-off-by: Uli Schlachter <psychon@znc.in>
Signed-off-by: Peter Harris <pharris@opentext.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/c_client.py | 12 |
1 files changed, 11 insertions, 1 deletions
diff --git a/src/c_client.py b/src/c_client.py index ef245c5..7a27c1f 100644 --- a/src/c_client.py +++ b/src/c_client.py @@ -171,6 +171,7 @@ def c_open(self): _c('#include <stdlib.h>') _c('#include <string.h>') _c('#include <assert.h>') + _c('#include <stddef.h> /* for offsetof() */') _c('#include "xcbext.h"') _c('#include "%s.h"', _ns.header) @@ -183,6 +184,9 @@ def c_open(self): _h('extern "C" {') _h('#endif') + _h('') + _h('#define ALIGNOF(type) offsetof(struct { char dummy; type member; }, member)') + if _ns.is_ext: _h('') _h('#define XCB_%s_MAJOR_VERSION %s', _ns.ext_name.upper(), _ns.major_version) @@ -637,7 +641,7 @@ def get_serialize_params(context, self, buffer_var='_buffer', aux_var='_aux'): def _c_serialize_helper_insert_padding(context, code_lines, space, postpone): code_lines.append('%s /* insert padding */' % space) - code_lines.append('%s xcb_pad = -xcb_block_len & 3;' % space) + code_lines.append('%s xcb_pad = -xcb_block_len & (xcb_align_to - 1);' % space) # code_lines.append('%s printf("automatically inserting padding: %%%%d\\n", xcb_pad);' % space) code_lines.append('%s xcb_buffer_len += xcb_block_len + xcb_pad;' % space) @@ -993,6 +997,8 @@ def _c_serialize_helper_fields(context, self, code_lines.append('%s xcb_parts_idx++;' % space) count += 1 + code_lines.append('%s xcb_align_to = ALIGNOF(%s);' % (space, 'char' if field.c_field_type == 'void' else field.c_field_type)) + need_padding = True if self.var_followed_by_fixed_fields: need_padding = False @@ -1100,9 +1106,11 @@ def _c_serialize(context, self): _c(' %s *xcb_out = *_buffer;', self.c_type) _c(' unsigned int xcb_out_pad = -sizeof(%s) & 3;', self.c_type) _c(' unsigned int xcb_buffer_len = sizeof(%s) + xcb_out_pad;', self.c_type) + _c(' unsigned int xcb_align_to;') else: _c(' char *xcb_out = *_buffer;') _c(' unsigned int xcb_buffer_len = 0;') + _c(' unsigned int xcb_align_to;') prefix = [('_aux', '->', self)] aux_ptr = 'xcb_out' @@ -1125,6 +1133,7 @@ def _c_serialize(context, self): _c(' unsigned int xcb_buffer_len = 0;') _c(' unsigned int xcb_block_len = 0;') _c(' unsigned int xcb_pad = 0;') + _c(' unsigned int xcb_align_to;') elif 'sizeof' == context: param_names = [p[2] for p in params] @@ -1169,6 +1178,7 @@ def _c_serialize(context, self): _c(' unsigned int xcb_buffer_len = 0;') _c(' unsigned int xcb_block_len = 0;') _c(' unsigned int xcb_pad = 0;') + _c(' unsigned int xcb_align_to;') _c('') for t in temp_vars: |