diff options
-rw-r--r-- | lexxer.l | 2 | ||||
-rw-r--r-- | parser.y | 46 | ||||
-rw-r--r-- | tests/good/complex-types.defs | 12 | ||||
-rw-r--r-- | tests/includes/types.h | 20 | ||||
-rw-r--r-- | type.c | 75 | ||||
-rw-r--r-- | type.h | 4 | ||||
-rw-r--r-- | utils.h | 11 |
7 files changed, 163 insertions, 7 deletions
@@ -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); @@ -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; } @@ -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); } /****************************************************** @@ -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; @@ -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); |