mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
Implement the NoBuiltin attribute.
The 'nobuiltin' attribute is applied to call sites to indicate that LLVM should not treat the callee function as a built-in function. I.e., it shouldn't try to replace that function with different code. llvm-svn: 175835
This commit is contained in:
parent
ce9cf63b6f
commit
eecb534c87
@ -720,6 +720,11 @@ Currently, only the following parameter attributes are defined:
|
||||
This indicates that the pointer parameter can be excised using the
|
||||
:ref:`trampoline intrinsics <int_trampoline>`. This is not a valid
|
||||
attribute for return values.
|
||||
``nobuiltin``
|
||||
This indicates that the callee function at a call site is not
|
||||
recognized as a built-in function. LLVM will retain the original call
|
||||
and not replace it with equivalent code based on the semantics of the
|
||||
built-in function.
|
||||
|
||||
.. _gc:
|
||||
|
||||
|
@ -75,6 +75,7 @@ public:
|
||||
Naked, ///< Naked function
|
||||
Nest, ///< Nested function static chain
|
||||
NoAlias, ///< Considered to not alias after call
|
||||
NoBuiltin, ///< Callee isn't recognized as a builtin
|
||||
NoCapture, ///< Function creates no aliases of pointer
|
||||
NoDuplicate, ///< Call cannot be duplicated
|
||||
NoImplicitFloat, ///< Disable implicit floating point insts
|
||||
@ -473,31 +474,7 @@ public:
|
||||
bool td_empty() const { return TargetDepAttrs.empty(); }
|
||||
|
||||
/// \brief Remove attributes that are used on functions only.
|
||||
void removeFunctionOnlyAttrs() {
|
||||
removeAttribute(Attribute::NoReturn)
|
||||
.removeAttribute(Attribute::NoUnwind)
|
||||
.removeAttribute(Attribute::ReadNone)
|
||||
.removeAttribute(Attribute::ReadOnly)
|
||||
.removeAttribute(Attribute::NoInline)
|
||||
.removeAttribute(Attribute::AlwaysInline)
|
||||
.removeAttribute(Attribute::OptimizeForSize)
|
||||
.removeAttribute(Attribute::StackProtect)
|
||||
.removeAttribute(Attribute::StackProtectReq)
|
||||
.removeAttribute(Attribute::StackProtectStrong)
|
||||
.removeAttribute(Attribute::NoRedZone)
|
||||
.removeAttribute(Attribute::NoImplicitFloat)
|
||||
.removeAttribute(Attribute::Naked)
|
||||
.removeAttribute(Attribute::InlineHint)
|
||||
.removeAttribute(Attribute::StackAlignment)
|
||||
.removeAttribute(Attribute::UWTable)
|
||||
.removeAttribute(Attribute::NonLazyBind)
|
||||
.removeAttribute(Attribute::ReturnsTwice)
|
||||
.removeAttribute(Attribute::AddressSafety)
|
||||
.removeAttribute(Attribute::ThreadSafety)
|
||||
.removeAttribute(Attribute::UninitializedChecks)
|
||||
.removeAttribute(Attribute::MinSize)
|
||||
.removeAttribute(Attribute::NoDuplicate);
|
||||
}
|
||||
void removeFunctionOnlyAttrs();
|
||||
|
||||
bool operator==(const AttrBuilder &B);
|
||||
bool operator!=(const AttrBuilder &B) {
|
||||
|
@ -571,6 +571,7 @@ lltok::Kind LLLexer::LexIdentifier() {
|
||||
KEYWORD(naked);
|
||||
KEYWORD(nest);
|
||||
KEYWORD(noalias);
|
||||
KEYWORD(nobuiltin);
|
||||
KEYWORD(nocapture);
|
||||
KEYWORD(noduplicate);
|
||||
KEYWORD(noimplicitfloat);
|
||||
|
@ -810,11 +810,13 @@ bool LLParser::ParseUnnamedAttrGrp() {
|
||||
assert(Lex.getKind() == lltok::AttrGrpID);
|
||||
unsigned VarID = Lex.getUIntVal();
|
||||
std::vector<unsigned> unused;
|
||||
LocTy NoBuiltinLoc;
|
||||
Lex.Lex();
|
||||
|
||||
if (ParseToken(lltok::equal, "expected '=' here") ||
|
||||
ParseToken(lltok::lbrace, "expected '{' here") ||
|
||||
ParseFnAttributeValuePairs(NumberedAttrBuilders[VarID], unused, true) ||
|
||||
ParseFnAttributeValuePairs(NumberedAttrBuilders[VarID], unused, true,
|
||||
NoBuiltinLoc) ||
|
||||
ParseToken(lltok::rbrace, "expected end of attribute group"))
|
||||
return true;
|
||||
|
||||
@ -828,13 +830,15 @@ bool LLParser::ParseUnnamedAttrGrp() {
|
||||
/// ::= <attr> | <attr> '=' <value>
|
||||
bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
|
||||
std::vector<unsigned> &FwdRefAttrGrps,
|
||||
bool inAttrGrp) {
|
||||
bool inAttrGrp, LocTy &NoBuiltinLoc) {
|
||||
bool HaveError = false;
|
||||
|
||||
B.clear();
|
||||
|
||||
while (true) {
|
||||
lltok::Kind Token = Lex.getKind();
|
||||
if (Token == lltok::kw_nobuiltin)
|
||||
NoBuiltinLoc = Lex.getLoc();
|
||||
switch (Token) {
|
||||
default:
|
||||
if (!inAttrGrp) return HaveError;
|
||||
@ -908,6 +912,7 @@ bool LLParser::ParseFnAttributeValuePairs(AttrBuilder &B,
|
||||
case lltok::kw_inlinehint: B.addAttribute(Attribute::InlineHint); break;
|
||||
case lltok::kw_minsize: B.addAttribute(Attribute::MinSize); break;
|
||||
case lltok::kw_naked: B.addAttribute(Attribute::Naked); break;
|
||||
case lltok::kw_nobuiltin: B.addAttribute(Attribute::NoBuiltin); break;
|
||||
case lltok::kw_noduplicate: B.addAttribute(Attribute::NoDuplicate); break;
|
||||
case lltok::kw_noimplicitfloat: B.addAttribute(Attribute::NoImplicitFloat); break;
|
||||
case lltok::kw_noinline: B.addAttribute(Attribute::NoInline); break;
|
||||
@ -1164,7 +1169,7 @@ bool LLParser::ParseOptionalParamAttrs(AttrBuilder &B) {
|
||||
case lltok::kw_naked: case lltok::kw_nonlazybind:
|
||||
case lltok::kw_address_safety: case lltok::kw_minsize:
|
||||
case lltok::kw_alignstack: case lltok::kw_thread_safety:
|
||||
case lltok::kw_uninitialized_checks:
|
||||
case lltok::kw_nobuiltin: case lltok::kw_uninitialized_checks:
|
||||
HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute");
|
||||
break;
|
||||
}
|
||||
@ -1207,6 +1212,7 @@ bool LLParser::ParseOptionalReturnAttrs(AttrBuilder &B) {
|
||||
case lltok::kw_minsize: case lltok::kw_alignstack:
|
||||
case lltok::kw_align: case lltok::kw_noduplicate:
|
||||
case lltok::kw_thread_safety: case lltok::kw_uninitialized_checks:
|
||||
case lltok::kw_nobuiltin:
|
||||
HaveError |= Error(Lex.getLoc(), "invalid use of function-only attribute");
|
||||
break;
|
||||
}
|
||||
@ -2944,6 +2950,7 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
|
||||
bool isVarArg;
|
||||
AttrBuilder FuncAttrs;
|
||||
std::vector<unsigned> FwdRefAttrGrps;
|
||||
LocTy NoBuiltinLoc;
|
||||
std::string Section;
|
||||
unsigned Alignment;
|
||||
std::string GC;
|
||||
@ -2953,7 +2960,8 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
|
||||
if (ParseArgumentList(ArgList, isVarArg) ||
|
||||
ParseOptionalToken(lltok::kw_unnamed_addr, UnnamedAddr,
|
||||
&UnnamedAddrLoc) ||
|
||||
ParseFnAttributeValuePairs(FuncAttrs, FwdRefAttrGrps, false) ||
|
||||
ParseFnAttributeValuePairs(FuncAttrs, FwdRefAttrGrps, false,
|
||||
NoBuiltinLoc) ||
|
||||
(EatIfPresent(lltok::kw_section) &&
|
||||
ParseStringConstant(Section)) ||
|
||||
ParseOptionalAlignment(Alignment) ||
|
||||
@ -2961,6 +2969,9 @@ bool LLParser::ParseFunctionHeader(Function *&Fn, bool isDefine) {
|
||||
ParseStringConstant(GC)))
|
||||
return true;
|
||||
|
||||
if (FuncAttrs.contains(Attribute::NoBuiltin))
|
||||
return Error(NoBuiltinLoc, "'nobuiltin' attribute not valid on function");
|
||||
|
||||
// If the alignment was parsed as an attribute, move to the alignment field.
|
||||
if (FuncAttrs.hasAlignmentAttr()) {
|
||||
Alignment = FuncAttrs.getAlignment();
|
||||
@ -3474,6 +3485,7 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
LocTy CallLoc = Lex.getLoc();
|
||||
AttrBuilder RetAttrs, FnAttrs;
|
||||
std::vector<unsigned> FwdRefAttrGrps;
|
||||
LocTy NoBuiltinLoc;
|
||||
CallingConv::ID CC;
|
||||
Type *RetType = 0;
|
||||
LocTy RetTypeLoc;
|
||||
@ -3486,7 +3498,8 @@ bool LLParser::ParseInvoke(Instruction *&Inst, PerFunctionState &PFS) {
|
||||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
|
||||
ParseValID(CalleeID) ||
|
||||
ParseParameterList(ArgList, PFS) ||
|
||||
ParseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false) ||
|
||||
ParseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false,
|
||||
NoBuiltinLoc) ||
|
||||
ParseToken(lltok::kw_to, "expected 'to' in invoke") ||
|
||||
ParseTypeAndBasicBlock(NormalBB, PFS) ||
|
||||
ParseToken(lltok::kw_unwind, "expected 'unwind' in invoke") ||
|
||||
@ -3881,6 +3894,7 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
|
||||
bool isTail) {
|
||||
AttrBuilder RetAttrs, FnAttrs;
|
||||
std::vector<unsigned> FwdRefAttrGrps;
|
||||
LocTy NoBuiltinLoc;
|
||||
CallingConv::ID CC;
|
||||
Type *RetType = 0;
|
||||
LocTy RetTypeLoc;
|
||||
@ -3894,7 +3908,8 @@ bool LLParser::ParseCall(Instruction *&Inst, PerFunctionState &PFS,
|
||||
ParseType(RetType, RetTypeLoc, true /*void allowed*/) ||
|
||||
ParseValID(CalleeID) ||
|
||||
ParseParameterList(ArgList, PFS) ||
|
||||
ParseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false))
|
||||
ParseFnAttributeValuePairs(FnAttrs, FwdRefAttrGrps, false,
|
||||
NoBuiltinLoc))
|
||||
return true;
|
||||
|
||||
// If RetType is a non-function pointer type, then this is the short syntax
|
||||
|
@ -242,7 +242,7 @@ namespace llvm {
|
||||
bool ParseUnnamedAttrGrp();
|
||||
bool ParseFnAttributeValuePairs(AttrBuilder &B,
|
||||
std::vector<unsigned> &FwdRefAttrGrps,
|
||||
bool inAttrGrp);
|
||||
bool inAttrGrp, LocTy &NoBuiltinLoc);
|
||||
|
||||
// Type Parsing.
|
||||
bool ParseType(Type *&Result, bool AllowVoid = false);
|
||||
|
@ -102,6 +102,7 @@ namespace lltok {
|
||||
kw_naked,
|
||||
kw_nest,
|
||||
kw_noalias,
|
||||
kw_nobuiltin,
|
||||
kw_nocapture,
|
||||
kw_noduplicate,
|
||||
kw_noimplicitfloat,
|
||||
|
@ -171,6 +171,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
|
||||
return "nest";
|
||||
if (hasAttribute(Attribute::NoAlias))
|
||||
return "noalias";
|
||||
if (hasAttribute(Attribute::NoBuiltin))
|
||||
return "nobuiltin";
|
||||
if (hasAttribute(Attribute::NoCapture))
|
||||
return "nocapture";
|
||||
if (hasAttribute(Attribute::NoDuplicate))
|
||||
@ -354,6 +356,8 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const {
|
||||
uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
|
||||
// FIXME: Remove this.
|
||||
switch (Val) {
|
||||
default:
|
||||
llvm_unreachable("Unsupported attribute type");
|
||||
case Attribute::EndAttrKinds:
|
||||
llvm_unreachable("Synthetic enumerators which should never get here");
|
||||
|
||||
@ -391,7 +395,6 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
|
||||
case Attribute::ThreadSafety: return 1ULL << 36;
|
||||
case Attribute::UninitializedChecks: return 1ULL << 37;
|
||||
}
|
||||
llvm_unreachable("Unsupported attribute type");
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1097,6 +1100,33 @@ bool AttrBuilder::operator==(const AttrBuilder &B) {
|
||||
return Alignment == B.Alignment && StackAlignment == B.StackAlignment;
|
||||
}
|
||||
|
||||
void AttrBuilder::removeFunctionOnlyAttrs() {
|
||||
removeAttribute(Attribute::NoReturn)
|
||||
.removeAttribute(Attribute::NoUnwind)
|
||||
.removeAttribute(Attribute::ReadNone)
|
||||
.removeAttribute(Attribute::ReadOnly)
|
||||
.removeAttribute(Attribute::NoInline)
|
||||
.removeAttribute(Attribute::AlwaysInline)
|
||||
.removeAttribute(Attribute::OptimizeForSize)
|
||||
.removeAttribute(Attribute::StackProtect)
|
||||
.removeAttribute(Attribute::StackProtectReq)
|
||||
.removeAttribute(Attribute::StackProtectStrong)
|
||||
.removeAttribute(Attribute::NoRedZone)
|
||||
.removeAttribute(Attribute::NoImplicitFloat)
|
||||
.removeAttribute(Attribute::Naked)
|
||||
.removeAttribute(Attribute::InlineHint)
|
||||
.removeAttribute(Attribute::StackAlignment)
|
||||
.removeAttribute(Attribute::UWTable)
|
||||
.removeAttribute(Attribute::NonLazyBind)
|
||||
.removeAttribute(Attribute::ReturnsTwice)
|
||||
.removeAttribute(Attribute::AddressSafety)
|
||||
.removeAttribute(Attribute::ThreadSafety)
|
||||
.removeAttribute(Attribute::UninitializedChecks)
|
||||
.removeAttribute(Attribute::MinSize)
|
||||
.removeAttribute(Attribute::NoDuplicate)
|
||||
.removeAttribute(Attribute::NoBuiltin);
|
||||
}
|
||||
|
||||
AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
|
||||
// FIXME: Remove this in 4.0.
|
||||
if (!Val) return *this;
|
||||
|
@ -653,7 +653,8 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, uint64_t Idx, Type *Ty,
|
||||
!Attrs.hasAttribute(Idx, Attribute::AddressSafety) &&
|
||||
!Attrs.hasAttribute(Idx, Attribute::ThreadSafety) &&
|
||||
!Attrs.hasAttribute(Idx, Attribute::UninitializedChecks) &&
|
||||
!Attrs.hasAttribute(Idx, Attribute::MinSize),
|
||||
!Attrs.hasAttribute(Idx, Attribute::MinSize) &&
|
||||
!Attrs.hasAttribute(Idx, Attribute::NoBuiltin),
|
||||
"Some attributes in '" + Attrs.getAsString(Idx) +
|
||||
"' only apply to functions!", V);
|
||||
|
||||
|
@ -165,7 +165,7 @@ bool SimplifyLibCalls::runOnFunction(Function &F) {
|
||||
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
|
||||
// Ignore non-calls.
|
||||
CallInst *CI = dyn_cast<CallInst>(I++);
|
||||
if (!CI) continue;
|
||||
if (!CI || CI->hasFnAttr(Attribute::NoBuiltin)) continue;
|
||||
|
||||
// Ignore indirect calls and calls to non-external functions.
|
||||
Function *Callee = CI->getCalledFunction();
|
||||
|
@ -1889,6 +1889,7 @@ LibCallSimplifier::~LibCallSimplifier() {
|
||||
}
|
||||
|
||||
Value *LibCallSimplifier::optimizeCall(CallInst *CI) {
|
||||
if (CI->hasFnAttr(Attribute::NoBuiltin)) return 0;
|
||||
return Impl->optimizeCall(CI);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user