// Emit the function name recognizer.
EmitFnNameRecognizer(Ints, OS);
- // Emit the intrinsic verifier.
- EmitVerifier(Ints, OS);
-
// Emit the intrinsic declaration generator.
EmitGenerator(Ints, OS);
OS << "#endif\n\n";
}
-/// RecordListComparator - Provide a deterministic comparator for lists of
-/// records.
-namespace {
- typedef std::pair<std::vector<Record*>, std::vector<Record*> > RecPair;
- struct RecordListComparator {
- bool operator()(const RecPair &LHS,
- const RecPair &RHS) const {
- unsigned i = 0;
- const std::vector<Record*> *LHSVec = &LHS.first;
- const std::vector<Record*> *RHSVec = &RHS.first;
- unsigned RHSSize = RHSVec->size();
- unsigned LHSSize = LHSVec->size();
-
- for (; i != LHSSize; ++i) {
- if (i == RHSSize) return false; // RHS is shorter than LHS.
- if ((*LHSVec)[i] != (*RHSVec)[i])
- return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
- }
-
- if (i != RHSSize) return true;
-
- i = 0;
- LHSVec = &LHS.second;
- RHSVec = &RHS.second;
- RHSSize = RHSVec->size();
- LHSSize = LHSVec->size();
-
- for (i = 0; i != LHSSize; ++i) {
- if (i == RHSSize) return false; // RHS is shorter than LHS.
- if ((*LHSVec)[i] != (*RHSVec)[i])
- return (*LHSVec)[i]->getName() < (*RHSVec)[i]->getName();
- }
-
- return i != RHSSize;
- }
- };
-}
-
-void IntrinsicEmitter::EmitVerifier(const std::vector<CodeGenIntrinsic> &Ints,
- raw_ostream &OS) {
- OS << "// Verifier::visitIntrinsicFunctionCall code.\n";
- OS << "#ifdef GET_INTRINSIC_VERIFIER\n";
- OS << " switch (ID) {\n";
- OS << " default: llvm_unreachable(\"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;
- std::vector<unsigned> OverloadedTypeIndices;
-
- 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 < OverloadedTypeIndices.size() &&
- "Invalid matching number!");
- Number = OverloadedTypeIndices[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 (EVT(VT).isOverloaded())
- OverloadedTypeIndices.push_back(j);
-
- 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 < OverloadedTypeIndices.size() &&
- "Invalid matching number!");
- Number = OverloadedTypeIndices[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 (EVT(VT).isOverloaded())
- OverloadedTypeIndices.push_back(j + RetTys.size());
-
- 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";
-}
-
// NOTE: This must be kept in synch with the copy in lib/VMCore/Function.cpp!
enum IIT_Info {
if (L->canThrow != R->canThrow)
return R->canThrow;
+ if (L->isNoReturn != R->isNoReturn)
+ return R->isNoReturn;
+
// Try to order by readonly/readnone attribute.
ModRefKind LK = getModRefKind(*L);
ModRefKind RK = getModRefKind(*R);
ModRefKind modRef = getModRefKind(intrinsic);
- if (!intrinsic.canThrow || modRef) {
+ if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn) {
OS << " AWI[" << numAttrs++ << "] = AttributeWithIndex::get(~0, ";
+ bool Emitted = false;
if (!intrinsic.canThrow) {
OS << "Attribute::NoUnwind";
- if (modRef) OS << '|';
+ Emitted = true;
+ }
+
+ if (intrinsic.isNoReturn) {
+ if (Emitted) OS << '|';
+ OS << "Attribute::NoReturn";
+ Emitted = true;
}
+
switch (modRef) {
case MRK_none: break;
- case MRK_readonly: OS << "Attribute::ReadOnly"; break;
- case MRK_readnone: OS << "Attribute::ReadNone"; break;
+ case MRK_readonly:
+ if (Emitted) OS << '|';
+ OS << "Attribute::ReadOnly";
+ break;
+ case MRK_readnone:
+ if (Emitted) OS << '|';
+ OS << "Attribute::ReadNone";
+ break;
}
OS << ");\n";
}