bool enforceInterface(Module& M, ComponentInterface& T, bool inside) { for (ComponentInterface::FunctionIterator i = T.begin(), e = T.end(); i != e; ++i) { Function* f = M.getFunction(i->first()); if (f == NULL) continue; if (inside) { if (!f->isDeclaration()) { FunctionContract* contract = getContractFromInterface(f->getName(), T); if (contract) { enforceInterfaceInside(f, *contract); delete contract; } } } else { if (f->isDeclaration()) { FunctionContract* contract = getContractFromInterface(f->getName(), T); if (contract) { enforceInterfaceOutside(f, *contract); delete contract; } } } } return true; }
virtual bool runOnModule(Module& M) { AliasAnalysis& aa = this->getAnalysis<AliasAnalysis>(); bool checked = false; errs() << "GatherInterfacePass::runOnModule: " << M.getModuleIdentifier() << "\n"; if (!GatherInterfaceMain.empty()) { checked = true; for (cl::list<std::string>::const_iterator i = GatherInterfaceMain.begin(), e = GatherInterfaceMain.end(); i != e; ++i) { Function* f = M.getFunction(*i); if (f == NULL) { errs() << "Function '" << *i << "' not found, skipping\n"; continue; } if (f->isDeclaration()) { errs() << "Function '" << *i << "' is declaration, skipping\n"; continue; } errs() << "Gathering from: " << *f << "\n"; GatherInterface(*f, this->interface, &aa); } } if (!GatherInterfaceEntry.empty()) { checked = true; ComponentInterface ci; for (cl::list<std::string>::const_iterator i = GatherInterfaceEntry.begin(), e = GatherInterfaceEntry.end(); i != e; ++i) { errs() << "Reading interface from '" << *i << "'..."; if (ci.readFromFile(*i)) { errs() << "success\n"; } else { errs() << "failed\n"; continue; } } for (ComponentInterface::FunctionIterator i = ci.begin(), e = ci.end(); i != e; ++i) { Function* f = M.getFunction(i->first()); if (f == NULL) continue; if (!GatherInterface(*f, this->interface, &aa)) break; } } if (!checked) { GatherInterface(M, this->interface, &aa); } if (GatherInterfaceOutput != "") { proto::ComponentInterface ci; codeInto<ComponentInterface, proto::ComponentInterface> ( this->interface, ci); std::ofstream output(GatherInterfaceOutput.c_str(), std::ios::binary); assert(ci.SerializeToOstream(&output)); output.close(); } return false; }
void codeInto<ComponentInterfaceTransform, proto::ComponentInterfaceTransform> ( const ComponentInterfaceTransform& ci, proto::ComponentInterfaceTransform& buf) { for (ComponentInterface::FunctionIterator fi = ci.interface->begin(), fe = ci.interface->end(); fi != fe; ++fi) { for (ComponentInterface::CallIterator c = ci.interface->call_begin(fi), e = ci.interface->call_end(fi); c != e; ++c) { const CallRewrite* rw = ci.lookupRewrite(fi->first(), *c); if (rw != NULL) { proto::CallRewrite* nrw = buf.add_calls(); codeInto<CallRewrite, proto::CallRewrite> (*rw, *nrw); nrw->mutable_call()->set_name(fi->first()); codeInto<CallInfo, proto::CallInfo> (**c, *nrw->mutable_call()); } } } }
void codeInto<ComponentInterface, proto::ComponentInterface> ( const ComponentInterface& ci, proto::ComponentInterface& buf) { for (ComponentInterface::FunctionIterator f = ci.calls.begin(), fe = ci.calls.end(); f != fe; ++f) { for (ComponentInterface::CallIterator c = f->second.begin(), ce = f->second.end(); c != ce; ++c) { proto::CallInfo* info = buf.add_calls(); info->set_name(f->first()); codeInto<CallInfo, proto::CallInfo> (**c, *info); } } buf.mutable_references()->Reserve(ci.references.size()); for (std::set<std::string>::const_iterator i = ci.references.begin(), e = ci.references.end(); i != e; ++i) { buf.add_references(*i); } }
/* * Reduce this module with respect to the given interface. * - The interface suggests some of the uses of the functions, * so here we can generate special versions of those functions. * Generate a ComponentInterfaceTransform for clients to rewrite their * code to use the new API */ bool SpecializeComponent(Module& M, ComponentInterfaceTransform& T, SpecializationPolicy &policy, std::list<Function*>& to_add) { int rewrite_count = 0; const ComponentInterface& I = T.getInterface(); // TODO: What needs to be done? // - Should try to handle strings & arrays for (ComponentInterface::FunctionIterator ff = I.begin(), fe = I.end(); ff != fe; ++ff) { StringRef name = ff->first(); Function* func = resolveFunction(M, name); if (func == NULL || func->isDeclaration()) { // We don't specialize declarations because we don't own them continue; } for (ComponentInterface::CallIterator cc = I.call_begin(name), ce = I.call_end(name); cc != ce; ++cc) { const CallInfo* const call = *cc; const unsigned arg_count = call->args.size(); if (func->isVarArg()) { // TODO: I don't know how to specialize variable argument functions yet continue; } if (arg_count != func->getArgumentList().size()) { // Not referring to this function? // NOTE: I can't assert this equality because of the way that approximations occur continue; } SmallBitVector slice(arg_count); bool shouldSpecialize = policy.specializeOn(func, call->args.begin(), call->args.end(), slice); if (!shouldSpecialize) continue; std::vector<Value*> args; std::vector<unsigned> argPerm; args.reserve(arg_count); argPerm.reserve(slice.count()); for (unsigned i = 0; i < arg_count; i++) { if (slice.test(i)) { Type * paramType = func->getFunctionType()->getParamType(i); Value *concreteArg = call->args[i].concretize(M, paramType); args.push_back(concreteArg); assert(concreteArg->getType() == paramType && "Specializing function with concrete argument of wrong type!"); } else { args.push_back(NULL); argPerm.push_back(i); } } Function* nfunc = specializeFunction(func, args); nfunc->setLinkage(GlobalValue::ExternalLinkage); FunctionHandle rewriteTo = nfunc->getName(); T.rewrite(name, call, rewriteTo, argPerm); to_add.push_back(nfunc); rewrite_count++; } } if (rewrite_count > 0) { errs() << rewrite_count << " pending rewrites\n"; } return rewrite_count > 0; }
/* * Reduce this module with respect to the given interface. * - The interface suggests some of the uses of the functions, * so here we can generate special versions of those functions. * Generate a ComponentInterfaceTransform for clients to rewrite their * code to use the new API */ bool SpecializeComponent(Module& M, ComponentInterfaceTransform& T, SpecializationPolicy &policy, std::list<Function*>& to_add) { errs() << "SpecializeComponent()\n"; int rewrite_count = 0; const ComponentInterface& I = T.getInterface(); // TODO: What needs to be done? // - Should try to handle strings & arrays // Iterate through all functions in the interface of T for (ComponentInterface::FunctionIterator ff = I.begin(), fe = I.end(); ff != fe; ++ff) { StringRef name = ff->first(); Function* func = resolveFunction(M, name); if (func == NULL || func->isDeclaration()) { // We don't specialize declarations because we don't own them continue; } // Now iterate through all calls to func in the interface of T for (ComponentInterface::CallIterator cc = I.call_begin(name), ce = I.call_end(name); cc != ce; ++cc) { const CallInfo* const call = *cc; const unsigned arg_count = call->args.size(); if (func->isVarArg()) { // TODO: I don't know how to specialize variable argument functions yet continue; } if (arg_count != func->getArgumentList().size()) { // Not referring to this function? // NOTE: I can't assert this equality because of the way that approximations occur continue; } /* should we specialize? if yes then each bit in slice will indicate whether the argument is a specializable constant */ SmallBitVector slice(arg_count); bool shouldSpecialize = policy.specializeOn(func, call->args.begin(), call->args.end(), slice); if (!shouldSpecialize) continue; std::vector<Value*> args; std::vector<unsigned> argPerm; args.reserve(arg_count); argPerm.reserve(slice.count()); for (unsigned i = 0; i < arg_count; i++) { if (slice.test(i)) { Type * paramType = func->getFunctionType()->getParamType(i); Value *concreteArg = call->args[i].concretize(M, paramType); args.push_back(concreteArg); assert(concreteArg->getType() == paramType && "Specializing function with concrete argument of wrong type!"); } else { args.push_back(NULL); argPerm.push_back(i); } } /* args is a list of pointers to values -- if the pointer is NULL then that argument is not specialized -- if the pointer is not NULL then the argument will be/has been specialized to that value argsPerm is a list on integers; the indices of the non-special arguments args[i] = NULL iff i is in argsPerm for i < arg_count. */ Function* nfunc = specializeFunction(func, args); nfunc->setLinkage(GlobalValue::ExternalLinkage); FunctionHandle rewriteTo = nfunc->getName(); T.rewrite(name, call, rewriteTo, argPerm); to_add.push_back(nfunc); errs() << "Specialized " << name << " to " << rewriteTo << "\n"; #if 0 for (unsigned i = 0; i < arg_count; i++) { errs() << "i = " << i << ": slice[i] = " << slice[i] << " args[i] = " << args.at(i) << "\n"; } errs() << " argPerm = ["; for (unsigned i = 0; i < argPerm.size(); i++) { errs() << argPerm.at(i) << " "; } errs() << "]\n"; #endif rewrite_count++; } } if (rewrite_count > 0) { errs() << rewrite_count << " pending rewrites\n"; } return rewrite_count > 0; }