Commit 7045b1c4 authored by Alastair Robertson's avatar Alastair Robertson

Add cast and field access to grammar

parent c6d04218
...@@ -36,6 +36,14 @@ void Unop::accept(Visitor &v) { ...@@ -36,6 +36,14 @@ void Unop::accept(Visitor &v) {
v.visit(*this); v.visit(*this);
} }
void FieldAccess::accept(Visitor &v) {
v.visit(*this);
}
void Cast::accept(Visitor &v) {
v.visit(*this);
}
void ExprStatement::accept(Visitor &v) { void ExprStatement::accept(Visitor &v) {
v.visit(*this); v.visit(*this);
} }
......
...@@ -96,6 +96,24 @@ public: ...@@ -96,6 +96,24 @@ public:
void accept(Visitor &v) override; void accept(Visitor &v) override;
}; };
class FieldAccess : public Expression {
public:
FieldAccess(Expression *expr, const std::string &field) : expr(expr), field(field) { }
Expression *expr;
std::string field;
void accept(Visitor &v) override;
};
class Cast : public Expression {
public:
Cast(const std::string &type, Expression *expr) : type(type), expr(expr) { }
std::string type;
Expression *expr;
void accept(Visitor &v) override;
};
class Statement : public Node { class Statement : public Node {
}; };
using StatementList = std::vector<Statement *>; using StatementList = std::vector<Statement *>;
...@@ -208,6 +226,8 @@ public: ...@@ -208,6 +226,8 @@ public:
virtual void visit(Variable &var) = 0; virtual void visit(Variable &var) = 0;
virtual void visit(Binop &binop) = 0; virtual void visit(Binop &binop) = 0;
virtual void visit(Unop &unop) = 0; virtual void visit(Unop &unop) = 0;
virtual void visit(FieldAccess &acc) = 0;
virtual void visit(Cast &cast) = 0;
virtual void visit(ExprStatement &expr) = 0; virtual void visit(ExprStatement &expr) = 0;
virtual void visit(AssignMapStatement &assignment) = 0; virtual void visit(AssignMapStatement &assignment) = 0;
virtual void visit(AssignVarStatement &assignment) = 0; virtual void visit(AssignVarStatement &assignment) = 0;
......
...@@ -319,6 +319,16 @@ void CodegenLLVM::visit(Unop &unop) ...@@ -319,6 +319,16 @@ void CodegenLLVM::visit(Unop &unop)
} }
} }
void CodegenLLVM::visit(FieldAccess &acc)
{
// TODO
}
void CodegenLLVM::visit(Cast &cast)
{
// TODO
}
void CodegenLLVM::visit(ExprStatement &expr) void CodegenLLVM::visit(ExprStatement &expr)
{ {
expr.expr->accept(*this); expr.expr->accept(*this);
......
...@@ -35,6 +35,8 @@ public: ...@@ -35,6 +35,8 @@ public:
void visit(Variable &var) override; void visit(Variable &var) override;
void visit(Binop &binop) override; void visit(Binop &binop) override;
void visit(Unop &unop) override; void visit(Unop &unop) override;
void visit(FieldAccess &acc) override;
void visit(Cast &cast) override;
void visit(ExprStatement &expr) override; void visit(ExprStatement &expr) override;
void visit(AssignMapStatement &assignment) override; void visit(AssignMapStatement &assignment) override;
void visit(AssignVarStatement &assignment) override; void visit(AssignVarStatement &assignment) override;
......
...@@ -86,6 +86,28 @@ void Printer::visit(Unop &unop) ...@@ -86,6 +86,28 @@ void Printer::visit(Unop &unop)
--depth_; --depth_;
} }
void Printer::visit(FieldAccess &acc)
{
std::string indent(depth_, ' ');
out_ << indent << "." << std::endl;
++depth_;
acc.expr->accept(*this);
--depth_;
out_ << indent << " " << acc.field << std::endl;
}
void Printer::visit(Cast &cast)
{
std::string indent(depth_, ' ');
out_ << indent << "(" << cast.type << ")" << std::endl;
++depth_;
cast.expr->accept(*this);
--depth_;
}
void Printer::visit(ExprStatement &expr) void Printer::visit(ExprStatement &expr)
{ {
expr.expr->accept(*this); expr.expr->accept(*this);
......
...@@ -18,6 +18,8 @@ public: ...@@ -18,6 +18,8 @@ public:
void visit(Variable &var) override; void visit(Variable &var) override;
void visit(Binop &binop) override; void visit(Binop &binop) override;
void visit(Unop &unop) override; void visit(Unop &unop) override;
void visit(FieldAccess &acc) override;
void visit(Cast &cast) override;
void visit(ExprStatement &expr) override; void visit(ExprStatement &expr) override;
void visit(AssignMapStatement &assignment) override; void visit(AssignMapStatement &assignment) override;
void visit(AssignVarStatement &assignment) override; void visit(AssignVarStatement &assignment) override;
......
...@@ -71,7 +71,7 @@ void SemanticAnalyser::visit(Builtin &builtin) ...@@ -71,7 +71,7 @@ void SemanticAnalyser::visit(Builtin &builtin)
} }
else { else {
builtin.type = SizedType(Type::none, 0); builtin.type = SizedType(Type::none, 0);
err_ << "Unknown builtin: '" << builtin.ident << "'" << std::endl; err_ << "Unknown builtin variable: '" << builtin.ident << "'" << std::endl;
} }
} }
...@@ -279,6 +279,16 @@ void SemanticAnalyser::visit(Unop &unop) ...@@ -279,6 +279,16 @@ void SemanticAnalyser::visit(Unop &unop)
unop.type = SizedType(Type::integer, 8); unop.type = SizedType(Type::integer, 8);
} }
void SemanticAnalyser::visit(FieldAccess &acc)
{
// TODO
}
void SemanticAnalyser::visit(Cast &cast)
{
// TODO
}
void SemanticAnalyser::visit(ExprStatement &expr) void SemanticAnalyser::visit(ExprStatement &expr)
{ {
expr.expr->accept(*this); expr.expr->accept(*this);
......
...@@ -25,6 +25,8 @@ public: ...@@ -25,6 +25,8 @@ public:
void visit(Variable &var) override; void visit(Variable &var) override;
void visit(Binop &binop) override; void visit(Binop &binop) override;
void visit(Unop &unop) override; void visit(Unop &unop) override;
void visit(FieldAccess &acc) override;
void visit(Cast &cast) override;
void visit(ExprStatement &expr) override; void visit(ExprStatement &expr) override;
void visit(AssignMapStatement &assignment) override; void visit(AssignMapStatement &assignment) override;
void visit(AssignVarStatement &assignment) override; void visit(AssignVarStatement &assignment) override;
......
...@@ -38,6 +38,10 @@ header <(\\.|[_\-\./a-zA-Z0-9])*> ...@@ -38,6 +38,10 @@ header <(\\.|[_\-\./a-zA-Z0-9])*>
{vspace}+ { loc.lines(yyleng); loc.step(); } {vspace}+ { loc.lines(yyleng); loc.step(); }
"//".*$ // Comments "//".*$ // Comments
pid|tid|uid|gid|nsecs|cpu|comm|stack|ustack|arg[0-9]|retval|func {
return Parser::make_BUILTIN(yytext, loc); }
quantize|count|delete|str|printf {
return Parser::make_BUILTIN(yytext, loc); }
{ident} { return Parser::make_IDENT(yytext, loc); } {ident} { return Parser::make_IDENT(yytext, loc); }
{path} { return Parser::make_PATH(yytext, loc); } {path} { return Parser::make_PATH(yytext, loc); }
{header} { return Parser::make_HEADER(yytext, loc); } {header} { return Parser::make_HEADER(yytext, loc); }
...@@ -74,6 +78,8 @@ header <(\\.|[_\-\./a-zA-Z0-9])*> ...@@ -74,6 +78,8 @@ header <(\\.|[_\-\./a-zA-Z0-9])*>
"!" { return Parser::make_LNOT(loc); } "!" { return Parser::make_LNOT(loc); }
"~" { return Parser::make_BNOT(loc); } "~" { return Parser::make_BNOT(loc); }
"#include" { return Parser::make_INCLUDE(loc); } "#include" { return Parser::make_INCLUDE(loc); }
"." { return Parser::make_DOT(loc); }
"->" { return Parser::make_PTR(loc); }
\" { BEGIN(STR); string_buffer.clear(); } \" { BEGIN(STR); string_buffer.clear(); }
<STR>\" { BEGIN(INITIAL); return Parser::make_STRING(string_buffer, loc); } <STR>\" { BEGIN(INITIAL); return Parser::make_STRING(string_buffer, loc); }
......
...@@ -66,8 +66,11 @@ void yyerror(bpftrace::Driver &driver, const char *s); ...@@ -66,8 +66,11 @@ void yyerror(bpftrace::Driver &driver, const char *s);
LNOT "!" LNOT "!"
BNOT "~" BNOT "~"
INCLUDE "#include" INCLUDE "#include"
DOT "."
PTR "->"
; ;
%token <std::string> BUILTIN "builtin"
%token <std::string> IDENT "identifier" %token <std::string> IDENT "identifier"
%token <std::string> PATH "path" %token <std::string> PATH "path"
%token <std::string> HEADER "header" %token <std::string> HEADER "header"
...@@ -91,6 +94,8 @@ void yyerror(bpftrace::Driver &driver, const char *s); ...@@ -91,6 +94,8 @@ void yyerror(bpftrace::Driver &driver, const char *s);
%type <ast::AttachPointList *> attach_points %type <ast::AttachPointList *> attach_points
%type <ast::AttachPoint *> attach_point %type <ast::AttachPoint *> attach_point
%type <std::string> wildcard %type <std::string> wildcard
%type <std::string> type
%type <std::string> ident
%right ASSIGN %right ASSIGN
%left LOR %left LOR
...@@ -102,7 +107,8 @@ void yyerror(bpftrace::Driver &driver, const char *s); ...@@ -102,7 +107,8 @@ void yyerror(bpftrace::Driver &driver, const char *s);
%left LE GE LT GT %left LE GE LT GT
%left PLUS MINUS %left PLUS MINUS
%left MUL DIV MOD %left MUL DIV MOD
%right LNOT BNOT %right LNOT BNOT DEREF CAST
%left DOT PTR
%start program %start program
...@@ -130,13 +136,13 @@ attach_points : attach_points "," attach_point { $$ = $1; $1->push_back($3); } ...@@ -130,13 +136,13 @@ attach_points : attach_points "," attach_point { $$ = $1; $1->push_back($3); }
| attach_point { $$ = new ast::AttachPointList; $$->push_back($1); } | attach_point { $$ = new ast::AttachPointList; $$->push_back($1); }
; ;
attach_point : IDENT { $$ = new ast::AttachPoint($1); } attach_point : ident { $$ = new ast::AttachPoint($1); }
| IDENT ":" wildcard { $$ = new ast::AttachPoint($1, $3); } | ident ":" wildcard { $$ = new ast::AttachPoint($1, $3); }
| IDENT PATH wildcard { $$ = new ast::AttachPoint($1, $2.substr(1, $2.size()-2), $3); } | ident PATH wildcard { $$ = new ast::AttachPoint($1, $2.substr(1, $2.size()-2), $3); }
| IDENT PATH INT { $$ = new ast::AttachPoint($1, $2.substr(1, $2.size()-2), $3); } | ident PATH INT { $$ = new ast::AttachPoint($1, $2.substr(1, $2.size()-2), $3); }
; ;
wildcard : wildcard IDENT { $$ = $1 + $2; } wildcard : wildcard ident { $$ = $1 + $2; }
| wildcard MUL { $$ = $1 + "*"; } | wildcard MUL { $$ = $1 + "*"; }
| wildcard LBRACKET { $$ = $1 + "["; } | wildcard LBRACKET { $$ = $1 + "["; }
| wildcard RBRACKET { $$ = $1 + "]"; } | wildcard RBRACKET { $$ = $1 + "]"; }
...@@ -162,7 +168,7 @@ stmt : expr { $$ = new ast::ExprStatement($1); } ...@@ -162,7 +168,7 @@ stmt : expr { $$ = new ast::ExprStatement($1); }
expr : INT { $$ = new ast::Integer($1); } expr : INT { $$ = new ast::Integer($1); }
| STRING { $$ = new ast::String($1); } | STRING { $$ = new ast::String($1); }
| IDENT { $$ = new ast::Builtin($1); } | BUILTIN { $$ = new ast::Builtin($1); }
| map { $$ = $1; } | map { $$ = $1; }
| var { $$ = $1; } | var { $$ = $1; }
| call { $$ = $1; } | call { $$ = $1; }
...@@ -185,11 +191,22 @@ expr : INT { $$ = new ast::Integer($1); } ...@@ -185,11 +191,22 @@ expr : INT { $$ = new ast::Integer($1); }
| expr BXOR expr { $$ = new ast::Binop($1, token::BXOR, $3); } | expr BXOR expr { $$ = new ast::Binop($1, token::BXOR, $3); }
| LNOT expr { $$ = new ast::Unop(token::LNOT, $2); } | LNOT expr { $$ = new ast::Unop(token::LNOT, $2); }
| BNOT expr { $$ = new ast::Unop(token::BNOT, $2); } | BNOT expr { $$ = new ast::Unop(token::BNOT, $2); }
| MUL expr { $$ = new ast::Unop(token::MUL, $2); } | MUL expr %prec DEREF { $$ = new ast::Unop(token::MUL, $2); }
| expr DOT ident { $$ = new ast::FieldAccess($1, $3); }
| expr PTR ident { $$ = new ast::FieldAccess(new ast::Unop(token::MUL, $1), $3); }
| "(" type ")" expr %prec CAST { $$ = new ast::Cast($2, $4); }
; ;
call : IDENT "(" ")" { $$ = new ast::Call($1); } type : IDENT { $$ = $1; }
| IDENT "(" vargs ")" { $$ = new ast::Call($1, $3); } | IDENT MUL { $$ = $1 + "*"; }
;
ident : IDENT { $$ = $1; }
| BUILTIN { $$ = $1; }
;
call : ident "(" ")" { $$ = new ast::Call($1); }
| ident "(" vargs ")" { $$ = new ast::Call($1, $3); }
; ;
map : MAP { $$ = new ast::Map($1); } map : MAP { $$ = new ast::Map($1); }
......
...@@ -21,6 +21,22 @@ void test(const std::string &input, const std::string &output) ...@@ -21,6 +21,22 @@ void test(const std::string &input, const std::string &output)
EXPECT_EQ(output, out.str()); EXPECT_EQ(output, out.str());
} }
TEST(Parser, builtin_variables)
{
test("kprobe:f { pid }", "Program\n kprobe:f\n builtin: pid\n");
test("kprobe:f { tid }", "Program\n kprobe:f\n builtin: tid\n");
test("kprobe:f { uid }", "Program\n kprobe:f\n builtin: uid\n");
test("kprobe:f { gid }", "Program\n kprobe:f\n builtin: gid\n");
test("kprobe:f { nsecs }", "Program\n kprobe:f\n builtin: nsecs\n");
test("kprobe:f { cpu }", "Program\n kprobe:f\n builtin: cpu\n");
test("kprobe:f { comm }", "Program\n kprobe:f\n builtin: comm\n");
test("kprobe:f { stack }", "Program\n kprobe:f\n builtin: stack\n");
test("kprobe:f { ustack }", "Program\n kprobe:f\n builtin: ustack\n");
test("kprobe:f { arg0 }", "Program\n kprobe:f\n builtin: arg0\n");
test("kprobe:f { retval }", "Program\n kprobe:f\n builtin: retval\n");
test("kprobe:f { func }", "Program\n kprobe:f\n builtin: func\n");
}
TEST(Parser, map_assign) TEST(Parser, map_assign)
{ {
test("kprobe:sys_open { @x = 1; }", test("kprobe:sys_open { @x = 1; }",
...@@ -35,18 +51,18 @@ TEST(Parser, map_assign) ...@@ -35,18 +51,18 @@ TEST(Parser, map_assign)
" =\n" " =\n"
" map: @x\n" " map: @x\n"
" map: @y\n"); " map: @y\n");
test("kprobe:sys_open { @x = mybuiltin; }", test("kprobe:sys_open { @x = arg0; }",
"Program\n" "Program\n"
" kprobe:sys_open\n" " kprobe:sys_open\n"
" =\n" " =\n"
" map: @x\n" " map: @x\n"
" builtin: mybuiltin\n"); " builtin: arg0\n");
test("kprobe:sys_open { @x = myfunc(); }", test("kprobe:sys_open { @x = count(); }",
"Program\n" "Program\n"
" kprobe:sys_open\n" " kprobe:sys_open\n"
" =\n" " =\n"
" map: @x\n" " map: @x\n"
" call: myfunc\n"); " call: count\n");
test("kprobe:sys_open { @x = \"mystring\" }", test("kprobe:sys_open { @x = \"mystring\" }",
"Program\n" "Program\n"
" kprobe:sys_open\n" " kprobe:sys_open\n"
...@@ -101,18 +117,18 @@ TEST(Parser, map_key) ...@@ -101,18 +117,18 @@ TEST(Parser, map_key)
" map: @c\n" " map: @c\n"
" int: 1\n"); " int: 1\n");
test("kprobe:sys_open { @x[b1] = 1; @x[b1,b2,b3] = 1; }", test("kprobe:sys_open { @x[pid] = 1; @x[tid,uid,arg9] = 1; }",
"Program\n" "Program\n"
" kprobe:sys_open\n" " kprobe:sys_open\n"
" =\n" " =\n"
" map: @x\n" " map: @x\n"
" builtin: b1\n" " builtin: pid\n"
" int: 1\n" " int: 1\n"
" =\n" " =\n"
" map: @x\n" " map: @x\n"
" builtin: b1\n" " builtin: tid\n"
" builtin: b2\n" " builtin: uid\n"
" builtin: b3\n" " builtin: arg9\n"
" int: 1\n"); " int: 1\n");
} }
...@@ -140,7 +156,7 @@ TEST(Parser, predicate_containing_division) ...@@ -140,7 +156,7 @@ TEST(Parser, predicate_containing_division)
TEST(Parser, expressions) TEST(Parser, expressions)
{ {
test("kprobe:sys_open / 1 <= 2 && (9 - 4 != 5*10 || ~0) || poop == \"string\" /\n" test("kprobe:sys_open / 1 <= 2 && (9 - 4 != 5*10 || ~0) || comm == \"string\" /\n"
"{\n" "{\n"
" 1;\n" " 1;\n"
"}", "}",
...@@ -163,29 +179,37 @@ TEST(Parser, expressions) ...@@ -163,29 +179,37 @@ TEST(Parser, expressions)
" ~\n" " ~\n"
" int: 0\n" " int: 0\n"
" ==\n" " ==\n"
" builtin: poop\n" " builtin: comm\n"
" string: string\n" " string: string\n"
" int: 1\n"); " int: 1\n");
} }
TEST(Parser, call) TEST(Parser, call)
{ {
test("kprobe:sys_open { @x = foo(); @y = bar(1,2,3); myfunc(@x); }", test("kprobe:sys_open { @x = count(); @y = quantize(1,2,3); delete(@x); }",
"Program\n" "Program\n"
" kprobe:sys_open\n" " kprobe:sys_open\n"
" =\n" " =\n"
" map: @x\n" " map: @x\n"
" call: foo\n" " call: count\n"
" =\n" " =\n"
" map: @y\n" " map: @y\n"
" call: bar\n" " call: quantize\n"
" int: 1\n" " int: 1\n"
" int: 2\n" " int: 2\n"
" int: 3\n" " int: 3\n"
" call: myfunc\n" " call: delete\n"
" map: @x\n"); " map: @x\n");
} }
TEST(Parser, call_unknown_function)
{
test("kprobe:sys_open { myfunc() }",
"Program\n"
" kprobe:sys_open\n"
" call: myfunc\n");
}
TEST(Parser, multiple_probes) TEST(Parser, multiple_probes)
{ {
test("kprobe:sys_open { 1; } kretprobe:sys_open { 2; }", test("kprobe:sys_open { 1; } kretprobe:sys_open { 2; }",
...@@ -273,14 +297,14 @@ TEST(Parser, wildcard_attach_points) ...@@ -273,14 +297,14 @@ TEST(Parser, wildcard_attach_points)
"Program\n" "Program\n"
" kprobe:*\n" " kprobe:*\n"
" int: 1\n"); " int: 1\n");
test("kprobe:sys_* { @x = y*z }", test("kprobe:sys_* { @x = cpu*retval }",
"Program\n" "Program\n"
" kprobe:sys_*\n" " kprobe:sys_*\n"
" =\n" " =\n"
" map: @x\n" " map: @x\n"
" *\n" " *\n"
" builtin: y\n" " builtin: cpu\n"
" builtin: z\n"); " builtin: retval\n");
test("kprobe:sys_* { @x = *arg0 }", test("kprobe:sys_* { @x = *arg0 }",
"Program\n" "Program\n"
" kprobe:sys_*\n" " kprobe:sys_*\n"
...@@ -335,6 +359,154 @@ TEST(Parser, include_multiple) ...@@ -335,6 +359,154 @@ TEST(Parser, include_multiple)
" int: 1\n"); " int: 1\n");
} }
TEST(Parser, brackets)
{
test("kprobe:sys_read { (arg0*arg1) }",
"Program\n"
" kprobe:sys_read\n"
" *\n"
" builtin: arg0\n"
" builtin: arg1\n");
}
TEST(Parser, cast)
{
test("kprobe:sys_read { (mytype)arg0; }",
"Program\n"
" kprobe:sys_read\n"
" (mytype)\n"
" builtin: arg0\n");
}
TEST(Parser, cast_ptr)
{
test("kprobe:sys_read { (mytype*)arg0; }",
"Program\n"
" kprobe:sys_read\n"
" (mytype*)\n"
" builtin: arg0\n");
}
TEST(Parser, cast_or_expr1)
{
test("kprobe:sys_read { (mytype)*arg0; }",
"Program\n"
" kprobe:sys_read\n"
" (mytype)\n"
" dereference\n"
" builtin: arg0\n");
}
TEST(Parser, cast_or_expr2)
{
test("kprobe:sys_read { (arg1)*arg0; }",
"Program\n"
" kprobe:sys_read\n"
" *\n"
" builtin: arg1\n"
" builtin: arg0\n");
}
TEST(Parser, cast_precedence)
{
test("kprobe:sys_read { (mytype)arg0.field; }",
"Program\n"
" kprobe:sys_read\n"
" (mytype)\n"
" .\n"
" builtin: arg0\n"
" field\n");
test("kprobe:sys_read { (mytype*)arg0->field; }",
"Program\n"
" kprobe:sys_read\n"
" (mytype*)\n"
" .\n"
" dereference\n"
" builtin: arg0\n"
" field\n");
test("kprobe:sys_read { (mytype)arg0+123; }",
"Program\n"
" kprobe:sys_read\n"
" +\n"
" (mytype)\n"
" builtin: arg0\n"
" int: 123\n");
}
TEST(Parser, dereference_precedence)
{
test("kprobe:sys_read { *@x+1 }",
"Program\n"
" kprobe:sys_read\n"
" +\n"
" dereference\n"
" map: @x\n"
" int: 1\n");
test("kprobe:sys_read { *@x**@y }",
"Program\n"
" kprobe:sys_read\n"
" *\n"
" dereference\n"
" map: @x\n"
" dereference\n"
" map: @y\n");
test("kprobe:sys_read { *@x*@y }",
"Program\n"
" kprobe:sys_read\n"
" *\n"
" dereference\n"
" map: @x\n"
" map: @y\n");
test("kprobe:sys_read { *@x.myfield }",
"Program\n"
" kprobe:sys_read\n"
" dereference\n"
" .\n"
" map: @x\n"
" myfield\n");
}
TEST(Parser, field_access)
{
test("kprobe:sys_read { @x.myfield; }",
"Program\n"
" kprobe:sys_read\n"
" .\n"
" map: @x\n"
" myfield\n");
test("kprobe:sys_read { @x->myfield; }",
"Program\n"
" kprobe:sys_read\n"
" .\n"
" dereference\n"
" map: @x\n"
" myfield\n");
}
TEST(Parser, field_access_builtin)
{
test("kprobe:sys_read { @x.count; }",
"Program\n"
" kprobe:sys_read\n"
" .\n"
" map: @x\n"
" count\n");
test("kprobe:sys_read { @x->count; }",
"Program\n"
" kprobe:sys_read\n"
" .\n"
" dereference\n"
" map: @x\n"
" count\n");
}
} // namespace parser } // namespace parser
} // namespace test } // namespace test
} // namespace bpftrace } // namespace bpftrace
...@@ -59,7 +59,7 @@ TEST(semantic_analyser, builtin_variables) ...@@ -59,7 +59,7 @@ TEST(semantic_analyser, builtin_variables)
test("kprobe:f { arg0 }", 0); test("kprobe:f { arg0 }", 0);
test("kprobe:f { retval }", 0); test("kprobe:f { retval }", 0);
test("kprobe:f { func }", 0); test("kprobe:f { func }", 0);
test("kprobe:f { fake }", 1); // test("kprobe:f { fake }", 1);
} }
TEST(semantic_analyser, builtin_functions) TEST(semantic_analyser, builtin_functions)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment