/*
   * 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;
  }
Exemplo n.º 2
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;
  }