+ const CodeGenIntrinsic &intrinsic = Ints[i];
+ maxArgAttrs =
+ std::max(maxArgAttrs, unsigned(intrinsic.ArgumentAttributes.size()));
+ unsigned &N = UniqAttributes[&intrinsic];
+ if (N) continue;
+ assert(AttrNum < 256 && "Too many unique attributes for table!");
+ N = ++AttrNum;
+ }
+
+ // Emit an array of AttributeSet. Most intrinsics will have at least one
+ // entry, for the function itself (index ~1), which is usually nounwind.
+ OS << " static const uint8_t IntrinsicsToAttributesMap[] = {\n";
+
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ const CodeGenIntrinsic &intrinsic = Ints[i];
+
+ OS << " " << UniqAttributes[&intrinsic] << ", // "
+ << intrinsic.Name << "\n";
+ }
+ OS << " };\n\n";
+
+ OS << " AttributeSet AS[" << maxArgAttrs+1 << "];\n";
+ OS << " unsigned NumAttrs = 0;\n";
+ OS << " if (id != 0) {\n";
+ OS << " SmallVector<Attribute::AttrKind, 8> AttrVec;\n";
+ OS << " switch(IntrinsicsToAttributesMap[id - ";
+ if (TargetOnly)
+ OS << "Intrinsic::num_intrinsics";
+ else
+ OS << "1";
+ OS << "]) {\n";
+ OS << " default: llvm_unreachable(\"Invalid attribute number\");\n";
+ for (UniqAttrMapTy::const_iterator I = UniqAttributes.begin(),
+ E = UniqAttributes.end(); I != E; ++I) {
+ OS << " case " << I->second << ":\n";
+
+ const CodeGenIntrinsic &intrinsic = *(I->first);
+
+ // Keep track of the number of attributes we're writing out.
+ unsigned numAttrs = 0;
+
+ // The argument attributes are alreadys sorted by argument index.
+ unsigned ai = 0, ae = intrinsic.ArgumentAttributes.size();
+ if (ae) {
+ while (ai != ae) {
+ unsigned argNo = intrinsic.ArgumentAttributes[ai].first;
+
+ OS << " AttrVec.clear();\n";
+
+ do {
+ switch (intrinsic.ArgumentAttributes[ai].second) {
+ case CodeGenIntrinsic::NoCapture:
+ OS << " AttrVec.push_back(Attribute::NoCapture);\n";
+ break;
+ case CodeGenIntrinsic::ReadOnly:
+ OS << " AttrVec.push_back(Attribute::ReadOnly);\n";
+ break;
+ case CodeGenIntrinsic::ReadNone:
+ OS << " AttrVec.push_back(Attribute::ReadNone);\n";
+ break;
+ }
+
+ ++ai;
+ } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
+
+ OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, "
+ << argNo+1 << ", AttrVec);\n";
+ }
+ }
+
+ ModRefKind modRef = getModRefKind(intrinsic);
+
+ if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn) {
+ OS << " AttrVec.clear();\n";
+
+ if (!intrinsic.canThrow)
+ OS << " AttrVec.push_back(Attribute::NoUnwind);\n";
+ if (intrinsic.isNoReturn)
+ OS << " AttrVec.push_back(Attribute::NoReturn);\n";
+
+ switch (modRef) {
+ case MRK_none: break;
+ case MRK_readonly:
+ OS << " AttrVec.push_back(Attribute::ReadOnly);\n";
+ break;
+ case MRK_readnone:
+ OS << " AttrVec.push_back(Attribute::ReadNone);\n";
+ break;
+ }
+ OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, "
+ << "AttributeSet::FunctionIndex, AttrVec);\n";
+ }
+
+ if (numAttrs) {
+ OS << " NumAttrs = " << numAttrs << ";\n";
+ OS << " break;\n";
+ } else {
+ OS << " return AttributeSet();\n";