mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-11-04 05:17:07 +00:00 
			
		
		
		
	Renamed PIC16FrameOverlay namespace to PIC16OVERLAY. Renamed PIC16FrameOverlay class to PIC16Overlay. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@96463 91177308-0d34-0410-b5e6-96231b3b80d8
		
			
				
	
	
		
			182 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			182 lines
		
	
	
		
			5.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//===-- PIC16Overlay.cpp - Implementation for PIC16 Frame Overlay===//
 | 
						|
//
 | 
						|
//                     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 PIC16 Frame Overlay implementation.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
 | 
						|
#include "llvm/Analysis/CallGraph.h"
 | 
						|
#include "llvm/Pass.h"
 | 
						|
#include "llvm/Module.h"
 | 
						|
#include "llvm/Instructions.h"
 | 
						|
#include "llvm/Value.h"
 | 
						|
#include "PIC16Overlay.h"
 | 
						|
#include "llvm/Function.h"
 | 
						|
#include <cstdlib>
 | 
						|
#include <sstream>
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
namespace llvm {
 | 
						|
  char PIC16Overlay::ID = 0;
 | 
						|
  ModulePass *createPIC16OverlayPass() { return new PIC16Overlay(); }
 | 
						|
}
 | 
						|
 | 
						|
void PIC16Overlay::getAnalysisUsage(AnalysisUsage &AU) const {
 | 
						|
  AU.setPreservesAll();
 | 
						|
  AU.addRequired<CallGraph>();
 | 
						|
}
 | 
						|
 | 
						|
void PIC16Overlay::DFSTraverse(CallGraphNode *CGN, unsigned Depth) {
 | 
						|
  // Do not set any color for external calling node.
 | 
						|
  if (Depth != 0 && CGN->getFunction()) {
 | 
						|
    unsigned Color = getColor(CGN->getFunction());
 | 
						|
 | 
						|
    // Handle indirectly called functions
 | 
						|
    if (Color >= PIC16OVERLAY::StartIndirectCallColor || 
 | 
						|
        Depth >= PIC16OVERLAY::StartIndirectCallColor) {
 | 
						|
      // All functions called from an indirectly called function are given
 | 
						|
      // an unique color.
 | 
						|
      if (Color < PIC16OVERLAY::StartIndirectCallColor &&
 | 
						|
          Depth >= PIC16OVERLAY::StartIndirectCallColor)
 | 
						|
        setColor(CGN->getFunction(), Depth);
 | 
						|
 | 
						|
      for (unsigned int i = 0; i < CGN->size(); i++)
 | 
						|
        DFSTraverse((*CGN)[i], ++IndirectCallColor);
 | 
						|
      return;
 | 
						|
    }
 | 
						|
    // Just return if the node already has a color greater than the current 
 | 
						|
    // depth. A node must be colored with the maximum depth that it has.
 | 
						|
    if (Color >= Depth)
 | 
						|
      return;
 | 
						|
    
 | 
						|
    Depth = ModifyDepthForInterrupt(CGN, Depth);  
 | 
						|
    setColor(CGN->getFunction(), Depth);
 | 
						|
  }
 | 
						|
  
 | 
						|
  // Color all children of this node with color depth+1.
 | 
						|
  for (unsigned int i = 0; i < CGN->size(); i++)
 | 
						|
    DFSTraverse((*CGN)[i], Depth+1);
 | 
						|
}
 | 
						|
 | 
						|
unsigned PIC16Overlay::ModifyDepthForInterrupt(CallGraphNode *CGN,
 | 
						|
                                                    unsigned Depth) {
 | 
						|
  Function *Fn = CGN->getFunction();
 | 
						|
 | 
						|
  // Return original Depth if function or section for function do not exist.
 | 
						|
  if (!Fn || !Fn->hasSection())
 | 
						|
    return Depth;
 | 
						|
 | 
						|
  // Return original Depth if this function is not marked as interrupt.
 | 
						|
  if (Fn->getSection().find("interrupt") == string::npos)
 | 
						|
    return Depth;
 | 
						|
 | 
						|
  Depth = Depth + InterruptDepth;
 | 
						|
  return Depth;
 | 
						|
}
 | 
						|
 | 
						|
void PIC16Overlay::setColor(Function *Fn, unsigned Color) {
 | 
						|
  std::string Section = "";
 | 
						|
  if (Fn->hasSection())
 | 
						|
    Section = Fn->getSection();
 | 
						|
 | 
						|
  size_t Pos = Section.find(OverlayStr);
 | 
						|
 | 
						|
  // Convert Color to string.
 | 
						|
  std::stringstream ss;
 | 
						|
  ss << Color;
 | 
						|
  std::string ColorString = ss.str();
 | 
						|
 | 
						|
  // If color is already set then reset it with the new value. Else append 
 | 
						|
  // the Color string to section.
 | 
						|
  if (Pos != std::string::npos) {
 | 
						|
    Pos += OverlayStr.length();
 | 
						|
    char c = Section.at(Pos);
 | 
						|
    unsigned OldColorLength = 0;  
 | 
						|
    while (c >= '0' && c<= '9') {
 | 
						|
      OldColorLength++;    
 | 
						|
      if (Pos < Section.length() - 1)
 | 
						|
        Pos++;
 | 
						|
      else
 | 
						|
        break;
 | 
						|
      c = Section.at(Pos);
 | 
						|
    }
 | 
						|
    // Replace old color with new one.
 | 
						|
    Section.replace(Pos-OldColorLength +1, OldColorLength, ColorString); 
 | 
						|
  }
 | 
						|
  else {
 | 
						|
    // Append Color information to section string.
 | 
						|
    if (Fn->hasSection())
 | 
						|
      Section.append(" ");
 | 
						|
    Section.append(OverlayStr + ColorString);
 | 
						|
  }
 | 
						|
  Fn->setSection(Section);
 | 
						|
}
 | 
						|
 | 
						|
unsigned PIC16Overlay::getColor(Function *Fn) {
 | 
						|
  int Color = 0;
 | 
						|
  if (!Fn->hasSection())
 | 
						|
    return 0;
 | 
						|
 | 
						|
  std::string Section = Fn->getSection();
 | 
						|
  size_t Pos = Section.find(OverlayStr);
 | 
						|
  
 | 
						|
  // Return 0 if Color is not set.
 | 
						|
  if (Pos == std::string::npos)
 | 
						|
    return 0;
 | 
						|
 | 
						|
  // Set Pos to after "Overlay=".
 | 
						|
  Pos += OverlayStr.length();
 | 
						|
  char c = Section.at(Pos);
 | 
						|
  std::string ColorString = "";
 | 
						|
 | 
						|
  // Find the string representing Color. A Color can only consist of digits.
 | 
						|
  while (c >= '0' && c<= '9') { 
 | 
						|
    ColorString.append(1,c);
 | 
						|
    if (Pos < Section.length() - 1)
 | 
						|
      Pos++;
 | 
						|
    else
 | 
						|
      break;
 | 
						|
    c = Section.at(Pos);
 | 
						|
  }
 | 
						|
  Color = atoi(ColorString.c_str());
 | 
						|
  
 | 
						|
  return Color;    
 | 
						|
}
 | 
						|
 | 
						|
bool PIC16Overlay::runOnModule(Module &M) {
 | 
						|
  CallGraph &CG = getAnalysis<CallGraph>();
 | 
						|
  CallGraphNode *ECN = CG.getExternalCallingNode();
 | 
						|
 | 
						|
  MarkIndirectlyCalledFunctions(M); 
 | 
						|
  // Since External Calling Node is the base function, do a depth first 
 | 
						|
  // traversal of CallGraph with ECN as root. Each node with be marked with 
 | 
						|
  // a color that is max(color(callers)) + 1.
 | 
						|
  if(ECN) {
 | 
						|
    DFSTraverse(ECN, 0);
 | 
						|
  }
 | 
						|
  return false;
 | 
						|
}
 | 
						|
 | 
						|
void PIC16Overlay::MarkIndirectlyCalledFunctions(Module &M) {
 | 
						|
  // If the use of a function is not a call instruction then this
 | 
						|
  // function might be called indirectly. In that case give it
 | 
						|
  // an unique color.
 | 
						|
  for (Module::iterator MI = M.begin(), E = M.end(); MI != E; ++MI) {
 | 
						|
    for (Value::use_iterator I = MI->use_begin(), E = MI->use_end(); I != E;
 | 
						|
         ++I) {
 | 
						|
      if ((!isa<CallInst>(I) && !isa<InvokeInst>(I))
 | 
						|
          || !CallSite(cast<Instruction>(I)).isCallee(I)) {
 | 
						|
        setColor(MI, ++IndirectCallColor);
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 |