void codeInto<proto::ComponentInterfaceTransform, ComponentInterfaceTransform> ( const proto::ComponentInterfaceTransform& buf, ComponentInterfaceTransform& ci) { if (ci.interface == NULL) { ci.ownsIface = true; ci.interface = new ComponentInterface(); } assert (ci.interface != NULL); for (int i = 0; i < buf.calls_size(); i++) { const proto::CallRewrite& rw = buf.calls(i); const proto::CallInfo& info = rw.call(); StringRef name = info.name(); CallInfo res; codeInto<proto::CallInfo, CallInfo> (info, res); CallInfo* result = ci.interface->getOrCreateCall(name, res.args); result->count += info.count(); CallRewrite rewrite; codeInto<proto::CallRewrite, CallRewrite> (rw, rewrite); ci.rewrite(name, result, rewrite); } }
/* * 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; }