diff options
-rw-r--r-- | lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp | 184 | ||||
-rw-r--r-- | lib/Target/PIC16/PIC16Passes/PIC16Cloner.h | 70 |
2 files changed, 254 insertions, 0 deletions
diff --git a/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp b/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp new file mode 100644 index 0000000000..58f72ee5ce --- /dev/null +++ b/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp @@ -0,0 +1,184 @@ +//===-- PIC16Cloner.cpp - PIC16 LLVM Cloner for shared functions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains code to clone all functions that are shared between +// the main line code (ML) and interrupt line code (IL). It clones all such +// shared functions and their automatic global vars by adding the .IL suffix. +// +// This pass is supposed to be run on the linked .bc module. +// It traveses the module call graph twice. Once starting from the main function +// and marking each reached function as "ML". Again, starting from the ISR +// and cloning any reachable function that was marked as "ML". After cloning +// the function, it remaps all the call sites in IL functions to call the +// cloned functions. +//===----------------------------------------------------------------------===// + +#include "llvm/Analysis/CallGraph.h" +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/Utils/Cloning.h" +#include "PIC16Cloner.h" +#include "../PIC16ABINames.h" +#include <vector> + +using namespace llvm; +using std::vector; +using std::string; +using std::map; + +namespace llvm { + char PIC16Cloner::ID = 0; + + ModulePass *createPIC16ClonerPass() { return new PIC16Cloner(); } +} + +// We currently intend to run these passes in opt, which does not have any +// diagnostic support. So use these functions for now. In future +// we will probably write our own driver tool. +// +void PIC16Cloner::reportError(string ErrorString) { + errs() << "ERROR : " << ErrorString << "\n"; + exit(1); +} + +void PIC16Cloner:: +reportError (string ErrorString, vector<string> &Values) { + unsigned ValCount = Values.size(); + string TargetString; + for (unsigned i=0; i<ValCount; ++i) { + TargetString = "%"; + TargetString += ((char)i + '0'); + ErrorString.replace(ErrorString.find(TargetString), TargetString.length(), + Values[i]); + } + errs() << "ERROR : " << ErrorString << "\n"; + exit(1); +} + + +// Entry point +// +bool PIC16Cloner::runOnModule(Module &M) { + CallGraph &CG = getAnalysis<CallGraph>(); + // Initially record that no interrupt has been found + foundISR = false; + + // First mark the MainLine. + 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 (PAN::isISR(it->first->getSection())) + reportError("Function 'main' can't be interrupt function"); + else { + // Function main itself is MainLine function. + it->second->getFunction()->setSection("ML"); + // mark the hierarchy + markCallGraph(it->second, "ML"); + // MainLine has been marked now break ; don't search any further. + break; + } + } + } + + // When the MainLine has been marked only then mark the InterruptLine. + 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 (PAN::isISR(it->first->getSection())) { + + if (foundISR) + reportError("More than one interrupt functions defined in the module"); + + foundISR = true; + + markCallGraph(it->second, "IL"); + // InterruptLine handled now break; don't search any further. + break; + } + } + + return true; +} + +// For PIC16, automatic variables of a function are emitted as globals. +// Clone the auto variables of a function and put them in ValueMap, +// this ValueMap will be used while +// Cloning the code of function itself. +// +void PIC16Cloner::CloneAutos(Function *F) { + // Not implemented yet. +} + + +// Mark all reachable functions from the given node, with the given mark. +// +void PIC16Cloner::markCallGraph(CallGraphNode *CGN, string StringMark) { + string AlternateMark; + if (StringMark == "ML") + AlternateMark = "IL"; + else + AlternateMark = "ML"; + + // Mark all the called functions + for(CallGraphNode::iterator cgn_it = CGN->begin(); + 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 (PAN::isISR(CalledF->getSection())) { + vector<string> Values; + Values.push_back(CalledF->getName().str()); + reportError("Interrupt function (%0) can't be called", Values); + } + + // Has already been mark + if (CalledF->getSection().find(StringMark) != string::npos) { + // Should we do anything here? + } else { + // Mark now + if (CalledF->getSection().find(AlternateMark) != string::npos) { + // Function is alternatively marked. It should be a shared one. + // Create IL copy. Passing called function as first argument + // and the caller as the second argument. + + // Before making IL copy, first ensure that this function has a + // body. If the function does have a body. It can't be cloned. + // Such a case may occur when the function has been declarated + // in the C source code but its body exists in assembly file. + if (!CalledF->isDeclaration()) { + // FIXME: Not implemented yet. Clone the function here. + } + } 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. + markCallGraph(cgn_it->second ,StringMark); + } // end of loop of all called functions. +} + diff --git a/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h b/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h new file mode 100644 index 0000000000..beeef7d25d --- /dev/null +++ b/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h @@ -0,0 +1,70 @@ +//===-- PIC16Cloner.h - PIC16 LLVM Cloner for shared functions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains declaration of a cloner class clone all functions that +// are shared between the main line code (ML) and interrupt line code (IL). +// +//===----------------------------------------------------------------------===// + +#ifndef PIC16CLONER_H +#define PIC16CLONER_H + +#include "llvm/ADT/DenseMap.h" + +using namespace llvm; +using std::vector; +using std::string; +using std::map; + +namespace llvm { + // forward classes. + class Value; + class Function; + class Module; + class ModulePass; + class CallGraph; + class CallGraphNode; + class AnalysisUsage; + + class PIC16Cloner : public ModulePass { + public: + static char ID; // Class identification + PIC16Cloner() : ModulePass(&ID) {} + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.addRequired<CallGraph>(); + } + virtual bool runOnModule(Module &M); + + private: // Functions + // Mark reachable functions for the MainLine or InterruptLine. + void markCallGraph(CallGraphNode *CGN, string StringMark); + + // Clone auto variables of function specified. + void CloneAutos(Function *F); + + // Error reporting for PIC16Pass + void reportError(string ErrorString, vector<string> &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 foundISR; + + // This ValueMap maps the auto variables of the original functions with + // the corresponding cloned auto variable of the cloned function. + // This value map is passed during the function cloning so that all the + // uses of auto variables be updated properly. + DenseMap<const Value*, Value*> ValueMap; + }; +} // End of anonymous namespace + +#endif |