diff --git a/llvm/lib/Target/PIC16/PIC16Passes/Makefile b/llvm/lib/Target/PIC16/PIC16Passes/Makefile new file mode 100644 index 000000000000..919562106a16 --- /dev/null +++ b/llvm/lib/Target/PIC16/PIC16Passes/Makefile @@ -0,0 +1,16 @@ +##===- lib/Target/PIC16/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../../.. +LIBRARYNAME = PIC16Passes +TARGET = PIC16 + +LOADABLE_MODULE = 1 + +include $(LEVEL)/Makefile.common + diff --git a/llvm/lib/Target/PIC16/PIC16Passes/PIC16CallGraph.cpp b/llvm/lib/Target/PIC16/PIC16Passes/PIC16CallGraph.cpp new file mode 100644 index 000000000000..7c792956ecf4 --- /dev/null +++ b/llvm/lib/Target/PIC16/PIC16Passes/PIC16CallGraph.cpp @@ -0,0 +1,162 @@ +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include +#include +using namespace llvm; +using std::vector; +using std::string; + +namespace { + class PIC16CallGraph : public ModulePass { + public: + static char ID; // Class identification + PIC16CallGraph() : ModulePass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired(); + } + virtual bool runOnModule(Module &M) { + // Initially record that no interrupt has been found + InterruptFound = false; + + CallGraph &CG = getAnalysis(); + for (CallGraph::iterator it = CG.begin() ; it != CG.end(); it++) + { + // External calling node doesn't have any function associated + // with it + if (!it->first) + continue; + + if (it->first->getName().str() == "main") { + // See if the main itself is interrupt function then report an error. + if (it->first->getSection().find("interrupt") != string::npos) + reportError("Function 'main' can't be interrupt function"); + else { + // Set the MainLine tag for function main also. + it->second->getFunction()->setSection("ML"); + // mark the hierarchy + markFunctionHierarchy(it->second, "ML"); + } + } else if (it->first->getSection().find("interrupt") != string::npos) { + if (InterruptFound) + reportError("More than one interrupt functions defined in the module"); + + InterruptFound = true; + markFunctionHierarchy(it->second, "IL"); + } + } + return false; + } + private: // Functions + // Makr function hierarchy for the MainLine or InterruptLine. + void markFunctionHierarchy(CallGraphNode *CGN, string StringMark); + + // Error reporting for PIC16Pass + void reportError(string ErrorString, vector &Values); + void reportError(string ErrorString); + private: // Data + // Records if the interrupt function has already been found. + // If more than one interrupt function is found then an error + // should be thrown. + bool InterruptFound; + }; + char PIC16CallGraph::ID =0; + static RegisterPass + Y("pic16cg", "PIC16 CallGraph Construction"); + +} // End of anonymous namespace + +void PIC16CallGraph::reportError(string ErrorString) { + errs() << "ERROR : " << ErrorString << "\n"; + exit(1); +} + +void PIC16CallGraph:: +reportError (string ErrorString, vector &Values) { + unsigned ValCount = Values.size(); + string TargetString; + for (unsigned i=0; ibegin(); + cgn_it != CGN->end(); ++cgn_it) { + Function *CalledF = cgn_it->second->getFunction(); + + // If calling an external function then CallGraphNode + // will not be associated with any function. + if (!CalledF) + continue; + + // Issue diagnostic if interrupt function is being called. + if (CalledF->getSection().find("interrupt") != string::npos) { + vector Values; + Values.push_back(CalledF->getName().str()); + reportError("Interrupt function (%0) can't be called", Values); + } + + // If already shared mark then no need to check any further. + // Also a great potential for recursion. + if (CalledF->getSection().find(SharedMark) != string::npos) { + continue; + } + + // Has already been mark + if (CalledF->getSection().find(StringMark) != string::npos) { + // Issue diagnostic + // Potential for recursion. + } else { + // Mark now + if (CalledF->getSection().find(AlternateMark) != string::npos) { + // Function is alternatively marked. It should be a shared one. + + // Shared functions should be clone. Clone here. + Function *ClonedFunc = CloneFunction(CalledF); + + // Add the newly created function to the module. + CalledF->getParent()->getFunctionList().push_back(ClonedFunc); + + // The new function should be for interrupt line. Therefore should have the + // name suffixed with IL and section attribute marked with IL. + ClonedFunc->setName(CalledF->getName().str() + ".IL"); + ClonedFunc->setSection("IL"); + + // Original function now should be for MainLine only. + CalledF->setSection("ML"); + + // Update the CallSite + CallSite CS = cgn_it->first; + CS.getInstruction()->getOperand(0)->setName(CalledF->getName().str() + ".shared"); + } else { + // Function is not marked. It should be marked now. + CalledF->setSection(StringMark); + } + } + + // Before going any further mark all the called function by current + // function. + markFunctionHierarchy(cgn_it->second ,StringMark); + } // end of loop of all called functions. + +}