Skip to content

Commit

Permalink
Fix Layers W/ Multiple Inheretence W/ Templates
Browse files Browse the repository at this point in the history
Fixes #15
  • Loading branch information
fundamental committed Apr 25, 2015
1 parent 44bb66d commit 248180d
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 39 deletions.
5 changes: 5 additions & 0 deletions data/whitelist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,11 @@ _ZSt9terminatev
rand
scalbnf

strchr
__log2_finite
__divdc3
__mulsc3

# hacks here
struct.rtosc::RtData0
struct.rtosc::RtData1
Expand Down
87 changes: 64 additions & 23 deletions lib/callgraph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -232,10 +232,11 @@ def add_destructor_chains()
def add_virtual_methods(vtables)
vtables.each do |cs, value|
value.each do |id, method|
css = cs.gsub(/.variant.$/,"")
css = cs.gsub(/.variant.*$/,"")
virtual_method = "#{css}$vtable#{id}"
declare virtual_method
if(method != "(none)" && method != "__cxa_pure_virtual")
#puts "vtable link #{virtual_method} -> #{method}"
declare method
strict_link(virtual_method, method)
self[virtual_method].add_attr :body
Expand All @@ -251,34 +252,74 @@ def has_method?(method)
# Add Plausible Virtual Method Calls Down the Class Hierarchy
def add_subclass_calls(classes, vtables)
classes.each do |sub, supers|
currently_processed = 100
iter = 0
vtoff = 0
supers.each do |super_|
vt = nil
if(iter == 0)
if(vtables.has_key?(sub))
vt = vtables[sub]
vtoff = nil
#puts "-------------------------------"
#pp sub
#pp supers
supers.reverse.each do |super_|
sp = super_.split "+"
supname = sp[0]
offset = 0
if(sp.length == 2)
offset = sp[1].to_i
end
#puts "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<"
#puts "working on #{supname}-#{offset}"
(offset..currently_processed).each do |vt_id|
#vtoff = 0
vt = nil
vt2 = nil
vt_id2 = vt_id-offset
#puts "vt_id2=#{vt_id2}"
if(vt_id == 0)
if(vtables.has_key?(sub))
vt = vtables[sub]
end
else
if(vtables.has_key?(sub+".variant"+vt_id.to_s))
vt = vtables[sub+".variant"+vt_id.to_s]
end
end
else
if(vtables.has_key?(sub+".variant"+iter.to_s))
vt = vtables[sub+".variant"+iter.to_s]
if(vt_id2 == 0)
if(vtables.has_key?(supname))
vt2 = vtables[supname]
end
else
if(vtables.has_key?(supname+".variant"+vt_id2.to_s))
vt2 = vtables[supname+".variant"+vt_id2.to_s]
end
end
end
if(vt)
vt.length.times do |x|
testing = "#{super_}$vtable#{x}"
source = "#{sub}$vtable#{x+vtoff}"
if(has_method?(testing) || has_method?(source))
declare testing
declare source
strict_link(testing,source)
self[testing].add_attr :body
self[source].add_attr :body
#if(vtables.has_key?(supname))
# vt2 = vtables[supname]
#end
if(vt && vt2)

#pp vt
#pp vt.keys.min
#puts "Oh my head"
#pp vt2
#pp vt2.length
vtoff = vt.keys.min
vtoff2 = vt2.keys.min
vt.length.times do |x|
testing = "#{supname}$vtable#{x+vtoff2}"
source = "#{sub}$vtable#{x+vtoff}"
if((has_method?(testing) || has_method?(source)) && x<vt2.length)
#puts "#{testing} -> #{source}"
declare testing
declare source
strict_link(testing,source)
self[testing].add_attr :body
self[source].add_attr :body
end
end
vtoff += vt.length
iter += 1
end
vtoff += vt.length
iter += 1
end
currently_processed = offset-1
end
end
end
Expand Down
17 changes: 13 additions & 4 deletions lib/graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -88,30 +88,39 @@ def self.to_graph(deductions, callgraph, graphfile, minimal_graph, shorten)


puts "Generating Graph Nodes..."
argh = Hash.new
node_list = Hash.new
important_nodes.each do |key|
if(color_nodes.has_key?(key))
val = color_nodes[key]
name = callgraph.node_list[key].demangled_short
if(shorten)
name = shorten_name(name)
argh[key] = name
end
node_list[key] = g.add_nodes(name, "color"=> val,
:shape=>:box)
end
end

puts "Generating Graph Links..."
dont_repeat = Hash.new
important_nodes.each do |src|
callgraph.children(src).each do |dest|
if(important_nodes.include?(dest) && node_list.has_key?(src) &&
node_list.has_key?(dest))
if(deductions[dest].non_realtime_p)
g.add_edges(node_list[src], node_list[dest],
"color"=>(random_color), "style"=>"bold")
#if(!dont_repeat.has_key?([argh[src],argh[dest]]))
g.add_edges(node_list[src], node_list[dest],
"color"=>(random_color), "style"=>"bold")
dont_repeat[[argh[src],argh[dest]]] = true
#end
else
g.add_edges(node_list[src], node_list[dest],
"color"=>(random_color), "style"=>"dashed")
#if(!dont_repeat.has_key?([argh[src],argh[dest]]))
g.add_edges(node_list[src], node_list[dest],
"color"=>(random_color), "style"=>"dashed")
dont_repeat[[argh[src],argh[dest]]] = true
#end
end
end
end
Expand Down
20 changes: 17 additions & 3 deletions lib/load-callgraph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ def load_callgraph(opt, library, files)
vtable_ninformation = YAML.load_file "stoat_vtable.txt"
rtosc_ninformation = YAML.load_file "stoat_rtosc.txt"

alias_map = create_alias_map(class_nhigh)
dealias(alias_map, class_nhigh, ncallgraph)

merge_maps(callgraph, ncallgraph)
merge_maps(function_props, nfunc)
merge_maps(class_high, class_nhigh)
Expand Down Expand Up @@ -106,6 +109,9 @@ def load_callgraph(opt, library, files)

def create_alias_map(class_hierarchy)
class_high = class_hierarchy
if(!class_high)
return nil
end
alias_map = Hash.new
class_high.each do |key, val|
val.each do |x|
Expand All @@ -120,16 +126,24 @@ def create_alias_map(class_hierarchy)
end

def dealias(alias_map, class_high, callgraph)
if(!alias_map)
return
end
class_high.each do |key, val|
replace = []
val.each do |x|
if(alias_map.has_key?(x))
replace << alias_map[x]
sp = x.split("+")
if(alias_map.has_key?(sp[0]))
if(sp.length == 1)
replace << alias_map[sp[0]]
else
replace << alias_map[sp[0]]+"+"+sp[1]
end
else
replace << x
end
end
class_high[key] = val.uniq
class_high[key] = replace.uniq
end

callgraph.each do |parent, children|
Expand Down
28 changes: 21 additions & 7 deletions src/llvm-passes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ struct ExtractClassHierarchy : public FunctionPass {
return false;
}

string extractSuperClass(Instruction *this_ptr, BitCastInst *possible)
string extractSuperClass(Instruction *this_ptr, BitCastInst *possible, bool &hasTrueClass)
{
//Single Inheritance
if(auto load = dyn_cast<LoadInst>(possible->getOperand(0))) {
Expand All @@ -381,6 +381,10 @@ struct ExtractClassHierarchy : public FunctionPass {
llvm::raw_string_ostream ss(data_str);
possible->getDestTy()->getScalarType()->getScalarType()->print(ss);
std::string s = ss.str();
if(hasTrueClass)
return "";
hasTrueClass = true;
//fprintf(stderr, "norm name = %s\n", s.c_str());
int l = s.length();
if(s.substr(0,6) == "%class")
return s.substr(7, l-8);
Expand All @@ -390,26 +394,32 @@ struct ExtractClassHierarchy : public FunctionPass {
return ss.str().substr(8, l-9);
if(s.substr(0,8) == "%\"struct")
return s.substr(9, l-11);
hasTrueClass = false;
}
}

if(auto getelm = dyn_cast<GetElementPtrInst>(possible->getOperand(0))) {
if(auto cast = dyn_cast<BitCastInst>(getelm->getOperand(0))) {
if(auto load = dyn_cast<LoadInst>(cast->getOperand(0))) {
if(this_ptr == dyn_cast<Instruction>(load->getOperand(0))) {
//getelm->dump();
if(!dyn_cast<ConstantInt>(getelm->getOperand(1)))
return "";
unsigned off = dyn_cast<ConstantInt>(getelm->getOperand(1))->getZExtValue()/8;
std::string data_str;
llvm::raw_string_ostream ss(data_str);
possible->getDestTy()->getScalarType()->getScalarType()->print(ss);
std::string s = ss.str();
//fprintf(stderr, "name = %s\n", s.c_str());
int l = s.length();
if(s.substr(0,6) == "%class")
return s.substr(7, l-8);
return s.substr(7, l-8)+"+"+to_s(off);
if(s.substr(0,7) == "%\"class")
return s.substr(8, l-10);
return s.substr(8, l-10)+"+"+to_s(off);
if(s.substr(0,7) == "%struct")
return ss.str().substr(8, l-9);
return ss.str().substr(8, l-9)+"+"+to_s(off);
if(s.substr(0,8) == "%\"struct")
return s.substr(9, l-11);
return s.substr(9, l-11)+"+"+to_s(off);
}
}
}
Expand Down Expand Up @@ -438,14 +448,15 @@ struct ExtractClassHierarchy : public FunctionPass {

std::vector<string> class_list;
Instruction *this_ptr = NULL;
bool hasTrueClass = false;
for(auto &bb:Fn) {
for(auto &I:bb) {
if(!this_ptr && dyn_cast<AllocaInst>(&I))
this_ptr = &I;

if(auto bitcast = dyn_cast<BitCastInst>(&I))
{
auto super = extractSuperClass(this_ptr, bitcast);
auto super = extractSuperClass(this_ptr, bitcast, hasTrueClass);
if(!super.empty())
{
bool not_already_here = true;
Expand Down Expand Up @@ -557,7 +568,10 @@ struct ExtractVtables : public ModulePass {
fname = NULL;

if(!fname) {
fprintf(stderr, "%s.variant%d:\n", name, ++variant);
int variant_id = 0;
if(auto n = dyn_cast<ConstantInt>(op->getOperand(0)))
variant_id = -n->getZExtValue()/8;
fprintf(stderr, "%s.variant%d:\n", name, variant_id);//++variant);
i++;
ii+=2;
continue;
Expand Down
34 changes: 34 additions & 0 deletions test/confusing-multi-inherit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class A
{
public:
virtual void m1(){};
};

class B
{
public:
virtual void m2(){};
};

class C:public A, public B
{
public:
virtual void m3(){};
};

class D:public C
{
public:
virtual void m4()__attribute__((annotate("non-realtime"))){};
};

void foo(C*c)__attribute__((annotate("realtime")))
{
c->m2();
}

int main()
{
new D;
return 0;
}
Loading

0 comments on commit 248180d

Please sign in to comment.