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