bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] Add support to define structures in mig.


From: Samuel Thibault
Subject: Re: [PATCH] Add support to define structures in mig.
Date: Sat, 5 Nov 2022 22:22:29 +0100
User-agent: NeoMutt/20170609 (1.8.3)

Applied, thanks!

Flavio Cruz, le ven. 04 nov. 2022 01:29:37 -0400, a ecrit:
> Basic syntax is presented below and allows users to define
> nested structured types by using simpler or structure types as
> members. Mig will use the C padding and alignment rules to produce
> the same size as the corresponding C structures.
> 
> type timespec_t = struct {
>   uint32_t tv_sec;
>   uint32_t tv_nsec;
> };
> 
> This allows us to build stubs that are more easily adaptable to other
> architectures.
> ---
> Hi
> 
> On Thu, Nov 03, 2022 at 09:02:03AM +0100, Luca wrote:
> > Due to 64-bit gnumach compatibility, my last patches on mig forced a 4-byte
> > alignment for all data fields. IIRC it's also forced on 32 bit, so I think
> > the alignment of struct here might not be working as expected.
> 
> If the struct has alignment that is less than 4 bytes, mig will pad the
> parameter with enough chars so that it is 4 bytes aligned, see here:
> https://git.savannah.gnu.org/cgit/hurd/mig.git/tree/type.c#n162
> I also made sure the alignment is never greater than the word size so it
> will be compatible with aligning the mig request to 4 bytes.
> 
> I've updated the test case with a smaller structure to ensure it works
> with our existing size assertions in the generated code.
> 
> diff --git a/lexxer.l b/lexxer.l
> index 71f43b2..508603a 100644
> --- a/lexxer.l
> +++ b/lexxer.l
> @@ -204,6 +204,8 @@ static void doSharp(const char *body); /* process body of 
> # directives */
>  <Normal>">"          RETURN(syRAngle);
>  <Normal>"["          RETURN(syLBrack);
>  <Normal>"]"          RETURN(syRBrack);
> +<Normal>"{"          RETURN(syLCBrack);
> +<Normal>"}"          RETURN(syRCBrack);
>  <Normal>"|"          RETURN(syBar);
>  
>  <Normal>{Ident}              { yylval.identifier = strmake(yytext);
> diff --git a/parser.y b/parser.y
> index 8521a84..104f604 100644
> --- a/parser.y
> +++ b/parser.y
> @@ -84,6 +84,8 @@
>  %token       syRAngle
>  %token       syLBrack
>  %token       syRBrack
> +%token       syLCBrack
> +%token       syRCBrack
>  %token       syBar
>  
>  %token       syError                 /* lex error */
> @@ -103,6 +105,7 @@
>  
>  %type        <statement_kind> ImportIndicant
>  %type        <number> VarArrayHead ArrayHead StructHead IntExp
> +%type   <structured_type> StructList
>  %type        <type> NamedTypeSpec TransTypeSpec TypeSpec
>  %type        <type> CStringSpec
>  %type        <type> BasicTypeSpec PrevTypeSpec ArgumentType
> @@ -124,6 +127,7 @@
>  #include "type.h"
>  #include "routine.h"
>  #include "statement.h"
> +#include "utils.h"
>  
>  static const char *import_name(statement_kind_t sk);
>  
> @@ -149,6 +153,14 @@ yyerror(const char *s)
>       const_string_t outstr;
>       u_int size;             /* 0 means there is no default size */
>      } symtype;
> +    /* Holds information about a structure while parsing. */
> +    struct
> +    {
> +        /* The required alignment (in bytes) so far. */
> +        u_int type_alignment_in_bytes;
> +        /* The size of the struct in bytes so far. */
> +        u_int size_in_bytes;
> +    } structured_type;
>      routine_t *routine;
>      arg_kind_t direction;
>      argument_t *argument;
> @@ -466,11 +478,43 @@ TypeSpec                :       BasicTypeSpec
>                       |       syCaret TypeSpec
>                               { $$ = itPtrDecl($2); }
>                       |       StructHead TypeSpec
> -                             { $$ = itStructDecl($1, $2); }
> +                             { $$ = itStructArrayDecl($1, $2); }
> +                        |       syStruct syLCBrack StructList syRCBrack
> +                             { $$ = itStructDecl($3.size_in_bytes, 
> $3.type_alignment_in_bytes); }
>                       |       CStringSpec
>                               { $$ = $1; }
>                       ;
>  
> +StructList                   :       syIdentifier syIdentifier sySemi
> +{
> +    ipc_type_t *t = itPrevDecl($1);
> +    if (!t) {
> +        error("Type %s not found\n", $1);
> +    }
> +    if (!t->itInLine) {
> +        error("Type %s must be inline\n", $2);
> +    }
> +
> +    $$.type_alignment_in_bytes = t->itAlignment;
> +    $$.size_in_bytes = t->itTypeSize;
> +}
> +                     |       StructList syIdentifier syIdentifier sySemi
> +{
> +    ipc_type_t *t = itPrevDecl($2);
> +    if (!t) {
> +        error("Type %s not found\n", $2);
> +    }
> +    if (!t->itInLine) {
> +        error("Type %s must be inline\n", $2);
> +    }
> +    $$.type_alignment_in_bytes = MAX(t->itAlignment, 
> $1.type_alignment_in_bytes);
> +    int padding_bytes = 0;
> +    if ($1.size_in_bytes % t->itAlignment)
> +        padding_bytes = t->itAlignment - ($1.size_in_bytes % t->itAlignment);
> +    $$.size_in_bytes = $1.size_in_bytes + padding_bytes + t->itTypeSize;
> +}
> +                        ;
> +
>  BasicTypeSpec                :       IPCType
>  {
>      $$ = itShortDecl($1.innumber, $1.instr,
> diff --git a/tests/good/complex-types.defs b/tests/good/complex-types.defs
> index 0a5c952..58d417e 100644
> --- a/tests/good/complex-types.defs
> +++ b/tests/good/complex-types.defs
> @@ -32,9 +32,21 @@ type mach_port_array_t = array[] of mach_port_t;
>  type char_struct_t = struct[4] of char;
>  type string_t = array[256] of char;
>  
> +type simple_struct_t = struct { byte a; };
> +
> +type complex_struct_x_t = struct { simple_struct_t a; simple_struct_t b; int 
> c; };
> +
> +type complex_struct_y_t = struct { complex_struct_x_t a; byte b; };
> +
> +type complex_struct_z_t = struct { complex_struct_y_t a; int d; };
> +
>  routine callcomplex(port : mach_port_t;
>                    p : pointer_t;
>                    q : intptr_t;
>                    str : char_struct_t;
>                    strt : string_t;
> +                  simple : simple_struct_t;
> +                  x : complex_struct_x_t;
> +                  y : complex_struct_y_t;
> +                  z : complex_struct_z_t;
>                    out vec : mach_port_array_t);
> diff --git a/tests/includes/types.h b/tests/includes/types.h
> index fe70e69..2a70443 100644
> --- a/tests/includes/types.h
> +++ b/tests/includes/types.h
> @@ -31,6 +31,26 @@ typedef struct char_struct {
>  typedef char string_t[256];
>  typedef const char* const_string_t;
>  
> +typedef struct simple_struct {
> +  char a;
> +} simple_struct_t;
> +
> +typedef struct complex_struct_x {
> +  simple_struct_t a;
> +  simple_struct_t b;
> +  int c;
> +} complex_struct_x_t;
> +
> +typedef struct complex_struct_y {
> +  complex_struct_x_t a;
> +  char b;
> +} complex_struct_y_t;
> +
> +typedef struct complex_struct_z {
> +  complex_struct_y_t a;
> +  int d;
> +} complex_struct_z_t;
> +
>  static inline int8_t int_to_int8(int n) {
>    return (int8_t) n;
>  }
> diff --git a/type.c b/type.c
> index 86137ae..66944d9 100644
> --- a/type.c
> +++ b/type.c
> @@ -24,6 +24,7 @@
>   * the rights to redistribute these changes.
>   */
>  
> +#include <assert.h>
>  #include <stdio.h>
>  #include <stdlib.h>
>  
> @@ -32,6 +33,7 @@
>  #include "type.h"
>  #include "message.h"
>  #include "cpu.h"
> +#include "utils.h"
>  
>  #if word_size_in_bits == 32
>  #define      word_size_name MACH_MSG_TYPE_INTEGER_32
> @@ -45,6 +47,7 @@
>  #endif
>  #endif
>  
> +ipc_type_t *itByteType;         /* used for defining struct types */
>  ipc_type_t *itRetCodeType;   /* used for return codes */
>  ipc_type_t *itDummyType;     /* used for camelot dummy args */
>  ipc_type_t *itRequestPortType;       /* used for default Request port arg */
> @@ -52,6 +55,8 @@ ipc_type_t *itZeroReplyPortType;/* used for dummy Reply 
> port arg */
>  ipc_type_t *itRealReplyPortType;/* used for default Reply port arg */
>  ipc_type_t *itWaitTimeType;  /* used for dummy WaitTime args */
>  ipc_type_t *itMsgOptionType; /* used for dummy MsgOption args */
> +ipc_type_t *itShortType;        /* used for the short type */
> +ipc_type_t *itIntType;          /* used for the int type */
>  
>  static ipc_type_t *list = itNULL;
>  
> @@ -100,6 +105,7 @@ itAlloc(void)
>       0,                      /* u_int itTypeSize */
>       0,                      /* u_int itPadSize */
>       0,                      /* u_int itMinTypeSize */
> +     0,                      /* u_int itAlignment */
>       0,                      /* u_int itInName */
>       0,                      /* u_int itOutName */
>       0,                      /* u_int itSize */
> @@ -173,6 +179,7 @@ itCalculateSizeInfo(ipc_type_t *it)
>       it->itTypeSize = bytes;
>       it->itPadSize = 0;
>       it->itMinTypeSize = bytes;
> +     it->itAlignment = bytes;
>      }
>  
>      /* Unfortunately, these warning messages can't give a type name;
> @@ -417,10 +424,10 @@ itCheckDecl(identifier_t name, ipc_type_t *it)
>  static void
>  itPrintTrans(const ipc_type_t *it)
>  {
> -    if (!streql(it->itName, it->itUserType))
> +    if (it->itName != strNULL && it->itUserType != strNULL && 
> !streql(it->itName, it->itUserType))
>       printf("\tCUserType:\t%s\n", it->itUserType);
>  
> -    if (!streql(it->itName, it->itServerType))
> +    if (it->itName != strNULL && !streql(it->itName, it->itServerType))
>       printf("\tCServerType:\t%s\n", it->itServerType);
>  
>      if (it->itInTrans != strNULL)
> @@ -525,6 +532,7 @@ itLongDecl(u_int inname, const_string_t instr, u_int 
> outname,
>      it->itOutName = outname;
>      it->itOutNameStr = outstr;
>      it->itSize = size;
> +    it->itAlignment = MIN(word_size, size / 8);
>      if (inname == MACH_MSG_TYPE_STRING_C)
>      {
>       it->itStruct = FALSE;
> @@ -643,6 +651,7 @@ itArrayDecl(u_int number, const ipc_type_t *old)
>      it->itNumber *= number;
>      it->itStruct = FALSE;
>      it->itString = FALSE;
> +    it->itAlignment = old->itAlignment;
>  
>      itCalculateSizeInfo(it);
>      return it;
> @@ -673,7 +682,7 @@ itPtrDecl(ipc_type_t *it)
>   *   type new = struct[number] of old;
>   */
>  ipc_type_t *
> -itStructDecl(u_int number, const ipc_type_t *old)
> +itStructArrayDecl(u_int number, const ipc_type_t *old)
>  {
>      ipc_type_t *it = itResetType(itCopyType(old));
>  
> @@ -682,6 +691,48 @@ itStructDecl(u_int number, const ipc_type_t *old)
>      it->itNumber *= number;
>      it->itStruct = TRUE;
>      it->itString = FALSE;
> +    it->itAlignment = old->itAlignment;
> +
> +    itCalculateSizeInfo(it);
> +    return it;
> +}
> +
> +/*
> + *  Handles the declaration
> + *   type new = struct { type1 a1; type2 a2; ... };
> + */
> +ipc_type_t *
> +itStructDecl(u_int min_type_size_in_bytes, u_int required_alignment_in_bytes)
> +{
> +    int final_struct_bytes = min_type_size_in_bytes;
> +    if (final_struct_bytes % required_alignment_in_bytes) {
> +         final_struct_bytes += required_alignment_in_bytes - 
> (final_struct_bytes % required_alignment_in_bytes);
> +    }
> +    ipc_type_t *element_type = NULL;
> +    int number_elements = 0;
> +    // If the struct is short or int aligned, use that as the base type.
> +    switch (required_alignment_in_bytes) {
> +     case 2:
> +         element_type = itShortType;
> +         assert(final_struct_bytes % 2 == 0);
> +         number_elements = final_struct_bytes / 2;
> +         break;
> +     case 4:
> +         element_type = itIntType;
> +         assert(final_struct_bytes % 4 == 0);
> +         number_elements = final_struct_bytes / 4;
> +         break;
> +        case 1:
> +     default:
> +         element_type = itByteType;
> +         number_elements = final_struct_bytes;
> +         break;
> +    }
> +    ipc_type_t *it = itResetType(itCopyType(element_type));
> +    it->itNumber = number_elements;
> +    it->itStruct = TRUE;
> +    it->itString = FALSE;
> +    it->itAlignment = required_alignment_in_bytes;
>  
>      itCalculateSizeInfo(it);
>      return it;
> @@ -709,6 +760,7 @@ itCStringDecl(u_int count, boolean_t varying)
>      it->itVarArray = varying;
>      it->itStruct = FALSE;
>      it->itString = TRUE;
> +    it->itAlignment = itElement->itAlignment;
>  
>      itCalculateSizeInfo(it);
>      return it;
> @@ -744,6 +796,7 @@ itCIntTypeDecl(const_string_t ctype, const size_t size)
>            exit(EXIT_FAILURE);
>      }
>      it->itName = ctype;
> +    it->itAlignment = size;
>      itCalculateNameInfo(it);
>      return it;
>  }
> @@ -822,6 +875,16 @@ itMakeDeallocType(void)
>  void
>  init_type(void)
>  {
> +    itByteType = itAlloc();
> +    itByteType->itName = "unsigned char";
> +    itByteType->itInName = MACH_MSG_TYPE_BYTE;
> +    itByteType->itInNameStr = "MACH_MSG_TYPE_BYTE";
> +    itByteType->itOutName = MACH_MSG_TYPE_BYTE;
> +    itByteType->itOutNameStr = "MACH_MSG_TYPE_BYTE";
> +    itByteType->itSize = 8;
> +    itCalculateSizeInfo(itByteType);
> +    itCalculateNameInfo(itByteType);
> +
>      itRetCodeType = itAlloc();
>      itRetCodeType->itName = "kern_return_t";
>      itRetCodeType->itInName = MACH_MSG_TYPE_INTEGER_32;
> @@ -877,8 +940,10 @@ init_type(void)
>  
>      /* Define basic C integral types. */
>      itInsert("char", itCIntTypeDecl("char", sizeof_char));
> -    itInsert("short", itCIntTypeDecl("short", sizeof_short));
> -    itInsert("int", itCIntTypeDecl("int", sizeof_int));
> +    itShortType = itCIntTypeDecl("short", sizeof_short);
> +    itInsert("short", itShortType);
> +    itIntType = itCIntTypeDecl("int", sizeof_int);
> +    itInsert("int", itIntType);
>  }
>  
>  /******************************************************
> diff --git a/type.h b/type.h
> index 6cf5d63..6031ee1 100644
> --- a/type.h
> +++ b/type.h
> @@ -143,6 +143,7 @@ typedef struct ipc_type
>      u_int itTypeSize;                /* size of the C type */
>      u_int itPadSize;         /* amount of padding after data */
>      u_int itMinTypeSize;     /* minimal amount of space occupied by data */
> +    u_int itAlignment;         /* alignment required for this type */
>  
>      u_int itInName;          /* name supplied to kernel in sent msg */
>      u_int itOutName;         /* name in received msg */
> @@ -193,7 +194,8 @@ extern ipc_type_t *itResetType(ipc_type_t *it);
>  extern ipc_type_t *itVarArrayDecl(u_int number, const ipc_type_t *it);
>  extern ipc_type_t *itArrayDecl(u_int number, const ipc_type_t *it);
>  extern ipc_type_t *itPtrDecl(ipc_type_t *it);
> -extern ipc_type_t *itStructDecl(u_int number, const ipc_type_t *it);
> +extern ipc_type_t *itStructArrayDecl(u_int number, const ipc_type_t *it);
> +extern ipc_type_t *itStructDecl(u_int min_type_size_in_bytes, u_int 
> required_alignment_in_bytes);
>  extern ipc_type_t *itCStringDecl(u_int number, boolean_t varying);
>  
>  extern ipc_type_t *itRetCodeType;
> diff --git a/utils.h b/utils.h
> index a5673b0..64e2ebf 100644
> --- a/utils.h
> +++ b/utils.h
> @@ -27,8 +27,19 @@
>  #ifndef      _UTILS_H
>  #define      _UTILS_H
>  
> +#include "routine.h"
> +
>  /* stuff used by more than one of header.c, user.c, server.c */
>  
> +#define MAX(a,b) \
> +  ({ __typeof__ (a) _a = (a); \
> +      __typeof__ (b) _b = (b); \
> +    _a > _b ? _a : _b; })
> +#define MIN(a,b) \
> +  ({ __typeof__ (a) _a = (a); \
> +      __typeof__ (b) _b = (b); \
> +    _a > _b ? _b : _a; })
> +
>  typedef void write_list_fn_t(FILE *file, const argument_t *arg);
>  
>  extern void WriteImport(FILE *file, const_string_t filename);
> -- 
> 2.37.2
> 
> 

-- 
Samuel
---
Pour une évaluation indépendante, transparente et rigoureuse !
Je soutiens la Commission d'Évaluation de l'Inria.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]