Skip to content

Commit f41393a

Browse files
committed
change to access
1 parent 7f0f912 commit f41393a

File tree

5 files changed

+331
-126
lines changed

5 files changed

+331
-126
lines changed
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
2+
from collections import Counter
3+
from subprocess import run, PIPE
4+
5+
def parse_trace(trace_string) -> dict:
6+
7+
result = {}
8+
9+
# Split the trace string into lines
10+
lines = trace_string.split('\n')
11+
12+
for line in lines:
13+
if line == '':
14+
continue
15+
function, _, _, value = line.split(' ')
16+
if function not in result:
17+
result[function] = []
18+
result[function].append(value)
19+
20+
return result
21+
22+
def convert_to_count_dict(trace_dict) -> dict:
23+
result = {}
24+
for function, values in trace_dict.items():
25+
result[function] = Counter(values)
26+
return result
27+
28+
def parse_file(file_path) -> dict:
29+
with open(file_path, 'r') as f:
30+
trace_string = f.read()
31+
return parse_trace(trace_string)
32+
33+
def demangle_function_name(function_name):
34+
cmd = f"llvm-cxxfilt {function_name}"
35+
result = run(cmd, shell=True, stdout=PIPE)
36+
return result.stdout.decode('utf-8').strip()
37+
38+
def single_valued_functions(trace_dict):
39+
result = {}
40+
for function, values in trace_dict.items():
41+
if len(set(values)) == 1:
42+
if values[0] not in result:
43+
result[values[0]] = []
44+
result[values[0]].append(function)
45+
return result
46+
47+
def compare_single_valued_functions(trace_dict1, trace_dict2):
48+
single_valued_functions1 = single_valued_functions(trace_dict1)
49+
single_valued_functions2 = single_valued_functions(trace_dict2)
50+
51+
num_same = 0
52+
num_in_1 = 0
53+
num_in_2 = 0
54+
55+
for value, functions1 in single_valued_functions1.items():
56+
if value in single_valued_functions2:
57+
functions2 = single_valued_functions2[value]
58+
num_same += len([f for f in functions1 if f in functions2])
59+
num_in_1 += len([f for f in functions1 if f not in functions2])
60+
else:
61+
num_in_1 += len(functions1)
62+
63+
for value, functions2 in single_valued_functions2.items():
64+
if value not in single_valued_functions1:
65+
num_in_2 += len(functions2)
66+
67+
68+
return num_same, num_in_1, num_in_2
69+
70+
def omnipresent_functions(opt_level_dict):
71+
# count functions that occur in all traces
72+
functions = list(opt_level_dict.values())[0].keys()
73+
for opt_level, trace_dict in opt_level_dict.items():
74+
functions = functions & trace_dict.keys()
75+
return functions
76+
77+
def same_value_functions(opt_level_dict):
78+
# count functions that return the same values in all traces
79+
omnipresent = omnipresent_functions(opt_level_dict)
80+
81+
same_value_functions = []
82+
for function in omnipresent:
83+
function_values = set()
84+
for opt_level, trace_dict in opt_level_dict.items():
85+
for value in trace_dict[function]:
86+
function_values.add(value)
87+
if len(function_values) == 1:
88+
same_value_functions.append(function)
89+
90+
return same_value_functions
91+
92+
93+
94+
95+
96+
97+
def print_stats(trace_dict):
98+
99+
print('Function Trace Statistics')
100+
print('-------------------------')
101+
print(f"There are {len(trace_dict)} called functions")
102+
103+
num_single_value_functions = 0
104+
num_value_zero_functions = 0
105+
num_value_one_functions = 0
106+
other_values = []
107+
108+
for function, values in trace_dict.items():
109+
value_set = set(values)
110+
if len(value_set) == 1:
111+
num_single_value_functions += 1
112+
if '0' in value_set:
113+
num_value_zero_functions += 1
114+
elif '1' in value_set:
115+
num_value_one_functions += 1
116+
else:
117+
other_values.append(values[0])
118+
119+
print(f"There are {num_single_value_functions} functions that only return one value")
120+
print(f" {num_value_zero_functions} functions only return 0")
121+
print(f" {num_value_one_functions} functions only return 1")
122+
#print(f" Other values: {other_values}")
123+
124+
max_function = ''
125+
max_value = 0
126+
max_distinct_values = 0
127+
for function, values in trace_dict.items():
128+
if len(values) > max_value:
129+
max_value = len(values)
130+
max_function = function
131+
max_distinct_values = len(set(values))
132+
133+
print(f"The most-called function is \"{demangle_function_name(max_function)}\" with {max_value} calls and {max_distinct_values} distinct values")
134+
135+
136+
if __name__ == '__main__':
137+
138+
opt_levels = ['no_opt', 'O1', 'O2', 'O3', 'Os', 'Oz']
139+
opt_level_dicts = {}
140+
for opt_level in opt_levels:
141+
opt_level_dicts[opt_level] = parse_file(f'print_example/function_trace_{opt_level}.txt')
142+
for opt_level in opt_levels:
143+
print(f"Optimization Level: {opt_level}")
144+
result = opt_level_dicts[opt_level]
145+
print_stats(result)
146+
print()
147+
148+
for outer_index, outer_opt_level in enumerate(opt_levels):
149+
for inner_opt_level in opt_levels[:outer_index]:
150+
print(f"Comparing {outer_opt_level} and {inner_opt_level}")
151+
result1 = opt_level_dicts[outer_opt_level]
152+
result2 = opt_level_dicts[inner_opt_level]
153+
single_valued1 = single_valued_functions(result1)
154+
single_valued2 = single_valued_functions(result2)
155+
num_single_functions_1 = sum([len(functions) for functions in single_valued1.values()])
156+
num_single_functions_2 = sum([len(functions) for functions in single_valued2.values()])
157+
num_same, num_in_1, num_in_2 = compare_single_valued_functions(result1, result2)
158+
159+
print(f" {num_same} single-valued functions return the same value (out of {num_single_functions_1} in {outer_opt_level} and {num_single_functions_2} in {inner_opt_level})")
160+
print()
161+
162+
omnipresent = omnipresent_functions(opt_level_dicts)
163+
print(f"Functions that occur in all traces: {len(omnipresent)}")
164+
165+
same_value = same_value_functions(opt_level_dicts)
166+
print(f"Functions that return the same value in all traces: {len(same_value)}")
167+
168+
del opt_level_dicts['no_opt']
169+
print()
170+
171+
omnipresent = omnipresent_functions(opt_level_dicts)
172+
print(f"Functions that occur in all optimized traces: {len(omnipresent)}")
173+
174+
same_value = same_value_functions(opt_level_dicts)
175+
print(f"Functions that return the same value in all optimized traces: {len(same_value)}")
176+
177+
178+
#print("====================================================")
179+
#print("Partial Trace for 605")
180+
#print("====================================================")
181+
182+
#trace_605 = parse_file('function_trace_605.txt')
183+
#print_stats(trace_605)
184+
#print()
185+
186+
#omnipresent = omnipresent_functions({'605': trace_605})
187+
#print(f"Functions that occur in all traces: {len(omnipresent)}")
188+
189+
#same_value = same_value_functions({'605': trace_605})
190+
#print(f"Functions that return the same value in all traces: {len(same_value)}")

llvm/lib/Transforms/Utils/CFFunctionInstrumentation.cpp

Lines changed: 33 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ PreservedAnalyses
1010
CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
1111

1212
CFFunctionAnalysisInfo CalledFunctions = AM.getResult<CFFunctionAnalysis>(M);
13+
int permissions_created = 0;
14+
Value *WritePermission = nullptr;
15+
Value *FileName = nullptr;
1316
for (auto &F : M) {
1417
if (F.isDeclaration()) {
1518
continue;
@@ -24,7 +27,7 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
2427
continue;
2528
}
2629

27-
std::string outputString = F.getName().str() + " return value: %lld\n";
30+
std::string outputString = F.getName().str() + " %lld\n";
2831
StringRef funcFormatStr = StringRef(outputString);
2932
std::string fileName = "function_trace.txt";
3033
StringRef funcFileName = StringRef(fileName);
@@ -47,29 +50,35 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
4750

4851
// insert call to print function
4952
IRBuilder<> OrigBuilder(RI);
50-
FunctionCallee OpenFunc = M.getOrInsertFunction(
51-
"fopen", FunctionType::get(PointerType::get(M.getContext(), 0),
52-
{PointerType::get(M.getContext(), 0),
53-
PointerType::get(M.getContext(), 0)},
54-
false));
55-
Value *FileName = OrigBuilder.CreateGlobalStringPtr(funcFileName);
56-
Value *WritePermission = OrigBuilder.CreateGlobalStringPtr("a");
57-
Value *ReadPermission = OrigBuilder.CreateGlobalStringPtr("r");
53+
FunctionCallee AccessFunc = M.getOrInsertFunction(
54+
"access",
55+
FunctionType::get(IntegerType::getInt32Ty(M.getContext()),
56+
{PointerType::get(M.getContext(), 0),
57+
IntegerType::getInt32Ty(M.getContext())},
58+
false));
59+
60+
if (!permissions_created) {
61+
permissions_created = 1;
62+
FileName = OrigBuilder.CreateGlobalStringPtr(funcFileName);
63+
WritePermission = OrigBuilder.CreateGlobalStringPtr("a");
64+
}
5865

5966
// split at return
6067
BasicBlock *ReturnBB = BB.splitBasicBlock(RI, "return", false);
6168

62-
BasicBlock *OpenBB = BasicBlock::Create(M.getContext(), "open", &F);
69+
BasicBlock *AccessBB =
70+
BasicBlock::Create(M.getContext(), "access", &F);
6371
BasicBlock *PrintBB = BasicBlock::Create(M.getContext(), "print", &F);
6472

65-
IRBuilder<> OpenBuilder(OpenBB);
66-
Value *read_fptr =
67-
OpenBuilder.CreateCall(OpenFunc, {FileName, ReadPermission});
73+
IRBuilder<> AccessBuilder(AccessBB);
74+
// insert call to access function with filename and 0
75+
Value *status = AccessBuilder.CreateCall(
76+
AccessFunc, {FileName, AccessBuilder.getInt32(0)});
6877

69-
Value *Cmp = OpenBuilder.CreateICmpNE(
70-
read_fptr,
71-
ConstantPointerNull::get(PointerType::get(M.getContext(), 0)));
72-
OpenBuilder.CreateCondBr(Cmp, PrintBB, ReturnBB);
78+
Value *Cmp = AccessBuilder.CreateICmpEQ(
79+
status,
80+
ConstantInt::get(IntegerType::getInt32Ty(M.getContext()), 0));
81+
AccessBuilder.CreateCondBr(Cmp, PrintBB, ReturnBB);
7382

7483
IRBuilder<> PrintBuilder(PrintBB);
7584
FunctionCallee PrintFunc = M.getOrInsertFunction(
@@ -83,7 +92,12 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
8392
"fclose",
8493
FunctionType::get(Type::getInt32Ty(M.getContext()),
8594
{PointerType::get(M.getContext(), 0)}, false));
86-
PrintBuilder.CreateCall(CloseFunc, read_fptr);
95+
96+
FunctionCallee OpenFunc = M.getOrInsertFunction(
97+
"fopen", FunctionType::get(PointerType::get(M.getContext(), 0),
98+
{PointerType::get(M.getContext(), 0),
99+
PointerType::get(M.getContext(), 0)},
100+
false));
87101

88102
Value *write_fptr =
89103
PrintBuilder.CreateCall(OpenFunc, {FileName, WritePermission});
@@ -95,7 +109,7 @@ CFFunctionInstrumentationPass::run(Module &M, ModuleAnalysisManager &AM) {
95109
PrintBuilder.CreateCall(CloseFunc, write_fptr);
96110
PrintBuilder.CreateBr(ReturnBB);
97111

98-
BB.getTerminator()->setSuccessor(0, OpenBB);
112+
BB.getTerminator()->setSuccessor(0, AccessBB);
99113

100114
// place new BBs in the correct order
101115
ReturnBB->moveAfter(PrintBB);

print_example/instrumented

48 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)