flush
authorMichael Wallner <mike@php.net>
Fri, 30 Oct 2015 09:16:28 +0000 (10:16 +0100)
committerMichael Wallner <mike@php.net>
Fri, 30 Oct 2015 09:16:28 +0000 (10:16 +0100)
php_psi.h
src/module.c
src/parser.h
src/parser.re
src/parser_proc.h
src/parser_proc.y
src/validator.c

index 08898011bae3876db07b2ec00aae128a9587f73f..f0e2ea27eae1d668acc224ca78d8eb905c7f8492 100644 (file)
--- a/php_psi.h
+++ b/php_psi.h
@@ -23,7 +23,9 @@ extern zend_module_entry psi_module_entry;
 #include "parser.h"
 
 void psi_error(int type, const char *msg, ...);
+size_t psi_t_alignment(token_t t);
 size_t psi_t_size(token_t t);
+size_t psi_t_align(token_t t, size_t s);
 int psi_internal_type(impl_type *type);
 zend_internal_arg_info *psi_internal_arginfo(impl *impl);
 size_t psi_num_min_args(impl *impl);
index 3e7de89e3be6d52baf9261f845b7fb3a772e0505..ee1230f3667267e8689a4ddfc2da73b589435b5a 100644 (file)
@@ -145,12 +145,16 @@ void psi_to_string(impl_val *ret_val, decl_arg *func, zval *return_value)
 size_t psi_t_alignment(token_t t)
 {
        size_t align;
-# define PSI_TAS_D(T) struct TAS_ ##T { \
+#define PSI_TAS_D(T) struct PSI_TAS_ ##T { \
        char c; \
-       ##T x; \
+       T x; \
 }
-# define PSI_TAS_C(T) align = offsetof(struct TAS_ ##T, x)
-# define PSI_TAS_CASE(T) { \
+#define PSI_TAS_P(T) struct PSI_TAS_ ## T ## _pointer { \
+       char c; \
+       T *x; \
+}
+#define PSI_TAS_C(T) align = offsetof(struct PSI_TAS_ ##T, x)
+#define PSI_TAS_CASE(T) { \
        PSI_TAS_D(T); \
        PSI_TAS_C(T); \
 }
@@ -197,8 +201,19 @@ size_t psi_t_alignment(token_t t)
        case PSI_T_DOUBLE:
                PSI_TAS_CASE(double);
                break;
+       case PSI_T_SIZE_T:
+               PSI_TAS_CASE(size_t);
+               break;
+       case PSI_T_POINTER:
+               {
+                       PSI_TAS_P(char);
+                       PSI_TAS_C(char_pointer);
+               }
+               break;
        EMPTY_SWITCH_DEFAULT_CASE();
        }
+
+       return align;
 }
 
 size_t psi_t_size(token_t t)
@@ -240,6 +255,12 @@ size_t psi_t_size(token_t t)
        case PSI_T_DOUBLE:
                size = sizeof(double);
                break;
+       case PSI_T_SIZE_T:
+               size = sizeof(size_t);
+               break;
+       case PSI_T_POINTER:
+               size = sizeof(char *);
+               break;
        EMPTY_SWITCH_DEFAULT_CASE();
        }
        return size;
index 8df41eafe50cf95aceba8e8fd9e32a938c809d1f..a39d15ecdd0255f72713f12fbfeea0fe80312ba0 100644 (file)
@@ -221,7 +221,9 @@ static inline decl* init_decl(decl_abi *abi, decl_arg *func, decl_args *args) {
 static inline void free_decl(decl *d) {
        free_decl_abi(d->abi);
        free_decl_arg(d->func);
-       free_decl_args(d->args);
+       if (d->args) {
+               free_decl_args(d->args);
+       }
        free(d);
 }
 
@@ -268,7 +270,9 @@ static inline decl_struct *init_decl_struct(char *name, decl_args *args) {
 }
 
 static inline void free_decl_struct(decl_struct *s) {
-       free_decl_args(s->args);
+       if (s->args) {
+               free_decl_args(s->args);
+       }
        free(s->name);
        free(s);
 }
index c134ffdf0e41020dbb485b6c11006beccf029fa2..0bca5b09aca87938a0645828ec222b70e1d1aca6 100644 (file)
@@ -189,6 +189,7 @@ token_t PSI_ParserScan(PSI_Parser *P)
                LONG = 'long';
                FLOAT = 'float';
                DOUBLE = 'double';
+               SIZE_T = 'size_t';
                SINT8 = 'sint8';
                UINT8 = 'uint8';
                SINT16 = 'sint16';
@@ -249,6 +250,7 @@ token_t PSI_ParserScan(PSI_Parser *P)
                LONG {RETURN(PSI_T_LONG);}
                FLOAT {RETURN(PSI_T_FLOAT);}
                DOUBLE {RETURN(PSI_T_DOUBLE);}
+               SIZE_T {RETURN(PSI_T_SIZE_T);}
                SINT8 {RETURN(PSI_T_SINT8);}
                UINT8 {RETURN(PSI_T_UINT8);}
                SINT16 {RETURN(PSI_T_SINT16);}
index bdc0b4572f228a0f77fd44a02a864002080474d2..a427b08c9c9ad53af57d5175ff105d27ea1c1cf6 100644 (file)
 #define PSI_T_SHORT                           25
 #define PSI_T_LONG                            26
 #define PSI_T_DOUBLE                          27
-#define PSI_T_SINT8                           28
-#define PSI_T_UINT8                           29
-#define PSI_T_SINT16                          30
-#define PSI_T_UINT16                          31
-#define PSI_T_SINT32                          32
-#define PSI_T_UINT32                          33
-#define PSI_T_SINT64                          34
-#define PSI_T_UINT64                          35
-#define PSI_T_FUNCTION                        36
-#define PSI_T_COLON                           37
-#define PSI_T_REFERENCE                       38
-#define PSI_T_NULL                            39
-#define PSI_T_TRUE                            40
-#define PSI_T_FALSE                           41
-#define PSI_T_DOLLAR                          42
-#define PSI_T_LET                             43
-#define PSI_T_CALLOC                          44
-#define PSI_T_STRLEN                          45
-#define PSI_T_STRVAL                          46
-#define PSI_T_INTVAL                          47
-#define PSI_T_FLOATVAL                        48
-#define PSI_T_BOOLVAL                         49
-#define PSI_T_SET                             50
-#define PSI_T_TO_ARRAY                        51
-#define PSI_T_TO_STRING                       52
-#define PSI_T_TO_INT                          53
-#define PSI_T_TO_FLOAT                        54
-#define PSI_T_TO_BOOL                         55
-#define PSI_T_RETURN                          56
-#define PSI_T_FREE                            57
-#define PSI_T_MIXED                           58
-#define PSI_T_ARRAY                           59
-#define PSI_T_POINTER                         60
+#define PSI_T_SIZE_T                          28
+#define PSI_T_SINT8                           29
+#define PSI_T_UINT8                           30
+#define PSI_T_SINT16                          31
+#define PSI_T_UINT16                          32
+#define PSI_T_SINT32                          33
+#define PSI_T_UINT32                          34
+#define PSI_T_SINT64                          35
+#define PSI_T_UINT64                          36
+#define PSI_T_FUNCTION                        37
+#define PSI_T_COLON                           38
+#define PSI_T_REFERENCE                       39
+#define PSI_T_NULL                            40
+#define PSI_T_TRUE                            41
+#define PSI_T_FALSE                           42
+#define PSI_T_DOLLAR                          43
+#define PSI_T_LET                             44
+#define PSI_T_CALLOC                          45
+#define PSI_T_STRLEN                          46
+#define PSI_T_STRVAL                          47
+#define PSI_T_INTVAL                          48
+#define PSI_T_FLOATVAL                        49
+#define PSI_T_BOOLVAL                         50
+#define PSI_T_SET                             51
+#define PSI_T_TO_ARRAY                        52
+#define PSI_T_TO_STRING                       53
+#define PSI_T_TO_INT                          54
+#define PSI_T_TO_FLOAT                        55
+#define PSI_T_TO_BOOL                         56
+#define PSI_T_RETURN                          57
+#define PSI_T_FREE                            58
+#define PSI_T_MIXED                           59
+#define PSI_T_ARRAY                           60
+#define PSI_T_POINTER                         61
index d368914f442bd091de8650e35926d4cc4272102c..59477baf28ef2ac830a96c61b32d0ec36b900377 100644 (file)
@@ -42,6 +42,9 @@ block ::= impl(impl). {
 }
 block ::= decl_typedef(def). {
        P->defs = add_decl_typedef(P->defs, def);
+       if (def->type->strct) {
+               P->structs = add_decl_struct(P->structs, def->type->strct);
+       }
 }
 block ::= constant(constant). {
        P->consts = add_constant(P->consts, constant);
@@ -89,6 +92,11 @@ decl_typedef(def) ::= TYPEDEF STRUCT(S) NAME(N) NAME(ALIAS) EOS. {
        free(S);
        free(N);
 }
+decl_typedef(def) ::= TYPEDEF decl_struct(s) NAME(ALIAS) EOS. {
+       def = init_decl_typedef(ALIAS->text, init_decl_type(PSI_T_STRUCT, s->name));
+       def->type->strct = s;
+       free(ALIAS);
+}
 
 %type decl {decl*}
 decl(decl) ::= decl_abi(abi) decl_arg(func) LPAREN decl_args(args) RPAREN EOS. {
@@ -179,6 +187,10 @@ decl_type(type_) ::= DOUBLE(T). {
        type_ = init_decl_type(T->type, T->text);
        free(T);
 }
+decl_type(type_) ::= SIZE_T(T). {
+       type_ = init_decl_type(T->type, T->text);
+       free(T);
+}
 decl_type(type_) ::= SINT8(T). {
        type_ = init_decl_type(T->type, T->text);
        free(T);
index 19956b73f475079183c1697632062b39933abf47..d4deddf5e0717574e183216ea92bdfb54d14078d 100644 (file)
@@ -6,6 +6,8 @@
 
 #include <jit/jit.h>
 
+#include "php.h"
+#include "php_psi.h"
 #include "validator.h"
 
 PSI_Validator *PSI_ValidatorInit(PSI_Validator *V, PSI_Parser *P)
@@ -141,7 +143,9 @@ static inline int validate_decl_func(PSI_Validator *V, decl *decl, decl_arg *fun
        if (!validate_decl_type(V, func, func->type)) {
                return 0;
        }
-
+#ifndef RTLD_NEXT
+# define RTLD_NEXT ((void *) -1l)
+#endif
        decl->dlptr = dlsym(V->dlopened ?: RTLD_NEXT, func->var->name);
        if (!decl->dlptr) {
                V->error(PSI_WARNING, "Failed to located symbol '%s': %s",
@@ -214,15 +218,17 @@ static inline int validate_struct(PSI_Validator *V, decl_struct *s) {
 
        s->layout = calloc(s->args->count, sizeof(*s->layout));
        for (i = 0; i < s->args->count; ++i) {
-               decl_type *t = real_decl_type(s->args->args[i]->type);
+               decl_arg *darg = s->args->args[i];
+               decl_type *type = real_decl_type(darg->type);
+               token_t t = darg->var->pointer_level ? PSI_T_POINTER : type->type;
 
                if (i) {
                        decl_struct_layout *l = &s->layout[i-1];
-                       s->layout[i].pos = psi_t_align(t->type, l->pos + l->size);
+                       s->layout[i].pos = psi_t_align(t, l->pos + l->len);
                } else {
                        s->layout[i].pos = 0;
                }
-               s->layout[i].len = psi_t_size(t->type);
+               s->layout[i].len = psi_t_size(t);
        }
        return 1;
 }
@@ -230,7 +236,7 @@ static inline int validate_structs(PSI_Validator *V) {
        size_t i;
 
        for (i = 0; i < V->structs->count; ++i) {
-               if (!validate_struct(V->structs->list[i])) {
+               if (!validate_struct(V, V->structs->list[i])) {
                        return 0;
                }
        }
@@ -294,7 +300,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
        if (stmts->ret.count != 1) {
                if (stmts->ret.count > 1) {
                        V->error(PSI_WARNING, "Too many `ret` statements for implmentation %s;"
-                                       "found %zu, exactly one is needed",
+                                       " found %zu, exactly one is needed",
                                        impl->func->name, stmts->ret.count);
                } else {
                        V->error(PSI_WARNING, "Missing `ret` statement for implementation %s",
@@ -312,7 +318,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
        }
 
        /* check that we have a let stmt for every decl arg */
-       for (i = 0; i < decl->args->count; ++i) {
+       if (decl->args) for (i = 0; i < decl->args->count; ++i) {
                decl_arg *darg = decl->args->args[i];
                int check = 0;
 
@@ -327,7 +333,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
                }
                if (!check) {
                        V->error(PSI_WARNING, "Missing `let` statement for arg '%s %.*s%s'"
-                                       "of declaration '%s' for implementation '%s'",
+                                       " of declaration '%s' for implementation '%s'",
                                        darg->type->name, (int) darg->var->pointer_level, "*****",
                                        darg->var->name, decl->func->var->name, impl->func->name);
                        return 0;
@@ -339,7 +345,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
                int check = 0;
 
                if (let->val && let->val->var) {
-                       for (j = 0; j < impl->func->args->count; ++j) {
+                       if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
                                impl_arg *iarg = impl->func->args->args[j];
 
                                if (!strcmp(let->val->var->name, iarg->var->name)) {
@@ -361,7 +367,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
                set_stmt *set = stmts->set.list[i];
                int check = 0;
 
-               for (j = 0; j < impl->func->args->count; ++j) {
+               if (impl->func->args) for (j = 0; j < impl->func->args->count; ++j) {
                        impl_arg *iarg = impl->func->args->args[j];
 
                        if (!strcmp(set->var->name, iarg->var->name)) {
@@ -381,7 +387,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
                        decl_var *set_var = set->val->vars->vars[j];
 
                        check = 0;
-                       for (k = 0; k < decl->args->count; ++k) {
+                       if (decl->args) for (k = 0; k < decl->args->count; ++k) {
                                decl_arg *set_arg = decl->args->args[k];
 
                                if (!strcmp(set_var->name, set_arg->var->name)) {
@@ -410,7 +416,7 @@ static inline int validate_impl_stmts(PSI_Validator *V, impl *impl, impl_stmts *
                        if (!strcmp(free_var->name, decl->func->var->name)) {
                                continue;
                        }
-                       for (k = 0; k < decl->args->count; ++k) {
+                       if (decl->args) for (k = 0; k < decl->args->count; ++k) {
                                decl_arg *free_arg = decl->args->args[k];
 
                                if (!strcmp(free_var->name, free_arg->var->name)) {