[ktap] [PATCHv2 3/8] Integrate cparser into ktap compiler

  • From: Qingping Hou <dave2008713@xxxxxxxxx>
  • To: ktap@xxxxxxxxxxxxx
  • Date: Fri, 29 Nov 2013 02:36:24 -0500

From: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx>

When ktapc finds a 'cdef' token, it passes the C code to cparser module,
which then generates c symbols accordingly.

This patch also handles how to dump c symbols into vm chunk.

Signed-off-by: Yicheng Qin <qycqycqycqycqyc@xxxxxxxxx>
Signed-off-by: Qingping Hou <qingping.hou@xxxxxxxxx>
---
 userspace/dump.c   | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 userspace/ktapc.h  | 14 ++++++++++++
 userspace/lex.c    |  8 +++----
 userspace/main.c   |  4 ++++
 userspace/parser.c | 50 +++++++++++++++++++++++++++++++++++++++++--
 5 files changed, 133 insertions(+), 6 deletions(-)

diff --git a/userspace/dump.c b/userspace/dump.c
index 0a27a1c..a1958eb 100644
--- a/userspace/dump.c
+++ b/userspace/dump.c
@@ -31,6 +31,7 @@
 #include "../include/ktap_opcodes.h"
 #include "ktapc.h"
 #include "../interpreter/kp_obj.h"
+#include "cparser.h"
 
 
 typedef struct {
@@ -171,6 +172,67 @@ static void DumpHeader(DumpState *D)
        DumpBlock(h, KTAPC_HEADERSIZE, D);
 }
 
+#ifdef CONFIG_KTAP_FFI
+static void DumpCSymbolFunc(csymbol *cs, DumpState *D)
+{
+       csymbol_func *csf = csym_func(cs);
+
+       DumpBlock(cs, sizeof(csymbol), D);
+       /* dump csymbol index for argument types */
+       DumpBlock(csf->arg_ids, csf->arg_nr*sizeof(int), D);
+}
+
+static void DumpCSymbolStruct(csymbol *cs, DumpState *D)
+{
+       csymbol_struct *csst = csym_struct(cs);
+
+       DumpBlock(cs, sizeof(csymbol), D);
+       /* dump csymbol index for argument types */
+       DumpBlock(csst->members, csst->memb_nr*sizeof(struct_member), D);
+}
+
+static void DumpCSymbols(DumpState *D)
+{
+       int i, cs_nr;
+       cp_csymbol_state *cs_state;
+       csymbol *cs, *cs_arr;
+
+       cs_state = ctype_get_csym_state();
+       cs_arr = cs_state->cs_arr;
+       cs_nr = cs_state->cs_nr;
+
+       if (!cs_arr || cs_nr == 0) {
+               DumpInt(0, D);
+               return;
+       }
+
+       /* dump number of csymbols */
+       DumpInt(cs_nr, D);
+       /* dump size of csymbol, for safty check in vm */
+       DumpInt(sizeof(csymbol), D);
+       for (i = 0; i < cs_nr; i++) {
+               cs = &cs_arr[i];
+               switch (cs->type) {
+               case FFI_FUNC:
+                       DumpCSymbolFunc(cs, D);
+                       break;
+               case FFI_STRUCT:
+                       DumpCSymbolStruct(cs, D);
+                       break;
+               default:
+                       DumpBlock(cs, sizeof(csymbol), D);
+                       break;
+               }
+       }
+}
+#else
+static void DumpCSymbols(DumpState *D)
+{
+       /* always dump zero when FFI is disabled */
+       DumpInt(0, D);
+}
+#endif /* CONFIG_KTAP_FFI */
+
 /*
  * dump ktap function as precompiled chunk
  */
@@ -183,6 +245,7 @@ int ktapc_dump(const ktap_proto *f, ktap_writer w, void 
*data, int strip)
        D.strip = strip;
        D.status = 0;
        DumpHeader(&D);
+       DumpCSymbols(&D);
        DumpFunction(f, &D);
        return D.status;
 }
diff --git a/userspace/ktapc.h b/userspace/ktapc.h
index a7a9e32..e6acbf5 100644
--- a/userspace/ktapc.h
+++ b/userspace/ktapc.h
@@ -78,6 +78,7 @@ enum RESERVED {
        /* terminal symbols denoted by reserved words */
        TK_TRACE = FIRST_RESERVED, TK_TRACE_END,
        TK_ARGEVENT, TK_ARGNAME,
+       TK_FFI_CDEF,
        TK_ARG1, TK_ARG2, TK_ARG3, TK_ARG4, TK_ARG5, TK_ARG6, TK_ARG7, TK_ARG8,
        TK_ARG9, TK_PROFILE, TK_TICK, TK_AGGR_ASSIGN,
        TK_AND, TK_BREAK,
@@ -377,3 +378,16 @@ int kallsyms_parse(void *arg,
 
 unsigned long find_kernel_symbol(const char *symbol);
 void list_available_events(const char *match);
+
+
+#ifdef CONFIG_KTAP_FFI
+#include "../interpreter/kp_ffi.h"
+
+typedef struct cp_csymbol_state {
+       int cs_nr; /* number of c symbols */
+       int cs_arr_size; /* size of current symbol arrays */
+       csymbol *cs_arr;
+} cp_csymbol_state;
+
+cp_csymbol_state *ctype_get_csym_state(void);
+#endif
diff --git a/userspace/lex.c b/userspace/lex.c
index 5180eec..2cfcd92 100644
--- a/userspace/lex.c
+++ b/userspace/lex.c
@@ -39,7 +39,7 @@
 
 /* ORDER RESERVED */
 static const char *const ktap_tokens [] = {
-       "trace", "trace_end", "argevent", "argname",
+       "trace", "trace_end", "argevent", "argname", "cdef",
        "arg1", "arg2", "arg3", "arg4", "arg5", "arg6", "arg7", "arg9", "arg9",
        "profile", "tick", "<<<",
        "and", "break", "do", "else", "elseif",
@@ -133,7 +133,7 @@ ktap_string *lex_newstring(ktap_lexstate *ls, const char 
*str, size_t l)
        ktap_value val;  /* entry for `str' */
        ktap_value tsv;
        ktap_string *ts = ktapc_ts_newlstr(str, l);  /* create new string */
-       set_string(&tsv, ts); 
+       set_string(&tsv, ts);
        o = ktapc_table_get(ls->fs->h, &tsv);
        if (is_nil(o)) {  /* not in use yet? (see 'addK') */
                /* boolean value does not need GC barrier;
@@ -553,7 +553,7 @@ static int llex(ktap_lexstate *ls, ktap_seminfo *seminfo)
                                next(ls);
                                return TK_AND;
                        }
-               } 
+               }
                case '|': {
                        next(ls);
                        if (ls->current != '|')
@@ -562,7 +562,7 @@ static int llex(ktap_lexstate *ls, ktap_seminfo *seminfo)
                                next(ls);
                                return TK_OR;
                        }
-               } 
+               }
                default: {
                        if (islalpha(ls->current)) {
                                /* identifier or reserved word? */
diff --git a/userspace/main.c b/userspace/main.c
index bdb6bb1..47df6df 100644
--- a/userspace/main.c
+++ b/userspace/main.c
@@ -40,6 +40,7 @@
 #include "../interpreter/kp_str.h"
 #include "../interpreter/kp_tab.h"
 #include "symbol.h"
+#include "cparser.h"
 
 
 /*******************************************************************/
@@ -618,6 +619,7 @@ static void compile(const char *input)
 
        if (oneline_src[0] != '\0') {
                init_dummy_global_state();
+               ffi_cparser_init();
                cl = ktapc_parser(oneline_src, input);
                goto dump;
        }
@@ -636,6 +638,7 @@ static void compile(const char *input)
                handle_error("mmap failed");
 
        init_dummy_global_state();
+       ffi_cparser_init();
        cl = ktapc_parser(buff, input);
 
        munmap(buff, sb.st_size);
@@ -653,6 +656,7 @@ static void compile(const char *input)
                handle_error("malloc failed");
 
        ktapc_dump(cl->p, ktapc_writer, NULL, 0);
+       ffi_cparser_free();
 }
 
 int main(int argc, char **argv)
diff --git a/userspace/parser.c b/userspace/parser.c
index 5366004..00afa20 100644
--- a/userspace/parser.c
+++ b/userspace/parser.c
@@ -30,6 +30,7 @@
 #include "../include/ktap_types.h"
 #include "../include/ktap_opcodes.h"
 #include "ktapc.h"
+#include "cparser.h"
 
 /* maximum number of local variables per function (must be smaller
    than 250, due to the bytecode format) */
@@ -1490,7 +1491,7 @@ static void forstat(ktap_lexstate *ls, int line)
        case ',': case TK_IN:
                forlist(ls, varname);
                break;
-       default: 
+       default:
                lex_syntaxerror(ls, KTAP_QL("=") " or " KTAP_QL("in") " 
expected");
        }
        //check_match(ls, TK_END, TK_FOR, line);
@@ -1797,6 +1798,49 @@ static void timerstat(ktap_lexstate *ls)
        SETARG_C(getcode(fs, v), 1);  /* call statement uses no results */
 }
 
+#ifdef CONFIG_KTAP_FFI
+static void __parsecdef(ktap_lexstate *ls)
+{
+       ktap_mbuffer cdef_buf;
+       int len;
+
+       /* get rid of double qoutes */
+       len = strlen(mbuff(ls->buff));
+       mbuff_init(&cdef_buf);
+       mbuff_resize(&cdef_buf, len-1);
+       mbuff_reset(&cdef_buf);
+       strncpy(mbuff(&cdef_buf), mbuff(ls->buff)+1, len-2);
+       ffi_cdef(mbuff(&cdef_buf));
+       mbuff_free(&cdef_buf);
+}
+#else
+static void __parsecdef(ktap_lexstate *ls)
+{
+       printf("Please compile with FFI support to use cdef!\n");
+       exit(EXIT_SUCCESS);
+}
+#endif
+
+/* we still keep cdef keyword even FFI feature is disabled, it just does
+ * nothing and prints out a warning */
+static void parsecdef(ktap_lexstate *ls)
+{
+       /* skip " */
+       lex_next(ls);
+       /* read cdef string */
+       lex_next(ls);
+
+       if (ls->t.token != TK_STRING)
+               error_expected(ls, TK_STRING);
+
+       __parsecdef(ls);
+
+       /* consume ( */
+       lex_next(ls);
+       /* consume newline */
+       lex_next(ls);
+}
+
 static void statement(ktap_lexstate *ls)
 {
        int line = ls->linenumber;  /* may be needed for error messages */
@@ -1865,6 +1909,9 @@ static void statement(ktap_lexstate *ls)
        case TK_TICK:
                timerstat(ls);
                break;
+       case TK_FFI_CDEF:
+               parsecdef(ls);
+               break;
        default: {  /* stat -> func | assignment */
                exprstat(ls);
                break;
@@ -1925,4 +1972,3 @@ ktap_closure *ktapc_parser(char *ptr, const char *name)
        ktap_assert(dyd.actvar.n == 0 && dyd.gt.n == 0 && dyd.label.n == 0);
        return cl;
 }
-
-- 
1.8.1.2


Other related posts:

  • » [ktap] [PATCHv2 3/8] Integrate cparser into ktap compiler - Qingping Hou