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"; }