Commit ccdf4d2b authored by Alastair Robertson's avatar Alastair Robertson

Change syntax for delete() function

A value is now deleted by calling: delete(@x)
parent 54043d13
......@@ -41,7 +41,7 @@ kprobe:sys_read
kretprobe:sys_read / @start[tid] /
{
@times = quantize(nsecs - @start[tid]);
@start[tid] = delete();
delete(@start[tid]);
}
```
```
......@@ -203,7 +203,7 @@ Variables:
Functions:
- `quantize(int n)` - Produce a log2 histogram of values of `n`
- `count()` - Count the number of times this function is called
- `delete()` - Delete the map element this is assigned to
- `delete(@x)` - Delete the map element passed in as an argument
- `str(char *s)` - Returns the string pointed to by `s`
- `printf(char *fmt, ...)` - Write to stdout
- `sym(void *p)` - Resolve kernel address
......
......@@ -25,6 +25,7 @@ public:
Variable *var = nullptr; // Set when this expression is assigned to a variable
bool is_literal = false;
bool is_variable = false;
bool is_map = false;
};
using ExpressionList = std::vector<Expression *>;
......@@ -64,8 +65,8 @@ public:
class Map : public Expression {
public:
explicit Map(std::string &ident) : ident(ident), vargs(nullptr) { }
Map(std::string &ident, ExpressionList *vargs) : ident(ident), vargs(vargs) { }
explicit Map(std::string &ident) : ident(ident), vargs(nullptr) { is_map = true; }
Map(std::string &ident, ExpressionList *vargs) : ident(ident), vargs(vargs) { is_map = true; }
std::string ident;
ExpressionList *vargs;
......
......@@ -138,7 +138,8 @@ void CodegenLLVM::visit(Call &call)
}
else if (call.func == "delete")
{
Map &map = *call.map;
auto &arg = *call.vargs->at(0);
auto &map = static_cast<Map&>(arg);
AllocaInst *key = getMapKey(map);
b_.CreateMapDeleteElem(map, key);
b_.CreateLifetimeEnd(key);
......
......@@ -95,10 +95,14 @@ void SemanticAnalyser::visit(Call &call)
call.type = SizedType(Type::count, 8);
}
else if (call.func == "delete") {
check_assignment(call, true, false);
check_nargs(call, 0);
check_assignment(call, false, false);
if (check_nargs(call, 1)) {
auto &arg = *call.vargs->at(0);
if (!arg.is_map)
err_ << "delete() expects a map to be provided" << std::endl;
}
call.type = SizedType(Type::del, 0);
call.type = SizedType(Type::none, 0);
}
else if (call.func == "str" || call.func == "sym" || call.func == "usym") {
check_nargs(call, 1);
......@@ -324,8 +328,7 @@ void SemanticAnalyser::visit(AssignMapStatement &assignment)
search->second = assignment.expr->type;
}
}
else if (search->second.type != assignment.expr->type.type &&
assignment.expr->type.type != Type::del) {
else if (search->second.type != assignment.expr->type.type) {
err_ << "Type mismatch for " << map_ident << ": ";
err_ << "trying to assign value of type '" << assignment.expr->type;
err_ << "'\n\twhen map already contains a value of type '";
......@@ -367,8 +370,7 @@ void SemanticAnalyser::visit(AssignVarStatement &assignment)
search->second = assignment.expr->type;
}
}
else if (search->second.type != assignment.expr->type.type &&
assignment.expr->type.type != Type::del) {
else if (search->second.type != assignment.expr->type.type) {
err_ << "Type mismatch for " << var_ident << ": ";
err_ << "trying to assign value of type '" << assignment.expr->type;
err_ << "'\n\twhen variable already contains a value of type '";
......
......@@ -14,7 +14,6 @@ const int STRING_SIZE = 64;
enum class Type
{
none,
del,
integer,
quantize,
count,
......
......@@ -856,7 +856,7 @@ attributes #1 = { argmemonly nounwind }
TEST(codegen, call_delete)
{
test("kprobe:f { @x = delete() }",
test("kprobe:f { @x = 1; delete(@x) }",
R"EXPECTED(; Function Attrs: nounwind
declare i64 @llvm.bpf.pseudo(i64, i64) #0
......@@ -866,13 +866,25 @@ declare void @llvm.lifetime.start.p0i8(i64, i8* nocapture) #1
define i64 @"kprobe:f"(i8* nocapture readnone) local_unnamed_addr section "s_kprobe:f" {
entry:
%"@x_key1" = alloca i64, align 8
%"@x_val" = alloca i64, align 8
%"@x_key" = alloca i64, align 8
%1 = bitcast i64* %"@x_key" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %1)
store i64 0, i64* %"@x_key", align 8
%2 = bitcast i64* %"@x_val" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %2)
store i64 1, i64* %"@x_val", align 8
%pseudo = tail call i64 @llvm.bpf.pseudo(i64 1, i64 1)
%delete_elem = call i64 inttoptr (i64 3 to i64 (i8*, i8*)*)(i64 %pseudo, i64* nonnull %"@x_key")
%update_elem = call i64 inttoptr (i64 2 to i64 (i8*, i8*, i8*, i64)*)(i64 %pseudo, i64* nonnull %"@x_key", i64* nonnull %"@x_val", i64 0)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %1)
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %2)
%3 = bitcast i64* %"@x_key1" to i8*
call void @llvm.lifetime.start.p0i8(i64 -1, i8* nonnull %3)
store i64 0, i64* %"@x_key1", align 8
%pseudo2 = call i64 @llvm.bpf.pseudo(i64 1, i64 1)
%delete_elem = call i64 inttoptr (i64 3 to i64 (i8*, i8*)*)(i64 %pseudo2, i64* nonnull %"@x_key1")
call void @llvm.lifetime.end.p0i8(i64 -1, i8* nonnull %3)
ret i64 0
}
......
......@@ -80,7 +80,7 @@ TEST(semantic_analyser, builtin_functions)
{
test("kprobe:f { @x = quantize(123) }", 0);
test("kprobe:f { @x = count() }", 0);
test("kprobe:f { @x = delete() }", 0);
test("kprobe:f { @x = 1; delete(@x) }", 0);
test("kprobe:f { str(0xffff) }", 0);
test("kprobe:f { printf(\"hello\\n\") }", 0);
test("kprobe:f { sym(0xffff) }", 0);
......@@ -116,7 +116,6 @@ TEST(semantic_analyser, mismatched_call_types)
{
test("kprobe:f { @x = 1; @x = count(); }", 1);
test("kprobe:f { @x = 1; @x = quantize(0); }", 1);
test("kprobe:f { @x = 1; @x = delete(); }", 0);
}
TEST(semantic_analyser, call_quantize)
......@@ -135,9 +134,11 @@ TEST(semantic_analyser, call_count)
TEST(semantic_analyser, call_delete)
{
test("kprobe:f { @x = delete(); }", 0);
test("kprobe:f { @x = delete(1); }", 1);
test("kprobe:f { @x = 1; delete(@x); }", 0);
test("kprobe:f { delete(1); }", 1);
test("kprobe:f { delete(); }", 1);
test("kprobe:f { @y = delete(@x); }", 1);
test("kprobe:f { $y = delete(@x); }", 1);
}
TEST(semantic_analyser, call_str)
......
......@@ -29,12 +29,12 @@ kprobe:blk_account_io_completion
($now - @epoch) / 1000000, @iocomm[arg0], @iopid[arg0],
($now - @start[arg0]) / 1000000);
@start[arg0] = delete();
@iopid[arg0] = delete();
@iocomm[arg0] = delete();
delete(@start[arg0]);
delete(@iopid[arg0]);
delete(@iocomm[arg0]);
}
END
{
@epoch = delete();
delete(@epoch);
}
......@@ -38,5 +38,5 @@ kprobe:sys_execve
END
{
@epoch = delete();
delete(@epoch);
}
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