mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-23 17:29:19 +00:00
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
This commit is contained in:
parent
e5ab34e05d
commit
d24479730a
@ -1346,6 +1346,11 @@ $(ObjDir)/%GenCallingConv.inc.tmp : %.td $(ObjDir)/.dir
|
|||||||
$(Echo) "Building $(<F) calling convention information with tblgen"
|
$(Echo) "Building $(<F) calling convention information with tblgen"
|
||||||
$(Verb) $(TableGen) -gen-callingconv -o $(call SYSPATH, $@) $<
|
$(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::
|
clean-local::
|
||||||
-$(Verb) $(RM) -f $(INCFiles)
|
-$(Verb) $(RM) -f $(INCFiles)
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ public:
|
|||||||
/// The particular intrinsic functions which correspond to this value are
|
/// The particular intrinsic functions which correspond to this value are
|
||||||
/// defined in llvm/Intrinsics.h.
|
/// defined in llvm/Intrinsics.h.
|
||||||
///
|
///
|
||||||
unsigned getIntrinsicID(bool noAssert = false) const;
|
unsigned getIntrinsicID() const;
|
||||||
bool isIntrinsic() const { return getIntrinsicID() != 0; }
|
bool isIntrinsic() const { return getIntrinsicID() != 0; }
|
||||||
|
|
||||||
/// getCallingConv()/setCallingConv(uint) - These method get and set the
|
/// getCallingConv()/setCallingConv(uint) - These method get and set the
|
||||||
|
@ -64,6 +64,9 @@ namespace Intrinsic {
|
|||||||
Function *getDeclaration(Module *M, ID id, const Type **Tys = 0,
|
Function *getDeclaration(Module *M, ID id, const Type **Tys = 0,
|
||||||
unsigned numTys = 0);
|
unsigned numTys = 0);
|
||||||
|
|
||||||
|
/// Map a GCC builtin name to an intrinsic ID.
|
||||||
|
ID getIntrinsicForGCCBuiltin(const char *Prefix, const char *BuiltinName);
|
||||||
|
|
||||||
} // End Intrinsic namespace
|
} // End Intrinsic namespace
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
@ -144,6 +144,8 @@ class Intrinsic<list<LLVMType> ret_types,
|
|||||||
list<LLVMType> RetTypes = ret_types;
|
list<LLVMType> RetTypes = ret_types;
|
||||||
list<LLVMType> ParamTypes = param_types;
|
list<LLVMType> ParamTypes = param_types;
|
||||||
list<IntrinsicProperty> Properties = properties;
|
list<IntrinsicProperty> Properties = properties;
|
||||||
|
|
||||||
|
bit isTarget = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this
|
/// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this
|
||||||
|
@ -213,6 +213,10 @@ public:
|
|||||||
Constant *getOrInsertFunction(const std::string &Name, const Type *RetTy, ...)
|
Constant *getOrInsertFunction(const std::string &Name, const Type *RetTy, ...)
|
||||||
END_WITH_NULL;
|
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.
|
/// getFunction - Look up the specified function in the module symbol table.
|
||||||
/// If it does not exist, return null.
|
/// If it does not exist, return null.
|
||||||
Function *getFunction(const std::string &Name) const;
|
Function *getFunction(const std::string &Name) const;
|
||||||
|
48
include/llvm/Target/TargetIntrinsicInfo.h
Normal file
48
include/llvm/Target/TargetIntrinsicInfo.h
Normal file
@ -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
|
@ -23,6 +23,7 @@ class TargetAsmInfo;
|
|||||||
class TargetData;
|
class TargetData;
|
||||||
class TargetSubtarget;
|
class TargetSubtarget;
|
||||||
class TargetInstrInfo;
|
class TargetInstrInfo;
|
||||||
|
class TargetIntrinsicInfo;
|
||||||
class TargetJITInfo;
|
class TargetJITInfo;
|
||||||
class TargetLowering;
|
class TargetLowering;
|
||||||
class TargetFrameInfo;
|
class TargetFrameInfo;
|
||||||
@ -118,7 +119,6 @@ public:
|
|||||||
virtual TargetLowering *getTargetLowering() const { return 0; }
|
virtual TargetLowering *getTargetLowering() const { return 0; }
|
||||||
virtual const TargetData *getTargetData() const { return 0; }
|
virtual const TargetData *getTargetData() const { return 0; }
|
||||||
|
|
||||||
|
|
||||||
/// getTargetAsmInfo - Return target specific asm information.
|
/// getTargetAsmInfo - Return target specific asm information.
|
||||||
///
|
///
|
||||||
const TargetAsmInfo *getTargetAsmInfo() const {
|
const TargetAsmInfo *getTargetAsmInfo() const {
|
||||||
@ -142,6 +142,11 @@ public:
|
|||||||
///
|
///
|
||||||
virtual const TargetRegisterInfo *getRegisterInfo() const { return 0; }
|
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,
|
/// getJITInfo - If this target supports a JIT, return information for it,
|
||||||
/// otherwise return null.
|
/// otherwise return null.
|
||||||
///
|
///
|
||||||
|
@ -2949,15 +2949,6 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
|
|||||||
Value *Callee;
|
Value *Callee;
|
||||||
if (ConvertValIDToValue(PFTy, CalleeID, Callee, PFS)) return true;
|
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
|
// FIXME: In LLVM 3.0, stop accepting zext, sext and inreg as optional
|
||||||
// function attributes.
|
// function attributes.
|
||||||
unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg;
|
unsigned ObsoleteFuncAttrs = Attribute::ZExt|Attribute::SExt|Attribute::InReg;
|
||||||
|
@ -43,6 +43,7 @@
|
|||||||
#include "llvm/Target/TargetData.h"
|
#include "llvm/Target/TargetData.h"
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
#include "llvm/Target/TargetFrameInfo.h"
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
#include "llvm/Target/TargetInstrInfo.h"
|
||||||
|
#include "llvm/Target/TargetIntrinsicInfo.h"
|
||||||
#include "llvm/Target/TargetLowering.h"
|
#include "llvm/Target/TargetLowering.h"
|
||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
@ -4426,6 +4427,14 @@ void SelectionDAGLowering::visitCall(CallInst &I) {
|
|||||||
const char *RenameFn = 0;
|
const char *RenameFn = 0;
|
||||||
if (Function *F = I.getCalledFunction()) {
|
if (Function *F = I.getCalledFunction()) {
|
||||||
if (F->isDeclaration()) {
|
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()) {
|
if (unsigned IID = F->getIntrinsicID()) {
|
||||||
RenameFn = visitIntrinsicCall(I, IID);
|
RenameFn = visitIntrinsicCall(I, IID);
|
||||||
if (!RenameFn)
|
if (!RenameFn)
|
||||||
|
22
lib/Target/TargetIntrinsicInfo.cpp
Normal file
22
lib/Target/TargetIntrinsicInfo.cpp
Normal file
@ -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() {
|
||||||
|
}
|
@ -217,7 +217,7 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
|
|||||||
// Upgrade intrinsic attributes. This does not change the function.
|
// Upgrade intrinsic attributes. This does not change the function.
|
||||||
if (NewFn)
|
if (NewFn)
|
||||||
F = NewFn;
|
F = NewFn;
|
||||||
if (unsigned id = F->getIntrinsicID(true))
|
if (unsigned id = F->getIntrinsicID())
|
||||||
F->setAttributes(Intrinsic::getAttributes((Intrinsic::ID)id));
|
F->setAttributes(Intrinsic::getAttributes((Intrinsic::ID)id));
|
||||||
return Upgraded;
|
return Upgraded;
|
||||||
}
|
}
|
||||||
|
@ -175,7 +175,7 @@ Function::Function(const FunctionType *Ty, LinkageTypes Linkage,
|
|||||||
ParentModule->getFunctionList().push_back(this);
|
ParentModule->getFunctionList().push_back(this);
|
||||||
|
|
||||||
// Ensure intrinsics have the right parameter attributes.
|
// Ensure intrinsics have the right parameter attributes.
|
||||||
if (unsigned IID = getIntrinsicID(true))
|
if (unsigned IID = getIntrinsicID())
|
||||||
setAttributes(Intrinsic::getAttributes(Intrinsic::ID(IID)));
|
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
|
/// particular intrinsic functions which correspond to this value are defined in
|
||||||
/// llvm/Intrinsics.h.
|
/// llvm/Intrinsics.h.
|
||||||
///
|
///
|
||||||
unsigned Function::getIntrinsicID(bool noAssert) const {
|
unsigned Function::getIntrinsicID() const {
|
||||||
const ValueName *ValName = this->getValueName();
|
const ValueName *ValName = this->getValueName();
|
||||||
if (!ValName)
|
if (!ValName)
|
||||||
return 0;
|
return 0;
|
||||||
@ -315,12 +315,9 @@ unsigned Function::getIntrinsicID(bool noAssert) const {
|
|||||||
|| Name[2] != 'v' || Name[3] != 'm')
|
|| Name[2] != 'v' || Name[3] != 'm')
|
||||||
return 0; // All intrinsics start with 'llvm.'
|
return 0; // All intrinsics start with 'llvm.'
|
||||||
|
|
||||||
assert((Len != 5 || noAssert) && "'llvm.' is an invalid intrinsic name!");
|
|
||||||
|
|
||||||
#define GET_FUNCTION_RECOGNIZER
|
#define GET_FUNCTION_RECOGNIZER
|
||||||
#include "llvm/Intrinsics.gen"
|
#include "llvm/Intrinsics.gen"
|
||||||
#undef GET_FUNCTION_RECOGNIZER
|
#undef GET_FUNCTION_RECOGNIZER
|
||||||
assert(noAssert && "Invalid LLVM intrinsic name");
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,4 +370,9 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, const Type **Tys,
|
|||||||
getType(id, Tys, numTys)));
|
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
|
// vim: sw=2 ai
|
||||||
|
@ -171,6 +171,25 @@ Constant *Module::getOrInsertFunction(const std::string &Name,
|
|||||||
return F;
|
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,
|
Constant *Module::getOrInsertFunction(const std::string &Name,
|
||||||
const FunctionType *Ty) {
|
const FunctionType *Ty) {
|
||||||
AttrListPtr AttributeList = AttrListPtr::get((AttributeWithIndex *)0, 0);
|
AttrListPtr AttributeList = AttrListPtr::get((AttributeWithIndex *)0, 0);
|
||||||
|
@ -1004,10 +1004,9 @@ void Verifier::VerifyCallSite(CallSite CS) {
|
|||||||
void Verifier::visitCallInst(CallInst &CI) {
|
void Verifier::visitCallInst(CallInst &CI) {
|
||||||
VerifyCallSite(&CI);
|
VerifyCallSite(&CI);
|
||||||
|
|
||||||
if (Function *F = CI.getCalledFunction()) {
|
if (Function *F = CI.getCalledFunction())
|
||||||
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
|
if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
|
||||||
visitIntrinsicFunctionCall(ID, CI);
|
visitIntrinsicFunctionCall(ID, CI);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Verifier::visitInvokeInst(InvokeInst &II) {
|
void Verifier::visitInvokeInst(InvokeInst &II) {
|
||||||
|
@ -1303,7 +1303,8 @@ void TreePattern::dump() const { print(*cerr.stream()); }
|
|||||||
|
|
||||||
// FIXME: REMOVE OSTREAM ARGUMENT
|
// FIXME: REMOVE OSTREAM ARGUMENT
|
||||||
CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) {
|
CodeGenDAGPatterns::CodeGenDAGPatterns(RecordKeeper &R) : Records(R) {
|
||||||
Intrinsics = LoadIntrinsics(Records);
|
Intrinsics = LoadIntrinsics(Records, false);
|
||||||
|
TgtIntrinsics = LoadIntrinsics(Records, true);
|
||||||
ParseNodeInfo();
|
ParseNodeInfo();
|
||||||
ParseNodeTransforms();
|
ParseNodeTransforms();
|
||||||
ParseComplexPatterns();
|
ParseComplexPatterns();
|
||||||
|
@ -465,6 +465,7 @@ class CodeGenDAGPatterns {
|
|||||||
RecordKeeper &Records;
|
RecordKeeper &Records;
|
||||||
CodeGenTarget Target;
|
CodeGenTarget Target;
|
||||||
std::vector<CodeGenIntrinsic> Intrinsics;
|
std::vector<CodeGenIntrinsic> Intrinsics;
|
||||||
|
std::vector<CodeGenIntrinsic> TgtIntrinsics;
|
||||||
|
|
||||||
std::map<Record*, SDNodeInfo> SDNodes;
|
std::map<Record*, SDNodeInfo> SDNodes;
|
||||||
std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms;
|
std::map<Record*, std::pair<Record*, std::string> > SDNodeXForms;
|
||||||
@ -515,18 +516,25 @@ public:
|
|||||||
const CodeGenIntrinsic &getIntrinsic(Record *R) const {
|
const CodeGenIntrinsic &getIntrinsic(Record *R) const {
|
||||||
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
|
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
|
||||||
if (Intrinsics[i].TheDef == R) return Intrinsics[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!");
|
assert(0 && "Unknown intrinsic!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
|
const CodeGenIntrinsic &getIntrinsicInfo(unsigned IID) const {
|
||||||
assert(IID-1 < Intrinsics.size() && "Bad intrinsic ID!");
|
if (IID-1 < Intrinsics.size())
|
||||||
return Intrinsics[IID-1];
|
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 {
|
unsigned getIntrinsicID(Record *R) const {
|
||||||
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
|
for (unsigned i = 0, e = Intrinsics.size(); i != e; ++i)
|
||||||
if (Intrinsics[i].TheDef == R) return 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!");
|
assert(0 && "Unknown intrinsic!");
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,8 @@ namespace llvm {
|
|||||||
|
|
||||||
/// LoadIntrinsics - Read all of the intrinsics defined in the specified
|
/// LoadIntrinsics - Read all of the intrinsics defined in the specified
|
||||||
/// .td file.
|
/// .td file.
|
||||||
std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC);
|
std::vector<CodeGenIntrinsic> LoadIntrinsics(const RecordKeeper &RC,
|
||||||
|
bool TargetOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -426,13 +426,17 @@ ComplexPattern::ComplexPattern(Record *R) {
|
|||||||
// CodeGenIntrinsic Implementation
|
// 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<Record*> I = RC.getAllDerivedDefinitions("Intrinsic");
|
||||||
|
|
||||||
std::vector<CodeGenIntrinsic> Result;
|
std::vector<CodeGenIntrinsic> Result;
|
||||||
|
|
||||||
for (unsigned i = 0, e = I.size(); i != e; ++i)
|
for (unsigned i = 0, e = I.size(); i != e; ++i) {
|
||||||
Result.push_back(CodeGenIntrinsic(I[i]));
|
bool isTarget = I[i]->getValueAsBit("isTarget");
|
||||||
|
if (isTarget == TargetOnly)
|
||||||
|
Result.push_back(CodeGenIntrinsic(I[i]));
|
||||||
|
}
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,10 @@ using namespace llvm;
|
|||||||
void IntrinsicEmitter::run(std::ostream &OS) {
|
void IntrinsicEmitter::run(std::ostream &OS) {
|
||||||
EmitSourceFileHeader("Intrinsic Function Source Fragment", 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.
|
// Emit the enum information.
|
||||||
EmitEnumInfo(Ints, OS);
|
EmitEnumInfo(Ints, OS);
|
||||||
@ -91,12 +94,12 @@ EmitFnNameRecognizer(const std::vector<CodeGenIntrinsic> &Ints,
|
|||||||
if (Ints[I->second].isOverloaded)
|
if (Ints[I->second].isOverloaded)
|
||||||
OS << " if (Len > " << I->first.size()
|
OS << " if (Len > " << I->first.size()
|
||||||
<< " && !memcmp(Name, \"" << I->first << ".\", "
|
<< " && !memcmp(Name, \"" << I->first << ".\", "
|
||||||
<< (I->first.size() + 1) << ")) return Intrinsic::"
|
<< (I->first.size() + 1) << ")) return " << TargetPrefix << "Intrinsic::"
|
||||||
<< Ints[I->second].EnumName << ";\n";
|
<< Ints[I->second].EnumName << ";\n";
|
||||||
else
|
else
|
||||||
OS << " if (Len == " << I->first.size()
|
OS << " if (Len == " << I->first.size()
|
||||||
<< " && !memcmp(Name, \"" << I->first << "\", "
|
<< " && !memcmp(Name, \"" << I->first << "\", "
|
||||||
<< I->first.size() << ")) return Intrinsic::"
|
<< I->first.size() << ")) return " << TargetPrefix << "Intrinsic::"
|
||||||
<< Ints[I->second].EnumName << ";\n";
|
<< Ints[I->second].EnumName << ";\n";
|
||||||
}
|
}
|
||||||
OS << " }\n";
|
OS << " }\n";
|
||||||
@ -351,11 +354,13 @@ void IntrinsicEmitter::EmitGenerator(const std::vector<CodeGenIntrinsic> &Ints,
|
|||||||
Ints[i].IS.ParamTypeDefs)].push_back(i);
|
Ints[i].IS.ParamTypeDefs)].push_back(i);
|
||||||
|
|
||||||
// Loop through the array, emitting one generator for each batch.
|
// Loop through the array, emitting one generator for each batch.
|
||||||
|
std::string IntrinsicStr = TargetPrefix + "Intrinsic::";
|
||||||
|
|
||||||
for (MapTy::iterator I = UniqueArgInfos.begin(),
|
for (MapTy::iterator I = UniqueArgInfos.begin(),
|
||||||
E = UniqueArgInfos.end(); I != E; ++I) {
|
E = UniqueArgInfos.end(); I != E; ++I) {
|
||||||
for (unsigned i = 0, e = I->second.size(); i != e; ++i)
|
for (unsigned i = 0, e = I->second.size(); i != e; ++i)
|
||||||
OS << " case Intrinsic::" << Ints[I->second[i]].EnumName << ":\t\t// "
|
OS << " case " << IntrinsicStr << Ints[I->second[i]].EnumName
|
||||||
<< Ints[I->second[i]].Name << "\n";
|
<< ":\t\t// " << Ints[I->second[i]].Name << "\n";
|
||||||
|
|
||||||
const RecPair &ArgTypes = I->first;
|
const RecPair &ArgTypes = I->first;
|
||||||
const std::vector<Record*> &RetTys = ArgTypes.first;
|
const std::vector<Record*> &RetTys = ArgTypes.first;
|
||||||
@ -392,7 +397,11 @@ void IntrinsicEmitter::
|
|||||||
EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
|
EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
|
||||||
OS << "// Add parameter attributes that are not common to all intrinsics.\n";
|
OS << "// Add parameter attributes that are not common to all intrinsics.\n";
|
||||||
OS << "#ifdef GET_INTRINSIC_ATTRIBUTES\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 << " // No intrinsic can throw exceptions.\n";
|
||||||
OS << " Attributes Attr = Attribute::NoUnwind;\n";
|
OS << " Attributes Attr = Attribute::NoUnwind;\n";
|
||||||
OS << " switch (id) {\n";
|
OS << " switch (id) {\n";
|
||||||
@ -404,7 +413,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
|
|||||||
switch (Ints[i].ModRef) {
|
switch (Ints[i].ModRef) {
|
||||||
default: break;
|
default: break;
|
||||||
case CodeGenIntrinsic::NoMem:
|
case CodeGenIntrinsic::NoMem:
|
||||||
OS << " case Intrinsic::" << Ints[i].EnumName << ":\n";
|
OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
|
||||||
|
<< ":\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -415,7 +425,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
|
|||||||
default: break;
|
default: break;
|
||||||
case CodeGenIntrinsic::ReadArgMem:
|
case CodeGenIntrinsic::ReadArgMem:
|
||||||
case CodeGenIntrinsic::ReadMem:
|
case CodeGenIntrinsic::ReadMem:
|
||||||
OS << " case Intrinsic::" << Ints[i].EnumName << ":\n";
|
OS << " case " << TargetPrefix << "Intrinsic::" << Ints[i].EnumName
|
||||||
|
<< ":\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -431,7 +442,8 @@ EmitAttributes(const std::vector<CodeGenIntrinsic> &Ints, std::ostream &OS) {
|
|||||||
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
|
for (unsigned i = 0, e = Ints.size(); i != e; ++i) {
|
||||||
if (Ints[i].ArgumentAttributes.empty()) continue;
|
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 =
|
std::vector<std::pair<unsigned, CodeGenIntrinsic::ArgAttribute> > ArgAttrs =
|
||||||
Ints[i].ArgumentAttributes;
|
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;
|
typedef std::map<std::string, std::string>::const_iterator StrMapIterator;
|
||||||
static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
|
static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
|
||||||
unsigned CharStart, unsigned Indent,
|
unsigned CharStart, unsigned Indent,
|
||||||
std::ostream &OS) {
|
std::string TargetPrefix, std::ostream &OS) {
|
||||||
if (Start == End) return; // empty range.
|
if (Start == End) return; // empty range.
|
||||||
|
|
||||||
// Determine what, if anything, is the same about all these strings.
|
// 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";
|
OS << CommonString.size() - CharStart << "))\n";
|
||||||
++Indent;
|
++Indent;
|
||||||
}
|
}
|
||||||
OS << std::string(Indent*2, ' ') << "IntrinsicID = Intrinsic::";
|
OS << std::string(Indent*2, ' ') << "IntrinsicID = " << TargetPrefix
|
||||||
|
<< "Intrinsic::";
|
||||||
OS << Start->second << ";\n";
|
OS << Start->second << ";\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -535,7 +548,8 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
|
|||||||
OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
|
OS << ", \"" << (CommonString.c_str()+CharStart) << "\", ";
|
||||||
OS << CommonString.size()-CharStart << ")) {\n";
|
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";
|
OS << std::string(Indent*2, ' ') << "}\n";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -556,7 +570,7 @@ static void EmitBuiltinComparisons(StrMapIterator Start, StrMapIterator End,
|
|||||||
for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar;
|
for (++NextChar; NextChar != End && NextChar->first[CharStart] == ThisChar;
|
||||||
++NextChar)
|
++NextChar)
|
||||||
/*empty*/;
|
/*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";
|
OS << std::string(Indent*2, ' ') << " break;\n";
|
||||||
I = NextChar;
|
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
|
/// EmitTargetBuiltins - All of the builtins in the specified map are for the
|
||||||
/// same target, and we already checked it.
|
/// same target, and we already checked it.
|
||||||
static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
|
static void EmitTargetBuiltins(const std::map<std::string, std::string> &BIM,
|
||||||
|
const std::string &TargetPrefix,
|
||||||
std::ostream &OS) {
|
std::ostream &OS) {
|
||||||
// Rearrange the builtins by length.
|
// Rearrange the builtins by length.
|
||||||
std::vector<std::map<std::string, std::string> > BuiltinsByLen;
|
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;
|
if (BuiltinsByLen[i].empty()) continue;
|
||||||
OS << " case " << i << ":\n";
|
OS << " case " << i << ":\n";
|
||||||
EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(),
|
EmitBuiltinComparisons(BuiltinsByLen[i].begin(), BuiltinsByLen[i].end(),
|
||||||
0, 3, OS);
|
0, 3, TargetPrefix, OS);
|
||||||
OS << " break;\n";
|
OS << " break;\n";
|
||||||
}
|
}
|
||||||
OS << " }\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 BuiltinName, and a target prefix (e.g. 'ppc') is passed\n";
|
||||||
OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
|
OS << "// in as TargetPrefix. The result is assigned to 'IntrinsicID'.\n";
|
||||||
OS << "#ifdef GET_LLVM_INTRINSIC_FOR_GCC_BUILTIN\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.
|
// Note: this could emit significantly better code if we cared.
|
||||||
for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
|
for (BIMTy::iterator I = BuiltinMap.begin(), E = BuiltinMap.end();I != E;++I){
|
||||||
@ -625,8 +655,10 @@ EmitIntrinsicToGCCBuiltinMap(const std::vector<CodeGenIntrinsic> &Ints,
|
|||||||
OS << "{\n";
|
OS << "{\n";
|
||||||
|
|
||||||
// Emit the comparisons for this target prefix.
|
// Emit the comparisons for this target prefix.
|
||||||
EmitTargetBuiltins(I->second, OS);
|
EmitTargetBuiltins(I->second, TargetPrefix, OS);
|
||||||
OS << " }\n";
|
OS << " }\n";
|
||||||
}
|
}
|
||||||
|
OS << " return IntrinsicID;\n";
|
||||||
|
OS << "}\n";
|
||||||
OS << "#endif\n\n";
|
OS << "#endif\n\n";
|
||||||
}
|
}
|
||||||
|
@ -20,9 +20,12 @@
|
|||||||
namespace llvm {
|
namespace llvm {
|
||||||
class IntrinsicEmitter : public TableGenBackend {
|
class IntrinsicEmitter : public TableGenBackend {
|
||||||
RecordKeeper &Records;
|
RecordKeeper &Records;
|
||||||
|
bool TargetOnly;
|
||||||
|
std::string TargetPrefix;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IntrinsicEmitter(RecordKeeper &R) : Records(R) {}
|
IntrinsicEmitter(RecordKeeper &R, bool T = false)
|
||||||
|
: Records(R), TargetOnly(T) {}
|
||||||
|
|
||||||
void run(std::ostream &OS);
|
void run(std::ostream &OS);
|
||||||
|
|
||||||
|
@ -49,6 +49,7 @@ enum ActionType {
|
|||||||
GenFastISel,
|
GenFastISel,
|
||||||
GenSubtarget,
|
GenSubtarget,
|
||||||
GenIntrinsic,
|
GenIntrinsic,
|
||||||
|
GenTgtIntrinsic,
|
||||||
GenLLVMCConf,
|
GenLLVMCConf,
|
||||||
PrintEnums
|
PrintEnums
|
||||||
};
|
};
|
||||||
@ -82,6 +83,8 @@ namespace {
|
|||||||
"Generate subtarget enumerations"),
|
"Generate subtarget enumerations"),
|
||||||
clEnumValN(GenIntrinsic, "gen-intrinsic",
|
clEnumValN(GenIntrinsic, "gen-intrinsic",
|
||||||
"Generate intrinsic information"),
|
"Generate intrinsic information"),
|
||||||
|
clEnumValN(GenTgtIntrinsic, "gen-tgt-intrinsic",
|
||||||
|
"Generate target intrinsic information"),
|
||||||
clEnumValN(GenLLVMCConf, "gen-llvmc",
|
clEnumValN(GenLLVMCConf, "gen-llvmc",
|
||||||
"Generate LLVMC configuration library"),
|
"Generate LLVMC configuration library"),
|
||||||
clEnumValN(PrintEnums, "print-enums",
|
clEnumValN(PrintEnums, "print-enums",
|
||||||
@ -190,6 +193,9 @@ int main(int argc, char **argv) {
|
|||||||
case GenIntrinsic:
|
case GenIntrinsic:
|
||||||
IntrinsicEmitter(Records).run(*Out);
|
IntrinsicEmitter(Records).run(*Out);
|
||||||
break;
|
break;
|
||||||
|
case GenTgtIntrinsic:
|
||||||
|
IntrinsicEmitter(Records, true).run(*Out);
|
||||||
|
break;
|
||||||
case GenLLVMCConf:
|
case GenLLVMCConf:
|
||||||
LLVMCConfigurationEmitter(Records).run(*Out);
|
LLVMCConfigurationEmitter(Records).run(*Out);
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user