diff options
Diffstat (limited to 'lib/Target/PIC16')
30 files changed, 1828 insertions, 437 deletions
diff --git a/lib/Target/PIC16/AsmPrinter/CMakeLists.txt b/lib/Target/PIC16/AsmPrinter/CMakeLists.txt new file mode 100644 index 0000000..2e1b809 --- /dev/null +++ b/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/lib/Target/PIC16/AsmPrinter/Makefile b/lib/Target/PIC16/AsmPrinter/Makefile new file mode 100644 index 0000000..f4db57e --- /dev/null +++ b/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 +CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. + +include $(LEVEL)/Makefile.common diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp new file mode 100644 index 0000000..3f415af --- /dev/null +++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.cpp @@ -0,0 +1,484 @@ +//===-- 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 "PIC16AsmPrinter.h" +#include "MCSectionPIC16.h" +#include "PIC16MCAsmInfo.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Function.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/Target/TargetRegistry.h" +#include "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/Support/Mangler.h" +#include <cstring> +using namespace llvm; + +#include "PIC16GenAsmWriter.inc" + +PIC16AsmPrinter::PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, bool V) +: AsmPrinter(O, TM, T, V), DbgInfo(O, T) { + PTLI = static_cast<PIC16TargetLowering*>(TM.getTargetLowering()); + PMAI = static_cast<const PIC16MCAsmInfo*>(T); + PTOF = (PIC16TargetObjectFile*)&PTLI->getObjFileLowering(); +} + +bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) { + processDebugLoc(MI, true); + printInstruction(MI); + if (VerboseAsm && !MI->getDebugLoc().isUnknown()) + EmitComments(*MI); + O << '\n'; + processDebugLoc(MI, false); + return true; +} + +/// 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->MF = &MF; + + // This calls the base class function required to be called at beginning + // of runOnMachineFunction. + SetupMachineFunction(MF); + + // Get the mangled name. + const Function *F = MF.getFunction(); + CurrentFnName = Mang->getMangledName(F); + + // Emit the function frame (args and temps). + EmitFunctionFrame(MF); + + DbgInfo.BeginFunction(MF); + + // Emit the autos section of function. + EmitAutos(CurrentFnName); + + // Now emit the instructions of function in its code section. + const MCSection *fCodeSection = + getObjFileLowering().getSectionForFunction(CurrentFnName); + // Start the Code Section. + O << "\n"; + OutStreamer.SwitchSection(fCodeSection); + + // Emit the frame address of the function at the beginning of code. + O << "\tretlw low(" << PAN::getFrameLabel(CurrentFnName) << ")\n"; + O << "\tretlw high(" << PAN::getFrameLabel(CurrentFnName) << ")\n"; + + // Emit function start label. + O << CurrentFnName << ":\n"; + + DebugLoc CurDL; + O << "\n"; + // 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. + const DebugLoc DL = II->getDebugLoc(); + if (!DL.isUnknown() && DL != CurDL) { + DbgInfo.ChangeDebugLoc(MF, DL); + CurDL = DL; + } + + // Print the assembly for the instruction. + printMachineInstruction(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) { + const MachineOperand &MO = MI->getOperand(opNum); + + switch (MO.getType()) { + case MachineOperand::MO_Register: + O << getRegisterName(MO.getReg()); + return; + + case MachineOperand::MO_Immediate: + O << (int)MO.getImm(); + return; + + case MachineOperand::MO_GlobalAddress: { + std::string Sname = Mang->getMangledName(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(Sname)) { + LibcallDecls.push_back(createESName(Sname)); + } + + O << Sname; + break; + } + case MachineOperand::MO_ExternalSymbol: { + const char *Sname = MO.getSymbolName(); + + // If its a libcall name, record it to decls section. + if (PAN::getSymbolTag(Sname) == PAN::LIBCALL) { + LibcallDecls.push_back(Sname); + } + + // Record a call to intrinsic to print the extern declaration for it. + std::string Sym = Sname; + if (PAN::isMemIntrinsic(Sym)) { + Sym = PAN::addPrefix(Sym); + LibcallDecls.push_back(createESName(Sym)); + } + + O << Sym; + break; + } + case MachineOperand::MO_MachineBasicBlock: + GetMBBSymbol(MO.getMBB()->getNumber())->print(O, MAI); + return; + + default: + llvm_unreachable(" Operand type not supported."); + } +} + +/// printCCOperand - Print the cond code operand. +/// +void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) { + int CC = (int)MI->getOperand(opNum).getImm(); + O << PIC16CondCodeToString((PIC16CC::CondCodes)CC); +} + +// This function is used to sort the decls list. +// should return true if s1 should come before s2. +static bool is_before(const char *s1, const char *s2) { + return strcmp(s1, s2) <= 0; +} + +// This is used by list::unique below. +// unique will filter out duplicates if it knows them. +static bool is_duplicate(const char *s1, const char *s2) { + return !strcmp(s1, s2); +} + +/// printLibcallDecls - print the extern declarations for compiler +/// intrinsics. +/// +void PIC16AsmPrinter::printLibcallDecls() { + // If no libcalls used, return. + if (LibcallDecls.empty()) return; + + O << MAI->getCommentString() << "External decls for libcalls - BEGIN." <<"\n"; + // Remove duplicate entries. + LibcallDecls.sort(is_before); + LibcallDecls.unique(is_duplicate); + + for (std::list<const char*>::const_iterator I = LibcallDecls.begin(); + I != LibcallDecls.end(); I++) { + O << MAI->getExternDirective() << *I << "\n"; + O << MAI->getExternDirective() << PAN::getArgsLabel(*I) << "\n"; + O << MAI->getExternDirective() << PAN::getRetvalLabel(*I) << "\n"; + } + O << MAI->getCommentString() << "External decls for libcalls - END." <<"\n"; +} + +/// 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); + + // FIXME:: This is temporary solution to generate the include file. + // The processor should be passed to llc as in input and the header file + // should be generated accordingly. + O << "\n\t#include P16F1937.INC\n"; + + // Set the section names for all globals. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) + if (!I->isDeclaration() && !I->hasAvailableExternallyLinkage()) { + const MCSection *S = getObjFileLowering().SectionForGlobal(I, Mang, TM); + + I->setSection(((const MCSectionPIC16*)S)->getName()); + } + + DbgInfo.BeginModule(M); + EmitFunctionDecls(M); + EmitUndefinedVars(M); + EmitDefinedVars(M); + EmitIData(M); + EmitUData(M); + EmitRomData(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. + O <<"\n"<<MAI->getCommentString() << "Function Declarations - BEGIN." <<"\n"; + for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) { + if (I->isIntrinsic()) + continue; + + std::string Name = Mang->getMangledName(I); + if (Name.compare("@abort") == 0) + continue; + + if (!I->isDeclaration() && !I->hasExternalLinkage()) + continue; + + // 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(Name)) continue; + + const char *directive = I->isDeclaration() ? MAI->getExternDirective() : + MAI->getGlobalDirective(); + + O << directive << Name << "\n"; + O << directive << PAN::getRetvalLabel(Name) << "\n"; + O << directive << PAN::getArgsLabel(Name) << "\n"; + } + + O << MAI->getCommentString() << "Function Declarations - END." <<"\n"; +} + +// Emit variables imported from other Modules. +void PIC16AsmPrinter::EmitUndefinedVars(Module &M) { + std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDecls->Items; + if (!Items.size()) return; + + O << "\n" << MAI->getCommentString() << "Imported Variables - BEGIN" << "\n"; + for (unsigned j = 0; j < Items.size(); j++) { + O << MAI->getExternDirective() << Mang->getMangledName(Items[j]) << "\n"; + } + O << MAI->getCommentString() << "Imported Variables - END" << "\n"; +} + +// Emit variables defined in this module and are available to other modules. +void PIC16AsmPrinter::EmitDefinedVars(Module &M) { + std::vector<const GlobalVariable*> Items = PTOF->ExternalVarDefs->Items; + if (!Items.size()) return; + + O << "\n" << MAI->getCommentString() << "Exported Variables - BEGIN" << "\n"; + for (unsigned j = 0; j < Items.size(); j++) { + O << MAI->getGlobalDirective() << Mang->getMangledName(Items[j]) << "\n"; + } + O << MAI->getCommentString() << "Exported Variables - END" << "\n"; +} + +// Emit initialized data placed in ROM. +void PIC16AsmPrinter::EmitRomData(Module &M) { + // Print ROM Data section. + const std::vector<PIC16Section*> &ROSections = PTOF->ROSections; + for (unsigned i = 0; i < ROSections.size(); i++) { + const std::vector<const GlobalVariable*> &Items = ROSections[i]->Items; + if (!Items.size()) continue; + O << "\n"; + OutStreamer.SwitchSection(PTOF->ROSections[i]->S_); + for (unsigned j = 0; j < Items.size(); j++) { + O << Mang->getMangledName(Items[j]); + Constant *C = Items[j]->getInitializer(); + int AddrSpace = Items[j]->getType()->getAddressSpace(); + EmitGlobalConstant(C, AddrSpace); + } + } +} + +bool PIC16AsmPrinter::doFinalization(Module &M) { + printLibcallDecls(); + EmitRemainingAutos(); + DbgInfo.EndModule(M); + O << "\n\t" << "END\n"; + return AsmPrinter::doFinalization(M); +} + +void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) { + const Function *F = MF.getFunction(); + std::string FuncName = Mang->getMangledName(F); + const TargetData *TD = TM.getTargetData(); + // Emit the data section name. + O << "\n"; + + const MCSection *fPDataSection = + getObjFileLowering().getSectionForFunctionFrame(CurrentFnName); + OutStreamer.SwitchSection(fPDataSection); + + // Emit function frame label + O << PAN::getFrameLabel(CurrentFnName) << ":\n"; + + 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) + O << PAN::getRetvalLabel(CurrentFnName) << " RES " << RetSize << "\n"; + else + O << PAN::getRetvalLabel(CurrentFnName) << ": \n"; + + // 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); + } + + O << PAN::getArgsLabel(CurrentFnName) << " RES " << ArgSize << "\n"; + + // Emit temporary space + int TempSize = PTLI->GetTmpSize(); + if (TempSize > 0) + O << PAN::getTempdataLabel(CurrentFnName) << " RES " << TempSize << '\n'; +} + +void PIC16AsmPrinter::EmitIData(Module &M) { + + // Print all IDATA sections. + const std::vector<PIC16Section*> &IDATASections = PTOF->IDATASections; + for (unsigned i = 0; i < IDATASections.size(); i++) { + O << "\n"; + if (IDATASections[i]->S_->getName().find("llvm.") != std::string::npos) + continue; + OutStreamer.SwitchSection(IDATASections[i]->S_); + std::vector<const GlobalVariable*> Items = IDATASections[i]->Items; + for (unsigned j = 0; j < Items.size(); j++) { + std::string Name = Mang->getMangledName(Items[j]); + Constant *C = Items[j]->getInitializer(); + int AddrSpace = Items[j]->getType()->getAddressSpace(); + O << Name; + EmitGlobalConstant(C, AddrSpace); + } + } +} + +void PIC16AsmPrinter::EmitUData(Module &M) { + const TargetData *TD = TM.getTargetData(); + + // Print all BSS sections. + const std::vector<PIC16Section*> &BSSSections = PTOF->BSSSections; + for (unsigned i = 0; i < BSSSections.size(); i++) { + O << "\n"; + OutStreamer.SwitchSection(BSSSections[i]->S_); + std::vector<const GlobalVariable*> Items = BSSSections[i]->Items; + for (unsigned j = 0; j < Items.size(); j++) { + std::string Name = Mang->getMangledName(Items[j]); + Constant *C = Items[j]->getInitializer(); + const Type *Ty = C->getType(); + unsigned Size = TD->getTypeAllocSize(Ty); + + O << Name << " RES " << Size << "\n"; + } + } +} + +void PIC16AsmPrinter::EmitAutos(std::string FunctName) { + // Section names for all globals are already set. + const TargetData *TD = TM.getTargetData(); + + // Now print Autos section for this function. + std::string SectionName = PAN::getAutosSectionName(FunctName); + const std::vector<PIC16Section*> &AutosSections = PTOF->AutosSections; + for (unsigned i = 0; i < AutosSections.size(); i++) { + O << "\n"; + if (AutosSections[i]->S_->getName() == SectionName) { + // Set the printing status to true + AutosSections[i]->setPrintedStatus(true); + OutStreamer.SwitchSection(AutosSections[i]->S_); + const std::vector<const GlobalVariable*> &Items = AutosSections[i]->Items; + for (unsigned j = 0; j < Items.size(); j++) { + std::string VarName = Mang->getMangledName(Items[j]); + Constant *C = Items[j]->getInitializer(); + const Type *Ty = C->getType(); + unsigned Size = TD->getTypeAllocSize(Ty); + // Emit memory reserve directive. + O << VarName << " RES " << Size << "\n"; + } + break; + } + } +} + +// Print autos that were not printed during the code printing of functions. +// As the functions might themselves would have got deleted by the optimizer. +void PIC16AsmPrinter::EmitRemainingAutos() { + const TargetData *TD = TM.getTargetData(); + + // Now print Autos section for this function. + std::vector <PIC16Section *>AutosSections = PTOF->AutosSections; + for (unsigned i = 0; i < AutosSections.size(); i++) { + + // if the section is already printed then don't print again + if (AutosSections[i]->isPrinted()) + continue; + + // Set status as printed + AutosSections[i]->setPrintedStatus(true); + + O << "\n"; + OutStreamer.SwitchSection(AutosSections[i]->S_); + const std::vector<const GlobalVariable*> &Items = AutosSections[i]->Items; + for (unsigned j = 0; j < Items.size(); j++) { + std::string VarName = Mang->getMangledName(Items[j]); + Constant *C = Items[j]->getInitializer(); + const Type *Ty = C->getType(); + unsigned Size = TD->getTypeAllocSize(Ty); + // Emit memory reserve directive. + O << VarName << " RES " << Size << "\n"; + } + } +} + + +extern "C" void LLVMInitializePIC16AsmPrinter() { + RegisterAsmPrinter<PIC16AsmPrinter> X(ThePIC16Target); +} + + diff --git a/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h new file mode 100644 index 0000000..2dd4600 --- /dev/null +++ b/lib/Target/PIC16/AsmPrinter/PIC16AsmPrinter.h @@ -0,0 +1,80 @@ +//===-- 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 <string> + +namespace llvm { + class VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter { + public: + explicit PIC16AsmPrinter(formatted_raw_ostream &O, TargetMachine &TM, + const MCAsmInfo *T, bool V); + private: + virtual const char *getPassName() const { + return "PIC16 Assembly Printer"; + } + + PIC16TargetObjectFile &getObjFileLowering() const { + return (PIC16TargetObjectFile &)AsmPrinter::getObjFileLowering(); + } + + bool runOnMachineFunction(MachineFunction &F); + void printOperand(const MachineInstr *MI, int opNum); + void printCCOperand(const MachineInstr *MI, int opNum); + void printInstruction(const MachineInstr *MI); // definition autogenerated. + static const char *getRegisterName(unsigned RegNo); + + bool printMachineInstruction(const MachineInstr *MI); + void EmitFunctionDecls (Module &M); + void EmitUndefinedVars (Module &M); + void EmitDefinedVars (Module &M); + void EmitIData (Module &M); + void EmitUData (Module &M); + void EmitAutos (std::string FunctName); + void EmitRemainingAutos (); + void EmitRomData (Module &M); + void EmitFunctionFrame(MachineFunction &MF); + void printLibcallDecls(); + protected: + bool doInitialization(Module &M); + bool doFinalization(Module &M); + + /// PrintGlobalVariable - Emit the specified global variable and its + /// initializer to the output stream. + virtual void PrintGlobalVariable(const GlobalVariable *GV) { + // PIC16 doesn't use normal hooks for this. + } + + private: + PIC16TargetObjectFile *PTOF; + PIC16TargetLowering *PTLI; + PIC16DbgInfo DbgInfo; + const PIC16MCAsmInfo *PMAI; + std::list<const char *> LibcallDecls; // List of extern decls. + }; +} // end of namespace + +#endif diff --git a/lib/Target/PIC16/CMakeLists.txt b/lib/Target/PIC16/CMakeLists.txt index 00d737a..0ee88f9 100644 --- a/lib/Target/PIC16/CMakeLists.txt +++ b/lib/Target/PIC16/CMakeLists.txt @@ -11,14 +11,14 @@ tablegen(PIC16GenCallingConv.inc -gen-callingconv) tablegen(PIC16GenSubtarget.inc -gen-subtarget) add_llvm_target(PIC16 - PIC16AsmPrinter.cpp PIC16DebugInfo.cpp PIC16InstrInfo.cpp PIC16ISelDAGToDAG.cpp PIC16ISelLowering.cpp PIC16MemSelOpt.cpp + PIC16MCAsmInfo.cpp PIC16RegisterInfo.cpp PIC16Subtarget.cpp - PIC16TargetAsmInfo.cpp PIC16TargetMachine.cpp + PIC16TargetObjectFile.cpp ) diff --git a/lib/Target/PIC16/MCSectionPIC16.h b/lib/Target/PIC16/MCSectionPIC16.h new file mode 100644 index 0000000..352be99 --- /dev/null +++ b/lib/Target/PIC16/MCSectionPIC16.h @@ -0,0 +1,88 @@ +//===- MCSectionPIC16.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 MCSectionPIC16 class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PIC16SECTION_H +#define LLVM_PIC16SECTION_H + +#include "llvm/MC/MCSection.h" + +namespace llvm { + + /// MCSectionPIC16 - Represents a physical section in PIC16 COFF. + /// Contains data objects. + /// + class MCSectionPIC16 : public MCSection { + /// Name of the section to uniquely identify it. + std::string Name; + + /// User can specify an address at which a section should be placed. + /// Negative value here means user hasn't specified any. + int Address; + + /// Overlay information - Sections with same color can be overlaid on + /// one another. + int Color; + + /// Conatined data objects. + std::vector<const GlobalVariable *>Items; + + /// Total size of all data objects contained here. + unsigned Size; + + MCSectionPIC16(const StringRef &name, SectionKind K, int addr, int color) + : MCSection(K), Name(name), Address(addr), Color(color) { + } + + public: + /// Return the name of the section. + const std::string &getName() const { return Name; } + + /// Return the Address of the section. + int getAddress() const { return Address; } + + /// Return the Color of the section. + int getColor() const { return Color; } + + /// 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) + /// So, let's have some convenience functions to Map PIC16 Section types + /// to SectionKind just for the sake of better readability. + static SectionKind UDATA_Kind() { return SectionKind::getBSS(); } + static SectionKind IDATA_Kind() { return SectionKind::getMetadata(); } + static SectionKind ROMDATA_Kind() { return SectionKind::getReadOnly(); } + static SectionKind UDATA_OVR_Kind() { return SectionKind::getThreadBSS(); } + + // If we could just do getKind() == UDATA_Kind() ? + bool isUDATA_Kind() { return getKind().isBSS(); } + bool isIDATA_Kind() { return getKind().isMetadata(); } + bool isROMDATA_Kind() { return getKind().isMetadata(); } + bool isUDATA_OVR_Kind() { return getKind().isThreadBSS(); } + + /// This would be the only way to create a section. + static MCSectionPIC16 *Create(const StringRef &Name, SectionKind K, + int 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; + }; + +} // end namespace llvm + +#endif diff --git a/lib/Target/PIC16/Makefile b/lib/Target/PIC16/Makefile index c429324..f913675 100644 --- a/lib/Target/PIC16/Makefile +++ b/lib/Target/PIC16/Makefile @@ -7,7 +7,7 @@ # ##===----------------------------------------------------------------------===## LEVEL = ../../.. -LIBRARYNAME = LLVMPIC16 +LIBRARYNAME = LLVMPIC16CodeGen TARGET = PIC16 # Make sure that tblgen is run, first thing. @@ -17,5 +17,7 @@ BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \ PIC16GenDAGISel.inc PIC16GenCallingConv.inc \ PIC16GenSubtarget.inc +DIRS = AsmPrinter TargetInfo + include $(LEVEL)/Makefile.common diff --git a/lib/Target/PIC16/PIC16.h b/lib/Target/PIC16/PIC16.h index 7940648..8a3704d 100644 --- a/lib/Target/PIC16/PIC16.h +++ b/lib/Target/PIC16/PIC16.h @@ -15,8 +15,8 @@ #ifndef LLVM_TARGET_PIC16_H #define LLVM_TARGET_PIC16_H +#include "llvm/Support/ErrorHandling.h" #include "llvm/Target/TargetMachine.h" -#include <iosfwd> #include <cassert> #include <sstream> #include <cstring> @@ -26,7 +26,7 @@ namespace llvm { class PIC16TargetMachine; class FunctionPass; class MachineCodeEmitter; - class raw_ostream; + class formatted_raw_ostream; namespace PIC16CC { enum CondCodes { @@ -83,7 +83,7 @@ namespace PIC16CC { // initialized globals - @idata.<num>.# // Function frame - @<func>.frame_section. // Function autos - @<func>.autos_section. - // Declarations - @section.0 + // Declarations - Enclosed in comments. No section for them. //---------------------------------------------------------- // Tags used to mangle different names. @@ -221,17 +221,29 @@ namespace PIC16CC { return Func1 + tag + "# CODE"; } - // udata and idata section names are generated by a given number. + // udata, romdata and idata section names are generated by a given number. // @udata.<num>.# - static std::string getUdataSectionName(unsigned num) { + static std::string getUdataSectionName(unsigned num, + std::string prefix = "") { std::ostringstream o; - o << getTagName(PREFIX_SYMBOL) << "udata." << num << ".# UDATA"; + o << getTagName(PREFIX_SYMBOL) << prefix << "udata." << num + << ".# UDATA"; return o.str(); } - static std::string getIdataSectionName(unsigned num) { + static std::string getRomdataSectionName(unsigned num, + std::string prefix = "") { std::ostringstream o; - o << getTagName(PREFIX_SYMBOL) << "idata." << num << ".# IDATA"; + o << getTagName(PREFIX_SYMBOL) << prefix << "romdata." << num + << ".# ROMDATA"; + return o.str(); + } + + static std::string getIdataSectionName(unsigned num, + std::string prefix = "") { + std::ostringstream o; + o << getTagName(PREFIX_SYMBOL) << prefix << "idata." << num + << ".# IDATA"; return o.str(); } @@ -242,6 +254,15 @@ namespace PIC16CC { 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; + } + inline static bool isLocalToFunc (std::string &Func, std::string &Var) { if (! isLocalName(Var)) return false; @@ -295,7 +316,7 @@ namespace PIC16CC { inline static const char *PIC16CondCodeToString(PIC16CC::CondCodes CC) { switch (CC) { - default: assert(0 && "Unknown condition code"); + default: llvm_unreachable("Unknown condition code"); case PIC16CC::NE: return "ne"; case PIC16CC::EQ: return "eq"; case PIC16CC::LT: return "lt"; @@ -311,7 +332,7 @@ namespace PIC16CC { inline static bool isSignedComparison(PIC16CC::CondCodes CC) { switch (CC) { - default: assert(0 && "Unknown condition code"); + default: llvm_unreachable("Unknown condition code"); case PIC16CC::NE: case PIC16CC::EQ: case PIC16CC::LT: @@ -330,11 +351,12 @@ namespace PIC16CC { FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM); - FunctionPass *createPIC16CodePrinterPass(raw_ostream &OS, - PIC16TargetMachine &TM, - bool Verbose); - // Banksel optimzer pass. + // 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 diff --git a/lib/Target/PIC16/PIC16DebugInfo.cpp b/lib/Target/PIC16/PIC16DebugInfo.cpp index 4300588..961caed 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.cpp +++ b/lib/Target/PIC16/PIC16DebugInfo.cpp @@ -1,3 +1,4 @@ + //===-- PIC16DebugInfo.cpp - Implementation for PIC16 Debug Information ======// // // The LLVM Compiler Infrastructure @@ -15,8 +16,10 @@ #include "PIC16DebugInfo.h" #include "llvm/GlobalVariable.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/MC/MCAsmInfo.h" #include "llvm/Support/DebugLoc.h" -#include "llvm/Support/raw_ostream.h" +#include "llvm/Support/FormattedStream.h" +#include "llvm/ADT/SmallString.h" using namespace llvm; @@ -25,11 +28,11 @@ using namespace llvm; void PIC16DbgInfo::PopulateDebugInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux, int Aux[], std::string &TagName) { - if (Ty.isBasicType(Ty.getTag())) + if (Ty.isBasicType()) PopulateBasicTypeInfo (Ty, TypeNo); - else if (Ty.isDerivedType(Ty.getTag())) + else if (Ty.isDerivedType()) PopulateDerivedTypeInfo (Ty, TypeNo, HasAux, Aux, TagName); - else if (Ty.isCompositeType(Ty.getTag())) + else if (Ty.isCompositeType()) PopulateCompositeTypeInfo (Ty, TypeNo, HasAux, Aux, TagName); else { TypeNo = PIC16Dbg::T_NULL; @@ -41,8 +44,7 @@ void PIC16DbgInfo::PopulateDebugInfo (DIType Ty, unsigned short &TypeNo, /// PopulateBasicTypeInfo- Populate TypeNo for basic type from Ty. /// void PIC16DbgInfo::PopulateBasicTypeInfo (DIType Ty, unsigned short &TypeNo) { - std::string Name = ""; - Ty.getName(Name); + std::string Name = Ty.getName(); unsigned short BaseTy = GetTypeDebugNumber(Name); TypeNo = TypeNo << PIC16Dbg::S_BASIC; TypeNo = TypeNo | (0xffff & BaseTy); @@ -67,7 +69,7 @@ void PIC16DbgInfo::PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo, // We also need to encode the the information about the base type of // pointer in TypeNo. - DIType BaseType = DIDerivedType(Ty.getGV()).getTypeDerivedFrom(); + DIType BaseType = DIDerivedType(Ty.getNode()).getTypeDerivedFrom(); PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName); } @@ -76,7 +78,7 @@ void PIC16DbgInfo::PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux, int Aux[], std::string &TagName) { - DICompositeType CTy = DICompositeType(Ty.getGV()); + DICompositeType CTy = DICompositeType(Ty.getNode()); DIArray Elements = CTy.getTypeArray(); unsigned short size = 1; unsigned short Dimension[4]={0,0,0,0}; @@ -85,7 +87,7 @@ void PIC16DbgInfo::PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo, if (Element.getTag() == dwarf::DW_TAG_subrange_type) { TypeNo = TypeNo << PIC16Dbg::S_DERIVED; TypeNo = TypeNo | PIC16Dbg::DT_ARY; - DISubrange SubRange = DISubrange(Element.getGV()); + DISubrange SubRange = DISubrange(Element.getNode()); 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]; @@ -108,16 +110,20 @@ void PIC16DbgInfo::PopulateStructOrUnionTypeInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux, int Aux[], std::string &TagName) { - DICompositeType CTy = DICompositeType(Ty.getGV()); + DICompositeType CTy = DICompositeType(Ty.getNode()); TypeNo = TypeNo << PIC16Dbg::S_BASIC; if (Ty.getTag() == dwarf::DW_TAG_structure_type) TypeNo = TypeNo | PIC16Dbg::T_STRUCT; else TypeNo = TypeNo | PIC16Dbg::T_UNION; - CTy.getName(TagName); + TagName = CTy.getName(); // UniqueSuffix is .number where number is obtained from // llvm.dbg.composite<number>. - std::string UniqueSuffix = "." + Ty.getGV()->getName().substr(18); + // 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.getNode()->getNameStr().substr(18); TagName += UniqueSuffix; unsigned short size = CTy.getSizeInBits()/8; // 7th and 8th byte represent size. @@ -200,12 +206,14 @@ short PIC16DbgInfo::getStorageClass(DIGlobalVariable DIGV) { /// required initializations. void PIC16DbgInfo::BeginModule(Module &M) { // Emit file directive for module. - GlobalVariable *CU = M.getNamedGlobal("llvm.dbg.compile_unit"); - if (CU) { + 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); } @@ -233,10 +241,11 @@ void PIC16DbgInfo::BeginFunction(const MachineFunction &MF) { // Retreive the first valid debug Loc and process it. const DebugLoc &DL = GetDebugLocForFunction(MF); - ChangeDebugLoc(MF, DL, true); - - EmitFunctBeginDI(MF.getFunction()); - + // 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; } @@ -249,7 +258,7 @@ void PIC16DbgInfo::ChangeDebugLoc(const MachineFunction &MF, if (! EmitDebugDirectives) return; assert (! DL.isUnknown() && "can't change to invalid debug loc"); - GlobalVariable *CU = MF.getDebugLocTuple(DL).CompileUnit; + MDNode *CU = MF.getDebugLocTuple(DL).Scope; unsigned line = MF.getDebugLocTuple(DL).Line; SwitchToCU(CU); @@ -268,7 +277,10 @@ void PIC16DbgInfo::SwitchToLine(unsigned Line, bool IsInBeginFunction) { /// void PIC16DbgInfo::EndFunction(const MachineFunction &MF) { if (! EmitDebugDirectives) return; - EmitFunctEndDI(MF.getFunction(), CurLine); + 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. @@ -283,7 +295,7 @@ void PIC16DbgInfo::EndModule(Module &M) { /// composite type. /// void PIC16DbgInfo::EmitCompositeTypeElements (DICompositeType CTy, - std::string UniqueSuffix) { + std::string SuffixNo) { unsigned long Value = 0; DIArray Elements = CTy.getTypeArray(); for (unsigned i = 0, N = Elements.getNumElements(); i < N; i++) { @@ -292,24 +304,22 @@ void PIC16DbgInfo::EmitCompositeTypeElements (DICompositeType CTy, bool HasAux = false; int ElementAux[PIC16Dbg::AuxSize] = { 0 }; std::string TagName = ""; - std::string ElementName; - GlobalVariable *GV = Element.getGV(); - DIDerivedType DITy(GV); - DITy.getName(ElementName); + DIDerivedType DITy(Element.getNode()); + const char *ElementName = DITy.getName(); unsigned short ElementSize = DITy.getSizeInBits()/8; // Get mangleddd name for this structure/union element. - std::string MangMemName = ElementName + UniqueSuffix; + std::string MangMemName = ElementName + 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, Class, TypeNo, Value); + EmitSymbol(MangMemName.c_str(), Class, TypeNo, Value); if (CTy.getTag() == dwarf::DW_TAG_structure_type) Value += ElementSize; if (HasAux) - EmitAuxEntry(MangMemName, ElementAux, PIC16Dbg::AuxSize, TagName); + EmitAuxEntry(MangMemName.c_str(), ElementAux, PIC16Dbg::AuxSize, TagName); } } @@ -317,48 +327,48 @@ void PIC16DbgInfo::EmitCompositeTypeElements (DICompositeType CTy, /// and union declarations. /// void PIC16DbgInfo::EmitCompositeTypeDecls(Module &M) { - for(iplist<GlobalVariable>::iterator I = M.getGlobalList().begin(), - E = M.getGlobalList().end(); I != E; I++) { - // Structures and union declaration's debug info has llvm.dbg.composite - // in its name. - if(I->getName().find("llvm.dbg.composite") != std::string::npos) { - GlobalVariable *GV = cast<GlobalVariable >(I); - DICompositeType CTy(GV); - if (CTy.getTag() == dwarf::DW_TAG_union_type || - CTy.getTag() == dwarf::DW_TAG_structure_type ) { - std::string name; - CTy.getName(name); - std::string DIVar = I->getName(); - // Get the number after llvm.dbg.composite and make UniqueSuffix from - // it. - std::string UniqueSuffix = "." + DIVar.substr(18); - std::string MangledCTyName = name + 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, PIC16Dbg::C_UNTAG); - else if (CTy.getTag() == dwarf::DW_TAG_structure_type) - EmitSymbol(MangledCTyName, PIC16Dbg::C_STRTAG); - - // Emit auxiliary debug information for structure/union tag. - EmitAuxEntry(MangledCTyName, Aux, PIC16Dbg::AuxSize); - - // Emit members. - EmitCompositeTypeElements (CTy, UniqueSuffix); - - // Emit mangled Symbol for end of structure/union. - std::string EOSSymbol = ".eos" + UniqueSuffix; - EmitSymbol(EOSSymbol, PIC16Dbg::C_EOS); - EmitAuxEntry(EOSSymbol, Aux, PIC16Dbg::AuxSize, MangledCTyName); - } + DebugInfoFinder DbgFinder; + DbgFinder.processModule(M); + for (DebugInfoFinder::iterator I = DbgFinder.type_begin(), + E = DbgFinder.type_end(); I != E; ++I) { + DICompositeType CTy(*I); + if (CTy.isNull()) + continue; + if (CTy.getTag() == dwarf::DW_TAG_union_type || + CTy.getTag() == dwarf::DW_TAG_structure_type ) { + const char *Name = CTy.getName(); + // Get the number after llvm.dbg.composite and make UniqueSuffix from + // it. + std::string DIVar = CTy.getNode()->getNameStr(); + std::string UniqueSuffix = "." + DIVar.substr(18); + std::string MangledCTyName = Name + 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) { @@ -425,31 +435,26 @@ void PIC16DbgInfo::EmitSymbol(std::string Name, short Class, unsigned short /// EmitVarDebugInfo - Emit debug information for all variables. /// void PIC16DbgInfo::EmitVarDebugInfo(Module &M) { - GlobalVariable *Root = M.getGlobalVariable("llvm.dbg.global_variables"); - if (!Root) - return; - - Constant *RootC = cast<Constant>(*Root->use_begin()); - for (Value::use_iterator UI = RootC->use_begin(), UE = Root->use_end(); - UI != UE; ++UI) { - for (Value::use_iterator UUI = UI->use_begin(), UUE = UI->use_end(); - UUI != UUE; ++UUI) { - DIGlobalVariable DIGV(cast<GlobalVariable>(*UUI)); - DIType Ty = DIGV.getType(); - unsigned short TypeNo = 0; - bool HasAux = false; - int Aux[PIC16Dbg::AuxSize] = { 0 }; - std::string TagName = ""; - std::string VarName = TAI->getGlobalPrefix()+DIGV.getGlobal()->getName(); - PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TagName); - // Emit debug info only if type information is availaible. - if (TypeNo != PIC16Dbg::T_NULL) { - O << "\n\t.type " << VarName << ", " << TypeNo; - short ClassNo = getStorageClass(DIGV); - O << "\n\t.class " << VarName << ", " << ClassNo; - if (HasAux) - EmitAuxEntry(VarName, Aux, PIC16Dbg::AuxSize, TagName); - } + 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 = MAI->getGlobalPrefix()+DIGV.getGlobal()->getNameStr(); + PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TagName); + // Emit debug info only if type information is availaible. + if (TypeNo != PIC16Dbg::T_NULL) { + O << "\n\t.type " << VarName << ", " << TypeNo; + short ClassNo = getStorageClass(DIGV); + O << "\n\t.class " << VarName << ", " << ClassNo; + if (HasAux) + EmitAuxEntry(VarName, Aux, PIC16Dbg::AuxSize, TagName); } } O << "\n"; @@ -457,12 +462,12 @@ void PIC16DbgInfo::EmitVarDebugInfo(Module &M) { /// SwitchToCU - Switch to a new compilation unit. /// -void PIC16DbgInfo::SwitchToCU(GlobalVariable *CU) { +void PIC16DbgInfo::SwitchToCU(MDNode *CU) { // Get the file path from CU. DICompileUnit cu(CU); - std::string DirName, FileName; - std::string FilePath = cu.getDirectory(DirName) + "/" + - cu.getFilename(FileName); + 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; diff --git a/lib/Target/PIC16/PIC16DebugInfo.h b/lib/Target/PIC16/PIC16DebugInfo.h index d126d85..54e27c7 100644 --- a/lib/Target/PIC16/PIC16DebugInfo.h +++ b/lib/Target/PIC16/PIC16DebugInfo.h @@ -16,8 +16,6 @@ #include "llvm/Analysis/DebugInfo.h" #include "llvm/Module.h" -#include "llvm/Target/TargetAsmInfo.h" -#include <map> namespace llvm { class MachineFunction; @@ -90,11 +88,11 @@ namespace llvm { }; } - class raw_ostream; + class formatted_raw_ostream; class PIC16DbgInfo { - raw_ostream &O; - const TargetAsmInfo *TAI; + formatted_raw_ostream &O; + const MCAsmInfo *MAI; std::string CurFile; unsigned CurLine; @@ -103,7 +101,8 @@ namespace llvm { bool EmitDebugDirectives; public: - PIC16DbgInfo(raw_ostream &o, const TargetAsmInfo *T) : O(o), TAI(T) { + PIC16DbgInfo(formatted_raw_ostream &o, const MCAsmInfo *T) + : O(o), MAI(T) { CurFile = ""; CurLine = 0; EmitDebugDirectives = false; @@ -118,7 +117,7 @@ namespace llvm { private: - void SwitchToCU (GlobalVariable *CU); + void SwitchToCU (MDNode *CU); void SwitchToLine (unsigned Line, bool IsInBeginFunction = false); void PopulateDebugInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux, @@ -144,8 +143,7 @@ namespace llvm { short getStorageClass(DIGlobalVariable DIGV); void EmitFunctBeginDI(const Function *F); void EmitCompositeTypeDecls(Module &M); - void EmitCompositeTypeElements (DICompositeType CTy, - std::string UniqueSuffix); + 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 = ""); diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp index 6c2b8ec..cc57d12 100644 --- a/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp +++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.cpp @@ -13,6 +13,8 @@ #define DEBUG_TYPE "pic16-isel" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/raw_ostream.h" #include "PIC16ISelDAGToDAG.h" #include "llvm/Support/Debug.h" diff --git a/lib/Target/PIC16/PIC16ISelDAGToDAG.h b/lib/Target/PIC16/PIC16ISelDAGToDAG.h index 83abed3..3a2f6b4 100644 --- a/lib/Target/PIC16/PIC16ISelDAGToDAG.h +++ b/lib/Target/PIC16/PIC16ISelDAGToDAG.h @@ -31,7 +31,7 @@ class VISIBILITY_HIDDEN PIC16DAGToDAGISel : public SelectionDAGISel { /// PIC16Lowering - This object fully describes how to lower LLVM code to an /// PIC16-specific SelectionDAG. - PIC16TargetLowering PIC16Lowering; + PIC16TargetLowering &PIC16Lowering; public: explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) : diff --git a/lib/Target/PIC16/PIC16ISelLowering.cpp b/lib/Target/PIC16/PIC16ISelLowering.cpp index 0d24f61..bf986b1 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.cpp +++ b/lib/Target/PIC16/PIC16ISelLowering.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #define DEBUG_TYPE "pic16-lower" - #include "PIC16ISelLowering.h" +#include "PIC16TargetObjectFile.h" #include "PIC16TargetMachine.h" #include "llvm/DerivedTypes.h" #include "llvm/GlobalValue.h" @@ -23,6 +23,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -30,7 +31,7 @@ using namespace llvm; static const char *getIntrinsicName(unsigned opcode) { std::string Basename; switch(opcode) { - default: assert (0 && "do not know intrinsic name"); + 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; @@ -114,22 +115,48 @@ static const char *getIntrinsicName(unsigned opcode) { std::string Fullname = prefix + tagname + Basename; // The name has to live through program life. - char *tmp = new char[Fullname.size() + 1]; - strcpy (tmp, Fullname.c_str()); - - return tmp; + return 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 createESName(LibCallName); } // PIC16TargetLowering Constructor. PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) - : TargetLowering(TM), TmpSize(0) { + : TargetLowering(TM, new PIC16TargetObjectFile()), TmpSize(0) { Subtarget = &TM.getSubtarget<PIC16Subtarget>(); addRegisterClass(MVT::i8, PIC16::GPRRegisterClass); setShiftAmountType(MVT::i8); - setShiftAmountFlavor(Extend); + + // 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)); @@ -226,6 +253,7 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) 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); @@ -240,46 +268,27 @@ PIC16TargetLowering::PIC16TargetLowering(PIC16TargetMachine &TM) setOperationAction(ISD::XOR, MVT::i8, Custom); setOperationAction(ISD::FrameIndex, MVT::i16, Custom); - setOperationAction(ISD::CALL, MVT::i16, Custom); - setOperationAction(ISD::RET, MVT::Other, Custom); - setOperationAction(ISD::MUL, MVT::i8, Custom); - setOperationAction(ISD::MUL, MVT::i16, Expand); - setOperationAction(ISD::MUL, MVT::i32, Expand); + setOperationAction(ISD::MUL, MVT::i8, Custom); setOperationAction(ISD::SMUL_LOHI, MVT::i8, Expand); - setOperationAction(ISD::SMUL_LOHI, MVT::i16, Expand); - setOperationAction(ISD::SMUL_LOHI, MVT::i32, Expand); setOperationAction(ISD::UMUL_LOHI, MVT::i8, Expand); - setOperationAction(ISD::UMUL_LOHI, MVT::i16, Expand); - setOperationAction(ISD::UMUL_LOHI, MVT::i32, Expand); setOperationAction(ISD::MULHU, MVT::i8, Expand); - setOperationAction(ISD::MULHU, MVT::i16, Expand); - setOperationAction(ISD::MULHU, MVT::i32, Expand); setOperationAction(ISD::MULHS, MVT::i8, Expand); - setOperationAction(ISD::MULHS, MVT::i16, Expand); - setOperationAction(ISD::MULHS, MVT::i32, Expand); setOperationAction(ISD::SRA, MVT::i8, Custom); - setOperationAction(ISD::SRA, MVT::i16, Expand); - setOperationAction(ISD::SRA, MVT::i32, Expand); setOperationAction(ISD::SHL, MVT::i8, Custom); - setOperationAction(ISD::SHL, MVT::i16, Expand); - setOperationAction(ISD::SHL, MVT::i32, Expand); setOperationAction(ISD::SRL, MVT::i8, Custom); - setOperationAction(ISD::SRL, MVT::i16, Expand); - setOperationAction(ISD::SRL, MVT::i32, Expand); + + 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::SRA_PARTS, MVT::i16, Expand); - setOperationAction(ISD::SRA_PARTS, MVT::i32, Expand); + setOperationAction(ISD::SRA_PARTS, MVT::i8, Expand); setOperationAction(ISD::SHL_PARTS, MVT::i8, Expand); - setOperationAction(ISD::SHL_PARTS, MVT::i16, Expand); - setOperationAction(ISD::SHL_PARTS, MVT::i32, Expand); setOperationAction(ISD::SRL_PARTS, MVT::i8, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i16, Expand); - setOperationAction(ISD::SRL_PARTS, MVT::i32, Expand); // PIC16 does not have a SETCC, expand it to SELECT_CC. @@ -356,7 +365,8 @@ static void PopulateResults(SDValue N, SmallVectorImpl<SDValue>&Results) { Results.push_back(N); } -MVT PIC16TargetLowering::getSetCCResultType(MVT ValType) const { +MVT::SimpleValueType +PIC16TargetLowering::getSetCCResultType(EVT ValType) const { return MVT::i8; } @@ -379,7 +389,7 @@ PIC16TargetLowering::getPIC16LibcallName(PIC16ISD::PIC16Libcall Call) { SDValue PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, - MVT RetVT, const SDValue *Ops, + EVT RetVT, const SDValue *Ops, unsigned NumOps, bool isSigned, SelectionDAG &DAG, DebugLoc dl) { @@ -389,17 +399,20 @@ PIC16TargetLowering::MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, TargetLowering::ArgListEntry Entry; for (unsigned i = 0; i != NumOps; ++i) { Entry.Node = Ops[i]; - Entry.Ty = Entry.Node.getValueType().getTypeForMVT(); + 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::i8); - const Type *RetTy = RetVT.getTypeForMVT(); + 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, Callee, Args, DAG, dl); + false, 0, CallingConv::C, false, + /*isReturnValueUsed=*/true, + Callee, Args, DAG, dl); return CallInfo.first; } @@ -429,6 +442,7 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const { 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"; } } @@ -502,7 +516,7 @@ SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { SDValue Chain = St->getChain(); SDValue Src = St->getValue(); SDValue Ptr = St->getBasePtr(); - MVT ValueType = Src.getValueType(); + EVT ValueType = Src.getValueType(); unsigned StoreOffset = 0; DebugLoc dl = N->getDebugLoc(); @@ -519,6 +533,10 @@ SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { 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); @@ -546,16 +564,19 @@ SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { 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); @@ -583,8 +604,26 @@ SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) { getChain(Store3), getChain(Store4)); return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, RetLo, RetHi); - } - else { + } 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); + + 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); + + return DAG.getNode(ISD::TokenFactor, dl, MVT::Other, Store1, + Store2); + } else { assert (0 && "value type not supported"); return SDValue(); } @@ -660,7 +699,7 @@ void PIC16TargetLowering::GetExpandedParts(SDValue Op, SelectionDAG &DAG, SDValue &Lo, SDValue &Hi) { SDNode *N = Op.getNode(); DebugLoc dl = N->getDebugLoc(); - MVT NewVT = getTypeToTransformTo(N->getValueType(0)); + EVT NewVT = getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); // Extract the lo component. Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, dl, NewVT, Op, @@ -808,7 +847,7 @@ SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) { SDValue Load, Offset; SDVTList Tys; - MVT VT, NewVT; + EVT VT, NewVT; SDValue PtrLo, PtrHi; unsigned LoadOffset; @@ -821,7 +860,7 @@ SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) { unsigned NumLoads = VT.getSizeInBits() / 8; std::vector<SDValue> PICLoads; unsigned iter; - MVT MemVT = LD->getMemoryVT(); + EVT MemVT = LD->getMemoryVT(); if(ISD::isNON_EXTLoad(N)) { for (iter=0; iter<NumLoads ; ++iter) { // Add the pointer offset if any @@ -839,7 +878,7 @@ SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) { // For extended loads this is the memory value type // i.e. without any extension - MVT MemVT = LD->getMemoryVT(); + 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 @@ -945,6 +984,19 @@ SDValue PIC16TargetLowering::LowerShift(SDValue Op, SelectionDAG &DAG) { return Call; } +SDValue PIC16TargetLowering::LowerMUL(SDValue Op, SelectionDAG &DAG) { + // 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, @@ -953,12 +1005,8 @@ PIC16TargetLowering::LowerOperationWrapper(SDNode *N, SDValue Res; unsigned i; switch (Op.getOpcode()) { - case ISD::FORMAL_ARGUMENTS: - Res = LowerFORMAL_ARGUMENTS(Op, DAG); break; case ISD::LOAD: Res = ExpandLoad(Op.getNode(), DAG); break; - case ISD::CALL: - Res = LowerCALL(Op, DAG); break; default: { // All other operations are handled in LowerOperation. Res = LowerOperation(Op, DAG); @@ -978,8 +1026,6 @@ PIC16TargetLowering::LowerOperationWrapper(SDNode *N, SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { switch (Op.getOpcode()) { - case ISD::FORMAL_ARGUMENTS: - return LowerFORMAL_ARGUMENTS(Op, DAG); case ISD::ADD: case ISD::ADDC: case ISD::ADDE: @@ -992,6 +1038,8 @@ SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { 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: @@ -1000,10 +1048,6 @@ SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) { case ISD::AND: case ISD::XOR: return LowerBinOp(Op, DAG); - case ISD::CALL: - return LowerCALL(Op, DAG); - case ISD::RET: - return LowerRET(Op, DAG); case ISD::BR_CC: return LowerBR_CC(Op, DAG); case ISD::SELECT_CC: @@ -1048,12 +1092,12 @@ SDValue PIC16TargetLowering::ConvertToMemOperand(SDValue Op, } SDValue PIC16TargetLowering:: -LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag, +LowerIndirectCallArguments(SDValue Chain, SDValue InFlag, SDValue DataAddr_Lo, SDValue DataAddr_Hi, - SelectionDAG &DAG) { - CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); - unsigned NumOps = TheCall->getNumArgs(); - DebugLoc dl = TheCall->getDebugLoc(); + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG) { + unsigned NumOps = Outs.size(); // If call has no arguments then do nothing and return. if (NumOps == 0) @@ -1064,10 +1108,10 @@ LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag, SDValue Arg, StoreRet; // For PIC16 ABI the arguments come after the return value. - unsigned RetVals = TheCall->getNumRetVals(); + unsigned RetVals = Ins.size(); for (unsigned i = 0, ArgOffset = RetVals; i < NumOps; i++) { // Get the arguments - Arg = TheCall->getArg(i); + Arg = Outs[i].Val; Ops.clear(); Ops.push_back(Chain); @@ -1087,16 +1131,14 @@ LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag, } SDValue PIC16TargetLowering:: -LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue ArgLabel, - SDValue InFlag, SelectionDAG &DAG) { - CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); - unsigned NumOps = TheCall->getNumArgs(); - DebugLoc dl = TheCall->getDebugLoc(); +LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag, + const SmallVectorImpl<ISD::OutputArg> &Outs, + DebugLoc dl, SelectionDAG &DAG) { + unsigned NumOps = Outs.size(); std::string Name; SDValue Arg, StoreAt; - MVT ArgVT; + EVT ArgVT; unsigned Size=0; - unsigned ArgCount=0; // If call has no arguments then do nothing and return. if (NumOps == 0) @@ -1114,9 +1156,9 @@ LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue ArgLabel, std::vector<SDValue> Ops; SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag); - for (unsigned i=ArgCount, Offset = 0; i<NumOps; i++) { + for (unsigned i=0, Offset = 0; i<NumOps; i++) { // Get the argument - Arg = TheCall->getArg(i); + Arg = Outs[i].Val; StoreOffset = (Offset + AddressOffset); // Store the argument on frame @@ -1144,12 +1186,12 @@ LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue ArgLabel, } SDValue PIC16TargetLowering:: -LowerIndirectCallReturn (SDValue Op, SDValue Chain, SDValue InFlag, - SDValue DataAddr_Lo, SDValue DataAddr_Hi, - SelectionDAG &DAG) { - CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); - DebugLoc dl = TheCall->getDebugLoc(); - unsigned RetVals = TheCall->getNumRetVals(); +LowerIndirectCallReturn(SDValue Chain, SDValue InFlag, + SDValue DataAddr_Lo, SDValue DataAddr_Hi, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) { + unsigned RetVals = Ins.size(); // If call does not have anything to return // then do nothing and go back. @@ -1157,7 +1199,6 @@ LowerIndirectCallReturn (SDValue Op, SDValue Chain, SDValue InFlag, return Chain; // Call has something to return - std::vector<SDValue> ResultVals; SDValue LoadRet; SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Other, MVT::Flag); @@ -1167,23 +1208,20 @@ LowerIndirectCallReturn (SDValue Op, SDValue Chain, SDValue InFlag, InFlag); InFlag = getOutFlag(LoadRet); Chain = getChain(LoadRet); - ResultVals.push_back(LoadRet); + InVals.push_back(LoadRet); } - ResultVals.push_back(Chain); - SDValue Res = DAG.getMergeValues(&ResultVals[0], ResultVals.size(), dl); - return Res; + return Chain; } SDValue PIC16TargetLowering:: -LowerDirectCallReturn(SDValue Op, SDValue Chain, SDValue RetLabel, - SDValue InFlag, SelectionDAG &DAG) { - CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); - DebugLoc dl = TheCall->getDebugLoc(); +LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) { + // Currently handling primitive types only. They will come in // i8 parts - unsigned RetVals = TheCall->getNumRetVals(); - - std::vector<SDValue> ResultVals; + unsigned RetVals = Ins.size(); // Return immediately if the return type is void if (RetVals == 0) @@ -1209,30 +1247,20 @@ LowerDirectCallReturn(SDValue Op, SDValue Chain, SDValue RetLabel, Chain = getChain(LoadRet); Offset++; - ResultVals.push_back(LoadRet); + InVals.push_back(LoadRet); } - // To return use MERGE_VALUES - ResultVals.push_back(Chain); - SDValue Res = DAG.getMergeValues(&ResultVals[0], ResultVals.size(), dl); - return Res; + return Chain; } -SDValue PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) { - SDValue Chain = Op.getOperand(0); - DebugLoc dl = Op.getDebugLoc(); - - if (Op.getNumOperands() == 1) // return void - return Op; +SDValue +PIC16TargetLowering::LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + DebugLoc dl, SelectionDAG &DAG) { - // return should have odd number of operands - if ((Op.getNumOperands() % 2) == 0 ) { - assert(0 && "Do not know how to return this many arguments!"); - abort(); - } - // Number of values to return - unsigned NumRet = (Op.getNumOperands() / 2); + unsigned NumRet = Outs.size(); // Function returns value always on stack with the offset starting // from 0 @@ -1246,68 +1274,13 @@ SDValue PIC16TargetLowering::LowerRET(SDValue Op, SelectionDAG &DAG) { SDValue BS = DAG.getConstant(1, MVT::i8); SDValue RetVal; for(unsigned i=0;i<NumRet; ++i) { - RetVal = Op.getNode()->getOperand(2*i + 1); + RetVal = Outs[i].Val; Chain = DAG.getNode (PIC16ISD::PIC16Store, dl, MVT::Other, Chain, RetVal, ES, BS, DAG.getConstant (i, MVT::i8)); } - return DAG.getNode(ISD::RET, dl, MVT::Other, Chain); -} - -// CALL node may have some operands non-legal to PIC16. Generate new CALL -// node with all the operands legal. -// Currently only Callee operand of the CALL node is non-legal. This function -// legalizes the Callee operand and uses all other operands as are to generate -// new CALL node. - -SDValue PIC16TargetLowering::LegalizeCALL(SDValue Op, SelectionDAG &DAG) { - CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); - SDValue Chain = TheCall->getChain(); - SDValue Callee = TheCall->getCallee(); - DebugLoc dl = TheCall->getDebugLoc(); - unsigned i =0; - - assert(Callee.getValueType() == MVT::i16 && - "Don't know how to legalize this call node!!!"); - assert(Callee.getOpcode() == ISD::BUILD_PAIR && - "Don't know how to legalize this call node!!!"); - - if (isDirectAddress(Callee)) { - // Come here for direct calls - Callee = Callee.getOperand(0).getOperand(0); - } else { - // 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); - } - std::vector<SDValue> Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - - // Add the call arguments and their flags - unsigned NumArgs = TheCall->getNumArgs(); - for(i=0;i<NumArgs;i++) { - Ops.push_back(TheCall->getArg(i)); - Ops.push_back(TheCall->getArgFlagsVal(i)); - } - std::vector<MVT> NodeTys; - unsigned NumRets = TheCall->getNumRetVals(); - for(i=0;i<NumRets;i++) - NodeTys.push_back(TheCall->getRetValType(i)); - - // Return a Chain as well - NodeTys.push_back(MVT::Other); - - SDVTList VTs = DAG.getVTList(&NodeTys[0], NodeTys.size()); - // Generate new call with all the operands legal - return DAG.getCall(TheCall->getCallingConv(), dl, - TheCall->isVarArg(), TheCall->isTailCall(), - TheCall->isInreg(), VTs, &Ops[0], Ops.size(), - TheCall->getNumFixedArgs()); + return DAG.getNode(PIC16ISD::RET, dl, MVT::Other, Chain); } void PIC16TargetLowering:: @@ -1372,36 +1345,40 @@ GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain, 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) { -SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { - CallSDNode *TheCall = dyn_cast<CallSDNode>(Op); - SDValue Chain = TheCall->getChain(); - SDValue Callee = TheCall->getCallee(); - DebugLoc dl = TheCall->getDebugLoc(); - if (Callee.getValueType() == MVT::i16 && - Callee.getOpcode() == ISD::BUILD_PAIR) { - // Control should come here only from TypeLegalizer for lowering - - // Legalize the non-legal arguments of call and return the - // new call with legal arguments. - return LegalizeCALL(Op, DAG); - } - // Control should come here from Legalize DAG. - // Here all the operands of CALL node should be legal. - - // 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. + 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 = TheCall->getNumRetVals(); - unsigned NumArgs = TheCall->getNumArgs(); + unsigned RetVals = Ins.size(); + unsigned NumArgs = Outs.size(); SDValue DataAddr_Lo, DataAddr_Hi; - if (Callee.getOpcode() == PIC16ISD::PIC16Connect) { + 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)) @@ -1457,12 +1434,13 @@ SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { // Pass the argument to function before making the call. SDValue CallArgs; if (IsDirectCall) { - CallArgs = LowerDirectCallArguments(Op, Chain, ArgLabel, OperFlag, DAG); + CallArgs = LowerDirectCallArguments(ArgLabel, Chain, OperFlag, + Outs, dl, DAG); Chain = getChain(CallArgs); OperFlag = getOutFlag(CallArgs); } else { - CallArgs = LowerIndirectCallArguments(Op, Chain, OperFlag, DataAddr_Lo, - DataAddr_Hi, DAG); + CallArgs = LowerIndirectCallArguments(Chain, OperFlag, DataAddr_Lo, + DataAddr_Hi, Outs, Ins, dl, DAG); Chain = getChain(CallArgs); OperFlag = getOutFlag(CallArgs); } @@ -1483,10 +1461,11 @@ SDValue PIC16TargetLowering::LowerCALL(SDValue Op, SelectionDAG &DAG) { // Lower the return value reading after the call. if (IsDirectCall) - return LowerDirectCallReturn(Op, Chain, RetLabel, OperFlag, DAG); + return LowerDirectCallReturn(RetLabel, Chain, OperFlag, + Ins, dl, DAG, InVals); else - return LowerIndirectCallReturn(Op, Chain, OperFlag, DataAddr_Lo, - DataAddr_Hi, DAG); + return LowerIndirectCallReturn(Chain, OperFlag, DataAddr_Lo, + DataAddr_Hi, Ins, dl, DAG, InVals); } bool PIC16TargetLowering::isDirectLoad(const SDValue Op) { @@ -1591,11 +1570,20 @@ SDValue PIC16TargetLowering::LowerSUB(SDValue Op, SelectionDAG &DAG) { SDValue NewVal = ConvertToMemOperand (Op.getOperand(0), DAG, dl); SDVTList Tys = DAG.getVTList(MVT::i8, MVT::Flag); - if (Op.getOpcode() == ISD::SUBE) - return DAG.getNode(Op.getOpcode(), dl, Tys, NewVal, Op.getOperand(1), - Op.getOperand(2)); - else - return DAG.getNode(Op.getOpcode(), dl, Tys, NewVal, Op.getOperand(1)); + 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; + } } void PIC16TargetLowering::InitReservedFrameCount(const Function *F) { @@ -1609,17 +1597,19 @@ void PIC16TargetLowering::InitReservedFrameCount(const Function *F) { ReservedFrameCount = NumArgs + 1; } -// LowerFORMAL_ARGUMENTS - Argument values are loaded from the +// 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::LowerFORMAL_ARGUMENTS(SDValue Op, - SelectionDAG &DAG) { - SmallVector<SDValue, 8> ArgValues; - unsigned NumArgVals = Op.getNode()->getNumValues() - 1; - DebugLoc dl = Op.getDebugLoc(); - SDValue Chain = Op.getOperand(0); // Formal arguments' chain - +SDValue +PIC16TargetLowering::LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, + SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) { + unsigned NumArgVals = Ins.size(); // Get the callee's name to create the <fname>.args label to pass args. MachineFunction &MF = DAG.getMachineFunction(); @@ -1643,13 +1633,10 @@ SDValue PIC16TargetLowering::LowerFORMAL_ARGUMENTS(SDValue Op, SDValue PICLoad = DAG.getNode(PIC16ISD::PIC16LdArg, dl, VTs, Chain, ES, BS, Offset); Chain = getChain(PICLoad); - ArgValues.push_back(PICLoad); + InVals.push_back(PICLoad); } - // Return a MERGE_VALUE node. - ArgValues.push_back(Op.getOperand(0)); - return DAG.getNode(ISD::MERGE_VALUES, dl, Op.getNode()->getVTList(), - &ArgValues[0], ArgValues.size()).getValue(Op.getResNo()); + return Chain; } // Perform DAGCombine of PIC16Load. @@ -1697,7 +1684,7 @@ SDValue PIC16TargetLowering::PerformDAGCombine(SDNode *N, static PIC16CC::CondCodes IntCCToPIC16CC(ISD::CondCode CC) { switch (CC) { - default: assert(0 && "Unknown condition code!"); + default: llvm_unreachable("Unknown condition code!"); case ISD::SETNE: return PIC16CC::NE; case ISD::SETEQ: return PIC16CC::EQ; case ISD::SETGT: return PIC16CC::GT; @@ -1826,7 +1813,8 @@ SDValue PIC16TargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) { MachineBasicBlock * PIC16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, - MachineBasicBlock *BB) const { + MachineBasicBlock *BB, + DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const { const TargetInstrInfo &TII = *getTargetMachine().getInstrInfo(); unsigned CC = (PIC16CC::CondCodes)MI->getOperand(3).getImm(); DebugLoc dl = MI->getDebugLoc(); @@ -1852,9 +1840,18 @@ PIC16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, F->insert(It, copy0MBB); F->insert(It, sinkMBB); - // Update machine-CFG edges by transferring all successors of the current + // 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. - sinkMBB->transferSuccessors(BB); + // Also inform sdisel of the edge changes. + for (MachineBasicBlock::succ_iterator I = BB->succ_begin(), + E = BB->succ_end(); I != E; ++I) { + EM->insert(std::make_pair(*I, sinkMBB)); + 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); diff --git a/lib/Target/PIC16/PIC16ISelLowering.h b/lib/Target/PIC16/PIC16ISelLowering.h index b40ea12..286ed24 100644 --- a/lib/Target/PIC16/PIC16ISelLowering.h +++ b/lib/Target/PIC16/PIC16ISelLowering.h @@ -52,6 +52,7 @@ namespace llvm { SUBCC, // Compare for equality or inequality. SELECT_ICC, // Psuedo to be caught in schedular and expanded to brcond. BRCOND, // Conditional branch. + RET, // Return. Dummy }; @@ -81,39 +82,45 @@ namespace llvm { /// DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; /// getSetCCResultType - Return the ISD::SETCC ValueType - virtual MVT getSetCCResultType(MVT ValType) const; - SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG); + virtual MVT::SimpleValueType getSetCCResultType(EVT ValType) const; SDValue LowerShift(SDValue Op, SelectionDAG &DAG); + SDValue LowerMUL(SDValue Op, SelectionDAG &DAG); SDValue LowerADD(SDValue Op, SelectionDAG &DAG); SDValue LowerSUB(SDValue Op, SelectionDAG &DAG); SDValue LowerBinOp(SDValue Op, SelectionDAG &DAG); - SDValue LowerCALL(SDValue Op, SelectionDAG &DAG); - SDValue LowerRET(SDValue Op, SelectionDAG &DAG); // Call returns SDValue - LowerDirectCallReturn(SDValue Op, SDValue Chain, SDValue FrameAddress, - SDValue InFlag, SelectionDAG &DAG); + LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals); SDValue - LowerIndirectCallReturn(SDValue Op, SDValue Chain, SDValue InFlag, - SDValue DataAddr_Lo, SDValue DataAddr_Hi, - SelectionDAG &DAG); + LowerIndirectCallReturn(SDValue Chain, SDValue InFlag, + SDValue DataAddr_Lo, SDValue DataAddr_Hi, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals); // Call arguments SDValue - LowerDirectCallArguments(SDValue Op, SDValue Chain, SDValue FrameAddress, - SDValue InFlag, SelectionDAG &DAG); + LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag, + const SmallVectorImpl<ISD::OutputArg> &Outs, + DebugLoc dl, SelectionDAG &DAG); SDValue - LowerIndirectCallArguments(SDValue Op, SDValue Chain, SDValue InFlag, + LowerIndirectCallArguments(SDValue Chain, SDValue InFlag, SDValue DataAddr_Lo, SDValue DataAddr_Hi, - SelectionDAG &DAG); + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG); SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG); SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG); SDValue getPIC16Cmp(SDValue LHS, SDValue RHS, unsigned OrigCC, SDValue &CC, SelectionDAG &DAG, DebugLoc dl); virtual MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, - MachineBasicBlock *MBB) const; + MachineBasicBlock *MBB, + DenseMap<MachineBasicBlock*, MachineBasicBlock*> *EM) const; virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG); @@ -124,6 +131,28 @@ namespace llvm { SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG); + virtual SDValue + LowerFormalArguments(SDValue Chain, + CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + DebugLoc dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals); + + 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); + + virtual SDValue + LowerReturn(SDValue Chain, + CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + DebugLoc dl, SelectionDAG &DAG); + SDValue ExpandStore(SDNode *N, SelectionDAG &DAG); SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG); SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG); @@ -174,12 +203,6 @@ namespace llvm { void LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, SDValue &ES, int &Offset); - - // CALL node should have all legal operands only. Legalize all non-legal - // operands of CALL node and then return the new call will all operands - // legal. - SDValue LegalizeCALL(SDValue Op, SelectionDAG &DAG); - // 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. @@ -209,7 +232,7 @@ namespace llvm { const char *getPIC16LibcallName(PIC16ISD::PIC16Libcall Call); // Make PIC16 Libcall. - SDValue MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, MVT RetVT, + SDValue MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, EVT RetVT, const SDValue *Ops, unsigned NumOps, bool isSigned, SelectionDAG &DAG, DebugLoc dl); diff --git a/lib/Target/PIC16/PIC16InstrInfo.cpp b/lib/Target/PIC16/PIC16InstrInfo.cpp index 8418423..cb0c41b 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.cpp +++ b/lib/Target/PIC16/PIC16InstrInfo.cpp @@ -20,6 +20,7 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Support/ErrorHandling.h" #include <cstdio> @@ -104,7 +105,7 @@ void PIC16InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB, .addImm(1); // Emit banksel for it. } else - assert(0 && "Can't store this register to stack slot"); + llvm_unreachable("Can't store this register to stack slot"); } void PIC16InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, @@ -144,7 +145,7 @@ void PIC16InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB, .addImm(1); // Emit banksel for it. } else - assert(0 && "Can't load this register from stack slot"); + llvm_unreachable("Can't load this register from stack slot"); } bool PIC16InstrInfo::copyRegToReg (MachineBasicBlock &MBB, diff --git a/lib/Target/PIC16/PIC16InstrInfo.td b/lib/Target/PIC16/PIC16InstrInfo.td index a054bdc..250ca0a 100644 --- a/lib/Target/PIC16/PIC16InstrInfo.td +++ b/lib/Target/PIC16/PIC16InstrInfo.td @@ -115,6 +115,8 @@ def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond, def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc, [SDNPInFlag]>; +def PIC16ret : SDNode<"PIC16ISD::RET", SDTNone, [SDNPHasChain]>; + //===----------------------------------------------------------------------===// // PIC16 Operand Definitions. //===----------------------------------------------------------------------===// @@ -375,8 +377,9 @@ def subfw_2: SUBFW<0, "subwf", subc>; let Uses = [STATUS] in def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow. -def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>; } +let Defs = [STATUS], isTerminator = 1 in +def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>; // [F] -= W ; let mayStore = 1 in @@ -425,8 +428,9 @@ class SUBLW<bits<6> opcode, SDNode OpNode> : let Defs = [STATUS] in { def sublw_1 : SUBLW<0, sub>; def sublw_2 : SUBLW<0, subc>; -def sublw_cc : SUBLW<0, PIC16Subcc>; } +let Defs = [STATUS], isTerminator = 1 in +def sublw_cc : SUBLW<0, PIC16Subcc>; // Call instruction. let isCall = 1, @@ -489,8 +493,9 @@ def pagesel : // Return insn. +let isTerminator = 1, isBarrier = 1, isReturn = 1 in def Return : - ControlFormat<0, (outs), (ins), "return", [(ret)]>; + ControlFormat<0, (outs), (ins), "return", [(PIC16ret)]>; //===----------------------------------------------------------------------===// // PIC16 Replacment Patterns. diff --git a/lib/Target/PIC16/PIC16MCAsmInfo.cpp b/lib/Target/PIC16/PIC16MCAsmInfo.cpp new file mode 100644 index 0000000..a17d1a8 --- /dev/null +++ b/lib/Target/PIC16/PIC16MCAsmInfo.cpp @@ -0,0 +1,58 @@ +//===-- 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 "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 "; + + + // 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/lib/Target/PIC16/PIC16MCAsmInfo.h b/lib/Target/PIC16/PIC16MCAsmInfo.h new file mode 100644 index 0000000..e84db85 --- /dev/null +++ b/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/lib/Target/PIC16/PIC16MemSelOpt.cpp b/lib/Target/PIC16/PIC16MemSelOpt.cpp index 43d47ae..c9ebb57 100644 --- a/lib/Target/PIC16/PIC16MemSelOpt.cpp +++ b/lib/Target/PIC16/PIC16MemSelOpt.cpp @@ -22,7 +22,7 @@ #define DEBUG_TYPE "pic16-codegen" #include "PIC16.h" #include "PIC16InstrInfo.h" -#include "PIC16TargetAsmInfo.h" +#include "PIC16MCAsmInfo.h" #include "PIC16TargetMachine.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" diff --git a/lib/Target/PIC16/PIC16RegisterInfo.cpp b/lib/Target/PIC16/PIC16RegisterInfo.cpp index eb758d8..47087ab 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.cpp +++ b/lib/Target/PIC16/PIC16RegisterInfo.cpp @@ -16,7 +16,7 @@ #include "PIC16.h" #include "PIC16RegisterInfo.h" #include "llvm/ADT/BitVector.h" - +#include "llvm/Support/ErrorHandling.h" using namespace llvm; @@ -51,10 +51,13 @@ bool PIC16RegisterInfo::hasFP(const MachineFunction &MF) const { return false; } -void PIC16RegisterInfo:: +unsigned PIC16RegisterInfo:: eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, - RegScavenger *RS) const -{ /* NOT YET IMPLEMENTED */ } + int *Value, RegScavenger *RS) const +{ + /* NOT YET IMPLEMENTED */ + return 0; +} void PIC16RegisterInfo::emitPrologue(MachineFunction &MF) const { /* NOT YET IMPLEMENTED */ } @@ -65,17 +68,17 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const int PIC16RegisterInfo:: getDwarfRegNum(unsigned RegNum, bool isEH) const { - assert(0 && "Not keeping track of debug information yet!!"); + llvm_unreachable("Not keeping track of debug information yet!!"); return -1; } unsigned PIC16RegisterInfo::getFrameRegister(MachineFunction &MF) const { - assert(0 && "PIC16 Does not have any frame register"); + llvm_unreachable("PIC16 Does not have any frame register"); return 0; } unsigned PIC16RegisterInfo::getRARegister() const { - assert(0 && "PIC16 Does not have any return address register"); + llvm_unreachable("PIC16 Does not have any return address register"); return 0; } diff --git a/lib/Target/PIC16/PIC16RegisterInfo.h b/lib/Target/PIC16/PIC16RegisterInfo.h index 83689d0..8aa5a10 100644 --- a/lib/Target/PIC16/PIC16RegisterInfo.h +++ b/lib/Target/PIC16/PIC16RegisterInfo.h @@ -48,8 +48,9 @@ class PIC16RegisterInfo : public PIC16GenRegisterInfo { virtual BitVector getReservedRegs(const MachineFunction &MF) const; virtual bool hasFP(const MachineFunction &MF) const; - virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, - int SPAdj, RegScavenger *RS=NULL) const; + virtual unsigned eliminateFrameIndex(MachineBasicBlock::iterator MI, + int SPAdj, int *Value = NULL, + RegScavenger *RS=NULL) const; void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, diff --git a/lib/Target/PIC16/PIC16Subtarget.cpp b/lib/Target/PIC16/PIC16Subtarget.cpp index db8a5d8..33fc3fb 100644 --- a/lib/Target/PIC16/PIC16Subtarget.cpp +++ b/lib/Target/PIC16/PIC16Subtarget.cpp @@ -16,7 +16,7 @@ using namespace llvm; -PIC16Subtarget::PIC16Subtarget(const Module &M, const std::string &FS, +PIC16Subtarget::PIC16Subtarget(const std::string &TT, const std::string &FS, bool Cooper) :IsCooper(Cooper) { diff --git a/lib/Target/PIC16/PIC16Subtarget.h b/lib/Target/PIC16/PIC16Subtarget.h index e5147a0..81e3783 100644 --- a/lib/Target/PIC16/PIC16Subtarget.h +++ b/lib/Target/PIC16/PIC16Subtarget.h @@ -19,7 +19,6 @@ #include <string> namespace llvm { -class Module; class PIC16Subtarget : public TargetSubtarget { @@ -28,9 +27,9 @@ class PIC16Subtarget : public TargetSubtarget { public: /// This constructor initializes the data members to match that - /// of the specified module. + /// of the specified triple. /// - PIC16Subtarget(const Module &M, const std::string &FS, bool Cooper); + 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; } diff --git a/lib/Target/PIC16/PIC16TargetMachine.cpp b/lib/Target/PIC16/PIC16TargetMachine.cpp index 77ad188..08307e7 100644 --- a/lib/Target/PIC16/PIC16TargetMachine.cpp +++ b/lib/Target/PIC16/PIC16TargetMachine.cpp @@ -12,51 +12,32 @@ //===----------------------------------------------------------------------===// #include "PIC16.h" -#include "PIC16TargetAsmInfo.h" +#include "PIC16MCAsmInfo.h" #include "PIC16TargetMachine.h" -#include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/Target/TargetAsmInfo.h" -#include "llvm/Target/TargetMachineRegistry.h" +#include "llvm/Target/TargetRegistry.h" using namespace llvm; -/// PIC16TargetMachineModule - Note that this is used on hosts that -/// cannot link in a library unless there are references into the -/// library. In particular, it seems that it is not possible to get -/// things to work on Win32 without this. Though it is unused, do not -/// remove it. -extern "C" int PIC16TargetMachineModule; -int PIC16TargetMachineModule = 0; - - -// Register the targets -static RegisterTarget<PIC16TargetMachine> -X("pic16", "PIC16 14-bit [experimental]."); -static RegisterTarget<CooperTargetMachine> -Y("cooper", "PIC16 Cooper [experimental]."); +extern "C" void LLVMInitializePIC16Target() { + // Register the target. Curretnly the codegen works for + // enhanced pic16 mid-range. + RegisterTargetMachine<PIC16TargetMachine> X(ThePIC16Target); + RegisterAsmInfo<PIC16MCAsmInfo> A(ThePIC16Target); +} -// Force static initialization. -extern "C" void LLVMInitializePIC16Target() { } -// PIC16TargetMachine - Traditional PIC16 Machine. -PIC16TargetMachine::PIC16TargetMachine(const Module &M, const std::string &FS, - bool Cooper) -: Subtarget(M, FS, Cooper), +// 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"), InstrInfo(*this), TLInfo(*this), FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { } -// CooperTargetMachine - Uses the same PIC16TargetMachine, but makes IsCooper -// as true. -CooperTargetMachine::CooperTargetMachine(const Module &M, const std::string &FS) - : PIC16TargetMachine(M, FS, true) {} - - -const TargetAsmInfo *PIC16TargetMachine::createTargetAsmInfo() const { - return new PIC16TargetAsmInfo(*this); -} bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { @@ -65,15 +46,7 @@ bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM, return false; } -bool PIC16TargetMachine::addAssemblyEmitter(PassManagerBase &PM, - CodeGenOpt::Level OptLevel, - bool Verbose, raw_ostream &Out) { - // Output assembly language. - PM.add(createPIC16CodePrinterPass(Out, *this, Verbose)); - return false; -} - -bool PIC16TargetMachine::addPostRegAlloc(PassManagerBase &PM, +bool PIC16TargetMachine::addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel) { PM.add(createPIC16MemSelOptimizerPass()); return true; // -print-machineinstr should print after this. diff --git a/lib/Target/PIC16/PIC16TargetMachine.h b/lib/Target/PIC16/PIC16TargetMachine.h index 7f62d5c..b11fdd5 100644 --- a/lib/Target/PIC16/PIC16TargetMachine.h +++ b/lib/Target/PIC16/PIC16TargetMachine.h @@ -37,12 +37,9 @@ class PIC16TargetMachine : public LLVMTargetMachine { // any PIC16 specific FrameInfo class. TargetFrameInfo FrameInfo; -protected: - virtual const TargetAsmInfo *createTargetAsmInfo() const; - public: - PIC16TargetMachine(const Module &M, const std::string &FS, - bool Cooper = false); + 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; } @@ -59,18 +56,9 @@ public: virtual bool addInstSelector(PassManagerBase &PM, CodeGenOpt::Level OptLevel); - virtual bool addAssemblyEmitter(PassManagerBase &PM, - CodeGenOpt::Level OptLevel, - bool Verbose, raw_ostream &Out); - virtual bool addPostRegAlloc(PassManagerBase &PM, CodeGenOpt::Level OptLevel); + virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel); }; // PIC16TargetMachine. -/// CooperTargetMachine -class CooperTargetMachine : public PIC16TargetMachine { -public: - CooperTargetMachine(const Module &M, const std::string &FS); -}; // CooperTargetMachine. - } // end namespace llvm #endif diff --git a/lib/Target/PIC16/PIC16TargetObjectFile.cpp b/lib/Target/PIC16/PIC16TargetObjectFile.cpp new file mode 100644 index 0000000..a2a4c09 --- /dev/null +++ b/lib/Target/PIC16/PIC16TargetObjectFile.cpp @@ -0,0 +1,440 @@ +//===-- 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 "MCSectionPIC16.h" +#include "PIC16ISelLowering.h" +#include "PIC16TargetMachine.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; + + +MCSectionPIC16 *MCSectionPIC16::Create(const StringRef &Name, SectionKind K, + int Address, int Color, MCContext &Ctx) { + return new (Ctx) MCSectionPIC16(Name, K, Address, Color); +} + + +void MCSectionPIC16::PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const { + OS << getName() << '\n'; +} + + + + +PIC16TargetObjectFile::PIC16TargetObjectFile() + : ExternalVarDecls(0), ExternalVarDefs(0) { +} + +const MCSectionPIC16 *PIC16TargetObjectFile:: +getPIC16Section(const char *Name, SectionKind Kind, + int Address, int Color) const { + MCSectionPIC16 *&Entry = SectionsByName[Name]; + if (Entry) + return Entry; + + return Entry = MCSectionPIC16::Create(Name, Kind, Address, Color, + getContext()); +} + + +void PIC16TargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &tm){ + TargetLoweringObjectFile::Initialize(Ctx, tm); + TM = &tm; + + BSSSection = getPIC16Section("udata.# UDATA", MCSectionPIC16::UDATA_Kind()); + ReadOnlySection = getPIC16Section("romdata.# ROMDATA", + MCSectionPIC16::ROMDATA_Kind()); + DataSection = getPIC16Section("idata.# IDATA", MCSectionPIC16::IDATA_Kind()); + + // Need because otherwise a .text symbol is emitted by DwarfWriter + // in BeginModule, and gpasm cribbs for that .text symbol. + TextSection = getPIC16Section("", SectionKind::getText()); + + ROSections.push_back(new PIC16Section((MCSectionPIC16*)ReadOnlySection)); + + // FIXME: I don't know what the classification of these sections really is. + // These aren't really objects belonging to any section. Just emit them + // in AsmPrinter and remove this code from here. + ExternalVarDecls = new PIC16Section(getPIC16Section("ExternalVarDecls", + SectionKind::getMetadata())); + ExternalVarDefs = new PIC16Section(getPIC16Section("ExternalVarDefs", + SectionKind::getMetadata())); +} + +const MCSection *PIC16TargetObjectFile:: +getSectionForFunction(const std::string &FnName) const { + std::string T = PAN::getCodeSectionName(FnName); + return getPIC16Section(T.c_str(), SectionKind::getText()); +} + + +const MCSection *PIC16TargetObjectFile:: +getSectionForFunctionFrame(const std::string &FnName) const { + std::string T = PAN::getFrameSectionName(FnName); + return getPIC16Section(T.c_str(), SectionKind::getDataRel()); +} + +const MCSection * +PIC16TargetObjectFile::getBSSSectionForGlobal(const GlobalVariable *GV) const { + assert(GV->hasInitializer() && "This global doesn't need space"); + 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 BSS Sections and assign this variable + // to the first available section having enough space. + PIC16Section *FoundBSS = NULL; + for (unsigned i = 0; i < BSSSections.size(); i++) { + if (DataBankSize - BSSSections[i]->Size >= ValSize) { + FoundBSS = BSSSections[i]; + break; + } + } + + // No BSS section spacious enough was found. Crate a new one. + if (!FoundBSS) { + std::string name = PAN::getUdataSectionName(BSSSections.size()); + const MCSectionPIC16 *NewSection + = getPIC16Section(name.c_str(), MCSectionPIC16::UDATA_Kind()); + + FoundBSS = new PIC16Section(NewSection); + + // Add this newly created BSS section to the list of BSSSections. + BSSSections.push_back(FoundBSS); + } + + // Insert the GV into this BSS. + FoundBSS->Items.push_back(GV); + FoundBSS->Size += ValSize; + return FoundBSS->S_; +} + +const MCSection * +PIC16TargetObjectFile::getIDATASectionForGlobal(const GlobalVariable *GV) const{ + assert(GV->hasInitializer() && "This global doesn't need space"); + Constant *C = GV->getInitializer(); + assert(!C->isNullValue() && "initialized globals has zero initializer"); + assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE && + "can split 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 *FoundIDATA = NULL; + for (unsigned i = 0; i < IDATASections.size(); i++) { + if (DataBankSize - IDATASections[i]->Size >= ValSize) { + FoundIDATA = IDATASections[i]; + break; + } + } + + // No IDATA section spacious enough was found. Crate a new one. + if (!FoundIDATA) { + std::string name = PAN::getIdataSectionName(IDATASections.size()); + const MCSectionPIC16 *NewSection = + getPIC16Section(name.c_str(), MCSectionPIC16::IDATA_Kind()); + + FoundIDATA = new PIC16Section(NewSection); + + // Add this newly created IDATA section to the list of IDATASections. + IDATASections.push_back(FoundIDATA); + } + + // Insert the GV into this IDATA. + FoundIDATA->Items.push_back(GV); + FoundIDATA->Size += ValSize; + return FoundIDATA->S_; +} + +// Get the section for an automatic variable of a function. +// For PIC16 they are globals only with mangled names. +const MCSection * +PIC16TargetObjectFile::getSectionForAuto(const GlobalVariable *GV) const { + + const std::string name = PAN::getSectionNameForSym(GV->getName()); + + // Go through all Auto Sections and assign this variable + // to the appropriate section. + PIC16Section *FoundAutoSec = NULL; + for (unsigned i = 0; i < AutosSections.size(); i++) { + if (AutosSections[i]->S_->getName() == name) { + FoundAutoSec = AutosSections[i]; + break; + } + } + + // No Auto section was found. Crate a new one. + if (!FoundAutoSec) { + const MCSectionPIC16 *NewSection = + getPIC16Section(name.c_str(), MCSectionPIC16::UDATA_OVR_Kind()); + + FoundAutoSec = new PIC16Section(NewSection); + + // Add this newly created autos section to the list of AutosSections. + AutosSections.push_back(FoundAutoSec); + } + + // Insert the auto into this section. + FoundAutoSec->Items.push_back(GV); + + return FoundAutoSec->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); + + // Record External Var Decls. + if (GV->isDeclaration()) { + ExternalVarDecls->Items.push_back(GV); + return ExternalVarDecls->S_; + } + + 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 getSectionForAuto(GV); + + // Record Exteranl Var Defs. + if (GV->hasExternalLinkage() || GV->hasCommonLinkage()) + ExternalVarDefs->Items.push_back(GV); + + // See if this is an uninitialized global. + const Constant *C = GV->getInitializer(); + if (C->isNullValue()) + return getBSSSectionForGlobal(GV); + + // If this is initialized data in RAM. Put it in the correct IDATA section. + if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) + return getIDATASectionForGlobal(GV); + + // This is initialized data in rom, put it in the readonly section. + if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) + return getROSectionForGlobal(GV); + + // Else let the default implementation take care of it. + return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, Mang,TM); +} + +PIC16TargetObjectFile::~PIC16TargetObjectFile() { + for (unsigned i = 0; i < BSSSections.size(); i++) + delete BSSSections[i]; + for (unsigned i = 0; i < IDATASections.size(); i++) + delete IDATASections[i]; + for (unsigned i = 0; i < AutosSections.size(); i++) + delete AutosSections[i]; + for (unsigned i = 0; i < ROSections.size(); i++) + delete ROSections[i]; + delete ExternalVarDecls; + delete ExternalVarDefs; +} + + +/// getSpecialCasedSectionGlobals - 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. + std::string AddrStr = "Address="; + if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) { + std::string SectAddr = SectName.substr(AddrStr.length()); + return CreateSectionForGlobal(GVar, Mang, SectAddr); + } + + // Create the section specified with section attribute. + return CreateSectionForGlobal(GVar, Mang); + } + + return getPIC16Section(GV->getSection().c_str(), Kind); +} + +// Create a new section for global variable. If Addr is given then create +// section at that address else create by name. +const MCSection * +PIC16TargetObjectFile::CreateSectionForGlobal(const GlobalVariable *GV, + Mangler *Mang, + const std::string &Addr) const { + // See if this is an uninitialized global. + const Constant *C = GV->getInitializer(); + if (C->isNullValue()) + return CreateBSSSectionForGlobal(GV, Addr); + + // If this is initialized data in RAM. Put it in the correct IDATA section. + if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) + return CreateIDATASectionForGlobal(GV, Addr); + + // This is initialized data in rom, put it in the readonly section. + if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE) + return CreateROSectionForGlobal(GV, Addr); + + // Else let the default implementation take care of it. + return TargetLoweringObjectFile::SectionForGlobal(GV, Mang, *TM); +} + +// Create uninitialized section for a variable. +const MCSection * +PIC16TargetObjectFile::CreateBSSSectionForGlobal(const GlobalVariable *GV, + std::string Addr) const { + assert(GV->hasInitializer() && "This global doesn't need space"); + assert(GV->getInitializer()->isNullValue() && + "Unitialized global has non-zero initializer"); + std::string Name; + // If address is given then create a section at that address else create a + // section by section name specified in GV. + PIC16Section *FoundBSS = NULL; + if (Addr.empty()) { + Name = GV->getSection() + " UDATA"; + for (unsigned i = 0; i < BSSSections.size(); i++) { + if (BSSSections[i]->S_->getName() == Name) { + FoundBSS = BSSSections[i]; + break; + } + } + } else { + std::string Prefix = GV->getNameStr() + "." + Addr + "."; + Name = PAN::getUdataSectionName(BSSSections.size(), Prefix) + " " + Addr; + } + + PIC16Section *NewBSS = FoundBSS; + if (NewBSS == NULL) { + const MCSectionPIC16 *NewSection = + getPIC16Section(Name.c_str(), MCSectionPIC16::UDATA_Kind()); + NewBSS = new PIC16Section(NewSection); + BSSSections.push_back(NewBSS); + } + + // Insert the GV into this BSS. + NewBSS->Items.push_back(GV); + + // We do not want to put any GV without explicit section into this section + // so set its size to DatabankSize. + NewBSS->Size = DataBankSize; + return NewBSS->S_; +} + +// Get rom section for a variable. Currently there can be only one rom section +// unless a variable explicitly requests a section. +const MCSection * +PIC16TargetObjectFile::getROSectionForGlobal(const GlobalVariable *GV) const { + ROSections[0]->Items.push_back(GV); + return ROSections[0]->S_; +} + +// Create initialized data section for a variable. +const MCSection * +PIC16TargetObjectFile::CreateIDATASectionForGlobal(const GlobalVariable *GV, + std::string Addr) const { + assert(GV->hasInitializer() && "This global doesn't need space"); + assert(!GV->getInitializer()->isNullValue() && + "initialized global has zero initializer"); + assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE && + "can be used for initialized RAM data only"); + + std::string Name; + // If address is given then create a section at that address else create a + // section by section name specified in GV. + PIC16Section *FoundIDATASec = NULL; + if (Addr.empty()) { + Name = GV->getSection() + " IDATA"; + for (unsigned i = 0; i < IDATASections.size(); i++) { + if (IDATASections[i]->S_->getName() == Name) { + FoundIDATASec = IDATASections[i]; + break; + } + } + } else { + std::string Prefix = GV->getNameStr() + "." + Addr + "."; + Name = PAN::getIdataSectionName(IDATASections.size(), Prefix) + " " + Addr; + } + + PIC16Section *NewIDATASec = FoundIDATASec; + if (NewIDATASec == NULL) { + const MCSectionPIC16 *NewSection = + getPIC16Section(Name.c_str(), MCSectionPIC16::IDATA_Kind()); + NewIDATASec = new PIC16Section(NewSection); + IDATASections.push_back(NewIDATASec); + } + // Insert the GV into this IDATA Section. + NewIDATASec->Items.push_back(GV); + // We do not want to put any GV without explicit section into this section + // so set its size to DatabankSize. + NewIDATASec->Size = DataBankSize; + return NewIDATASec->S_; +} + +// Create a section in rom for a variable. +const MCSection * +PIC16TargetObjectFile::CreateROSectionForGlobal(const GlobalVariable *GV, + std::string Addr) const { + assert(GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE && + "can be used for ROM data only"); + + std::string Name; + // If address is given then create a section at that address else create a + // section by section name specified in GV. + PIC16Section *FoundROSec = NULL; + if (Addr.empty()) { + Name = GV->getSection() + " ROMDATA"; + for (unsigned i = 1; i < ROSections.size(); i++) { + if (ROSections[i]->S_->getName() == Name) { + FoundROSec = ROSections[i]; + break; + } + } + } else { + std::string Prefix = GV->getNameStr() + "." + Addr + "."; + Name = PAN::getRomdataSectionName(ROSections.size(), Prefix) + " " + Addr; + } + + PIC16Section *NewRomSec = FoundROSec; + if (NewRomSec == NULL) { + const MCSectionPIC16 *NewSection = + getPIC16Section(Name.c_str(), MCSectionPIC16::ROMDATA_Kind()); + NewRomSec = new PIC16Section(NewSection); + ROSections.push_back(NewRomSec); + } + + // Insert the GV into this ROM Section. + NewRomSec->Items.push_back(GV); + return NewRomSec->S_; +} + diff --git a/lib/Target/PIC16/PIC16TargetObjectFile.h b/lib/Target/PIC16/PIC16TargetObjectFile.h new file mode 100644 index 0000000..75f6cce --- /dev/null +++ b/lib/Target/PIC16/PIC16TargetObjectFile.h @@ -0,0 +1,120 @@ +//===-- 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 "llvm/Target/TargetLoweringObjectFile.h" +#include "llvm/ADT/StringMap.h" +#include <vector> +#include <string> + +namespace llvm { + class GlobalVariable; + class Module; + class PIC16TargetMachine; + class MCSectionPIC16; + + 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 MCSectionPIC16. + /// + struct PIC16Section { + const MCSectionPIC16 *S_; // Connection to actual Section. + unsigned Size; // Total size of the objects contained. + bool SectionPrinted; + std::vector<const GlobalVariable*> Items; + + PIC16Section(const MCSectionPIC16 *s) { + S_ = s; + Size = 0; + SectionPrinted = false; + } + bool isPrinted() const { return SectionPrinted; } + void setPrintedStatus(bool status) { SectionPrinted = status; } + }; + + class PIC16TargetObjectFile : public TargetLoweringObjectFile { + /// SectionsByName - Bindings of names to allocated sections. + mutable StringMap<MCSectionPIC16*> SectionsByName; + + const TargetMachine *TM; + + const MCSectionPIC16 *getPIC16Section(const char *Name, + SectionKind K, + int Address = -1, + int Color = -1) const; + public: + mutable std::vector<PIC16Section*> BSSSections; + mutable std::vector<PIC16Section*> IDATASections; + mutable std::vector<PIC16Section*> AutosSections; + mutable std::vector<PIC16Section*> ROSections; + mutable PIC16Section *ExternalVarDecls; + mutable PIC16Section *ExternalVarDefs; + + PIC16TargetObjectFile(); + ~PIC16TargetObjectFile(); + + void Initialize(MCContext &Ctx, const TargetMachine &TM); + + + virtual const MCSection * + getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler *Mang, const TargetMachine &TM) const; + + virtual const MCSection *SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, + Mangler *Mang, + const TargetMachine&) const; + + const MCSection *getSectionForFunction(const std::string &FnName) const; + const MCSection *getSectionForFunctionFrame(const std::string &FnName)const; + + + private: + std::string getSectionNameForSym(const std::string &Sym) const; + + const MCSection *getBSSSectionForGlobal(const GlobalVariable *GV) const; + const MCSection *getIDATASectionForGlobal(const GlobalVariable *GV) const; + const MCSection *getSectionForAuto(const GlobalVariable *GV) const; + const MCSection *CreateBSSSectionForGlobal(const GlobalVariable *GV, + std::string Addr = "") const; + const MCSection *CreateIDATASectionForGlobal(const GlobalVariable *GV, + std::string Addr = "") const; + const MCSection *getROSectionForGlobal(const GlobalVariable *GV) const; + const MCSection *CreateROSectionForGlobal(const GlobalVariable *GV, + std::string Addr = "") const; + const MCSection *CreateSectionForGlobal(const GlobalVariable *GV, + Mangler *Mang, + const std::string &Addr = "") const; + public: + void SetSectionForGVs(Module &M); + const std::vector<PIC16Section*> &getBSSSections() const { + return BSSSections; + } + const std::vector<PIC16Section*> &getIDATASections() const { + return IDATASections; + } + const std::vector<PIC16Section*> &getAutosSections() const { + return AutosSections; + } + const std::vector<PIC16Section*> &getROSections() const { + return ROSections; + } + + }; +} // end namespace llvm + +#endif diff --git a/lib/Target/PIC16/TargetInfo/CMakeLists.txt b/lib/Target/PIC16/TargetInfo/CMakeLists.txt new file mode 100644 index 0000000..bfc6ff4 --- /dev/null +++ b/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/lib/Target/PIC16/TargetInfo/Makefile b/lib/Target/PIC16/TargetInfo/Makefile new file mode 100644 index 0000000..76609f6 --- /dev/null +++ b/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/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp b/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp new file mode 100644 index 0000000..46cc819 --- /dev/null +++ b/lib/Target/PIC16/TargetInfo/PIC16TargetInfo.cpp @@ -0,0 +1,21 @@ +//===-- 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<> X(ThePIC16Target, "pic16", "PIC16 14-bit [experimental]"); + + RegisterTarget<> Y(TheCooperTarget, "cooper", "PIC16 Cooper [experimental]"); +} |