mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-14 14:56:47 +00:00
[Driver] Add support for -fno-builtin-foo options.
Addresses PR4941 and rdar://6756912. http://reviews.llvm.org/D15195 llvm-svn: 256937
This commit is contained in:
parent
2d0418e842
commit
7dbc9cf876
@ -192,6 +192,10 @@ public:
|
||||
/// for AuxTarget).
|
||||
unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); }
|
||||
|
||||
/// Returns true if this is a libc/libm function without the '__builtin_'
|
||||
/// prefix.
|
||||
static bool isBuiltinFunc(const char *Name);
|
||||
|
||||
private:
|
||||
const Info &getRecord(unsigned ID) const;
|
||||
|
||||
|
@ -109,6 +109,9 @@ public:
|
||||
/// \brief Options for parsing comments.
|
||||
CommentOptions CommentOpts;
|
||||
|
||||
/// \brief A list of all -fno-builtin-* function names (e.g., memset).
|
||||
std::vector<std::string> NoBuiltinFuncs;
|
||||
|
||||
/// \brief Triples of the OpenMP targets that the host code codegen should
|
||||
/// take into account in order to generate accurate offloading descriptors.
|
||||
std::vector<llvm::Triple> OMPTargetTriples;
|
||||
@ -142,6 +145,10 @@ public:
|
||||
/// \brief Reset all of the options that are not considered when building a
|
||||
/// module.
|
||||
void resetNonModularOptions();
|
||||
|
||||
/// \brief Is this a libc/libm function that is no longer recognized as a
|
||||
/// builtin because a -fno-builtin-* option has been specified?
|
||||
bool isNoBuiltinFunc(const char *Name) const;
|
||||
};
|
||||
|
||||
/// \brief Floating point control options
|
||||
|
@ -814,7 +814,7 @@ def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>;
|
||||
def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group<f_Group>;
|
||||
def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Disable implicit builtin knowledge of functions">;
|
||||
def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<clang_ignored_f_Group>,
|
||||
def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Disable implicit builtin knowledge of a specific function">;
|
||||
def fno_math_builtin : Flag<["-"], "fno-math-builtin">, Group<f_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Disable implicit builtin knowledge of math functions">;
|
||||
|
@ -218,6 +218,9 @@ public:
|
||||
/// Set of sanitizer checks that trap rather than diagnose.
|
||||
SanitizerSet SanitizeTrap;
|
||||
|
||||
/// \brief A list of all -fno-builtin-* function names (e.g., memset).
|
||||
std::vector<std::string> NoBuiltinFuncs;
|
||||
|
||||
public:
|
||||
// Define accessors/mutators for code generation options of enumeration type.
|
||||
#define CODEGENOPT(Name, Bits, Default)
|
||||
@ -227,6 +230,14 @@ public:
|
||||
#include "clang/Frontend/CodeGenOptions.def"
|
||||
|
||||
CodeGenOptions();
|
||||
|
||||
/// \brief Is this a libc/libm function that is no longer recognized as a
|
||||
/// builtin because a -fno-builtin-* option has been specified?
|
||||
bool isNoBuiltinFunc(const char *Name) const;
|
||||
|
||||
const std::vector<std::string> &getNoBuiltinFuncs() const {
|
||||
return NoBuiltinFuncs;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -48,10 +48,20 @@ void Builtin::Context::InitializeTarget(const TargetInfo &Target,
|
||||
AuxTSRecords = AuxTarget->getTargetBuiltins();
|
||||
}
|
||||
|
||||
bool Builtin::Context::isBuiltinFunc(const char *Name) {
|
||||
StringRef FuncName(Name);
|
||||
for (unsigned i = Builtin::NotBuiltin + 1; i != Builtin::FirstTSBuiltin; ++i)
|
||||
if (FuncName.equals(BuiltinInfo[i].Name))
|
||||
return strchr(BuiltinInfo[i].Attributes, 'f') != nullptr;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Builtin::Context::builtinIsSupported(const Builtin::Info &BuiltinInfo,
|
||||
const LangOptions &LangOpts) {
|
||||
bool BuiltinsUnsupported = LangOpts.NoBuiltin &&
|
||||
strchr(BuiltinInfo.Attributes, 'f');
|
||||
bool BuiltinsUnsupported =
|
||||
(LangOpts.NoBuiltin || LangOpts.isNoBuiltinFunc(BuiltinInfo.Name)) &&
|
||||
strchr(BuiltinInfo.Attributes, 'f');
|
||||
bool MathBuiltinsUnsupported =
|
||||
LangOpts.NoMathBuiltin && BuiltinInfo.HeaderName &&
|
||||
llvm::StringRef(BuiltinInfo.HeaderName).equals("math.h");
|
||||
|
@ -11,6 +11,7 @@
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
@ -36,3 +37,10 @@ void LangOptions::resetNonModularOptions() {
|
||||
ImplementationOfModule.clear();
|
||||
}
|
||||
|
||||
bool LangOptions::isNoBuiltinFunc(const char *Name) const {
|
||||
StringRef FuncName(Name);
|
||||
for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i)
|
||||
if (FuncName.equals(NoBuiltinFuncs[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -249,6 +249,13 @@ static TargetLibraryInfoImpl *createTLII(llvm::Triple &TargetTriple,
|
||||
TargetLibraryInfoImpl *TLII = new TargetLibraryInfoImpl(TargetTriple);
|
||||
if (!CodeGenOpts.SimplifyLibCalls)
|
||||
TLII->disableAllFunctions();
|
||||
else {
|
||||
// Disable individual libc/libm calls in TargetLibraryInfo.
|
||||
LibFunc::Func F;
|
||||
for (auto &FuncName : CodeGenOpts.getNoBuiltinFuncs())
|
||||
if (TLII->getLibFunc(FuncName, F))
|
||||
TLII->setUnavailable(F);
|
||||
}
|
||||
|
||||
switch (CodeGenOpts.getVecLib()) {
|
||||
case CodeGenOptions::Accelerate:
|
||||
|
@ -1431,11 +1431,9 @@ static void AddAttributesFromFunctionProtoType(ASTContext &Ctx,
|
||||
FuncAttrs.addAttribute(llvm::Attribute::NoUnwind);
|
||||
}
|
||||
|
||||
void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
||||
CGCalleeInfo CalleeInfo,
|
||||
AttributeListType &PAL,
|
||||
unsigned &CallingConv,
|
||||
bool AttrOnCallSite) {
|
||||
void CodeGenModule::ConstructAttributeList(
|
||||
StringRef Name, const CGFunctionInfo &FI, CGCalleeInfo CalleeInfo,
|
||||
AttributeListType &PAL, unsigned &CallingConv, bool AttrOnCallSite) {
|
||||
llvm::AttrBuilder FuncAttrs;
|
||||
llvm::AttrBuilder RetAttrs;
|
||||
bool HasOptnone = false;
|
||||
@ -1510,7 +1508,8 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
|
||||
|
||||
if (AttrOnCallSite) {
|
||||
// Attributes that should go on the call site only.
|
||||
if (!CodeGenOpts.SimplifyLibCalls)
|
||||
if (!CodeGenOpts.SimplifyLibCalls ||
|
||||
CodeGenOpts.isNoBuiltinFunc(Name.data()))
|
||||
FuncAttrs.addAttribute(llvm::Attribute::NoBuiltin);
|
||||
if (!CodeGenOpts.TrapFuncName.empty())
|
||||
FuncAttrs.addAttribute("trap-func-name", CodeGenOpts.TrapFuncName);
|
||||
@ -3490,8 +3489,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo,
|
||||
|
||||
unsigned CallingConv;
|
||||
CodeGen::AttributeListType AttributeList;
|
||||
CGM.ConstructAttributeList(CallInfo, CalleeInfo, AttributeList, CallingConv,
|
||||
true);
|
||||
CGM.ConstructAttributeList(Callee->getName(), CallInfo, CalleeInfo,
|
||||
AttributeList, CallingConv,
|
||||
/*AttrOnCallSite=*/true);
|
||||
llvm::AttributeSet Attrs = llvm::AttributeSet::get(getLLVMContext(),
|
||||
AttributeList);
|
||||
|
||||
|
@ -378,8 +378,8 @@ void CodeGenFunction::EmitMustTailThunk(const CXXMethodDecl *MD,
|
||||
// Apply the standard set of call attributes.
|
||||
unsigned CallingConv;
|
||||
CodeGen::AttributeListType AttributeList;
|
||||
CGM.ConstructAttributeList(*CurFnInfo, MD, AttributeList, CallingConv,
|
||||
/*AttrOnCallSite=*/true);
|
||||
CGM.ConstructAttributeList(Callee->getName(), *CurFnInfo, MD, AttributeList,
|
||||
CallingConv, /*AttrOnCallSite=*/true);
|
||||
llvm::AttributeSet Attrs =
|
||||
llvm::AttributeSet::get(getLLVMContext(), AttributeList);
|
||||
Call->setAttributes(Attrs);
|
||||
|
@ -774,7 +774,8 @@ void CodeGenModule::SetLLVMFunctionAttributes(const Decl *D,
|
||||
llvm::Function *F) {
|
||||
unsigned CallingConv;
|
||||
AttributeListType AttributeList;
|
||||
ConstructAttributeList(Info, D, AttributeList, CallingConv, false);
|
||||
ConstructAttributeList(F->getName(), Info, D, AttributeList, CallingConv,
|
||||
false);
|
||||
F->setAttributes(llvm::AttributeSet::get(getLLVMContext(), AttributeList));
|
||||
F->setCallingConv(static_cast<llvm::CallingConv::ID>(CallingConv));
|
||||
}
|
||||
|
@ -966,13 +966,14 @@ public:
|
||||
/// Get the LLVM attributes and calling convention to use for a particular
|
||||
/// function type.
|
||||
///
|
||||
/// \param Name - The function name.
|
||||
/// \param Info - The function type information.
|
||||
/// \param CalleeInfo - The callee information these attributes are being
|
||||
/// constructed for. If valid, the attributes applied to this decl may
|
||||
/// contribute to the function attributes and calling convention.
|
||||
/// \param PAL [out] - On return, the attribute list to use.
|
||||
/// \param CallingConv [out] - On return, the LLVM calling convention to use.
|
||||
void ConstructAttributeList(const CGFunctionInfo &Info,
|
||||
void ConstructAttributeList(StringRef Name, const CGFunctionInfo &Info,
|
||||
CGCalleeInfo CalleeInfo, AttributeListType &PAL,
|
||||
unsigned &CallingConv, bool AttrOnCallSite);
|
||||
|
||||
|
@ -4740,11 +4740,33 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
A->render(Args, CmdArgs);
|
||||
}
|
||||
|
||||
// -fbuiltin is default unless -mkernel is used
|
||||
if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin,
|
||||
!Args.hasArg(options::OPT_mkernel)))
|
||||
// -fbuiltin is default unless -mkernel is used.
|
||||
bool UseBuiltins =
|
||||
Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin,
|
||||
!Args.hasArg(options::OPT_mkernel));
|
||||
if (!UseBuiltins)
|
||||
CmdArgs.push_back("-fno-builtin");
|
||||
|
||||
// -ffreestanding implies -fno-builtin.
|
||||
if (Args.hasArg(options::OPT_ffreestanding))
|
||||
UseBuiltins = false;
|
||||
|
||||
// Process the -fno-builtin-* options.
|
||||
for (const auto &Arg : Args) {
|
||||
const Option &O = Arg->getOption();
|
||||
if (!O.matches(options::OPT_fno_builtin_))
|
||||
continue;
|
||||
|
||||
Arg->claim();
|
||||
// If -fno-builtin is specified, then there's no need to pass the option to
|
||||
// the frontend.
|
||||
if (!UseBuiltins)
|
||||
continue;
|
||||
|
||||
StringRef FuncName = Arg->getValue();
|
||||
CmdArgs.push_back(Args.MakeArgString("-fno-builtin-" + FuncName));
|
||||
}
|
||||
|
||||
if (!Args.hasFlag(options::OPT_fassume_sane_operator_new,
|
||||
options::OPT_fno_assume_sane_operator_new))
|
||||
CmdArgs.push_back("-fno-assume-sane-operator-new");
|
||||
|
@ -21,4 +21,12 @@ CodeGenOptions::CodeGenOptions() {
|
||||
memcpy(CoverageVersion, "402*", 4);
|
||||
}
|
||||
|
||||
bool CodeGenOptions::isNoBuiltinFunc(const char *Name) const {
|
||||
StringRef FuncName(Name);
|
||||
for (unsigned i = 0, e = NoBuiltinFuncs.size(); i != e; ++i)
|
||||
if (FuncName.equals(NoBuiltinFuncs[i]))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
@ -8,13 +8,14 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "TestModuleFileExtension.h"
|
||||
#include "clang/Frontend/CompilerInvocation.h"
|
||||
#include "clang/Basic/Builtins.h"
|
||||
#include "clang/Basic/FileManager.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
#include "clang/Config/config.h"
|
||||
#include "clang/Driver/DriverDiagnostic.h"
|
||||
#include "clang/Driver/Options.h"
|
||||
#include "clang/Driver/Util.h"
|
||||
#include "clang/Frontend/CompilerInvocation.h"
|
||||
#include "clang/Frontend/FrontendDiagnostic.h"
|
||||
#include "clang/Frontend/LangStandard.h"
|
||||
#include "clang/Frontend/Utils.h"
|
||||
@ -135,6 +136,20 @@ static void addDiagnosticArgs(ArgList &Args, OptSpecifier Group,
|
||||
}
|
||||
}
|
||||
|
||||
static void getAllNoBuiltinFuncValues(ArgList &Args,
|
||||
std::vector<std::string> &Funcs) {
|
||||
SmallVector<const char *, 8> Values;
|
||||
for (const auto &Arg : Args) {
|
||||
const Option &O = Arg->getOption();
|
||||
if (O.matches(options::OPT_fno_builtin_)) {
|
||||
const char *FuncName = Arg->getValue();
|
||||
if (Builtin::Context::isBuiltinFunc(FuncName))
|
||||
Values.push_back(FuncName);
|
||||
}
|
||||
}
|
||||
Funcs.insert(Funcs.end(), Values.begin(), Values.end());
|
||||
}
|
||||
|
||||
static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
|
||||
DiagnosticsEngine &Diags) {
|
||||
using namespace options;
|
||||
@ -452,6 +467,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK,
|
||||
Opts.OptimizeSize = getOptimizationLevelSize(Args);
|
||||
Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
|
||||
Args.hasArg(OPT_ffreestanding));
|
||||
if (Opts.SimplifyLibCalls)
|
||||
getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
|
||||
Opts.UnrollLoops =
|
||||
Args.hasFlag(OPT_funroll_loops, OPT_fno_unroll_loops,
|
||||
(Opts.OptimizationLevel > 1 && !Opts.OptimizeSize));
|
||||
@ -1669,6 +1686,8 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
|
||||
Opts.ShortEnums = Args.hasArg(OPT_fshort_enums);
|
||||
Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
|
||||
Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
|
||||
if (!Opts.NoBuiltin)
|
||||
getAllNoBuiltinFuncValues(Args, Opts.NoBuiltinFuncs);
|
||||
Opts.NoMathBuiltin = Args.hasArg(OPT_fno_math_builtin);
|
||||
Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
|
||||
Opts.SizedDeallocation = Args.hasArg(OPT_fsized_deallocation);
|
||||
|
@ -1,4 +1,5 @@
|
||||
// RUN: %clang_cc1 -emit-llvm %s -O2 -fno-builtin -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -emit-llvm %s -O2 -fno-builtin-printf -o - | FileCheck %s
|
||||
// Check that -fno-builtin is honored.
|
||||
|
||||
extern int printf(const char*, ...);
|
||||
|
@ -1,4 +1,7 @@
|
||||
// RUN: %clang_cc1 -fno-builtin -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-YES %s
|
||||
// RUN: %clang_cc1 -fno-builtin-crealf -fno-builtin-creal -fno-builtin-creall \
|
||||
// RUN: -fno-builtin-cimagf -fno-builtin-cimag -fno-builtin-cimagl -emit-llvm \
|
||||
// RUN: -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-YES %s
|
||||
// RUN: %clang_cc1 -emit-llvm -o - %s -triple i386-unknown-unknown | FileCheck -check-prefix CHECK-NO %s
|
||||
|
||||
extern float crealf(float _Complex);
|
||||
|
@ -1,4 +1,11 @@
|
||||
// RUN: %clang_cc1 -S -O3 -fno-builtin -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -S -O3 -fno-builtin-ceil -fno-builtin-copysign -fno-builtin-cos \
|
||||
// RUN: -fno-builtin-fabs -fno-builtin-floor -fno-builtin-strcat -fno-builtin-strncat \
|
||||
// RUN: -fno-builtin-strchr -fno-builtin-strrchr -fno-builtin-strcmp -fno-builtin-strncmp \
|
||||
// RUN: -fno-builtin-strcpy -fno-builtin-stpcpy -fno-builtin-strncpy -fno-builtin-strlen \
|
||||
// RUN: -fno-builtin-strpbrk -fno-builtin-strspn -fno-builtin-strtod -fno-builtin-strtof \
|
||||
// RUN: -fno-builtin-strtold -fno-builtin-strtol -fno-builtin-strtoll -fno-builtin-strtoul \
|
||||
// RUN: -fno-builtin-strtoull -o - %s | FileCheck %s
|
||||
// rdar://10551066
|
||||
|
||||
typedef __SIZE_TYPE__ size_t;
|
||||
|
@ -1,4 +1,5 @@
|
||||
// RUN: %clang_cc1 -fno-builtin -O1 -S -o - %s | FileCheck %s
|
||||
// RUN: %clang_cc1 -fno-builtin-memset -O1 -S -o - %s | FileCheck -check-prefix=MEMSET %s
|
||||
|
||||
void PR13497() {
|
||||
char content[2];
|
||||
@ -6,3 +7,11 @@ void PR13497() {
|
||||
// CHECK: __strcpy_chk
|
||||
__builtin___strcpy_chk(content, "", 1);
|
||||
}
|
||||
|
||||
void PR4941(char *s) {
|
||||
// Make sure we don't optimize this loop to a memset().
|
||||
// MEMSET-LABEL: PR4941:
|
||||
// MEMSET-NOT: memset
|
||||
for (unsigned i = 0; i < 8192; ++i)
|
||||
s[i] = 0;
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -ffreestanding %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -fno-builtin %s
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify -fno-builtin-malloc %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
int malloc(int a) { return a; }
|
||||
|
Loading…
x
Reference in New Issue
Block a user