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;
  }
Exemple #2
0
    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;
  }