Index: llvm/include/llvm/CodeGen/Passes.h =================================================================== --- llvm/include/llvm/CodeGen/Passes.h +++ llvm/include/llvm/CodeGen/Passes.h @@ -441,6 +441,19 @@ /// Creates CFI Instruction Inserter pass. \see CFIInstrInserter.cpp FunctionPass *createCFIInstrInserter(); + // This pass logs information about the stack (stack size, function signature, + // direct & indirect calls) to a yaml file with the same name as the module. + FunctionPass *createLogStackInfo(); + + // This pass logs information from the IR of how classes are related. + // This supplements the information that LogStackInfo logs, making it possible + // to analyze indirect function calls based on their signatures. + ModulePass *createLogStackInfoClasses(); + + extern char &LogStackInfoID; + + extern char &LogStackInfoClassesID; + } // End llvm namespace #endif Index: llvm/include/llvm/InitializePasses.h =================================================================== --- llvm/include/llvm/InitializePasses.h +++ llvm/include/llvm/InitializePasses.h @@ -207,6 +207,8 @@ void initializeLoaderPassPass(PassRegistry&); void initializeLocalStackSlotPassPass(PassRegistry&); void initializeLocalizerPass(PassRegistry&); +void initializeLogStackInfoPass(PassRegistry&); +void initializeLogStackInfoClassesPass(PassRegistry&); void initializeLoopAccessLegacyAnalysisPass(PassRegistry&); void initializeLoopDataPrefetchLegacyPassPass(PassRegistry&); void initializeLoopDeletionLegacyPassPass(PassRegistry&); Index: llvm/lib/CodeGen/CMakeLists.txt =================================================================== --- llvm/lib/CodeGen/CMakeLists.txt +++ llvm/lib/CodeGen/CMakeLists.txt @@ -58,6 +58,8 @@ LiveVariables.cpp LLVMTargetMachine.cpp LocalStackSlotAllocation.cpp + LogStackInfo.cpp + LogStackInfoClasses.cpp LoopTraversal.cpp LowLevelType.cpp LowerEmuTLS.cpp Index: llvm/lib/CodeGen/CodeGen.cpp =================================================================== --- llvm/lib/CodeGen/CodeGen.cpp +++ llvm/lib/CodeGen/CodeGen.cpp @@ -50,6 +50,8 @@ initializeLiveStacksPass(Registry); initializeLiveVariablesPass(Registry); initializeLocalStackSlotPassPass(Registry); + initializeLogStackInfoPass(Registry); + initializeLogStackInfoClassesPass(Registry); initializeLowerIntrinsicsPass(Registry); initializeMIRCanonicalizerPass(Registry); initializeMachineBlockFrequencyInfoPass(Registry); Index: llvm/lib/CodeGen/LogStackInfo.h =================================================================== --- /dev/null +++ llvm/lib/CodeGen/LogStackInfo.h @@ -0,0 +1,100 @@ +//===-- LogStackInfo.h ----------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines types used by the LogStackInfo & LogStackInfoClasses passes +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_LOGSTACKINFO_H +#define LLVM_LOGSTACKINFO_H + +#include "llvm/Support/YAMLTraits.h" + +struct TypeSignature { + std::string ReturnType; + std::vector ArgTypes; +}; + +template <> struct llvm::yaml::MappingTraits { + static void mapping(IO &io, TypeSignature &info) { + io.mapRequired("ReturnType", info.ReturnType); + io.mapOptional("ArgTypes", info.ArgTypes); + } +}; +LLVM_YAML_IS_SEQUENCE_VECTOR(std::vector) +LLVM_YAML_IS_SEQUENCE_VECTOR(TypeSignature) + +struct ClassInfo { + std::string FName; + std::vector IsA; +}; + +LLVM_YAML_IS_SEQUENCE_VECTOR(ClassInfo) + +template <> struct llvm::yaml::MappingTraits { + static void mapping(IO &io, ClassInfo &info) { + io.mapRequired("Function", info.FName); + io.mapRequired("IsA", info.IsA); + } +}; + +struct ModuleClassInfo { + std::string PassName; + std::string Name; + std::string DebugModuleName; + std::vector Args; +}; + +template <> struct llvm::yaml::MappingTraits { + static void mapping(IO &io, ModuleClassInfo &info) { + io.mapTag("!StackDepthData", true); + io.mapRequired("Pass", info.PassName); + io.mapRequired("Name", info.Name); + io.mapRequired("DebugLoc-File", info.DebugModuleName); + io.mapRequired("Args", info.Args); + } +}; + +struct StackInfo { + TypeSignature Signature; + int StackSize; + bool IsEntry; + std::vector DirectCalls; + std::vector IndirectCallSigs; +}; + +template <> struct llvm::yaml::MappingTraits { + static void mapping(IO &io, StackInfo &info) { + io.mapRequired("Signature", info.Signature); + io.mapRequired("StackSize", info.StackSize); + io.mapRequired("IsEntry", info.IsEntry); + io.mapOptional("DirectCalls", info.DirectCalls); + io.mapOptional("IndirectCallSigs", info.IndirectCallSigs); + } +}; + +struct FunctionStackInfo { + std::string PassName; + std::string Name; + std::string DebugModuleName; + std::string Function; + StackInfo Args; +}; + +template <> struct llvm::yaml::MappingTraits { + static void mapping(IO &io, FunctionStackInfo &info) { + io.mapTag("!StackDepthData", true); + io.mapRequired("Pass", info.PassName); + io.mapRequired("Name", info.Name); + io.mapRequired("DebugLoc-File", info.DebugModuleName); + io.mapRequired("Function", info.Function); + io.mapRequired("Args", info.Args); + } +}; + +#endif // LLVM_LOGSTACKINFO_H Index: llvm/lib/CodeGen/LogStackInfo.cpp =================================================================== --- /dev/null +++ llvm/lib/CodeGen/LogStackInfo.cpp @@ -0,0 +1,126 @@ +//===-- LogStackInfo.cpp --------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass logs information about the stack (stack size, function signature, +// direct & indirect calls) to a yaml file with the same name as the module. +// +//===----------------------------------------------------------------------===// + +#include "LogStackInfo.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include + +extern llvm::cl::opt GenerateStackAnalysis; + +using namespace llvm; + +#define LOGSTACKINFO_PASS_NAME "Log Stack Frame Info" + +namespace { +class LogStackInfo : public MachineFunctionPass { +public: + static char ID; + + LogStackInfo() : MachineFunctionPass(ID) { + initializeLogStackInfoPass(*PassRegistry::getPassRegistry()); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + StringRef getPassName() const override { return LOGSTACKINFO_PASS_NAME; } +}; // end class + +// Function to format the type signature +TypeSignature getSignature(FunctionType *FuncType) { + TypeSignature Sig; + std::string OutputString; + llvm::raw_string_ostream SOS(OutputString); + FuncType->getReturnType()->print(SOS); + SOS.str(); + Sig.ReturnType = OutputString; + + std::vector ArgTypes; + for (Type *ArgType : FuncType->params()) { + OutputString = ""; // reset the string used in the buffer + ArgType->print(SOS); + ArgTypes.push_back(SOS.str()); + } + Sig.ArgTypes = ArgTypes; + return Sig; +} + +bool LogStackInfo::runOnMachineFunction(MachineFunction &MF) { + if (GenerateStackAnalysis) { + const Module *M = MF.getMMI().getModule(); + yaml::Output *Yout = M->getContext().getDiagnosticsOutputFile(); + // This pass must be run with the -fsave-optimization-record pass to + // produce an output file; LogStackInfoClasses notifies the user of this. + if (!Yout) + return false; + + Function *F = const_cast(&(MF.getFunction())); + StackInfo Info; + Info.StackSize = MF.getFrameInfo().getStackSize(); + Info.Signature = getSignature(F->getFunctionType()); + std::vector DirectCalls; + std::vector IndirectCallSigs; + + for (BasicBlock &BB : *F) { + for (Instruction &I : BB) { + if (auto CS = CallSite(&I)) { + if (CS.isIndirectCall()) + IndirectCallSigs.push_back(getSignature(CS.getFunctionType())); + else { + if (CS.getCalledFunction() && + (CS.getIntrinsicID() == Intrinsic::not_intrinsic)) + DirectCalls.push_back(CS.getCalledFunction()->getName()); + } + } + } + } + Info.IndirectCallSigs = IndirectCallSigs; + Info.DirectCalls = DirectCalls; + Info.IsEntry = (F->hasDefaultVisibility() && F->hasExternalLinkage()); + + FunctionStackInfo FSI; + FSI.PassName = LOGSTACKINFO_PASS_NAME; + FSI.Name = "StackDepthData"; + FSI.DebugModuleName = M->getName(); + FSI.Function = F->getName(); + FSI.Args = Info; + + *(Yout) << FSI; + } // end if + return false; +} // end runOnMachineFunction +} // end anonymous namespace + +char LogStackInfo::ID = 0; +char &llvm::LogStackInfoID = LogStackInfo::ID; + +INITIALIZE_PASS(LogStackInfo, "logStackFrames-printer", LOGSTACKINFO_PASS_NAME, + true, // is CFG only? + true // is analysis? +) + +namespace llvm { +FunctionPass *createLogStackInfo() { return new LogStackInfo(); } +} // namespace llvm Index: llvm/lib/CodeGen/LogStackInfoClasses.cpp =================================================================== --- /dev/null +++ llvm/lib/CodeGen/LogStackInfoClasses.cpp @@ -0,0 +1,100 @@ +//===-- LogStackInfoClasses.cpp -------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass logs information from the IR of how classes are related. +// This supplements the information that LogStackInfo logs, making it possible +// to analyze indirect function calls based on their signatures. +// +//===----------------------------------------------------------------------===// + +#include "LogStackInfo.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/DerivedTypes.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +using namespace llvm; + +llvm::cl::opt GenerateStackAnalysis( + "gen-stack-depth-info", + cl::desc("Generate data necessary for stack depth analysis"), + cl::value_desc("")); + +#define LOGSTACKINFOCLASSES_PASS_NAME "logstackinfoclasses" + +namespace { +class LogStackInfoClasses : public ModulePass { +public: + static char ID; + + LogStackInfoClasses() : ModulePass(ID) { + initializeLogStackInfoClassesPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module &M) override; + + StringRef getPassName() const override { + return LOGSTACKINFOCLASSES_PASS_NAME; + } +}; + +bool LogStackInfoClasses::runOnModule(Module &M) { + if (GenerateStackAnalysis) { + yaml::Output *Yout = M.getContext().getDiagnosticsOutputFile(); + if (!Yout) { + errs() << "-gen-stack-depth-info must be run with the flag " + "-fsave-optimization-record to generate output file\n"; + return false; + } + std::vector AllClassData; + for (StructType *S : M.getIdentifiedStructTypes()) { + ClassInfo CI; + CI.FName = S->getName(); + std::vector IsA; + for (Type *CurrType : S->elements()) { + if (auto *ST = dyn_cast(CurrType)) + if (!ST->isLiteral()) + IsA.push_back(CurrType->getStructName()); + } + if (!IsA.empty()) { + CI.IsA = IsA; + AllClassData.push_back(CI); + } + } + + ModuleClassInfo MCI; + MCI.PassName = LOGSTACKINFOCLASSES_PASS_NAME; + MCI.Name = "StackDepthClassData"; + MCI.DebugModuleName = M.getName(); + MCI.Args = AllClassData; + + *(Yout) << MCI; + } // end if + return false; +} // end of runOnModule +} // end anonymous namespace + +char LogStackInfoClasses::ID = 0; +char &llvm::LogStackInfoClassesID = LogStackInfoClasses::ID; + +INITIALIZE_PASS(LogStackInfoClasses, "logstackinfoclasses", + LOGSTACKINFOCLASSES_PASS_NAME, + true, // is CFG only? + true // is analysis? +) + +namespace llvm { +ModulePass *createLogStackInfoClasses() { return new LogStackInfoClasses(); } +} // namespace llvm Index: llvm/lib/CodeGen/TargetPassConfig.cpp =================================================================== --- llvm/lib/CodeGen/TargetPassConfig.cpp +++ llvm/lib/CodeGen/TargetPassConfig.cpp @@ -925,6 +925,11 @@ // Add passes that directly emit MI after all other MI passes. addPreEmitPass2(); + // These passes log information about the state of the stack, so they need to + // run after all other passes which may possibly alter the stack. + addPass(&LogStackInfoID); + addPass(&LogStackInfoClassesID); + AddingMachinePasses = false; }