Commit a28012be authored by Alastair Robertson's avatar Alastair Robertson

Add string type

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