mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-11-01 15:11:24 +00:00
Add a pass to overlay pic16 data sections for function frame and automatic
variables. This pass can be invoked by llvm-ld or opt to traverse over the call graph to detect what function frames and their automatic variables can be overlaid. Currently this builds an archive , but needs to be changed to a loadable module. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@84753 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
db1d9dbdd7
commit
4e4bba5c80
@ -53,6 +53,45 @@ bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static int getFunctionColor(const Function *F) {
|
||||
if (F->hasSection()) {
|
||||
std::string Sectn = F->getSection();
|
||||
std::string StrToFind = "Overlay=";
|
||||
unsigned Pos = Sectn.find(StrToFind);
|
||||
|
||||
// Retreive the color number if the key is found.
|
||||
if (Pos != std::string::npos) {
|
||||
Pos += StrToFind.length();
|
||||
std::string Color = "";
|
||||
char c = Sectn.at(Pos);
|
||||
// A Color can only consist of digits.
|
||||
while (c >= '0' && c<= '9') {
|
||||
Color.append(1,c);
|
||||
Pos++;
|
||||
if (Pos >= Sectn.length())
|
||||
break;
|
||||
c = Sectn.at(Pos);
|
||||
}
|
||||
return atoi(Color.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
// Color was not set for function, so return -1.
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Color the Auto section of the given function.
|
||||
void PIC16AsmPrinter::ColorAutoSection(const Function *F) {
|
||||
std::string SectionName = PAN::getAutosSectionName(CurrentFnName);
|
||||
PIC16Section* Section = PTOF->findPIC16Section(SectionName);
|
||||
if (Section != NULL) {
|
||||
int Color = getFunctionColor(F);
|
||||
if (Color >= 0)
|
||||
Section->setColor(Color);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// runOnMachineFunction - This emits the frame section, autos section and
|
||||
/// assembly for each instruction. Also takes care of function begin debug
|
||||
/// directive and file begin debug directive (if required) for the function.
|
||||
@ -68,6 +107,9 @@ bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
||||
const Function *F = MF.getFunction();
|
||||
CurrentFnName = Mang->getMangledName(F);
|
||||
|
||||
// Put the color information from function to its auto section.
|
||||
ColorAutoSection(F);
|
||||
|
||||
// Emit the function frame (args and temps).
|
||||
EmitFunctionFrame(MF);
|
||||
|
||||
@ -255,7 +297,6 @@ bool PIC16AsmPrinter::doInitialization(Module &M) {
|
||||
EmitDefinedVars(M);
|
||||
EmitIData(M);
|
||||
EmitUData(M);
|
||||
EmitAllAutos(M);
|
||||
EmitRomData(M);
|
||||
EmitUserSections(M);
|
||||
return Result;
|
||||
@ -330,6 +371,7 @@ void PIC16AsmPrinter::EmitRomData(Module &M) {
|
||||
}
|
||||
|
||||
bool PIC16AsmPrinter::doFinalization(Module &M) {
|
||||
EmitAllAutos(M);
|
||||
printLibcallDecls();
|
||||
DbgInfo.EndModule(M);
|
||||
O << "\n\t" << "END\n";
|
||||
@ -343,8 +385,10 @@ void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
|
||||
// Emit the data section name.
|
||||
O << "\n";
|
||||
|
||||
const MCSection *fPDataSection =
|
||||
getObjFileLowering().SectionForFrame(CurrentFnName);
|
||||
PIC16Section *fPDataSection = const_cast<PIC16Section *>(getObjFileLowering().
|
||||
SectionForFrame(CurrentFnName));
|
||||
|
||||
fPDataSection->setColor(getFunctionColor(F));
|
||||
OutStreamer.SwitchSection(fPDataSection);
|
||||
|
||||
// Emit function frame label
|
||||
|
@ -63,6 +63,7 @@ namespace llvm {
|
||||
void EmitSingleSection(const PIC16Section *S);
|
||||
void EmitSectionList(Module &M,
|
||||
const std::vector< PIC16Section *> &SList);
|
||||
void ColorAutoSection(const Function *F);
|
||||
protected:
|
||||
bool doInitialization(Module &M);
|
||||
bool doFinalization(Module &M);
|
||||
|
@ -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
|
||||
|
||||
|
@ -304,6 +304,21 @@ namespace llvm {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return Overlay Name for the section.
|
||||
/// The ABI Convention is: @<Color>.##.<section_tag>
|
||||
/// The section_tag is retrieved from the SectName parameter and
|
||||
/// and Color is passed in parameter.
|
||||
static inline std::string getOverlayName(std::string SectName, int Color) {
|
||||
// FIXME: Only autos_section and frame_section are colored.
|
||||
// So check and assert if the passed SectName does not have AUTOS_SECTION
|
||||
// or FRAME_SECTION tag in it.
|
||||
std::ostringstream o;
|
||||
o << getTagName(PREFIX_SYMBOL) << Color << ".##"
|
||||
<< SectName.substr(SectName.find("."));
|
||||
|
||||
return o.str();
|
||||
}
|
||||
}; // class PAN.
|
||||
} // end namespace llvm;
|
||||
|
||||
|
17
lib/Target/PIC16/PIC16Passes/Makefile
Normal file
17
lib/Target/PIC16/PIC16Passes/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
##===- lib/Target/PIC16/PIC16Passes/Makefile -----------*- Makefile -*-===##
|
||||
#
|
||||
# The LLVM Compiler Infrastructure
|
||||
#
|
||||
# This file is distributed under the University of Illinois Open Source
|
||||
# License. See LICENSE.TXT for details.
|
||||
#
|
||||
##===----------------------------------------------------------------------===##
|
||||
LEVEL = ../../../..
|
||||
TARGET = PIC16
|
||||
LIBRARYNAME = LLVMpic16passes
|
||||
BUILD_ARCHIVE = 1
|
||||
|
||||
|
||||
|
||||
include $(LEVEL)/Makefile.common
|
||||
|
181
lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp
Normal file
181
lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp
Normal file
@ -0,0 +1,181 @@
|
||||
//===-- 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 PIC16FrameOverlay::ID = 0;
|
||||
ModulePass *createPIC16OverlayPass() { return new PIC16FrameOverlay(); }
|
||||
}
|
||||
|
||||
void PIC16FrameOverlay::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||
AU.setPreservesAll();
|
||||
AU.addRequired<CallGraph>();
|
||||
}
|
||||
|
||||
void PIC16FrameOverlay::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 PIC16FrameOverlay::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 PIC16FrameOverlay::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 PIC16FrameOverlay::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 PIC16FrameOverlay::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 PIC16FrameOverlay::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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
55
lib/Target/PIC16/PIC16Passes/PIC16Overlay.h
Normal file
55
lib/Target/PIC16/PIC16Passes/PIC16Overlay.h
Normal file
@ -0,0 +1,55 @@
|
||||
//===-- PIC16FrameOverlay.h - Interface for PIC16 Frame Overlay -*- 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 PIC16 Overlay infrastructure.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef PIC16FRAMEOVERLAY_H
|
||||
#define PIC16FRAMEOVERLAY_H
|
||||
|
||||
#include "llvm/Analysis/CallGraph.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/CallGraphSCCPass.h"
|
||||
|
||||
using std::string;
|
||||
using namespace llvm;
|
||||
|
||||
namespace llvm {
|
||||
namespace PIC16Overlay {
|
||||
enum OverlayConsts {
|
||||
StartInterruptColor = 200,
|
||||
StartIndirectCallColor = 300
|
||||
};
|
||||
}
|
||||
class PIC16FrameOverlay : public ModulePass {
|
||||
std::string OverlayStr;
|
||||
unsigned InterruptDepth;
|
||||
unsigned IndirectCallColor;
|
||||
public:
|
||||
static char ID; // Class identification
|
||||
PIC16FrameOverlay() : ModulePass(&ID) {
|
||||
OverlayStr = "Overlay=";
|
||||
InterruptDepth = PIC16Overlay::StartInterruptColor;
|
||||
IndirectCallColor = PIC16Overlay::StartIndirectCallColor;
|
||||
}
|
||||
|
||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||
virtual bool runOnModule(Module &M);
|
||||
|
||||
private:
|
||||
unsigned getColor(Function *Fn);
|
||||
void setColor(Function *Fn, unsigned Color);
|
||||
unsigned ModifyDepthForInterrupt(CallGraphNode *CGN, unsigned Depth);
|
||||
void MarkIndirectlyCalledFunctions(Module &M);
|
||||
void DFSTraverse(CallGraphNode *CGN, unsigned Depth);
|
||||
};
|
||||
} // End of namespace
|
||||
|
||||
#endif
|
@ -68,8 +68,13 @@ PIC16Section *PIC16Section::Create(const StringRef &Name,
|
||||
// A generic way to print all types of sections.
|
||||
void PIC16Section::PrintSwitchToSection(const MCAsmInfo &MAI,
|
||||
raw_ostream &OS) const {
|
||||
// Print name.
|
||||
OS << getName() << '\t';
|
||||
|
||||
// If the section is overlaid(i.e. it has a color), print overlay name for
|
||||
// it. Otherwise print its normal name.
|
||||
if (Color != -1)
|
||||
OS << PAN::getOverlayName(getName(), Color) << '\t';
|
||||
else
|
||||
OS << getName() << '\t';
|
||||
|
||||
// Print type.
|
||||
switch (getType()) {
|
||||
|
@ -57,6 +57,7 @@ namespace llvm {
|
||||
|
||||
/// Return the Color of the section.
|
||||
int getColor() const { return Color; }
|
||||
void setColor(int color) { Color = color; }
|
||||
|
||||
/// Return the size of the section.
|
||||
unsigned getSize() const { return Size; }
|
||||
|
@ -25,6 +25,18 @@ PIC16TargetObjectFile::PIC16TargetObjectFile() {
|
||||
PIC16TargetObjectFile::~PIC16TargetObjectFile() {
|
||||
}
|
||||
|
||||
/// Find a pic16 section. Return null if not found. Do not create one.
|
||||
PIC16Section *PIC16TargetObjectFile::
|
||||
findPIC16Section(const std::string &Name) {
|
||||
/// Return if we have an already existing one.
|
||||
PIC16Section *Entry = SectionsByName[Name];
|
||||
if (Entry)
|
||||
return Entry;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/// Find a pic16 section. If not found, create one.
|
||||
PIC16Section *PIC16TargetObjectFile::
|
||||
getPIC16Section(const std::string &Name, PIC16SectionType Ty,
|
||||
|
@ -116,6 +116,9 @@ namespace llvm {
|
||||
~PIC16TargetObjectFile();
|
||||
void Initialize(MCContext &Ctx, const TargetMachine &TM);
|
||||
|
||||
/// Return the section with the given Name. Null if not found.
|
||||
PIC16Section *findPIC16Section(const std::string &Name);
|
||||
|
||||
/// Override section allocations for user specified sections.
|
||||
virtual const MCSection *
|
||||
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
|
||||
@ -127,6 +130,7 @@ namespace llvm {
|
||||
Mangler *Mang,
|
||||
const TargetMachine&) const;
|
||||
|
||||
|
||||
/// Return a code section for a function.
|
||||
const PIC16Section *SectionForCode (const std::string &FnName) const;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user