Add two csmith benching scripts
This commit is contained in:
parent
7960b5ba08
commit
715a8f371a
3 changed files with 130 additions and 0 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -33,3 +33,4 @@
|
||||||
|
|
||||||
dwarf-assembly
|
dwarf-assembly
|
||||||
__pycache__
|
__pycache__
|
||||||
|
platform.info
|
||||||
|
|
5
benching/csmith/csmith-bench.sh
Executable file
5
benching/csmith/csmith-bench.sh
Executable file
|
@ -0,0 +1,5 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
csmith "$@" | \
|
||||||
|
sed 's/#include "csmith.h"/#include "bench.h"\n#include "csmith.h"/g' |\
|
||||||
|
sed 's/return /bench_unwinding(); return/g'
|
124
benching/csmith/gen_call_graph.py
Executable file
124
benching/csmith/gen_call_graph.py
Executable file
|
@ -0,0 +1,124 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
""" Generates the call graph (in dot format) of a C code generated by CSmith.
|
||||||
|
|
||||||
|
This does not parse C code, but performs only string lookups. In particular, it
|
||||||
|
assumes functions are named `func_[0-9]+` or `main`, and that a function
|
||||||
|
implementation is of the form (whitespaces meaningful)
|
||||||
|
|
||||||
|
(static)? RETURN_TYPE func_[0-9]+(.*)
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
|
||||||
|
|
||||||
|
def build_graph(prog):
|
||||||
|
func_declare_re = re.compile(r'(?:static )?\S.* (func_\d+|main) ?\(.*\)$')
|
||||||
|
func_call_re = re.compile(r'func_\d+')
|
||||||
|
|
||||||
|
graph = {}
|
||||||
|
cur_function = None
|
||||||
|
|
||||||
|
for line in prog:
|
||||||
|
func_declare_groups = func_declare_re.match(line)
|
||||||
|
if func_declare_groups:
|
||||||
|
func_name = func_declare_groups.group(1)
|
||||||
|
cur_function = func_name
|
||||||
|
graph[func_name] = []
|
||||||
|
|
||||||
|
elif line == '}':
|
||||||
|
cur_function = None
|
||||||
|
|
||||||
|
else:
|
||||||
|
if cur_function is None:
|
||||||
|
continue # Not interresting outside of functions
|
||||||
|
|
||||||
|
last_find_pos = 0
|
||||||
|
call_match = func_call_re.search(line, pos=last_find_pos)
|
||||||
|
|
||||||
|
while call_match is not None:
|
||||||
|
graph[cur_function].append(call_match.group(0))
|
||||||
|
last_find_pos = call_match.end()
|
||||||
|
call_match = func_call_re.search(line, pos=last_find_pos)
|
||||||
|
|
||||||
|
reachable = set()
|
||||||
|
def mark_reachable(node):
|
||||||
|
nonlocal reachable, graph
|
||||||
|
if node in reachable:
|
||||||
|
return
|
||||||
|
reachable.add(node)
|
||||||
|
|
||||||
|
for child in graph[node]:
|
||||||
|
mark_reachable(child)
|
||||||
|
mark_reachable('main')
|
||||||
|
|
||||||
|
delete = []
|
||||||
|
for node in graph:
|
||||||
|
if node not in reachable:
|
||||||
|
delete.append(node)
|
||||||
|
for node in delete:
|
||||||
|
print('> Deleted: {}'.format(node), file=sys.stderr)
|
||||||
|
graph.pop(node)
|
||||||
|
|
||||||
|
return graph
|
||||||
|
|
||||||
|
|
||||||
|
def dump_graph(graph):
|
||||||
|
print('digraph prog {')
|
||||||
|
|
||||||
|
for node in graph:
|
||||||
|
for call in graph[node]:
|
||||||
|
if call in graph:
|
||||||
|
print('\t{} -> {}'.format(node, call))
|
||||||
|
else:
|
||||||
|
print('Wtf is {} (called from {})?'.format(node, call),
|
||||||
|
file=sys.stderr)
|
||||||
|
print('}')
|
||||||
|
|
||||||
|
|
||||||
|
def dump_stats(graph, out_file):
|
||||||
|
entry_point = 'main'
|
||||||
|
|
||||||
|
depth_of = {}
|
||||||
|
def find_depth(node):
|
||||||
|
nonlocal depth_of
|
||||||
|
|
||||||
|
if node in depth_of:
|
||||||
|
return depth_of[node]
|
||||||
|
|
||||||
|
callees = graph[node]
|
||||||
|
if callees:
|
||||||
|
depth = max(map(find_depth, callees)) + 1
|
||||||
|
else:
|
||||||
|
depth = 1
|
||||||
|
depth_of[node] = depth
|
||||||
|
return depth
|
||||||
|
|
||||||
|
print("Call chain max depth: {}".format(find_depth(entry_point)),
|
||||||
|
file=out_file)
|
||||||
|
|
||||||
|
|
||||||
|
def get_prog_lines():
|
||||||
|
def do_read(handle):
|
||||||
|
return handle.readlines()
|
||||||
|
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
with open(sys.argv[1], 'r') as handle:
|
||||||
|
return do_read(handle)
|
||||||
|
else:
|
||||||
|
return do_read(sys.stdin)
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
prog = get_prog_lines()
|
||||||
|
graph = build_graph(prog)
|
||||||
|
dump_graph(graph)
|
||||||
|
dump_stats(graph, out_file=sys.stderr)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
Loading…
Reference in a new issue