class AttributeSetNode;
class Constant;
template<typename T> struct DenseMapInfo;
-class Function;
class LLVMContext;
class Type;
/// \brief Which attributes cannot be applied to a type.
AttrBuilder typeIncompatible(Type *Ty);
-/// \returns Return true if the two functions have compatible target-independent
-/// attributes for inlining purposes.
-bool areInlineCompatible(const Function &Caller, const Function &Callee);
-
-/// \brief Merge caller's and callee's attributes.
-void mergeAttributesForInlining(Function &Caller, const Function &Callee);
-
} // end AttributeFuncs namespace
} // end llvm namespace
def NoInfsFPMath : StrBoolAttr<"no-infs-fp-math">;
def NoNansFPMath : StrBoolAttr<"no-nans-fp-math">;
def UnsafeFPMath : StrBoolAttr<"unsafe-fp-math">;
-
-class CompatRule<string F> {
- // The name of the function called to check the attribute of the caller and
- // callee and decide whether inlining should be allowed. The function's
- // signature must match "bool(const Function&, const Function &)", where the
- // first parameter is the reference to the caller and the second parameter is
- // the reference to the callee. It must return false if the attributes of the
- // caller and callee are incompatible, and true otherwise.
- string CompatFunc = F;
-}
-
-def : CompatRule<"isEqual<SanitizeAddressAttr>">;
-def : CompatRule<"isEqual<SanitizeThreadAttr>">;
-def : CompatRule<"isEqual<SanitizeMemoryAttr>">;
-
-class MergeRule<string F> {
- // The name of the function called to merge the attributes of the caller and
- // callee. The function's signature must match
- // "void(Function&, const Function &)", where the first parameter is the
- // reference to the caller and the second parameter is the reference to the
- // callee.
- string MergeFunc = F;
-}
-
-def : MergeRule<"adjustCallerSSPLevel">;
return getInlineCost(CS, CS.getCalledFunction(), Threshold);
}
+/// \brief Test that two functions either have or have not the given attribute
+/// at the same time.
+template<typename AttrKind>
+static bool attributeMatches(Function *F1, Function *F2, AttrKind Attr) {
+ return F1->getFnAttribute(Attr) == F2->getFnAttribute(Attr);
+}
+
/// \brief Test that there are no attribute conflicts between Caller and Callee
/// that prevent inlining.
static bool functionsHaveCompatibleAttributes(Function *Caller,
Function *Callee,
TargetTransformInfo &TTI) {
return TTI.areInlineCompatible(Caller, Callee) &&
- AttributeFuncs::areInlineCompatible(*Caller, *Callee);
+ attributeMatches(Caller, Callee, Attribute::SanitizeAddress) &&
+ attributeMatches(Caller, Callee, Attribute::SanitizeMemory) &&
+ attributeMatches(Caller, Callee, Attribute::SanitizeThread);
}
InlineCost InlineCostAnalysis::getInlineCost(CallSite CS, Function *Callee,
//===----------------------------------------------------------------------===//
#include "llvm/IR/Attributes.h"
-#include "llvm/IR/Function.h"
#include "AttributeImpl.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/STLExtras.h"
return Incompatible;
}
-
-template<typename AttrClass>
-static bool isEqual(const Function &Caller, const Function &Callee) {
- return Caller.getFnAttribute(AttrClass::Kind) ==
- Callee.getFnAttribute(AttrClass::Kind);
-}
-
-/// \brief Compute the logical AND of the attributes of the caller and the
-/// callee.
-///
-/// This function sets the caller's attribute to false if the callee's attribute
-/// is false.
-template<typename AttrClass>
-static void setAND(Function &Caller, const Function &Callee) {
- if (AttrClass::isSet(Caller, AttrClass::Kind) &&
- !AttrClass::isSet(Callee, AttrClass::Kind))
- AttrClass::set(Caller, AttrClass::Kind, false);
-}
-
-/// \brief Compute the logical OR of the attributes of the caller and the
-/// callee.
-///
-/// This function sets the caller's attribute to true if the callee's attribute
-/// is true.
-template<typename AttrClass>
-static void setOR(Function &Caller, const Function &Callee) {
- if (!AttrClass::isSet(Caller, AttrClass::Kind) &&
- AttrClass::isSet(Callee, AttrClass::Kind))
- AttrClass::set(Caller, AttrClass::Kind, true);
-}
-
-/// \brief If the inlined function had a higher stack protection level than the
-/// calling function, then bump up the caller's stack protection level.
-static void adjustCallerSSPLevel(Function &Caller, const Function &Callee) {
- // If upgrading the SSP attribute, clear out the old SSP Attributes first.
- // Having multiple SSP attributes doesn't actually hurt, but it adds useless
- // clutter to the IR.
- AttrBuilder B;
- B.addAttribute(Attribute::StackProtect)
- .addAttribute(Attribute::StackProtectStrong)
- .addAttribute(Attribute::StackProtectReq);
- AttributeSet OldSSPAttr = AttributeSet::get(Caller.getContext(),
- AttributeSet::FunctionIndex,
- B);
-
- if (Callee.hasFnAttribute(Attribute::SafeStack)) {
- Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
- Caller.addFnAttr(Attribute::SafeStack);
- } else if (Callee.hasFnAttribute(Attribute::StackProtectReq) &&
- !Caller.hasFnAttribute(Attribute::SafeStack)) {
- Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
- Caller.addFnAttr(Attribute::StackProtectReq);
- } else if (Callee.hasFnAttribute(Attribute::StackProtectStrong) &&
- !Caller.hasFnAttribute(Attribute::SafeStack) &&
- !Caller.hasFnAttribute(Attribute::StackProtectReq)) {
- Caller.removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
- Caller.addFnAttr(Attribute::StackProtectStrong);
- } else if (Callee.hasFnAttribute(Attribute::StackProtect) &&
- !Caller.hasFnAttribute(Attribute::SafeStack) &&
- !Caller.hasFnAttribute(Attribute::StackProtectReq) &&
- !Caller.hasFnAttribute(Attribute::StackProtectStrong))
- Caller.addFnAttr(Attribute::StackProtect);
-}
-
-#define GET_ATTR_COMPAT_FUNC
-#include "AttributesCompatFunc.inc"
-
-bool AttributeFuncs::areInlineCompatible(const Function &Caller,
- const Function &Callee) {
- return hasCompatibleFnAttrs(Caller, Callee);
-}
-
-
-void AttributeFuncs::mergeAttributesForInlining(Function &Caller,
- const Function &Callee) {
- mergeFnAttrs(Caller, Callee);
-}
+++ /dev/null
-include "llvm/IR/Attributes.td"
-set(LLVM_TARGET_DEFINITIONS AttributesCompatFunc.td)
-tablegen(LLVM AttributesCompatFunc.inc -gen-attrs)
-add_public_tablegen_target(AttributeCompatFuncTableGen)
-
add_llvm_library(LLVMCore
AsmWriter.cpp
Attributes.cpp
BUILD_ARCHIVE = 1
BUILT_SOURCES = $(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen \
- $(PROJ_OBJ_ROOT)/include/llvm/IR/Attributes.inc \
- $(PROJ_OBJ_ROOT)/lib/IR/AttributesCompatFunc.inc
+ $(PROJ_OBJ_ROOT)/include/llvm/IR/Attributes.inc
include $(LEVEL)/Makefile.common
GENFILE:=$(PROJ_OBJ_ROOT)/include/llvm/IR/Intrinsics.gen
ATTRINCFILE:=$(PROJ_OBJ_ROOT)/include/llvm/IR/Attributes.inc
-ATTRCOMPATFUNCINCFILE:=$(PROJ_OBJ_ROOT)/lib/IR/AttributesCompatFunc.inc
INTRINSICTD := $(PROJ_SRC_ROOT)/include/llvm/IR/Intrinsics.td
INTRINSICTDS := $(wildcard $(PROJ_SRC_ROOT)/include/llvm/IR/Intrinsics*.td)
ATTRIBUTESTD := $(PROJ_SRC_ROOT)/include/llvm/IR/Attributes.td
-ATTRCOMPATFUNCTD := $(PROJ_SRC_ROOT)/lib/IR/AttributesCompatFunc.td
$(ObjDir)/Intrinsics.gen.tmp: $(ObjDir)/.dir $(INTRINSICTDS) $(LLVM_TBLGEN)
$(Echo) Building Intrinsics.gen.tmp from Intrinsics.td
$(EchoCmd) Updated Attributes.inc because Attributes.inc.tmp \
changed significantly. )
-$(ObjDir)/AttributesCompatFunc.inc.tmp: $(ObjDir)/.dir $(ATTRCOMPATFUNCTD) $(LLVM_TBLGEN)
- $(Echo) Building AttributesCompatFunc.inc.tmp from $(ATTRCOMPATFUNCTD)
- $(Verb) $(LLVMTableGen) $(call SYSPATH, $(ATTRCOMPATFUNCTD)) -o $(call SYSPATH, $@) -gen-attrs
-
-$(ATTRCOMPATFUNCINCFILE): $(ObjDir)/AttributesCompatFunc.inc.tmp $(PROJ_OBJ_ROOT)/include/llvm/IR/.dir
- $(Verb) $(CMP) -s $@ $< || ( $(CP) $< $@ && \
- $(EchoCmd) Updated AttributesCompatFunc.inc because AttributesCompatFunc.inc.tmp \
- changed significantly. )
-
install-local:: $(GENFILE)
$(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/IR/Intrinsics.gen
$(Verb) $(DataInstall) $(GENFILE) $(DESTDIR)$(PROJ_includedir)/llvm/IR/Intrinsics.gen
install-local:: $(ATTRINCFILE)
$(Echo) Installing $(DESTDIR)$(PROJ_includedir)/llvm/IR/Attributes.inc
$(Verb) $(DataInstall) $(ATTRINCFILE) $(DESTDIR)$(PROJ_includedir)/llvm/IR/Attributes.inc
-
-install-local:: $(ATTRCOMPATFUNCINCFILE)
- $(Echo) Installing $(DESTDIR)$(PROJ_libdir)/IR/AttributesCompatFunc.inc
- $(Verb) $(DataInstall) $(ATTRCOMPATFUNCINCFILE) $(DESTDIR)$(PROJ_libdir)/IR/AttributesCompatFunc.inc
typedef DenseMap<ArrayType*, std::vector<AllocaInst*> >
InlinedArrayAllocasTy;
+/// \brief If the inlined function had a higher stack protection level than the
+/// calling function, then bump up the caller's stack protection level.
+static void AdjustCallerSSPLevel(Function *Caller, Function *Callee) {
+ // If upgrading the SSP attribute, clear out the old SSP Attributes first.
+ // Having multiple SSP attributes doesn't actually hurt, but it adds useless
+ // clutter to the IR.
+ AttrBuilder B;
+ B.addAttribute(Attribute::StackProtect)
+ .addAttribute(Attribute::StackProtectStrong)
+ .addAttribute(Attribute::StackProtectReq);
+ AttributeSet OldSSPAttr = AttributeSet::get(Caller->getContext(),
+ AttributeSet::FunctionIndex,
+ B);
+
+ if (Callee->hasFnAttribute(Attribute::SafeStack)) {
+ Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller->addFnAttr(Attribute::SafeStack);
+ } else if (Callee->hasFnAttribute(Attribute::StackProtectReq) &&
+ !Caller->hasFnAttribute(Attribute::SafeStack)) {
+ Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller->addFnAttr(Attribute::StackProtectReq);
+ } else if (Callee->hasFnAttribute(Attribute::StackProtectStrong) &&
+ !Caller->hasFnAttribute(Attribute::SafeStack) &&
+ !Caller->hasFnAttribute(Attribute::StackProtectReq)) {
+ Caller->removeAttributes(AttributeSet::FunctionIndex, OldSSPAttr);
+ Caller->addFnAttr(Attribute::StackProtectStrong);
+ } else if (Callee->hasFnAttribute(Attribute::StackProtect) &&
+ !Caller->hasFnAttribute(Attribute::SafeStack) &&
+ !Caller->hasFnAttribute(Attribute::StackProtectReq) &&
+ !Caller->hasFnAttribute(Attribute::StackProtectStrong))
+ Caller->addFnAttr(Attribute::StackProtect);
+}
+
/// If it is possible to inline the specified call site,
/// do so and update the CallGraph for this operation.
///
if (!InlineFunction(CS, IFI, &AAR, InsertLifetime))
return false;
- AttributeFuncs::mergeAttributesForInlining(*Caller, *Callee);
+ AdjustCallerSSPLevel(Caller, Callee);
// Look at all of the allocas that we inlined through this call site. If we
// have already inlined other allocas through other calls into this function,
private:
void emitTargetIndependentEnums(raw_ostream &OS);
- void emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr);
-
- void printEnumAttrClasses(raw_ostream &OS,
- const std::vector<Record *> &Records);
- void printStrBoolAttrClasses(raw_ostream &OS,
- const std::vector<Record *> &Records);
RecordKeeper &Records;
};
OS << "#endif\n";
}
-void Attributes::emitFnAttrCompatCheck(raw_ostream &OS, bool IsStringAttr) {
- OS << "#ifdef GET_ATTR_COMPAT_FUNC\n";
- OS << "#undef GET_ATTR_COMPAT_FUNC\n";
-
- OS << "struct EnumAttr {\n";
- OS << " static bool isSet(const Function &Fn,\n";
- OS << " Attribute::AttrKind Kind) {\n";
- OS << " return Fn.hasFnAttribute(Kind);\n";
- OS << " }\n\n";
- OS << " static void set(Function &Fn,\n";
- OS << " Attribute::AttrKind Kind, bool Val) {\n";
- OS << " if (Val)\n";
- OS << " Fn.addFnAttr(Kind);\n";
- OS << " else\n";
- OS << " Fn.removeFnAttr(Kind);\n";
- OS << " }\n";
- OS << "};\n\n";
-
- OS << "struct StrBoolAttr {\n";
- OS << " static bool isSet(const Function &Fn,\n";
- OS << " StringRef Kind) {\n";
- OS << " auto A = Fn.getFnAttribute(Kind);\n";
- OS << " return A.getValueAsString().equals(\"true\");\n";
- OS << " }\n\n";
- OS << " static void set(Function &Fn,\n";
- OS << " StringRef Kind, bool Val) {\n";
- OS << " Fn.addFnAttr(Kind, Val ? \"true\" : \"false\");\n";
- OS << " }\n";
- OS << "};\n\n";
-
- printEnumAttrClasses(OS ,Records.getAllDerivedDefinitions("EnumAttr"));
- printStrBoolAttrClasses(OS , Records.getAllDerivedDefinitions("StrBoolAttr"));
-
- OS << "static inline bool hasCompatibleFnAttrs(const Function &Caller,\n"
- << " const Function &Callee) {\n";
- OS << " bool Ret = true;\n\n";
-
- const std::vector<Record *> &CompatRules =
- Records.getAllDerivedDefinitions("CompatRule");
-
- for (auto *Rule : CompatRules) {
- std::string FuncName = Rule->getValueAsString("CompatFunc");
- OS << " Ret &= " << FuncName << "(Caller, Callee);\n";
- }
-
- OS << "\n";
- OS << " return Ret;\n";
- OS << "}\n\n";
-
- const std::vector<Record *> &MergeRules =
- Records.getAllDerivedDefinitions("MergeRule");
- OS << "static inline void mergeFnAttrs(Function &Caller,\n"
- << " const Function &Callee) {\n";
-
- for (auto *Rule : MergeRules) {
- std::string FuncName = Rule->getValueAsString("MergeFunc");
- OS << " " << FuncName << "(Caller, Callee);\n";
- }
-
- OS << "}\n\n";
-
- OS << "#endif\n";
-}
-
-void Attributes::printEnumAttrClasses(raw_ostream &OS,
- const std::vector<Record *> &Records) {
- OS << "// EnumAttr classes\n";
- for (const auto *R : Records) {
- OS << "struct " << R->getName() << "Attr : EnumAttr {\n";
- OS << " constexpr static const enum Attribute::AttrKind Kind = ";
- OS << "Attribute::" << R->getName() << ";\n";
- OS << "};\n";
- }
- OS << "\n";
-}
-
-void Attributes::printStrBoolAttrClasses(raw_ostream &OS,
- const std::vector<Record *> &Records) {
- OS << "// StrBoolAttr classes\n";
- for (const auto *R : Records) {
- OS << "struct " << R->getName() << "Attr : StrBoolAttr {\n";
- OS << " constexpr static const char * const Kind = \"";
- OS << R->getValueAsString("AttrString") << "\";\n";
- OS << "};\n";
- }
- OS << "\n";
-}
-
void Attributes::emit(raw_ostream &OS) {
emitTargetIndependentEnums(OS);
- emitFnAttrCompatCheck(OS, false);
}
namespace llvm {