forked from OSchip/llvm-project
Support GCC's -fstack-usage flag
This patch adds support for GCC's -fstack-usage flag. With this flag, a stack usage file (i.e., .su file) is generated for each input source file. The format of the stack usage file is also similar to what is used by GCC. For each function defined in the source file, a line with the following information is produced in the .su file. <source_file>:<line_number>:<function_name> <size_in_byte> <static/dynamic> "Static" means that the function's frame size is static and the size info is an accurate reflection of the frame size. While "dynamic" means the function's frame size can only be determined at run-time because the function manipulates the stack dynamically (e.g., due to variable size objects). The size info only reflects the size of the fixed size frame objects in this case and therefore is not a reliable measure of the total frame size. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D100509
This commit is contained in:
parent
c012a388a1
commit
c9b36a041f
|
@ -70,6 +70,10 @@ New Compiler Flags
|
|||
- ``-Wreserved-identifier`` emits warning when user code uses reserved
|
||||
identifiers.
|
||||
|
||||
- ``-fstack-usage`` generates an extra .su file per input source file. The .su
|
||||
file contains frame size information for each function defined in the source
|
||||
file.
|
||||
|
||||
Deprecated Compiler Flags
|
||||
-------------------------
|
||||
|
||||
|
|
|
@ -372,6 +372,11 @@ public:
|
|||
/// coverage pass should actually not be instrumented.
|
||||
std::vector<std::string> SanitizeCoverageIgnorelistFiles;
|
||||
|
||||
/// Name of the stack usage file (i.e., .su file) if user passes
|
||||
/// -fstack-usage. If empty, it can be implied that -fstack-usage is not
|
||||
/// passed on the command line.
|
||||
std::string StackUsageOutput;
|
||||
|
||||
/// Executable and command-line used to create a given CompilerInvocation.
|
||||
/// Most of the time this will be the full -cc1 command.
|
||||
const char *Argv0 = nullptr;
|
||||
|
|
|
@ -2709,6 +2709,12 @@ defm stack_size_section : BoolFOption<"stack-size-section",
|
|||
CodeGenOpts<"StackSizeSection">, DefaultFalse,
|
||||
PosFlag<SetTrue, [CC1Option], "Emit section containing metadata on function stack sizes">,
|
||||
NegFlag<SetFalse>>;
|
||||
def fstack_usage : Flag<["-"], "fstack-usage">, Group<f_Group>,
|
||||
HelpText<"Emit .su file containing information on function stack sizes">;
|
||||
def stack_usage_file : Separate<["-"], "stack-usage-file">,
|
||||
Flags<[CC1Option, NoDriverOption]>,
|
||||
HelpText<"Filename (or -) to write stack usage output to">,
|
||||
MarshallingInfoString<CodeGenOpts<"StackUsageOutput">>;
|
||||
|
||||
defm unique_basic_block_section_names : BoolFOption<"unique-basic-block-section-names",
|
||||
CodeGenOpts<"UniqueBasicBlockSectionNames">, DefaultFalse,
|
||||
|
|
|
@ -567,6 +567,7 @@ static bool initTargetOptions(DiagnosticsEngine &Diags,
|
|||
Options.ExplicitEmulatedTLS = CodeGenOpts.ExplicitEmulatedTLS;
|
||||
Options.DebuggerTuning = CodeGenOpts.getDebuggerTuning();
|
||||
Options.EmitStackSizeSection = CodeGenOpts.StackSizeSection;
|
||||
Options.StackUsageOutput = CodeGenOpts.StackUsageOutput;
|
||||
Options.EmitAddrsig = CodeGenOpts.Addrsig;
|
||||
Options.ForceDwarfFrameSection = CodeGenOpts.ForceDwarfFrameSection;
|
||||
Options.EmitCallSiteInfo = CodeGenOpts.EmitCallSiteInfo;
|
||||
|
|
|
@ -5492,6 +5492,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
options::OPT_fno_stack_size_section, RawTriple.isPS4()))
|
||||
CmdArgs.push_back("-fstack-size-section");
|
||||
|
||||
if (Args.hasArg(options::OPT_fstack_usage)) {
|
||||
CmdArgs.push_back("-stack-usage-file");
|
||||
|
||||
if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) {
|
||||
SmallString<128> OutputFilename(OutputOpt->getValue());
|
||||
llvm::sys::path::replace_extension(OutputFilename, "su");
|
||||
CmdArgs.push_back(Args.MakeArgString(OutputFilename));
|
||||
} else
|
||||
CmdArgs.push_back(
|
||||
Args.MakeArgString(Twine(getBaseInputStem(Args, Inputs)) + ".su"));
|
||||
}
|
||||
|
||||
CmdArgs.push_back("-ferror-limit");
|
||||
if (Arg *A = Args.getLastArg(options::OPT_ferror_limit_EQ))
|
||||
CmdArgs.push_back(A->getValue());
|
||||
|
|
|
@ -1931,6 +1931,9 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
|
|||
if (UsingSampleProfile)
|
||||
NeedLocTracking = true;
|
||||
|
||||
if (!Opts.StackUsageOutput.empty())
|
||||
NeedLocTracking = true;
|
||||
|
||||
// If the user requested a flag that requires source locations available in
|
||||
// the backend, make sure that the backend tracks source location information.
|
||||
if (NeedLocTracking && Opts.getDebugInfo() == codegenoptions::NoDebugInfo)
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
// REQUIRES: aarch64-registered-target
|
||||
|
||||
// RUN: rm -rf %t && mkdir %t && cd %t
|
||||
// RUN: %clang_cc1 -triple aarch64-unknown -stack-usage-file b.su -emit-obj %s -o b.o
|
||||
// RUN: FileCheck %s < b.su
|
||||
|
||||
// CHECK: stack-usage.c:[[#@LINE+1]]:foo {{[0-9]+}} static
|
||||
int foo() {
|
||||
char a[8];
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// CHECK: stack-usage.c:[[#@LINE+1]]:bar {{[0-9]+}} dynamic
|
||||
int bar(int len) {
|
||||
char a[len];
|
||||
|
||||
return 1;
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
// RUN: %clang -target aarch64-unknown %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-ABSENT
|
||||
// CHECK-ABSENT-NOT: "-stack-usage-file"
|
||||
|
||||
// RUN: %clang -target aarch64-unknown -fstack-usage %s -### 2>&1 | FileCheck %s --check-prefix=CHECK-PRESENT
|
||||
// CHECK-PRESENT: "-stack-usage-file"
|
||||
|
||||
int foo() { return 42; }
|
|
@ -182,6 +182,9 @@ private:
|
|||
/// Emit comments in assembly output if this is true.
|
||||
bool VerboseAsm;
|
||||
|
||||
/// Output stream for the stack usage file (i.e., .su file).
|
||||
std::unique_ptr<raw_fd_ostream> StackUsageStream;
|
||||
|
||||
static char ID;
|
||||
|
||||
protected:
|
||||
|
@ -358,6 +361,8 @@ public:
|
|||
|
||||
void emitStackSizeSection(const MachineFunction &MF);
|
||||
|
||||
void emitStackUsage(const MachineFunction &MF);
|
||||
|
||||
void emitBBAddrMapSection(const MachineFunction &MF);
|
||||
|
||||
void emitPseudoProbe(const MachineInstr &MI);
|
||||
|
|
|
@ -342,6 +342,11 @@ namespace llvm {
|
|||
/// Stack protector guard reg to use, e.g. usually fs or gs in X86.
|
||||
std::string StackProtectorGuardReg = "None";
|
||||
|
||||
/// Name of the stack usage file (i.e., .su file) if user passes
|
||||
/// -fstack-usage. If empty, it can be implied that -fstack-usage is not
|
||||
/// passed on the command line.
|
||||
std::string StackUsageOutput;
|
||||
|
||||
/// FloatABIType - This setting is set by -float-abi=xxx option is specfied
|
||||
/// on the command line. This setting may either be Default, Soft, or Hard.
|
||||
/// Default selects the target's default behavior. Soft selects the ABI for
|
||||
|
|
|
@ -1185,6 +1185,37 @@ void AsmPrinter::emitStackSizeSection(const MachineFunction &MF) {
|
|||
OutStreamer->PopSection();
|
||||
}
|
||||
|
||||
void AsmPrinter::emitStackUsage(const MachineFunction &MF) {
|
||||
const std::string &OutputFilename = MF.getTarget().Options.StackUsageOutput;
|
||||
|
||||
// OutputFilename empty implies -fstack-usage is not passed.
|
||||
if (OutputFilename.empty())
|
||||
return;
|
||||
|
||||
const MachineFrameInfo &FrameInfo = MF.getFrameInfo();
|
||||
uint64_t StackSize = FrameInfo.getStackSize();
|
||||
|
||||
if (StackUsageStream == nullptr) {
|
||||
std::error_code EC;
|
||||
StackUsageStream =
|
||||
std::make_unique<raw_fd_ostream>(OutputFilename, EC, sys::fs::OF_Text);
|
||||
if (EC) {
|
||||
errs() << "Could not open file: " << EC.message();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
*StackUsageStream << MF.getFunction().getParent()->getName();
|
||||
if (const DISubprogram *DSP = MF.getFunction().getSubprogram())
|
||||
*StackUsageStream << ':' << DSP->getLine();
|
||||
|
||||
*StackUsageStream << ':' << MF.getName() << '\t' << StackSize << '\t';
|
||||
if (FrameInfo.hasVarSizedObjects())
|
||||
*StackUsageStream << "dynamic\n";
|
||||
else
|
||||
*StackUsageStream << "static\n";
|
||||
}
|
||||
|
||||
static bool needFuncLabelsForEHOrDebugInfo(const MachineFunction &MF) {
|
||||
MachineModuleInfo &MMI = MF.getMMI();
|
||||
if (!MF.getLandingPads().empty() || MF.hasEHFunclets() || MMI.hasDebugInfo())
|
||||
|
@ -1469,6 +1500,9 @@ void AsmPrinter::emitFunctionBody() {
|
|||
// Emit section containing stack size metadata.
|
||||
emitStackSizeSection(*MF);
|
||||
|
||||
// Emit .su file containing function stack size information.
|
||||
emitStackUsage(*MF);
|
||||
|
||||
emitPatchableFunctionEntries();
|
||||
|
||||
if (isVerbose())
|
||||
|
|
Loading…
Reference in New Issue