aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNate Begeman <natebegeman@mac.com>2009-02-04 19:47:21 +0000
committerNate Begeman <natebegeman@mac.com>2009-02-04 19:47:21 +0000
commitd24479730a8790d82c4859dc477bc2416d7a6bda (patch)
tree7e0310ae5edc0f659e09b9d67efe437da9d4e6f9
parente5ab34e05d701da042619bf540046efc3c7bc41f (diff)
downloadexternal_llvm-d24479730a8790d82c4859dc477bc2416d7a6bda.zip
external_llvm-d24479730a8790d82c4859dc477bc2416d7a6bda.tar.gz
external_llvm-d24479730a8790d82c4859dc477bc2416d7a6bda.tar.bz2
New feature: add support for target intrinsics being defined in the
target directories themselves. This also means that VMCore no longer needs to know about every target's list of intrinsics. Future work will include converting the PowerPC target to this interface as an example implementation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63765 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--Makefile.rules5
-rw-r--r--include/llvm/Function.h2
-rw-r--r--include/llvm/Intrinsics.h3
-rw-r--r--include/llvm/Intrinsics.td2
-rw-r--r--include/llvm/Module.h4
-rw-r--r--include/llvm/Target/TargetIntrinsicInfo.h48
-rw-r--r--include/llvm/Target/TargetMachine.h7
-rw-r--r--lib/AsmParser/LLParser.cpp9
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp9
-rw-r--r--lib/Target/TargetIntrinsicInfo.cpp22
-rw-r--r--lib/VMCore/AutoUpgrade.cpp2
-rw-r--r--lib/VMCore/Function.cpp12
-rw-r--r--lib/VMCore/Module.cpp19
-rw-r--r--lib/VMCore/Verifier.cpp3
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.cpp3
-rw-r--r--utils/TableGen/CodeGenDAGPatterns.h12
-rw-r--r--utils/TableGen/CodeGenIntrinsics.h3
-rw-r--r--utils/TableGen/CodeGenTarget.cpp10
-rw-r--r--utils/TableGen/IntrinsicEmitter.cpp64
-rw-r--r--utils/TableGen/IntrinsicEmitter.h5
-rw-r--r--utils/TableGen/TableGen.cpp6
21 files changed, 207 insertions, 43 deletions
diff --git a/Makefile.rules b/Makefile.rules
index 5bddff8..8122b8f 100644
--- a/Makefile.rules
+++ b/Makefile.rules
@@ -1346,6 +1346,11 @@ $(ObjDir)/%GenCallingConv.inc.tmp : %.td $(ObjDir)/.dir
$(Echo) "Building $(<F) calling convention information with tblgen"
$(Verb) $(TableGen) -gen-callingconv -o $(call SYSPATH, $@) $<
+$(TARGET:%=$(ObjDir)/%GenIntrinsics.inc.tmp): \
+$(ObjDir)/%GenIntrinsics.inc.tmp : Intrinsics%.td $(ObjDir)/.dir
+ $(Echo) "Building $(<F) calling convention information with tblgen"
+ $(Verb) $(TableGen) -gen-tgt-intrinsic -o $(call SYSPATH, $@) $<
+
clean-local::
-$(Verb) $(RM) -f $(INCFiles)
diff --git a/include/llvm/Function.h b/include/llvm/Function.h
index 689d0e6..942a5f0 100644
--- a/include/llvm/Function.h
+++ b/include/llvm/Function.h
@@ -129,7 +129,7 @@ public:
/// The particular intrinsic functions which correspond to this value are
/// defined in llvm/Intrinsics.h.
///
- unsigned getIntrinsicID(bool noAssert = false) const;
+ unsigned getIntrinsicID() const;
bool isIntrinsic() const { return getIntrinsicID() != 0; }
/// getCallingConv()/setCallingConv(uint) - These method get and set the
diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h
index b15b021..2433599 100644
--- a/include/llvm/Intrinsics.h
+++ b/include/llvm/Intrinsics.h
@@ -63,6 +63,9 @@ namespace Intrinsic {
/// intrinsic.
Function *getDeclaration(Module *M, ID id, const Type **Tys = 0,
unsigned numTys = 0);
+
+ /// Map a GCC builtin name to an intrinsic ID.
+ ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName);
} // End Intrinsic namespace
diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td
index 8145700..4ecc1a7 100644
--- a/include/llvm/Intrinsics.td
+++ b/include/llvm/Intrinsics.td
@@ -144,6 +144,8 @@ class Intrinsic<list<LLVMType> ret_types,
list<LLVMType> RetTypes = ret_types;
list<LLVMType> ParamTypes = param_types;
list<IntrinsicProperty> Properties = properties;
+
+ bit isTarget = 0;
}
/// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this
diff --git a/include/llvm/Module.h b/include/llvm/Module.h
index b0db50a..aa2c449 100644
--- a/include/llvm/Module.h
+++ b/include/llvm/Module.h
@@ -213,6 +213,10 @@ public:
Constant *getOrInsertFunction(const std::string &Name, const Type *RetTy, ...)
END_WITH_NULL;
+ Constant *getOrInsertTargetIntrinsic(const std::string &Name,
+ const FunctionType *Ty,
+ AttrListPtr AttributeList);
+
/// getFunction - Look up the specified function in the module symbol table.
/// If it does not exist, return null.
Function *getFunction(const std::string &Name) const;
diff --git a/include/llvm/Target/TargetIntrinsicInfo.h b/include/llvm/Target/TargetIntrinsicInfo.h
new file mode 100644
index 0000000..323e29a
--- /dev/null
+++ b/include/llvm/Target/TargetIntrinsicInfo.h
@@ -0,0 +1,48 @@
+//===-- llvm/Target/TargetIntrinsicInfo.h - Instruction Info ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the target intrinsic instructions to the code generator.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_TARGETINTRINSICINFO_H
+#define LLVM_TARGET_TARGETINTRINSICINFO_H
+
+namespace llvm {
+
+class Function;
+class Module;
+
+//---------------------------------------------------------------------------
+///
+/// TargetIntrinsicInfo - Interface to description of machine instruction set
+///
+class TargetIntrinsicInfo {
+
+ const char **Intrinsics; // Raw array to allow static init'n
+ unsigned NumIntrinsics; // Number of entries in the desc array
+
+ TargetIntrinsicInfo(const TargetIntrinsicInfo &); // DO NOT IMPLEMENT
+ void operator=(const TargetIntrinsicInfo &); // DO NOT IMPLEMENT
+public:
+ TargetIntrinsicInfo(const char **desc, unsigned num);
+ virtual ~TargetIntrinsicInfo();
+
+ unsigned getNumIntrinsics() const { return NumIntrinsics; }
+
+ virtual Function *getDeclaration(Module *M, const char *BuiltinName) const {
+ return 0;
+ }
+
+ virtual unsigned getIntrinsicID(Function *F) const { return 0; }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h
index b8bfc83..0be3286 100644
--- a/include/llvm/Target/TargetMachine.h
+++ b/include/llvm/Target/TargetMachine.h
@@ -23,6 +23,7 @@ class TargetAsmInfo;
class TargetData;
class TargetSubtarget;
class TargetInstrInfo;
+class TargetIntrinsicInfo;
class TargetJITInfo;
class TargetLowering;
class TargetFrameInfo;
@@ -118,7 +119,6 @@ public:
virtual TargetLowering *getTargetLowering() const { return 0; }
virtual const TargetData *getTargetData() const { return 0; }
-
/// getTargetAsmInfo - Return target specific asm information.
///
const TargetAsmInfo *getTargetAsmInfo() const {
@@ -141,6 +141,11 @@ public:
/// details of graph coloring register allocation removed from it.
///
virtual const TargetRegisterInfo *getRegisterInfo() const { return 0; }
+
+ /// getIntrinsicInfo - If intrinsic information is available, return it. If
+ /// not, return null.
+ ///
+ virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return 0; }
/// getJITInfo - If this target supports a JIT, return information for it,
/// otherwise return null.
diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp
index 943f1d0..60e863c 100644
--- a/lib/AsmParser/LLParser.cpp
+++ b/lib/AsmParser/LLParser.cpp
@@ -2949,15 +2949,6 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
Value *Callee;
if (ConvertValIDToValue(PFTy, CalleeID, Callee, PFS)) return true;
- // Check for call to invalid intrinsic to avoid crashing later.
- if (Function *F = dyn_cast<Function>(Callee)) {
- if (F->hasName() && F->getNameLen() >= 5 &&
- !strncmp(F->getValueName()->getKeyData(), "llvm.", 5) &&
- !F->getIntrinsicID(true))
- return Error(CallLoc, "Call to invalid LLVM intrinsic function '" +
- F->getNameStr() + "'");
- }
-
// FIXME: In LLVM 3.0, stop accepting zext, sext and inreg as optional
// function attributes.
unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg;
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
index c3cff20..1b1d70b 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
@@ -43,6 +43,7 @@
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetIntrinsicInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
@@ -4426,6 +4427,14 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
const char *RenameFn = 0;
if (Function *F = I.getCalledFunction()) {
if (F->isDeclaration()) {
+ const TargetIntrinsicInfo *II = TLI.getTargetMachine().getIntrinsicInfo();
+ if (II) {
+ if (unsigned IID = II->getIntrinsicID(F)) {
+ RenameFn = visitIntrinsicCall(I, IID);
+ if (!RenameFn)
+ return;
+ }
+ }
if (unsigned IID = F->getIntrinsicID()) {
RenameFn = visitIntrinsicCall(I, IID);
if (!RenameFn)
diff --git a/lib/Target/TargetIntrinsicInfo.cpp b/lib/Target/TargetIntrinsicInfo.cpp
new file mode 100644
index 0000000..d8da08e
--- /dev/null
+++ b/lib/Target/TargetIntrinsicInfo.cpp
@@ -0,0 +1,22 @@
+//===-- TargetIntrinsicInfo.cpp - Target Instruction Information ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the TargetIntrinsicInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Target/TargetIntrinsicInfo.h"
+using namespace llvm;
+
+TargetIntrinsicInfo::TargetIntrinsicInfo(const char **desc, unsigned count)
+ : Intrinsics(desc), NumIntrinsics(count) {
+}
+
+TargetIntrinsicInfo::~TargetIntrinsicInfo() {
+}
diff --git a/lib/VMCore/AutoUpgrade.cpp b/lib/VMCore/AutoUpgrade.cpp
index abad7af..dd36607 100644
--- a/lib/VMCore/AutoUpgrade.cpp
+++ b/lib/VMCore/AutoUpgrade.cpp
@@ -217,7 +217,7 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
// Upgrade intrinsic attributes. This does not change the function.
if (NewFn)
F = NewFn;
- if (unsigned id = F->getIntrinsicID(true))
+ if (unsigned id = F->getIntrinsicID())
F->setAttributes(Intrinsic::getAttributes((Intrinsic::ID)id));
return Upgraded;
}
diff --git a/lib/VMCore/Function.cpp b/lib/VMCore/Function.cpp
index bda2eff..bc3b611 100644
--- a/lib/VMCore/Function.cpp
+++ b/lib/VMCore/Function.cpp
@@ -175,7 +175,7 @@ Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
ParentModule->getFunctionList().push_back(this);
// Ensure intrinsics have the right parameter attributes.
- if (unsigned IID = getIntrinsicID(true))
+ if (unsigned IID = getIntrinsicID())
setAttributes(Intrinsic::getAttributes(Intrinsic::ID(IID)));
}
@@ -304,7 +304,7 @@ void Function::copyAttributesFrom(const GlobalValue *Src) {
/// particular intrinsic functions which correspond to this value are defined in
/// llvm/Intrinsics.h.
///
-unsigned Function::getIntrinsicID(bool noAssert) const {
+unsigned Function::getIntrinsicID() const {
const ValueName *ValName = this->getValueName();
if (!ValName)
return 0;
@@ -315,12 +315,9 @@ unsigned Function::getIntrinsicID(bool noAssert) const {
|| Name[2] != 'v' || Name[3] != 'm')
return 0; // All intrinsics start with 'llvm.'
- assert((Len != 5 || noAssert) && "'llvm.' is an invalid intrinsic name!");
-
#define GET_FUNCTION_RECOGNIZER
#include "llvm/Intrinsics.gen"
#undef GET_FUNCTION_RECOGNIZER
- assert(noAssert && "Invalid LLVM intrinsic name");
return 0;
}
@@ -373,4 +370,9 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys,
getType(id, Tys, numTys)));
}
+// This defines the "Intrinsic::getIntrinsicForGCCBuiltin()" method.
+#define GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
+#include "llvm/Intrinsics.gen"
+#undef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN
+
// vim: sw=2 ai
diff --git a/lib/VMCore/Module.cpp b/lib/VMCore/Module.cpp
index ef94796..896245d 100644
--- a/lib/VMCore/Module.cpp
+++ b/lib/VMCore/Module.cpp
@@ -171,6 +171,25 @@ Constant *Module::getOrInsertFunction(const std::string &Name,
return F;
}
+Constant *Module::getOrInsertTargetIntrinsic(const std::string &Name,
+ const FunctionType *Ty,
+ AttrListPtr AttributeList) {
+ ValueSymbolTable &SymTab = getValueSymbolTable();
+
+ // See if we have a definition for the specified function already.
+ GlobalValue *F = dyn_cast_or_null<GlobalValue>(SymTab.lookup(Name));
+ if (F == 0) {
+ // Nope, add it
+ Function *New = Function::Create(Ty, GlobalVariable::ExternalLinkage, Name);
+ New->setAttributes(AttributeList);
+ FunctionList.push_back(New);
+ return New; // Return the new prototype.
+ }
+
+ // Otherwise, we just found the existing function or a prototype.
+ return F;
+}
+
Constant *Module::getOrInsertFunction(const std::string &Name,
const FunctionType *Ty) {
AttrListPtr AttributeList = AttrListPtr::get((AttributeWithIndex *)0, 0);
diff --git a/lib/VMCore/Verifier.cpp b/lib/VMCore/Verifier.cpp
index 62d2930..99a5b92 100644
--- a/lib/VMCore/Verifier.cpp
+++ b/lib/VMCore/Verifier.cpp
@@ -1004,10 +1004,9 @@ void Verifier::VerifyCallSite(CallSite CS) {
void Verifier::visitCallInst(CallInst &CI) {
VerifyCallSite(&CI);
- if (Function *F = CI.getCalledFunction()) {
+ if (Function *F = CI.getCalledFunction())
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
visitIntrinsicFunctionCall(ID, CI);
- }
}
void Verifier::visitInvokeInst(InvokeInst &II) {
diff --git a/utils/TableGen/CodeGenDAGPatterns.cpp b/utils/TableGen/CodeGenDAGPatterns.cpp
index f3bdb4f..6e7dd1e 100644
--- a/utils/TableGen/CodeGenDAGPatterns.cpp
+++ b/utils/TableGen/CodeGenDAGPatterns.cpp
@@ -1303,7 +1303,8 @@ void TreePattern::dump() const { print(*cerr.stream()); }
// FIXME: REMOVE OSTREAM ARGUMENT
CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) {
- Intrinsics = LoadIntrinsics(Records);
+ Intrinsics = LoadIntrinsics(Records, false);
+ TgtIntrinsics = LoadIntrinsics(Records, true);
ParseNodeInfo();
ParseNodeTransforms();
ParseComplexPatterns();
diff --git a/utils/TableGen/CodeGenDAGPatterns.h b/utils/TableGen/CodeGenDAGPatterns.h
index d44bfc9..0bd3165 100644
--- a/utils/TableGen/CodeGenDAGPatterns.h
+++ b/utils/TableGen/CodeGenDAGPatterns.h
@@ -465,6 +465,7 @@ class CodeGenDAGPatterns {
RecordKeeper &Records;
CodeGenTarget Target;
std::vector<CodeGenIntrinsic> Intrinsics;
+ std::vector<CodeGenIntrinsic> TgtIntrinsics;
std::map<Record*, SDNodeInfo> SDNodes;
std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms;
@@ -515,18 +516,25 @@ public:
const CodeGenIntrinsic &getIntrinsic(Record *R) const {
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
if (Intrinsics[i].TheDef == R) return Intrinsics[i];
+ for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i)
+ if (TgtIntrinsics[i].TheDef == R) return TgtIntrinsics[i];
assert(0 && "Unknown intrinsic!");
abort();
}
const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
- assert(IID-1 < Intrinsics.size() && "Bad intrinsic ID!");
- return Intrinsics[IID-1];
+ if (IID-1 < Intrinsics.size())
+ return Intrinsics[IID-1];
+ if (IID-Intrinsics.size()-1 < TgtIntrinsics.size())
+ return TgtIntrinsics[IID-Intrinsics.size()-1];
+ assert(0 && "Bad intrinsic ID!");
}
unsigned getIntrinsicID(Record *R) const {
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
if (Intrinsics[i].TheDef == R) return i;
+ for (unsigned i = 0, e = TgtIntrinsics.size(); i != e; ++i)
+ if (TgtIntrinsics[i].TheDef == R) return i + Intrinsics.size();
assert(0 && "Unknown intrinsic!");
abort();
}
diff --git a/utils/TableGen/CodeGenIntrinsics.h b/utils/TableGen/CodeGenIntrinsics.h
index dd99e31..fea868b 100644
--- a/utils/TableGen/CodeGenIntrinsics.h
+++ b/utils/TableGen/CodeGenIntrinsics.h
@@ -80,7 +80,8 @@ namespace llvm {
/// LoadIntrinsics - Read all of the intrinsics defined in the specified
/// .td file.
- std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC);
+ std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC,
+ bool TargetOnly);
}
#endif
diff --git a/utils/TableGen/CodeGenTarget.cpp b/utils/TableGen/CodeGenTarget.cpp
index 274cc78..9ef64d6 100644
--- a/utils/TableGen/CodeGenTarget.cpp
+++ b/utils/TableGen/CodeGenTarget.cpp
@@ -426,13 +426,17 @@ ComplexPattern::ComplexPattern(Record *R) {
// CodeGenIntrinsic Implementation
//===----------------------------------------------------------------------===//
-std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC) {
+std::vector<CodeGenIntrinsic> llvm::LoadIntrinsics(const RecordKeeper &RC,
+ bool TargetOnly) {
std::vector<Record*> I = RC.getAllDerivedDefinitions("Intrinsic");
std::vector<CodeGenIntrinsic> Result;
- for (unsigned i = 0, e = I.size(); i != e; ++i)
- Result.push_back(CodeGenIntrinsic(I[i]));
+ for (unsigned i = 0, e = I.size(); i != e; ++i) {
+ bool isTarget = I[i]->getValueAsBit("isTarget");
+ if (isTarget == TargetOnly)
+ Result.push_back(CodeGenIntrinsic(I[i]));
+ }
return Result;
}
diff --git a/utils/TableGen/IntrinsicEmitter.cpp b/utils/TableGen/IntrinsicEmitter.cpp
index eda55e1..53081ff 100644
--- a/utils/TableGen/IntrinsicEmitter.cpp
+++ b/utils/TableGen/IntrinsicEmitter.cpp
@@ -25,7 +25,10 @@ using namespace llvm;
void IntrinsicEmitter::run(std::ostream &OS) {
EmitSourceFileHeader("Intrinsic Function Source Fragment", OS);
- std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records);
+ std::vector<CodeGenIntrinsic> Ints = LoadIntrinsics(Records, TargetOnly);
+
+ if (TargetOnly && !Ints.empty())
+ TargetPrefix = Ints[0].TargetPrefix;
// Emit the enum information.
EmitEnumInfo(Ints, OS);
@@ -91,12 +94,12 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
if (Ints[I->second].isOverloaded)
OS << " if (Len > " << I->first.size()
<< " && !memcmp(Name, \"" << I->first << ".\", "
- << (I->first.size() + 1) << ")) return Intrinsic::"
+ << (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::"
<< Ints[I->second].EnumName << ";\n";
else
OS << " if (Len == " << I->first.size()
<< " && !memcmp(Name, \"" << I->first << "\", "
- << I->first.size() << ")) return Intrinsic::"
+ << I->first.size() << ")) return " << TargetPrefix << "Intrinsic::"
<< Ints[I->second].EnumName << ";\n";
}
OS << " }\n";
@@ -351,11 +354,13 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
Ints[i].IS.ParamTypeDefs)].push_back(i);
// Loop through the array, emitting one generator for each batch.
+ std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
+
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";
+ OS << " case " << IntrinsicStr << 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;
@@ -392,7 +397,11 @@ void IntrinsicEmitter::
EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
OS << "// Add parameter attributes that are not common to all intrinsics.\n";
OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\n";
- OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
+ if (TargetOnly)
+ OS << "static AttrListPtr getAttributes(" << TargetPrefix
+ << "Intrinsic::ID id) {";
+ else
+ OS << "AttrListPtr Intrinsic::getAttributes(ID id) {";
OS << " // No intrinsic can throw exceptions.\n";
OS << " Attributes Attr = Attribute::NoUnwind;\n";
OS << " switch (id) {\n";
@@ -404,7 +413,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
switch (Ints[i].ModRef) {
default: break;
case CodeGenIntrinsic::NoMem:
- OS << " case Intrinsic::" << Ints[i].EnumName << ":\n";
+ OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
+ << ":\n";
break;
}
}
@@ -415,7 +425,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
default: break;
case CodeGenIntrinsic::ReadArgMem:
case CodeGenIntrinsic::ReadMem:
- OS << " case Intrinsic::" << Ints[i].EnumName << ":\n";
+ OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
+ << ":\n";
break;
}
}
@@ -431,7 +442,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
if (Ints[i].ArgumentAttributes.empty()) continue;
- OS << " case Intrinsic::" << Ints[i].EnumName << ":\n";
+ OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
+ << ":\n";
std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
Ints[i].ArgumentAttributes;
@@ -495,7 +507,7 @@ EmitGCCBuiltinList(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS){
typedef std::map<std::string, std::string>::const_iterator StrMapIterator;
static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
unsigned CharStart, unsigned Indent,
- std::ostream &OS) {
+ std::string TargetPrefix, std::ostream &OS) {
if (Start == End) return; // empty range.
// Determine what, if anything, is the same about all these strings.
@@ -522,7 +534,8 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
OS << CommonString.size() - CharStart << "))\n";
++Indent;
}
- OS << std::string(Indent*2, ' ') << "IntrinsicID = Intrinsic::";
+ OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix
+ << "Intrinsic::";
OS << Start->second << ";\n";
return;
}
@@ -535,7 +548,8 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
OS << CommonString.size()-CharStart << ")) {\n";
- EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1, OS);
+ EmitBuiltinComparisons(Start, End, CommonString.size(), Indent+1,
+ TargetPrefix, OS);
OS << std::string(Indent*2, ' ') << "}\n";
return;
}
@@ -556,7 +570,7 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar;
++NextChar)
/*empty*/;
- EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, OS);
+ EmitBuiltinComparisons(I, NextChar, CharStart+1, Indent+1, TargetPrefix,OS);
OS << std::string(Indent*2, ' ') << " break;\n";
I = NextChar;
}
@@ -566,6 +580,7 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
/// EmitTargetBuiltins - All of the builtins in the specified map are for the
/// same target, and we already checked it.
static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
+ const std::string &TargetPrefix,
std::ostream &OS) {
// Rearrange the builtins by length.
std::vector<std::map<std::string, std::string> > BuiltinsByLen;
@@ -584,7 +599,7 @@ static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
if (BuiltinsByLen[i].empty()) continue;
OS << " case " << i << ":\n";
EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(),
- 0, 3, OS);
+ 0, 3, TargetPrefix, OS);
OS << " break;\n";
}
OS << " }\n";
@@ -613,7 +628,22 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
OS << "// in as BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\n";
- OS << " IntrinsicID = Intrinsic::not_intrinsic;\n";
+
+ if (TargetOnly) {
+ OS << "static " << TargetPrefix << "Intrinsic::ID "
+ << "getIntrinsicForGCCBuiltin(const char "
+ << "*TargetPrefix, const char *BuiltinName) {\n";
+ OS << " " << TargetPrefix << "Intrinsic::ID IntrinsicID = ";
+ } else {
+ OS << "Intrinsic::ID Intrinsic::getIntrinsicForGCCBuiltin(const char "
+ << "*TargetPrefix, const char *BuiltinName) {\n";
+ OS << " Intrinsic::ID IntrinsicID = ";
+ }
+
+ if (TargetOnly)
+ OS << "(" << TargetPrefix<< "Intrinsic::ID)";
+
+ OS << "Intrinsic::not_intrinsic;\n";
// Note: this could emit significantly better code if we cared.
for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
@@ -625,8 +655,10 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
OS << "{\n";
// Emit the comparisons for this target prefix.
- EmitTargetBuiltins(I->second, OS);
+ EmitTargetBuiltins(I->second, TargetPrefix, OS);
OS << " }\n";
}
+ OS << " return IntrinsicID;\n";
+ OS << "}\n";
OS << "#endif\n\n";
}
diff --git a/utils/TableGen/IntrinsicEmitter.h b/utils/TableGen/IntrinsicEmitter.h
index 3573692..0f3f0e7 100644
--- a/utils/TableGen/IntrinsicEmitter.h
+++ b/utils/TableGen/IntrinsicEmitter.h
@@ -20,9 +20,12 @@
namespace llvm {
class IntrinsicEmitter : public TableGenBackend {
RecordKeeper &Records;
+ bool TargetOnly;
+ std::string TargetPrefix;
public:
- IntrinsicEmitter(RecordKeeper &R) : Records(R) {}
+ IntrinsicEmitter(RecordKeeper &R, bool T = false)
+ : Records(R), TargetOnly(T) {}
void run(std::ostream &OS);
diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp
index c6692f8..98a188e 100644
--- a/utils/TableGen/TableGen.cpp
+++ b/utils/TableGen/TableGen.cpp
@@ -49,6 +49,7 @@ enum ActionType {
GenFastISel,
GenSubtarget,
GenIntrinsic,
+ GenTgtIntrinsic,
GenLLVMCConf,
PrintEnums
};
@@ -82,6 +83,8 @@ namespace {
"Generate subtarget enumerations"),
clEnumValN(GenIntrinsic, "gen-intrinsic",
"Generate intrinsic information"),
+ clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
+ "Generate target intrinsic information"),
clEnumValN(GenLLVMCConf, "gen-llvmc",
"Generate LLVMC configuration library"),
clEnumValN(PrintEnums, "print-enums",
@@ -190,6 +193,9 @@ int main(int argc, char **argv) {
case GenIntrinsic:
IntrinsicEmitter(Records).run(*Out);
break;
+ case GenTgtIntrinsic:
+ IntrinsicEmitter(Records, true).run(*Out);
+ break;
case GenLLVMCConf:
LLVMCConfigurationEmitter(Records).run(*Out);
break;