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 ento::CheckObjCInstMethSignature(const ObjCImplementationDecl* ID, BugReporter& BR) { const ObjCInterfaceDecl* D = ID->getClassInterface(); const ObjCInterfaceDecl* C = D->getSuperClass(); if (!C) return; ASTContext& Ctx = BR.getContext(); // Build a DenseMap of the methods for quick querying. typedef llvm::DenseMap<Selector,ObjCMethodDecl*> MapTy; MapTy IMeths; unsigned NumMethods = 0; for (ObjCImplementationDecl::instmeth_iterator I=ID->instmeth_begin(), E=ID->instmeth_end(); I!=E; ++I) { ObjCMethodDecl* M = *I; IMeths[M->getSelector()] = M; ++NumMethods; } // Now recurse the class hierarchy chain looking for methods with the // same signatures. while (C && NumMethods) { for (ObjCInterfaceDecl::instmeth_iterator I=C->instmeth_begin(), E=C->instmeth_end(); I!=E; ++I) { ObjCMethodDecl* M = *I; Selector S = M->getSelector(); MapTy::iterator MI = IMeths.find(S); if (MI == IMeths.end() || MI->second == 0) continue; --NumMethods; ObjCMethodDecl* MethDerived = MI->second; MI->second = 0; CompareReturnTypes(MethDerived, M, BR, Ctx, ID); } C = C->getSuperClass(); } }
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"; }
Stmt* ParentMap::getParent(Stmt* S) const { MapTy* M = (MapTy*) Impl; MapTy::iterator I = M->find(S); return I == M->end() ? 0 : I->second; }