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 + X86LogStackInfo.cpp + X86LogStackInfoClasses.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,17 @@ class X86Subtarget; class X86TargetMachine; +// 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 *createX86LogStackInfo(); +void initializeX86LogStackInfoPass(PassRegistry &); + +// This pass logs information from the IR of how classes are related. This supplements +// the information that X86LogStackInfo logs, making it possible to analyze +// indirect function calls based on their signatures. +ModulePass *createX86LogStackInfoClasses(); +void initializeX86LogStackInfoClassesPass(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/X86LogStackInfo.h =================================================================== --- /dev/null +++ llvm/lib/Target/X86/X86LogStackInfo.h @@ -0,0 +1,50 @@ +#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(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("fname", info.FName); + io.mapRequired("isa", info.IsA); + } + }; + + struct StackInfo { + std::string FName; + TypeSignature Signature; + int StackSize; + std::vector DirectCalls; + std::vector IndirectCallSigs; + }; + + template <> + struct llvm::yaml::MappingTraits { + static void mapping(IO &io, StackInfo &info) { + io.mapRequired("fname", info.FName); + io.mapRequired("signature", info.Signature); + io.mapRequired("stackSize", info.StackSize); + io.mapRequired("directCalls", info.DirectCalls); + io.mapRequired("indirectCallSigs", info.IndirectCallSigs); + } + }; Index: llvm/lib/Target/X86/X86LogStackInfo.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/X86/X86LogStackInfo.cpp @@ -0,0 +1,100 @@ +#include "X86.h" +#include "X86LogStackInfo.h" +#include "X86MachineFunctionInfo.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineModuleInfo.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/YAMLTraits.h" +#include "llvm/Support/raw_ostream.h" +#include + +extern llvm::cl::opt GenerateStackAnalysis; + +using namespace llvm; + +#define X86_LOGSTACKINFO_PASS_NAME "X86 Log Stack Frame" + +namespace { +class X86LogStackInfo : public MachineFunctionPass { + public: + static char ID; + + X86LogStackInfo() : MachineFunctionPass(ID) { + initializeX86LogStackInfoPass(*PassRegistry::getPassRegistry()); + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + StringRef getPassName() const override + { return X86_LOGSTACKINFO_PASS_NAME; } +}; //end class + +char X86LogStackInfo::ID = 0; + +// 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 X86LogStackInfo::runOnMachineFunction(MachineFunction &MF) { + if(GenerateStackAnalysis){ + std::string OutputFilename = MF.getMMI().getModule()->getName().split(".").first.str() + ".yaml"; + 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"; + + StackInfo Info; + std::vector DirectCalls; + std::vector IndirectCallSigs; + Info.FName = MF.getName(); + Info.StackSize = MF.getFrameInfo().getStackSize(); + Function *F = const_cast(&(MF.getFunction())); + Info.Signature = getSignature(F->getFunctionType()); + for (BasicBlock &BB : *F){ + for (Instruction &I : BB) { + if (auto CS = CallSite(&I)) { + if(CS.isIndirectCall()) + IndirectCallSigs.push_back(getSignature(CS.getFunctionType())); + else + DirectCalls.push_back(CS.getCalledFunction()->getName()); + }}} + Info.IndirectCallSigs = IndirectCallSigs; + Info.DirectCalls = DirectCalls; + llvm::yaml::Output yout(OS); + yout << Info; + OS.close(); + } // end if + return false; +} //end runOnMachineFunction +} // end anonymous namespace + +INITIALIZE_PASS(X86LogStackInfo, "x86-logStackFrames-printer", + X86_LOGSTACKINFO_PASS_NAME, + true, // is CFG only? + true // is analysis? +) + +namespace llvm { +FunctionPass *createX86LogStackInfo() { return new X86LogStackInfo(); } +} Index: llvm/lib/Target/X86/X86LogStackInfoClasses.cpp =================================================================== --- /dev/null +++ llvm/lib/Target/X86/X86LogStackInfoClasses.cpp @@ -0,0 +1,75 @@ +#include "X86.h" +#include "X86LogStackInfo.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.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 X86_LOGSTACKINFOCLASSES_PASS_NAME "LOG CALL GRAPH MODULE PASS" + +namespace { +class X86LogStackInfoClasses : public ModulePass { + public: + static char ID; + + X86LogStackInfoClasses() : ModulePass(ID) { + initializeX86LogStackInfoClassesPass(*PassRegistry::getPassRegistry()); + } + + bool runOnModule(Module& M) override; + + StringRef getPassName() const override { return X86_LOGSTACKINFOCLASSES_PASS_NAME; } +}; + +char X86LogStackInfoClasses::ID = 0; + +bool X86LogStackInfoClasses::runOnModule(Module& M){ + if(GenerateStackAnalysis){ + std::string OutputFilename = M.getName().split(".").first.str() + ".yaml"; + 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"; + + std::vector AllClassData; + for(StructType* s: M.getIdentifiedStructTypes()){ + ClassInfo CI; + CI.FName = s->getName(); + std::vector IsA; + for(Type* t: s->elements()){ + if(t->isStructTy()) + IsA.push_back(t->getStructName()); + } + if (!IsA.empty()){ + CI.IsA = IsA; + AllClassData.push_back(CI); + } + } + llvm::yaml::Output yout(OS); + yout << AllClassData; + OS.close(); + } // end if + return false; +} //end of runOnModule +} // end anonymous namespace + +INITIALIZE_PASS(X86LogStackInfoClasses, "x86-logstackinfoclasses", + X86_LOGSTACKINFOCLASSES_PASS_NAME, + true, // is CFG only? + true // is analysis? +) + +namespace llvm { +ModulePass *createX86LogStackInfoClasses() { return new X86LogStackInfoClasses(); } +} 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); + + initializeX86LogStackInfoPass(PR); + initializeX86LogStackInfoClassesPass(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(createX86LogStackInfo()); + addPass(createX86LogStackInfoClasses()); }