summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Target/PIC16
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/Target/PIC16')
-rw-r--r--contrib/llvm/lib/Target/PIC16/AsmPrinter/CMakeLists.txt9
-rw-r--r--contrib/llvm/lib/Target/PIC16/AsmPrinter/Makefile15
-rw-r--r--contrib/llvm/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp512
-rw-r--r--contrib/llvm/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h88
-rw-r--r--contrib/llvm/lib/Target/PIC16/CMakeLists.txt26
-rw-r--r--contrib/llvm/lib/Target/PIC16/Makefile24
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16.h137
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16.td40
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16ABINames.h399
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16DebugInfo.cpp490
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16DebugInfo.h156
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp50
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16ISelDAGToDAG.h60
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp1986
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.h246
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16InstrFormats.td117
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.cpp244
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.h81
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.td540
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16MCAsmInfo.cpp59
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16MCAsmInfo.h35
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16MachineFunctionInfo.h52
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16MemSelOpt.cpp254
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Passes/Makefile15
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp299
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h83
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp181
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Overlay.h60
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.cpp94
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.h69
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.td33
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Section.cpp104
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Section.h99
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16SelectionDAGInfo.cpp23
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16SelectionDAGInfo.h31
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Subtarget.cpp27
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16Subtarget.h44
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16TargetMachine.cpp55
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16TargetMachine.h70
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp384
-rw-r--r--contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.h168
-rw-r--r--contrib/llvm/lib/Target/PIC16/TargetInfo/CMakeLists.txt7
-rw-r--r--contrib/llvm/lib/Target/PIC16/TargetInfo/Makefile15
-rw-r--r--contrib/llvm/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp22
44 files changed, 7503 insertions, 0 deletions
diff --git a/contrib/llvm/lib/Target/PIC16/AsmPrinter/CMakeLists.txt b/contrib/llvm/lib/Target/PIC16/AsmPrinter/CMakeLists.txt
new file mode 100644
index 0000000..d36bb8e
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/AsmPrinter/CMakeLists.txt
@@ -0,0 +1,9 @@
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}/..
+ ${CMAKE_CURRENT_SOURCE_DIR}/..
+ )
+
+add_llvm_library(LLVMPIC16AsmPrinter
+ PIC16AsmPrinter.cpp
+ )
+add_dependencies(LLVMPIC16AsmPrinter PIC16CodeGenTable_gen)
diff --git a/contrib/llvm/lib/Target/PIC16/AsmPrinter/Makefile b/contrib/llvm/lib/Target/PIC16/AsmPrinter/Makefile
new file mode 100644
index 0000000..e3c0684
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/AsmPrinter/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Target/PIC16/AsmPrinter/Makefile ----------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../../../..
+LIBRARYNAME = LLVMPIC16AsmPrinter
+
+# Hack: we need to include 'main' pic16 target directory to grab private headers
+CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp b/contrib/llvm/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
new file mode 100644
index 0000000..b665817
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp
@@ -0,0 +1,512 @@
+//===-- PIC16AsmPrinter.cpp - PIC16 LLVM assembly writer ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains a printer that converts from our internal representation
+// of machine-dependent LLVM code to PIC16 assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16ABINames.h"
+#include "PIC16AsmPrinter.h"
+#include "PIC16Section.h"
+#include "PIC16MCAsmInfo.h"
+#include "PIC16MachineFunctionInfo.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Function.h"
+#include "llvm/Module.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/Target/Mangler.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ADT/SmallString.h"
+#include <cstring>
+using namespace llvm;
+
+#include "PIC16GenAsmWriter.inc"
+
+PIC16AsmPrinter::PIC16AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
+: AsmPrinter(TM, Streamer), DbgInfo(Streamer, TM.getMCAsmInfo()) {
+ PMAI = static_cast<const PIC16MCAsmInfo*>(TM.getMCAsmInfo());
+ PTOF = &getObjFileLowering();
+}
+
+void PIC16AsmPrinter::EmitInstruction(const MachineInstr *MI) {
+ SmallString<128> Str;
+ raw_svector_ostream OS(Str);
+ printInstruction(MI, OS);
+
+ OutStreamer.EmitRawText(OS.str());
+}
+
+static int getFunctionColor(const Function *F) {
+ if (F->hasSection()) {
+ std::string Sectn = F->getSection();
+ std::string StrToFind = "Overlay=";
+ std::string::size_type 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(CurrentFnSym->getName());
+ 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.
+///
+bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+ // This calls the base class function required to be called at beginning
+ // of runOnMachineFunction.
+ SetupMachineFunction(MF);
+
+ // Put the color information from function to its auto section.
+ const Function *F = MF.getFunction();
+ ColorAutoSection(F);
+
+ // Emit the function frame (args and temps).
+ EmitFunctionFrame(MF);
+
+ DbgInfo.BeginFunction(MF);
+
+ // Now emit the instructions of function in its code section.
+ const MCSection *fCodeSection =
+ getObjFileLowering().SectionForCode(CurrentFnSym->getName(),
+ PAN::isISR(F->getSection()));
+
+ // Start the Code Section.
+ OutStreamer.SwitchSection(fCodeSection);
+
+ // Emit the frame address of the function at the beginning of code.
+ OutStreamer.EmitRawText("\tretlw low(" +
+ Twine(PAN::getFrameLabel(CurrentFnSym->getName())) +
+ ")");
+ OutStreamer.EmitRawText("\tretlw high(" +
+ Twine(PAN::getFrameLabel(CurrentFnSym->getName())) +
+ ")");
+
+ // Emit function start label.
+ OutStreamer.EmitLabel(CurrentFnSym);
+
+ DebugLoc CurDL;
+ // Print out code for the function.
+ for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+
+ // Print a label for the basic block.
+ if (I != MF.begin())
+ EmitBasicBlockStart(I);
+
+ // Print a basic block.
+ for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
+ II != E; ++II) {
+ // Emit the line directive if source line changed.
+ DebugLoc DL = II->getDebugLoc();
+ if (!DL.isUnknown() && DL != CurDL) {
+ DbgInfo.ChangeDebugLoc(MF, DL);
+ CurDL = DL;
+ }
+
+ // Print the assembly for the instruction.
+ EmitInstruction(II);
+ }
+ }
+
+ // Emit function end debug directives.
+ DbgInfo.EndFunction(MF);
+
+ return false; // we didn't modify anything.
+}
+
+
+// printOperand - print operand of insn.
+void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum,
+ raw_ostream &O) {
+ const MachineOperand &MO = MI->getOperand(opNum);
+ const Function *F = MI->getParent()->getParent()->getFunction();
+
+ switch (MO.getType()) {
+ case MachineOperand::MO_Register:
+ {
+ // For indirect load/store insns, the fsr name is printed as INDF.
+ std::string RegName = getRegisterName(MO.getReg());
+ if ((MI->getOpcode() == PIC16::load_indirect) ||
+ (MI->getOpcode() == PIC16::store_indirect))
+ RegName.replace (0, 3, "INDF");
+ O << RegName;
+ }
+ return;
+
+ case MachineOperand::MO_Immediate:
+ O << (int)MO.getImm();
+ return;
+
+ case MachineOperand::MO_GlobalAddress: {
+ MCSymbol *Sym = Mang->getSymbol(MO.getGlobal());
+ // FIXME: currently we do not have a memcpy def coming in the module
+ // by any chance, as we do not link in those as .bc lib. So these calls
+ // are always external and it is safe to emit an extern.
+ if (PAN::isMemIntrinsic(Sym->getName()))
+ LibcallDecls.insert(Sym->getName());
+
+ O << *Sym;
+ break;
+ }
+ case MachineOperand::MO_ExternalSymbol: {
+ const char *Sname = MO.getSymbolName();
+ std::string Printname = Sname;
+
+ // Intrinsic stuff needs to be renamed if we are printing IL fn.
+ if (PAN::isIntrinsicStuff(Printname)) {
+ if (PAN::isISR(F->getSection())) {
+ Printname = PAN::Rename(Sname);
+ }
+ // Record these decls, we need to print them in asm as extern.
+ LibcallDecls.insert(Printname);
+ }
+
+ O << Printname;
+ break;
+ }
+ case MachineOperand::MO_MachineBasicBlock:
+ O << *MO.getMBB()->getSymbol();
+ return;
+
+ default:
+ llvm_unreachable(" Operand type not supported.");
+ }
+}
+
+/// printCCOperand - Print the cond code operand.
+///
+void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum,
+ raw_ostream &O) {
+ int CC = (int)MI->getOperand(opNum).getImm();
+ O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
+}
+
+/// printLibcallDecls - print the extern declarations for compiler
+/// intrinsics.
+///
+void PIC16AsmPrinter::printLibcallDecls() {
+ // If no libcalls used, return.
+ if (LibcallDecls.empty()) return;
+
+ OutStreamer.AddComment("External decls for libcalls - BEGIN");
+ OutStreamer.AddBlankLine();
+
+ for (std::set<std::string>::const_iterator I = LibcallDecls.begin(),
+ E = LibcallDecls.end(); I != E; I++)
+ OutStreamer.EmitRawText(MAI->getExternDirective() + Twine(*I));
+
+ OutStreamer.AddComment("External decls for libcalls - END");
+ OutStreamer.AddBlankLine();
+}
+
+/// doInitialization - Perform Module level initializations here.
+/// One task that we do here is to sectionize all global variables.
+/// The MemSelOptimizer pass depends on the sectionizing.
+///
+bool PIC16AsmPrinter::doInitialization(Module &M) {
+ bool Result = AsmPrinter::doInitialization(M);
+
+ // Every asmbly contains these std headers.
+ OutStreamer.EmitRawText(StringRef("\n#include p16f1xxx.inc"));
+ OutStreamer.EmitRawText(StringRef("#include stdmacros.inc"));
+
+ // Set the section names for all globals.
+ for (Module::global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ++I) {
+
+ // Record External Var Decls.
+ if (I->isDeclaration()) {
+ ExternalVarDecls.push_back(I);
+ continue;
+ }
+
+ // Record Exteranl Var Defs.
+ if (I->hasExternalLinkage() || I->hasCommonLinkage()) {
+ ExternalVarDefs.push_back(I);
+ }
+
+ // Sectionify actual data.
+ if (!I->hasAvailableExternallyLinkage()) {
+ const MCSection *S = getObjFileLowering().SectionForGlobal(I, Mang, TM);
+
+ I->setSection(((const PIC16Section *)S)->getName());
+ }
+ }
+
+ DbgInfo.BeginModule(M);
+ EmitFunctionDecls(M);
+ EmitUndefinedVars(M);
+ EmitDefinedVars(M);
+ EmitIData(M);
+ EmitUData(M);
+ EmitRomData(M);
+ EmitSharedUdata(M);
+ EmitUserSections(M);
+ return Result;
+}
+
+/// Emit extern decls for functions imported from other modules, and emit
+/// global declarations for function defined in this module and which are
+/// available to other modules.
+///
+void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
+ // Emit declarations for external functions.
+ OutStreamer.AddComment("Function Declarations - BEGIN");
+ OutStreamer.AddBlankLine();
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
+ if (I->isIntrinsic() || I->getName() == "@abort")
+ continue;
+
+ if (!I->isDeclaration() && !I->hasExternalLinkage())
+ continue;
+
+ MCSymbol *Sym = Mang->getSymbol(I);
+
+ // Do not emit memcpy, memset, and memmove here.
+ // Calls to these routines can be generated in two ways,
+ // 1. User calling the standard lib function
+ // 2. Codegen generating these calls for llvm intrinsics.
+ // In the first case a prototype is alread availale, while in
+ // second case the call is via and externalsym and the prototype is missing.
+ // So declarations for these are currently always getting printing by
+ // tracking both kind of references in printInstrunction.
+ if (I->isDeclaration() && PAN::isMemIntrinsic(Sym->getName())) continue;
+
+ const char *directive = I->isDeclaration() ? MAI->getExternDirective() :
+ MAI->getGlobalDirective();
+
+ OutStreamer.EmitRawText(directive + Twine(Sym->getName()));
+ OutStreamer.EmitRawText(directive +
+ Twine(PAN::getRetvalLabel(Sym->getName())));
+ OutStreamer.EmitRawText(directive +
+ Twine(PAN::getArgsLabel(Sym->getName())));
+ }
+
+ OutStreamer.AddComment("Function Declarations - END");
+ OutStreamer.AddBlankLine();
+
+}
+
+// Emit variables imported from other Modules.
+void PIC16AsmPrinter::EmitUndefinedVars(Module &M) {
+ std::vector<const GlobalVariable*> Items = ExternalVarDecls;
+ if (!Items.size()) return;
+
+ OutStreamer.AddComment("Imported Variables - BEGIN");
+ OutStreamer.AddBlankLine();
+ for (unsigned j = 0; j < Items.size(); j++)
+ OutStreamer.EmitRawText(MAI->getExternDirective() +
+ Twine(Mang->getSymbol(Items[j])->getName()));
+
+ OutStreamer.AddComment("Imported Variables - END");
+ OutStreamer.AddBlankLine();
+}
+
+// Emit variables defined in this module and are available to other modules.
+void PIC16AsmPrinter::EmitDefinedVars(Module &M) {
+ std::vector<const GlobalVariable*> Items = ExternalVarDefs;
+ if (!Items.size()) return;
+
+ OutStreamer.AddComment("Exported Variables - BEGIN");
+ OutStreamer.AddBlankLine();
+
+ for (unsigned j = 0; j < Items.size(); j++)
+ OutStreamer.EmitRawText(MAI->getGlobalDirective() +
+ Twine(Mang->getSymbol(Items[j])->getName()));
+ OutStreamer.AddComment("Exported Variables - END");
+ OutStreamer.AddBlankLine();
+}
+
+// Emit initialized data placed in ROM.
+void PIC16AsmPrinter::EmitRomData(Module &M) {
+ EmitSingleSection(PTOF->ROMDATASection());
+}
+
+// Emit Shared section udata.
+void PIC16AsmPrinter::EmitSharedUdata(Module &M) {
+ EmitSingleSection(PTOF->SHAREDUDATASection());
+}
+
+bool PIC16AsmPrinter::doFinalization(Module &M) {
+ EmitAllAutos(M);
+ printLibcallDecls();
+ DbgInfo.EndModule(M);
+ OutStreamer.EmitRawText(StringRef("\tEND"));
+ return AsmPrinter::doFinalization(M);
+}
+
+void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
+ const Function *F = MF.getFunction();
+ const TargetData *TD = TM.getTargetData();
+ PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>();
+
+ // Emit the data section name.
+
+ PIC16Section *fPDataSection =
+ const_cast<PIC16Section *>(getObjFileLowering().
+ SectionForFrame(CurrentFnSym->getName()));
+
+ fPDataSection->setColor(getFunctionColor(F));
+ OutStreamer.SwitchSection(fPDataSection);
+
+ // Emit function frame label
+ OutStreamer.EmitRawText(PAN::getFrameLabel(CurrentFnSym->getName()) +
+ Twine(":"));
+
+ const Type *RetType = F->getReturnType();
+ unsigned RetSize = 0;
+ if (RetType->getTypeID() != Type::VoidTyID)
+ RetSize = TD->getTypeAllocSize(RetType);
+
+ //Emit function return value space
+ // FIXME: Do not emit RetvalLable when retsize is zero. To do this
+ // we will need to avoid printing a global directive for Retval label
+ // in emitExternandGloblas.
+ if(RetSize > 0)
+ OutStreamer.EmitRawText(PAN::getRetvalLabel(CurrentFnSym->getName()) +
+ Twine(" RES ") + Twine(RetSize));
+ else
+ OutStreamer.EmitRawText(PAN::getRetvalLabel(CurrentFnSym->getName()) +
+ Twine(":"));
+
+ // Emit variable to hold the space for function arguments
+ unsigned ArgSize = 0;
+ for (Function::const_arg_iterator argi = F->arg_begin(),
+ arge = F->arg_end(); argi != arge ; ++argi) {
+ const Type *Ty = argi->getType();
+ ArgSize += TD->getTypeAllocSize(Ty);
+ }
+
+ OutStreamer.EmitRawText(PAN::getArgsLabel(CurrentFnSym->getName()) +
+ Twine(" RES ") + Twine(ArgSize));
+
+ // Emit temporary space
+ int TempSize = FuncInfo->getTmpSize();
+ if (TempSize > 0)
+ OutStreamer.EmitRawText(PAN::getTempdataLabel(CurrentFnSym->getName()) +
+ Twine(" RES ") + Twine(TempSize));
+}
+
+
+void PIC16AsmPrinter::EmitInitializedDataSection(const PIC16Section *S) {
+ /// Emit Section header.
+ OutStreamer.SwitchSection(S);
+
+ std::vector<const GlobalVariable*> Items = S->Items;
+ for (unsigned j = 0; j < Items.size(); j++) {
+ Constant *C = Items[j]->getInitializer();
+ int AddrSpace = Items[j]->getType()->getAddressSpace();
+ OutStreamer.EmitRawText(Mang->getSymbol(Items[j])->getName());
+ EmitGlobalConstant(C, AddrSpace);
+ }
+}
+
+// Print all IDATA sections.
+void PIC16AsmPrinter::EmitIData(Module &M) {
+ EmitSectionList (M, PTOF->IDATASections());
+}
+
+void PIC16AsmPrinter::
+EmitUninitializedDataSection(const PIC16Section *S) {
+ const TargetData *TD = TM.getTargetData();
+ OutStreamer.SwitchSection(S);
+ std::vector<const GlobalVariable*> Items = S->Items;
+ for (unsigned j = 0; j < Items.size(); j++) {
+ Constant *C = Items[j]->getInitializer();
+ const Type *Ty = C->getType();
+ unsigned Size = TD->getTypeAllocSize(Ty);
+ OutStreamer.EmitRawText(Mang->getSymbol(Items[j])->getName() +
+ Twine(" RES ") + Twine(Size));
+ }
+}
+
+// Print all UDATA sections.
+void PIC16AsmPrinter::EmitUData(Module &M) {
+ EmitSectionList (M, PTOF->UDATASections());
+}
+
+// Print all USER sections.
+void PIC16AsmPrinter::EmitUserSections(Module &M) {
+ EmitSectionList (M, PTOF->USERSections());
+}
+
+// Print all AUTO sections.
+void PIC16AsmPrinter::EmitAllAutos(Module &M) {
+ EmitSectionList (M, PTOF->AUTOSections());
+}
+
+extern "C" void LLVMInitializePIC16AsmPrinter() {
+ RegisterAsmPrinter<PIC16AsmPrinter> X(ThePIC16Target);
+}
+
+// Emit one data section using correct section emitter based on section type.
+void PIC16AsmPrinter::EmitSingleSection(const PIC16Section *S) {
+ if (S == NULL) return;
+
+ switch (S->getType()) {
+ default: llvm_unreachable ("unknow user section type");
+ case UDATA:
+ case UDATA_SHR:
+ case UDATA_OVR:
+ EmitUninitializedDataSection(S);
+ break;
+ case IDATA:
+ case ROMDATA:
+ EmitInitializedDataSection(S);
+ break;
+ }
+}
+
+// Emit a list of sections.
+void PIC16AsmPrinter::
+EmitSectionList(Module &M, const std::vector<PIC16Section *> &SList) {
+ for (unsigned i = 0; i < SList.size(); i++) {
+ // Exclude llvm specific metadata sections.
+ if (SList[i]->getName().find("llvm.") != std::string::npos)
+ continue;
+ OutStreamer.AddBlankLine();
+ EmitSingleSection(SList[i]);
+ }
+}
+
diff --git a/contrib/llvm/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h b/contrib/llvm/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h
new file mode 100644
index 0000000..aa2e1f4
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h
@@ -0,0 +1,88 @@
+//===-- PIC16AsmPrinter.h - PIC16 LLVM assembly writer ----------*- 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 a printer that converts from our internal representation
+// of machine-dependent LLVM code to PIC16 assembly language.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16ASMPRINTER_H
+#define PIC16ASMPRINTER_H
+
+#include "PIC16.h"
+#include "PIC16TargetMachine.h"
+#include "PIC16DebugInfo.h"
+#include "PIC16MCAsmInfo.h"
+#include "PIC16TargetObjectFile.h"
+#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/CodeGen/AsmPrinter.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetMachine.h"
+#include <list>
+#include <set>
+#include <string>
+
+namespace llvm {
+ class LLVM_LIBRARY_VISIBILITY PIC16AsmPrinter : public AsmPrinter {
+ public:
+ explicit PIC16AsmPrinter(TargetMachine &TM, MCStreamer &Streamer);
+ private:
+ virtual const char *getPassName() const {
+ return "PIC16 Assembly Printer";
+ }
+
+ const PIC16TargetObjectFile &getObjFileLowering() const {
+ return (const PIC16TargetObjectFile &)AsmPrinter::getObjFileLowering();
+ }
+
+ bool runOnMachineFunction(MachineFunction &F);
+ void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
+ void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
+ void printInstruction(const MachineInstr *MI, raw_ostream &O);
+ static const char *getRegisterName(unsigned RegNo);
+
+ void EmitInstruction(const MachineInstr *MI);
+ void EmitFunctionDecls (Module &M);
+ void EmitUndefinedVars (Module &M);
+ void EmitDefinedVars (Module &M);
+ void EmitIData (Module &M);
+ void EmitUData (Module &M);
+ void EmitAllAutos (Module &M);
+ void EmitRomData (Module &M);
+ void EmitSharedUdata(Module &M);
+ void EmitUserSections (Module &M);
+ void EmitFunctionFrame(MachineFunction &MF);
+ void printLibcallDecls();
+ void EmitUninitializedDataSection(const PIC16Section *S);
+ void EmitInitializedDataSection(const PIC16Section *S);
+ 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);
+
+ /// EmitGlobalVariable - Emit the specified global variable and its
+ /// initializer to the output stream.
+ virtual void EmitGlobalVariable(const GlobalVariable *GV) {
+ // PIC16 doesn't use normal hooks for this.
+ }
+
+ private:
+ const PIC16TargetObjectFile *PTOF;
+ PIC16DbgInfo DbgInfo;
+ const PIC16MCAsmInfo *PMAI;
+ std::set<std::string> LibcallDecls; // Sorted & uniqued set of extern decls.
+ std::vector<const GlobalVariable *> ExternalVarDecls;
+ std::vector<const GlobalVariable *> ExternalVarDefs;
+ };
+} // end of namespace
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/CMakeLists.txt b/contrib/llvm/lib/Target/PIC16/CMakeLists.txt
new file mode 100644
index 0000000..cd4afe8
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(LLVM_TARGET_DEFINITIONS PIC16.td)
+
+tablegen(PIC16GenRegisterInfo.h.inc -gen-register-desc-header)
+tablegen(PIC16GenRegisterNames.inc -gen-register-enums)
+tablegen(PIC16GenRegisterInfo.inc -gen-register-desc)
+tablegen(PIC16GenInstrNames.inc -gen-instr-enums)
+tablegen(PIC16GenInstrInfo.inc -gen-instr-desc)
+tablegen(PIC16GenAsmWriter.inc -gen-asm-writer)
+tablegen(PIC16GenDAGISel.inc -gen-dag-isel)
+tablegen(PIC16GenCallingConv.inc -gen-callingconv)
+tablegen(PIC16GenSubtarget.inc -gen-subtarget)
+
+add_llvm_target(PIC16
+ PIC16DebugInfo.cpp
+ PIC16InstrInfo.cpp
+ PIC16ISelDAGToDAG.cpp
+ PIC16ISelLowering.cpp
+ PIC16MemSelOpt.cpp
+ PIC16MCAsmInfo.cpp
+ PIC16RegisterInfo.cpp
+ PIC16Section.cpp
+ PIC16Subtarget.cpp
+ PIC16TargetMachine.cpp
+ PIC16TargetObjectFile.cpp
+ PIC16SelectionDAGInfo.cpp
+ )
diff --git a/contrib/llvm/lib/Target/PIC16/Makefile b/contrib/llvm/lib/Target/PIC16/Makefile
new file mode 100644
index 0000000..9e784d1
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/Makefile
@@ -0,0 +1,24 @@
+##===- lib/Target/PIC16/Makefile ---------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../..
+LIBRARYNAME = LLVMPIC16CodeGen
+TARGET = PIC16
+
+# Make sure that tblgen is run, first thing.
+BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \
+ PIC16GenRegisterInfo.inc PIC16GenInstrNames.inc \
+ PIC16GenInstrInfo.inc PIC16GenAsmWriter.inc \
+ PIC16GenDAGISel.inc PIC16GenCallingConv.inc \
+ PIC16GenSubtarget.inc
+
+DIRS = AsmPrinter TargetInfo PIC16Passes
+
+include $(LEVEL)/Makefile.common
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16.h b/contrib/llvm/lib/Target/PIC16/PIC16.h
new file mode 100644
index 0000000..cee55f4
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16.h
@@ -0,0 +1,137 @@
+//===-- PIC16.h - Top-level interface for PIC16 representation --*- 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_PIC16_H
+#define LLVM_TARGET_PIC16_H
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetMachine.h"
+#include <cassert>
+#include <sstream>
+#include <cstring>
+#include <string>
+#include <vector>
+
+namespace llvm {
+ class PIC16TargetMachine;
+ class FunctionPass;
+ class MachineCodeEmitter;
+ class formatted_raw_ostream;
+
+namespace PIC16CC {
+ enum CondCodes {
+ EQ,
+ NE,
+ LT,
+ LE,
+ GT,
+ GE,
+ ULT,
+ UGT,
+ ULE,
+ UGE
+ };
+}
+
+ enum PIC16SectionType {
+ CODE,
+ UDATA,
+ IDATA,
+ ROMDATA,
+ UDATA_OVR,
+ UDATA_SHR
+ };
+
+ class ESNames {
+ std::vector<char*> stk;
+ ESNames() {}
+ public:
+ ~ESNames() {
+ std::vector<char*>::iterator it = stk.end();
+ it--;
+ while(stk.end() != stk.begin())
+ {
+ char* p = *it;
+ delete [] p;
+ it--;
+ stk.pop_back();
+ }
+ }
+
+ // External symbol names require memory to live till the program end.
+ // So we have to allocate it and keep. Push all such allocations into a
+ // vector so that they get freed up on termination.
+ inline static const char *createESName (const std::string &name) {
+ static ESNames esn;
+ char *tmpName = new char[name.size() + 1];
+ memcpy(tmpName, name.c_str(), name.size() + 1);
+ esn.stk.push_back(tmpName);
+ return tmpName;
+ }
+
+ };
+
+ inline static const char *PIC16CondCodeToString(PIC16CC::CondCodes CC) {
+ switch (CC) {
+ default: llvm_unreachable("Unknown condition code");
+ case PIC16CC::NE: return "ne";
+ case PIC16CC::EQ: return "eq";
+ case PIC16CC::LT: return "lt";
+ case PIC16CC::ULT: return "lt";
+ case PIC16CC::LE: return "le";
+ case PIC16CC::ULE: return "le";
+ case PIC16CC::GT: return "gt";
+ case PIC16CC::UGT: return "gt";
+ case PIC16CC::GE: return "ge";
+ case PIC16CC::UGE: return "ge";
+ }
+ }
+
+ inline static bool isSignedComparison(PIC16CC::CondCodes CC) {
+ switch (CC) {
+ default: llvm_unreachable("Unknown condition code");
+ case PIC16CC::NE:
+ case PIC16CC::EQ:
+ case PIC16CC::LT:
+ case PIC16CC::LE:
+ case PIC16CC::GE:
+ case PIC16CC::GT:
+ return true;
+ case PIC16CC::ULT:
+ case PIC16CC::UGT:
+ case PIC16CC::ULE:
+ case PIC16CC::UGE:
+ return false; // condition codes for unsigned comparison.
+ }
+ }
+
+
+
+ FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM);
+ // Banksel optimizer pass.
+ FunctionPass *createPIC16MemSelOptimizerPass();
+
+ extern Target ThePIC16Target;
+ extern Target TheCooperTarget;
+
+} // end namespace llvm;
+
+// Defines symbolic names for PIC16 registers. This defines a mapping from
+// register name to register number.
+#include "PIC16GenRegisterNames.inc"
+
+// Defines symbolic names for the PIC16 instructions.
+#include "PIC16GenInstrNames.inc"
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16.td b/contrib/llvm/lib/Target/PIC16/PIC16.td
new file mode 100644
index 0000000..b2b9b1c
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16.td
@@ -0,0 +1,40 @@
+//===- PIC16.td - Describe the PIC16 Target Machine -----------*- tblgen -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// This is the top level entry point for the PIC16 target.
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Target-independent interfaces
+//===----------------------------------------------------------------------===//
+
+include "llvm/Target/Target.td"
+
+include "PIC16RegisterInfo.td"
+include "PIC16InstrInfo.td"
+
+//===----------------------------------------------------------------------===//
+// Subtarget Features.
+//===----------------------------------------------------------------------===//
+def FeatureCooper : SubtargetFeature<"cooper", "IsCooper", "true",
+ "PIC16 Cooper ISA Support">;
+
+//===----------------------------------------------------------------------===//
+// PIC16 supported processors.
+//===----------------------------------------------------------------------===//
+
+def : Processor<"generic", NoItineraries, []>;
+def : Processor<"cooper", NoItineraries, [FeatureCooper]>;
+
+
+def PIC16InstrInfo : InstrInfo {}
+
+def PIC16 : Target {
+ let InstructionSet = PIC16InstrInfo;
+}
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16ABINames.h b/contrib/llvm/lib/Target/PIC16/PIC16ABINames.h
new file mode 100644
index 0000000..4c1a8da
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16ABINames.h
@@ -0,0 +1,399 @@
+//===-- PIC16ABINames.h - PIC16 Naming conventios for ABI----- --*- 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 functions to manage ABI Naming conventions for PIC16.
+//
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_PIC16ABINAMES_H
+#define LLVM_TARGET_PIC16ABINAMES_H
+
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Target/TargetMachine.h"
+#include <cassert>
+#include <sstream>
+#include <cstring>
+#include <string>
+
+namespace llvm {
+ class PIC16TargetMachine;
+ class FunctionPass;
+ class MachineCodeEmitter;
+ class formatted_raw_ostream;
+
+ // 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
+ // Static local variables - @<func>.<var>
+ // -------------------------------------------------------
+ // 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>.#
+ // Program memory data - @romdata.#
+ // Variables with user defined section name - <user_defined_section>
+ // Variables with user defined address - @<var>.user_section.<address>.#
+ // Function frame - @<func>.frame_section.
+ // Function autos - @<func>.autos_section.
+ // Overlay sections - @<color>.##
+ // 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,
+ USER_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.";
+ case USER_SECTION: return ".user_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;
+ }
+
+ // Get the retval label for the given function.
+ static std::string getRetvalLabel(const std::string &Func) {
+ std::string Func1 = addPrefix(Func);
+ std::string tag = getTagName(RET_LABEL);
+ return Func1 + tag;
+ }
+
+ // Get the argument label for the given function.
+ static std::string getArgsLabel(const std::string &Func) {
+ std::string Func1 = addPrefix(Func);
+ std::string tag = getTagName(ARGS_LABEL);
+ return Func1 + tag;
+ }
+
+ // Get the tempdata label for the given function.
+ 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 + "#";
+ }
+
+ static std::string getAutosSectionName(const std::string &Func) {
+ std::string Func1 = addPrefix(Func);
+ std::string tag = getTagName(AUTOS_SECTION);
+ return Func1 + tag + "#";
+ }
+
+ static std::string getCodeSectionName(const std::string &Func) {
+ std::string Func1 = addPrefix(Func);
+ std::string tag = getTagName(CODE_SECTION);
+ return Func1 + tag + "#";
+ }
+
+ static std::string getUserSectionName(const std::string &Name) {
+ std::string sname = addPrefix(Name);;
+ std::string tag = getTagName(USER_SECTION);
+ return sname + tag + "#";
+ }
+
+ // 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
+ << ".#";
+ return o.str();
+ }
+
+ static std::string getRomdataSectionName() {
+ return "romdata.#";
+ }
+
+ static std::string getSharedUDataSectionName() {
+ std::ostringstream o;
+ o << getTagName(PREFIX_SYMBOL) << "udata_shr" << ".#";
+ return o.str();
+ }
+
+ static std::string getRomdataSectionName(unsigned num,
+ std::string prefix = "") {
+ std::ostringstream o;
+ o << getTagName(PREFIX_SYMBOL) << prefix << "romdata." << num
+ << ".#";
+ return o.str();
+ }
+
+ static std::string getIdataSectionName(unsigned num,
+ std::string prefix = "") {
+ std::ostringstream o;
+ o << getTagName(PREFIX_SYMBOL) << prefix << "idata." << num
+ << ".#";
+ 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;
+ }
+
+ // Currently names of libcalls are assigned during TargetLowering
+ // object construction. There is no provision to change the when the
+ // code for a function IL function being generated.
+ // So we have to change these names while printing assembly.
+ // We need to do that mainly for names related to intrinsics. This
+ // function returns true if a name needs to be cloned.
+ inline static bool isIntrinsicStuff(const std::string &Name) {
+ // Return true if the name contains LIBCALL marker, or a MemIntrinisc.
+ // these are mainly ARGS_LABEL, RET_LABEL, and the LIBCALL name itself.
+ if ((Name.find(getTagName(LIBCALL)) != std::string::npos)
+ || isMemIntrinsic(Name))
+ return true;
+
+ return false;
+ }
+
+ // Rename the name for IL.
+ inline static std::string Rename(const std::string &Name) {
+ std::string Newname;
+ // If its a label (LIBCALL+Func+LABEL), change it to
+ // (LIBCALL+Func+IL+LABEL).
+ TAGS id = getSymbolTag(Name);
+ if (id == ARGS_LABEL || id == RET_LABEL) {
+ std::size_t pos = Name.find(getTagName(id));
+ Newname = Name.substr(0, pos) + ".IL" + getTagName(id);
+ return Newname;
+ }
+
+ // Else, just append IL to name.
+ return Name + ".IL";
+ }
+
+
+
+
+ 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);
+ }
+ }
+ }
+
+ /// 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();
+ }
+
+ // Return true if the current function is an ISR
+ inline static bool isISR(const std::string SectName) {
+ if (SectName.find("interrupt") != std::string::npos)
+ return true;
+
+ return false;
+ }
+
+ // Return the address for ISR starts in rom.
+ inline static std::string getISRAddr(void) {
+ return "0x4";
+ }
+
+ // Returns the name of clone of a function.
+ static std::string getCloneFnName(const std::string &Func) {
+ return (Func + ".IL");
+ }
+
+ // Returns the name of clone of a variable.
+ static std::string getCloneVarName(const std::string &Fn,
+ const std::string &Var) {
+ std::string cloneVarName = Var;
+ // These vars are named like fun.auto.var.
+ // Just replace the function name, with clone function name.
+ std::string cloneFnName = getCloneFnName(Fn);
+ cloneVarName.replace(cloneVarName.find(Fn), Fn.length(), cloneFnName);
+ return cloneVarName;
+ }
+ }; // class PAN.
+} // end namespace llvm;
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16DebugInfo.cpp b/contrib/llvm/lib/Target/PIC16/PIC16DebugInfo.cpp
new file mode 100644
index 0000000..6a4d0d6
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16DebugInfo.cpp
@@ -0,0 +1,490 @@
+
+//===-- PIC16DebugInfo.cpp - Implementation for PIC16 Debug Information ======//
+//
+// 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 helper functions for representing debug information.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16.h"
+#include "PIC16ABINames.h"
+#include "PIC16DebugInfo.h"
+#include "llvm/GlobalVariable.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/MC/MCAsmInfo.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/Support/DebugLoc.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+using namespace llvm;
+
+/// PopulateDebugInfo - Populate the TypeNo, Aux[] and TagName from Ty.
+///
+void PIC16DbgInfo::PopulateDebugInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+ if (Ty.isBasicType())
+ PopulateBasicTypeInfo (Ty, TypeNo);
+ else if (Ty.isCompositeType())
+ PopulateCompositeTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
+ else if (Ty.isDerivedType())
+ PopulateDerivedTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
+ else {
+ TypeNo = PIC16Dbg::T_NULL;
+ HasAux = false;
+ }
+ return;
+}
+
+/// PopulateBasicTypeInfo- Populate TypeNo for basic type from Ty.
+///
+void PIC16DbgInfo::PopulateBasicTypeInfo (DIType Ty, unsigned short &TypeNo) {
+ std::string Name = Ty.getName();
+ unsigned short BaseTy = GetTypeDebugNumber(Name);
+ TypeNo = TypeNo << PIC16Dbg::S_BASIC;
+ TypeNo = TypeNo | (0xffff & BaseTy);
+}
+
+/// PopulateDerivedTypeInfo - Populate TypeNo, Aux[], TagName for derived type
+/// from Ty. Derived types are mostly pointers.
+///
+void PIC16DbgInfo::PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+
+ switch(Ty.getTag())
+ {
+ case dwarf::DW_TAG_pointer_type:
+ TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
+ TypeNo = TypeNo | PIC16Dbg::DT_PTR;
+ break;
+ default:
+ TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
+ }
+
+ // We also need to encode the information about the base type of
+ // pointer in TypeNo.
+ DIType BaseType = DIDerivedType(Ty).getTypeDerivedFrom();
+ PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName);
+}
+
+/// PopulateArrayTypeInfo - Populate TypeNo, Aux[] for array from Ty.
+void PIC16DbgInfo::PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+
+ DICompositeType CTy = DICompositeType(Ty);
+ DIArray Elements = CTy.getTypeArray();
+ unsigned short size = 1;
+ unsigned short Dimension[4]={0,0,0,0};
+ for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
+ DIDescriptor Element = Elements.getElement(i);
+ if (Element.getTag() == dwarf::DW_TAG_subrange_type) {
+ TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
+ TypeNo = TypeNo | PIC16Dbg::DT_ARY;
+ DISubrange SubRange = DISubrange(Element);
+ Dimension[i] = SubRange.getHi() - SubRange.getLo() + 1;
+ // Each dimension is represented by 2 bytes starting at byte 9.
+ Aux[8+i*2+0] = Dimension[i];
+ Aux[8+i*2+1] = Dimension[i] >> 8;
+ size = size * Dimension[i];
+ }
+ }
+ HasAux = true;
+ // In auxillary entry for array, 7th and 8th byte represent array size.
+ Aux[6] = size & 0xff;
+ Aux[7] = size >> 8;
+ DIType BaseType = CTy.getTypeDerivedFrom();
+ PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName);
+}
+
+/// PopulateStructOrUnionTypeInfo - Populate TypeNo, Aux[] , TagName for
+/// structure or union.
+///
+void PIC16DbgInfo::PopulateStructOrUnionTypeInfo (DIType Ty,
+ unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+ DICompositeType CTy = DICompositeType(Ty);
+ TypeNo = TypeNo << PIC16Dbg::S_BASIC;
+ if (Ty.getTag() == dwarf::DW_TAG_structure_type)
+ TypeNo = TypeNo | PIC16Dbg::T_STRUCT;
+ else
+ TypeNo = TypeNo | PIC16Dbg::T_UNION;
+ TagName = CTy.getName();
+ // UniqueSuffix is .number where number is obtained from
+ // llvm.dbg.composite<number>.
+ // FIXME: This will break when composite type is not represented by
+ // llvm.dbg.composite* global variable. Since we need to revisit
+ // PIC16DebugInfo implementation anyways after the MDNodes based
+ // framework is done, let us continue with the way it is.
+ std::string UniqueSuffix = "." + Ty->getNameStr().substr(18);
+ TagName += UniqueSuffix;
+ unsigned short size = CTy.getSizeInBits()/8;
+ // 7th and 8th byte represent size.
+ HasAux = true;
+ Aux[6] = size & 0xff;
+ Aux[7] = size >> 8;
+}
+
+/// PopulateEnumTypeInfo - Populate TypeNo for enum from Ty.
+void PIC16DbgInfo::PopulateEnumTypeInfo (DIType Ty, unsigned short &TypeNo) {
+ TypeNo = TypeNo << PIC16Dbg::S_BASIC;
+ TypeNo = TypeNo | PIC16Dbg::T_ENUM;
+}
+
+/// PopulateCompositeTypeInfo - Populate TypeNo, Aux[] and TagName for
+/// composite types from Ty.
+///
+void PIC16DbgInfo::PopulateCompositeTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TagName) {
+ switch (Ty.getTag()) {
+ case dwarf::DW_TAG_array_type: {
+ PopulateArrayTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
+ break;
+ }
+ case dwarf:: DW_TAG_union_type:
+ case dwarf::DW_TAG_structure_type: {
+ PopulateStructOrUnionTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
+ break;
+ }
+ case dwarf::DW_TAG_enumeration_type: {
+ PopulateEnumTypeInfo (Ty, TypeNo);
+ break;
+ }
+ default:
+ TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
+ }
+}
+
+/// GetTypeDebugNumber - Get debug type number for given type.
+///
+unsigned PIC16DbgInfo::GetTypeDebugNumber(std::string &type) {
+ if (type == "char")
+ return PIC16Dbg::T_CHAR;
+ else if (type == "short")
+ return PIC16Dbg::T_SHORT;
+ else if (type == "int")
+ return PIC16Dbg::T_INT;
+ else if (type == "long")
+ return PIC16Dbg::T_LONG;
+ else if (type == "unsigned char")
+ return PIC16Dbg::T_UCHAR;
+ else if (type == "unsigned short")
+ return PIC16Dbg::T_USHORT;
+ else if (type == "unsigned int")
+ return PIC16Dbg::T_UINT;
+ else if (type == "unsigned long")
+ return PIC16Dbg::T_ULONG;
+ else
+ return 0;
+}
+
+/// GetStorageClass - Get storage class for give debug variable.
+///
+short PIC16DbgInfo::getStorageClass(DIGlobalVariable DIGV) {
+ short ClassNo;
+ if (PAN::isLocalName(DIGV.getName())) {
+ // Generating C_AUTO here fails due to error in linker. Change it once
+ // linker is fixed.
+ ClassNo = PIC16Dbg::C_STAT;
+ }
+ else if (DIGV.isLocalToUnit())
+ ClassNo = PIC16Dbg::C_STAT;
+ else
+ ClassNo = PIC16Dbg::C_EXT;
+ return ClassNo;
+}
+
+/// BeginModule - Emit necessary debug info to start a Module and do other
+/// required initializations.
+void PIC16DbgInfo::BeginModule(Module &M) {
+ // Emit file directive for module.
+ DebugInfoFinder DbgFinder;
+ DbgFinder.processModule(M);
+ if (DbgFinder.compile_unit_count() != 0) {
+ // FIXME : What if more then one CUs are present in a module ?
+ MDNode *CU = *DbgFinder.compile_unit_begin();
+ EmitDebugDirectives = true;
+ SwitchToCU(CU);
+ }
+ // Emit debug info for decls of composite types.
+ EmitCompositeTypeDecls(M);
+}
+
+/// Helper to find first valid debug loc for a function.
+///
+static const DebugLoc GetDebugLocForFunction(const MachineFunction &MF) {
+ DebugLoc DL;
+ for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
+ II != E; ++II) {
+ DL = II->getDebugLoc();
+ if (!DL.isUnknown())
+ return DL;
+ }
+ }
+ return DL;
+}
+
+/// BeginFunction - Emit necessary debug info to start a function.
+///
+void PIC16DbgInfo::BeginFunction(const MachineFunction &MF) {
+ if (! EmitDebugDirectives) return;
+
+ // Retreive the first valid debug Loc and process it.
+ const DebugLoc &DL = GetDebugLocForFunction(MF);
+ // Emit debug info only if valid debug info is available.
+ if (!DL.isUnknown()) {
+ ChangeDebugLoc(MF, DL, true);
+ EmitFunctBeginDI(MF.getFunction());
+ }
+ // Set current line to 0 so that.line directive is genearted after .bf.
+ CurLine = 0;
+}
+
+/// ChangeDebugLoc - Take necessary steps when DebugLoc changes.
+/// CurFile and CurLine may change as a result of this.
+///
+void PIC16DbgInfo::ChangeDebugLoc(const MachineFunction &MF,
+ const DebugLoc &DL, bool IsInBeginFunction) {
+ if (!EmitDebugDirectives) return;
+ assert(!DL.isUnknown() && "can't change to invalid debug loc");
+
+ SwitchToCU(DL.getScope(MF.getFunction()->getContext()));
+ SwitchToLine(DL.getLine(), IsInBeginFunction);
+}
+
+/// SwitchToLine - Emit line directive for a new line.
+///
+void PIC16DbgInfo::SwitchToLine(unsigned Line, bool IsInBeginFunction) {
+ if (CurLine == Line) return;
+ if (!IsInBeginFunction)
+ OS.EmitRawText("\n\t.line " + Twine(Line));
+ CurLine = Line;
+}
+
+/// EndFunction - Emit .ef for end of function.
+///
+void PIC16DbgInfo::EndFunction(const MachineFunction &MF) {
+ if (! EmitDebugDirectives) return;
+ const DebugLoc &DL = GetDebugLocForFunction(MF);
+ // Emit debug info only if valid debug info is available.
+ if (!DL.isUnknown())
+ EmitFunctEndDI(MF.getFunction(), CurLine);
+}
+
+/// EndModule - Emit .eof for end of module.
+///
+void PIC16DbgInfo::EndModule(Module &M) {
+ if (! EmitDebugDirectives) return;
+ EmitVarDebugInfo(M);
+ if (CurFile != "") OS.EmitRawText(StringRef("\n\t.eof"));
+}
+
+/// EmitCompositeTypeElements - Emit debug information for members of a
+/// composite type.
+///
+void PIC16DbgInfo::EmitCompositeTypeElements (DICompositeType CTy,
+ std::string SuffixNo) {
+ unsigned long Value = 0;
+ DIArray Elements = CTy.getTypeArray();
+ for (unsigned i = 0, N = Elements.getNumElements(); i < N; i++) {
+ DIDescriptor Element = Elements.getElement(i);
+ unsigned short TypeNo = 0;
+ bool HasAux = false;
+ int ElementAux[PIC16Dbg::AuxSize] = { 0 };
+ std::string TagName = "";
+ DIDerivedType DITy(Element);
+ unsigned short ElementSize = DITy.getSizeInBits()/8;
+ // Get mangleddd name for this structure/union element.
+ std::string MangMemName = DITy.getName().str() + SuffixNo;
+ PopulateDebugInfo(DITy, TypeNo, HasAux, ElementAux, TagName);
+ short Class = 0;
+ if( CTy.getTag() == dwarf::DW_TAG_union_type)
+ Class = PIC16Dbg::C_MOU;
+ else if (CTy.getTag() == dwarf::DW_TAG_structure_type)
+ Class = PIC16Dbg::C_MOS;
+ EmitSymbol(MangMemName.c_str(), Class, TypeNo, Value);
+ if (CTy.getTag() == dwarf::DW_TAG_structure_type)
+ Value += ElementSize;
+ if (HasAux)
+ EmitAuxEntry(MangMemName.c_str(), ElementAux, PIC16Dbg::AuxSize, TagName);
+ }
+}
+
+/// EmitCompositeTypeDecls - Emit composite type declarations like structure
+/// and union declarations.
+///
+void PIC16DbgInfo::EmitCompositeTypeDecls(Module &M) {
+ DebugInfoFinder DbgFinder;
+ DbgFinder.processModule(M);
+ for (DebugInfoFinder::iterator I = DbgFinder.type_begin(),
+ E = DbgFinder.type_end(); I != E; ++I) {
+ DICompositeType CTy(*I);
+ if (!CTy.Verify())
+ continue;
+ if (CTy.getTag() == dwarf::DW_TAG_union_type ||
+ CTy.getTag() == dwarf::DW_TAG_structure_type ) {
+ // Get the number after llvm.dbg.composite and make UniqueSuffix from
+ // it.
+ std::string DIVar = CTy->getNameStr();
+ std::string UniqueSuffix = "." + DIVar.substr(18);
+ std::string MangledCTyName = CTy.getName().str() + UniqueSuffix;
+ unsigned short size = CTy.getSizeInBits()/8;
+ int Aux[PIC16Dbg::AuxSize] = {0};
+ // 7th and 8th byte represent size of structure/union.
+ Aux[6] = size & 0xff;
+ Aux[7] = size >> 8;
+ // Emit .def for structure/union tag.
+ if( CTy.getTag() == dwarf::DW_TAG_union_type)
+ EmitSymbol(MangledCTyName.c_str(), PIC16Dbg::C_UNTAG);
+ else if (CTy.getTag() == dwarf::DW_TAG_structure_type)
+ EmitSymbol(MangledCTyName.c_str(), PIC16Dbg::C_STRTAG);
+
+ // Emit auxiliary debug information for structure/union tag.
+ EmitAuxEntry(MangledCTyName.c_str(), Aux, PIC16Dbg::AuxSize);
+
+ // Emit members.
+ EmitCompositeTypeElements (CTy, UniqueSuffix);
+
+ // Emit mangled Symbol for end of structure/union.
+ std::string EOSSymbol = ".eos" + UniqueSuffix;
+ EmitSymbol(EOSSymbol.c_str(), PIC16Dbg::C_EOS);
+ EmitAuxEntry(EOSSymbol.c_str(), Aux, PIC16Dbg::AuxSize,
+ MangledCTyName.c_str());
+ }
+ }
+}
+
+
+/// EmitFunctBeginDI - Emit .bf for function.
+///
+void PIC16DbgInfo::EmitFunctBeginDI(const Function *F) {
+ std::string FunctName = F->getName();
+ if (EmitDebugDirectives) {
+ std::string FunctBeginSym = ".bf." + FunctName;
+ std::string BlockBeginSym = ".bb." + FunctName;
+
+ int BFAux[PIC16Dbg::AuxSize] = {0};
+ BFAux[4] = CurLine;
+ BFAux[5] = CurLine >> 8;
+
+ // Emit debug directives for beginning of function.
+ EmitSymbol(FunctBeginSym, PIC16Dbg::C_FCN);
+ EmitAuxEntry(FunctBeginSym, BFAux, PIC16Dbg::AuxSize);
+
+ EmitSymbol(BlockBeginSym, PIC16Dbg::C_BLOCK);
+ EmitAuxEntry(BlockBeginSym, BFAux, PIC16Dbg::AuxSize);
+ }
+}
+
+/// EmitFunctEndDI - Emit .ef for function end.
+///
+void PIC16DbgInfo::EmitFunctEndDI(const Function *F, unsigned Line) {
+ std::string FunctName = F->getName();
+ if (EmitDebugDirectives) {
+ std::string FunctEndSym = ".ef." + FunctName;
+ std::string BlockEndSym = ".eb." + FunctName;
+
+ // Emit debug directives for end of function.
+ EmitSymbol(BlockEndSym, PIC16Dbg::C_BLOCK);
+ int EFAux[PIC16Dbg::AuxSize] = {0};
+ // 5th and 6th byte stand for line number.
+ EFAux[4] = CurLine;
+ EFAux[5] = CurLine >> 8;
+ EmitAuxEntry(BlockEndSym, EFAux, PIC16Dbg::AuxSize);
+ EmitSymbol(FunctEndSym, PIC16Dbg::C_FCN);
+ EmitAuxEntry(FunctEndSym, EFAux, PIC16Dbg::AuxSize);
+ }
+}
+
+/// EmitAuxEntry - Emit Auxiliary debug information.
+///
+void PIC16DbgInfo::EmitAuxEntry(const std::string VarName, int Aux[], int Num,
+ std::string TagName) {
+ std::string Tmp;
+ // TagName is emitted in case of structure/union objects.
+ if (!TagName.empty()) Tmp += ", " + TagName;
+
+ for (int i = 0; i<Num; i++)
+ Tmp += "," + utostr(Aux[i] && 0xff);
+
+ OS.EmitRawText("\n\t.dim " + Twine(VarName) + ", 1" + Tmp);
+}
+
+/// EmitSymbol - Emit .def for a symbol. Value is offset for the member.
+///
+void PIC16DbgInfo::EmitSymbol(std::string Name, short Class,
+ unsigned short Type, unsigned long Value) {
+ std::string Tmp;
+ if (Value > 0)
+ Tmp = ", value = " + utostr(Value);
+
+ OS.EmitRawText("\n\t.def " + Twine(Name) + ", type = " + utostr(Type) +
+ ", class = " + utostr(Class) + Tmp);
+}
+
+/// EmitVarDebugInfo - Emit debug information for all variables.
+///
+void PIC16DbgInfo::EmitVarDebugInfo(Module &M) {
+ DebugInfoFinder DbgFinder;
+ DbgFinder.processModule(M);
+
+ for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
+ E = DbgFinder.global_variable_end(); I != E; ++I) {
+ DIGlobalVariable DIGV(*I);
+ DIType Ty = DIGV.getType();
+ unsigned short TypeNo = 0;
+ bool HasAux = false;
+ int Aux[PIC16Dbg::AuxSize] = { 0 };
+ std::string TagName = "";
+ std::string VarName = DIGV.getName();
+ VarName = MAI->getGlobalPrefix() + VarName;
+ PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TagName);
+ // Emit debug info only if type information is availaible.
+ if (TypeNo != PIC16Dbg::T_NULL) {
+ OS.EmitRawText("\t.type " + Twine(VarName) + ", " + Twine(TypeNo));
+ short ClassNo = getStorageClass(DIGV);
+ OS.EmitRawText("\t.class " + Twine(VarName) + ", " + Twine(ClassNo));
+ if (HasAux)
+ EmitAuxEntry(VarName, Aux, PIC16Dbg::AuxSize, TagName);
+ }
+ }
+}
+
+/// SwitchToCU - Switch to a new compilation unit.
+///
+void PIC16DbgInfo::SwitchToCU(MDNode *CU) {
+ // Get the file path from CU.
+ DICompileUnit cu(CU);
+ std::string DirName = cu.getDirectory();
+ std::string FileName = cu.getFilename();
+ std::string FilePath = DirName + "/" + FileName;
+
+ // Nothing to do if source file is still same.
+ if ( FilePath == CurFile ) return;
+
+ // Else, close the current one and start a new.
+ if (CurFile != "")
+ OS.EmitRawText(StringRef("\t.eof"));
+ OS.EmitRawText("\n\t.file\t\"" + Twine(FilePath) + "\"");
+ CurFile = FilePath;
+ CurLine = 0;
+}
+
+/// EmitEOF - Emit .eof for end of file.
+///
+void PIC16DbgInfo::EmitEOF() {
+ if (CurFile != "")
+ OS.EmitRawText(StringRef("\t.EOF"));
+}
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16DebugInfo.h b/contrib/llvm/lib/Target/PIC16/PIC16DebugInfo.h
new file mode 100644
index 0000000..031dcf0
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16DebugInfo.h
@@ -0,0 +1,156 @@
+//===-- PIC16DebugInfo.h - Interfaces for PIC16 Debug Information ============//
+//
+// 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 helper functions for representing debug information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16DBG_H
+#define PIC16DBG_H
+
+#include "llvm/Analysis/DebugInfo.h"
+#include "llvm/Module.h"
+
+namespace llvm {
+ class MachineFunction;
+ class DebugLoc;
+ class MCStreamer;
+
+ namespace PIC16Dbg {
+ enum VarType {
+ T_NULL,
+ T_VOID,
+ T_CHAR,
+ T_SHORT,
+ T_INT,
+ T_LONG,
+ T_FLOAT,
+ T_DOUBLE,
+ T_STRUCT,
+ T_UNION,
+ T_ENUM,
+ T_MOE,
+ T_UCHAR,
+ T_USHORT,
+ T_UINT,
+ T_ULONG
+ };
+ enum DerivedType {
+ DT_NONE,
+ DT_PTR,
+ DT_FCN,
+ DT_ARY
+ };
+ enum TypeSize {
+ S_BASIC = 5,
+ S_DERIVED = 3
+ };
+ enum DbgClass {
+ C_NULL,
+ C_AUTO,
+ C_EXT,
+ C_STAT,
+ C_REG,
+ C_EXTDEF,
+ C_LABEL,
+ C_ULABEL,
+ C_MOS,
+ C_ARG,
+ C_STRTAG,
+ C_MOU,
+ C_UNTAG,
+ C_TPDEF,
+ C_USTATIC,
+ C_ENTAG,
+ C_MOE,
+ C_REGPARM,
+ C_FIELD,
+ C_AUTOARG,
+ C_LASTENT,
+ C_BLOCK = 100,
+ C_FCN,
+ C_EOS,
+ C_FILE,
+ C_LINE,
+ C_ALIAS,
+ C_HIDDEN,
+ C_EOF,
+ C_LIST,
+ C_SECTION,
+ C_EFCN = 255
+ };
+ enum SymbolSize {
+ AuxSize =20
+ };
+ }
+
+ class PIC16DbgInfo {
+ MCStreamer &OS;
+ const MCAsmInfo *MAI;
+ std::string CurFile;
+ unsigned CurLine;
+
+ // EmitDebugDirectives is set if debug information is available. Default
+ // value for it is false.
+ bool EmitDebugDirectives;
+
+ public:
+ PIC16DbgInfo(MCStreamer &os, const MCAsmInfo *T) : OS(os), MAI(T) {
+ CurFile = "";
+ CurLine = 0;
+ EmitDebugDirectives = false;
+ }
+
+ void BeginModule (Module &M);
+ void BeginFunction (const MachineFunction &MF);
+ void ChangeDebugLoc (const MachineFunction &MF, const DebugLoc &DL,
+ bool IsInBeginFunction = false);
+ void EndFunction (const MachineFunction &MF);
+ void EndModule (Module &M);
+
+
+ private:
+ void SwitchToCU (MDNode *CU);
+ void SwitchToLine (unsigned Line, bool IsInBeginFunction = false);
+
+ void PopulateDebugInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux,
+ int Aux[], std::string &TypeName);
+ void PopulateBasicTypeInfo (DIType Ty, unsigned short &TypeNo);
+ void PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TypeName);
+
+ void PopulateCompositeTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TypeName);
+ void PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TypeName);
+
+ void PopulateStructOrUnionTypeInfo (DIType Ty, unsigned short &TypeNo,
+ bool &HasAux, int Aux[],
+ std::string &TypeName);
+ void PopulateEnumTypeInfo (DIType Ty, unsigned short &TypeNo);
+
+ unsigned GetTypeDebugNumber(std::string &Type);
+ short getStorageClass(DIGlobalVariable DIGV);
+ void EmitFunctBeginDI(const Function *F);
+ void EmitCompositeTypeDecls(Module &M);
+ void EmitCompositeTypeElements (DICompositeType CTy, std::string Suffix);
+ void EmitFunctEndDI(const Function *F, unsigned Line);
+ void EmitAuxEntry(const std::string VarName, int Aux[],
+ int num = PIC16Dbg::AuxSize, std::string TagName = "");
+ inline void EmitSymbol(std::string Name, short Class,
+ unsigned short Type = PIC16Dbg::T_NULL,
+ unsigned long Value = 0);
+ void EmitVarDebugInfo(Module &M);
+ void EmitEOF();
+ };
+} // end namespace llvm;
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp b/contrib/llvm/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
new file mode 100644
index 0000000..6cbd002
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp
@@ -0,0 +1,50 @@
+//===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an instruction selector for the PIC16 target.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-isel"
+
+#include "llvm/Support/ErrorHandling.h"
+#include "PIC16ISelDAGToDAG.h"
+using namespace llvm;
+
+/// createPIC16ISelDag - This pass converts a legalized DAG into a
+/// PIC16-specific DAG, ready for instruction scheduling.
+FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
+ return new PIC16DAGToDAGISel(TM);
+}
+
+
+/// Select - Select instructions not customized! Used for
+/// expanded, promoted and normal instructions.
+SDNode* PIC16DAGToDAGISel::Select(SDNode *N) {
+
+ // Select the default instruction.
+ SDNode *ResNode = SelectCode(N);
+
+ return ResNode;
+}
+
+
+// SelectDirectAddr - Match a direct address for DAG.
+// A direct address could be a globaladdress or externalsymbol.
+bool PIC16DAGToDAGISel::SelectDirectAddr(SDNode *Op, SDValue N,
+ SDValue &Address) {
+ // Return true if TGA or ES.
+ if (N.getOpcode() == ISD::TargetGlobalAddress
+ || N.getOpcode() == ISD::TargetExternalSymbol) {
+ Address = N;
+ return true;
+ }
+
+ return false;
+}
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16ISelDAGToDAG.h b/contrib/llvm/lib/Target/PIC16/PIC16ISelDAGToDAG.h
new file mode 100644
index 0000000..ecaddd3
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16ISelDAGToDAG.h
@@ -0,0 +1,60 @@
+//===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an instruction selector for the PIC16 target.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-isel"
+
+#include "PIC16.h"
+#include "PIC16RegisterInfo.h"
+#include "PIC16TargetMachine.h"
+#include "PIC16MachineFunctionInfo.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Intrinsics.h"
+using namespace llvm;
+
+namespace {
+
+class LLVM_LIBRARY_VISIBILITY PIC16DAGToDAGISel : public SelectionDAGISel {
+
+ /// TM - Keep a reference to PIC16TargetMachine.
+ const PIC16TargetMachine &TM;
+
+ /// PIC16Lowering - This object fully describes how to lower LLVM code to an
+ /// PIC16-specific SelectionDAG.
+ const PIC16TargetLowering &PIC16Lowering;
+
+public:
+ explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
+ SelectionDAGISel(tm),
+ TM(tm), PIC16Lowering(*TM.getTargetLowering()) {}
+
+ // Pass Name
+ virtual const char *getPassName() const {
+ return "PIC16 DAG->DAG Pattern Instruction Selection";
+ }
+
+private:
+ // Include the pieces autogenerated from the target description.
+#include "PIC16GenDAGISel.inc"
+
+ SDNode *Select(SDNode *N);
+
+ // Match direct address complex pattern.
+ bool SelectDirectAddr(SDNode *Op, SDValue N, SDValue &Address);
+
+};
+
+}
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp b/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp
new file mode 100644
index 0000000..f479f46
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.cpp
@@ -0,0 +1,1986 @@
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that PIC16 uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-lower"
+#include "PIC16ABINames.h"
+#include "PIC16ISelLowering.h"
+#include "PIC16TargetObjectFile.h"
+#include "PIC16TargetMachine.h"
+#include "PIC16MachineFunctionInfo.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/GlobalValue.h"
+#include "llvm/Function.h"
+#include "llvm/CallingConv.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+#include "llvm/Support/ErrorHandling.h"
+
+
+using namespace llvm;
+
+static const char *getIntrinsicName(unsigned opcode) {
+ std::string Basename;
+ switch(opcode) {
+ default: llvm_unreachable("do not know intrinsic name");
+ // Arithmetic Right shift for integer types.
+ case PIC16ISD::SRA_I8: Basename = "sra.i8"; break;
+ case RTLIB::SRA_I16: Basename = "sra.i16"; break;
+ case RTLIB::SRA_I32: Basename = "sra.i32"; break;
+
+ // Left shift for integer types.
+ case PIC16ISD::SLL_I8: Basename = "sll.i8"; break;
+ case RTLIB::SHL_I16: Basename = "sll.i16"; break;
+ case RTLIB::SHL_I32: Basename = "sll.i32"; break;
+
+ // Logical Right Shift for integer types.
+ case PIC16ISD::SRL_I8: Basename = "srl.i8"; break;
+ case RTLIB::SRL_I16: Basename = "srl.i16"; break;
+ case RTLIB::SRL_I32: Basename = "srl.i32"; break;
+
+ // Multiply for integer types.
+ case PIC16ISD::MUL_I8: Basename = "mul.i8"; break;
+ case RTLIB::MUL_I16: Basename = "mul.i16"; break;
+ case RTLIB::MUL_I32: Basename = "mul.i32"; break;
+
+ // Signed division for integers.
+ case RTLIB::SDIV_I16: Basename = "sdiv.i16"; break;
+ case RTLIB::SDIV_I32: Basename = "sdiv.i32"; break;
+
+ // Unsigned division for integers.
+ case RTLIB::UDIV_I16: Basename = "udiv.i16"; break;
+ case RTLIB::UDIV_I32: Basename = "udiv.i32"; break;
+
+ // Signed Modulas for integers.
+ case RTLIB::SREM_I16: Basename = "srem.i16"; break;
+ case RTLIB::SREM_I32: Basename = "srem.i32"; break;
+
+ // Unsigned Modulas for integers.
+ case RTLIB::UREM_I16: Basename = "urem.i16"; break;
+ case RTLIB::UREM_I32: Basename = "urem.i32"; break;
+
+ //////////////////////
+ // LIBCALLS FOR FLOATS
+ //////////////////////
+
+ // Float to signed integrals
+ case RTLIB::FPTOSINT_F32_I8: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOSINT_F32_I16: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOSINT_F32_I32: Basename = "f32_to_si32"; break;
+
+ // Signed integrals to float. char and int are first sign extended to i32
+ // before being converted to float, so an I8_F32 or I16_F32 isn't required.
+ case RTLIB::SINTTOFP_I32_F32: Basename = "si32_to_f32"; break;
+
+ // Float to Unsigned conversions.
+ // Signed conversion can be used for unsigned conversion as well.
+ // In signed and unsigned versions only the interpretation of the
+ // MSB is different. Bit representation remains the same.
+ case RTLIB::FPTOUINT_F32_I8: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOUINT_F32_I16: Basename = "f32_to_si32"; break;
+ case RTLIB::FPTOUINT_F32_I32: Basename = "f32_to_si32"; break;
+
+ // Unsigned to Float conversions. char and int are first zero extended
+ // before being converted to float.
+ case RTLIB::UINTTOFP_I32_F32: Basename = "ui32_to_f32"; break;
+
+ // Floating point add, sub, mul, div.
+ case RTLIB::ADD_F32: Basename = "add.f32"; break;
+ case RTLIB::SUB_F32: Basename = "sub.f32"; break;
+ case RTLIB::MUL_F32: Basename = "mul.f32"; break;
+ case RTLIB::DIV_F32: Basename = "div.f32"; break;
+
+ // Floating point comparison
+ case RTLIB::O_F32: Basename = "unordered.f32"; break;
+ case RTLIB::UO_F32: Basename = "unordered.f32"; break;
+ case RTLIB::OLE_F32: Basename = "le.f32"; break;
+ case RTLIB::OGE_F32: Basename = "ge.f32"; break;
+ case RTLIB::OLT_F32: Basename = "lt.f32"; break;
+ case RTLIB::OGT_F32: Basename = "gt.f32"; break;
+ case RTLIB::OEQ_F32: Basename = "eq.f32"; break;
+ case RTLIB::UNE_F32: Basename = "neq.f32"; break;
+ }
+
+ std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
+ std::string tagname = PAN::getTagName(PAN::LIBCALL);
+ std::string Fullname = prefix + tagname + Basename;
+
+ // The name has to live through program life.
+ return ESNames::createESName(Fullname);
+}
+
+// getStdLibCallName - Get the name for the standard library function.
+static const char *getStdLibCallName(unsigned opcode) {
+ std::string BaseName;
+ switch(opcode) {
+ case RTLIB::COS_F32: BaseName = "cos";
+ break;
+ case RTLIB::SIN_F32: BaseName = "sin";
+ break;
+ case RTLIB::MEMCPY: BaseName = "memcpy";
+ break;
+ case RTLIB::MEMSET: BaseName = "memset";
+ break;
+ case RTLIB::MEMMOVE: BaseName = "memmove";
+ break;
+ default: llvm_unreachable("do not know std lib call name");
+ }
+ std::string prefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
+ std::string LibCallName = prefix + BaseName;
+
+ // The name has to live through program life.
+ return ESNames::createESName(LibCallName);
+}
+
+// PIC16TargetLowering Constructor.
+PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM)
+ : TargetLowering(TM, new PIC16TargetObjectFile()) {
+
+ Subtarget = &TM.getSubtarget<PIC16Subtarget>();
+
+ addRegisterClass(MVT::i8, PIC16::GPRRegisterClass);
+
+ setShiftAmountType(MVT::i8);
+
+ // Std lib call names
+ setLibcallName(RTLIB::COS_F32, getStdLibCallName(RTLIB::COS_F32));
+ setLibcallName(RTLIB::SIN_F32, getStdLibCallName(RTLIB::SIN_F32));
+ setLibcallName(RTLIB::MEMCPY, getStdLibCallName(RTLIB::MEMCPY));
+ setLibcallName(RTLIB::MEMSET, getStdLibCallName(RTLIB::MEMSET));
+ setLibcallName(RTLIB::MEMMOVE, getStdLibCallName(RTLIB::MEMMOVE));
+
+ // SRA library call names
+ setPIC16LibcallName(PIC16ISD::SRA_I8, getIntrinsicName(PIC16ISD::SRA_I8));
+ setLibcallName(RTLIB::SRA_I16, getIntrinsicName(RTLIB::SRA_I16));
+ setLibcallName(RTLIB::SRA_I32, getIntrinsicName(RTLIB::SRA_I32));
+
+ // SHL library call names
+ setPIC16LibcallName(PIC16ISD::SLL_I8, getIntrinsicName(PIC16ISD::SLL_I8));
+ setLibcallName(RTLIB::SHL_I16, getIntrinsicName(RTLIB::SHL_I16));
+ setLibcallName(RTLIB::SHL_I32, getIntrinsicName(RTLIB::SHL_I32));
+
+ // SRL library call names
+ setPIC16LibcallName(PIC16ISD::SRL_I8, getIntrinsicName(PIC16ISD::SRL_I8));
+ setLibcallName(RTLIB::SRL_I16, getIntrinsicName(RTLIB::SRL_I16));
+ setLibcallName(RTLIB::SRL_I32, getIntrinsicName(RTLIB::SRL_I32));
+
+ // MUL Library call names
+ setPIC16LibcallName(PIC16ISD::MUL_I8, getIntrinsicName(PIC16ISD::MUL_I8));
+ setLibcallName(RTLIB::MUL_I16, getIntrinsicName(RTLIB::MUL_I16));
+ setLibcallName(RTLIB::MUL_I32, getIntrinsicName(RTLIB::MUL_I32));
+
+ // Signed division lib call names
+ setLibcallName(RTLIB::SDIV_I16, getIntrinsicName(RTLIB::SDIV_I16));
+ setLibcallName(RTLIB::SDIV_I32, getIntrinsicName(RTLIB::SDIV_I32));
+
+ // Unsigned division lib call names
+ setLibcallName(RTLIB::UDIV_I16, getIntrinsicName(RTLIB::UDIV_I16));
+ setLibcallName(RTLIB::UDIV_I32, getIntrinsicName(RTLIB::UDIV_I32));
+
+ // Signed remainder lib call names
+ setLibcallName(RTLIB::SREM_I16, getIntrinsicName(RTLIB::SREM_I16));
+ setLibcallName(RTLIB::SREM_I32, getIntrinsicName(RTLIB::SREM_I32));
+
+ // Unsigned remainder lib call names
+ setLibcallName(RTLIB::UREM_I16, getIntrinsicName(RTLIB::UREM_I16));
+ setLibcallName(RTLIB::UREM_I32, getIntrinsicName(RTLIB::UREM_I32));
+
+ // Floating point to signed int conversions.
+ setLibcallName(RTLIB::FPTOSINT_F32_I8,
+ getIntrinsicName(RTLIB::FPTOSINT_F32_I8));
+ setLibcallName(RTLIB::FPTOSINT_F32_I16,
+ getIntrinsicName(RTLIB::FPTOSINT_F32_I16));
+ setLibcallName(RTLIB::FPTOSINT_F32_I32,
+ getIntrinsicName(RTLIB::FPTOSINT_F32_I32));
+
+ // Signed int to floats.
+ setLibcallName(RTLIB::SINTTOFP_I32_F32,
+ getIntrinsicName(RTLIB::SINTTOFP_I32_F32));
+
+ // Floating points to unsigned ints.
+ setLibcallName(RTLIB::FPTOUINT_F32_I8,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I8));
+ setLibcallName(RTLIB::FPTOUINT_F32_I16,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I16));
+ setLibcallName(RTLIB::FPTOUINT_F32_I32,
+ getIntrinsicName(RTLIB::FPTOUINT_F32_I32));
+
+ // Unsigned int to floats.
+ setLibcallName(RTLIB::UINTTOFP_I32_F32,
+ getIntrinsicName(RTLIB::UINTTOFP_I32_F32));
+
+ // Floating point add, sub, mul ,div.
+ setLibcallName(RTLIB::ADD_F32, getIntrinsicName(RTLIB::ADD_F32));
+ setLibcallName(RTLIB::SUB_F32, getIntrinsicName(RTLIB::SUB_F32));
+ setLibcallName(RTLIB::MUL_F32, getIntrinsicName(RTLIB::MUL_F32));
+ setLibcallName(RTLIB::DIV_F32, getIntrinsicName(RTLIB::DIV_F32));
+
+ // Floationg point comparison
+ setLibcallName(RTLIB::O_F32, getIntrinsicName(RTLIB::O_F32));
+ setLibcallName(RTLIB::UO_F32, getIntrinsicName(RTLIB::UO_F32));
+ setLibcallName(RTLIB::OLE_F32, getIntrinsicName(RTLIB::OLE_F32));
+ setLibcallName(RTLIB::OGE_F32, getIntrinsicName(RTLIB::OGE_F32));
+ setLibcallName(RTLIB::OLT_F32, getIntrinsicName(RTLIB::OLT_F32));
+ setLibcallName(RTLIB::OGT_F32, getIntrinsicName(RTLIB::OGT_F32));
+ setLibcallName(RTLIB::OEQ_F32, getIntrinsicName(RTLIB::OEQ_F32));
+ setLibcallName(RTLIB::UNE_F32, getIntrinsicName(RTLIB::UNE_F32));
+
+ // Return value comparisons of floating point calls.
+ setCmpLibcallCC(RTLIB::OEQ_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::UNE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OLT_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OLE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OGE_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::OGT_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::UO_F32, ISD::SETNE);
+ setCmpLibcallCC(RTLIB::O_F32, ISD::SETEQ);
+
+ setOperationAction(ISD::GlobalAddress, MVT::i16, Custom);
+ setOperationAction(ISD::ExternalSymbol, MVT::i16, Custom);
+
+ setOperationAction(ISD::LOAD, MVT::i8, Legal);
+ setOperationAction(ISD::LOAD, MVT::i16, Custom);
+ setOperationAction(ISD::LOAD, MVT::i32, Custom);
+
+ setOperationAction(ISD::STORE, MVT::i8, Legal);
+ setOperationAction(ISD::STORE, MVT::i16, Custom);
+ setOperationAction(ISD::STORE, MVT::i32, Custom);
+ setOperationAction(ISD::STORE, MVT::i64, Custom);
+
+ setOperationAction(ISD::ADDE, MVT::i8, Custom);
+ setOperationAction(ISD::ADDC, MVT::i8, Custom);
+ setOperationAction(ISD::SUBE, MVT::i8, Custom);
+ setOperationAction(ISD::SUBC, MVT::i8, Custom);
+ setOperationAction(ISD::SUB, MVT::i8, Custom);
+ setOperationAction(ISD::ADD, MVT::i8, Custom);
+ setOperationAction(ISD::ADD, MVT::i16, Custom);
+
+ setOperationAction(ISD::OR, MVT::i8, Custom);
+ setOperationAction(ISD::AND, MVT::i8, Custom);
+ setOperationAction(ISD::XOR, MVT::i8, Custom);
+
+ setOperationAction(ISD::FrameIndex, MVT::i16, Custom);
+
+ setOperationAction(ISD::MUL, MVT::i8, Custom);
+
+ setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand);
+ setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand);
+ setOperationAction(ISD::MULHU, MVT::i8, Expand);
+ setOperationAction(ISD::MULHS, MVT::i8, Expand);
+
+ setOperationAction(ISD::SRA, MVT::i8, Custom);
+ setOperationAction(ISD::SHL, MVT::i8, Custom);
+ setOperationAction(ISD::SRL, MVT::i8, Custom);
+
+ setOperationAction(ISD::ROTL, MVT::i8, Expand);
+ setOperationAction(ISD::ROTR, MVT::i8, Expand);
+
+ setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
+
+ // PIC16 does not support shift parts
+ setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand);
+ setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand);
+ setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand);
+
+
+ // PIC16 does not have a SETCC, expand it to SELECT_CC.
+ setOperationAction(ISD::SETCC, MVT::i8, Expand);
+ setOperationAction(ISD::SELECT, MVT::i8, Expand);
+ setOperationAction(ISD::BRCOND, MVT::Other, Expand);
+ setOperationAction(ISD::BRIND, MVT::Other, Expand);
+
+ setOperationAction(ISD::SELECT_CC, MVT::i8, Custom);
+ setOperationAction(ISD::BR_CC, MVT::i8, Custom);
+
+ //setOperationAction(ISD::TRUNCATE, MVT::i16, Custom);
+ setTruncStoreAction(MVT::i16, MVT::i8, Custom);
+
+ // Now deduce the information based on the above mentioned
+ // actions
+ computeRegisterProperties();
+}
+
+// getOutFlag - Extract the flag result if the Op has it.
+static SDValue getOutFlag(SDValue &Op) {
+ // Flag is the last value of the node.
+ SDValue Flag = Op.getValue(Op.getNode()->getNumValues() - 1);
+
+ assert (Flag.getValueType() == MVT::Flag
+ && "Node does not have an out Flag");
+
+ return Flag;
+}
+// Get the TmpOffset for FrameIndex
+unsigned PIC16TargetLowering::GetTmpOffsetForFI(unsigned FI, unsigned size,
+ MachineFunction &MF) const {
+ PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>();
+ std::map<unsigned, unsigned> &FiTmpOffsetMap = FuncInfo->getFiTmpOffsetMap();
+
+ std::map<unsigned, unsigned>::iterator
+ MapIt = FiTmpOffsetMap.find(FI);
+ if (MapIt != FiTmpOffsetMap.end())
+ return MapIt->second;
+
+ // This FI (FrameIndex) is not yet mapped, so map it
+ FiTmpOffsetMap[FI] = FuncInfo->getTmpSize();
+ FuncInfo->setTmpSize(FuncInfo->getTmpSize() + size);
+ return FiTmpOffsetMap[FI];
+}
+
+void PIC16TargetLowering::ResetTmpOffsetMap(SelectionDAG &DAG) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>();
+ FuncInfo->getFiTmpOffsetMap().clear();
+ FuncInfo->setTmpSize(0);
+}
+
+// To extract chain value from the SDValue Nodes
+// This function will help to maintain the chain extracting
+// code at one place. In case of any change in future it will
+// help maintain the code.
+static SDValue getChain(SDValue &Op) {
+ SDValue Chain = Op.getValue(Op.getNode()->getNumValues() - 1);
+
+ // If the last value returned in Flag then the chain is
+ // second last value returned.
+ if (Chain.getValueType() == MVT::Flag)
+ Chain = Op.getValue(Op.getNode()->getNumValues() - 2);
+
+ // All nodes may not produce a chain. Therefore following assert
+ // verifies that the node is returning a chain only.
+ assert (Chain.getValueType() == MVT::Other
+ && "Node does not have a chain");
+
+ return Chain;
+}
+
+/// PopulateResults - Helper function to LowerOperation.
+/// If a node wants to return multiple results after lowering,
+/// it stuffs them into an array of SDValue called Results.
+
+static void PopulateResults(SDValue N, SmallVectorImpl<SDValue>&Results) {
+ if (N.getOpcode() == ISD::MERGE_VALUES) {
+ int NumResults = N.getNumOperands();
+ for( int i = 0; i < NumResults; i++)
+ Results.push_back(N.getOperand(i));
+ }
+ else
+ Results.push_back(N);
+}
+
+MVT::SimpleValueType
+PIC16TargetLowering::getSetCCResultType(EVT ValType) const {
+ return MVT::i8;
+}
+
+MVT::SimpleValueType
+PIC16TargetLowering::getCmpLibcallReturnType() const {
+ return MVT::i8;
+}
+
+/// The type legalizer framework of generating legalizer can generate libcalls
+/// only when the operand/result types are illegal.
+/// PIC16 needs to generate libcalls even for the legal types (i8) for some ops.
+/// For example an arithmetic right shift. These functions are used to lower
+/// such operations that generate libcall for legal types.
+
+void
+PIC16TargetLowering::setPIC16LibcallName(PIC16ISD::PIC16Libcall Call,
+ const char *Name) {
+ PIC16LibcallNames[Call] = Name;
+}
+
+const char *
+PIC16TargetLowering::getPIC16LibcallName(PIC16ISD::PIC16Libcall Call) const {
+ return PIC16LibcallNames[Call];
+}
+
+SDValue
+PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call,
+ EVT RetVT, const SDValue *Ops,
+ unsigned NumOps, bool isSigned,
+ SelectionDAG &DAG, DebugLoc dl) const {
+
+ TargetLowering::ArgListTy Args;
+ Args.reserve(NumOps);
+
+ TargetLowering::ArgListEntry Entry;
+ for (unsigned i = 0; i != NumOps; ++i) {
+ Entry.Node = Ops[i];
+ Entry.Ty = Entry.Node.getValueType().getTypeForEVT(*DAG.getContext());
+ Entry.isSExt = isSigned;
+ Entry.isZExt = !isSigned;
+ Args.push_back(Entry);
+ }
+
+ SDValue Callee = DAG.getExternalSymbol(getPIC16LibcallName(Call), MVT::i16);
+
+ const Type *RetTy = RetVT.getTypeForEVT(*DAG.getContext());
+ std::pair<SDValue,SDValue> CallInfo =
+ LowerCallTo(DAG.getEntryNode(), RetTy, isSigned, !isSigned, false,
+ false, 0, CallingConv::C, false,
+ /*isReturnValueUsed=*/true,
+ Callee, Args, DAG, dl);
+
+ return CallInfo.first;
+}
+
+const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const {
+ switch (Opcode) {
+ default: return NULL;
+ case PIC16ISD::Lo: return "PIC16ISD::Lo";
+ case PIC16ISD::Hi: return "PIC16ISD::Hi";
+ case PIC16ISD::MTLO: return "PIC16ISD::MTLO";
+ case PIC16ISD::MTHI: return "PIC16ISD::MTHI";
+ case PIC16ISD::MTPCLATH: return "PIC16ISD::MTPCLATH";
+ case PIC16ISD::PIC16Connect: return "PIC16ISD::PIC16Connect";
+ case PIC16ISD::Banksel: return "PIC16ISD::Banksel";
+ case PIC16ISD::PIC16Load: return "PIC16ISD::PIC16Load";
+ case PIC16ISD::PIC16LdArg: return "PIC16ISD::PIC16LdArg";
+ case PIC16ISD::PIC16LdWF: return "PIC16ISD::PIC16LdWF";
+ case PIC16ISD::PIC16Store: return "PIC16ISD::PIC16Store";
+ case PIC16ISD::PIC16StWF: return "PIC16ISD::PIC16StWF";
+ case PIC16ISD::BCF: return "PIC16ISD::BCF";
+ case PIC16ISD::LSLF: return "PIC16ISD::LSLF";
+ case PIC16ISD::LRLF: return "PIC16ISD::LRLF";
+ case PIC16ISD::RLF: return "PIC16ISD::RLF";
+ case PIC16ISD::RRF: return "PIC16ISD::RRF";
+ case PIC16ISD::CALL: return "PIC16ISD::CALL";
+ case PIC16ISD::CALLW: return "PIC16ISD::CALLW";
+ case PIC16ISD::SUBCC: return "PIC16ISD::SUBCC";
+ case PIC16ISD::SELECT_ICC: return "PIC16ISD::SELECT_ICC";
+ case PIC16ISD::BRCOND: return "PIC16ISD::BRCOND";
+ case PIC16ISD::RET: return "PIC16ISD::RET";
+ case PIC16ISD::Dummy: return "PIC16ISD::Dummy";
+ }
+}
+
+void PIC16TargetLowering::ReplaceNodeResults(SDNode *N,
+ SmallVectorImpl<SDValue>&Results,
+ SelectionDAG &DAG) const {
+
+ switch (N->getOpcode()) {
+ case ISD::GlobalAddress:
+ Results.push_back(ExpandGlobalAddress(N, DAG));
+ return;
+ case ISD::ExternalSymbol:
+ Results.push_back(ExpandExternalSymbol(N, DAG));
+ return;
+ case ISD::STORE:
+ Results.push_back(ExpandStore(N, DAG));
+ return;
+ case ISD::LOAD:
+ PopulateResults(ExpandLoad(N, DAG), Results);
+ return;
+ case ISD::ADD:
+ // Results.push_back(ExpandAdd(N, DAG));
+ return;
+ case ISD::FrameIndex:
+ Results.push_back(ExpandFrameIndex(N, DAG));
+ return;
+ default:
+ assert (0 && "not implemented");
+ return;
+ }
+}
+
+SDValue PIC16TargetLowering::ExpandFrameIndex(SDNode *N,
+ SelectionDAG &DAG) const {
+
+ // Currently handling FrameIndex of size MVT::i16 only
+ // One example of this scenario is when return value is written on
+ // FrameIndex#0
+
+ if (N->getValueType(0) != MVT::i16)
+ return SDValue();
+
+ // Expand the FrameIndex into ExternalSymbol and a Constant node
+ // The constant will represent the frame index number
+ // Get the current function frame
+ MachineFunction &MF = DAG.getMachineFunction();
+ const Function *Func = MF.getFunction();
+ const std::string Name = Func->getName();
+
+ FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(SDValue(N,0));
+ // FIXME there isn't really debug info here
+ DebugLoc dl = FR->getDebugLoc();
+
+ // Expand FrameIndex like GlobalAddress and ExternalSymbol
+ // Also use Offset field for lo and hi parts. The default
+ // offset is zero.
+
+ SDValue ES;
+ int FrameOffset;
+ SDValue FI = SDValue(N,0);
+ LegalizeFrameIndex(FI, DAG, ES, FrameOffset);
+ SDValue Offset = DAG.getConstant(FrameOffset, MVT::i8);
+ SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, ES, Offset);
+ SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, ES, Offset);
+ return DAG.getNode(ISD::BUILD_PAIR, dl, N->getValueType(0), Lo, Hi);
+}
+
+
+SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) const {
+ StoreSDNode *St = cast<StoreSDNode>(N);
+ SDValue Chain = St->getChain();
+ SDValue Src = St->getValue();
+ SDValue Ptr = St->getBasePtr();
+ EVT ValueType = Src.getValueType();
+ unsigned StoreOffset = 0;
+ DebugLoc dl = N->getDebugLoc();
+
+ SDValue PtrLo, PtrHi;
+ LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, StoreOffset, dl);
+
+ if (ValueType == MVT::i8) {
+ return DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, Src,
+ PtrLo, PtrHi,
+ DAG.getConstant (0 + StoreOffset, MVT::i8));
+ }
+ else if (ValueType == MVT::i16) {
+ // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
+ SDValue SrcLo, SrcHi;
+ GetExpandedParts(Src, DAG, SrcLo, SrcHi);
+ SDValue ChainLo = Chain, ChainHi = Chain;
+ // FIXME: This makes unsafe assumptions. The Chain may be a TokenFactor
+ // created for an unrelated purpose, in which case it may not have
+ // exactly two operands. Also, even if it does have two operands, they
+ // may not be the low and high parts of an aligned load that was split.
+ if (Chain.getOpcode() == ISD::TokenFactor) {
+ ChainLo = Chain.getOperand(0);
+ ChainHi = Chain.getOperand(1);
+ }
+ SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other,
+ ChainLo,
+ SrcLo, PtrLo, PtrHi,
+ DAG.getConstant (0 + StoreOffset, MVT::i8));
+
+ SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi,
+ SrcHi, PtrLo, PtrHi,
+ DAG.getConstant (1 + StoreOffset, MVT::i8));
+
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, getChain(Store1),
+ getChain(Store2));
+ }
+ else if (ValueType == MVT::i32) {
+ // Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
+ SDValue SrcLo, SrcHi;
+ GetExpandedParts(Src, DAG, SrcLo, SrcHi);
+
+ // Get the expanded parts of each of SrcLo and SrcHi.
+ SDValue SrcLo1, SrcLo2, SrcHi1, SrcHi2;
+ GetExpandedParts(SrcLo, DAG, SrcLo1, SrcLo2);
+ GetExpandedParts(SrcHi, DAG, SrcHi1, SrcHi2);
+
+ SDValue ChainLo = Chain, ChainHi = Chain;
+ // FIXME: This makes unsafe assumptions; see the FIXME above.
+ if (Chain.getOpcode() == ISD::TokenFactor) {
+ ChainLo = Chain.getOperand(0);
+ ChainHi = Chain.getOperand(1);
+ }
+ SDValue ChainLo1 = ChainLo, ChainLo2 = ChainLo, ChainHi1 = ChainHi,
+ ChainHi2 = ChainHi;
+ // FIXME: This makes unsafe assumptions; see the FIXME above.
+ if (ChainLo.getOpcode() == ISD::TokenFactor) {
+ ChainLo1 = ChainLo.getOperand(0);
+ ChainLo2 = ChainLo.getOperand(1);
+ }
+ // FIXME: This makes unsafe assumptions; see the FIXME above.
+ if (ChainHi.getOpcode() == ISD::TokenFactor) {
+ ChainHi1 = ChainHi.getOperand(0);
+ ChainHi2 = ChainHi.getOperand(1);
+ }
+ SDValue Store1 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other,
+ ChainLo1,
+ SrcLo1, PtrLo, PtrHi,
+ DAG.getConstant (0 + StoreOffset, MVT::i8));
+
+ SDValue Store2 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainLo2,
+ SrcLo2, PtrLo, PtrHi,
+ DAG.getConstant (1 + StoreOffset, MVT::i8));
+
+ SDValue Store3 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi1,
+ SrcHi1, PtrLo, PtrHi,
+ DAG.getConstant (2 + StoreOffset, MVT::i8));
+
+ SDValue Store4 = DAG.getNode(PIC16ISD::PIC16Store, dl, MVT::Other, ChainHi2,
+ SrcHi2, PtrLo, PtrHi,
+ DAG.getConstant (3 + StoreOffset, MVT::i8));
+
+ SDValue RetLo = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ getChain(Store1), getChain(Store2));
+ SDValue RetHi = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ getChain(Store3), getChain(Store4));
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, RetLo, RetHi);
+
+ } else if (ValueType == MVT::i64) {
+ SDValue SrcLo, SrcHi;
+ GetExpandedParts(Src, DAG, SrcLo, SrcHi);
+ SDValue ChainLo = Chain, ChainHi = Chain;
+ // FIXME: This makes unsafe assumptions; see the FIXME above.
+ if (Chain.getOpcode() == ISD::TokenFactor) {
+ ChainLo = Chain.getOperand(0);
+ ChainHi = Chain.getOperand(1);
+ }
+ SDValue Store1 = DAG.getStore(ChainLo, dl, SrcLo, Ptr, NULL,
+ 0 + StoreOffset, false, false, 0);
+
+ Ptr = DAG.getNode(ISD::ADD, dl, Ptr.getValueType(), Ptr,
+ DAG.getConstant(4, Ptr.getValueType()));
+ SDValue Store2 = DAG.getStore(ChainHi, dl, SrcHi, Ptr, NULL,
+ 1 + StoreOffset, false, false, 0);
+
+ return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1,
+ Store2);
+ } else {
+ assert (0 && "value type not supported");
+ return SDValue();
+ }
+}
+
+SDValue PIC16TargetLowering::ExpandExternalSymbol(SDNode *N,
+ SelectionDAG &DAG)
+ const {
+ ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(SDValue(N, 0));
+ // FIXME there isn't really debug info here
+ DebugLoc dl = ES->getDebugLoc();
+
+ SDValue TES = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8);
+ SDValue Offset = DAG.getConstant(0, MVT::i8);
+ SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, TES, Offset);
+ SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, TES, Offset);
+
+ return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, Lo, Hi);
+}
+
+// ExpandGlobalAddress -
+SDValue PIC16TargetLowering::ExpandGlobalAddress(SDNode *N,
+ SelectionDAG &DAG) const {
+ GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(SDValue(N, 0));
+ // FIXME there isn't really debug info here
+ DebugLoc dl = G->getDebugLoc();
+
+ SDValue TGA = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i8,
+ G->getOffset());
+
+ SDValue Offset = DAG.getConstant(0, MVT::i8);
+ SDValue Lo = DAG.getNode(PIC16ISD::Lo, dl, MVT::i8, TGA, Offset);
+ SDValue Hi = DAG.getNode(PIC16ISD::Hi, dl, MVT::i8, TGA, Offset);
+
+ return DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16, Lo, Hi);
+}
+
+bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) const {
+ assert (Op.getNode() != NULL && "Can't operate on NULL SDNode!!");
+
+ if (Op.getOpcode() == ISD::BUILD_PAIR) {
+ if (Op.getOperand(0).getOpcode() == PIC16ISD::Lo)
+ return true;
+ }
+ return false;
+}
+
+// Return true if DirectAddress is in ROM_SPACE
+bool PIC16TargetLowering::isRomAddress(const SDValue &Op) const {
+
+ // RomAddress is a GlobalAddress in ROM_SPACE_
+ // If the Op is not a GlobalAddress return NULL without checking
+ // anything further.
+ if (!isDirectAddress(Op))
+ return false;
+
+ // Its a GlobalAddress.
+ // It is BUILD_PAIR((PIC16Lo TGA), (PIC16Hi TGA)) and Op is BUILD_PAIR
+ SDValue TGA = Op.getOperand(0).getOperand(0);
+ GlobalAddressSDNode *GSDN = dyn_cast<GlobalAddressSDNode>(TGA);
+
+ if (GSDN->getAddressSpace() == PIC16ISD::ROM_SPACE)
+ return true;
+
+ // Any other address space return it false
+ return false;
+}
+
+
+// GetExpandedParts - This function is on the similiar lines as
+// the GetExpandedInteger in type legalizer is. This returns expanded
+// parts of Op in Lo and Hi.
+
+void PIC16TargetLowering::GetExpandedParts(SDValue Op, SelectionDAG &DAG,
+ SDValue &Lo, SDValue &Hi) const {
+ SDNode *N = Op.getNode();
+ DebugLoc dl = N->getDebugLoc();
+ EVT NewVT = getTypeToTransformTo(*DAG.getContext(), N->getValueType(0));
+
+ // Extract the lo component.
+ Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NewVT, Op,
+ DAG.getConstant(0, MVT::i8));
+
+ // extract the hi component
+ Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NewVT, Op,
+ DAG.getConstant(1, MVT::i8));
+}
+
+// Legalize FrameIndex into ExternalSymbol and offset.
+void
+PIC16TargetLowering::LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG,
+ SDValue &ES, int &Offset) const {
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ const Function *Func = MF.getFunction();
+ MachineFrameInfo *MFI = MF.getFrameInfo();
+ PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>();
+ const std::string Name = Func->getName();
+
+ FrameIndexSDNode *FR = dyn_cast<FrameIndexSDNode>(Op);
+
+ // FrameIndices are not stack offsets. But they represent the request
+ // for space on stack. That space requested may be more than one byte.
+ // Therefore, to calculate the stack offset that a FrameIndex aligns
+ // with, we need to traverse all the FrameIndices available earlier in
+ // the list and add their requested size.
+ unsigned FIndex = FR->getIndex();
+ const char *tmpName;
+ if (FIndex < FuncInfo->getReservedFrameCount()) {
+ tmpName = ESNames::createESName(PAN::getFrameLabel(Name));
+ ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
+ Offset = 0;
+ for (unsigned i=0; i<FIndex ; ++i) {
+ Offset += MFI->getObjectSize(i);
+ }
+ } else {
+ // FrameIndex has been made for some temporary storage
+ tmpName = ESNames::createESName(PAN::getTempdataLabel(Name));
+ ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
+ Offset = GetTmpOffsetForFI(FIndex, MFI->getObjectSize(FIndex), MF);
+ }
+
+ return;
+}
+
+// This function legalizes the PIC16 Addresses. If the Pointer is
+// -- Direct address variable residing
+// --> then a Banksel for that variable will be created.
+// -- Rom variable
+// --> then it will be treated as an indirect address.
+// -- Indirect address
+// --> then the address will be loaded into FSR
+// -- ADD with constant operand
+// --> then constant operand of ADD will be returned as Offset
+// and non-constant operand of ADD will be treated as pointer.
+// Returns the high and lo part of the address, and the offset(in case of ADD).
+
+void PIC16TargetLowering::LegalizeAddress(SDValue Ptr, SelectionDAG &DAG,
+ SDValue &Lo, SDValue &Hi,
+ unsigned &Offset, DebugLoc dl) const {
+
+ // Offset, by default, should be 0
+ Offset = 0;
+
+ // If the pointer is ADD with constant,
+ // return the constant value as the offset
+ if (Ptr.getOpcode() == ISD::ADD) {
+ SDValue OperLeft = Ptr.getOperand(0);
+ SDValue OperRight = Ptr.getOperand(1);
+ if ((OperLeft.getOpcode() == ISD::Constant) &&
+ (dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue() < 32 )) {
+ Offset = dyn_cast<ConstantSDNode>(OperLeft)->getZExtValue();
+ Ptr = OperRight;
+ } else if ((OperRight.getOpcode() == ISD::Constant) &&
+ (dyn_cast<ConstantSDNode>(OperRight)->getZExtValue() < 32 )){
+ Offset = dyn_cast<ConstantSDNode>(OperRight)->getZExtValue();
+ Ptr = OperLeft;
+ }
+ }
+
+ // If the pointer is Type i8 and an external symbol
+ // then treat it as direct address.
+ // One example for such case is storing and loading
+ // from function frame during a call
+ if (Ptr.getValueType() == MVT::i8) {
+ switch (Ptr.getOpcode()) {
+ case ISD::TargetExternalSymbol:
+ Lo = Ptr;
+ Hi = DAG.getConstant(1, MVT::i8);
+ return;
+ }
+ }
+
+ // Expansion of FrameIndex has Lo/Hi parts
+ if (isDirectAddress(Ptr)) {
+ SDValue TFI = Ptr.getOperand(0).getOperand(0);
+ int FrameOffset;
+ if (TFI.getOpcode() == ISD::TargetFrameIndex) {
+ LegalizeFrameIndex(TFI, DAG, Lo, FrameOffset);
+ Hi = DAG.getConstant(1, MVT::i8);
+ Offset += FrameOffset;
+ return;
+ } else if (TFI.getOpcode() == ISD::TargetExternalSymbol) {
+ // FrameIndex has already been expanded.
+ // Now just make use of its expansion
+ Lo = TFI;
+ Hi = DAG.getConstant(1, MVT::i8);
+ SDValue FOffset = Ptr.getOperand(0).getOperand(1);
+ assert (FOffset.getOpcode() == ISD::Constant &&
+ "Invalid operand of PIC16ISD::Lo");
+ Offset += dyn_cast<ConstantSDNode>(FOffset)->getZExtValue();
+ return;
+ }
+ }
+
+ if (isDirectAddress(Ptr) && !isRomAddress(Ptr)) {
+ // Direct addressing case for RAM variables. The Hi part is constant
+ // and the Lo part is the TGA itself.
+ Lo = Ptr.getOperand(0).getOperand(0);
+
+ // For direct addresses Hi is a constant. Value 1 for the constant
+ // signifies that banksel needs to generated for it. Value 0 for
+ // the constant signifies that banksel does not need to be generated
+ // for it. Mark it as 1 now and optimize later.
+ Hi = DAG.getConstant(1, MVT::i8);
+ return;
+ }
+
+ // Indirect addresses. Get the hi and lo parts of ptr.
+ GetExpandedParts(Ptr, DAG, Lo, Hi);
+
+ // Put the hi and lo parts into FSR.
+ Lo = DAG.getNode(PIC16ISD::MTLO, dl, MVT::i8, Lo);
+ Hi = DAG.getNode(PIC16ISD::MTHI, dl, MVT::i8, Hi);
+
+ return;
+}
+
+SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) const {
+ LoadSDNode *LD = dyn_cast<LoadSDNode>(SDValue(N, 0));
+ SDValue Chain = LD->getChain();
+ SDValue Ptr = LD->getBasePtr();
+ DebugLoc dl = LD->getDebugLoc();
+
+ SDValue Load, Offset;
+ SDVTList Tys;
+ EVT VT, NewVT;
+ SDValue PtrLo, PtrHi;
+ unsigned LoadOffset;
+
+ // Legalize direct/indirect addresses. This will give the lo and hi parts
+ // of the address and the offset.
+ LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, LoadOffset, dl);
+
+ // Load from the pointer (direct address or FSR)
+ VT = N->getValueType(0);
+ unsigned NumLoads = VT.getSizeInBits() / 8;
+ std::vector<SDValue> PICLoads;
+ unsigned iter;
+ EVT MemVT = LD->getMemoryVT();
+ if(ISD::isNON_EXTLoad(N)) {
+ for (iter=0; iter<NumLoads ; ++iter) {
+ // Add the pointer offset if any
+ Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
+ Tys = DAG.getVTList(MVT::i8, MVT::Other);
+ Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Chain, PtrLo, PtrHi,
+ Offset);
+ PICLoads.push_back(Load);
+ }
+ } else {
+ // If it is extended load then use PIC16Load for Memory Bytes
+ // and for all extended bytes perform action based on type of
+ // extention - i.e. SignExtendedLoad or ZeroExtendedLoad
+
+
+ // For extended loads this is the memory value type
+ // i.e. without any extension
+ EVT MemVT = LD->getMemoryVT();
+ unsigned MemBytes = MemVT.getSizeInBits() / 8;
+ // if MVT::i1 is extended to MVT::i8 then MemBytes will be zero
+ // So set it to one
+ if (MemBytes == 0) MemBytes = 1;
+
+ unsigned ExtdBytes = VT.getSizeInBits() / 8;
+ Offset = DAG.getConstant(LoadOffset, MVT::i8);
+
+ Tys = DAG.getVTList(MVT::i8, MVT::Other);
+ // For MemBytes generate PIC16Load with proper offset
+ for (iter=0; iter < MemBytes; ++iter) {
+ // Add the pointer offset if any
+ Offset = DAG.getConstant(iter + LoadOffset, MVT::i8);
+ Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Chain, PtrLo, PtrHi,
+ Offset);
+ PICLoads.push_back(Load);
+ }
+
+ // For SignExtendedLoad
+ if (ISD::isSEXTLoad(N)) {
+ // For all ExtdBytes use the Right Shifted(Arithmetic) Value of the
+ // highest MemByte
+ SDValue SRA = DAG.getNode(ISD::SRA, dl, MVT::i8, Load,
+ DAG.getConstant(7, MVT::i8));
+ for (iter=MemBytes; iter<ExtdBytes; ++iter) {
+ PICLoads.push_back(SRA);
+ }
+ } else if (ISD::isZEXTLoad(N) || ISD::isEXTLoad(N)) {
+ //} else if (ISD::isZEXTLoad(N)) {
+ // ZeroExtendedLoad -- For all ExtdBytes use constant 0
+ SDValue ConstZero = DAG.getConstant(0, MVT::i8);
+ for (iter=MemBytes; iter<ExtdBytes; ++iter) {
+ PICLoads.push_back(ConstZero);
+ }
+ }
+ }
+ SDValue BP;
+
+ if (VT == MVT::i8) {
+ // Operand of Load is illegal -- Load itself is legal
+ return PICLoads[0];
+ }
+ else if (VT == MVT::i16) {
+ BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, PICLoads[0], PICLoads[1]);
+ if ((MemVT == MVT::i8) || (MemVT == MVT::i1))
+ Chain = getChain(PICLoads[0]);
+ else
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ getChain(PICLoads[0]), getChain(PICLoads[1]));
+ } else if (VT == MVT::i32) {
+ SDValue BPs[2];
+ BPs[0] = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16,
+ PICLoads[0], PICLoads[1]);
+ BPs[1] = DAG.getNode(ISD::BUILD_PAIR, dl, MVT::i16,
+ PICLoads[2], PICLoads[3]);
+ BP = DAG.getNode(ISD::BUILD_PAIR, dl, VT, BPs[0], BPs[1]);
+ if ((MemVT == MVT::i8) || (MemVT == MVT::i1))
+ Chain = getChain(PICLoads[0]);
+ else if (MemVT == MVT::i16)
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ getChain(PICLoads[0]), getChain(PICLoads[1]));
+ else {
+ SDValue Chains[2];
+ Chains[0] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ getChain(PICLoads[0]), getChain(PICLoads[1]));
+ Chains[1] = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ getChain(PICLoads[2]), getChain(PICLoads[3]));
+ Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other,
+ Chains[0], Chains[1]);
+ }
+ }
+ Tys = DAG.getVTList(VT, MVT::Other);
+ return DAG.getNode(ISD::MERGE_VALUES, dl, Tys, BP, Chain);
+}
+
+SDValue PIC16TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) const {
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal shift to lower");
+
+ SDNode *N = Op.getNode();
+ SDValue Value = N->getOperand(0);
+ SDValue Amt = N->getOperand(1);
+ PIC16ISD::PIC16Libcall CallCode;
+ switch (N->getOpcode()) {
+ case ISD::SRA:
+ CallCode = PIC16ISD::SRA_I8;
+ break;
+ case ISD::SHL:
+ CallCode = PIC16ISD::SLL_I8;
+ break;
+ case ISD::SRL:
+ CallCode = PIC16ISD::SRL_I8;
+ break;
+ default:
+ assert ( 0 && "This shift is not implemented yet.");
+ return SDValue();
+ }
+ SmallVector<SDValue, 2> Ops(2);
+ Ops[0] = Value;
+ Ops[1] = Amt;
+ SDValue Call = MakePIC16Libcall(CallCode, N->getValueType(0), &Ops[0], 2,
+ true, DAG, N->getDebugLoc());
+ return Call;
+}
+
+SDValue PIC16TargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) const {
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal multiply to lower");
+
+ SDNode *N = Op.getNode();
+ SmallVector<SDValue, 2> Ops(2);
+ Ops[0] = N->getOperand(0);
+ Ops[1] = N->getOperand(1);
+ SDValue Call = MakePIC16Libcall(PIC16ISD::MUL_I8, N->getValueType(0),
+ &Ops[0], 2, true, DAG, N->getDebugLoc());
+ return Call;
+}
+
+void
+PIC16TargetLowering::LowerOperationWrapper(SDNode *N,
+ SmallVectorImpl<SDValue>&Results,
+ SelectionDAG &DAG) const {
+ SDValue Op = SDValue(N, 0);
+ SDValue Res;
+ unsigned i;
+ switch (Op.getOpcode()) {
+ case ISD::LOAD:
+ Res = ExpandLoad(Op.getNode(), DAG); break;
+ default: {
+ // All other operations are handled in LowerOperation.
+ Res = LowerOperation(Op, DAG);
+ if (Res.getNode())
+ Results.push_back(Res);
+
+ return;
+ }
+ }
+
+ N = Res.getNode();
+ unsigned NumValues = N->getNumValues();
+ for (i = 0; i < NumValues ; i++) {
+ Results.push_back(SDValue(N, i));
+ }
+}
+
+SDValue PIC16TargetLowering::LowerOperation(SDValue Op,
+ SelectionDAG &DAG) const {
+ switch (Op.getOpcode()) {
+ case ISD::ADD:
+ case ISD::ADDC:
+ case ISD::ADDE:
+ return LowerADD(Op, DAG);
+ case ISD::SUB:
+ case ISD::SUBC:
+ case ISD::SUBE:
+ return LowerSUB(Op, DAG);
+ case ISD::LOAD:
+ return ExpandLoad(Op.getNode(), DAG);
+ case ISD::STORE:
+ return ExpandStore(Op.getNode(), DAG);
+ case ISD::MUL:
+ return LowerMUL(Op, DAG);
+ case ISD::SHL:
+ case ISD::SRA:
+ case ISD::SRL:
+ return LowerShift(Op, DAG);
+ case ISD::OR:
+ case ISD::AND:
+ case ISD::XOR:
+ return LowerBinOp(Op, DAG);
+ case ISD::BR_CC:
+ return LowerBR_CC(Op, DAG);
+ case ISD::SELECT_CC:
+ return LowerSELECT_CC(Op, DAG);
+ }
+ return SDValue();
+}
+
+SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op,
+ SelectionDAG &DAG,
+ DebugLoc dl) const {
+ assert (Op.getValueType() == MVT::i8
+ && "illegal value type to store on stack.");
+
+ MachineFunction &MF = DAG.getMachineFunction();
+ const Function *Func = MF.getFunction();
+ const std::string FuncName = Func->getName();
+
+
+ // Put the value on stack.
+ // Get a stack slot index and convert to es.
+ int FI = MF.getFrameInfo()->CreateStackObject(1, 1, false);
+ const char *tmpName = ESNames::createESName(PAN::getTempdataLabel(FuncName));
+ SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
+
+ // Store the value to ES.
+ SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other,
+ DAG.getEntryNode(),
+ Op, ES,
+ DAG.getConstant (1, MVT::i8), // Banksel.
+ DAG.getConstant (GetTmpOffsetForFI(FI, 1, MF),
+ MVT::i8));
+
+ // Load the value from ES.
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other);
+ SDValue Load = DAG.getNode(PIC16ISD::PIC16Load, dl, Tys, Store,
+ ES, DAG.getConstant (1, MVT::i8),
+ DAG.getConstant (GetTmpOffsetForFI(FI, 1, MF),
+ MVT::i8));
+
+ return Load.getValue(0);
+}
+
+SDValue PIC16TargetLowering::
+LowerIndirectCallArguments(SDValue Chain, SDValue InFlag,
+ SDValue DataAddr_Lo, SDValue DataAddr_Hi,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG) const {
+ unsigned NumOps = Outs.size();
+
+ // If call has no arguments then do nothing and return.
+ if (NumOps == 0)
+ return Chain;
+
+ std::vector<SDValue> Ops;
+ SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
+ SDValue Arg, StoreRet;
+
+ // For PIC16 ABI the arguments come after the return value.
+ unsigned RetVals = Ins.size();
+ for (unsigned i = 0, ArgOffset = RetVals; i < NumOps; i++) {
+ // Get the arguments
+ Arg = Outs[i].Val;
+
+ Ops.clear();
+ Ops.push_back(Chain);
+ Ops.push_back(Arg);
+ Ops.push_back(DataAddr_Lo);
+ Ops.push_back(DataAddr_Hi);
+ Ops.push_back(DAG.getConstant(ArgOffset, MVT::i8));
+ Ops.push_back(InFlag);
+
+ StoreRet = DAG.getNode (PIC16ISD::PIC16StWF, dl, Tys, &Ops[0], Ops.size());
+
+ Chain = getChain(StoreRet);
+ InFlag = getOutFlag(StoreRet);
+ ArgOffset++;
+ }
+ return Chain;
+}
+
+SDValue PIC16TargetLowering::
+LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) const {
+ unsigned NumOps = Outs.size();
+ std::string Name;
+ SDValue Arg, StoreAt;
+ EVT ArgVT;
+ unsigned Size=0;
+
+ // If call has no arguments then do nothing and return.
+ if (NumOps == 0)
+ return Chain;
+
+ // FIXME: This portion of code currently assumes only
+ // primitive types being passed as arguments.
+
+ // Legalize the address before use
+ SDValue PtrLo, PtrHi;
+ unsigned AddressOffset;
+ int StoreOffset = 0;
+ LegalizeAddress(ArgLabel, DAG, PtrLo, PtrHi, AddressOffset, dl);
+ SDValue StoreRet;
+
+ std::vector<SDValue> Ops;
+ SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
+ for (unsigned i=0, Offset = 0; i<NumOps; i++) {
+ // Get the argument
+ Arg = Outs[i].Val;
+ StoreOffset = (Offset + AddressOffset);
+
+ // Store the argument on frame
+
+ Ops.clear();
+ Ops.push_back(Chain);
+ Ops.push_back(Arg);
+ Ops.push_back(PtrLo);
+ Ops.push_back(PtrHi);
+ Ops.push_back(DAG.getConstant(StoreOffset, MVT::i8));
+ Ops.push_back(InFlag);
+
+ StoreRet = DAG.getNode (PIC16ISD::PIC16StWF, dl, Tys, &Ops[0], Ops.size());
+
+ Chain = getChain(StoreRet);
+ InFlag = getOutFlag(StoreRet);
+
+ // Update the frame offset to be used for next argument
+ ArgVT = Arg.getValueType();
+ Size = ArgVT.getSizeInBits();
+ Size = Size/8; // Calculate size in bytes
+ Offset += Size; // Increase the frame offset
+ }
+ return Chain;
+}
+
+SDValue PIC16TargetLowering::
+LowerIndirectCallReturn(SDValue Chain, SDValue InFlag,
+ SDValue DataAddr_Lo, SDValue DataAddr_Hi,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+ unsigned RetVals = Ins.size();
+
+ // If call does not have anything to return
+ // then do nothing and go back.
+ if (RetVals == 0)
+ return Chain;
+
+ // Call has something to return
+ SDValue LoadRet;
+
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
+ for(unsigned i=0;i<RetVals;i++) {
+ LoadRet = DAG.getNode(PIC16ISD::PIC16LdWF, dl, Tys, Chain, DataAddr_Lo,
+ DataAddr_Hi, DAG.getConstant(i, MVT::i8),
+ InFlag);
+ InFlag = getOutFlag(LoadRet);
+ Chain = getChain(LoadRet);
+ InVals.push_back(LoadRet);
+ }
+ return Chain;
+}
+
+SDValue PIC16TargetLowering::
+LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+
+ // Currently handling primitive types only. They will come in
+ // i8 parts
+ unsigned RetVals = Ins.size();
+
+ // Return immediately if the return type is void
+ if (RetVals == 0)
+ return Chain;
+
+ // Call has something to return
+
+ // Legalize the address before use
+ SDValue LdLo, LdHi;
+ unsigned LdOffset;
+ LegalizeAddress(RetLabel, DAG, LdLo, LdHi, LdOffset, dl);
+
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
+ SDValue LoadRet;
+
+ for(unsigned i=0, Offset=0;i<RetVals;i++) {
+
+ LoadRet = DAG.getNode(PIC16ISD::PIC16LdWF, dl, Tys, Chain, LdLo, LdHi,
+ DAG.getConstant(LdOffset + Offset, MVT::i8),
+ InFlag);
+
+ InFlag = getOutFlag(LoadRet);
+
+ Chain = getChain(LoadRet);
+ Offset++;
+ InVals.push_back(LoadRet);
+ }
+
+ return Chain;
+}
+
+SDValue
+PIC16TargetLowering::LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) const {
+
+ // Number of values to return
+ unsigned NumRet = Outs.size();
+
+ // Function returns value always on stack with the offset starting
+ // from 0
+ MachineFunction &MF = DAG.getMachineFunction();
+ const Function *F = MF.getFunction();
+ std::string FuncName = F->getName();
+
+ const char *tmpName = ESNames::createESName(PAN::getFrameLabel(FuncName));
+ SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
+ SDValue BS = DAG.getConstant(1, MVT::i8);
+ SDValue RetVal;
+ for(unsigned i=0;i<NumRet; ++i) {
+ RetVal = Outs[i].Val;
+ Chain = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, RetVal,
+ ES, BS,
+ DAG.getConstant (i, MVT::i8));
+
+ }
+ return DAG.getNode(PIC16ISD::RET, dl, MVT::Other, Chain);
+}
+
+void PIC16TargetLowering::
+GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain,
+ SDValue &DataAddr_Lo, SDValue &DataAddr_Hi,
+ SelectionDAG &DAG) const {
+ assert (Callee.getOpcode() == PIC16ISD::PIC16Connect
+ && "Don't know what to do of such callee!!");
+ SDValue ZeroOperand = DAG.getConstant(0, MVT::i8);
+ SDValue SeqStart = DAG.getCALLSEQ_START(Chain, ZeroOperand);
+ Chain = getChain(SeqStart);
+ SDValue OperFlag = getOutFlag(SeqStart); // To manage the data dependency
+
+ // Get the Lo and Hi part of code address
+ SDValue Lo = Callee.getOperand(0);
+ SDValue Hi = Callee.getOperand(1);
+
+ SDValue Data_Lo, Data_Hi;
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag);
+ // Subtract 2 from Address to get the Lower part of DataAddress.
+ SDVTList VTList = DAG.getVTList(MVT::i8, MVT::Flag);
+ Data_Lo = DAG.getNode(ISD::SUBC, dl, VTList, Lo,
+ DAG.getConstant(2, MVT::i8));
+ SDValue Ops[3] = { Hi, DAG.getConstant(0, MVT::i8), Data_Lo.getValue(1)};
+ Data_Hi = DAG.getNode(ISD::SUBE, dl, VTList, Ops, 3);
+ SDValue PCLATH = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, Data_Hi);
+ Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Data_Lo, PCLATH);
+ SDValue Call = DAG.getNode(PIC16ISD::CALLW, dl, Tys, Chain, Callee,
+ OperFlag);
+ Chain = getChain(Call);
+ OperFlag = getOutFlag(Call);
+ SDValue SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand,
+ OperFlag);
+ Chain = getChain(SeqEnd);
+ OperFlag = getOutFlag(SeqEnd);
+
+ // Low part of Data Address
+ DataAddr_Lo = DAG.getNode(PIC16ISD::MTLO, dl, MVT::i8, Call, OperFlag);
+
+ // Make the second call.
+ SeqStart = DAG.getCALLSEQ_START(Chain, ZeroOperand);
+ Chain = getChain(SeqStart);
+ OperFlag = getOutFlag(SeqStart); // To manage the data dependency
+
+ // Subtract 1 from Address to get high part of data address.
+ Data_Lo = DAG.getNode(ISD::SUBC, dl, VTList, Lo,
+ DAG.getConstant(1, MVT::i8));
+ SDValue HiOps[3] = { Hi, DAG.getConstant(0, MVT::i8), Data_Lo.getValue(1)};
+ Data_Hi = DAG.getNode(ISD::SUBE, dl, VTList, HiOps, 3);
+ PCLATH = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, Data_Hi);
+
+ // Use new Lo to make another CALLW
+ Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Data_Lo, PCLATH);
+ Call = DAG.getNode(PIC16ISD::CALLW, dl, Tys, Chain, Callee, OperFlag);
+ Chain = getChain(Call);
+ OperFlag = getOutFlag(Call);
+ SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand,
+ OperFlag);
+ Chain = getChain(SeqEnd);
+ OperFlag = getOutFlag(SeqEnd);
+ // Hi part of Data Address
+ DataAddr_Hi = DAG.getNode(PIC16ISD::MTHI, dl, MVT::i8, Call, OperFlag);
+}
+
+SDValue
+PIC16TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg,
+ bool &isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const {
+ // PIC16 target does not yet support tail call optimization.
+ isTailCall = false;
+
+ assert(Callee.getValueType() == MVT::i16 &&
+ "Don't know how to legalize this call node!!!");
+
+ // The flag to track if this is a direct or indirect call.
+ bool IsDirectCall = true;
+ unsigned RetVals = Ins.size();
+ unsigned NumArgs = Outs.size();
+
+ SDValue DataAddr_Lo, DataAddr_Hi;
+ if (!isa<GlobalAddressSDNode>(Callee) &&
+ !isa<ExternalSymbolSDNode>(Callee)) {
+ IsDirectCall = false; // This is indirect call
+
+ // If this is an indirect call then to pass the arguments
+ // and read the return value back, we need the data address
+ // of the function being called.
+ // To get the data address two more calls need to be made.
+
+ // Come here for indirect calls
+ SDValue Lo, Hi;
+ // Indirect addresses. Get the hi and lo parts of ptr.
+ GetExpandedParts(Callee, DAG, Lo, Hi);
+ // Connect Lo and Hi parts of the callee with the PIC16Connect
+ Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, Lo, Hi);
+
+ // Read DataAddress only if we have to pass arguments or
+ // read return value.
+ if ((RetVals > 0) || (NumArgs > 0))
+ GetDataAddress(dl, Callee, Chain, DataAddr_Lo, DataAddr_Hi, DAG);
+ }
+
+ SDValue ZeroOperand = DAG.getConstant(0, MVT::i8);
+
+ // Start the call sequence.
+ // Carring the Constant 0 along the CALLSEQSTART
+ // because there is nothing else to carry.
+ SDValue SeqStart = DAG.getCALLSEQ_START(Chain, ZeroOperand);
+ Chain = getChain(SeqStart);
+ SDValue OperFlag = getOutFlag(SeqStart); // To manage the data dependency
+ std::string Name;
+
+ // For any direct call - callee will be GlobalAddressNode or
+ // ExternalSymbol
+ SDValue ArgLabel, RetLabel;
+ if (IsDirectCall) {
+ // Considering the GlobalAddressNode case here.
+ if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
+ const GlobalValue *GV = G->getGlobal();
+ Callee = DAG.getTargetGlobalAddress(GV, MVT::i8);
+ Name = G->getGlobal()->getName();
+ } else {// Considering the ExternalSymbol case here
+ ExternalSymbolSDNode *ES = dyn_cast<ExternalSymbolSDNode>(Callee);
+ Callee = DAG.getTargetExternalSymbol(ES->getSymbol(), MVT::i8);
+ Name = ES->getSymbol();
+ }
+
+ // Label for argument passing
+ const char *argFrame = ESNames::createESName(PAN::getArgsLabel(Name));
+ ArgLabel = DAG.getTargetExternalSymbol(argFrame, MVT::i8);
+
+ // Label for reading return value
+ const char *retName = ESNames::createESName(PAN::getRetvalLabel(Name));
+ RetLabel = DAG.getTargetExternalSymbol(retName, MVT::i8);
+ } else {
+ // if indirect call
+ SDValue CodeAddr_Lo = Callee.getOperand(0);
+ SDValue CodeAddr_Hi = Callee.getOperand(1);
+
+ /*CodeAddr_Lo = DAG.getNode(ISD::ADD, dl, MVT::i8, CodeAddr_Lo,
+ DAG.getConstant(2, MVT::i8));*/
+
+ // move Hi part in PCLATH
+ CodeAddr_Hi = DAG.getNode(PIC16ISD::MTPCLATH, dl, MVT::i8, CodeAddr_Hi);
+ Callee = DAG.getNode(PIC16ISD::PIC16Connect, dl, MVT::i8, CodeAddr_Lo,
+ CodeAddr_Hi);
+ }
+
+ // Pass the argument to function before making the call.
+ SDValue CallArgs;
+ if (IsDirectCall) {
+ CallArgs = LowerDirectCallArguments(ArgLabel, Chain, OperFlag,
+ Outs, dl, DAG);
+ Chain = getChain(CallArgs);
+ OperFlag = getOutFlag(CallArgs);
+ } else {
+ CallArgs = LowerIndirectCallArguments(Chain, OperFlag, DataAddr_Lo,
+ DataAddr_Hi, Outs, Ins, dl, DAG);
+ Chain = getChain(CallArgs);
+ OperFlag = getOutFlag(CallArgs);
+ }
+
+ SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
+ SDValue PICCall = DAG.getNode(PIC16ISD::CALL, dl, Tys, Chain, Callee,
+ OperFlag);
+ Chain = getChain(PICCall);
+ OperFlag = getOutFlag(PICCall);
+
+
+ // Carrying the Constant 0 along the CALLSEQSTART
+ // because there is nothing else to carry.
+ SDValue SeqEnd = DAG.getCALLSEQ_END(Chain, ZeroOperand, ZeroOperand,
+ OperFlag);
+ Chain = getChain(SeqEnd);
+ OperFlag = getOutFlag(SeqEnd);
+
+ // Lower the return value reading after the call.
+ if (IsDirectCall)
+ return LowerDirectCallReturn(RetLabel, Chain, OperFlag,
+ Ins, dl, DAG, InVals);
+ else
+ return LowerIndirectCallReturn(Chain, OperFlag, DataAddr_Lo,
+ DataAddr_Hi, Ins, dl, DAG, InVals);
+}
+
+bool PIC16TargetLowering::isDirectLoad(const SDValue Op) const {
+ if (Op.getOpcode() == PIC16ISD::PIC16Load)
+ if (Op.getOperand(1).getOpcode() == ISD::TargetGlobalAddress
+ || Op.getOperand(1).getOpcode() == ISD::TargetExternalSymbol)
+ return true;
+ return false;
+}
+
+// NeedToConvertToMemOp - Returns true if one of the operands of the
+// operation 'Op' needs to be put into memory. Also returns the
+// operand no. of the operand to be converted in 'MemOp'. Remember, PIC16 has
+// no instruction that can operation on two registers. Most insns take
+// one register and one memory operand (addwf) / Constant (addlw).
+bool PIC16TargetLowering::NeedToConvertToMemOp(SDValue Op, unsigned &MemOp,
+ SelectionDAG &DAG) const {
+ // If one of the operand is a constant, return false.
+ if (Op.getOperand(0).getOpcode() == ISD::Constant ||
+ Op.getOperand(1).getOpcode() == ISD::Constant)
+ return false;
+
+ // Return false if one of the operands is already a direct
+ // load and that operand has only one use.
+ if (isDirectLoad(Op.getOperand(0))) {
+ if (Op.getOperand(0).hasOneUse()) {
+ // Legal and profitable folding check uses the NodeId of DAG nodes.
+ // This NodeId is assigned by topological order. Therefore first
+ // assign topological order then perform legal and profitable check.
+ // Note:- Though this ordering is done before begining with legalization,
+ // newly added node during legalization process have NodeId=-1 (NewNode)
+ // therefore before performing any check proper ordering of the node is
+ // required.
+ DAG.AssignTopologicalOrder();
+
+ // Direct load operands are folded in binary operations. But before folding
+ // verify if this folding is legal. Fold only if it is legal otherwise
+ // convert this direct load to a separate memory operation.
+ if (SelectionDAGISel::IsLegalToFold(Op.getOperand(0),
+ Op.getNode(), Op.getNode(),
+ CodeGenOpt::Default))
+ return false;
+ else
+ MemOp = 0;
+ }
+ }
+
+ // For operations that are non-cummutative there is no need to check
+ // for right operand because folding right operand may result in
+ // incorrect operation.
+ if (! SelectionDAG::isCommutativeBinOp(Op.getOpcode()))
+ return true;
+
+ if (isDirectLoad(Op.getOperand(1))) {
+ if (Op.getOperand(1).hasOneUse()) {
+ // Legal and profitable folding check uses the NodeId of DAG nodes.
+ // This NodeId is assigned by topological order. Therefore first
+ // assign topological order then perform legal and profitable check.
+ // Note:- Though this ordering is done before begining with legalization,
+ // newly added node during legalization process have NodeId=-1 (NewNode)
+ // therefore before performing any check proper ordering of the node is
+ // required.
+ DAG.AssignTopologicalOrder();
+
+ // Direct load operands are folded in binary operations. But before folding
+ // verify if this folding is legal. Fold only if it is legal otherwise
+ // convert this direct load to a separate memory operation.
+ if (SelectionDAGISel::IsLegalToFold(Op.getOperand(1),
+ Op.getNode(), Op.getNode(),
+ CodeGenOpt::Default))
+ return false;
+ else
+ MemOp = 1;
+ }
+ }
+ return true;
+}
+
+// LowerBinOp - Lower a commutative binary operation that does not
+// affect status flag carry.
+SDValue PIC16TargetLowering::LowerBinOp(SDValue Op, SelectionDAG &DAG) const {
+ DebugLoc dl = Op.getDebugLoc();
+
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal Op to lower");
+
+ unsigned MemOp = 1;
+ if (NeedToConvertToMemOp(Op, MemOp, DAG)) {
+ // Put one value on stack.
+ SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl);
+
+ return DAG.getNode(Op.getOpcode(), dl, MVT::i8, Op.getOperand(MemOp ^ 1),
+ NewVal);
+ }
+ else {
+ return Op;
+ }
+}
+
+// LowerADD - Lower all types of ADD operations including the ones
+// that affects carry.
+SDValue PIC16TargetLowering::LowerADD(SDValue Op, SelectionDAG &DAG) const {
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal add to lower");
+ DebugLoc dl = Op.getDebugLoc();
+ unsigned MemOp = 1;
+ if (NeedToConvertToMemOp(Op, MemOp, DAG)) {
+ // Put one value on stack.
+ SDValue NewVal = ConvertToMemOperand (Op.getOperand(MemOp), DAG, dl);
+
+ // ADDC and ADDE produce two results.
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+
+ // ADDE has three operands, the last one is the carry bit.
+ if (Op.getOpcode() == ISD::ADDE)
+ return DAG.getNode(Op.getOpcode(), dl, Tys, Op.getOperand(MemOp ^ 1),
+ NewVal, Op.getOperand(2));
+ // ADDC has two operands.
+ else if (Op.getOpcode() == ISD::ADDC)
+ return DAG.getNode(Op.getOpcode(), dl, Tys, Op.getOperand(MemOp ^ 1),
+ NewVal);
+ // ADD it is. It produces only one result.
+ else
+ return DAG.getNode(Op.getOpcode(), dl, MVT::i8, Op.getOperand(MemOp ^ 1),
+ NewVal);
+ }
+ else
+ return Op;
+}
+
+SDValue PIC16TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) const {
+ DebugLoc dl = Op.getDebugLoc();
+ // We should have handled larger operands in type legalizer itself.
+ assert (Op.getValueType() == MVT::i8 && "illegal sub to lower");
+ unsigned MemOp = 1;
+ SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag);
+
+ // Since we don't have an instruction for X - c ,
+ // we can change it to X + (-c)
+ ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op.getOperand(1));
+ if (C && (Op.getOpcode() == ISD::SUB))
+ {
+ return DAG.getNode(ISD::ADD,
+ dl, MVT::i8, Op.getOperand(0),
+ DAG.getConstant(0-(C->getZExtValue()), MVT::i8));
+ }
+
+ if (NeedToConvertToMemOp(Op, MemOp, DAG) ||
+ (isDirectLoad(Op.getOperand(1)) &&
+ (!isDirectLoad(Op.getOperand(0))) &&
+ (Op.getOperand(0).getOpcode() != ISD::Constant)))
+ {
+ // Put first operand on stack.
+ SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG, dl);
+
+ switch (Op.getOpcode()) {
+ default:
+ assert (0 && "Opcode unknown.");
+ case ISD::SUBE:
+ return DAG.getNode(Op.getOpcode(),
+ dl, Tys, NewVal, Op.getOperand(1),
+ Op.getOperand(2));
+ break;
+ case ISD::SUBC:
+ return DAG.getNode(Op.getOpcode(),
+ dl, Tys, NewVal, Op.getOperand(1));
+ break;
+ case ISD::SUB:
+ return DAG.getNode(Op.getOpcode(),
+ dl, MVT::i8, NewVal, Op.getOperand(1));
+ break;
+ }
+ }
+ else
+ return Op;
+}
+
+void PIC16TargetLowering::InitReservedFrameCount(const Function *F,
+ SelectionDAG &DAG) const {
+ MachineFunction &MF = DAG.getMachineFunction();
+ PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>();
+
+ unsigned NumArgs = F->arg_size();
+
+ bool isVoidFunc = (F->getReturnType()->getTypeID() == Type::VoidTyID);
+
+ if (isVoidFunc)
+ FuncInfo->setReservedFrameCount(NumArgs);
+ else
+ FuncInfo->setReservedFrameCount(NumArgs + 1);
+}
+
+// LowerFormalArguments - Argument values are loaded from the
+// <fname>.args + offset. All arguments are already broken to leaglized
+// types, so the offset just runs from 0 to NumArgVals - 1.
+
+SDValue
+PIC16TargetLowering::LowerFormalArguments(SDValue Chain,
+ CallingConv::ID CallConv,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl,
+ SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals)
+ const {
+ unsigned NumArgVals = Ins.size();
+
+ // Get the callee's name to create the <fname>.args label to pass args.
+ MachineFunction &MF = DAG.getMachineFunction();
+ const Function *F = MF.getFunction();
+ std::string FuncName = F->getName();
+
+ // Reset the map of FI and TmpOffset
+ ResetTmpOffsetMap(DAG);
+ // Initialize the ReserveFrameCount
+ InitReservedFrameCount(F, DAG);
+
+ // Create the <fname>.args external symbol.
+ const char *tmpName = ESNames::createESName(PAN::getArgsLabel(FuncName));
+ SDValue ES = DAG.getTargetExternalSymbol(tmpName, MVT::i8);
+
+ // Load arg values from the label + offset.
+ SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Other);
+ SDValue BS = DAG.getConstant(1, MVT::i8);
+ for (unsigned i = 0; i < NumArgVals ; ++i) {
+ SDValue Offset = DAG.getConstant(i, MVT::i8);
+ SDValue PICLoad = DAG.getNode(PIC16ISD::PIC16LdArg, dl, VTs, Chain, ES, BS,
+ Offset);
+ Chain = getChain(PICLoad);
+ InVals.push_back(PICLoad);
+ }
+
+ return Chain;
+}
+
+// Perform DAGCombine of PIC16Load.
+// FIXME - Need a more elaborate comment here.
+SDValue PIC16TargetLowering::
+PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const {
+ SelectionDAG &DAG = DCI.DAG;
+ SDValue Chain = N->getOperand(0);
+ if (N->hasNUsesOfValue(0, 0)) {
+ DAG.ReplaceAllUsesOfValueWith(SDValue(N,1), Chain);
+ }
+ return SDValue();
+}
+
+// For all the functions with arguments some STORE nodes are generated
+// that store the argument on the frameindex. However in PIC16 the arguments
+// are passed on stack only. Therefore these STORE nodes are redundant.
+// To remove these STORE nodes will be removed in PerformStoreCombine
+//
+// Currently this function is doint nothing and will be updated for removing
+// unwanted store operations
+SDValue PIC16TargetLowering::
+PerformStoreCombine(SDNode *N, DAGCombinerInfo &DCI) const {
+ return SDValue(N, 0);
+ /*
+ // Storing an undef value is of no use, so remove it
+ if (isStoringUndef(N, Chain, DAG)) {
+ return Chain; // remove the store and return the chain
+ }
+ //else everything is ok.
+ return SDValue(N, 0);
+ */
+}
+
+SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N,
+ DAGCombinerInfo &DCI) const {
+ switch (N->getOpcode()) {
+ case ISD::STORE:
+ return PerformStoreCombine(N, DCI);
+ case PIC16ISD::PIC16Load:
+ return PerformPIC16LoadCombine(N, DCI);
+ }
+ return SDValue();
+}
+
+static PIC16CC::CondCodes IntCCToPIC16CC(ISD::CondCode CC) {
+ switch (CC) {
+ default: llvm_unreachable("Unknown condition code!");
+ case ISD::SETNE: return PIC16CC::NE;
+ case ISD::SETEQ: return PIC16CC::EQ;
+ case ISD::SETGT: return PIC16CC::GT;
+ case ISD::SETGE: return PIC16CC::GE;
+ case ISD::SETLT: return PIC16CC::LT;
+ case ISD::SETLE: return PIC16CC::LE;
+ case ISD::SETULT: return PIC16CC::ULT;
+ case ISD::SETULE: return PIC16CC::ULE;
+ case ISD::SETUGE: return PIC16CC::UGE;
+ case ISD::SETUGT: return PIC16CC::UGT;
+ }
+}
+
+// Look at LHS/RHS/CC and see if they are a lowered setcc instruction. If so
+// set LHS/RHS and SPCC to the LHS/RHS of the setcc and SPCC to the condition.
+static void LookThroughSetCC(SDValue &LHS, SDValue &RHS,
+ ISD::CondCode CC, unsigned &SPCC) {
+ if (isa<ConstantSDNode>(RHS) &&
+ cast<ConstantSDNode>(RHS)->getZExtValue() == 0 &&
+ CC == ISD::SETNE &&
+ (LHS.getOpcode() == PIC16ISD::SELECT_ICC &&
+ LHS.getOperand(3).getOpcode() == PIC16ISD::SUBCC) &&
+ isa<ConstantSDNode>(LHS.getOperand(0)) &&
+ isa<ConstantSDNode>(LHS.getOperand(1)) &&
+ cast<ConstantSDNode>(LHS.getOperand(0))->getZExtValue() == 1 &&
+ cast<ConstantSDNode>(LHS.getOperand(1))->getZExtValue() == 0) {
+ SDValue CMPCC = LHS.getOperand(3);
+ SPCC = cast<ConstantSDNode>(LHS.getOperand(2))->getZExtValue();
+ LHS = CMPCC.getOperand(0);
+ RHS = CMPCC.getOperand(1);
+ }
+}
+
+// Returns appropriate CMP insn and corresponding condition code in PIC16CC
+SDValue PIC16TargetLowering::getPIC16Cmp(SDValue LHS, SDValue RHS,
+ unsigned CC, SDValue &PIC16CC,
+ SelectionDAG &DAG, DebugLoc dl) const {
+ PIC16CC::CondCodes CondCode = (PIC16CC::CondCodes) CC;
+
+ // PIC16 sub is literal - W. So Swap the operands and condition if needed.
+ // i.e. a < 12 can be rewritten as 12 > a.
+ if (RHS.getOpcode() == ISD::Constant) {
+
+ SDValue Tmp = LHS;
+ LHS = RHS;
+ RHS = Tmp;
+
+ switch (CondCode) {
+ default: break;
+ case PIC16CC::LT:
+ CondCode = PIC16CC::GT;
+ break;
+ case PIC16CC::GT:
+ CondCode = PIC16CC::LT;
+ break;
+ case PIC16CC::ULT:
+ CondCode = PIC16CC::UGT;
+ break;
+ case PIC16CC::UGT:
+ CondCode = PIC16CC::ULT;
+ break;
+ case PIC16CC::GE:
+ CondCode = PIC16CC::LE;
+ break;
+ case PIC16CC::LE:
+ CondCode = PIC16CC::GE;
+ break;
+ case PIC16CC::ULE:
+ CondCode = PIC16CC::UGE;
+ break;
+ case PIC16CC::UGE:
+ CondCode = PIC16CC::ULE;
+ break;
+ }
+ }
+
+ PIC16CC = DAG.getConstant(CondCode, MVT::i8);
+
+ // These are signed comparisons.
+ SDValue Mask = DAG.getConstant(128, MVT::i8);
+ if (isSignedComparison(CondCode)) {
+ LHS = DAG.getNode (ISD::XOR, dl, MVT::i8, LHS, Mask);
+ RHS = DAG.getNode (ISD::XOR, dl, MVT::i8, RHS, Mask);
+ }
+
+ SDVTList VTs = DAG.getVTList (MVT::i8, MVT::Flag);
+ // We can use a subtract operation to set the condition codes. But
+ // we need to put one operand in memory if required.
+ // Nothing to do if the first operand is already a valid type (direct load
+ // for subwf and literal for sublw) and it is used by this operation only.
+ if ((LHS.getOpcode() == ISD::Constant || isDirectLoad(LHS))
+ && LHS.hasOneUse())
+ return DAG.getNode(PIC16ISD::SUBCC, dl, VTs, LHS, RHS);
+
+ // else convert the first operand to mem.
+ LHS = ConvertToMemOperand (LHS, DAG, dl);
+ return DAG.getNode(PIC16ISD::SUBCC, dl, VTs, LHS, RHS);
+}
+
+
+SDValue PIC16TargetLowering::LowerSELECT_CC(SDValue Op,
+ SelectionDAG &DAG) const {
+ SDValue LHS = Op.getOperand(0);
+ SDValue RHS = Op.getOperand(1);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get();
+ SDValue TrueVal = Op.getOperand(2);
+ SDValue FalseVal = Op.getOperand(3);
+ unsigned ORIGCC = ~0;
+ DebugLoc dl = Op.getDebugLoc();
+
+ // If this is a select_cc of a "setcc", and if the setcc got lowered into
+ // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
+ // i.e.
+ // A setcc: lhs, rhs, cc is expanded by llvm to
+ // select_cc: result of setcc, 0, 1, 0, setne
+ // We can think of it as:
+ // select_cc: lhs, rhs, 1, 0, cc
+ LookThroughSetCC(LHS, RHS, CC, ORIGCC);
+ if (ORIGCC == ~0U) ORIGCC = IntCCToPIC16CC (CC);
+
+ SDValue PIC16CC;
+ SDValue Cmp = getPIC16Cmp(LHS, RHS, ORIGCC, PIC16CC, DAG, dl);
+
+ return DAG.getNode (PIC16ISD::SELECT_ICC, dl, TrueVal.getValueType(), TrueVal,
+ FalseVal, PIC16CC, Cmp.getValue(1));
+}
+
+MachineBasicBlock *
+PIC16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *BB) const {
+ const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo();
+ unsigned CC = (PIC16CC::CondCodes)MI->getOperand(3).getImm();
+ DebugLoc dl = MI->getDebugLoc();
+
+ // To "insert" a SELECT_CC instruction, we actually have to insert the diamond
+ // control-flow pattern. The incoming instruction knows the destination vreg
+ // to set, the condition code register to branch on, the true/false values to
+ // select between, and a branch opcode to use.
+ const BasicBlock *LLVM_BB = BB->getBasicBlock();
+ MachineFunction::iterator It = BB;
+ ++It;
+
+ // thisMBB:
+ // ...
+ // TrueVal = ...
+ // [f]bCC copy1MBB
+ // fallthrough --> copy0MBB
+ MachineBasicBlock *thisMBB = BB;
+ MachineFunction *F = BB->getParent();
+ MachineBasicBlock *copy0MBB = F->CreateMachineBasicBlock(LLVM_BB);
+ MachineBasicBlock *sinkMBB = F->CreateMachineBasicBlock(LLVM_BB);
+ BuildMI(BB, dl, TII.get(PIC16::pic16brcond)).addMBB(sinkMBB).addImm(CC);
+ F->insert(It, copy0MBB);
+ F->insert(It, sinkMBB);
+
+ // Update machine-CFG edges by first adding all successors of the current
+ // block to the new block which will contain the Phi node for the select.
+ for (MachineBasicBlock::succ_iterator I = BB->succ_begin(),
+ E = BB->succ_end(); I != E; ++I)
+ sinkMBB->addSuccessor(*I);
+ // Next, remove all successors of the current block, and add the true
+ // and fallthrough blocks as its successors.
+ while (!BB->succ_empty())
+ BB->removeSuccessor(BB->succ_begin());
+ // Next, add the true and fallthrough blocks as its successors.
+ BB->addSuccessor(copy0MBB);
+ BB->addSuccessor(sinkMBB);
+
+ // copy0MBB:
+ // %FalseValue = ...
+ // # fallthrough to sinkMBB
+ BB = copy0MBB;
+
+ // Update machine-CFG edges
+ BB->addSuccessor(sinkMBB);
+
+ // sinkMBB:
+ // %Result = phi [ %FalseValue, copy0MBB ], [ %TrueValue, thisMBB ]
+ // ...
+ BB = sinkMBB;
+ BuildMI(BB, dl, TII.get(PIC16::PHI), MI->getOperand(0).getReg())
+ .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB)
+ .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB);
+
+ F->DeleteMachineInstr(MI); // The pseudo instruction is gone now.
+ return BB;
+}
+
+
+SDValue PIC16TargetLowering::LowerBR_CC(SDValue Op, SelectionDAG &DAG) const {
+ SDValue Chain = Op.getOperand(0);
+ ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get();
+ SDValue LHS = Op.getOperand(2); // LHS of the condition.
+ SDValue RHS = Op.getOperand(3); // RHS of the condition.
+ SDValue Dest = Op.getOperand(4); // BB to jump to
+ unsigned ORIGCC = ~0;
+ DebugLoc dl = Op.getDebugLoc();
+
+ // If this is a br_cc of a "setcc", and if the setcc got lowered into
+ // an CMP[IF]CC/SELECT_[IF]CC pair, find the original compared values.
+ LookThroughSetCC(LHS, RHS, CC, ORIGCC);
+ if (ORIGCC == ~0U) ORIGCC = IntCCToPIC16CC (CC);
+
+ // Get the Compare insn and condition code.
+ SDValue PIC16CC;
+ SDValue Cmp = getPIC16Cmp(LHS, RHS, ORIGCC, PIC16CC, DAG, dl);
+
+ return DAG.getNode(PIC16ISD::BRCOND, dl, MVT::Other, Chain, Dest, PIC16CC,
+ Cmp.getValue(1));
+}
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.h b/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.h
new file mode 100644
index 0000000..eea17f8
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16ISelLowering.h
@@ -0,0 +1,246 @@
+//===-- PIC16ISelLowering.h - PIC16 DAG Lowering Interface ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the interfaces that PIC16 uses to lower LLVM code into a
+// selection DAG.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16ISELLOWERING_H
+#define PIC16ISELLOWERING_H
+
+#include "PIC16.h"
+#include "PIC16Subtarget.h"
+#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/Target/TargetLowering.h"
+#include <map>
+
+namespace llvm {
+ namespace PIC16ISD {
+ enum NodeType {
+ // Start the numbering from where ISD NodeType finishes.
+ FIRST_NUMBER = ISD::BUILTIN_OP_END,
+
+ Lo, // Low 8-bits of GlobalAddress.
+ Hi, // High 8-bits of GlobalAddress.
+ PIC16Load,
+ PIC16LdArg, // This is replica of PIC16Load but used to load function
+ // arguments and is being used for facilitating for some
+ // store removal optimizations.
+
+ PIC16LdWF,
+ PIC16Store,
+ PIC16StWF,
+ Banksel,
+ MTLO, // Move to low part of FSR
+ MTHI, // Move to high part of FSR
+ MTPCLATH, // Move to PCLATCH
+ PIC16Connect, // General connector for PIC16 nodes
+ BCF,
+ LSLF, // PIC16 Logical shift left
+ LRLF, // PIC16 Logical shift right
+ RLF, // Rotate left through carry
+ RRF, // Rotate right through carry
+ CALL, // PIC16 Call instruction
+ CALLW, // PIC16 CALLW instruction
+ SUBCC, // Compare for equality or inequality.
+ SELECT_ICC, // Psuedo to be caught in schedular and expanded to brcond.
+ BRCOND, // Conditional branch.
+ RET, // Return.
+ Dummy
+ };
+
+ // Keep track of different address spaces.
+ enum AddressSpace {
+ RAM_SPACE = 0, // RAM address space
+ ROM_SPACE = 1 // ROM address space number is 1
+ };
+ enum PIC16Libcall {
+ MUL_I8 = RTLIB::UNKNOWN_LIBCALL + 1,
+ SRA_I8,
+ SLL_I8,
+ SRL_I8,
+ PIC16UnknownCall
+ };
+ }
+
+
+ //===--------------------------------------------------------------------===//
+ // TargetLowering Implementation
+ //===--------------------------------------------------------------------===//
+ class PIC16TargetLowering : public TargetLowering {
+ public:
+ explicit PIC16TargetLowering(PIC16TargetMachine &TM);
+
+ /// getTargetNodeName - This method returns the name of a target specific
+ /// DAG node.
+ virtual const char *getTargetNodeName(unsigned Opcode) const;
+ /// getSetCCResultType - Return the ISD::SETCC ValueType
+ virtual MVT::SimpleValueType getSetCCResultType(EVT ValType) const;
+ virtual MVT::SimpleValueType getCmpLibcallReturnType() const;
+ SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerADD(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSUB(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerBinOp(SDValue Op, SelectionDAG &DAG) const;
+ // Call returns
+ SDValue
+ LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+ SDValue
+ LowerIndirectCallReturn(SDValue Chain, SDValue InFlag,
+ SDValue DataAddr_Lo, SDValue DataAddr_Hi,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+
+ // Call arguments
+ SDValue
+ LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) const;
+
+ SDValue
+ LowerIndirectCallArguments(SDValue Chain, SDValue InFlag,
+ SDValue DataAddr_Lo, SDValue DataAddr_Hi,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG) const;
+
+ SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
+ SDValue getPIC16Cmp(SDValue LHS, SDValue RHS, unsigned OrigCC, SDValue &CC,
+ SelectionDAG &DAG, DebugLoc dl) const;
+ virtual MachineBasicBlock *
+ EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *MBB) const;
+
+ virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
+ virtual void ReplaceNodeResults(SDNode *N,
+ SmallVectorImpl<SDValue> &Results,
+ SelectionDAG &DAG) const;
+ virtual void LowerOperationWrapper(SDNode *N,
+ SmallVectorImpl<SDValue> &Results,
+ SelectionDAG &DAG) const;
+
+ virtual SDValue
+ LowerFormalArguments(SDValue Chain,
+ CallingConv::ID CallConv,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+
+ virtual SDValue
+ LowerCall(SDValue Chain, SDValue Callee,
+ CallingConv::ID CallConv, bool isVarArg, bool &isTailCall,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ DebugLoc dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const;
+
+ virtual SDValue
+ LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ DebugLoc dl, SelectionDAG &DAG) const;
+
+ SDValue ExpandStore(SDNode *N, SelectionDAG &DAG) const;
+ SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG) const;
+ SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) const;
+ SDValue ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG) const;
+ SDValue ExpandFrameIndex(SDNode *N, SelectionDAG &DAG) const;
+
+ SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+ SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+ SDValue PerformStoreCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+
+ // This function returns the Tmp Offset for FrameIndex. If any TmpOffset
+ // already exists for the FI then it returns the same else it creates the
+ // new offset and returns.
+ unsigned GetTmpOffsetForFI(unsigned FI, unsigned slot_size,
+ MachineFunction &MF) const;
+ void ResetTmpOffsetMap(SelectionDAG &DAG) const;
+ void InitReservedFrameCount(const Function *F,
+ SelectionDAG &DAG) const;
+
+ /// getFunctionAlignment - Return the Log2 alignment of this function.
+ virtual unsigned getFunctionAlignment(const Function *) const {
+ // FIXME: The function never seems to be aligned.
+ return 1;
+ }
+ private:
+ // If the Node is a BUILD_PAIR representing a direct Address,
+ // then this function will return true.
+ bool isDirectAddress(const SDValue &Op) const;
+
+ // If the Node is a DirectAddress in ROM_SPACE then this
+ // function will return true
+ bool isRomAddress(const SDValue &Op) const;
+
+ // Extract the Lo and Hi component of Op.
+ void GetExpandedParts(SDValue Op, SelectionDAG &DAG, SDValue &Lo,
+ SDValue &Hi) const;
+
+
+ // Load pointer can be a direct or indirect address. In PIC16 direct
+ // addresses need Banksel and Indirect addresses need to be loaded to
+ // FSR first. Handle address specific cases here.
+ void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain,
+ SDValue &NewPtr, unsigned &Offset, DebugLoc dl) const;
+
+ // FrameIndex should be broken down into ExternalSymbol and FrameOffset.
+ void LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, SDValue &ES,
+ int &Offset) const;
+
+ // For indirect calls data address of the callee frame need to be
+ // extracted. This function fills the arguments DataAddr_Lo and
+ // DataAddr_Hi with the address of the callee frame.
+ void GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain,
+ SDValue &DataAddr_Lo, SDValue &DataAddr_Hi,
+ SelectionDAG &DAG) const;
+
+ // We can not have both operands of a binary operation in W.
+ // This function is used to put one operand on stack and generate a load.
+ SDValue ConvertToMemOperand(SDValue Op, SelectionDAG &DAG,
+ DebugLoc dl) const;
+
+ // This function checks if we need to put an operand of an operation on
+ // stack and generate a load or not.
+ // DAG parameter is required to access DAG information during
+ // analysis.
+ bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp,
+ SelectionDAG &DAG) const;
+
+ /// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
+ /// make the right decision when generating code for different targets.
+ const PIC16Subtarget *Subtarget;
+
+
+ // Extending the LIB Call framework of LLVM
+ // to hold the names of PIC16Libcalls.
+ const char *PIC16LibcallNames[PIC16ISD::PIC16UnknownCall];
+
+ // To set and retrieve the lib call names.
+ void setPIC16LibcallName(PIC16ISD::PIC16Libcall Call, const char *Name);
+ const char *getPIC16LibcallName(PIC16ISD::PIC16Libcall Call) const;
+
+ // Make PIC16 Libcall.
+ SDValue MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, EVT RetVT,
+ const SDValue *Ops, unsigned NumOps, bool isSigned,
+ SelectionDAG &DAG, DebugLoc dl) const;
+
+ // Check if operation has a direct load operand.
+ inline bool isDirectLoad(const SDValue Op) const;
+ };
+} // namespace llvm
+
+#endif // PIC16ISELLOWERING_H
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16InstrFormats.td b/contrib/llvm/lib/Target/PIC16/PIC16InstrFormats.td
new file mode 100644
index 0000000..e213ea8
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16InstrFormats.td
@@ -0,0 +1,117 @@
+//===- PIC16InstrFormats.td - PIC16 Instruction Formats-------*- tblgen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Describe PIC16 instructions format
+//
+// All the possible PIC16 fields are:
+//
+// opcode - operation code.
+// f - 7-bit register file address.
+// d - 1-bit direction specifier
+// k - 8/11 bit literals
+// b - 3 bits bit num specifier
+//
+//===----------------------------------------------------------------------===//
+
+// Generic PIC16 Format
+// PIC16 Instructions are 14-bit wide.
+
+// FIXME: Add Cooper Specific Formats if any.
+
+class PIC16Inst<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : Instruction {
+ field bits<14> Inst;
+
+ let Namespace = "PIC16";
+ dag OutOperandList = outs;
+ dag InOperandList = ins;
+ let AsmString = asmstr;
+ let Pattern = pattern;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Byte Oriented instruction class in PIC16 : <|opcode|d|f|>
+// opcode = 6 bits.
+// d = direction = 1 bit.
+// f = file register address = 7 bits.
+//===----------------------------------------------------------------------===//
+
+class ByteFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ :PIC16Inst<outs, ins, asmstr, pattern> {
+ bits<1> d;
+ bits<7> f;
+
+ let Inst{13-8} = opcode;
+
+ let Inst{7} = d;
+ let Inst{6-0} = f;
+}
+
+//===----------------------------------------------------------------------===//
+// Bit Oriented instruction class in PIC16 : <|opcode|b|f|>
+// opcode = 4 bits.
+// b = bit specifier = 3 bits.
+// f = file register address = 7 bits.
+//===----------------------------------------------------------------------===//
+
+class BitFormat<bits<4> opcode, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ : PIC16Inst<outs, ins, asmstr, pattern> {
+ bits<3> b;
+ bits<7> f;
+
+ let Inst{13-10} = opcode;
+
+ let Inst{9-7} = b;
+ let Inst{6-0} = f;
+}
+
+//===----------------------------------------------------------------------===//
+// Literal Format instruction class in PIC16 : <|opcode|k|>
+// opcode = 6 bits
+// k = literal = 8 bits
+//===----------------------------------------------------------------------===//
+
+class LiteralFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ : PIC16Inst<outs, ins, asmstr, pattern> {
+ bits<8> k;
+
+ let Inst{13-8} = opcode;
+
+ let Inst{7-0} = k;
+}
+
+//===----------------------------------------------------------------------===//
+// Control Format instruction class in PIC16 : <|opcode|k|>
+// opcode = 3 bits.
+// k = jump address = 11 bits.
+//===----------------------------------------------------------------------===//
+
+class ControlFormat<bits<3> opcode, dag outs, dag ins, string asmstr,
+ list<dag> pattern>
+ : PIC16Inst<outs, ins, asmstr, pattern> {
+ bits<11> k;
+
+ let Inst{13-11} = opcode;
+
+ let Inst{10-0} = k;
+}
+
+//===----------------------------------------------------------------------===//
+// Pseudo instruction class in PIC16
+//===----------------------------------------------------------------------===//
+
+class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
+ : PIC16Inst<outs, ins, asmstr, pattern> {
+ let Inst{13-6} = 0;
+}
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.cpp b/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.cpp
new file mode 100644
index 0000000..793dd9f
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.cpp
@@ -0,0 +1,244 @@
+//===- PIC16InstrInfo.cpp - PIC16 Instruction Information -----------------===//
+//
+// 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 implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16.h"
+#include "PIC16ABINames.h"
+#include "PIC16InstrInfo.h"
+#include "PIC16TargetMachine.h"
+#include "PIC16GenInstrInfo.inc"
+#include "llvm/Function.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/ErrorHandling.h"
+#include <cstdio>
+
+
+using namespace llvm;
+
+// FIXME: Add the subtarget support on this constructor.
+PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm)
+ : TargetInstrInfoImpl(PIC16Insts, array_lengthof(PIC16Insts)),
+ TM(tm),
+ RegInfo(*this, *TM.getSubtargetImpl()) {}
+
+
+/// isStoreToStackSlot - If the specified machine instruction is a direct
+/// store to a stack slot, return the virtual or physical register number of
+/// the source reg along with the FrameIndex of the loaded stack slot.
+/// If not, return 0. This predicate must return 0 if the instruction has
+/// any side effects other than storing to the stack slot.
+unsigned PIC16InstrInfo::isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const {
+ if (MI->getOpcode() == PIC16::movwf
+ && MI->getOperand(0).isReg()
+ && MI->getOperand(1).isSymbol()) {
+ FrameIndex = MI->getOperand(1).getIndex();
+ return MI->getOperand(0).getReg();
+ }
+ return 0;
+}
+
+/// isLoadFromStackSlot - If the specified machine instruction is a direct
+/// load from a stack slot, return the virtual or physical register number of
+/// the dest reg along with the FrameIndex of the stack slot.
+/// If not, return 0. This predicate must return 0 if the instruction has
+/// any side effects other than storing to the stack slot.
+unsigned PIC16InstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const {
+ if (MI->getOpcode() == PIC16::movf
+ && MI->getOperand(0).isReg()
+ && MI->getOperand(1).isSymbol()) {
+ FrameIndex = MI->getOperand(1).getIndex();
+ return MI->getOperand(0).getReg();
+ }
+ return 0;
+}
+
+
+void PIC16InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned SrcReg, bool isKill, int FI,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const {
+ const PIC16TargetLowering *PTLI = TM.getTargetLowering();
+ DebugLoc DL;
+ if (I != MBB.end()) DL = I->getDebugLoc();
+
+ const Function *Func = MBB.getParent()->getFunction();
+ const std::string FuncName = Func->getName();
+
+ const char *tmpName = ESNames::createESName(PAN::getTempdataLabel(FuncName));
+
+ // On the order of operands here: think "movwf SrcReg, tmp_slot, offset".
+ if (RC == PIC16::GPRRegisterClass) {
+ //MachineFunction &MF = *MBB.getParent();
+ //MachineRegisterInfo &RI = MF.getRegInfo();
+ BuildMI(MBB, I, DL, get(PIC16::movwf))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addImm(PTLI->GetTmpOffsetForFI(FI, 1, *MBB.getParent()))
+ .addExternalSymbol(tmpName)
+ .addImm(1); // Emit banksel for it.
+ }
+ else if (RC == PIC16::FSR16RegisterClass) {
+ // This is a 16-bit register and the frameindex given by llvm is of
+ // size two here. Break this index N into two zero based indexes and
+ // put one into the map. The second one is always obtained by adding 1
+ // to the first zero based index. In fact it is going to use 3 slots
+ // as saving FSRs corrupts W also and hence we need to save/restore W also.
+
+ unsigned opcode = (SrcReg == PIC16::FSR0) ? PIC16::save_fsr0
+ : PIC16::save_fsr1;
+ BuildMI(MBB, I, DL, get(opcode))
+ .addReg(SrcReg, getKillRegState(isKill))
+ .addImm(PTLI->GetTmpOffsetForFI(FI, 3, *MBB.getParent()))
+ .addExternalSymbol(tmpName)
+ .addImm(1); // Emit banksel for it.
+ }
+ else
+ llvm_unreachable("Can't store this register to stack slot");
+}
+
+void PIC16InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned DestReg, int FI,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const {
+ const PIC16TargetLowering *PTLI = TM.getTargetLowering();
+ DebugLoc DL;
+ if (I != MBB.end()) DL = I->getDebugLoc();
+
+ const Function *Func = MBB.getParent()->getFunction();
+ const std::string FuncName = Func->getName();
+
+ const char *tmpName = ESNames::createESName(PAN::getTempdataLabel(FuncName));
+
+ // On the order of operands here: think "movf FrameIndex, W".
+ if (RC == PIC16::GPRRegisterClass) {
+ //MachineFunction &MF = *MBB.getParent();
+ //MachineRegisterInfo &RI = MF.getRegInfo();
+ BuildMI(MBB, I, DL, get(PIC16::movf), DestReg)
+ .addImm(PTLI->GetTmpOffsetForFI(FI, 1, *MBB.getParent()))
+ .addExternalSymbol(tmpName)
+ .addImm(1); // Emit banksel for it.
+ }
+ else if (RC == PIC16::FSR16RegisterClass) {
+ // This is a 16-bit register and the frameindex given by llvm is of
+ // size two here. Break this index N into two zero based indexes and
+ // put one into the map. The second one is always obtained by adding 1
+ // to the first zero based index. In fact it is going to use 3 slots
+ // as saving FSRs corrupts W also and hence we need to save/restore W also.
+
+ unsigned opcode = (DestReg == PIC16::FSR0) ? PIC16::restore_fsr0
+ : PIC16::restore_fsr1;
+ BuildMI(MBB, I, DL, get(opcode), DestReg)
+ .addImm(PTLI->GetTmpOffsetForFI(FI, 3, *MBB.getParent()))
+ .addExternalSymbol(tmpName)
+ .addImm(1); // Emit banksel for it.
+ }
+ else
+ llvm_unreachable("Can't load this register from stack slot");
+}
+
+bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned DestReg, unsigned SrcReg,
+ const TargetRegisterClass *DestRC,
+ const TargetRegisterClass *SrcRC,
+ DebugLoc DL) const {
+
+ if (DestRC == PIC16::FSR16RegisterClass) {
+ BuildMI(MBB, I, DL, get(PIC16::copy_fsr), DestReg).addReg(SrcReg);
+ return true;
+ }
+
+ if (DestRC == PIC16::GPRRegisterClass) {
+ BuildMI(MBB, I, DL, get(PIC16::copy_w), DestReg).addReg(SrcReg);
+ return true;
+ }
+
+ // Not yet supported.
+ return false;
+}
+
+bool PIC16InstrInfo::isMoveInstr(const MachineInstr &MI,
+ unsigned &SrcReg, unsigned &DestReg,
+ unsigned &SrcSubIdx, unsigned &DstSubIdx) const {
+ SrcSubIdx = DstSubIdx = 0; // No sub-registers.
+
+ if (MI.getOpcode() == PIC16::copy_fsr
+ || MI.getOpcode() == PIC16::copy_w) {
+ DestReg = MI.getOperand(0).getReg();
+ SrcReg = MI.getOperand(1).getReg();
+ return true;
+ }
+
+ return false;
+}
+
+/// InsertBranch - Insert a branch into the end of the specified
+/// MachineBasicBlock. This operands to this method are the same as those
+/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
+/// returns success and when an unconditional branch (TBB is non-null, FBB is
+/// null, Cond is empty) needs to be inserted. It returns the number of
+/// instructions inserted.
+unsigned PIC16InstrInfo::
+InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ const SmallVectorImpl<MachineOperand> &Cond) const {
+ // Shouldn't be a fall through.
+ assert(TBB && "InsertBranch must not be told to insert a fallthrough");
+
+ if (FBB == 0) { // One way branch.
+ if (Cond.empty()) {
+ // Unconditional branch?
+ DebugLoc dl;
+ BuildMI(&MBB, dl, get(PIC16::br_uncond)).addMBB(TBB);
+ }
+ return 1;
+ }
+
+ // FIXME: If the there are some conditions specified then conditional branch
+ // should be generated.
+ // For the time being no instruction is being generated therefore
+ // returning NULL.
+ return 0;
+}
+
+bool PIC16InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const {
+ MachineBasicBlock::iterator I = MBB.end();
+ if (I == MBB.begin())
+ return true;
+
+ // Get the terminator instruction.
+ --I;
+ while (I->isDebugValue()) {
+ if (I == MBB.begin())
+ return true;
+ --I;
+ }
+ // Handle unconditional branches. If the unconditional branch's target is
+ // successor basic block then remove the unconditional branch.
+ if (I->getOpcode() == PIC16::br_uncond && AllowModify) {
+ if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
+ TBB = 0;
+ I->eraseFromParent();
+ }
+ }
+ return true;
+}
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.h b/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.h
new file mode 100644
index 0000000..40a4cb4
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.h
@@ -0,0 +1,81 @@
+//===- PIC16InstrInfo.h - PIC16 Instruction Information----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the niversity of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the PIC16 implementation of the TargetInstrInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16INSTRUCTIONINFO_H
+#define PIC16INSTRUCTIONINFO_H
+
+#include "PIC16.h"
+#include "PIC16RegisterInfo.h"
+#include "llvm/Target/TargetInstrInfo.h"
+
+namespace llvm {
+
+
+class PIC16InstrInfo : public TargetInstrInfoImpl
+{
+ PIC16TargetMachine &TM;
+ const PIC16RegisterInfo RegInfo;
+public:
+ explicit PIC16InstrInfo(PIC16TargetMachine &TM);
+
+ virtual const PIC16RegisterInfo &getRegisterInfo() const { return RegInfo; }
+
+ /// isLoadFromStackSlot - If the specified machine instruction is a direct
+ /// load from a stack slot, return the virtual or physical register number of
+ /// the destination along with the FrameIndex of the loaded stack slot. If
+ /// not, return 0. This predicate must return 0 if the instruction has
+ /// any side effects other than loading from the stack slot.
+ virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const;
+
+ /// isStoreToStackSlot - If the specified machine instruction is a direct
+ /// store to a stack slot, return the virtual or physical register number of
+ /// the source reg along with the FrameIndex of the loaded stack slot. If
+ /// not, return 0. This predicate must return 0 if the instruction has
+ /// any side effects other than storing to the stack slot.
+ virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const;
+
+ virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const;
+
+ virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const;
+ virtual bool copyRegToReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned DestReg, unsigned SrcReg,
+ const TargetRegisterClass *DestRC,
+ const TargetRegisterClass *SrcRC,
+ DebugLoc DL) const;
+ virtual bool isMoveInstr(const MachineInstr &MI,
+ unsigned &SrcReg, unsigned &DstReg,
+ unsigned &SrcSubIdx, unsigned &DstSubIdx) const;
+
+ virtual
+ unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ const SmallVectorImpl<MachineOperand> &Cond) const;
+ virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const;
+ };
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.td b/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.td
new file mode 100644
index 0000000..24df251
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16InstrInfo.td
@@ -0,0 +1,540 @@
+//===- PIC16InstrInfo.td - PIC16 Instruction defs -------------*- tblgen-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes the PIC16 instructions in TableGen format.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// PIC16 Specific Type Constraints.
+//===----------------------------------------------------------------------===//
+class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
+class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
+
+//===----------------------------------------------------------------------===//
+// PIC16 Specific Type Profiles.
+//===----------------------------------------------------------------------===//
+
+// Generic type profiles for i8/i16 unary/binary operations.
+// Taking one i8 or i16 and producing void.
+def SDTI8VoidOp : SDTypeProfile<0, 1, [SDTCisI8<0>]>;
+def SDTI16VoidOp : SDTypeProfile<0, 1, [SDTCisI16<0>]>;
+
+// Taking one value and producing an output of same type.
+def SDTI8UnaryOp : SDTypeProfile<1, 1, [SDTCisI8<0>, SDTCisI8<1>]>;
+def SDTI16UnaryOp : SDTypeProfile<1, 1, [SDTCisI16<0>, SDTCisI16<1>]>;
+
+// Taking two values and producing an output of same type.
+def SDTI8BinOp : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>]>;
+def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>,
+ SDTCisI16<2>]>;
+
+// Node specific type profiles.
+def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>,
+ SDTCisI8<2>, SDTCisI8<3>]>;
+
+def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>,
+ SDTCisI8<2>, SDTCisI8<3>]>;
+
+def SDT_PIC16Connect : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>,
+ SDTCisI8<2>]>;
+
+// PIC16ISD::CALL type prorile
+def SDT_PIC16call : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
+def SDT_PIC16callw : SDTypeProfile<1, -1, [SDTCisInt<0>]>;
+
+// PIC16ISD::BRCOND
+def SDT_PIC16Brcond: SDTypeProfile<0, 2,
+ [SDTCisVT<0, OtherVT>, SDTCisI8<1>]>;
+
+// PIC16ISD::BRCOND
+def SDT_PIC16Selecticc: SDTypeProfile<1, 3,
+ [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>,
+ SDTCisI8<3>]>;
+
+//===----------------------------------------------------------------------===//
+// PIC16 addressing modes matching via DAG.
+//===----------------------------------------------------------------------===//
+def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
+
+//===----------------------------------------------------------------------===//
+// PIC16 Specific Node Definitions.
+//===----------------------------------------------------------------------===//
+def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
+ [SDNPHasChain, SDNPOutFlag]>;
+def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
+ [SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
+
+// Low 8-bits of GlobalAddress.
+def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8BinOp>;
+
+// High 8-bits of GlobalAddress.
+def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8BinOp>;
+
+// The MTHI and MTLO nodes are used only to match them in the incoming
+// DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
+// These nodes are not used for defining any instructions.
+def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
+def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
+def MTPCLATH : SDNode<"PIC16ISD::MTPCLATH", SDTI8UnaryOp>;
+
+// Node to generate Bank Select for a GlobalAddress.
+def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
+
+// Node to match a direct store operation.
+def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
+def PIC16StWF : SDNode<"PIC16ISD::PIC16StWF", SDT_PIC16Store,
+ [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
+
+// Node to match a direct load operation.
+def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
+def PIC16LdArg : SDNode<"PIC16ISD::PIC16LdArg", SDT_PIC16Load, [SDNPHasChain]>;
+def PIC16LdWF : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load,
+ [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
+def PIC16Connect: SDNode<"PIC16ISD::PIC16Connect", SDT_PIC16Connect, []>;
+
+// Node to match PIC16 call
+def PIC16call : SDNode<"PIC16ISD::CALL", SDT_PIC16call,
+ [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
+def PIC16callw : SDNode<"PIC16ISD::CALLW", SDT_PIC16callw,
+ [SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
+
+// Node to match a comparison instruction.
+def PIC16Subcc : SDNode<"PIC16ISD::SUBCC", SDTI8BinOp, [SDNPOutFlag]>;
+
+// Node to match a conditional branch.
+def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond,
+ [SDNPHasChain, SDNPInFlag]>;
+
+def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc,
+ [SDNPInFlag]>;
+
+def PIC16ret : SDNode<"PIC16ISD::RET", SDTNone, [SDNPHasChain]>;
+
+//===----------------------------------------------------------------------===//
+// PIC16 Operand Definitions.
+//===----------------------------------------------------------------------===//
+def i8mem : Operand<i8>;
+def brtarget: Operand<OtherVT>;
+
+// Operand for printing out a condition code.
+let PrintMethod = "printCCOperand" in
+ def CCOp : Operand<i8>;
+
+include "PIC16InstrFormats.td"
+
+//===----------------------------------------------------------------------===//
+// PIC16 Common Classes.
+//===----------------------------------------------------------------------===//
+
+// W = W Op F : Load the value from F and do Op to W.
+let isTwoAddress = 1, mayLoad = 1 in
+class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
+ ByteFormat<OpCode, (outs GPR:$dst),
+ (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
+ !strconcat(OpcStr, " $ptrlo + $offset, W"),
+ [(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
+ (i8 imm:$ptrhi),
+ (i8 imm:$offset))))]>;
+
+// F = F Op W : Load the value from F, do op with W and store in F.
+// This insn class is not marked as TwoAddress because the reg is
+// being used as a source operand only. (Remember a TwoAddress insn
+// needs a copyRegToReg.)
+let mayStore = 1 in
+class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
+ ByteFormat<OpCode, (outs),
+ (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
+ !strconcat(OpcStr, " $ptrlo + $offset, F"),
+ [(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
+ (i8 imm:$ptrhi),
+ (i8 imm:$offset))),
+ diraddr:$ptrlo,
+ (i8 imm:$ptrhi), (i8 imm:$offset)
+ )]>;
+
+// W = W Op L : Do Op of L with W and place result in W.
+let isTwoAddress = 1 in
+class BinOpWL<bits<6> opcode, string OpcStr, SDNode OpNode> :
+ LiteralFormat<opcode, (outs GPR:$dst),
+ (ins GPR:$src, i8imm:$literal),
+ !strconcat(OpcStr, " $literal"),
+ [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
+
+//===----------------------------------------------------------------------===//
+// PIC16 Instructions.
+//===----------------------------------------------------------------------===//
+
+// Pseudo-instructions.
+def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
+ "!ADJCALLSTACKDOWN $amt",
+ [(PIC16callseq_start imm:$amt)]>;
+
+def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
+ "!ADJCALLSTACKUP $amt",
+ [(PIC16callseq_end imm:$amt)]>;
+
+//-----------------------------------
+// Vaious movlw insn patterns.
+//-----------------------------------
+let isReMaterializable = 1 in {
+// Move 8-bit literal to W.
+def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
+ "movlw $src",
+ [(set GPR:$dst, (i8 imm:$src))]>;
+
+// Move a Lo(TGA) to W.
+def movlw_lo_1 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
+ "movlw LOW(${src} + ${src2})",
+ [(set GPR:$dst, (PIC16Lo tglobaladdr:$src, imm:$src2 ))]>;
+
+// Move a Lo(TES) to W.
+def movlw_lo_2 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
+ "movlw LOW(${src} + ${src2})",
+ [(set GPR:$dst, (PIC16Lo texternalsym:$src, imm:$src2 ))]>;
+
+// Move a Hi(TGA) to W.
+def movlw_hi_1 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
+ "movlw HIGH(${src} + ${src2})",
+ [(set GPR:$dst, (PIC16Hi tglobaladdr:$src, imm:$src2))]>;
+
+// Move a Hi(TES) to W.
+def movlw_hi_2 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
+ "movlw HIGH(${src} + ${src2})",
+ [(set GPR:$dst, (PIC16Hi texternalsym:$src, imm:$src2))]>;
+}
+
+//-------------------
+// FSR setting insns.
+//-------------------
+// These insns are matched via a DAG replacement pattern.
+def set_fsrlo:
+ ByteFormat<0, (outs FSR16:$fsr),
+ (ins GPR:$val),
+ "movwf ${fsr}L",
+ []>;
+
+let isTwoAddress = 1 in
+def set_fsrhi:
+ ByteFormat<0, (outs FSR16:$dst),
+ (ins FSR16:$src, GPR:$val),
+ "movwf ${dst}H",
+ []>;
+
+def set_pclath:
+ ByteFormat<0, (outs PCLATHR:$dst),
+ (ins GPR:$val),
+ "movwf ${dst}",
+ [(set PCLATHR:$dst , (MTPCLATH GPR:$val))]>;
+
+//----------------------------
+// copyRegToReg
+// copyRegToReg insns. These are dummy. They should always be deleted
+// by the optimizer and never be present in the final generated code.
+// if they are, then we have to write correct macros for these insns.
+//----------------------------
+def copy_fsr:
+ Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
+
+def copy_w:
+ Pseudo<(outs GPR:$dst), (ins GPR:$src), "copy_w $dst, $src", []>;
+
+class SAVE_FSR<string OpcStr>:
+ Pseudo<(outs),
+ (ins FSR16:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
+ !strconcat(OpcStr, " $ptrlo, $offset"),
+ []>;
+
+def save_fsr0: SAVE_FSR<"save_fsr0">;
+def save_fsr1: SAVE_FSR<"save_fsr1">;
+
+class RESTORE_FSR<string OpcStr>:
+ Pseudo<(outs FSR16:$dst),
+ (ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
+ !strconcat(OpcStr, " $ptrlo, $offset"),
+ []>;
+
+def restore_fsr0: RESTORE_FSR<"restore_fsr0">;
+def restore_fsr1: RESTORE_FSR<"restore_fsr1">;
+
+//--------------------------
+// Store to memory
+//-------------------------
+
+// Direct store.
+// Input operands are: val = W, ptrlo = GA, offset = offset, ptrhi = banksel.
+let mayStore = 1 in
+class MOVWF_INSN<bits<6> OpCode, SDNode OpNodeDest, SDNode Op>:
+ ByteFormat<0, (outs),
+ (ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
+ "movwf ${ptrlo} + ${offset}",
+ [(Op GPR:$val, OpNodeDest:$ptrlo, (i8 imm:$ptrhi),
+ (i8 imm:$offset))]>;
+
+// Store W to a Global Address.
+def movwf : MOVWF_INSN<0, tglobaladdr, PIC16Store>;
+
+// Store W to an External Symobol.
+def movwf_1 : MOVWF_INSN<0, texternalsym, PIC16Store>;
+
+// Store with InFlag and OutFlag
+// This is same as movwf_1 but has a flag. A flag is required to
+// order the stores while passing the params to function.
+def movwf_2 : MOVWF_INSN<0, texternalsym, PIC16StWF>;
+
+// Indirect store. Matched via a DAG replacement pattern.
+def store_indirect :
+ ByteFormat<0, (outs),
+ (ins GPR:$val, FSR16:$fsr, i8imm:$offset),
+ "movwi $offset[$fsr]",
+ []>;
+
+//----------------------------
+// Load from memory
+//----------------------------
+// Direct load.
+// Input Operands are: ptrlo = GA, offset = offset, ptrhi = banksel.
+// Output: dst = W
+let Defs = [STATUS], mayLoad = 1 in
+class MOVF_INSN<bits<6> OpCode, SDNode OpNodeSrc, SDNode Op>:
+ ByteFormat<0, (outs GPR:$dst),
+ (ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
+ "movf ${ptrlo} + ${offset}, W",
+ [(set GPR:$dst,
+ (Op OpNodeSrc:$ptrlo, (i8 imm:$ptrhi),
+ (i8 imm:$offset)))]>;
+
+// Load from a GA.
+def movf : MOVF_INSN<0, tglobaladdr, PIC16Load>;
+
+// Load from an ES.
+def movf_1 : MOVF_INSN<0, texternalsym, PIC16Load>;
+def movf_1_1 : MOVF_INSN<0, texternalsym, PIC16LdArg>;
+
+// Load with InFlag and OutFlag
+// This is same as movf_1 but has a flag. A flag is required to
+// order the loads while copying the return value of a function.
+def movf_2 : MOVF_INSN<0, texternalsym, PIC16LdWF>;
+
+// Indirect load. Matched via a DAG replacement pattern.
+def load_indirect :
+ ByteFormat<0, (outs GPR:$dst),
+ (ins FSR16:$fsr, i8imm:$offset),
+ "moviw $offset[$fsr]",
+ []>;
+
+//-------------------------
+// Bitwise operations patterns
+//--------------------------
+// W = W op [F]
+let Defs = [STATUS] in {
+def OrFW : BinOpFW<0, "iorwf", or>;
+def XOrFW : BinOpFW<0, "xorwf", xor>;
+def AndFW : BinOpFW<0, "andwf", and>;
+
+// F = W op [F]
+def OrWF : BinOpWF<0, "iorwf", or>;
+def XOrWF : BinOpWF<0, "xorwf", xor>;
+def AndWF : BinOpWF<0, "andwf", and>;
+
+//-------------------------
+// Various add/sub patterns.
+//-------------------------
+
+// W = W + [F]
+def addfw_1: BinOpFW<0, "addwf", add>;
+def addfw_2: BinOpFW<0, "addwf", addc>;
+
+let Uses = [STATUS] in
+def addfwc: BinOpFW<0, "addwfc", adde>; // With Carry.
+
+// F = W + [F]
+def addwf_1: BinOpWF<0, "addwf", add>;
+def addwf_2: BinOpWF<0, "addwf", addc>;
+let Uses = [STATUS] in
+def addwfc: BinOpWF<0, "addwfc", adde>; // With Carry.
+}
+
+// W -= [F] ; load from F and sub the value from W.
+let isTwoAddress = 1, mayLoad = 1 in
+class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
+ ByteFormat<OpCode, (outs GPR:$dst),
+ (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
+ !strconcat(OpcStr, " $ptrlo + $offset, W"),
+ [(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
+ (i8 imm:$ptrhi), (i8 imm:$offset)),
+ GPR:$src))]>;
+let Defs = [STATUS] in {
+def subfw_1: SUBFW<0, "subwf", sub>;
+def subfw_2: SUBFW<0, "subwf", subc>;
+
+let Uses = [STATUS] in
+def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow.
+
+}
+let Defs = [STATUS], isTerminator = 1 in
+def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>;
+
+// [F] -= W ;
+let mayStore = 1 in
+class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
+ ByteFormat<OpCode, (outs),
+ (ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
+ !strconcat(OpcStr, " $ptrlo + $offset"),
+ [(PIC16Store (OpNode (PIC16Load diraddr:$ptrlo,
+ (i8 imm:$ptrhi), (i8 imm:$offset)),
+ GPR:$src), diraddr:$ptrlo,
+ (i8 imm:$ptrhi), (i8 imm:$offset))]>;
+
+let Defs = [STATUS] in {
+def subwf_1: SUBWF<0, "subwf", sub>;
+def subwf_2: SUBWF<0, "subwf", subc>;
+
+let Uses = [STATUS] in
+ def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
+
+def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>;
+}
+
+// addlw
+let Defs = [STATUS] in {
+def addlw_1 : BinOpWL<0, "addlw", add>;
+def addlw_2 : BinOpWL<0, "addlw", addc>;
+
+let Uses = [STATUS] in
+def addlwc : BinOpWL<0, "addlwc", adde>; // With Carry. (Assembler macro).
+
+// bitwise operations involving a literal and w.
+def andlw : BinOpWL<0, "andlw", and>;
+def xorlw : BinOpWL<0, "xorlw", xor>;
+def orlw : BinOpWL<0, "iorlw", or>;
+}
+
+// sublw
+// W = C - W ; sub W from literal. (Without borrow).
+let isTwoAddress = 1 in
+class SUBLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
+ LiteralFormat<opcode, (outs GPR:$dst),
+ (ins GPR:$src, i8imm:$literal),
+ !strconcat(OpcStr, " $literal"),
+ [(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
+// subwl
+// W = W - C ; sub literal from W (Without borrow).
+let isTwoAddress = 1 in
+class SUBWL<bits<6> opcode, string OpcStr, SDNode OpNode> :
+ LiteralFormat<opcode, (outs GPR:$dst),
+ (ins GPR:$src, i8imm:$literal),
+ !strconcat(OpcStr, " $literal"),
+ [(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
+
+let Defs = [STATUS] in {
+def sublw_1 : SUBLW<0, "sublw", sub>;
+def sublw_2 : SUBLW<0, "sublw", subc>;
+def sublw_3 : SUBLW<0, "sublwb", sube>; // With borrow (Assembler macro).
+
+def sublw_4 : SUBWL<0, "subwl", sub>; // Assembler macro replace with addlw
+def sublw_5 : SUBWL<0, "subwl", subc>; // Assembler macro replace with addlw
+def sublw_6 : SUBWL<0, "subwlb", sube>; // With borrow (Assembler macro).
+}
+let Defs = [STATUS], isTerminator = 1 in
+def sublw_cc : SUBLW<0, "sublw", PIC16Subcc>;
+
+// Call instruction.
+let isCall = 1,
+ Defs = [W, FSR0, FSR1] in {
+ def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func),
+ //"call ${func} + 2",
+ "call ${func}",
+ [(PIC16call diraddr:$func)]>;
+}
+
+let isCall = 1,
+ Defs = [W, FSR0, FSR1] in {
+ def CALL_1: LiteralFormat<0x1, (outs), (ins GPR:$func, PCLATHR:$pc),
+ "callw",
+ [(PIC16call (PIC16Connect GPR:$func, PCLATHR:$pc))]>;
+}
+
+let isCall = 1,
+ Defs = [FSR0, FSR1] in {
+ def CALLW: LiteralFormat<0x1, (outs GPR:$dest),
+ (ins GPR:$func, PCLATHR:$pc),
+ "callw",
+ [(set GPR:$dest, (PIC16callw (PIC16Connect GPR:$func, PCLATHR:$pc)))]>;
+}
+
+let Uses = [STATUS], isBranch = 1, isTerminator = 1, hasDelaySlot = 0 in
+def pic16brcond: ControlFormat<0x0, (outs), (ins brtarget:$dst, CCOp:$cc),
+ "b$cc $dst",
+ [(PIC16Brcond bb:$dst, imm:$cc)]>;
+
+// Unconditional branch.
+let isBranch = 1, isTerminator = 1, hasDelaySlot = 0 in
+def br_uncond: ControlFormat<0x0, (outs), (ins brtarget:$dst),
+ "goto $dst",
+ [(br bb:$dst)]>;
+
+// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded after
+// instruction selection into a branch sequence.
+let usesCustomInserter = 1 in { // Expanded after instruction selection.
+ def SELECT_CC_Int_ICC
+ : Pseudo<(outs GPR:$dst), (ins GPR:$T, GPR:$F, i8imm:$Cond),
+ "; SELECT_CC_Int_ICC PSEUDO!",
+ [(set GPR:$dst, (PIC16Selecticc GPR:$T, GPR:$F,
+ imm:$Cond))]>;
+}
+
+
+// Banksel.
+def banksel :
+ Pseudo<(outs),
+ (ins i8mem:$ptr),
+ "banksel $ptr",
+ []>;
+
+def pagesel :
+ Pseudo<(outs),
+ (ins i8mem:$ptr),
+ "movlp $ptr",
+ []>;
+
+
+// Return insn.
+let isTerminator = 1, isBarrier = 1, isReturn = 1 in
+def Return :
+ ControlFormat<0, (outs), (ins), "return", [(PIC16ret)]>;
+
+//===----------------------------------------------------------------------===//
+// PIC16 Replacment Patterns.
+//===----------------------------------------------------------------------===//
+
+// Identify an indirect store and select insns for it.
+def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
+ imm:$offset),
+ (store_indirect GPR:$val,
+ (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
+ imm:$offset)>;
+
+def : Pat<(PIC16StWF GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
+ imm:$offset),
+ (store_indirect GPR:$val,
+ (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
+ imm:$offset)>;
+
+// Identify an indirect load and select insns for it.
+def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
+ imm:$offset),
+ (load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
+ imm:$offset)>;
+
+def : Pat<(PIC16LdWF (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
+ imm:$offset),
+ (load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
+ imm:$offset)>;
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16MCAsmInfo.cpp b/contrib/llvm/lib/Target/PIC16/PIC16MCAsmInfo.cpp
new file mode 100644
index 0000000..b080542
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16MCAsmInfo.cpp
@@ -0,0 +1,59 @@
+//===-- PIC16MCAsmInfo.cpp - PIC16 asm properties -------------------------===//
+//
+// 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 declarations of the PIC16MCAsmInfo properties.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16MCAsmInfo.h"
+
+// FIXME: Layering violation to get enums and static function, should be moved
+// to separate headers.
+#include "PIC16.h"
+#include "PIC16ABINames.h"
+#include "PIC16ISelLowering.h"
+using namespace llvm;
+
+PIC16MCAsmInfo::PIC16MCAsmInfo(const Target &T, const StringRef &TT) {
+ CommentString = ";";
+ GlobalPrefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
+ GlobalDirective = "\tglobal\t";
+ ExternDirective = "\textern\t";
+
+ Data8bitsDirective = " db ";
+ Data16bitsDirective = " dw ";
+ Data32bitsDirective = " dl ";
+ Data64bitsDirective = NULL;
+ ZeroDirective = NULL;
+ AsciiDirective = " dt ";
+ AscizDirective = NULL;
+
+ RomData8bitsDirective = " dw ";
+ RomData16bitsDirective = " rom_di ";
+ RomData32bitsDirective = " rom_dl ";
+ HasSetDirective = false;
+
+ // Set it to false because we weed to generate c file name and not bc file
+ // name.
+ HasSingleParameterDotFile = false;
+}
+
+const char *PIC16MCAsmInfo::getDataASDirective(unsigned Size,
+ unsigned AS) const {
+ if (AS != PIC16ISD::ROM_SPACE)
+ return 0;
+
+ switch (Size) {
+ case 8: return RomData8bitsDirective;
+ case 16: return RomData16bitsDirective;
+ case 32: return RomData32bitsDirective;
+ default: return NULL;
+ }
+}
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16MCAsmInfo.h b/contrib/llvm/lib/Target/PIC16/PIC16MCAsmInfo.h
new file mode 100644
index 0000000..e84db85
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16MCAsmInfo.h
@@ -0,0 +1,35 @@
+//=====-- PIC16MCAsmInfo.h - PIC16 asm properties -------------*- 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 declaration of the PIC16MCAsmInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16TARGETASMINFO_H
+#define PIC16TARGETASMINFO_H
+
+#include "llvm/MC/MCAsmInfo.h"
+
+namespace llvm {
+ class Target;
+ class StringRef;
+
+ class PIC16MCAsmInfo : public MCAsmInfo {
+ const char *RomData8bitsDirective;
+ const char *RomData16bitsDirective;
+ const char *RomData32bitsDirective;
+ public:
+ PIC16MCAsmInfo(const Target &T, const StringRef &TT);
+
+ virtual const char *getDataASDirective(unsigned size, unsigned AS) const;
+ };
+
+} // namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16MachineFunctionInfo.h b/contrib/llvm/lib/Target/PIC16/PIC16MachineFunctionInfo.h
new file mode 100644
index 0000000..bdf5086
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16MachineFunctionInfo.h
@@ -0,0 +1,52 @@
+//====- PIC16MachineFuctionInfo.h - PIC16 machine function info -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares PIC16-specific per-machine-function information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16MACHINEFUNCTIONINFO_H
+#define PIC16MACHINEFUNCTIONINFO_H
+
+#include "llvm/CodeGen/MachineFunction.h"
+
+namespace llvm {
+
+/// PIC16MachineFunctionInfo - This class is derived from MachineFunction
+/// private PIC16 target-specific information for each MachineFunction.
+class PIC16MachineFunctionInfo : public MachineFunctionInfo {
+ // The frameindexes generated for spill/reload are stack based.
+ // This maps maintain zero based indexes for these FIs.
+ std::map<unsigned, unsigned> FiTmpOffsetMap;
+ unsigned TmpSize;
+
+ // These are the frames for return value and argument passing
+ // These FrameIndices will be expanded to foo.frame external symbol
+ // and all others will be expanded to foo.tmp external symbol.
+ unsigned ReservedFrameCount;
+
+public:
+ PIC16MachineFunctionInfo()
+ : TmpSize(0), ReservedFrameCount(0) {}
+
+ explicit PIC16MachineFunctionInfo(MachineFunction &MF)
+ : TmpSize(0), ReservedFrameCount(0) {}
+
+ std::map<unsigned, unsigned> &getFiTmpOffsetMap() { return FiTmpOffsetMap; }
+
+ unsigned getTmpSize() const { return TmpSize; }
+ void setTmpSize(unsigned Size) { TmpSize = Size; }
+
+ unsigned getReservedFrameCount() const { return ReservedFrameCount; }
+ void setReservedFrameCount(unsigned Count) { ReservedFrameCount = Count; }
+};
+
+} // End llvm namespace
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16MemSelOpt.cpp b/contrib/llvm/lib/Target/PIC16/PIC16MemSelOpt.cpp
new file mode 100644
index 0000000..ab81ed1
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16MemSelOpt.cpp
@@ -0,0 +1,254 @@
+//===-- PIC16MemSelOpt.cpp - PIC16 banksel optimizer --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the pass which optimizes the emitting of banksel
+// instructions before accessing data memory. This currently works within
+// a basic block only and keep tracks of the last accessed memory bank.
+// If memory access continues to be in the same bank it just makes banksel
+// immediate, which is a part of the insn accessing the data memory, from 1
+// to zero. The asm printer emits a banksel only if that immediate is 1.
+//
+// FIXME: this is not implemented yet. The banksel pass only works on local
+// basic blocks.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-codegen"
+#include "PIC16.h"
+#include "PIC16ABINames.h"
+#include "PIC16InstrInfo.h"
+#include "PIC16MCAsmInfo.h"
+#include "PIC16TargetMachine.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/GlobalValue.h"
+#include "llvm/DerivedTypes.h"
+
+using namespace llvm;
+
+namespace {
+ struct MemSelOpt : public MachineFunctionPass {
+ static char ID;
+ MemSelOpt() : MachineFunctionPass(&ID) {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addPreservedID(MachineLoopInfoID);
+ AU.addPreservedID(MachineDominatorsID);
+ MachineFunctionPass::getAnalysisUsage(AU);
+ }
+
+ virtual bool runOnMachineFunction(MachineFunction &MF);
+
+ virtual const char *getPassName() const {
+ return "PIC16 Memsel Optimizer";
+ }
+
+ bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
+ bool processInstruction(MachineInstr *MI);
+
+ private:
+ const TargetInstrInfo *TII; // Machine instruction info.
+ MachineBasicBlock *MBB; // Current basic block
+ std::string CurBank;
+ int PageChanged;
+
+ };
+ char MemSelOpt::ID = 0;
+}
+
+FunctionPass *llvm::createPIC16MemSelOptimizerPass() {
+ return new MemSelOpt();
+}
+
+
+/// runOnMachineFunction - Loop over all of the basic blocks, transforming FP
+/// register references into FP stack references.
+///
+bool MemSelOpt::runOnMachineFunction(MachineFunction &MF) {
+ TII = MF.getTarget().getInstrInfo();
+ bool Changed = false;
+ for (MachineFunction::iterator I = MF.begin(), E = MF.end();
+ I != E; ++I) {
+ Changed |= processBasicBlock(MF, *I);
+ }
+
+ return Changed;
+}
+
+/// processBasicBlock - Loop over all of the instructions in the basic block,
+/// transforming FP instructions into their stack form.
+///
+bool MemSelOpt::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
+ bool Changed = false;
+ MBB = &BB;
+
+ // Let us assume that when entering a basic block now bank is selected.
+ // Ideally we should look at the predecessors for this information.
+ CurBank="";
+ PageChanged=0;
+
+ MachineBasicBlock::iterator I;
+ for (I = BB.begin(); I != BB.end(); ++I) {
+ Changed |= processInstruction(I);
+
+ // if the page has changed insert a page sel before
+ // any instruction that needs one
+ if (PageChanged == 1)
+ {
+ // Restore the page if it was changed, before leaving the basic block,
+ // because it may be required by the goto terminator or the fall thru
+ // basic blcok.
+ // If the terminator is return, we don't need to restore since there
+ // is no goto or fall thru basic block.
+ if ((I->getOpcode() == PIC16::sublw_3) || //macro has goto
+ (I->getOpcode() == PIC16::sublw_6) || //macro has goto
+ (I->getOpcode() == PIC16::addlwc) || //macro has goto
+ (TII->get(I->getOpcode()).isBranch()))
+ {
+ DebugLoc dl = I->getDebugLoc();
+ BuildMI(*MBB, I, dl, TII->get(PIC16::pagesel)).addExternalSymbol("$");
+ Changed = true;
+ PageChanged = 0;
+ }
+ }
+ }
+
+ // The basic block is over, but if we did not find any goto yet,
+ // we haven't restored the page.
+ // Restore the page if it was changed, before leaving the basic block,
+ // because it may be required by fall thru basic blcok.
+ // If the terminator is return, we don't need to restore since there
+ // is fall thru basic block.
+ if (PageChanged == 1) {
+ // save the end pointer before we move back to last insn.
+ MachineBasicBlock::iterator J = I;
+ I--;
+ const TargetInstrDesc &TID = TII->get(I->getOpcode());
+ if (! TID.isReturn())
+ {
+ DebugLoc dl = I->getDebugLoc();
+ BuildMI(*MBB, J, dl,
+ TII->get(PIC16::pagesel)).addExternalSymbol("$");
+ Changed = true;
+ PageChanged = 0;
+ }
+ }
+
+
+ return Changed;
+}
+
+bool MemSelOpt::processInstruction(MachineInstr *MI) {
+ bool Changed = false;
+
+ unsigned NumOperands = MI->getNumOperands();
+ if (NumOperands == 0) return false;
+
+
+ // If this insn is not going to access any memory, return.
+ const TargetInstrDesc &TID = TII->get(MI->getOpcode());
+ if (!(TID.isBranch() || TID.isCall() || TID.mayLoad() || TID.mayStore()))
+ return false;
+
+ // The first thing we should do is that record if banksel/pagesel are
+ // changed in an unknown way. This can happend via any type of call.
+ // We do it here first before scanning of MemOp / BBOp as the indirect
+ // call insns do not have any operands, but they still may change bank/page.
+ if (TID.isCall()) {
+ // Record that we have changed the page, so that we can restore it
+ // before basic block ends.
+ // We require to signal that a page anc bank change happened even for
+ // indirect calls.
+ PageChanged = 1;
+
+ // When a call is made, there may be banksel for variables in callee.
+ // Hence the banksel in caller needs to be reset.
+ CurBank = "";
+ }
+
+ // Scan for the memory address operand.
+ // FIXME: Should we use standard interfaces like memoperands_iterator,
+ // hasMemOperand() etc ?
+ int MemOpPos = -1;
+ int BBOpPos = -1;
+ for (unsigned i = 0; i < NumOperands; i++) {
+ MachineOperand Op = MI->getOperand(i);
+ if (Op.getType() == MachineOperand::MO_GlobalAddress ||
+ Op.getType() == MachineOperand::MO_ExternalSymbol) {
+ // We found one mem operand. Next one may be BS.
+ MemOpPos = i;
+ }
+ if (Op.getType() == MachineOperand::MO_MachineBasicBlock) {
+ // We found one BB operand. Next one may be pagesel.
+ BBOpPos = i;
+ }
+ }
+
+ // If we did not find an insn accessing memory. Continue.
+ if ((MemOpPos == -1) &&
+ (BBOpPos == -1))
+ return false;
+ assert ((BBOpPos != MemOpPos) && "operand can only be of one type");
+
+
+ // If this is a pagesel material, handle it first.
+ // CALL and br_ucond insns use MemOp (GA or ES) and not BBOp.
+ // Pagesel is required only for a direct call.
+ if ((MI->getOpcode() == PIC16::CALL)) {
+ // Get the BBOp.
+ MachineOperand &MemOp = MI->getOperand(MemOpPos);
+ DebugLoc dl = MI->getDebugLoc();
+ BuildMI(*MBB, MI, dl, TII->get(PIC16::pagesel)).addOperand(MemOp);
+
+ // CALL and br_ucond needs only pagesel. so we are done.
+ return true;
+ }
+
+ // Pagesel is handled. Now, add a Banksel if needed.
+ if (MemOpPos == -1) return Changed;
+ // Get the MemOp.
+ MachineOperand &Op = MI->getOperand(MemOpPos);
+
+ // Get the section name(NewBank) for MemOp.
+ // This assumes that the section names for globals are already set by
+ // AsmPrinter->doInitialization.
+ std::string NewBank = CurBank;
+ bool hasExternalLinkage = false;
+ if (Op.getType() == MachineOperand::MO_GlobalAddress &&
+ Op.getGlobal()->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) {
+ if (Op.getGlobal()->hasExternalLinkage())
+ hasExternalLinkage= true;
+ NewBank = Op.getGlobal()->getSection();
+ } else if (Op.getType() == MachineOperand::MO_ExternalSymbol) {
+ // External Symbol is generated for temp data and arguments. They are
+ // in fpdata.<functionname>.# section.
+ std::string Sym = Op.getSymbolName();
+ NewBank = PAN::getSectionNameForSym(Sym);
+ }
+
+ // If the section is shared section, do not emit banksel.
+ if (NewBank == PAN::getSharedUDataSectionName())
+ return Changed;
+
+ // If the previous and new section names are same, we don't need to
+ // emit banksel.
+ if (NewBank.compare(CurBank) != 0 || hasExternalLinkage) {
+ DebugLoc dl = MI->getDebugLoc();
+ BuildMI(*MBB, MI, dl, TII->get(PIC16::banksel)).
+ addOperand(Op);
+ Changed = true;
+ CurBank = NewBank;
+ }
+
+ return Changed;
+}
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Passes/Makefile b/contrib/llvm/lib/Target/PIC16/PIC16Passes/Makefile
new file mode 100644
index 0000000..9684b8d
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Passes/Makefile
@@ -0,0 +1,15 @@
+##===- 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
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp b/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp
new file mode 100644
index 0000000..c282521
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Cloner.cpp
@@ -0,0 +1,299 @@
+//===-- PIC16Cloner.cpp - PIC16 LLVM Cloner for shared functions -*- 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 code to clone all functions that are shared between
+// the main line code (ML) and interrupt line code (IL). It clones all such
+// shared functions and their automatic global vars by adding the .IL suffix.
+//
+// This pass is supposed to be run on the linked .bc module.
+// It traveses the module call graph twice. Once starting from the main function
+// and marking each reached function as "ML". Again, starting from the ISR
+// and cloning any reachable function that was marked as "ML". After cloning
+// the function, it remaps all the call sites in IL functions to call the
+// cloned functions.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Analysis/CallGraph.h"
+#include "llvm/Pass.h"
+#include "llvm/Module.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Transforms/Utils/Cloning.h"
+#include "PIC16Cloner.h"
+#include "../PIC16ABINames.h"
+#include <vector>
+
+using namespace llvm;
+using std::vector;
+using std::string;
+using std::map;
+
+namespace llvm {
+ char PIC16Cloner::ID = 0;
+
+ ModulePass *createPIC16ClonerPass() { return new PIC16Cloner(); }
+}
+
+// We currently intend to run these passes in opt, which does not have any
+// diagnostic support. So use these functions for now. In future
+// we will probably write our own driver tool.
+//
+void PIC16Cloner::reportError(string ErrorString) {
+ errs() << "ERROR : " << ErrorString << "\n";
+ exit(1);
+}
+
+void PIC16Cloner::
+reportError (string ErrorString, vector<string> &Values) {
+ unsigned ValCount = Values.size();
+ string TargetString;
+ for (unsigned i=0; i<ValCount; ++i) {
+ TargetString = "%";
+ TargetString += ((char)i + '0');
+ ErrorString.replace(ErrorString.find(TargetString), TargetString.length(),
+ Values[i]);
+ }
+ errs() << "ERROR : " << ErrorString << "\n";
+ exit(1);
+}
+
+
+// Entry point
+//
+bool PIC16Cloner::runOnModule(Module &M) {
+ CallGraph &CG = getAnalysis<CallGraph>();
+
+ // Search for the "main" and "ISR" functions.
+ CallGraphNode *mainCGN = NULL, *isrCGN = NULL;
+ for (CallGraph::iterator it = CG.begin() ; it != CG.end(); it++)
+ {
+ // External calling node doesn't have any function associated with it.
+ if (! it->first)
+ continue;
+
+ if (it->first->getName().str() == "main") {
+ mainCGN = it->second;
+ }
+
+ if (PAN::isISR(it->first->getSection())) {
+ isrCGN = it->second;
+ }
+
+ // Don't search further if we've found both.
+ if (mainCGN && isrCGN)
+ break;
+ }
+
+ // We have nothing to do if any of the main or ISR is missing.
+ if (! mainCGN || ! isrCGN) return false;
+
+ // Time for some diagnostics.
+ // See if the main itself is interrupt function then report an error.
+ if (PAN::isISR(mainCGN->getFunction()->getSection())) {
+ reportError("Function 'main' can't be interrupt function");
+ }
+
+
+ // Mark all reachable functions from main as ML.
+ markCallGraph(mainCGN, "ML");
+
+ // And then all the functions reachable from ISR will be cloned.
+ cloneSharedFunctions(isrCGN);
+
+ return true;
+}
+
+// Mark all reachable functions from the given node, with the given mark.
+//
+void PIC16Cloner::markCallGraph(CallGraphNode *CGN, string StringMark) {
+ // Mark the top node first.
+ Function *thisF = CGN->getFunction();
+
+ thisF->setSection(StringMark);
+
+ // Mark all the called functions
+ for(CallGraphNode::iterator cgn_it = CGN->begin();
+ cgn_it != CGN->end(); ++cgn_it) {
+ Function *CalledF = cgn_it->second->getFunction();
+
+ // If calling an external function then CallGraphNode
+ // will not be associated with any function.
+ if (! CalledF)
+ continue;
+
+ // Issue diagnostic if interrupt function is being called.
+ if (PAN::isISR(CalledF->getSection())) {
+ vector<string> Values;
+ Values.push_back(CalledF->getName().str());
+ reportError("Interrupt function (%0) can't be called", Values);
+ }
+
+ // Has already been mark
+ if (CalledF->getSection().find(StringMark) != string::npos) {
+ // Should we do anything here?
+ } else {
+ // Mark now
+ CalledF->setSection(StringMark);
+ }
+
+ // Before going any further mark all the called function by current
+ // function.
+ markCallGraph(cgn_it->second ,StringMark);
+ } // end of loop of all called functions.
+}
+
+
+// For PIC16, automatic variables of a function are emitted as globals.
+// Clone the auto variables of a function and put them in ValueMap,
+// this ValueMap will be used while
+// Cloning the code of function itself.
+//
+void PIC16Cloner::CloneAutos(Function *F) {
+ // We'll need to update module's globals list as well. So keep a reference
+ // handy.
+ Module *M = F->getParent();
+ Module::GlobalListType &Globals = M->getGlobalList();
+
+ // Clear the leftovers in ValueMap by any previous cloning.
+ ValueMap.clear();
+
+ // Find the auto globls for this function and clone them, and put them
+ // in ValueMap.
+ std::string FnName = F->getName().str();
+ std::string VarName, ClonedVarName;
+ for (Module::global_iterator I = M->global_begin(), E = M->global_end();
+ I != E; ++I) {
+ VarName = I->getName().str();
+ if (PAN::isLocalToFunc(FnName, VarName)) {
+ // Auto variable for current function found. Clone it.
+ const GlobalVariable *GV = I;
+
+ const Type *InitTy = GV->getInitializer()->getType();
+ GlobalVariable *ClonedGV =
+ new GlobalVariable(InitTy, false, GV->getLinkage(),
+ GV->getInitializer());
+ ClonedGV->setName(PAN::getCloneVarName(FnName, VarName));
+ // Add these new globals to module's globals list.
+ Globals.push_back(ClonedGV);
+
+ // Update ValueMap.
+ ValueMap[GV] = ClonedGV;
+ }
+ }
+}
+
+
+// Clone all functions that are reachable from ISR and are already
+// marked as ML.
+//
+void PIC16Cloner::cloneSharedFunctions(CallGraphNode *CGN) {
+
+ // Check all the called functions from ISR.
+ for(CallGraphNode::iterator cgn_it = CGN->begin();
+ cgn_it != CGN->end(); ++cgn_it) {
+ Function *CalledF = cgn_it->second->getFunction();
+
+ // If calling an external function then CallGraphNode
+ // will not be associated with any function.
+ if (!CalledF)
+ continue;
+
+ // Issue diagnostic if interrupt function is being called.
+ if (PAN::isISR(CalledF->getSection())) {
+ vector<string> Values;
+ Values.push_back(CalledF->getName().str());
+ reportError("Interrupt function (%0) can't be called", Values);
+ }
+
+ if (CalledF->getSection().find("ML") != string::npos) {
+ // Function is alternatively marked. It should be a shared one.
+ // Create IL copy. Passing called function as first argument
+ // and the caller as the second argument.
+
+ // Before making IL copy, first ensure that this function has a
+ // body. If the function does have a body. It can't be cloned.
+ // Such a case may occur when the function has been declarated
+ // in the C source code but its body exists in assembly file.
+ if (!CalledF->isDeclaration()) {
+ Function *cf = cloneFunction(CalledF);
+ remapAllSites(CGN->getFunction(), CalledF, cf);
+ } else {
+ // It is called only from ISR. Still mark it as we need this info
+ // in code gen while calling intrinsics.Function is not marked.
+ CalledF->setSection("IL");
+ }
+ }
+ // Before going any further clone all the shared function reachaable
+ // by current function.
+ cloneSharedFunctions(cgn_it->second);
+ } // end of loop of all called functions.
+}
+
+// Clone the given function and return it.
+// Note: it uses the ValueMap member of the class, which is already populated
+// by cloneAutos by the time we reach here.
+// FIXME: Should we just pass ValueMap's ref as a parameter here? rather
+// than keeping the ValueMap as a member.
+Function *
+PIC16Cloner::cloneFunction(Function *OrgF) {
+ Function *ClonedF;
+
+ // See if we already cloned it. Return that.
+ cloned_map_iterator cm_it = ClonedFunctionMap.find(OrgF);
+ if(cm_it != ClonedFunctionMap.end()) {
+ ClonedF = cm_it->second;
+ return ClonedF;
+ }
+
+ // Clone does not exist.
+ // First clone the autos, and populate ValueMap.
+ CloneAutos(OrgF);
+
+ // Now create the clone.
+ ClonedF = CloneFunction(OrgF, ValueMap);
+
+ // The new function should be for interrupt line. Therefore should have
+ // the name suffixed with IL and section attribute marked with IL.
+ ClonedF->setName(PAN::getCloneFnName(OrgF->getName()));
+ ClonedF->setSection("IL");
+
+ // Add the newly created function to the module.
+ OrgF->getParent()->getFunctionList().push_back(ClonedF);
+
+ // Update the ClonedFunctionMap to record this cloning activity.
+ ClonedFunctionMap[OrgF] = ClonedF;
+
+ return ClonedF;
+}
+
+
+// Remap the call sites of shared functions, that are in IL.
+// Change the IL call site of a shared function to its clone.
+//
+void PIC16Cloner::
+remapAllSites(Function *Caller, Function *OrgF, Function *Clone) {
+ // First find the caller to update. If the caller itself is cloned
+ // then use the cloned caller. Otherwise use it.
+ cloned_map_iterator cm_it = ClonedFunctionMap.find(Caller);
+ if (cm_it != ClonedFunctionMap.end())
+ Caller = cm_it->second;
+
+ // For the lack of a better call site finding mechanism, iterate over
+ // all insns to find the uses of original fn.
+ for (Function::iterator BI = Caller->begin(); BI != Caller->end(); ++BI) {
+ BasicBlock &BB = *BI;
+ for (BasicBlock::iterator II = BB.begin(); II != BB.end(); ++II) {
+ if (II->getNumOperands() > 0 && II->getOperand(0) == OrgF)
+ II->setOperand(0, Clone);
+ }
+ }
+}
+
+
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h b/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h
new file mode 100644
index 0000000..24c1152
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Cloner.h
@@ -0,0 +1,83 @@
+//===-- PIC16Cloner.h - PIC16 LLVM Cloner for shared functions --*- 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 declaration of a cloner class clone all functions that
+// are shared between the main line code (ML) and interrupt line code (IL).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16CLONER_H
+#define PIC16CLONER_H
+
+#include "llvm/ADT/DenseMap.h"
+
+using namespace llvm;
+using std::vector;
+using std::string;
+using std::map;
+
+namespace llvm {
+ // forward classes.
+ class Value;
+ class Function;
+ class Module;
+ class ModulePass;
+ class CallGraph;
+ class CallGraphNode;
+ class AnalysisUsage;
+
+ class PIC16Cloner : public ModulePass {
+ public:
+ static char ID; // Class identification
+ PIC16Cloner() : ModulePass(&ID) {}
+
+ virtual void getAnalysisUsage(AnalysisUsage &AU) const {
+ AU.addRequired<CallGraph>();
+ }
+ virtual bool runOnModule(Module &M);
+
+ private: // Functions
+ // Mark reachable functions for the MainLine or InterruptLine.
+ void markCallGraph(CallGraphNode *CGN, string StringMark);
+
+ // Clone auto variables of function specified.
+ void CloneAutos(Function *F);
+
+ // Clone the body of a function.
+ Function *cloneFunction(Function *F);
+
+ // Clone all shared functions.
+ void cloneSharedFunctions(CallGraphNode *isrCGN);
+
+ // Remap all call sites to the shared function.
+ void remapAllSites(Function *Caller, Function *OrgF, Function *Clone);
+
+ // Error reporting for PIC16Pass
+ void reportError(string ErrorString, vector<string> &Values);
+ void reportError(string ErrorString);
+
+ private: //data
+ // Records if the interrupt function has already been found.
+ // If more than one interrupt function is found then an error
+ // should be thrown.
+ bool foundISR;
+
+ // This ValueMap maps the auto variables of the original functions with
+ // the corresponding cloned auto variable of the cloned function.
+ // This value map is passed during the function cloning so that all the
+ // uses of auto variables be updated properly.
+ DenseMap<const Value*, Value*> ValueMap;
+
+ // Map of a already cloned functions.
+ map<Function *, Function *> ClonedFunctionMap;
+ typedef map<Function *, Function *>::iterator cloned_map_iterator;
+ };
+} // End of anonymous namespace
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp b/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp
new file mode 100644
index 0000000..5ecb6aa
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Overlay.cpp
@@ -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 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;
+ }
+ }
+ }
+}
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Overlay.h b/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Overlay.h
new file mode 100644
index 0000000..5a2551f
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Passes/PIC16Overlay.h
@@ -0,0 +1,60 @@
+//===-- PIC16Overlay.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
+
+
+using std::string;
+using namespace llvm;
+
+namespace llvm {
+ // Forward declarations.
+ class Function;
+ class Module;
+ class ModulePass;
+ class AnalysisUsage;
+ class CallGraphNode;
+ class CallGraph;
+
+ namespace PIC16OVERLAY {
+ enum OverlayConsts {
+ StartInterruptColor = 200,
+ StartIndirectCallColor = 300
+ };
+ }
+ class PIC16Overlay : public ModulePass {
+ std::string OverlayStr;
+ unsigned InterruptDepth;
+ unsigned IndirectCallColor;
+ public:
+ static char ID; // Class identification
+ PIC16Overlay() : 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
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.cpp b/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.cpp
new file mode 100644
index 0000000..30a1d4a
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.cpp
@@ -0,0 +1,94 @@
+//===- PIC16RegisterInfo.cpp - PIC16 Register Information -----------------===//
+//
+// 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 implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-reg-info"
+
+#include "PIC16.h"
+#include "PIC16RegisterInfo.h"
+#include "llvm/ADT/BitVector.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii,
+ const PIC16Subtarget &st)
+ : PIC16GenRegisterInfo(PIC16::ADJCALLSTACKDOWN, PIC16::ADJCALLSTACKUP),
+ TII(tii),
+ ST(st) {}
+
+#include "PIC16GenRegisterInfo.inc"
+
+/// PIC16 Callee Saved Registers
+const unsigned* PIC16RegisterInfo::
+getCalleeSavedRegs(const MachineFunction *MF) const {
+ static const unsigned CalleeSavedRegs[] = { 0 };
+ return CalleeSavedRegs;
+}
+
+// PIC16 Callee Saved Reg Classes
+const TargetRegisterClass* const*
+PIC16RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
+ static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 0 };
+ return CalleeSavedRegClasses;
+}
+
+BitVector PIC16RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
+ BitVector Reserved(getNumRegs());
+ return Reserved;
+}
+
+bool PIC16RegisterInfo::hasFP(const MachineFunction &MF) const {
+ return false;
+}
+
+unsigned PIC16RegisterInfo::
+eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
+ FrameIndexValue *Value, RegScavenger *RS) const
+{
+ /* NOT YET IMPLEMENTED */
+ return 0;
+}
+
+void PIC16RegisterInfo::emitPrologue(MachineFunction &MF) const
+{ /* NOT YET IMPLEMENTED */ }
+
+void PIC16RegisterInfo::
+emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
+{ /* NOT YET IMPLEMENTED */ }
+
+int PIC16RegisterInfo::
+getDwarfRegNum(unsigned RegNum, bool isEH) const {
+ llvm_unreachable("Not keeping track of debug information yet!!");
+ return -1;
+}
+
+unsigned PIC16RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
+ llvm_unreachable("PIC16 Does not have any frame register");
+ return 0;
+}
+
+unsigned PIC16RegisterInfo::getRARegister() const {
+ llvm_unreachable("PIC16 Does not have any return address register");
+ return 0;
+}
+
+// This function eliminates ADJCALLSTACKDOWN,
+// ADJCALLSTACKUP pseudo instructions
+void PIC16RegisterInfo::
+eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const {
+ // Simply discard ADJCALLSTACKDOWN,
+ // ADJCALLSTACKUP instructions.
+ MBB.erase(I);
+}
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.h b/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.h
new file mode 100644
index 0000000..6a9a038
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.h
@@ -0,0 +1,69 @@
+//===- PIC16RegisterInfo.h - PIC16 Register Information Impl ----*- 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 implementation of the TargetRegisterInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16REGISTERINFO_H
+#define PIC16REGISTERINFO_H
+
+#include "PIC16GenRegisterInfo.h.inc"
+#include "llvm/Target/TargetRegisterInfo.h"
+
+namespace llvm {
+
+// Forward Declarations.
+ class PIC16Subtarget;
+ class TargetInstrInfo;
+
+class PIC16RegisterInfo : public PIC16GenRegisterInfo {
+ private:
+ const TargetInstrInfo &TII;
+ const PIC16Subtarget &ST;
+
+ public:
+ PIC16RegisterInfo(const TargetInstrInfo &tii,
+ const PIC16Subtarget &st);
+
+
+ //------------------------------------------------------
+ // Pure virtual functions from TargetRegisterInfo
+ //------------------------------------------------------
+
+ // PIC16 callee saved registers
+ virtual const unsigned*
+ getCalleeSavedRegs(const MachineFunction *MF = 0) const;
+
+ // PIC16 callee saved register classes
+ virtual const TargetRegisterClass* const *
+ getCalleeSavedRegClasses(const MachineFunction *MF) const;
+
+ virtual BitVector getReservedRegs(const MachineFunction &MF) const;
+ virtual bool hasFP(const MachineFunction &MF) const;
+
+ virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI,
+ int SPAdj, FrameIndexValue *Value = NULL,
+ RegScavenger *RS=NULL) const;
+
+ void eliminateCallFramePseudoInstr(MachineFunction &MF,
+ MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const;
+
+ virtual void emitPrologue(MachineFunction &MF) const;
+ virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
+ virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const;
+ virtual unsigned getFrameRegister(const MachineFunction &MF) const;
+ virtual unsigned getRARegister() const;
+
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.td b/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.td
new file mode 100644
index 0000000..2959d91
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16RegisterInfo.td
@@ -0,0 +1,33 @@
+//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Declarations that describe the PIC16 register file
+//===----------------------------------------------------------------------===//
+
+class PIC16Reg<string n> : Register<n> {
+ let Namespace = "PIC16";
+}
+
+// PIC16 Registers.
+def W : PIC16Reg<"W">;
+def FSR0 : PIC16Reg<"FSR0">;
+def FSR1 : PIC16Reg<"FSR1">;
+def BS : PIC16Reg<"BS">;
+def PCLATH : PIC16Reg<"PCLATH">;
+
+def STATUS : PIC16Reg<"STATUS">;
+
+// PIC16 Register classes.
+def GPR : RegisterClass<"PIC16", [i8], 8, [W]>;
+def FSR16 : RegisterClass<"PIC16", [i16], 8, [FSR0, FSR1]>;
+def BSR : RegisterClass<"PIC16", [i8], 8, [BS]>;
+def PCLATHR : RegisterClass<"PIC16", [i8], 8, [PCLATH]>;
+def STATUSR : RegisterClass<"PIC16", [i8], 8, [STATUS]>;
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Section.cpp b/contrib/llvm/lib/Target/PIC16/PIC16Section.cpp
new file mode 100644
index 0000000..2505b11
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Section.cpp
@@ -0,0 +1,104 @@
+//===-- PIC16Section.cpp - PIC16 Section ----------- --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16.h"
+#include "PIC16ABINames.h"
+#include "PIC16Section.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+
+// This is the only way to create a PIC16Section. Sections created here
+// do not need to be explicitly deleted as they are managed by auto_ptrs.
+PIC16Section *PIC16Section::Create(StringRef Name, PIC16SectionType Ty,
+ StringRef Address, int Color,
+ MCContext &Ctx) {
+
+ /// Determine the internal SectionKind info.
+ /// Users of PIC16Section class should not need to know the internal
+ /// SectionKind. They should work only with PIC16SectionType.
+ ///
+ /// PIC16 Terminology for section kinds is as below.
+ /// UDATA - BSS
+ /// IDATA - initialized data (equiv to Metadata)
+ /// ROMDATA - ReadOnly.
+ /// UDATA_OVR - Sections that can be overlaid. Section of such type is
+ /// used to contain function autos an frame. We can think of
+ /// it as equiv to llvm ThreadBSS)
+ /// UDATA_SHR - Shared RAM. Memory area that is mapped to all banks.
+
+ SectionKind K;
+ switch (Ty) {
+ default: llvm_unreachable ("can not create unknown section type");
+ case UDATA_OVR: {
+ K = SectionKind::getThreadBSS();
+ break;
+ }
+ case UDATA_SHR:
+ case UDATA: {
+ K = SectionKind::getBSS();
+ break;
+ }
+ case ROMDATA:
+ case IDATA: {
+ K = SectionKind::getMetadata();
+ break;
+ }
+ case CODE: {
+ K = SectionKind::getText();
+ break;
+ }
+
+ }
+
+ // Copy strings into context allocated memory so they get free'd when the
+ // context is destroyed.
+ char *NameCopy = static_cast<char*>(Ctx.Allocate(Name.size(), 1));
+ memcpy(NameCopy, Name.data(), Name.size());
+ char *AddressCopy = static_cast<char*>(Ctx.Allocate(Address.size(), 1));
+ memcpy(AddressCopy, Address.data(), Address.size());
+
+ // Create the Section.
+ PIC16Section *S =
+ new (Ctx) PIC16Section(StringRef(NameCopy, Name.size()), K,
+ StringRef(AddressCopy, Address.size()), Color);
+ S->T = Ty;
+ return S;
+}
+
+// A generic way to print all types of sections.
+void PIC16Section::PrintSwitchToSection(const MCAsmInfo &MAI,
+ raw_ostream &OS) const {
+
+ // 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()) {
+ default : llvm_unreachable ("unknown section type");
+ case UDATA: OS << "UDATA"; break;
+ case IDATA: OS << "IDATA"; break;
+ case ROMDATA: OS << "ROMDATA"; break;
+ case UDATA_SHR: OS << "UDATA_SHR"; break;
+ case UDATA_OVR: OS << "UDATA_OVR"; break;
+ case CODE: OS << "CODE"; break;
+ }
+
+ OS << '\t';
+
+ // Print Address.
+ OS << Address;
+
+ OS << '\n';
+}
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Section.h b/contrib/llvm/lib/Target/PIC16/PIC16Section.h
new file mode 100644
index 0000000..5b33b51
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Section.h
@@ -0,0 +1,99 @@
+//===- PIC16Section.h - PIC16-specific section representation -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the PIC16Section class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_PIC16SECTION_H
+#define LLVM_PIC16SECTION_H
+
+#include "llvm/MC/MCSection.h"
+#include "llvm/GlobalVariable.h"
+#include <vector>
+
+namespace llvm {
+ /// PIC16Section - Represents a physical section in PIC16 COFF.
+ /// Contains data objects.
+ ///
+ class PIC16Section : public MCSection {
+ /// PIC16 Sections does not really use the SectionKind class to
+ /// to distinguish between various types of sections. PIC16 maintain
+ /// its own Section Type info. See the PIC16SectionType enum in PIC16.h
+ /// for various section types.
+ PIC16SectionType T;
+
+ /// Name of the section to uniquely identify it.
+ StringRef Name;
+
+ /// User can specify an address at which a section should be placed.
+ /// Negative value here means user hasn't specified any.
+ StringRef Address;
+
+ /// Overlay information - Sections with same color can be overlaid on
+ /// one another.
+ int Color;
+
+ /// Total size of all data objects contained here.
+ unsigned Size;
+
+ PIC16Section(StringRef name, SectionKind K, StringRef addr, int color)
+ : MCSection(SV_PIC16, K), Name(name), Address(addr),
+ Color(color), Size(0) {
+ }
+
+ public:
+ /// Return the name of the section.
+ StringRef getName() const { return Name; }
+
+ /// Return the Address of the section.
+ StringRef getAddress() const { return Address; }
+
+ /// 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; }
+ void setSize(unsigned size) { Size = size; }
+
+ /// Conatined data objects.
+ // FIXME: This vector is leaked because sections are allocated with a
+ // BumpPtrAllocator.
+ std::vector<const GlobalVariable *>Items;
+
+ /// Check section type.
+ bool isUDATA_Type() const { return T == UDATA; }
+ bool isIDATA_Type() const { return T == IDATA; }
+ bool isROMDATA_Type() const { return T == ROMDATA; }
+ bool isUDATA_OVR_Type() const { return T == UDATA_OVR; }
+ bool isUDATA_SHR_Type() const { return T == UDATA_SHR; }
+ bool isCODE_Type() const { return T == CODE; }
+
+ PIC16SectionType getType() const { return T; }
+
+ /// This would be the only way to create a section.
+ static PIC16Section *Create(StringRef Name, PIC16SectionType Ty,
+ StringRef Address, int Color,
+ MCContext &Ctx);
+
+ /// Override this as PIC16 has its own way of printing switching
+ /// to a section.
+ virtual void PrintSwitchToSection(const MCAsmInfo &MAI,
+ raw_ostream &OS) const;
+
+ static bool classof(const MCSection *S) {
+ return S->getVariant() == SV_PIC16;
+ }
+ static bool classof(const PIC16Section *) { return true; }
+ };
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16SelectionDAGInfo.cpp b/contrib/llvm/lib/Target/PIC16/PIC16SelectionDAGInfo.cpp
new file mode 100644
index 0000000..995955a
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16SelectionDAGInfo.cpp
@@ -0,0 +1,23 @@
+//===-- PIC16SelectionDAGInfo.cpp - PIC16 SelectionDAG Info ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PIC16SelectionDAGInfo class.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "pic16-selectiondag-info"
+#include "PIC16TargetMachine.h"
+using namespace llvm;
+
+PIC16SelectionDAGInfo::PIC16SelectionDAGInfo(const PIC16TargetMachine &TM)
+ : TargetSelectionDAGInfo(TM) {
+}
+
+PIC16SelectionDAGInfo::~PIC16SelectionDAGInfo() {
+}
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16SelectionDAGInfo.h b/contrib/llvm/lib/Target/PIC16/PIC16SelectionDAGInfo.h
new file mode 100644
index 0000000..c67fd8b
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16SelectionDAGInfo.h
@@ -0,0 +1,31 @@
+//===-- PIC16SelectionDAGInfo.h - PIC16 SelectionDAG Info -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the PIC16 subclass for TargetSelectionDAGInfo.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16SELECTIONDAGINFO_H
+#define PIC16SELECTIONDAGINFO_H
+
+#include "llvm/Target/TargetSelectionDAGInfo.h"
+
+namespace llvm {
+
+class PIC16TargetMachine;
+
+class PIC16SelectionDAGInfo : public TargetSelectionDAGInfo {
+public:
+ explicit PIC16SelectionDAGInfo(const PIC16TargetMachine &TM);
+ ~PIC16SelectionDAGInfo();
+};
+
+}
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Subtarget.cpp b/contrib/llvm/lib/Target/PIC16/PIC16Subtarget.cpp
new file mode 100644
index 0000000..33fc3fb
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Subtarget.cpp
@@ -0,0 +1,27 @@
+//===- PIC16Subtarget.cpp - PIC16 Subtarget Information -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the PIC16 specific subclass of TargetSubtarget.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16Subtarget.h"
+#include "PIC16GenSubtarget.inc"
+
+using namespace llvm;
+
+PIC16Subtarget::PIC16Subtarget(const std::string &TT, const std::string &FS,
+ bool Cooper)
+ :IsCooper(Cooper)
+{
+ std::string CPU = "generic";
+
+ // Parse features string.
+ ParseSubtargetFeatures(FS, CPU);
+}
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16Subtarget.h b/contrib/llvm/lib/Target/PIC16/PIC16Subtarget.h
new file mode 100644
index 0000000..81e3783
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16Subtarget.h
@@ -0,0 +1,44 @@
+//=====-- PIC16Subtarget.h - Define Subtarget for the PIC16 ---*- C++ -*--====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the PIC16 specific subclass of TargetSubtarget.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef PIC16SUBTARGET_H
+#define PIC16SUBTARGET_H
+
+#include "llvm/Target/TargetSubtarget.h"
+
+#include <string>
+
+namespace llvm {
+
+class PIC16Subtarget : public TargetSubtarget {
+
+ // IsCooper - Target ISA is Cooper.
+ bool IsCooper;
+
+public:
+ /// This constructor initializes the data members to match that
+ /// of the specified triple.
+ ///
+ PIC16Subtarget(const std::string &TT, const std::string &FS, bool Cooper);
+
+ /// isCooper - Returns true if the target ISA is Cooper.
+ bool isCooper() const { return IsCooper; }
+
+ /// ParseSubtargetFeatures - Parses features string setting specified
+ /// subtarget options. Definition of function is auto generated by tblgen.
+ std::string ParseSubtargetFeatures(const std::string &FS,
+ const std::string &CPU);
+};
+} // End llvm namespace
+
+#endif // PIC16SUBTARGET_H
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16TargetMachine.cpp b/contrib/llvm/lib/Target/PIC16/PIC16TargetMachine.cpp
new file mode 100644
index 0000000..82b69be
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16TargetMachine.cpp
@@ -0,0 +1,55 @@
+//===-- PIC16TargetMachine.cpp - Define TargetMachine for PIC16 -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Top-level implementation for the PIC16 target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16.h"
+#include "PIC16MCAsmInfo.h"
+#include "PIC16TargetMachine.h"
+#include "llvm/PassManager.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Target/TargetRegistry.h"
+
+using namespace llvm;
+
+extern "C" void LLVMInitializePIC16Target() {
+ // Register the target. Curretnly the codegen works for
+ // enhanced pic16 mid-range.
+ RegisterTargetMachine<PIC16TargetMachine> X(ThePIC16Target);
+ RegisterAsmInfo<PIC16MCAsmInfo> A(ThePIC16Target);
+}
+
+
+// PIC16TargetMachine - Enhanced PIC16 mid-range Machine. May also represent
+// a Traditional Machine if 'Trad' is true.
+PIC16TargetMachine::PIC16TargetMachine(const Target &T, const std::string &TT,
+ const std::string &FS, bool Trad)
+: LLVMTargetMachine(T, TT),
+ Subtarget(TT, FS, Trad),
+ DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-n8"),
+ InstrInfo(*this), TLInfo(*this), TSInfo(*this),
+ FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { }
+
+
+bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
+ // Install an instruction selector.
+ PM.add(createPIC16ISelDag(*this));
+ return false;
+}
+
+bool PIC16TargetMachine::addPreEmitPass(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel) {
+ PM.add(createPIC16MemSelOptimizerPass());
+ return true; // -print-machineinstr should print after this.
+}
+
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16TargetMachine.h b/contrib/llvm/lib/Target/PIC16/PIC16TargetMachine.h
new file mode 100644
index 0000000..dae5d31
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16TargetMachine.h
@@ -0,0 +1,70 @@
+//===-- PIC16TargetMachine.h - Define TargetMachine for PIC16 ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the PIC16 specific subclass of TargetMachine.
+//
+//===----------------------------------------------------------------------===//
+
+
+#ifndef PIC16_TARGETMACHINE_H
+#define PIC16_TARGETMACHINE_H
+
+#include "PIC16InstrInfo.h"
+#include "PIC16ISelLowering.h"
+#include "PIC16SelectionDAGInfo.h"
+#include "PIC16RegisterInfo.h"
+#include "PIC16Subtarget.h"
+#include "llvm/Target/TargetData.h"
+#include "llvm/Target/TargetFrameInfo.h"
+#include "llvm/Target/TargetMachine.h"
+
+namespace llvm {
+
+/// PIC16TargetMachine
+///
+class PIC16TargetMachine : public LLVMTargetMachine {
+ PIC16Subtarget Subtarget;
+ const TargetData DataLayout; // Calculates type size & alignment
+ PIC16InstrInfo InstrInfo;
+ PIC16TargetLowering TLInfo;
+ PIC16SelectionDAGInfo TSInfo;
+
+ // PIC16 does not have any call stack frame, therefore not having
+ // any PIC16 specific FrameInfo class.
+ TargetFrameInfo FrameInfo;
+
+public:
+ PIC16TargetMachine(const Target &T, const std::string &TT,
+ const std::string &FS, bool Cooper = false);
+
+ virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
+ virtual const PIC16InstrInfo *getInstrInfo() const { return &InstrInfo; }
+ virtual const TargetData *getTargetData() const { return &DataLayout;}
+ virtual const PIC16Subtarget *getSubtargetImpl() const { return &Subtarget; }
+
+ virtual const PIC16RegisterInfo *getRegisterInfo() const {
+ return &(InstrInfo.getRegisterInfo());
+ }
+
+ virtual const PIC16TargetLowering *getTargetLowering() const {
+ return &TLInfo;
+ }
+
+ virtual const PIC16SelectionDAGInfo* getSelectionDAGInfo() const {
+ return &TSInfo;
+ }
+
+ virtual bool addInstSelector(PassManagerBase &PM,
+ CodeGenOpt::Level OptLevel);
+ virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
+}; // PIC16TargetMachine.
+
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp b/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp
new file mode 100644
index 0000000..ff0f971
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.cpp
@@ -0,0 +1,384 @@
+//===-- PIC16TargetObjectFile.cpp - PIC16 object files --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16TargetObjectFile.h"
+#include "PIC16TargetMachine.h"
+#include "PIC16Section.h"
+#include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+
+PIC16TargetObjectFile::PIC16TargetObjectFile() {
+}
+
+PIC16TargetObjectFile::~PIC16TargetObjectFile() {
+}
+
+/// Find a pic16 section. Return null if not found. Do not create one.
+PIC16Section *PIC16TargetObjectFile::
+findPIC16Section(const std::string &Name) const {
+ /// 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,
+ const std::string &Address, int Color) const {
+
+ /// Return if we have an already existing one.
+ PIC16Section *&Entry = SectionsByName[Name];
+ if (Entry)
+ return Entry;
+
+
+ Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
+ return Entry;
+}
+
+/// Find a standard pic16 data section. If not found, create one and keep
+/// track of it by adding it to appropriate std section list.
+PIC16Section *PIC16TargetObjectFile::
+getPIC16DataSection(const std::string &Name, PIC16SectionType Ty,
+ const std::string &Address, int Color) const {
+
+ /// Return if we have an already existing one.
+ PIC16Section *&Entry = SectionsByName[Name];
+ if (Entry)
+ return Entry;
+
+
+ /// Else create a new one and add it to appropriate section list.
+ Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
+
+ switch (Ty) {
+ default: llvm_unreachable ("unknow standard section type.");
+ case UDATA: UDATASections_.push_back(Entry); break;
+ case IDATA: IDATASections_.push_back(Entry); break;
+ case ROMDATA: ROMDATASection_ = Entry; break;
+ case UDATA_SHR: SHAREDUDATASection_ = Entry; break;
+ }
+
+ return Entry;
+}
+
+
+/// Find a standard pic16 autos section. If not found, create one and keep
+/// track of it by adding it to appropriate std section list.
+PIC16Section *PIC16TargetObjectFile::
+getPIC16AutoSection(const std::string &Name, PIC16SectionType Ty,
+ const std::string &Address, int Color) const {
+
+ /// Return if we have an already existing one.
+ PIC16Section *&Entry = SectionsByName[Name];
+ if (Entry)
+ return Entry;
+
+
+ /// Else create a new one and add it to appropriate section list.
+ Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
+
+ assert (Ty == UDATA_OVR && "incorrect section type for autos");
+ AUTOSections_.push_back(Entry);
+
+ return Entry;
+}
+
+/// Find a pic16 user section. If not found, create one and keep
+/// track of it by adding it to appropriate std section list.
+PIC16Section *PIC16TargetObjectFile::
+getPIC16UserSection(const std::string &Name, PIC16SectionType Ty,
+ const std::string &Address, int Color) const {
+
+ /// Return if we have an already existing one.
+ PIC16Section *&Entry = SectionsByName[Name];
+ if (Entry)
+ return Entry;
+
+
+ /// Else create a new one and add it to appropriate section list.
+ Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
+
+ USERSections_.push_back(Entry);
+
+ return Entry;
+}
+
+/// Do some standard initialization.
+void PIC16TargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &tm){
+ TargetLoweringObjectFile::Initialize(Ctx, tm);
+ TM = &tm;
+
+ ROMDATASection_ = NULL;
+ SHAREDUDATASection_ = NULL;
+}
+
+/// allocateUDATA - Allocate a un-initialized global to an existing or new UDATA
+/// section and return that section.
+const MCSection *
+PIC16TargetObjectFile::allocateUDATA(const GlobalVariable *GV) const {
+ assert(GV->hasInitializer() && "This global doesn't need space");
+ const Constant *C = GV->getInitializer();
+ assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
+
+ // Find how much space this global needs.
+ const TargetData *TD = TM->getTargetData();
+ const Type *Ty = C->getType();
+ unsigned ValSize = TD->getTypeAllocSize(Ty);
+
+ // Go through all UDATA Sections and assign this variable
+ // to the first available section having enough space.
+ PIC16Section *Found = NULL;
+ for (unsigned i = 0; i < UDATASections_.size(); i++) {
+ if (DataBankSize - UDATASections_[i]->getSize() >= ValSize) {
+ Found = UDATASections_[i];
+ break;
+ }
+ }
+
+ // No UDATA section spacious enough was found. Crate a new one.
+ if (!Found) {
+ std::string name = PAN::getUdataSectionName(UDATASections_.size());
+ Found = getPIC16DataSection(name.c_str(), UDATA);
+ }
+
+ // Insert the GV into this UDATA section.
+ Found->Items.push_back(GV);
+ Found->setSize(Found->getSize() + ValSize);
+ return Found;
+}
+
+/// allocateIDATA - allocate an initialized global into an existing
+/// or new section and return that section.
+const MCSection *
+PIC16TargetObjectFile::allocateIDATA(const GlobalVariable *GV) const{
+ assert(GV->hasInitializer() && "This global doesn't need space");
+ const Constant *C = GV->getInitializer();
+ assert(!C->isNullValue() && "initialized globals has zero initializer");
+ assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
+ "can allocate initialized RAM data only");
+
+ // Find how much space this global needs.
+ const TargetData *TD = TM->getTargetData();
+ const Type *Ty = C->getType();
+ unsigned ValSize = TD->getTypeAllocSize(Ty);
+
+ // Go through all IDATA Sections and assign this variable
+ // to the first available section having enough space.
+ PIC16Section *Found = NULL;
+ for (unsigned i = 0; i < IDATASections_.size(); i++) {
+ if (DataBankSize - IDATASections_[i]->getSize() >= ValSize) {
+ Found = IDATASections_[i];
+ break;
+ }
+ }
+
+ // No IDATA section spacious enough was found. Crate a new one.
+ if (!Found) {
+ std::string name = PAN::getIdataSectionName(IDATASections_.size());
+ Found = getPIC16DataSection(name.c_str(), IDATA);
+ }
+
+ // Insert the GV into this IDATA.
+ Found->Items.push_back(GV);
+ Found->setSize(Found->getSize() + ValSize);
+ return Found;
+}
+
+// Allocate a program memory variable into ROMDATA section.
+const MCSection *
+PIC16TargetObjectFile::allocateROMDATA(const GlobalVariable *GV) const {
+
+ std::string name = PAN::getRomdataSectionName();
+ PIC16Section *S = getPIC16DataSection(name.c_str(), ROMDATA);
+
+ S->Items.push_back(GV);
+ return S;
+}
+
+// Get the section for an automatic variable of a function.
+// For PIC16 they are globals only with mangled names.
+const MCSection *
+PIC16TargetObjectFile::allocateAUTO(const GlobalVariable *GV) const {
+
+ const std::string name = PAN::getSectionNameForSym(GV->getName());
+ PIC16Section *S = getPIC16AutoSection(name.c_str());
+
+ S->Items.push_back(GV);
+ return S;
+}
+
+
+// Override default implementation to put the true globals into
+// multiple data sections if required.
+const MCSection *
+PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1,
+ SectionKind Kind,
+ Mangler *Mang,
+ const TargetMachine &TM) const {
+ // We select the section based on the initializer here, so it really
+ // has to be a GlobalVariable.
+ const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
+ if (!GV)
+ return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Kind, Mang,TM);
+
+ assert(GV->hasInitializer() && "A def without initializer?");
+
+ // First, if this is an automatic variable for a function, get the section
+ // name for it and return.
+ std::string name = GV->getName();
+ if (PAN::isLocalName(name))
+ return allocateAUTO(GV);
+
+ // See if this is an uninitialized global.
+ const Constant *C = GV->getInitializer();
+ if (C->isNullValue())
+ return allocateUDATA(GV);
+
+ // If this is initialized data in RAM. Put it in the correct IDATA section.
+ if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
+ return allocateIDATA(GV);
+
+ // This is initialized data in rom, put it in the readonly section.
+ if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
+ return allocateROMDATA(GV);
+
+ // Else let the default implementation take care of it.
+ return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, Mang,TM);
+}
+
+
+
+
+/// getExplicitSectionGlobal - Allow the target to completely override
+/// section assignment of a global.
+const MCSection *PIC16TargetObjectFile::
+getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler *Mang, const TargetMachine &TM) const {
+ assert(GV->hasSection());
+
+ if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
+ std::string SectName = GVar->getSection();
+ // If address for a variable is specified, get the address and create
+ // section.
+ // FIXME: move this attribute checking in PAN.
+ std::string AddrStr = "Address=";
+ if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
+ std::string SectAddr = SectName.substr(AddrStr.length());
+ if (SectAddr.compare("NEAR") == 0)
+ return allocateSHARED(GVar, Mang);
+ else
+ return allocateAtGivenAddress(GVar, SectAddr);
+ }
+
+ // Create the section specified with section attribute.
+ return allocateInGivenSection(GVar);
+ }
+
+ return getPIC16DataSection(GV->getSection().c_str(), UDATA);
+}
+
+const MCSection *
+PIC16TargetObjectFile::allocateSHARED(const GlobalVariable *GV,
+ Mangler *Mang) const {
+ // Make sure that this is an uninitialized global.
+ assert(GV->hasInitializer() && "This global doesn't need space");
+ if (!GV->getInitializer()->isNullValue()) {
+ // FIXME: Generate a warning in this case that near qualifier will be
+ // ignored.
+ return SelectSectionForGlobal(GV, SectionKind::getDataRel(), Mang, *TM);
+ }
+ std::string Name = PAN::getSharedUDataSectionName();
+
+ PIC16Section *SharedUDataSect = getPIC16DataSection(Name.c_str(), UDATA_SHR);
+ // Insert the GV into shared section.
+ SharedUDataSect->Items.push_back(GV);
+ return SharedUDataSect;
+}
+
+
+// Interface used by AsmPrinter to get a code section for a function.
+const PIC16Section *
+PIC16TargetObjectFile::SectionForCode(const std::string &FnName,
+ bool isISR) const {
+ const std::string &sec_name = PAN::getCodeSectionName(FnName);
+ // If it is ISR, its code section starts at a specific address.
+ if (isISR)
+ return getPIC16Section(sec_name, CODE, PAN::getISRAddr());
+ return getPIC16Section(sec_name, CODE);
+}
+
+// Interface used by AsmPrinter to get a frame section for a function.
+const PIC16Section *
+PIC16TargetObjectFile::SectionForFrame(const std::string &FnName) const {
+ const std::string &sec_name = PAN::getFrameSectionName(FnName);
+ return getPIC16Section(sec_name, UDATA_OVR);
+}
+
+// Allocate a global var in existing or new section of given name.
+const MCSection *
+PIC16TargetObjectFile::allocateInGivenSection(const GlobalVariable *GV) const {
+ // Determine the type of section that we need to create.
+ PIC16SectionType SecTy;
+
+ // See if this is an uninitialized global.
+ const Constant *C = GV->getInitializer();
+ if (C->isNullValue())
+ SecTy = UDATA;
+ // If this is initialized data in RAM. Put it in the correct IDATA section.
+ else if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
+ SecTy = IDATA;
+ // This is initialized data in rom, put it in the readonly section.
+ else if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
+ SecTy = ROMDATA;
+ else
+ llvm_unreachable ("Could not determine section type for global");
+
+ PIC16Section *S = getPIC16UserSection(GV->getSection().c_str(), SecTy);
+ S->Items.push_back(GV);
+ return S;
+}
+
+// Allocate a global var in a new absolute sections at given address.
+const MCSection *
+PIC16TargetObjectFile::allocateAtGivenAddress(const GlobalVariable *GV,
+ const std::string &Addr) const {
+ // Determine the type of section that we need to create.
+ PIC16SectionType SecTy;
+
+ // See if this is an uninitialized global.
+ const Constant *C = GV->getInitializer();
+ if (C->isNullValue())
+ SecTy = UDATA;
+ // If this is initialized data in RAM. Put it in the correct IDATA section.
+ else if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
+ SecTy = IDATA;
+ // This is initialized data in rom, put it in the readonly section.
+ else if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
+ SecTy = ROMDATA;
+ else
+ llvm_unreachable ("Could not determine section type for global");
+
+ std::string Prefix = GV->getNameStr() + "." + Addr + ".";
+ std::string SName = PAN::getUserSectionName(Prefix);
+ PIC16Section *S = getPIC16UserSection(SName.c_str(), SecTy, Addr.c_str());
+ S->Items.push_back(GV);
+ return S;
+}
+
+
diff --git a/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.h b/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.h
new file mode 100644
index 0000000..b1eb9f9
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/PIC16TargetObjectFile.h
@@ -0,0 +1,168 @@
+//===-- PIC16TargetObjectFile.h - PIC16 Object Info -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_PIC16_TARGETOBJECTFILE_H
+#define LLVM_TARGET_PIC16_TARGETOBJECTFILE_H
+
+#include "PIC16.h"
+#include "PIC16ABINames.h"
+#include "llvm/Target/TargetLoweringObjectFile.h"
+#include "llvm/ADT/StringMap.h"
+#include <vector>
+#include <string>
+
+namespace llvm {
+ class GlobalVariable;
+ class Module;
+ class PIC16TargetMachine;
+ class PIC16Section;
+
+ enum { DataBankSize = 80 };
+
+ /// PIC16 Splits the global data into mulitple udata and idata sections.
+ /// Each udata and idata section needs to contain a list of globals that
+ /// they contain, in order to avoid scanning over all the global values
+ /// again and printing only those that match the current section.
+ /// Keeping values inside the sections make printing a section much easier.
+ ///
+ /// FIXME: MOVE ALL THIS STUFF TO PIC16Section.
+ ///
+
+ /// PIC16TargetObjectFile - PIC16 Object file. Contains data and code
+ /// sections.
+ // PIC16 Object File has two types of sections.
+ // 1. Standard Sections
+ // 1.1 un-initialized global data
+ // 1.2 initialized global data
+ // 1.3 program memory data
+ // 1.4 local variables of functions.
+ // 2. User defined sections
+ // 2.1 Objects placed in a specific section. (By _Section() macro)
+ // 2.2 Objects placed at a specific address. (By _Address() macro)
+ class PIC16TargetObjectFile : public TargetLoweringObjectFile {
+ /// SectionsByName - Bindings of names to allocated sections.
+ mutable StringMap<PIC16Section*> SectionsByName;
+
+ const TargetMachine *TM;
+
+ /// Lists of sections.
+ /// Standard Data Sections.
+ mutable std::vector<PIC16Section *> UDATASections_;
+ mutable std::vector<PIC16Section *> IDATASections_;
+ mutable PIC16Section * ROMDATASection_;
+ mutable PIC16Section * SHAREDUDATASection_;
+
+ /// Standard Auto Sections.
+ mutable std::vector<PIC16Section *> AUTOSections_;
+
+ /// User specified sections.
+ mutable std::vector<PIC16Section *> USERSections_;
+
+
+ /// Find or Create a PIC16 Section, without adding it to any
+ /// section list.
+ PIC16Section *getPIC16Section(const std::string &Name,
+ PIC16SectionType Ty,
+ const std::string &Address = "",
+ int Color = -1) const;
+
+ /// Convenience functions. These wrappers also take care of adding
+ /// the newly created section to the appropriate sections list.
+
+ /// Find or Create PIC16 Standard Data Section.
+ PIC16Section *getPIC16DataSection(const std::string &Name,
+ PIC16SectionType Ty,
+ const std::string &Address = "",
+ int Color = -1) const;
+
+ /// Find or Create PIC16 Standard Auto Section.
+ PIC16Section *getPIC16AutoSection(const std::string &Name,
+ PIC16SectionType Ty = UDATA_OVR,
+ const std::string &Address = "",
+ int Color = -1) const;
+
+ /// Find or Create PIC16 Standard Auto Section.
+ PIC16Section *getPIC16UserSection(const std::string &Name,
+ PIC16SectionType Ty,
+ const std::string &Address = "",
+ int Color = -1) const;
+
+ /// Allocate Un-initialized data to a standard UDATA section.
+ const MCSection *allocateUDATA(const GlobalVariable *GV) const;
+
+ /// Allocate Initialized data to a standard IDATA section.
+ const MCSection *allocateIDATA(const GlobalVariable *GV) const;
+
+ /// Allocate ROM data to the standard ROMDATA section.
+ const MCSection *allocateROMDATA(const GlobalVariable *GV) const;
+
+ /// Allocate an AUTO variable to an AUTO section.
+ const MCSection *allocateAUTO(const GlobalVariable *GV) const;
+
+ /// Allocate DATA in user specified section.
+ const MCSection *allocateInGivenSection(const GlobalVariable *GV) const;
+
+ /// Allocate DATA at user specified address.
+ const MCSection *allocateAtGivenAddress(const GlobalVariable *GV,
+ const std::string &Addr) const;
+
+ /// Allocate a shared variable to SHARED section.
+ const MCSection *allocateSHARED(const GlobalVariable *GV,
+ Mangler *Mang) const;
+
+ public:
+ PIC16TargetObjectFile();
+ ~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) const;
+
+ /// Override section allocations for user specified sections.
+ virtual const MCSection *
+ getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
+ Mangler *Mang, const TargetMachine &TM) const;
+
+ /// Select sections for Data and Auto variables(globals).
+ virtual const MCSection *SelectSectionForGlobal(const GlobalValue *GV,
+ SectionKind Kind,
+ Mangler *Mang,
+ const TargetMachine&) const;
+
+
+ /// Return a code section for a function.
+ const PIC16Section *SectionForCode (const std::string &FnName,
+ bool isISR) const;
+
+ /// Return a frame section for a function.
+ const PIC16Section *SectionForFrame (const std::string &FnName) const;
+
+ /// Accessors for various section lists.
+ const std::vector<PIC16Section *> &UDATASections() const {
+ return UDATASections_;
+ }
+ const std::vector<PIC16Section *> &IDATASections() const {
+ return IDATASections_;
+ }
+ const PIC16Section *ROMDATASection() const {
+ return ROMDATASection_;
+ }
+ const PIC16Section *SHAREDUDATASection() const {
+ return SHAREDUDATASection_;
+ }
+ const std::vector<PIC16Section *> &AUTOSections() const {
+ return AUTOSections_;
+ }
+ const std::vector<PIC16Section *> &USERSections() const {
+ return USERSections_;
+ }
+ };
+} // end namespace llvm
+
+#endif
diff --git a/contrib/llvm/lib/Target/PIC16/TargetInfo/CMakeLists.txt b/contrib/llvm/lib/Target/PIC16/TargetInfo/CMakeLists.txt
new file mode 100644
index 0000000..bfc6ff4
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/TargetInfo/CMakeLists.txt
@@ -0,0 +1,7 @@
+include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
+
+add_llvm_library(LLVMPIC16Info
+ PIC16TargetInfo.cpp
+ )
+
+add_dependencies(LLVMPIC16Info PIC16Table_gen)
diff --git a/contrib/llvm/lib/Target/PIC16/TargetInfo/Makefile b/contrib/llvm/lib/Target/PIC16/TargetInfo/Makefile
new file mode 100644
index 0000000..76609f6
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/TargetInfo/Makefile
@@ -0,0 +1,15 @@
+##===- lib/Target/PIC16/TargetInfo/Makefile ----------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+LEVEL = ../../../..
+LIBRARYNAME = LLVMPIC16Info
+
+# Hack: we need to include 'main' target directory to grab private headers
+CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
+
+include $(LEVEL)/Makefile.common
diff --git a/contrib/llvm/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp b/contrib/llvm/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp
new file mode 100644
index 0000000..f1bdb12
--- /dev/null
+++ b/contrib/llvm/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp
@@ -0,0 +1,22 @@
+//===-- PIC16TargetInfo.cpp - PIC16 Target Implementation -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "PIC16.h"
+#include "llvm/Module.h"
+#include "llvm/Target/TargetRegistry.h"
+using namespace llvm;
+
+Target llvm::ThePIC16Target, llvm::TheCooperTarget;
+
+extern "C" void LLVMInitializePIC16TargetInfo() {
+ RegisterTarget<Triple::pic16> X(ThePIC16Target, "pic16",
+ "PIC16 14-bit [experimental]");
+
+ RegisterTarget<> Y(TheCooperTarget, "cooper", "PIC16 Cooper [experimental]");
+}
OpenPOWER on IntegriCloud