X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=utils%2FTableGen%2FIntrinsicEmitter.cpp;h=9ec39340e3f62cb4e007c43ba2b680ce2accffaa;hb=47f0e3f434e2e43f951c3a826c40906cb15b7285;hp=5dba9514283ddad13b94eb1a1c1ffcd297dd8165;hpb=10d664fee72917960c8bf38cc2ec8e3b84924044;p=oota-llvm.git diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp index 5dba9514283..9ec39340e3f 100644 --- a/utils/TableGen/IntrinsicEmitter.cpp +++ b/utils/TableGen/IntrinsicEmitter.cpp @@ -54,6 +54,8 @@ public: raw_ostream &OS); void EmitIntrinsicToGCCBuiltinMap(const std::vector &Ints, raw_ostream &OS); + void EmitIntrinsicToMSBuiltinMap(const std::vector &Ints, + raw_ostream &OS); void EmitSuffix(raw_ostream &OS); }; } // End anonymous namespace @@ -96,6 +98,9 @@ void IntrinsicEmitter::run(raw_ostream &OS) { // Emit code to translate GCC builtins into LLVM intrinsics. EmitIntrinsicToGCCBuiltinMap(Ints, OS); + // Emit code to translate MS builtins into LLVM intrinsics. + EmitIntrinsicToMSBuiltinMap(Ints, OS); + EmitSuffix(OS); } @@ -124,8 +129,9 @@ void IntrinsicEmitter::EmitEnumInfo(const std::vector &Ints, for (unsigned i = 0, e = Ints.size(); i != e; ++i) { OS << " " << Ints[i].EnumName; OS << ((i != e-1) ? ", " : " "); - OS << std::string(40-Ints[i].EnumName.size(), ' ') - << "// " << Ints[i].Name << "\n"; + if (Ints[i].EnumName.size() < 40) + OS << std::string(40-Ints[i].EnumName.size(), ' '); + OS << " // " << Ints[i].Name << "\n"; } OS << "#endif\n\n"; } @@ -238,19 +244,25 @@ enum IIT_Info { IIT_ARG = 15, // Values from 16+ are only encodable with the inefficient encoding. - IIT_MMX = 16, - IIT_METADATA = 17, - IIT_EMPTYSTRUCT = 18, - IIT_STRUCT2 = 19, - IIT_STRUCT3 = 20, - IIT_STRUCT4 = 21, - IIT_STRUCT5 = 22, - IIT_EXTEND_ARG = 23, - IIT_TRUNC_ARG = 24, - IIT_ANYPTR = 25, - IIT_V1 = 26, - IIT_VARARG = 27, - IIT_HALF_VEC_ARG = 28 + IIT_V64 = 16, + IIT_MMX = 17, + IIT_TOKEN = 18, + IIT_METADATA = 19, + IIT_EMPTYSTRUCT = 20, + IIT_STRUCT2 = 21, + IIT_STRUCT3 = 22, + IIT_STRUCT4 = 23, + IIT_STRUCT5 = 24, + IIT_EXTEND_ARG = 25, + IIT_TRUNC_ARG = 26, + IIT_ANYPTR = 27, + IIT_V1 = 28, + IIT_VARARG = 29, + IIT_HALF_VEC_ARG = 30, + IIT_SAME_VEC_WIDTH_ARG = 31, + IIT_PTR_TO_ARG = 32, + IIT_VEC_OF_PTRS_TO_ELT = 33, + IIT_I128 = 34 }; @@ -265,6 +277,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, case 16: return Sig.push_back(IIT_I16); case 32: return Sig.push_back(IIT_I32); case 64: return Sig.push_back(IIT_I64); + case 128: return Sig.push_back(IIT_I128); } } @@ -273,6 +286,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, case MVT::f16: return Sig.push_back(IIT_F16); case MVT::f32: return Sig.push_back(IIT_F32); case MVT::f64: return Sig.push_back(IIT_F64); + case MVT::token: return Sig.push_back(IIT_TOKEN); case MVT::Metadata: return Sig.push_back(IIT_METADATA); case MVT::x86mmx: return Sig.push_back(IIT_MMX); // MVT::OtherVT is used to mean the empty struct type here. @@ -282,7 +296,7 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT, } } -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) #pragma optimize("",off) // MSVC 2010 optimizer can't deal with this function. #endif @@ -298,9 +312,20 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, Sig.push_back(IIT_TRUNC_ARG); else if (R->isSubClassOf("LLVMHalfElementsVectorType")) Sig.push_back(IIT_HALF_VEC_ARG); + else if (R->isSubClassOf("LLVMVectorSameWidth")) { + Sig.push_back(IIT_SAME_VEC_WIDTH_ARG); + Sig.push_back((Number << 3) | ArgCodes[Number]); + MVT::SimpleValueType VT = getValueType(R->getValueAsDef("ElTy")); + EncodeFixedValueType(VT, Sig); + return; + } + else if (R->isSubClassOf("LLVMPointerTo")) + Sig.push_back(IIT_PTR_TO_ARG); + else if (R->isSubClassOf("LLVMVectorOfPointersToElt")) + Sig.push_back(IIT_VEC_OF_PTRS_TO_ELT); else Sig.push_back(IIT_ARG); - return Sig.push_back((Number << 2) | ArgCodes[Number]); + return Sig.push_back((Number << 3) | ArgCodes[Number]); } MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT")); @@ -311,7 +336,8 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, case MVT::iPTRAny: ++Tmp; // FALL THROUGH. case MVT::vAny: ++Tmp; // FALL THROUGH. case MVT::fAny: ++Tmp; // FALL THROUGH. - case MVT::iAny: { + case MVT::iAny: ++Tmp; // FALL THROUGH. + case MVT::Any: { // If this is an "any" valuetype, then the type is the type of the next // type in the list specified to getIntrinsic(). Sig.push_back(IIT_ARG); @@ -320,8 +346,8 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, unsigned ArgNo = ArgCodes.size(); ArgCodes.push_back(Tmp); - // Encode what sort of argument it must be in the low 2 bits of the ArgNo. - return Sig.push_back((ArgNo << 2) | Tmp); + // Encode what sort of argument it must be in the low 3 bits of the ArgNo. + return Sig.push_back((ArgNo << 3) | Tmp); } case MVT::iPTR: { @@ -350,6 +376,7 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, case 8: Sig.push_back(IIT_V8); break; case 16: Sig.push_back(IIT_V16); break; case 32: Sig.push_back(IIT_V32); break; + case 64: Sig.push_back(IIT_V64); break; } return EncodeFixedValueType(VVT.getVectorElementType().SimpleTy, Sig); @@ -358,7 +385,7 @@ static void EncodeFixedType(Record *R, std::vector &ArgCodes, EncodeFixedValueType(VT, Sig); } -#ifdef _MSC_VER +#if defined(_MSC_VER) && !defined(__clang__) #pragma optimize("",on) #endif @@ -477,28 +504,6 @@ void IntrinsicEmitter::EmitGenerator(const std::vector &Ints, OS << "#endif\n\n"; // End of GET_INTRINSIC_GENERATOR_GLOBAL } -namespace { -enum ModRefKind { - MRK_none, - MRK_readonly, - MRK_readnone -}; -} - -static ModRefKind getModRefKind(const CodeGenIntrinsic &intrinsic) { - switch (intrinsic.ModRef) { - case CodeGenIntrinsic::NoMem: - return MRK_readnone; - case CodeGenIntrinsic::ReadArgMem: - case CodeGenIntrinsic::ReadMem: - return MRK_readonly; - case CodeGenIntrinsic::ReadWriteArgMem: - case CodeGenIntrinsic::ReadWriteMem: - return MRK_none; - } - llvm_unreachable("bad mod-ref kind"); -} - namespace { struct AttributeComparator { bool operator()(const CodeGenIntrinsic *L, const CodeGenIntrinsic *R) const { @@ -512,9 +517,12 @@ struct AttributeComparator { if (L->isNoReturn != R->isNoReturn) return R->isNoReturn; + if (L->isConvergent != R->isConvergent) + return R->isConvergent; + // Try to order by readonly/readnone attribute. - ModRefKind LK = getModRefKind(*L); - ModRefKind RK = getModRefKind(*R); + CodeGenIntrinsic::ModRefKind LK = L->ModRef; + CodeGenIntrinsic::ModRefKind RK = R->ModRef; if (LK != RK) return (LK > RK); // Order by argument attributes. @@ -608,7 +616,7 @@ EmitAttributes(const std::vector &Ints, raw_ostream &OS) { case CodeGenIntrinsic::ReadNone: if (addComma) OS << ","; - OS << "Attributes::ReadNone"; + OS << "Attribute::ReadNone"; addComma = true; break; } @@ -621,10 +629,10 @@ EmitAttributes(const std::vector &Ints, raw_ostream &OS) { } } - ModRefKind modRef = getModRefKind(intrinsic); - - if (!intrinsic.canThrow || modRef || intrinsic.isNoReturn || - intrinsic.isNoDuplicate) { + if (!intrinsic.canThrow || + intrinsic.ModRef != CodeGenIntrinsic::ReadWriteMem || + intrinsic.isNoReturn || intrinsic.isNoDuplicate || + intrinsic.isConvergent) { OS << " const Attribute::AttrKind Atts[] = {"; bool addComma = false; if (!intrinsic.canThrow) { @@ -643,18 +651,36 @@ EmitAttributes(const std::vector &Ints, raw_ostream &OS) { OS << "Attribute::NoDuplicate"; addComma = true; } + if (intrinsic.isConvergent) { + if (addComma) + OS << ","; + OS << "Attribute::Convergent"; + addComma = true; + } - switch (modRef) { - case MRK_none: break; - case MRK_readonly: + switch (intrinsic.ModRef) { + case CodeGenIntrinsic::NoMem: + if (addComma) + OS << ","; + OS << "Attribute::ReadNone"; + break; + case CodeGenIntrinsic::ReadArgMem: + if (addComma) + OS << ","; + OS << "Attribute::ReadOnly,"; + OS << "Attribute::ArgMemOnly"; + break; + case CodeGenIntrinsic::ReadMem: if (addComma) OS << ","; OS << "Attribute::ReadOnly"; break; - case MRK_readnone: + case CodeGenIntrinsic::ReadWriteArgMem: if (addComma) OS << ","; - OS << "Attribute::ReadNone"; + OS << "Attribute::ArgMemOnly"; + break; + case CodeGenIntrinsic::ReadWriteMem: break; } OS << "};\n"; @@ -674,8 +700,7 @@ EmitAttributes(const std::vector &Ints, raw_ostream &OS) { OS << " }\n"; OS << " }\n"; - OS << " return AttributeSet::get(C, ArrayRef(AS, " - "NumAttrs));\n"; + OS << " return AttributeSet::get(C, makeArrayRef(AS, NumAttrs));\n"; OS << "}\n"; OS << "#endif // GET_INTRINSIC_ATTRIBUTES\n\n"; } @@ -689,29 +714,30 @@ EmitModRefBehavior(const std::vector &Ints, raw_ostream &OS){ << "\"Unknown intrinsic.\");\n\n"; OS << "static const uint8_t IntrinsicModRefBehavior[] = {\n" - << " /* invalid */ UnknownModRefBehavior,\n"; + << " /* invalid */ FMRB_UnknownModRefBehavior,\n"; for (unsigned i = 0, e = Ints.size(); i != e; ++i) { OS << " /* " << TargetPrefix << Ints[i].EnumName << " */ "; switch (Ints[i].ModRef) { case CodeGenIntrinsic::NoMem: - OS << "DoesNotAccessMemory,\n"; + OS << "FMRB_DoesNotAccessMemory,\n"; break; case CodeGenIntrinsic::ReadArgMem: - OS << "OnlyReadsArgumentPointees,\n"; + OS << "FMRB_OnlyReadsArgumentPointees,\n"; break; case CodeGenIntrinsic::ReadMem: - OS << "OnlyReadsMemory,\n"; + OS << "FMRB_OnlyReadsMemory,\n"; break; case CodeGenIntrinsic::ReadWriteArgMem: - OS << "OnlyAccessesArgumentPointees,\n"; + OS << "FMRB_OnlyAccessesArgumentPointees,\n"; break; case CodeGenIntrinsic::ReadWriteMem: - OS << "UnknownModRefBehavior,\n"; + OS << "FMRB_UnknownModRefBehavior,\n"; break; } } OS << "};\n\n" - << "return static_cast(IntrinsicModRefBehavior[iid]);\n" + << "return " + "static_cast(IntrinsicModRefBehavior[iid]);\n" << "#endif // GET_INTRINSIC_MODREF_BEHAVIOR\n\n"; } @@ -727,7 +753,7 @@ static void EmitTargetBuiltins(const std::map &BIM, E = BIM.end(); I != E; ++I) { std::string ResultCode = "return " + TargetPrefix + "Intrinsic::" + I->second + ";"; - Results.push_back(StringMatcher::StringPair(I->first, ResultCode)); + Results.emplace_back(I->first, ResultCode); } StringMatcher("BuiltinName", Results, OS).Emit(); @@ -790,6 +816,55 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector &Ints, OS << "#endif\n\n"; } +void IntrinsicEmitter:: +EmitIntrinsicToMSBuiltinMap(const std::vector &Ints, + raw_ostream &OS) { + std::map> TargetBuiltins; + + for (const auto &Intrinsic : Ints) { + if (Intrinsic.MSBuiltinName.empty()) + continue; + + auto &Builtins = TargetBuiltins[Intrinsic.TargetPrefix]; + if (!Builtins.insert(std::make_pair(Intrinsic.MSBuiltinName, + Intrinsic.EnumName)).second) + PrintFatalError("Intrinsic '" + Intrinsic.TheDef->getName() + "': " + "duplicate MS builtin name!"); + } + + OS << "// Get the LLVM intrinsic that corresponds to a MS builtin.\n" + "// This is used by the C front-end. The MS builtin name is passed\n" + "// in as a BuiltinName, and a target prefix (e.g. 'arm') is passed\n" + "// in as a TargetPrefix. The result is assigned to 'IntrinsicID'.\n" + "#ifdef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN\n"; + + OS << (TargetOnly ? "static " + TargetPrefix : "") << "Intrinsic::ID " + << (TargetOnly ? "" : "Intrinsic::") + << "getIntrinsicForMSBuiltin(const char *TP, const char *BN) {\n"; + OS << " StringRef BuiltinName(BN);\n" + " StringRef TargetPrefix(TP);\n" + "\n"; + + for (const auto &Builtins : TargetBuiltins) { + OS << " "; + if (Builtins.first.empty()) + OS << "/* Target Independent Builtins */ "; + else + OS << "if (TargetPrefix == \"" << Builtins.first << "\") "; + OS << "{\n"; + EmitTargetBuiltins(Builtins.second, TargetPrefix, OS); + OS << "}"; + } + + OS << " return "; + if (!TargetPrefix.empty()) + OS << "(" << TargetPrefix << "Intrinsic::ID)"; + OS << "Intrinsic::not_intrinsic;\n"; + OS << "}\n"; + + OS << "#endif\n\n"; +} + void llvm::EmitIntrinsics(RecordKeeper &RK, raw_ostream &OS, bool TargetOnly) { IntrinsicEmitter(RK, TargetOnly).run(OS); }