Skip to content

Instantly share code, notes, and snippets.

@jdoerfert
Created October 16, 2019 18:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jdoerfert/c0abef910a66a680ce1f0625c4a264e6 to your computer and use it in GitHub Desktop.
Save jdoerfert/c0abef910a66a680ce1f0625c4a264e6 to your computer and use it in GitHub Desktop.
# Run grep -E 'class|struct AA|public AA|private AA|getAAFor|AAReturnedFromReturnedValues|AACallSiteReturnedFromReturned|MustBeExecutedContext|AAArgumentFromCallSiteArguments' llvm/lib/Transforms/IPO/Attributor.cpp &>! /tmp/dep_graph_inp
# Filter the first lines untill you hit AANoUnwind and the onies after AAMemoryBehaviorCallSite manually or put two comments in the source like: "// AA HERE"
# Filter the two occurences of getAAFor in front of AANonNull that are otherwise associated with AANoFree
# run the python scrip like:
# python dep_Graph.py /tmp/dep_graph_inp /tmp/dep_graph.dot
import sys
import re
import os
full = 'full' in sys.argv
get_re = re.compile('getAAFor<([^>]*)>')
aa_rv_re = re.compile('(AA\w+).*?:.*AA\w*From\w*<(AA[a-zA-Z]*)')
aa_re = re.compile('(AA\w+).*?:.*?(AA\w*)')
inh = {}
dep = {'AAReturnedValues':set(), 'AAIsDead':set()}
with open(sys.argv[1], 'r') as fd:
last_class = None
lines = fd.readlines()
erase = True
for i, line in enumerate(lines):
if 'HERE' in line:
erase = not erase
lines[i] = None
continue
if erase:
lines[i] = None
continue
if line.strip().startswith(':'):
if lines[i-1]:
if line[:-1].endswith('AACallSiteReturnedFromReturnedAndMustBeExecutedContext<'):
aaidx = lines[i-1].index('AA')
line = line[:-1] + lines[i-1][aaidx:aaidx+(lines[i-1][aaidx:].index(' '))-16] + ","
lines[i-1] = lines[i-1][:-1] + line
lines[i] = None
if 'getAAFor' in line:
continue
if 'using' in line or '//' in line or 'Base' in line or 'Tracker' in line or 'InfoCache' in line or '=' in line or ';' in line:
lines[i] = None
for line in lines:
if not line:
continue
print(line[:-1])
qm_match = get_re.search(line)
aa_rv_match = aa_rv_re.search(line)
aa_match = aa_re.search(line)
if qm_match:
cl = qm_match.group(1)
if not cl in dep:
dep[cl] = set()
dep[cl].add(last_class)
elif aa_rv_match:
new_class = aa_rv_match.group(1)
new_parent = aa_rv_match.group(2)
print(new_class, new_parent)
inh[new_class] = new_parent
if not last_class or last_class not in new_parent:
last_class = new_class
if 'AAReturnedValues' in line:
dep['AAReturnedValues'].add(last_class)
elif aa_match:
new_class = aa_match.group(1)
new_parent = aa_match.group(2)
print(new_class, new_parent)
inh[new_class] = new_parent
if not last_class or last_class not in new_parent:
last_class = new_class
else:
print('unknown', line)
print()
if full:
with open(sys.argv[2], 'w') as fd:
fd.write(f'digraph {os.path.basename(sys.argv[1])} {{{os.linesep}compound=true;{os.linesep}')
rev_inh = {}
for c,p in inh.items():
rev_inh[p] = c
if p not in inh:
fd.write(f'subgraph cluster_{p} {{{os.linesep}style=filled;{os.linesep}color=lightgrey;{os.linesep}node [style=filled,color=white];{os.linesep}')
for cl2, _ in inh.items():
if p in cl2:
fd.write(f' "{cl2}"')
fd.write(f'{os.linesep}label = "{p}";{os.linesep}}}{os.linesep}')
for cl, srcs in dep.items():
for src in srcs:
srcp = src
while srcp in inh:
if srcp == inh[srcp]:
print(srcp)
assert False
srcp = inh[srcp]
if srcp != cl:
fd.write(f' "{src}" -> "{rev_inh[cl]}" [ltail=cluster_{srcp},lhead=cluster_{cl}];{os.linesep}')
if cl in inh:
if inh[cl] in inh:
fd.write(f' "{inh[cl]}" -> "{cl}" [style=dotted];{os.linesep}')
elif cl is not 'AAIsDead':
fd.write(f' "{rev_inh[cl]}" -> "AAIsDeadFloating" [ltail=cluster_{cl},lhead=cluster_AAIsDead];{os.linesep}')
fd.write(f'}}{os.linesep}')
else:
with open(sys.argv[2], 'w') as fd:
fd.write(f'digraph {os.path.basename(sys.argv[1])} {{{os.linesep}')
for cl, srcs in dep.items():
for src in srcs:
fd.write(f' "{src}" -> "{cl}";{os.linesep}')
fd.write(f'}}{os.linesep}')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment