-void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
- std::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<std::vector<Record*>, std::vector<unsigned>,
- RecordListComparator> MapTy;
- MapTy UniqueArgInfos;
-
- // Compute the unique argument type info.
- for (unsigned i = 0, e = Ints.size(); i != e; ++i)
- UniqueArgInfos[Ints[i].ArgTypeDefs].push_back(i);
-
- // Loop through the array, emitting one generator 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";
+namespace {
+struct AttributeComparator {
+ bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const {
+ // Sort throwing intrinsics after non-throwing intrinsics.
+ if (L->canThrow != R->canThrow)
+ return R->canThrow;
+
+ if (L->isNoDuplicate != R->isNoDuplicate)
+ return R->isNoDuplicate;
+
+ if (L->isNoReturn != R->isNoReturn)
+ return R->isNoReturn;
+
+ if (L->isConvergent != R->isConvergent)
+ return R->isConvergent;
+
+ // Try to order by readonly/readnone attribute.
+ CodeGenIntrinsic::ModRefKind LK = L->ModRef;
+ CodeGenIntrinsic::ModRefKind RK = R->ModRef;
+ if (LK != RK) return (LK > RK);
+
+ // Order by argument attributes.
+ // This is reliable because each side is already sorted internally.
+ return (L->ArgumentAttributes < R->ArgumentAttributes);
+ }
+};
+} // End anonymous namespace
+
+/// EmitAttributes - This emits the Intrinsic::getAttributes method.
+void IntrinsicEmitter::
+EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS) {
+ OS << "// Add parameter attributes that are not common to all intrinsics.\n";
+ OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
+ if (TargetOnly)
+ OS << "static AttributeSet getAttributes(LLVMContext &C, " << TargetPrefix
+ << "Intrinsic::ID id) {\n";
+ else
+ OS << "AttributeSet Intrinsic::getAttributes(LLVMContext &C, ID id) {\n";
+
+ // Compute the maximum number of attribute arguments and the map
+ typedef std::map<const CodeGenIntrinsic*, unsigned,
+ AttributeComparator> UniqAttrMapTy;
+ UniqAttrMapTy UniqAttributes;
+ unsigned maxArgAttrs = 0;
+ unsigned AttrNum = 0;
+ for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
+ 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 << " 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 << " const Attribute::AttrKind AttrParam" << argNo + 1 <<"[]= {";
+ bool addComma = false;
+
+ do {
+ switch (intrinsic.ArgumentAttributes[ai].second) {
+ case CodeGenIntrinsic::NoCapture:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::NoCapture";
+ addComma = true;
+ break;
+ case CodeGenIntrinsic::ReadOnly:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadOnly";
+ addComma = true;
+ break;
+ case CodeGenIntrinsic::ReadNone:
+ if (addComma)
+ OS << ",";
+ OS << "Attribute::ReadNone";
+ addComma = true;
+ break;
+ }
+
+ ++ai;
+ } while (ai != ae && intrinsic.ArgumentAttributes[ai].first == argNo);
+ OS << "};\n";
+ OS << " AS[" << numAttrs++ << "] = AttributeSet::get(C, "
+ << argNo+1 << ", AttrParam" << argNo +1 << ");\n";
+ }