diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/IR/Intrinsics.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/IR/Intrinsics.td | 4 | ||||
-rw-r--r-- | llvm/lib/IR/Function.cpp | 5 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeGenIntrinsics.h | 1 | ||||
-rw-r--r-- | llvm/utils/TableGen/CodeGenTarget.cpp | 2 | ||||
-rw-r--r-- | llvm/utils/TableGen/IntrinsicEmitter.cpp | 54 |
6 files changed, 69 insertions, 0 deletions
diff --git a/llvm/include/llvm/IR/Intrinsics.h b/llvm/include/llvm/IR/Intrinsics.h index 839bbbd8b47..b0d746bd412 100644 --- a/llvm/include/llvm/IR/Intrinsics.h +++ b/llvm/include/llvm/IR/Intrinsics.h @@ -71,6 +71,9 @@ namespace Intrinsic { /// Map a GCC builtin name to an intrinsic ID. ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName); + + /// Map a MS builtin name to an intrinsic ID. + ID getIntrinsicForMSBuiltin(const char *Prefix, const char *BuiltinName); /// IITDescriptor - This is a type descriptor which explains the type /// requirements of an intrinsic. This is returned by diff --git a/llvm/include/llvm/IR/Intrinsics.td b/llvm/include/llvm/IR/Intrinsics.td index edd1621ef25..ae2a90c6295 100644 --- a/llvm/include/llvm/IR/Intrinsics.td +++ b/llvm/include/llvm/IR/Intrinsics.td @@ -226,6 +226,10 @@ class GCCBuiltin<string name> { string GCCBuiltinName = name; } +class MSBuiltin<string name> { + string MSBuiltinName = name; +} + //===--------------- Variable Argument Handling Intrinsics ----------------===// // diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index fe32c4613e7..14435711bb6 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -735,6 +735,11 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) { #include "llvm/IR/Intrinsics.gen" #undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN +// This defines the "Intrinsic::getIntrinsicForMSBuiltin()" method. +#define GET_LLVM_INTRINSIC_FOR_MS_BUILTIN +#include "llvm/IR/Intrinsics.gen" +#undef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN + /// hasAddressTaken - returns true if there are any uses of this function /// other than direct calls or invokes to it. bool Function::hasAddressTaken(const User* *PutOffender) const { diff --git a/llvm/utils/TableGen/CodeGenIntrinsics.h b/llvm/utils/TableGen/CodeGenIntrinsics.h index 06daa97b66e..a9ece01c904 100644 --- a/llvm/utils/TableGen/CodeGenIntrinsics.h +++ b/llvm/utils/TableGen/CodeGenIntrinsics.h @@ -28,6 +28,7 @@ namespace llvm { std::string Name; // The name of the LLVM function "llvm.bswap.i32" std::string EnumName; // The name of the enum "bswap_i32" std::string GCCBuiltinName;// Name of the corresponding GCC builtin, or "". + std::string MSBuiltinName; // Name of the corresponding MS builtin, or "". std::string TargetPrefix; // Target prefix, e.g. "ppc" for t-s intrinsics. /// IntrinsicSignature - This structure holds the return values and diff --git a/llvm/utils/TableGen/CodeGenTarget.cpp b/llvm/utils/TableGen/CodeGenTarget.cpp index de00dc6407e..d1b57118e0e 100644 --- a/llvm/utils/TableGen/CodeGenTarget.cpp +++ b/llvm/utils/TableGen/CodeGenTarget.cpp @@ -459,6 +459,8 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) { if (R->getValue("GCCBuiltinName")) // Ignore a missing GCCBuiltinName field. GCCBuiltinName = R->getValueAsString("GCCBuiltinName"); + if (R->getValue("MSBuiltinName")) // Ignore a missing MSBuiltinName field. + MSBuiltinName = R->getValueAsString("MSBuiltinName"); TargetPrefix = R->getValueAsString("TargetPrefix"); Name = R->getValueAsString("LLVMName"); diff --git a/llvm/utils/TableGen/IntrinsicEmitter.cpp b/llvm/utils/TableGen/IntrinsicEmitter.cpp index 5dba9514283..430ef32896d 100644 --- a/llvm/utils/TableGen/IntrinsicEmitter.cpp +++ b/llvm/utils/TableGen/IntrinsicEmitter.cpp @@ -54,6 +54,8 @@ public: raw_ostream &OS); void EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, raw_ostream &OS); + void EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &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); } @@ -790,6 +795,55 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, OS << "#endif\n\n"; } +void IntrinsicEmitter:: +EmitIntrinsicToMSBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints, + raw_ostream &OS) { + std::map<std::string, std::map<std::string, std::string>> 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); } |