Index: llvm/lib/Target/X86/CMakeLists.txt =================================================================== --- llvm/lib/Target/X86/CMakeLists.txt +++ llvm/lib/Target/X86/CMakeLists.txt @@ -39,6 +39,8 @@ X86FrameLowering.cpp X86InstructionSelector.cpp X86ISelDAGToDAG.cpp + X86LogStackFrames.cpp + X86LogCallGraph.cpp X86ISelLowering.cpp X86IndirectBranchTracking.cpp X86InterleavedAccess.cpp Index: llvm/lib/Target/X86/X86.h =================================================================== --- llvm/lib/Target/X86/X86.h +++ llvm/lib/Target/X86/X86.h @@ -28,6 +28,13 @@ class X86Subtarget; class X86TargetMachine; + +FunctionPass *createX86LogStackFrames(); +void initializeX86LogStackFramesPass(PassRegistry &); + +ModulePass *createX86LogCallGraph(); +void initializeX86LogCallGraphPass(PassRegistry &); + /// This pass converts a legalized DAG into a X86-specific DAG, ready for /// instruction scheduling. FunctionPass *createX86ISelDag(X86TargetMachine &TM, Index: llvm/lib/Target/X86/X86LogCallGraph.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/X86/X86LogCallGraph.cpp @@ -0,0 +1,104 @@ +#include "X86.h" +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/raw_ostream.h" +#include +#include + +using namespace llvm; + +llvm::cl::opt +OutputFilename("stack-depth", + cl::desc("Specify output filename for stack depth analysis"), + cl::value_desc("filename")); + +struct CFInfo { + std::string fname; + std::vector calls; +}; + +LLVM_YAML_IS_SEQUENCE_VECTOR(CFInfo) + + template <> + struct llvm::yaml::MappingTraits { + static void mapping(IO &io, CFInfo &info) { + io.mapRequired("fname", info.fname); + io.mapRequired("calls", info.calls); + } + }; + +#define X86_LOGCALLGRAPH_PASS_NAME "LOG CALL GRAPH MODULE PASS" + +namespace { + +class X86LogCallGraph : public ModulePass { + public: + static char ID; + + X86LogCallGraph() : ModulePass(ID) { + initializeX86LogCallGraphPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module& M) override; + void getAnalysisUsage(AnalysisUsage& au) const override; + + StringRef getPassName() const override { return X86_LOGCALLGRAPH_PASS_NAME; } +}; + +char X86LogCallGraph::ID = 0; + + +void X86LogCallGraph::getAnalysisUsage(AnalysisUsage& au) const +{ + au.addRequired(); +} + + +// based upon the print method in CallGraph +// http://llvm.org/doxygen/CallGraph_8cpp_source.html +bool X86LogCallGraph::runOnModule(Module& m) +{ + if(OutputFilename != ""){ + std::error_code OK; + std::error_code OutErrorInfo; + llvm::raw_fd_ostream OS(OutputFilename, OutErrorInfo, llvm::sys::fs::F_Append); + if (OutErrorInfo != OK) { + llvm::errs() << "Error opening yaml file: " << OutErrorInfo.message() << "\n"; + } + + CallGraph &cg = getAnalysis().getCallGraph(); + std::vector toLog; + for (const auto &I : cg){ + CallGraphNode *CN = I.second.get(); + Function *F = CN->getFunction(); + CFInfo temp; + temp.fname = F ? F->getName() : "<>"; + std::vector calls; + for (const auto &I : *CN) { + if (Function *FI = I.second->getFunction()) + calls.push_back(FI->getName()); + else + calls.push_back("external_node"); + } + temp.calls = calls; + toLog.push_back(temp); + } + llvm::yaml::Output yout(OS); + yout << toLog; + OS.close(); + } // end of if OutputFilename != "" + return false; +} //end of runOnModule +} // end of anonymous namespace + +INITIALIZE_PASS(X86LogCallGraph, "x86-logcallgraph", + X86_LOGCALLGRAPH_PASS_NAME, + true, // is CFG only? + true // is analysis? +) + +namespace llvm { + +ModulePass *createX86LogCallGraph() { return new X86LogCallGraph(); } +} Index: llvm/lib/Target/X86/X86LogStackFrames.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/X86/X86LogStackFrames.cpp @@ -0,0 +1,78 @@ +#include "X86.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "X86MachineFunctionInfo.h" +#include "llvm/Support/YAMLTraits.h" +#include "llvm/Support/CommandLine.h" +#include + +extern llvm::cl::opt OutputFilename; + +struct stackSize { + std::string fname; + int stackSize; +}; + +template <> +struct llvm::yaml::MappingTraits { + static void mapping(IO &io, stackSize &info) { + io.mapRequired("fname", info.fname); + io.mapOptional("stackSize", info.stackSize); + } +}; + +using namespace llvm; + +#define X86_LOGSTACKFRAMES_PASS_NAME "X86 Log Stack Frame" + +namespace { + +class X86LogStackFrames : public MachineFunctionPass { + public: + static char ID; + + X86LogStackFrames() : MachineFunctionPass(ID) { + initializeX86LogStackFramesPass(*PassRegistry::getPassRegistry()); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + StringRef getPassName() const override + { return X86_LOGSTACKFRAMES_PASS_NAME; } +}; //end class + +char X86LogStackFrames::ID = 0; + + +bool X86LogStackFrames::runOnMachineFunction(MachineFunction &MF) { + if(OutputFilename != ""){ + std::error_code OK; + std::error_code OutErrorInfo; + llvm::raw_fd_ostream OS(OutputFilename, OutErrorInfo, llvm::sys::fs::F_Append); + if (OutErrorInfo != OK) { + llvm::errs() << "Error opening yaml file: " << OutErrorInfo.message() << "\n"; + } + MachineFrameInfo &MFI = MF.getFrameInfo(); + + stackSize SS; + SS.fname = MF.getName(); + SS.stackSize = MFI.getStackSize(); + + llvm::yaml::Output yout(OS); + yout << SS; + OS.close(); + } // end if OutputFilename != "" + return false; +} //end runOnMachineFunction +} //end anon namespace + + +INITIALIZE_PASS(X86LogStackFrames, "x86-logStackFrames-printer", + X86_LOGSTACKFRAMES_PASS_NAME, + true, // is CFG only? + true // is analysis? +) + +namespace llvm { + +FunctionPass *createX86LogStackFrames() { return new X86LogStackFrames(); } +} Index: llvm/lib/Target/X86/X86TargetMachine.cpp =================================================================== --- llvm/lib/Target/X86/X86TargetMachine.cpp +++ llvm/lib/Target/X86/X86TargetMachine.cpp @@ -86,6 +86,9 @@ initializeX86DomainReassignmentPass(PR); initializeX86AvoidSFBPassPass(PR); initializeX86FlagsCopyLoweringPassPass(PR); + + initializeX86LogStackFramesPass(PR); + initializeX86LogCallGraphPass(PR); } static std::unique_ptr createTLOF(const Triple &TT) { @@ -499,4 +502,7 @@ const Triple &TT = TM->getTargetTriple(); if (!TT.isOSDarwin() && !TT.isOSWindows()) addPass(createCFIInstrInserter()); + + addPass(createX86LogStackFrames()); + addPass(createX86LogCallGraph()); }