blob: 197c3987d29666246c45334805d13e14c6f2581f [file] [log] [blame]
Sanjiv Gupta00e8f5a2009-10-21 10:42:44 +00001//===-- PIC16Overlay.cpp - Implementation for PIC16 Frame Overlay===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains the PIC16 Frame Overlay implementation.
11//
12//===----------------------------------------------------------------------===//
13
14
15#include "llvm/Analysis/CallGraph.h"
16#include "llvm/Pass.h"
17#include "llvm/Module.h"
18#include "llvm/Instructions.h"
19#include "llvm/Value.h"
20#include "PIC16Overlay.h"
21#include "llvm/Function.h"
22#include <cstdlib>
23#include <sstream>
24using namespace llvm;
25
26namespace llvm {
27 char PIC16FrameOverlay::ID = 0;
Anton Korobeynikovb9839c62009-10-26 18:40:24 +000028 ModulePass *createPIC16OverlayPass() { return new PIC16FrameOverlay(); }
Sanjiv Gupta00e8f5a2009-10-21 10:42:44 +000029}
30
31void PIC16FrameOverlay::getAnalysisUsage(AnalysisUsage &AU) const {
32 AU.setPreservesAll();
33 AU.addRequired<CallGraph>();
34}
35
36void PIC16FrameOverlay::DFSTraverse(CallGraphNode *CGN, unsigned Depth) {
37 // Do not set any color for external calling node.
38 if (Depth != 0 && CGN->getFunction()) {
39 unsigned Color = getColor(CGN->getFunction());
40
41 // Handle indirectly called functions
42 if (Color >= PIC16Overlay::StartIndirectCallColor ||
43 Depth >= PIC16Overlay::StartIndirectCallColor) {
44 // All functions called from an indirectly called function are given
45 // an unique color.
46 if (Color < PIC16Overlay::StartIndirectCallColor &&
47 Depth >= PIC16Overlay::StartIndirectCallColor)
48 setColor(CGN->getFunction(), Depth);
49
50 for (unsigned int i = 0; i < CGN->size(); i++)
51 DFSTraverse((*CGN)[i], ++IndirectCallColor);
52 return;
53 }
54 // Just return if the node already has a color greater than the current
55 // depth. A node must be colored with the maximum depth that it has.
56 if (Color >= Depth)
57 return;
58
59 Depth = ModifyDepthForInterrupt(CGN, Depth);
60 setColor(CGN->getFunction(), Depth);
61 }
62
63 // Color all children of this node with color depth+1.
64 for (unsigned int i = 0; i < CGN->size(); i++)
65 DFSTraverse((*CGN)[i], Depth+1);
66}
67
68unsigned PIC16FrameOverlay::ModifyDepthForInterrupt(CallGraphNode *CGN,
69 unsigned Depth) {
70 Function *Fn = CGN->getFunction();
71
72 // Return original Depth if function or section for function do not exist.
73 if (!Fn || !Fn->hasSection())
74 return Depth;
75
76 // Return original Depth if this function is not marked as interrupt.
77 if (Fn->getSection().find("interrupt") == string::npos)
78 return Depth;
79
80 Depth = Depth + InterruptDepth;
81 return Depth;
82}
83
84void PIC16FrameOverlay::setColor(Function *Fn, unsigned Color) {
85 std::string Section = "";
86 if (Fn->hasSection())
87 Section = Fn->getSection();
88
89 size_t Pos = Section.find(OverlayStr);
90
91 // Convert Color to string.
92 std::stringstream ss;
93 ss << Color;
94 std::string ColorString = ss.str();
95
96 // If color is already set then reset it with the new value. Else append
97 // the Color string to section.
98 if (Pos != std::string::npos) {
99 Pos += OverlayStr.length();
100 char c = Section.at(Pos);
101 unsigned OldColorLength = 0;
102 while (c >= '0' && c<= '9') {
103 OldColorLength++;
104 if (Pos < Section.length() - 1)
105 Pos++;
106 else
107 break;
108 c = Section.at(Pos);
109 }
110 // Replace old color with new one.
111 Section.replace(Pos-OldColorLength +1, OldColorLength, ColorString);
112 }
113 else {
114 // Append Color information to section string.
115 if (Fn->hasSection())
116 Section.append(" ");
117 Section.append(OverlayStr + ColorString);
118 }
119 Fn->setSection(Section);
120}
121
122unsigned PIC16FrameOverlay::getColor(Function *Fn) {
123 int Color = 0;
124 if (!Fn->hasSection())
125 return 0;
126
127 std::string Section = Fn->getSection();
128 size_t Pos = Section.find(OverlayStr);
129
130 // Return 0 if Color is not set.
131 if (Pos == std::string::npos)
132 return 0;
133
134 // Set Pos to after "Overlay=".
135 Pos += OverlayStr.length();
136 char c = Section.at(Pos);
137 std::string ColorString = "";
138
139 // Find the string representing Color. A Color can only consist of digits.
140 while (c >= '0' && c<= '9') {
141 ColorString.append(1,c);
142 if (Pos < Section.length() - 1)
143 Pos++;
144 else
145 break;
146 c = Section.at(Pos);
147 }
148 Color = atoi(ColorString.c_str());
149
150 return Color;
151}
152
153bool PIC16FrameOverlay::runOnModule(Module &M) {
154 CallGraph &CG = getAnalysis<CallGraph>();
155 CallGraphNode *ECN = CG.getExternalCallingNode();
156
157 MarkIndirectlyCalledFunctions(M);
158 // Since External Calling Node is the base function, do a depth first
159 // traversal of CallGraph with ECN as root. Each node with be marked with
160 // a color that is max(color(callers)) + 1.
161 if(ECN) {
162 DFSTraverse(ECN, 0);
163 }
164 return false;
165}
166
167void PIC16FrameOverlay::MarkIndirectlyCalledFunctions(Module &M) {
168 // If the use of a function is not a call instruction then this
169 // function might be called indirectly. In that case give it
170 // an unique color.
171 for (Module::iterator MI = M.begin(), E = M.end(); MI != E; ++MI) {
172 for (Value::use_iterator I = MI->use_begin(), E = MI->use_end(); I != E;
173 ++I) {
174 if ((!isa<CallInst>(I) && !isa<InvokeInst>(I))
175 || !CallSite(cast<Instruction>(I)).isCallee(I)) {
176 setColor(MI, ++IndirectCallColor);
177 break;
178 }
179 }
180 }
181}