mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-25 21:11:25 +00:00
[Flang][Clang] Add support for frame pointers in Flang
This commit is contained in:
parent
7832a8582a
commit
ea4eb691f4
@ -3172,7 +3172,8 @@ def fno_ms_compatibility : Flag<["-"], "fno-ms-compatibility">, Group<f_Group>,
|
||||
def fno_objc_legacy_dispatch : Flag<["-"], "fno-objc-legacy-dispatch">, Group<f_Group>;
|
||||
def fno_objc_weak : Flag<["-"], "fno-objc-weak">, Group<f_Group>,
|
||||
Visibility<[ClangOption, CC1Option]>;
|
||||
def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group<f_Group>;
|
||||
def fno_omit_frame_pointer : Flag<["-"], "fno-omit-frame-pointer">, Group<f_Group>,
|
||||
Visibility<[ClangOption, FlangOption]>;
|
||||
defm operator_names : BoolFOption<"operator-names",
|
||||
LangOpts<"CXXOperatorNames">, Default<cplusplus.KeyPath>,
|
||||
NegFlag<SetFalse, [], [ClangOption, CC1Option],
|
||||
@ -3298,6 +3299,7 @@ defm objc_avoid_heapify_local_blocks : BoolFOption<"objc-avoid-heapify-local-blo
|
||||
BothFlags<[], [CC1Option], " to avoid heapifying local blocks">>;
|
||||
|
||||
def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>,
|
||||
Visibility<[ClangOption, FlangOption]>,
|
||||
HelpText<"Omit the frame pointer from functions that don't need it. "
|
||||
"Some stack unwinding cases, such as profilers and sanitizers, may prefer specifying -fno-omit-frame-pointer. "
|
||||
"On many targets, -O1 and higher omit the frame pointer by default. "
|
||||
@ -6786,10 +6788,6 @@ def new_struct_path_tbaa : Flag<["-"], "new-struct-path-tbaa">,
|
||||
def mdebug_pass : Separate<["-"], "mdebug-pass">,
|
||||
HelpText<"Enable additional debug output">,
|
||||
MarshallingInfoString<CodeGenOpts<"DebugPass">>;
|
||||
def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">,
|
||||
HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,none">,
|
||||
NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "None"]>,
|
||||
MarshallingInfoEnum<CodeGenOpts<"FramePointer">, "None">;
|
||||
def mabi_EQ_ieeelongdouble : Flag<["-"], "mabi=ieeelongdouble">,
|
||||
HelpText<"Use IEEE 754 quadruple-precision for long double">,
|
||||
MarshallingInfoFlag<LangOpts<"PPCIEEELongDouble">>;
|
||||
@ -7400,6 +7398,11 @@ def pic_is_pie : Flag<["-"], "pic-is-pie">,
|
||||
HelpText<"File is for a position independent executable">,
|
||||
MarshallingInfoFlag<LangOpts<"PIE">>;
|
||||
|
||||
def mframe_pointer_EQ : Joined<["-"], "mframe-pointer=">,
|
||||
HelpText<"Specify which frame pointers to retain.">, Values<"all,non-leaf,none">,
|
||||
NormalizedValuesScope<"CodeGenOptions::FramePointerKind">, NormalizedValues<["All", "NonLeaf", "None"]>,
|
||||
MarshallingInfoEnum<CodeGenOpts<"FramePointer">, "None">;
|
||||
|
||||
|
||||
def dependent_lib : Joined<["--"], "dependent-lib=">,
|
||||
HelpText<"Add dependent library">,
|
||||
|
@ -409,139 +409,6 @@ static bool ShouldEnableAutolink(const ArgList &Args, const ToolChain &TC,
|
||||
Default);
|
||||
}
|
||||
|
||||
static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
|
||||
switch (Triple.getArch()){
|
||||
default:
|
||||
return false;
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::thumb:
|
||||
// ARM Darwin targets require a frame pointer to be always present to aid
|
||||
// offline debugging via backtraces.
|
||||
return Triple.isOSDarwin();
|
||||
}
|
||||
}
|
||||
|
||||
static bool useFramePointerForTargetByDefault(const ArgList &Args,
|
||||
const llvm::Triple &Triple) {
|
||||
if (Args.hasArg(options::OPT_pg) && !Args.hasArg(options::OPT_mfentry))
|
||||
return true;
|
||||
|
||||
if (Triple.isAndroid()) {
|
||||
switch (Triple.getArch()) {
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::armeb:
|
||||
case llvm::Triple::thumb:
|
||||
case llvm::Triple::thumbeb:
|
||||
case llvm::Triple::riscv64:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Triple.getArch()) {
|
||||
case llvm::Triple::xcore:
|
||||
case llvm::Triple::wasm32:
|
||||
case llvm::Triple::wasm64:
|
||||
case llvm::Triple::msp430:
|
||||
// XCore never wants frame pointers, regardless of OS.
|
||||
// WebAssembly never wants frame pointers.
|
||||
return false;
|
||||
case llvm::Triple::ppc:
|
||||
case llvm::Triple::ppcle:
|
||||
case llvm::Triple::ppc64:
|
||||
case llvm::Triple::ppc64le:
|
||||
case llvm::Triple::riscv32:
|
||||
case llvm::Triple::riscv64:
|
||||
case llvm::Triple::sparc:
|
||||
case llvm::Triple::sparcel:
|
||||
case llvm::Triple::sparcv9:
|
||||
case llvm::Triple::amdgcn:
|
||||
case llvm::Triple::r600:
|
||||
case llvm::Triple::csky:
|
||||
case llvm::Triple::loongarch32:
|
||||
case llvm::Triple::loongarch64:
|
||||
return !areOptimizationsEnabled(Args);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Triple.isOSFuchsia() || Triple.isOSNetBSD()) {
|
||||
return !areOptimizationsEnabled(Args);
|
||||
}
|
||||
|
||||
if (Triple.isOSLinux() || Triple.isOSHurd()) {
|
||||
switch (Triple.getArch()) {
|
||||
// Don't use a frame pointer on linux if optimizing for certain targets.
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::armeb:
|
||||
case llvm::Triple::thumb:
|
||||
case llvm::Triple::thumbeb:
|
||||
case llvm::Triple::mips64:
|
||||
case llvm::Triple::mips64el:
|
||||
case llvm::Triple::mips:
|
||||
case llvm::Triple::mipsel:
|
||||
case llvm::Triple::systemz:
|
||||
case llvm::Triple::x86:
|
||||
case llvm::Triple::x86_64:
|
||||
return !areOptimizationsEnabled(Args);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Triple.isOSWindows()) {
|
||||
switch (Triple.getArch()) {
|
||||
case llvm::Triple::x86:
|
||||
return !areOptimizationsEnabled(Args);
|
||||
case llvm::Triple::x86_64:
|
||||
return Triple.isOSBinFormatMachO();
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::thumb:
|
||||
// Windows on ARM builds with FPO disabled to aid fast stack walking
|
||||
return true;
|
||||
default:
|
||||
// All other supported Windows ISAs use xdata unwind information, so frame
|
||||
// pointers are not generally useful.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static CodeGenOptions::FramePointerKind
|
||||
getFramePointerKind(const ArgList &Args, const llvm::Triple &Triple) {
|
||||
// We have 4 states:
|
||||
//
|
||||
// 00) leaf retained, non-leaf retained
|
||||
// 01) leaf retained, non-leaf omitted (this is invalid)
|
||||
// 10) leaf omitted, non-leaf retained
|
||||
// (what -momit-leaf-frame-pointer was designed for)
|
||||
// 11) leaf omitted, non-leaf omitted
|
||||
//
|
||||
// "omit" options taking precedence over "no-omit" options is the only way
|
||||
// to make 3 valid states representable
|
||||
Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer,
|
||||
options::OPT_fno_omit_frame_pointer);
|
||||
bool OmitFP = A && A->getOption().matches(options::OPT_fomit_frame_pointer);
|
||||
bool NoOmitFP =
|
||||
A && A->getOption().matches(options::OPT_fno_omit_frame_pointer);
|
||||
bool OmitLeafFP =
|
||||
Args.hasFlag(options::OPT_momit_leaf_frame_pointer,
|
||||
options::OPT_mno_omit_leaf_frame_pointer,
|
||||
Triple.isAArch64() || Triple.isPS() || Triple.isVE() ||
|
||||
(Triple.isAndroid() && Triple.isRISCV64()));
|
||||
if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
|
||||
(!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
|
||||
if (OmitLeafFP)
|
||||
return CodeGenOptions::FramePointerKind::NonLeaf;
|
||||
return CodeGenOptions::FramePointerKind::All;
|
||||
}
|
||||
return CodeGenOptions::FramePointerKind::None;
|
||||
}
|
||||
|
||||
/// Add a CC1 option to specify the debug compilation directory.
|
||||
static const char *addDebugCompDirArg(const ArgList &Args,
|
||||
ArgStringList &CmdArgs,
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "MSP430.h"
|
||||
#include "Solaris.h"
|
||||
#include "clang/Basic/CharInfo.h"
|
||||
#include "clang/Basic/CodeGenOptions.h"
|
||||
#include "clang/Basic/LangOptions.h"
|
||||
#include "clang/Basic/ObjCRuntime.h"
|
||||
#include "clang/Basic/Version.h"
|
||||
@ -71,6 +72,144 @@ using namespace clang::driver::tools;
|
||||
using namespace clang;
|
||||
using namespace llvm::opt;
|
||||
|
||||
static bool useFramePointerForTargetByDefault(const llvm::opt::ArgList &Args,
|
||||
const llvm::Triple &Triple) {
|
||||
if (Args.hasArg(clang::driver::options::OPT_pg) &&
|
||||
!Args.hasArg(clang::driver::options::OPT_mfentry))
|
||||
return true;
|
||||
|
||||
if (Triple.isAndroid()) {
|
||||
switch (Triple.getArch()) {
|
||||
case llvm::Triple::aarch64:
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::armeb:
|
||||
case llvm::Triple::thumb:
|
||||
case llvm::Triple::thumbeb:
|
||||
case llvm::Triple::riscv64:
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Triple.getArch()) {
|
||||
case llvm::Triple::xcore:
|
||||
case llvm::Triple::wasm32:
|
||||
case llvm::Triple::wasm64:
|
||||
case llvm::Triple::msp430:
|
||||
// XCore never wants frame pointers, regardless of OS.
|
||||
// WebAssembly never wants frame pointers.
|
||||
return false;
|
||||
case llvm::Triple::ppc:
|
||||
case llvm::Triple::ppcle:
|
||||
case llvm::Triple::ppc64:
|
||||
case llvm::Triple::ppc64le:
|
||||
case llvm::Triple::riscv32:
|
||||
case llvm::Triple::riscv64:
|
||||
case llvm::Triple::sparc:
|
||||
case llvm::Triple::sparcel:
|
||||
case llvm::Triple::sparcv9:
|
||||
case llvm::Triple::amdgcn:
|
||||
case llvm::Triple::r600:
|
||||
case llvm::Triple::csky:
|
||||
case llvm::Triple::loongarch32:
|
||||
case llvm::Triple::loongarch64:
|
||||
return !clang::driver::tools::areOptimizationsEnabled(Args);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (Triple.isOSFuchsia() || Triple.isOSNetBSD()) {
|
||||
return !clang::driver::tools::areOptimizationsEnabled(Args);
|
||||
}
|
||||
|
||||
if (Triple.isOSLinux() || Triple.isOSHurd()) {
|
||||
switch (Triple.getArch()) {
|
||||
// Don't use a frame pointer on linux if optimizing for certain targets.
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::armeb:
|
||||
case llvm::Triple::thumb:
|
||||
case llvm::Triple::thumbeb:
|
||||
case llvm::Triple::mips64:
|
||||
case llvm::Triple::mips64el:
|
||||
case llvm::Triple::mips:
|
||||
case llvm::Triple::mipsel:
|
||||
case llvm::Triple::systemz:
|
||||
case llvm::Triple::x86:
|
||||
case llvm::Triple::x86_64:
|
||||
return !clang::driver::tools::areOptimizationsEnabled(Args);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (Triple.isOSWindows()) {
|
||||
switch (Triple.getArch()) {
|
||||
case llvm::Triple::x86:
|
||||
return !clang::driver::tools::areOptimizationsEnabled(Args);
|
||||
case llvm::Triple::x86_64:
|
||||
return Triple.isOSBinFormatMachO();
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::thumb:
|
||||
// Windows on ARM builds with FPO disabled to aid fast stack walking
|
||||
return true;
|
||||
default:
|
||||
// All other supported Windows ISAs use xdata unwind information, so frame
|
||||
// pointers are not generally useful.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mustUseNonLeafFramePointerForTarget(const llvm::Triple &Triple) {
|
||||
switch (Triple.getArch()) {
|
||||
default:
|
||||
return false;
|
||||
case llvm::Triple::arm:
|
||||
case llvm::Triple::thumb:
|
||||
// ARM Darwin targets require a frame pointer to be always present to aid
|
||||
// offline debugging via backtraces.
|
||||
return Triple.isOSDarwin();
|
||||
}
|
||||
}
|
||||
|
||||
clang::CodeGenOptions::FramePointerKind
|
||||
getFramePointerKind(const llvm::opt::ArgList &Args,
|
||||
const llvm::Triple &Triple) {
|
||||
// We have 4 states:
|
||||
//
|
||||
// 00) leaf retained, non-leaf retained
|
||||
// 01) leaf retained, non-leaf omitted (this is invalid)
|
||||
// 10) leaf omitted, non-leaf retained
|
||||
// (what -momit-leaf-frame-pointer was designed for)
|
||||
// 11) leaf omitted, non-leaf omitted
|
||||
//
|
||||
// "omit" options taking precedence over "no-omit" options is the only way
|
||||
// to make 3 valid states representable
|
||||
llvm::opt::Arg *A =
|
||||
Args.getLastArg(clang::driver::options::OPT_fomit_frame_pointer,
|
||||
clang::driver::options::OPT_fno_omit_frame_pointer);
|
||||
|
||||
bool OmitFP = A && A->getOption().matches(
|
||||
clang::driver::options::OPT_fomit_frame_pointer);
|
||||
bool NoOmitFP = A && A->getOption().matches(
|
||||
clang::driver::options::OPT_fno_omit_frame_pointer);
|
||||
bool OmitLeafFP =
|
||||
Args.hasFlag(clang::driver::options::OPT_momit_leaf_frame_pointer,
|
||||
clang::driver::options::OPT_mno_omit_leaf_frame_pointer,
|
||||
Triple.isAArch64() || Triple.isPS() || Triple.isVE() ||
|
||||
(Triple.isAndroid() && Triple.isRISCV64()));
|
||||
if (NoOmitFP || mustUseNonLeafFramePointerForTarget(Triple) ||
|
||||
(!OmitFP && useFramePointerForTargetByDefault(Args, Triple))) {
|
||||
if (OmitLeafFP)
|
||||
return clang::CodeGenOptions::FramePointerKind::NonLeaf;
|
||||
return clang::CodeGenOptions::FramePointerKind::All;
|
||||
}
|
||||
return clang::CodeGenOptions::FramePointerKind::None;
|
||||
}
|
||||
|
||||
static void renderRpassOptions(const ArgList &Args, ArgStringList &CmdArgs,
|
||||
const StringRef PluginOptPrefix) {
|
||||
if (const Arg *A = Args.getLastArg(options::OPT_Rpass_EQ))
|
||||
|
@ -9,6 +9,7 @@
|
||||
#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_COMMONARGS_H
|
||||
#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_COMMONARGS_H
|
||||
|
||||
#include "clang/Basic/CodeGenOptions.h"
|
||||
#include "clang/Driver/Driver.h"
|
||||
#include "clang/Driver/InputInfo.h"
|
||||
#include "clang/Driver/Multilib.h"
|
||||
@ -215,4 +216,7 @@ void addOpenMPDeviceRTL(const Driver &D, const llvm::opt::ArgList &DriverArgs,
|
||||
} // end namespace driver
|
||||
} // end namespace clang
|
||||
|
||||
clang::CodeGenOptions::FramePointerKind
|
||||
getFramePointerKind(const llvm::opt::ArgList &Args, const llvm::Triple &Triple);
|
||||
|
||||
#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_COMMONARGS_H
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include "Flang.h"
|
||||
#include "CommonArgs.h"
|
||||
|
||||
#include "clang/Basic/CodeGenOptions.h"
|
||||
#include "clang/Driver/Options.h"
|
||||
#include "llvm/Frontend/Debug/Options.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
@ -674,6 +675,24 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
|
||||
// Forward -Xflang arguments to -fc1
|
||||
Args.AddAllArgValues(CmdArgs, options::OPT_Xflang);
|
||||
|
||||
CodeGenOptions::FramePointerKind FPKeepKind =
|
||||
getFramePointerKind(Args, Triple);
|
||||
|
||||
const char *FPKeepKindStr = nullptr;
|
||||
switch (FPKeepKind) {
|
||||
case CodeGenOptions::FramePointerKind::None:
|
||||
FPKeepKindStr = "-mframe-pointer=none";
|
||||
break;
|
||||
case CodeGenOptions::FramePointerKind::NonLeaf:
|
||||
FPKeepKindStr = "-mframe-pointer=non-leaf";
|
||||
break;
|
||||
case CodeGenOptions::FramePointerKind::All:
|
||||
FPKeepKindStr = "-mframe-pointer=all";
|
||||
break;
|
||||
}
|
||||
assert(FPKeepKindStr && "unknown FramePointerKind");
|
||||
CmdArgs.push_back(FPKeepKindStr);
|
||||
|
||||
// Forward -mllvm options to the LLVM option parser. In practice, this means
|
||||
// forwarding to `-fc1` as that's where the LLVM parser is run.
|
||||
for (const Arg *A : Args.filtered(options::OPT_mllvm)) {
|
||||
|
@ -74,6 +74,7 @@
|
||||
! CHECK-NEXT: -fno-stack-arrays Allocate array temporaries on the heap (default)
|
||||
! CHECK-NEXT: -fno-version-loops-for-stride
|
||||
! CHECK-NEXT: Do not create unit-strided loops (default)
|
||||
! CHECK-NEXT: -fomit-frame-pointer Omit the frame pointer from functions that don't need it. Some stack unwinding cases, such as profilers and sanitizers, may prefer specifying -fno-omit-frame-pointer. On many targets, -O1 and higher omit the frame pointer by default. -m[no-]omit-leaf-frame-pointer takes precedence for leaf functions
|
||||
! CHECK-NEXT: -fopenacc Enable OpenACC
|
||||
! CHECK-NEXT: -fopenmp-assume-no-nested-parallelism
|
||||
! CHECK-NEXT: Assert no nested parallel regions in the GPU
|
||||
|
@ -64,6 +64,7 @@
|
||||
! HELP-NEXT: -fno-stack-arrays Allocate array temporaries on the heap (default)
|
||||
! HELP-NEXT: -fno-version-loops-for-stride
|
||||
! HELP-NEXT: Do not create unit-strided loops (default)
|
||||
! HELP-NEXT: -fomit-frame-pointer Omit the frame pointer from functions that don't need it. Some stack unwinding cases, such as profilers and sanitizers, may prefer specifying -fno-omit-frame-pointer. On many targets, -O1 and higher omit the frame pointer by default. -m[no-]omit-leaf-frame-pointer takes precedence for leaf functions
|
||||
! HELP-NEXT: -fopenacc Enable OpenACC
|
||||
! HELP-NEXT: -fopenmp-target-debug Enable debugging in the OpenMP offloading device RTL
|
||||
! HELP-NEXT: -fopenmp-targets=<value>
|
||||
@ -238,6 +239,7 @@
|
||||
! HELP-FC1-NEXT: Specify code object ABI version. Defaults to 4. (AMDGPU only)
|
||||
! HELP-FC1-NEXT: -menable-no-infs Allow optimization to assume there are no infinities.
|
||||
! HELP-FC1-NEXT: -menable-no-nans Allow optimization to assume there are no NaNs.
|
||||
! HELP-FC1-NEXT: -mframe-pointer=<value> Specify which frame pointers to retain.
|
||||
! HELP-FC1-NEXT: -mllvm <value> Additional arguments to forward to LLVM's option processing
|
||||
! HELP-FC1-NEXT: -mmlir <value> Additional arguments to forward to MLIR's option processing
|
||||
! HELP-FC1-NEXT: -module-dir <dir> Put MODULE files in <dir>
|
||||
|
9
flang/test/Driver/frame-pointer-forwarding.f90
Normal file
9
flang/test/Driver/frame-pointer-forwarding.f90
Normal file
@ -0,0 +1,9 @@
|
||||
! Test that flang-new forwards -fno-omit-frame-pointer and -fomit-frame-pointer Flang frontend
|
||||
! RUN: %flang -fno-omit-frame-pointer --target=x86-none-none -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s
|
||||
! CHECK: "-mframe-pointer=all"
|
||||
|
||||
! RUN: %flang -fno-omit-frame-pointer --target=aarch64-none-none -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-NONLEAFFP
|
||||
! CHECK-NONLEAFFP: "-mframe-pointer=non-leaf"
|
||||
|
||||
! RUN: %flang -fomit-frame-pointer --target=aarch64-none-none -fsyntax-only -### %s -o %t 2>&1 | FileCheck %s --check-prefix=CHECK-NONEFP
|
||||
! CHECK-NONEFP: "-mframe-pointer=none"
|
@ -14,6 +14,7 @@
|
||||
! RUN: -fno-signed-zeros \
|
||||
! RUN: -fassociative-math \
|
||||
! RUN: -freciprocal-math \
|
||||
! RUN: -fomit-frame-pointer \
|
||||
! RUN: -fpass-plugin=Bye%pluginext \
|
||||
! RUN: -fversion-loops-for-stride \
|
||||
! RUN: -flang-experimental-polymorphism \
|
||||
@ -60,5 +61,6 @@
|
||||
! CHECK: "-Reverything"
|
||||
! CHECK: "-Rno-everything"
|
||||
! CHECK: "-Rpass=inline"
|
||||
! CHECK: "-mframe-pointer=none"
|
||||
! CHECK: "-mllvm" "-print-before-all"
|
||||
! CHECK: "-save-temps=obj"
|
||||
|
Loading…
x
Reference in New Issue
Block a user