Implement support for ISRs.
authorSanjiv Gupta <sanjiv.gupta@microchip.com>
Thu, 20 Aug 2009 19:28:24 +0000 (19:28 +0000)
committerSanjiv Gupta <sanjiv.gupta@microchip.com>
Thu, 20 Aug 2009 19:28:24 +0000 (19:28 +0000)
Clone functions that are shared between the Main thread and Interrupt thread.
CallSites are changed in AsmPrinter currently. A better solution would have been to modify the legalizer (SoftenFloat) to allow targets to change the name of libcalls for float operations. But that currently breaks other targets.
Also, cloing of automatic variables is done AsmPrinter, a better approach would
be to use the ValueMap in CloneFunction itself.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@79562 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h
lib/Target/PIC16/Makefile
lib/Target/PIC16/PIC16.h
lib/Target/PIC16/PIC16ISelLowering.cpp
lib/Target/PIC16/PIC16ISelLowering.h
lib/Target/PIC16/PIC16InstrInfo.td
lib/Target/PIC16/PIC16PAN.h [new file with mode: 0644]
lib/Target/PIC16/PIC16TargetObjectFile.cpp
lib/Target/PIC16/PIC16TargetObjectFile.h

index 1522e4ca2e6ef44799af87f4861c8379a782c22b..b96ae54005ec9cf39c1df49e7143dd75d80dcdb1 100644 (file)
@@ -39,6 +39,7 @@ PIC16AsmPrinter::PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM,
   PTLI = static_cast<PIC16TargetLowering*>(TM.getTargetLowering());
   PTAI = static_cast<const PIC16TargetAsmInfo*>(T);
   PTOF = (PIC16TargetObjectFile*)&PTLI->getObjFileLowering();
+  CurrentFnPtr = NULL;
 }
 
 bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
@@ -60,6 +61,11 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
   // Get the mangled name.
   const Function *F = MF.getFunction();
   CurrentFnName = Mang->getMangledName(F);
+  CurrentFnPtr = F;
+
+  // Current function name was mangled in llvm-ld for both
+  // MainLine and InterruptLine and should be demangled here 
+  PAN::updateCallLineSymbol(CurrentFnName, CurrentFnPtr);
 
   // Emit the function frame (args and temps).
   EmitFunctionFrame(MF);
@@ -71,18 +77,23 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
 
   // Now emit the instructions of function in its code section.
   const MCSection *fCodeSection = 
-    getObjFileLowering().getSectionForFunction(CurrentFnName);
+    getObjFileLowering().getSectionForFunction(CurrentFnName, 
+                                               PAN::isISR(F));
   // Start the Code Section.
   O <<  "\n";
   OutStreamer.SwitchSection(fCodeSection);
-
-  // Emit the frame address of the function at the beginning of code.
-  O << "\tretlw  low(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
-  O << "\tretlw  high(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
+  
+  // If it is not an interrupt function then emit the data address
+  // retrieval code in function code itself.
+  if (!(PAN::isISR(F))) {
+     // Emit the frame address of the function at the beginning of code.
+     O << "\tretlw  low(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
+     O << "\tretlw  high(" << PAN::getFrameLabel(CurrentFnName) << ")\n";
+  }
 
   // Emit function start label.
   O << CurrentFnName << ":\n";
-
+  
   DebugLoc CurDL;
   O << "\n"; 
   // Print out code for the function.
@@ -142,7 +153,9 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
       if (PAN::isMemIntrinsic(Sname)) {
         LibcallDecls.push_back(createESName(Sname));
       }
-
+      // All the call sites were mangled in llvm-ld pass hence the 
+      // operands for call instructions should be demangled here.
+      PAN::updateCallLineSymbol(Sname, CurrentFnPtr);
       O << Sname;
       break;
     }
@@ -151,7 +164,9 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
 
       // If its a libcall name, record it to decls section.
       if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) {
-        LibcallDecls.push_back(Sname);
+         // LibCallDecls for InterruptLine functions should have ".IL" suffix 
+         const char *NewName= PAN::getUpdatedLibCallDecl(Sname, CurrentFnPtr);
+         LibcallDecls.push_back(NewName);
       }
 
       // Record a call to intrinsic to print the extern declaration for it.
@@ -160,9 +175,13 @@ void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
         Sym = PAN::addPrefix(Sym);
         LibcallDecls.push_back(createESName(Sym));
       }
-
-      O  << Sym;
-      break;
+      // Update the library call symbols. Library calls to InterruptLine
+      // functions are different. (They have ".IL" in their names)
+      // Also other symbols (frame and temp) for the cloned function
+      // should be updated here.
+      PAN::updateCallLineSymbol(Sym, CurrentFnPtr);
+      O << Sym; 
+     break;
     }
     case MachineOperand::MO_MachineBasicBlock:
       printBasicBlockLabel(MO.getMBB());
@@ -274,7 +293,11 @@ void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
 
     const char *directive = I->isDeclaration() ? TAI->getExternDirective() :
                                                  TAI->getGlobalDirective();
-      
+   
+    // This is called in initialization. Hence information of the current
+    // function line is not available. Hence UnspecifiedLine. UnspecifiedLine
+    // will be treated as MainLine. 
+    PAN::updateCallLineSymbol(Name, PAN::UnspecifiedLine);
     O << directive << Name << "\n";
     O << directive << PAN::getRetvalLabel(Name) << "\n";
     O << directive << PAN::getArgsLabel(Name) << "\n";
@@ -423,6 +446,13 @@ void PIC16AsmPrinter::EmitAutos(std::string FunctName) {
 
   // Now print Autos section for this function.
   std::string SectionName = PAN::getAutosSectionName(FunctName);
+
+  // If this function is a cloned function then the name of auto section 
+  // will not be present in the list of existing section. Hence this section
+  // should be cloned. 
+  // This function will check and clone
+  PTOF->createClonedSectionForAutos(SectionName);
+
   const std::vector<PIC16Section*> &AutosSections = PTOF->AutosSections;
   for (unsigned i = 0; i < AutosSections.size(); i++) {
     O << "\n";
@@ -436,6 +466,8 @@ void PIC16AsmPrinter::EmitAutos(std::string FunctName) {
         Constant *C = Items[j]->getInitializer();
         const Type *Ty = C->getType();
         unsigned Size = TD->getTypeAllocSize(Ty);
+        // Auto variables should be cloned for the cloned function 
+        PAN::updateCallLineAutos(VarName, CurrentFnName);
         // Emit memory reserve directive.
         O << VarName << "  RES  " << Size << "\n";
       }
index 3eea880a20a8af593855538569b21328052389ca..55a2fcf85a6fc9d63f7e7af790acea781c57ff46 100644 (file)
@@ -73,6 +73,7 @@ namespace llvm {
     PIC16DbgInfo DbgInfo;
     const PIC16TargetAsmInfo *PTAI;
     std::list<const char *> LibcallDecls; // List of extern decls.
+    const Function *CurrentFnPtr;   // Hold the pointer to current Function 
   };
 } // end of namespace
 
index f913675da8928a41c92a5666c1cef3c706478eac..4382eba7c240a1ac09027d2ad6547f9eda3acf66 100644 (file)
@@ -17,7 +17,7 @@ BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \
                PIC16GenDAGISel.inc PIC16GenCallingConv.inc \
                PIC16GenSubtarget.inc
 
-DIRS = AsmPrinter TargetInfo
+DIRS = AsmPrinter TargetInfo PIC16Passes
 
 include $(LEVEL)/Makefile.common
 
index ec2d1f6be1095363f523472e4621a72c5a8d29b3..29f907923083f9d93d4d771b5d2be58563309b82 100644 (file)
@@ -22,6 +22,7 @@
 #include <sstream>
 #include <cstring>
 #include <string>
+#include "PIC16PAN.h"
 
 namespace llvm {
   class PIC16TargetMachine;
@@ -43,268 +44,6 @@ namespace PIC16CC {
     UGE
   };
 }
-  // A Central class to manage all ABI naming conventions.
-  // PAN - [P]ic16 [A]BI [N]ames
-  class PAN {
-    public:
-    // Map the name of the symbol to its section name.
-    // Current ABI:
-    // -----------------------------------------------------
-    // ALL Names are prefixed with the symobl '@'.
-    // ------------------------------------------------------
-    // Global variables do not have any '.' in their names.
-    // These are maily function names and global variable names.
-    // Example - @foo,  @i
-    // -------------------------------------------------------
-    // Functions and auto variables.
-    // Names are mangled as <prefix><funcname>.<tag>.<varname>
-    // Where <prefix> is '@' and <tag> is any one of
-    // the following
-    // .auto. - an automatic var of a function.
-    // .temp. - temproray data of a function.
-    // .ret.  - return value label for a function.
-    // .frame. - Frame label for a function where retval, args
-    //           and temps are stored.
-    // .args. - Label used to pass arguments to a direct call.
-    // Example - Function name:   @foo
-    //           Its frame:       @foo.frame.
-    //           Its retval:      @foo.ret.
-    //           Its local vars:  @foo.auto.a
-    //           Its temp data:   @foo.temp.
-    //           Its arg passing: @foo.args.
-    //----------------------------------------------
-    // Libcall - compiler generated libcall names must start with .lib.
-    //           This id will be used to emit extern decls for libcalls.
-    // Example - libcall name:   @.lib.sra.i8
-    //           To pass args:   @.lib.sra.i8.args.
-    //           To return val:  @.lib.sra.i8.ret.
-    //----------------------------------------------
-    // SECTION Names
-    // uninitialized globals - @udata.<num>.#
-    // initialized globals - @idata.<num>.#
-    // Function frame - @<func>.frame_section.
-    // Function autos - @<func>.autos_section.
-    // Declarations - Enclosed in comments. No section for them.
-    //----------------------------------------------------------
-    
-    // Tags used to mangle different names. 
-    enum TAGS {
-      PREFIX_SYMBOL,
-      GLOBAL,
-      STATIC_LOCAL,
-      AUTOS_LABEL,
-      FRAME_LABEL,
-      RET_LABEL,
-      ARGS_LABEL,
-      TEMPS_LABEL,
-      
-      LIBCALL,
-      
-      FRAME_SECTION,
-      AUTOS_SECTION,
-      CODE_SECTION
-    };
-
-    // Textual names of the tags.
-    inline static const char *getTagName(TAGS tag) {
-      switch (tag) {
-      default: return "";
-      case PREFIX_SYMBOL:    return "@";
-      case AUTOS_LABEL:       return ".auto.";
-      case FRAME_LABEL:       return ".frame.";
-      case TEMPS_LABEL:       return ".temp.";
-      case ARGS_LABEL:       return ".args.";
-      case RET_LABEL:       return ".ret.";
-      case LIBCALL:       return ".lib.";
-      case FRAME_SECTION:       return ".frame_section.";
-      case AUTOS_SECTION:       return ".autos_section.";
-      case CODE_SECTION:       return ".code_section.";
-      }
-    }
-
-    // Get tag type for the Symbol.
-    inline static TAGS getSymbolTag(const std::string &Sym) {
-      if (Sym.find(getTagName(TEMPS_LABEL)) != std::string::npos)
-        return TEMPS_LABEL;
-
-      if (Sym.find(getTagName(FRAME_LABEL)) != std::string::npos)
-        return FRAME_LABEL;
-
-      if (Sym.find(getTagName(RET_LABEL)) != std::string::npos)
-        return RET_LABEL;
-
-      if (Sym.find(getTagName(ARGS_LABEL)) != std::string::npos)
-        return ARGS_LABEL;
-
-      if (Sym.find(getTagName(AUTOS_LABEL)) != std::string::npos)
-        return AUTOS_LABEL;
-
-      if (Sym.find(getTagName(LIBCALL)) != std::string::npos)
-        return LIBCALL;
-
-      // It does not have any Tag. So its a true global or static local.
-      if (Sym.find(".") == std::string::npos) 
-        return GLOBAL;
-      
-      // If a . is there, then it may be static local.
-      // We should mangle these as well in clang.
-      if (Sym.find(".") != std::string::npos) 
-        return STATIC_LOCAL;
-      assert (0 && "Could not determine Symbol's tag");
-      return PREFIX_SYMBOL; // Silence warning when assertions are turned off.
-    }
-
-    // addPrefix - add prefix symbol to a name if there isn't one already.
-    inline static std::string addPrefix (const std::string &Name) {
-      std::string prefix = getTagName (PREFIX_SYMBOL);
-
-      // If this name already has a prefix, nothing to do.
-      if (Name.compare(0, prefix.size(), prefix) == 0)
-        return Name;
-
-      return prefix + Name;
-    }
-
-    // Get mangled func name from a mangled sym name.
-    // In all cases func name is the first component before a '.'.
-    static inline std::string getFuncNameForSym(const std::string &Sym1) {
-      assert (getSymbolTag(Sym1) != GLOBAL && "not belongs to a function");
-
-      std::string Sym = addPrefix(Sym1);
-
-      // Position of the . after func name. That's where func name ends.
-      size_t func_name_end = Sym.find ('.');
-
-      return Sym.substr (0, func_name_end);
-    }
-
-    // Get Frame start label for a func.
-    static std::string getFrameLabel(const std::string &Func) {
-      std::string Func1 = addPrefix(Func);
-      std::string tag = getTagName(FRAME_LABEL);
-      return Func1 + tag;
-    }
-
-    static std::string getRetvalLabel(const std::string &Func) {
-      std::string Func1 = addPrefix(Func);
-      std::string tag = getTagName(RET_LABEL);
-      return Func1 + tag;
-    }
-
-    static std::string getArgsLabel(const std::string &Func) {
-      std::string Func1 = addPrefix(Func);
-      std::string tag = getTagName(ARGS_LABEL);
-      return Func1 + tag;
-    }
-
-    static std::string getTempdataLabel(const std::string &Func) {
-      std::string Func1 = addPrefix(Func);
-      std::string tag = getTagName(TEMPS_LABEL);
-      return Func1 + tag;
-    }
-
-    static std::string getFrameSectionName(const std::string &Func) {
-      std::string Func1 = addPrefix(Func);
-      std::string tag = getTagName(FRAME_SECTION);
-      return Func1 + tag + "# UDATA_OVR";
-    }
-
-    static std::string getAutosSectionName(const std::string &Func) {
-      std::string Func1 = addPrefix(Func);
-      std::string tag = getTagName(AUTOS_SECTION);
-      return Func1 + tag + "# UDATA_OVR";
-    }
-
-    static std::string getCodeSectionName(const std::string &Func) {
-      std::string Func1 = addPrefix(Func);
-      std::string tag = getTagName(CODE_SECTION);
-      return Func1 + tag + "# CODE";
-    }
-
-    // udata, romdata and idata section names are generated by a given number.
-    // @udata.<num>.# 
-    static std::string getUdataSectionName(unsigned num, 
-                                           std::string prefix = "") {
-       std::ostringstream o;
-       o << getTagName(PREFIX_SYMBOL) << prefix << "udata." << num 
-         << ".# UDATA"; 
-       return o.str(); 
-    }
-
-    static std::string getRomdataSectionName(unsigned num,
-                                             std::string prefix = "") {
-       std::ostringstream o;
-       o << getTagName(PREFIX_SYMBOL) << prefix << "romdata." << num 
-         << ".# ROMDATA";
-       return o.str();
-    }
-
-    static std::string getIdataSectionName(unsigned num,
-                                           std::string prefix = "") {
-       std::ostringstream o;
-       o << getTagName(PREFIX_SYMBOL) << prefix << "idata." << num 
-         << ".# IDATA"; 
-       return o.str(); 
-    }
-
-    inline static bool isLocalName (const std::string &Name) {
-      if (getSymbolTag(Name) == AUTOS_LABEL)
-        return true;
-
-      return false;
-    }
-
-    inline static bool isMemIntrinsic (const std::string &Name) {
-      if (Name.compare("@memcpy") == 0 || Name.compare("@memset") == 0 ||
-          Name.compare("@memmove") == 0) {
-        return true;
-      }
-      
-      return false;
-    }
-
-    inline static bool isLocalToFunc (std::string &Func, std::string &Var) {
-      if (! isLocalName(Var)) return false;
-
-      std::string Func1 = addPrefix(Func);
-      // Extract func name of the varilable.
-      const std::string &fname = getFuncNameForSym(Var);
-
-      if (fname.compare(Func1) == 0)
-        return true;
-
-      return false;
-    }
-
-
-    // Get the section for the given external symbol names.
-    // This tries to find the type (Tag) of the symbol from its mangled name
-    // and return appropriate section name for it.
-    static inline std::string getSectionNameForSym(const std::string &Sym1) {
-      std::string Sym = addPrefix(Sym1);
-
-      std::string SectionName;
-      std::string Fname = getFuncNameForSym (Sym);
-      TAGS id = getSymbolTag (Sym);
-
-      switch (id) {
-        default : assert (0 && "Could not determine external symbol type");
-        case FRAME_LABEL:
-        case RET_LABEL:
-        case TEMPS_LABEL:
-        case ARGS_LABEL:  {
-          return getFrameSectionName(Fname);
-        }
-        case AUTOS_LABEL: {
-          return getAutosSectionName(Fname);
-        }
-      }
-    }
-  }; // class PAN.
-
-
   // External symbol names require memory to live till the program end.
   // So we have to allocate it and keep.
   inline static const char *createESName (const std::string &name) {
index d4cbc0a1c3b082a867cf77e6b6401ddce8bb0408..efcbd9a64c230813ac264b8841b2d755c3b83fef 100644 (file)
@@ -443,6 +443,7 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const {
   case PIC16ISD::SELECT_ICC:       return "PIC16ISD::SELECT_ICC";
   case PIC16ISD::BRCOND:           return "PIC16ISD::BRCOND";
   case PIC16ISD::RET:              return "PIC16ISD::RET";
+  case PIC16ISD::RETFIE:           return "PIC16ISD::RETFIE";
   case PIC16ISD::Dummy:            return "PIC16ISD::Dummy";
   }
 }
@@ -1272,7 +1273,10 @@ PIC16TargetLowering::LowerReturn(SDValue Chain,
                         DAG.getConstant (i, MVT::i8));
       
   }
-  return DAG.getNode(PIC16ISD::RET, dl, MVT::Other, Chain);
+  if (PAN::isISR(F))
+     return DAG.getNode(PIC16ISD::RETFIE, dl, MVT::Other, Chain);
+  else
+     return DAG.getNode(PIC16ISD::RET, dl, MVT::Other, Chain);
 }
 
 void PIC16TargetLowering::
index aee39f0ae378334bb481424576c685be84546903..d8a5aea37a864d2adae5493a9711b403a8e46936 100644 (file)
@@ -53,6 +53,7 @@ namespace llvm {
       SELECT_ICC,    // Psuedo to be caught in schedular and expanded to brcond.
       BRCOND,        // Conditional branch.
       RET,           // Return.
+      RETFIE,        // Return from interrupt
       Dummy
     };
 
index 250ca0a373f21a2a296f630071d829d55dd2c636..659421e50465ae0a7a86a822969273f94f9694a2 100644 (file)
@@ -117,6 +117,7 @@ def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc,
 
 def PIC16ret       : SDNode<"PIC16ISD::RET", SDTNone, [SDNPHasChain]>;
 
+def PIC16Retfie : SDNode<"PIC16ISD::RETFIE", SDTNone, [SDNPHasChain]>;
 //===----------------------------------------------------------------------===//
 // PIC16 Operand Definitions.
 //===----------------------------------------------------------------------===//
@@ -497,6 +498,10 @@ let isTerminator = 1, isBarrier = 1, isReturn = 1 in
 def Return : 
   ControlFormat<0, (outs), (ins), "return", [(PIC16ret)]>;
 
+//Return instruction to return from ISR
+let isTerminator = 1, isBarrier = 1, isReturn = 1 in
+def Retfie : 
+  ControlFormat<0, (outs), (ins), "retfie", [(PIC16Retfie)]>;
 //===----------------------------------------------------------------------===//
 // PIC16 Replacment Patterns.
 //===----------------------------------------------------------------------===//
diff --git a/lib/Target/PIC16/PIC16PAN.h b/lib/Target/PIC16/PIC16PAN.h
new file mode 100644 (file)
index 0000000..cca8f35
--- /dev/null
@@ -0,0 +1,421 @@
+//===-- PIC16PAN.h - PIC16 ABI Naming conventions --*- 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 the entry points for global functions defined in 
+// the LLVM PIC16 back-end.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_PIC16PAN_H
+#define LLVM_TARGET_PIC16PAN_H
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Function.h"
+#include <iosfwd>
+#include <cassert>
+#include <cstring>
+#include <string>
+
+namespace llvm {
+  // A Central class to manage all ABI naming conventions.
+  // PAN - [P]ic16 [A]BI [N]ames
+  class PAN {
+    public:
+    // Map the name of the symbol to its section name.
+    // Current ABI:
+    // -----------------------------------------------------
+    // ALL Names are prefixed with the symobl '@'.
+    // ------------------------------------------------------
+    // Global variables do not have any '.' in their names.
+    // These are maily function names and global variable names.
+    // Example - @foo,  @i
+    // -------------------------------------------------------
+    // Functions and auto variables.
+    // Names are mangled as <prefix><funcname>.<tag>.<varname>
+    // Where <prefix> is '@' and <tag> is any one of
+    // the following
+    // .auto. - an automatic var of a function.
+    // .temp. - temproray data of a function.
+    // .ret.  - return value label for a function.
+    // .frame. - Frame label for a function where retval, args
+    //           and temps are stored.
+    // .args. - Label used to pass arguments to a direct call.
+    // Example - Function name:   @foo
+    //           Its frame:       @foo.frame.
+    //           Its retval:      @foo.ret.
+    //           Its local vars:  @foo.auto.a
+    //           Its temp data:   @foo.temp.
+    //           Its arg passing: @foo.args.
+    //----------------------------------------------
+    // Libcall - compiler generated libcall names must start with .lib.
+    //           This id will be used to emit extern decls for libcalls.
+    // Example - libcall name:   @.lib.sra.i8
+    //           To pass args:   @.lib.sra.i8.args.
+    //           To return val:  @.lib.sra.i8.ret.
+    //----------------------------------------------
+    // SECTION Names
+    // uninitialized globals - @udata.<num>.#
+    // initialized globals - @idata.<num>.#
+    // Function frame - @<func>.frame_section.
+    // Function autos - @<func>.autos_section.
+    // Declarations - Enclosed in comments. No section for them.
+    //----------------------------------------------------------
+    
+    // Tags used to mangle different names. 
+    enum TAGS {
+      PREFIX_SYMBOL,
+      GLOBAL,
+      STATIC_LOCAL,
+      AUTOS_LABEL,
+      FRAME_LABEL,
+      RET_LABEL,
+      ARGS_LABEL,
+      TEMPS_LABEL,
+      
+      LIBCALL,
+      
+      FRAME_SECTION,
+      AUTOS_SECTION,
+      CODE_SECTION
+    };
+    enum CallLine {
+      MainLine,
+      InterruptLine,
+      SharedLine,
+      UnspecifiedLine
+    };
+
+    // Textual names of the tags.
+    inline static const char *getTagName(TAGS tag) {
+      switch (tag) {
+      default: return "";
+      case PREFIX_SYMBOL:    return "@";
+      case AUTOS_LABEL:       return ".auto.";
+      case FRAME_LABEL:       return ".frame.";
+      case TEMPS_LABEL:       return ".temp.";
+      case ARGS_LABEL:       return ".args.";
+      case RET_LABEL:       return ".ret.";
+      case LIBCALL:       return ".lib.";
+      case FRAME_SECTION:       return ".frame_section.";
+      case AUTOS_SECTION:       return ".autos_section.";
+      case CODE_SECTION:       return ".code_section.";
+      }
+    }
+
+    inline static bool isISR(const Function *F) {
+       if (F->getSection().find("interrupt") != std::string::npos)
+         return true; 
+
+       return false;
+    } 
+    inline static bool isInterruptLineFunction(const Function *F) {
+       if (isISR(F)) return true;
+       if (F->getSection().find("IL") != std::string::npos)
+         return true; 
+
+       return false;
+    }
+    inline static bool isMainLineFunction(const Function *F) {
+       if (F->getSection().find("ML") != std::string::npos)
+         return true; 
+
+       return false;
+    }
+    inline static bool isSharedLineFunction(const Function *F) {
+       if (F->getSection().find("SL") != std::string::npos)
+         return true; 
+
+       return false;
+    }
+
+    inline static const char *getUpdatedLibCallDecl(const char *Name, 
+                                              const Function *F) {
+       // If the current function is not an interrupt line function then 
+       // there is no need to change the name.
+       if (!isInterruptLineFunction(F))
+          return Name;
+
+
+       // CAUTION::This code may cause some memory leak and at times
+       // use more memory than required.
+       // (We will try to clean it sometime later)
+
+       // InterruptLine functions should hold ".IL" suffix and
+       char *NewName = (char *)malloc(strlen(Name) + 3 + 1);
+       strcpy(NewName, Name);
+       strcat(NewName, ".IL");
+       return NewName;
+    }
+
+    inline static void updateCallLineAutos(std::string &Sym, std::string FuncName) {
+      // If the function has ".IL" in its name then it must be
+      // a cloned function and autos for such a function should also
+      // have ".IL" in their name. So update them here.
+      if (FuncName.find(".IL") != std::string::npos)
+          Sym.replace(Sym.find(".auto"), 5, ".IL.auto");
+    }
+
+    // Insert ".IL" at proper location in the ARGS and RET symbols
+    inline static void updateCallLineLibcall(std::string &Sym) {
+       std::string SubStr;
+       std::size_t pos;
+       std::string Suffix;
+       if (getSymbolTag(Sym) == ARGS_LABEL) {
+          Suffix = getTagName(ARGS_LABEL);
+          pos = Sym.find(Suffix);
+          SubStr = Sym.substr(0,pos);
+       } else if (getSymbolTag(Sym) == RET_LABEL) {
+          Suffix = getTagName(RET_LABEL);
+          pos = Sym.find(Suffix);
+          SubStr = Sym.substr(0,pos);
+       } else {
+          SubStr = Sym;
+          Suffix = "";
+       }
+       Sym = SubStr + ".IL" + Suffix;
+    }
+
+    inline static void updateCallLineSymbol(std::string &Sym, CallLine CLine) {
+      if (isLIBCALLSymbol(Sym) && CLine == InterruptLine) {
+         updateCallLineLibcall(Sym);
+         return;
+      }
+         
+       // UnMangle the function name - mangled in llvm-ld
+       // For MainLine function the shared string should be removed
+       // and for InterruptLine function the shared string should be 
+       // replaced with ".IL"
+       std::string ReplaceString="";
+       if (CLine == MainLine || CLine == UnspecifiedLine)
+         ReplaceString = "";
+       else if (CLine == InterruptLine)
+         ReplaceString = ".IL";
+       std::string FindString = ".shared";
+       if (Sym.find(FindString) != std::string::npos) {
+         Sym.replace(Sym.find(FindString), FindString.length(), ReplaceString);
+         return;
+       }
+    } 
+
+    inline static void updateCallLineSymbol(std::string &Sym, 
+                                            const Function *F) {
+       // If it is an auto symbol then it should be updated accordingly
+       if (Sym.find(".auto") != std::string::npos) {
+         updateCallLineAutos(Sym, F->getName().str());
+         return;
+       } 
+
+       if (isMainLineFunction(F))
+         updateCallLineSymbol(Sym, MainLine);
+       else if (isInterruptLineFunction(F))
+         updateCallLineSymbol(Sym, InterruptLine);
+       else
+         updateCallLineSymbol(Sym, UnspecifiedLine);
+    }
+
+    inline static bool isLIBCALLSymbol(const std::string &Sym) {
+      if (Sym.find(getTagName(LIBCALL)) != std::string::npos)
+        return true;
+     
+      return false;
+    }
+
+    // Get tag type for the Symbol.
+    inline static TAGS getSymbolTag(const std::string &Sym) {
+      if (Sym.find(getTagName(TEMPS_LABEL)) != std::string::npos)
+        return TEMPS_LABEL;
+
+      if (Sym.find(getTagName(FRAME_LABEL)) != std::string::npos)
+        return FRAME_LABEL;
+
+      if (Sym.find(getTagName(RET_LABEL)) != std::string::npos)
+        return RET_LABEL;
+
+      if (Sym.find(getTagName(ARGS_LABEL)) != std::string::npos)
+        return ARGS_LABEL;
+
+      if (Sym.find(getTagName(AUTOS_LABEL)) != std::string::npos)
+        return AUTOS_LABEL;
+
+      if (Sym.find(getTagName(LIBCALL)) != std::string::npos)
+        return LIBCALL;
+
+      // It does not have any Tag. So its a true global or static local.
+      if (Sym.find(".") == std::string::npos) 
+        return GLOBAL;
+      
+      // If a . is there, then it may be static local.
+      // We should mangle these as well in clang.
+      if (Sym.find(".") != std::string::npos) 
+        return STATIC_LOCAL;
+      assert (0 && "Could not determine Symbol's tag");
+      return PREFIX_SYMBOL; // Silence warning when assertions are turned off.
+    }
+
+    // addPrefix - add prefix symbol to a name if there isn't one already.
+    inline static std::string addPrefix (const std::string &Name) {
+      std::string prefix = getTagName (PREFIX_SYMBOL);
+
+      // If this name already has a prefix, nothing to do.
+      if (Name.compare(0, prefix.size(), prefix) == 0)
+        return Name;
+
+      return prefix + Name;
+    }
+
+    // Get mangled func name from a mangled sym name.
+    // In all cases func name is the first component before a '.'.
+    static inline std::string getFuncNameForSym(const std::string &Sym1) {
+      assert (getSymbolTag(Sym1) != GLOBAL && "not belongs to a function");
+
+      std::string Sym = addPrefix(Sym1);
+
+      // Position of the . after func name. That's where func name ends.
+      size_t func_name_end = Sym.find ('.');
+
+      return Sym.substr (0, func_name_end);
+    }
+
+    // Get Frame start label for a func.
+    static std::string getFrameLabel(const std::string &Func) {
+      std::string Func1 = addPrefix(Func);
+      std::string tag = getTagName(FRAME_LABEL);
+      return Func1 + tag;
+    }
+
+    static std::string getRetvalLabel(const std::string &Func) {
+      std::string Func1 = addPrefix(Func);
+      std::string tag = getTagName(RET_LABEL);
+      return Func1 + tag;
+    }
+
+    static std::string getArgsLabel(const std::string &Func) {
+      std::string Func1 = addPrefix(Func);
+      std::string tag = getTagName(ARGS_LABEL);
+      return Func1 + tag;
+    }
+
+    static std::string getTempdataLabel(const std::string &Func) {
+      std::string Func1 = addPrefix(Func);
+      std::string tag = getTagName(TEMPS_LABEL);
+      return Func1 + tag;
+    }
+
+    static std::string getFrameSectionName(const std::string &Func) {
+      std::string Func1 = addPrefix(Func);
+      std::string tag = getTagName(FRAME_SECTION);
+      return Func1 + tag + "# UDATA_OVR";
+    }
+
+    static std::string getAutosSectionName(const std::string &Func) {
+      std::string Func1 = addPrefix(Func);
+      std::string tag = getTagName(AUTOS_SECTION);
+      return Func1 + tag + "# UDATA_OVR";
+    }
+
+    static std::string getCodeSectionName(const std::string &Func, bool isInterrupt) {
+      std::string Func1 = addPrefix(Func);
+      std::string tag = getTagName(CODE_SECTION);
+      std::string Name = Func1 + tag + "# CODE";
+
+      // If this is an interrupt function then the code section should
+      // be placed at address 0x4 (hard)
+      if (isInterrupt)
+         Name += "    0x4";
+
+      return Name;
+    }
+
+    // udata, romdata and idata section names are generated by a given number.
+    // @udata.<num>.# 
+    static std::string getUdataSectionName(unsigned num, 
+                                           std::string prefix = "") {
+       std::ostringstream o;
+       o << getTagName(PREFIX_SYMBOL) << prefix << "udata." << num 
+         << ".# UDATA"; 
+       return o.str(); 
+    }
+
+    static std::string getRomdataSectionName(unsigned num,
+                                             std::string prefix = "") {
+       std::ostringstream o;
+       o << getTagName(PREFIX_SYMBOL) << prefix << "romdata." << num 
+         << ".# ROMDATA";
+       return o.str();
+    }
+
+    static std::string getIdataSectionName(unsigned num,
+                                           std::string prefix = "") {
+       std::ostringstream o;
+       o << getTagName(PREFIX_SYMBOL) << prefix << "idata." << num 
+         << ".# IDATA"; 
+       return o.str(); 
+    }
+
+    inline static bool isLocalName (const std::string &Name) {
+      if (getSymbolTag(Name) == AUTOS_LABEL)
+        return true;
+
+      return false;
+    }
+
+    inline static bool isMemIntrinsic (const std::string &Name) {
+      if (Name.compare("@memcpy") == 0 || Name.compare("@memset") == 0 ||
+          Name.compare("@memmove") == 0) {
+        return true;
+      }
+      
+      return false;
+    }
+
+    inline static bool isLocalToFunc (std::string &Func, std::string &Var) {
+      if (! isLocalName(Var)) return false;
+
+      std::string Func1 = addPrefix(Func);
+      // Extract func name of the varilable.
+      const std::string &fname = getFuncNameForSym(Var);
+
+      if (fname.compare(Func1) == 0)
+        return true;
+
+      return false;
+    }
+
+
+    // Get the section for the given external symbol names.
+    // This tries to find the type (Tag) of the symbol from its mangled name
+    // and return appropriate section name for it.
+    static inline std::string getSectionNameForSym(const std::string &Sym1) {
+      std::string Sym = addPrefix(Sym1);
+
+      std::string SectionName;
+      std::string Fname = getFuncNameForSym (Sym);
+      TAGS id = getSymbolTag (Sym);
+
+      switch (id) {
+        default : assert (0 && "Could not determine external symbol type");
+        case FRAME_LABEL:
+        case RET_LABEL:
+        case TEMPS_LABEL:
+        case ARGS_LABEL:  {
+          return getFrameSectionName(Fname);
+        }
+        case AUTOS_LABEL: {
+          return getAutosSectionName(Fname);
+        }
+      }
+    }
+  }; // class PAN.
+
+} // end namespace llvm;
+
+#endif
index 07d8381800a1ad0960a1a6daf61ba06b821690d6..3ff27a9ae7f3ae86e7ef3926a694a1575a3d1e5d 100644 (file)
@@ -70,8 +70,8 @@ void PIC16TargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &tm){
 }
 
 const MCSection *PIC16TargetObjectFile::
-getSectionForFunction(const std::string &FnName) const {
-  std::string T = PAN::getCodeSectionName(FnName);
+getSectionForFunction(const std::string &FnName, bool isInterrupt) const {
+  std::string T = PAN::getCodeSectionName(FnName, isInterrupt);
   return getPIC16Section(T.c_str(), SectionKind::getText());
 }
 
@@ -196,6 +196,48 @@ PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable *GV) const {
   return FoundAutoSec->S_;
 }
 
+void PIC16TargetObjectFile::createClonedSectionForAutos(const std::string &SecName) {
+
+  // If the function is cloned then it will have ".IL" in its name
+  // If this function is not cloned then return;
+  if (SecName.find(".IL") == std::string::npos) 
+      return;
+
+  // Come here if the function is cloned.
+  // Get the name of the original section from which it has been cloned.
+  std::string OrigName = SecName;
+  OrigName.replace(SecName.find(".IL"),3,"");
+
+  // Find original section
+  PIC16Section *FoundAutoSec = NULL;
+  for (unsigned i = 0; i < AutosSections.size(); i++) {
+    if (AutosSections[i]->S_->getName() == OrigName) {
+      FoundAutoSec = AutosSections[i];
+      break; 
+    }
+  }
+
+  // No auto section exists for the original function.
+  if (!FoundAutoSec)
+    return;
+
+  // Create new section for the cloned function 
+  const MCSectionPIC16 *NewSection =
+      getPIC16Section(SecName.c_str(), SectionKind::getMetadata());
+  
+  PIC16Section *NewAutoSec = new PIC16Section(NewSection);
+  // Add this newly created autos section to the list of AutosSections.
+  AutosSections.push_back(NewAutoSec);
+
+  // Add the items from the original section to the new section
+  // Donot mangle them here. Because mangling them here will distort 
+  // the original names. 
+  // These names will be mangled them at the time of printing only
+  const std::vector<const GlobalVariable*> &Items = FoundAutoSec->Items;
+  for (unsigned j = 0; j < Items.size(); j++) {
+    NewAutoSec->Items.push_back(Items[j]); 
+  }
+}
 
 // Override default implementation to put the true globals into
 // multiple data sections if required.
index 1c6d9cf3884bc89b7c46dc27725c708b8e4c49fb..4676b3c8d6f922e540852e3aa98f6a520e138ff4 100644 (file)
@@ -77,10 +77,13 @@ namespace llvm {
                                                     Mangler *Mang,
                                                     const TargetMachine&) const;
 
-    const MCSection *getSectionForFunction(const std::string &FnName) const;
+    const MCSection *getSectionForFunction(const std::string &FnName, 
+                                           bool isInterrupt=false) const;
     const MCSection *getSectionForFunctionFrame(const std::string &FnName)const;
     
-    
+    // If the current function is cloned then create the new autos section
+    // also. 
+    void createClonedSectionForAutos(const std::string &SecName);
   private:
     std::string getSectionNameForSym(const std::string &Sym) const;