Example #1
0
void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints, 
                                     raw_ostream &OS) {
  OS << "// Code for generating Intrinsic function declarations.\n";
  OS << "#ifdef GET_INTRINSIC_GENERATOR\n";
  OS << "  switch (id) {\n";
  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
  
  // Similar to GET_INTRINSIC_VERIFIER, batch up cases that have identical
  // types.
  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
  MapTy UniqueArgInfos;
  
  // Compute the unique argument type info.
  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
                             Ints[i].IS.ParamTypeDefs)].push_back(i);

  // Loop through the array, emitting one generator for each batch.
  std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
  
  for (MapTy::iterator I = UniqueArgInfos.begin(),
       E = UniqueArgInfos.end(); I != E; ++I) {
    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
      OS << "  case " << IntrinsicStr << Ints[I->second[i]].EnumName 
         << ":\t\t// " << Ints[I->second[i]].Name << "\n";
    
    const RecPair &ArgTypes = I->first;
    const std::vector<Record*> &RetTys = ArgTypes.first;
    const std::vector<Record*> &ParamTys = ArgTypes.second;

    unsigned N = ParamTys.size();

    if (N > 1 &&
        getValueType(ParamTys[N - 1]->getValueAsDef("VT")) == MVT::isVoid) {
      OS << "    IsVarArg = true;\n";
      --N;
    }

    unsigned ArgNo = 0;
    OS << "    ResultTy = ";
    EmitTypeGenerate(OS, RetTys, ArgNo);
    OS << ";\n";
    
    for (unsigned j = 0; j != N; ++j) {
      OS << "    ArgTys.push_back(";
      EmitTypeGenerate(OS, ParamTys[j], ArgNo);
      OS << ");\n";
    }

    OS << "    break;\n";
  }

  OS << "  }\n";
  OS << "#endif\n\n";
}
void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints, 
                                    std::ostream &OS) {
  OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
  OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
  OS << "  switch (ID) {\n";
  OS << "  default: assert(0 && \"Invalid intrinsic!\");\n";
  
  // This checking can emit a lot of very common code.  To reduce the amount of
  // code that we emit, batch up cases that have identical types.  This avoids
  // problems where GCC can run out of memory compiling Verifier.cpp.
  typedef std::map<RecPair, std::vector<unsigned>, RecordListComparator> MapTy;
  MapTy UniqueArgInfos;
  
  // Compute the unique argument type info.
  for (unsigned i = 0, e = Ints.size(); i != e; ++i)
    UniqueArgInfos[make_pair(Ints[i].IS.RetTypeDefs,
                             Ints[i].IS.ParamTypeDefs)].push_back(i);

  // Loop through the array, emitting one comparison for each batch.
  for (MapTy::iterator I = UniqueArgInfos.begin(),
       E = UniqueArgInfos.end(); I != E; ++I) {
    for (unsigned i = 0, e = I->second.size(); i != e; ++i)
      OS << "  case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
         << Ints[I->second[i]].Name << "\n";
    
    const RecPair &ArgTypes = I->first;
    const std::vector<Record*> &RetTys = ArgTypes.first;
    const std::vector<Record*> &ParamTys = ArgTypes.second;

    OS << "    VerifyIntrinsicPrototype(ID, IF, " << RetTys.size() << ", "
       << ParamTys.size();

    // Emit return types.
    for (unsigned j = 0, je = RetTys.size(); j != je; ++j) {
      Record *ArgType = RetTys[j];
      OS << ", ";

      if (ArgType->isSubClassOf("LLVMMatchType")) {
        unsigned Number = ArgType->getValueAsInt("Number");
        assert(Number < j && "Invalid matching number!");
        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
          OS << "~(ExtendedElementVectorType | " << Number << ")";
        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
          OS << "~(TruncatedElementVectorType | " << Number << ")";
        else
          OS << "~" << Number;
      } else {
        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
        OS << getEnumName(VT);

        if (VT == MVT::isVoid && j != 0 && j != je - 1)
          throw "Var arg type not last argument";
      }
    }

    // Emit the parameter types.
    for (unsigned j = 0, je = ParamTys.size(); j != je; ++j) {
      Record *ArgType = ParamTys[j];
      OS << ", ";

      if (ArgType->isSubClassOf("LLVMMatchType")) {
        unsigned Number = ArgType->getValueAsInt("Number");
        assert(Number < j + RetTys.size() && "Invalid matching number!");
        if (ArgType->isSubClassOf("LLVMExtendedElementVectorType"))
          OS << "~(ExtendedElementVectorType | " << Number << ")";
        else if (ArgType->isSubClassOf("LLVMTruncatedElementVectorType"))
          OS << "~(TruncatedElementVectorType | " << Number << ")";
        else
          OS << "~" << Number;
      } else {
        MVT::SimpleValueType VT = getValueType(ArgType->getValueAsDef("VT"));
        OS << getEnumName(VT);

        if (VT == MVT::isVoid && j != 0 && j != je - 1)
          throw "Var arg type not last argument";
      }
    }
      
    OS << ");\n";
    OS << "    break;\n";
  }
  OS << "  }\n";
  OS << "#endif\n\n";
}