Commit a28012be authored by Alastair Robertson's avatar Alastair Robertson

Add string type

parent e20808ff
...@@ -8,6 +8,10 @@ void Integer::accept(Visitor &v) { ...@@ -8,6 +8,10 @@ void Integer::accept(Visitor &v) {
v.visit(*this); v.visit(*this);
} }
void String::accept(Visitor &v) {
v.visit(*this);
}
void Builtin::accept(Visitor &v) { void Builtin::accept(Visitor &v) {
v.visit(*this); v.visit(*this);
} }
......
...@@ -30,6 +30,14 @@ public: ...@@ -30,6 +30,14 @@ public:
void accept(Visitor &v) override; void accept(Visitor &v) override;
}; };
class String : public Expression {
public:
explicit String(std::string str) : str(str) { }
std::string str;
void accept(Visitor &v) override;
};
class Builtin : public Expression { class Builtin : public Expression {
public: public:
explicit Builtin(std::string ident) : ident(ident) { } explicit Builtin(std::string ident) : ident(ident) { }
...@@ -144,6 +152,7 @@ class Visitor { ...@@ -144,6 +152,7 @@ class Visitor {
public: public:
virtual ~Visitor() { } virtual ~Visitor() { }
virtual void visit(Integer &integer) = 0; virtual void visit(Integer &integer) = 0;
virtual void visit(String &string) = 0;
virtual void visit(Builtin &builtin) = 0; virtual void visit(Builtin &builtin) = 0;
virtual void visit(Call &call) = 0; virtual void visit(Call &call) = 0;
virtual void visit(Map &map) = 0; virtual void visit(Map &map) = 0;
......
...@@ -106,6 +106,8 @@ int BPFtrace::print_map(Map &map) const ...@@ -106,6 +106,8 @@ int BPFtrace::print_map(Map &map) const
std::cout << get_stack(*(uint32_t*)value.data(), false, 8); std::cout << get_stack(*(uint32_t*)value.data(), false, 8);
else if (map.type_.type == Type::ustack) else if (map.type_.type == Type::ustack)
std::cout << get_stack(*(uint32_t*)value.data(), true, 8); std::cout << get_stack(*(uint32_t*)value.data(), true, 8);
else if (map.type_.type == Type::string)
std::cout << value.data() << std::endl;
else else
std::cout << *(int64_t*)value.data() << std::endl; std::cout << *(int64_t*)value.data() << std::endl;
......
...@@ -17,6 +17,15 @@ void CodegenLLVM::visit(Integer &integer) ...@@ -17,6 +17,15 @@ void CodegenLLVM::visit(Integer &integer)
expr_ = b_.getInt64(integer.n); expr_ = b_.getInt64(integer.n);
} }
void CodegenLLVM::visit(String &string)
{
string.str.resize(string.type.size-1);
Constant *const_str = ConstantDataArray::getString(module_->getContext(), string.str, true);
AllocaInst *buf = b_.CreateAllocaBPF(string.type, "str");
b_.CreateStore(b_.CreateGEP(const_str, b_.getInt64(0)), buf);
expr_ = buf;
}
void CodegenLLVM::visit(Builtin &builtin) void CodegenLLVM::visit(Builtin &builtin)
{ {
if (builtin.ident == "nsecs") if (builtin.ident == "nsecs")
...@@ -146,10 +155,19 @@ void CodegenLLVM::visit(AssignMapStatement &assignment) ...@@ -146,10 +155,19 @@ void CodegenLLVM::visit(AssignMapStatement &assignment)
assignment.expr->accept(*this); assignment.expr->accept(*this);
AllocaInst *val = b_.CreateAllocaBPF(map.type, map.ident + "_val"); if (assignment.expr->type.type == Type::string)
b_.CreateStore(expr_, val); {
AllocaInst *key = getMapKey(map); Value *val = expr_;
b_.CreateMapUpdateElem(map, key, val); AllocaInst *key = getMapKey(map);
b_.CreateMapUpdateElem(map, key, val);
}
else
{
AllocaInst *val = b_.CreateAllocaBPF(map.type, map.ident + "_val");
b_.CreateStore(expr_, val);
AllocaInst *key = getMapKey(map);
b_.CreateMapUpdateElem(map, key, val);
}
} }
void CodegenLLVM::visit(AssignMapCallStatement &assignment) void CodegenLLVM::visit(AssignMapCallStatement &assignment)
...@@ -256,7 +274,10 @@ AllocaInst *CodegenLLVM::getMapKey(Map &map) ...@@ -256,7 +274,10 @@ AllocaInst *CodegenLLVM::getMapKey(Map &map)
for (Expression *expr : *map.vargs) { for (Expression *expr : *map.vargs) {
expr->accept(*this); expr->accept(*this);
Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)}); Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)});
b_.CreateStore(expr_, offset_val); if (expr->type.type == Type::string)
b_.CreateMemcpy(offset_val, expr_, b_.getInt64(expr->type.size));
else
b_.CreateStore(expr_, offset_val);
offset += expr->type.size; offset += expr->type.size;
} }
} }
...@@ -283,7 +304,10 @@ AllocaInst *CodegenLLVM::getQuantizeMapKey(Map &map, Value *log2) ...@@ -283,7 +304,10 @@ AllocaInst *CodegenLLVM::getQuantizeMapKey(Map &map, Value *log2)
for (Expression *expr : *map.vargs) { for (Expression *expr : *map.vargs) {
expr->accept(*this); expr->accept(*this);
Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)}); Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)});
b_.CreateStore(expr_, offset_val); if (expr->type.type == Type::string)
b_.CreateMemcpy(offset_val, expr_, b_.getInt64(expr->type.size));
else
b_.CreateStore(expr_, offset_val);
offset += expr->type.size; offset += expr->type.size;
} }
Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)}); Value *offset_val = b_.CreateGEP(key, {b_.getInt64(0), b_.getInt64(offset)});
......
...@@ -24,6 +24,7 @@ public: ...@@ -24,6 +24,7 @@ public:
{ } { }
void visit(Integer &integer) override; void visit(Integer &integer) override;
void visit(String &string) override;
void visit(Builtin &builtin) override; void visit(Builtin &builtin) override;
void visit(Call &call) override; void visit(Call &call) override;
void visit(Map &map) override; void visit(Map &map) override;
......
...@@ -23,21 +23,38 @@ IRBuilderBPF::IRBuilderBPF(LLVMContext &context, ...@@ -23,21 +23,38 @@ IRBuilderBPF::IRBuilderBPF(LLVMContext &context,
GlobalValue::ExternalLinkage, GlobalValue::ExternalLinkage,
"llvm.bpf.pseudo", "llvm.bpf.pseudo",
&module_); &module_);
FunctionType *memcpy_func_type = FunctionType::get(
getVoidTy(),
{getInt8PtrTy(), getInt8PtrTy(), getInt64Ty(), getInt32Ty(), getInt1Ty()},
false);
Function::Create(
memcpy_func_type,
GlobalValue::ExternalLinkage,
"llvm.memcpy.p0i8.p0i8.i64",
&module_);
} }
AllocaInst *IRBuilderBPF::CreateAllocaBPF(const SizedType &stype, const std::string &name) AllocaInst *IRBuilderBPF::CreateAllocaBPF(const SizedType &stype, const std::string &name)
{ {
llvm::Type *ty; llvm::Type *ty;
switch (stype.size) if (stype.type == Type::string)
{ {
case 8: ty = ArrayType::get(getInt8Ty(), stype.size);
ty = getInt64Ty(); }
break; else
case 4: {
ty = getInt32Ty(); switch (stype.size)
break; {
default: case 8:
abort(); ty = getInt64Ty();
break;
case 4:
ty = getInt32Ty();
break;
default:
abort();
}
} }
Function *parent = GetInsertBlock()->getParent(); Function *parent = GetInsertBlock()->getParent();
BasicBlock &entry_block = parent->getEntryBlock(); BasicBlock &entry_block = parent->getEntryBlock();
...@@ -59,6 +76,12 @@ AllocaInst *IRBuilderBPF::CreateAllocaMapKey(int bytes, const std::string &name) ...@@ -59,6 +76,12 @@ AllocaInst *IRBuilderBPF::CreateAllocaMapKey(int bytes, const std::string &name)
return new AllocaInst(ty, name, &entry_block.front()); return new AllocaInst(ty, name, &entry_block.front());
} }
void IRBuilderBPF::CreateMemcpy(Value *dst, Value *src, Value *len)
{
Function *memcpy_func = module_.getFunction("llvm.memcpy.p0i8.p0i8.i64");
CreateCall(memcpy_func, {dst, src, len, getInt32(1), getInt1(0)}, "memcpy");
}
CallInst *IRBuilderBPF::CreateBpfPseudoCall(int mapfd) CallInst *IRBuilderBPF::CreateBpfPseudoCall(int mapfd)
{ {
Function *pseudo_func = module_.getFunction("llvm.bpf.pseudo"); Function *pseudo_func = module_.getFunction("llvm.bpf.pseudo");
......
...@@ -20,6 +20,7 @@ public: ...@@ -20,6 +20,7 @@ public:
AllocaInst *CreateAllocaBPF(const SizedType &stype, const std::string &name=""); AllocaInst *CreateAllocaBPF(const SizedType &stype, const std::string &name="");
AllocaInst *CreateAllocaMapKey(int bytes, const std::string &name=""); AllocaInst *CreateAllocaMapKey(int bytes, const std::string &name="");
void CreateMemcpy(Value *dst, Value *src, Value *len);
CallInst *CreateBpfPseudoCall(int mapfd); CallInst *CreateBpfPseudoCall(int mapfd);
CallInst *CreateBpfPseudoCall(Map &map); CallInst *CreateBpfPseudoCall(Map &map);
LoadInst *CreateMapLookupElem(Map &map, AllocaInst *key); LoadInst *CreateMapLookupElem(Map &map, AllocaInst *key);
......
...@@ -23,6 +23,7 @@ hspace [ \t] ...@@ -23,6 +23,7 @@ hspace [ \t]
vspace [\n\r] vspace [\n\r]
space {hspace}|{vspace} space {hspace}|{vspace}
path :(\\.|[_\-\./a-zA-Z0-9])*: path :(\\.|[_\-\./a-zA-Z0-9])*:
string \"(\\.|[^\\"])*\"
%% %%
...@@ -36,6 +37,7 @@ path :(\\.|[_\-\./a-zA-Z0-9])*: ...@@ -36,6 +37,7 @@ path :(\\.|[_\-\./a-zA-Z0-9])*:
{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); }
{string} { return Parser::make_STRING(yytext, loc); }
{map} { return Parser::make_MAP(yytext, loc); } {map} { return Parser::make_MAP(yytext, loc); }
{int} { return Parser::make_INT(strtoul(yytext, NULL, 0), loc); } {int} { return Parser::make_INT(strtoul(yytext, NULL, 0), loc); }
":" { return Parser::make_COLON(loc); } ":" { return Parser::make_COLON(loc); }
......
...@@ -69,6 +69,8 @@ std::string MapKey::argument_value(const BPFtrace &bpftrace, ...@@ -69,6 +69,8 @@ std::string MapKey::argument_value(const BPFtrace &bpftrace,
return bpftrace.get_stack(*(uint32_t*)data, false); return bpftrace.get_stack(*(uint32_t*)data, false);
case Type::ustack: case Type::ustack:
return bpftrace.get_stack(*(uint32_t*)data, true); return bpftrace.get_stack(*(uint32_t*)data, true);
case Type::string:
return std::string((char*)data);
} }
abort(); abort();
} }
......
...@@ -69,6 +69,7 @@ void yyerror(bpftrace::Driver &driver, const char *s); ...@@ -69,6 +69,7 @@ void yyerror(bpftrace::Driver &driver, const char *s);
%token <std::string> IDENT "identifier" %token <std::string> IDENT "identifier"
%token <std::string> PATH "path" %token <std::string> PATH "path"
%token <std::string> STRING "string"
%token <std::string> MAP "map" %token <std::string> MAP "map"
%token <int> INT "integer" %token <int> INT "integer"
...@@ -127,6 +128,7 @@ stmt : expr { $$ = new ast::ExprStatement($1); } ...@@ -127,6 +128,7 @@ stmt : expr { $$ = new ast::ExprStatement($1); }
; ;
expr : INT { $$ = new ast::Integer($1); } expr : INT { $$ = new ast::Integer($1); }
| STRING { $$ = new ast::String($1.substr(1, $1.size()-2)); }
| IDENT { $$ = new ast::Builtin($1); } | IDENT { $$ = new ast::Builtin($1); }
| map { $$ = $1; } | map { $$ = $1; }
| "(" expr ")" { $$ = $2; } | "(" expr ")" { $$ = $2; }
......
...@@ -10,6 +10,12 @@ void Printer::visit(Integer &integer) ...@@ -10,6 +10,12 @@ void Printer::visit(Integer &integer)
out_ << indent << "int: " << integer.n << std::endl; out_ << indent << "int: " << integer.n << std::endl;
} }
void Printer::visit(String &string)
{
std::string indent(depth_, ' ');
out_ << indent << "string: " << string.str << std::endl;
}
void Printer::visit(Builtin &builtin) void Printer::visit(Builtin &builtin)
{ {
std::string indent(depth_, ' '); std::string indent(depth_, ' ');
......
...@@ -11,6 +11,7 @@ public: ...@@ -11,6 +11,7 @@ public:
explicit Printer(std::ostream &out) : out_(out) { } explicit Printer(std::ostream &out) : out_(out) { }
void visit(Integer &integer) override; void visit(Integer &integer) override;
void visit(String &string) override;
void visit(Builtin &builtin) override; void visit(Builtin &builtin) override;
void visit(Call &call) override; void visit(Call &call) override;
void visit(Map &map) override; void visit(Map &map) override;
......
...@@ -13,6 +13,14 @@ void SemanticAnalyser::visit(Integer &integer) ...@@ -13,6 +13,14 @@ void SemanticAnalyser::visit(Integer &integer)
integer.type = SizedType(Type::integer, 8); integer.type = SizedType(Type::integer, 8);
} }
void SemanticAnalyser::visit(String &string)
{
if (string.str.size() > STRING_SIZE-1) {
err_ << "String is too long (over " << STRING_SIZE << " bytes): " << string.str << std::endl;
}
string.type = SizedType(Type::string, STRING_SIZE);
}
void SemanticAnalyser::visit(Builtin &builtin) void SemanticAnalyser::visit(Builtin &builtin)
{ {
if (builtin.ident == "nsecs" || if (builtin.ident == "nsecs" ||
......
...@@ -18,6 +18,7 @@ public: ...@@ -18,6 +18,7 @@ public:
out_(out) { } out_(out) { }
void visit(Integer &integer) override; void visit(Integer &integer) override;
void visit(String &string) override;
void visit(Builtin &builtin) override; void visit(Builtin &builtin) override;
void visit(Call &call) override; void visit(Call &call) override;
void visit(Map &map) override; void visit(Map &map) override;
......
...@@ -31,6 +31,7 @@ std::string typestr(Type t) ...@@ -31,6 +31,7 @@ std::string typestr(Type t)
case Type::count: return "count"; break; case Type::count: return "count"; break;
case Type::stack: return "stack"; break; case Type::stack: return "stack"; break;
case Type::ustack: return "ustack"; break; case Type::ustack: return "ustack"; break;
case Type::string: return "string"; break;
default: abort(); default: abort();
} }
} }
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
namespace bpftrace { namespace bpftrace {
const int MAX_STACK_SIZE = 32; const int MAX_STACK_SIZE = 32;
const int STRING_SIZE = 32;
enum class Type enum class Type
{ {
......
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