diff options
23 files changed, 3323 insertions, 0 deletions
diff --git a/lib/Target/PIC16/Makefile b/lib/Target/PIC16/Makefile new file mode 100644 index 0000000000..c429324cc2 --- /dev/null +++ b/lib/Target/PIC16/Makefile @@ -0,0 +1,21 @@ +##===- lib/Target/PIC16/Makefile ---------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## +LEVEL = ../../.. +LIBRARYNAME = LLVMPIC16 +TARGET = PIC16 + +# Make sure that tblgen is run, first thing. +BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \ + PIC16GenRegisterInfo.inc PIC16GenInstrNames.inc \ + PIC16GenInstrInfo.inc PIC16GenAsmWriter.inc \ + PIC16GenDAGISel.inc PIC16GenCallingConv.inc \ + PIC16GenSubtarget.inc + +include $(LEVEL)/Makefile.common + diff --git a/lib/Target/PIC16/PIC16.h b/lib/Target/PIC16/PIC16.h new file mode 100644 index 0000000000..5c2a4cce82 --- /dev/null +++ b/lib/Target/PIC16/PIC16.h @@ -0,0 +1,38 @@ +//===-- PIC16.h - Top-level interface for PIC16 representation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Bruno Cardoso Lopes and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the entry points for global functions defined in +// the LLVM PIC16 back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_PIC16_H +#define TARGET_PIC16_H + +#include <iosfwd> + +namespace llvm { + class PIC16TargetMachine; + class FunctionPassManager; + class FunctionPass; + class MachineCodeEmitter; + + FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM); + FunctionPass *createPIC16CodePrinterPass(std::ostream &OS, + PIC16TargetMachine &TM); +} // end namespace llvm; + +// Defines symbolic names for PIC16 registers. This defines a mapping from +// register name to register number. +#include "PIC16GenRegisterNames.inc" + +// Defines symbolic names for the PIC16 instructions. +#include "PIC16GenInstrNames.inc" + +#endif diff --git a/lib/Target/PIC16/PIC16.td b/lib/Target/PIC16/PIC16.td new file mode 100644 index 0000000000..0ab4a3444f --- /dev/null +++ b/lib/Target/PIC16/PIC16.td @@ -0,0 +1,46 @@ +//===- PIC16.td - Describe the PIC16 Target Machine -----------*- tblgen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This is the top level entry point for the PIC16 target. +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces +//===----------------------------------------------------------------------===// + +include "../Target.td" + +//===----------------------------------------------------------------------===// +// Descriptions +//===----------------------------------------------------------------------===// + +include "PIC16RegisterInfo.td" +include "PIC16CallingConv.td" +include "PIC16InstrInfo.td" + +def PIC16InstrInfo : InstrInfo { + let TSFlagsFields = []; + let TSFlagsShifts = []; +} + + + +// Not currently supported, but work as SubtargetFeature placeholder. +def FeaturePIC16Old : SubtargetFeature<"pic16old", "IsPIC16Old", "true", + "PIC16 Old ISA Support">; + +//===----------------------------------------------------------------------===// +// PIC16 processors supported. +//===----------------------------------------------------------------------===// + +def : Processor<"generic", NoItineraries, []>; + +def PIC16 : Target { + let InstructionSet = PIC16InstrInfo; +} + diff --git a/lib/Target/PIC16/PIC16AsmPrinter.cpp b/lib/Target/PIC16/PIC16AsmPrinter.cpp new file mode 100644 index 0000000000..151fafc4c5 --- /dev/null +++ b/lib/Target/PIC16/PIC16AsmPrinter.cpp @@ -0,0 +1,569 @@ +//===-- 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. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "PIC16.h" +#include "PIC16TargetMachine.h" +#include "PIC16ConstantPoolValue.h" +#include "PIC16InstrInfo.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/ADT/SetVector.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetOptions.h" +#include <cctype> + +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +namespace { + struct VISIBILITY_HIDDEN PIC16AsmPrinter : public AsmPrinter { + PIC16AsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T) + : AsmPrinter(O, TM, T) { + } + + + /// We name each basic block in a Function with a unique number, so + /// that we can consistently refer to them later. This is cleared + /// at the beginning of each call to runOnMachineFunction(). + /// + typedef std::map<const Value *, unsigned> ValueMapTy; + ValueMapTy NumberForBB; + + /// Keeps the set of GlobalValues that require non-lazy-pointers for + /// indirect access. + std::set<std::string> GVNonLazyPtrs; + + /// Keeps the set of external function GlobalAddresses that the asm + /// printer should generate stubs for. + std::set<std::string> FnStubs; + + /// True if asm printer is printing a series of CONSTPOOL_ENTRY. + bool InCPMode; + + virtual const char *getPassName() const { + return "PIC16 Assembly Printer"; + } + + void printOperand(const MachineInstr *MI, int opNum, + const char *Modifier = 0); + + void printSOImmOperand(const MachineInstr *MI, int opNum); + + void printAddrModeOperand(const MachineInstr *MI, int OpNo); + + void printRegisterList(const MachineInstr *MI, int opNum); + void printCPInstOperand(const MachineInstr *MI, int opNum, + const char *Modifier); + + + bool printInstruction(const MachineInstr *MI); // autogenerated. + void emitFunctionStart(MachineFunction &F); + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); + + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); + + void getAnalysisUsage(AnalysisUsage &AU) const; + + public: + void SwitchToTextSection(const char *NewSection, + const GlobalValue *GV = NULL); + void SwitchToDataSection(const char *NewSection, + const GlobalValue *GV = NULL); + void SwitchToDataOvrSection(const char *NewSection, + const GlobalValue *GV = NULL); + }; +} // end of anonymous namespace + +#include "PIC16GenAsmWriter.inc" + +/// createPIC16CodePrinterPass - Returns a pass that prints the PIC16 +/// assembly code for a MachineFunction to the given output stream, +/// using the given target machine description. This should work +/// regardless of whether the function is in SSA form. +/// +FunctionPass *llvm::createPIC16CodePrinterPass(std::ostream &o, + PIC16TargetMachine &tm) { + return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo()); +} + +void PIC16AsmPrinter::getAnalysisUsage(AnalysisUsage &AU) const +{ + // Currently unimplemented. +} + + +void PIC16AsmPrinter :: +EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) +{ + printDataDirective(MCPV->getType()); + + PIC16ConstantPoolValue *ACPV = (PIC16ConstantPoolValue*)MCPV; + GlobalValue *GV = ACPV->getGV(); + std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix(); + if (!GV) + Name += ACPV->getSymbol(); + if (ACPV->isNonLazyPointer()) { + GVNonLazyPtrs.insert(Name); + O << TAI->getPrivateGlobalPrefix() << Name << "$non_lazy_ptr"; + } else if (ACPV->isStub()) { + FnStubs.insert(Name); + O << TAI->getPrivateGlobalPrefix() << Name << "$stub"; + } else + O << Name; + if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")"; + + if (ACPV->getPCAdjustment() != 0) { + O << "-(" << TAI->getPrivateGlobalPrefix() << "PC" + << utostr(ACPV->getLabelId()) + << "+" << (unsigned)ACPV->getPCAdjustment(); + + if (ACPV->mustAddCurrentAddress()) + O << "-."; + + O << ")"; + } + O << "\n"; + + // If the constant pool value is a extern weak symbol, remember to emit + // the weak reference. + if (GV && GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); +} + +/// Emit the directives used by ASM on the start of functions +void PIC16AsmPrinter:: emitFunctionStart(MachineFunction &MF) +{ + // Print out the label for the function. + const Function *F = MF.getFunction(); + MachineFrameInfo *FrameInfo = MF.getFrameInfo(); + if (FrameInfo->hasStackObjects()) { + int indexBegin = FrameInfo->getObjectIndexBegin(); + int indexEnd = FrameInfo->getObjectIndexEnd(); + while (indexBegin<indexEnd) { + if (indexBegin ==0) + SwitchToDataOvrSection(F->getParent()->getModuleIdentifier().c_str(), + F); + + O << "\t\t" << CurrentFnName << "_" << indexBegin << " " << "RES" + << " " << FrameInfo->getObjectSize(indexBegin) << "\n" ; + indexBegin++; + } + } + SwitchToTextSection(CurrentFnName.c_str(), F); + O << "_" << CurrentFnName << ":" ; + O << "\n"; +} + + +/// runOnMachineFunction - This uses the printInstruction() +/// method to print assembly for each instruction. +/// +bool PIC16AsmPrinter:: +runOnMachineFunction(MachineFunction &MF) +{ + + // DW.SetModuleInfo(&getAnalysis<MachineModuleInfo>()); + SetupMachineFunction(MF); + O << "\n"; + + // NOTE: we don't print out constant pools here, they are handled as + // instructions. + O << "\n"; + + // What's my mangled name? + CurrentFnName = Mang->getValueName(MF.getFunction()); + + // Emit the function start directives + emitFunctionStart(MF); + + // Emit pre-function debug information. + // DW.BeginFunction(&MF); + + // 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()) { + printBasicBlockLabel(I, true); + O << '\n'; + } + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << '\t'; + printInstruction(II); + ++EmittedInsts; + } + } + + // Emit post-function debug information. + // DW.EndFunction(); + + // We didn't modify anything. + return false; +} + +void PIC16AsmPrinter:: +printOperand(const MachineInstr *MI, int opNum, const char *Modifier) +{ + const MachineOperand &MO = MI->getOperand(opNum); + const TargetRegisterInfo &RI = *TM.getRegisterInfo(); + + switch (MO.getType()) + { + case MachineOperand::MO_Register: + { + if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) + O << RI.get(MO.getReg()).Name; + else + assert(0 && "not implemented"); + break; + } + case MachineOperand::MO_Immediate: + { + if (!Modifier || strcmp(Modifier, "no_hash") != 0) + O << "#"; + O << (int)MO.getImm(); + break; + } + case MachineOperand::MO_MachineBasicBlock: + { + printBasicBlockLabel(MO.getMBB()); + return; + } + case MachineOperand::MO_GlobalAddress: + { + O << Mang->getValueName(MO.getGlobal())<<'+'<<MO.getOffset(); + break; + } + case MachineOperand::MO_ExternalSymbol: + { + O << MO.getSymbolName(); + break; + } + case MachineOperand::MO_ConstantPoolIndex: + { + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + } + case MachineOperand::MO_FrameIndex: + { + O << "_" << CurrentFnName + << '+' << MO.getIndex(); + break; + } + case MachineOperand::MO_JumpTableIndex: + { + O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber() + << '_' << MO.getIndex(); + break; + } + default: + { + O << "<unknown operand type>"; abort (); + break; + } + } // end switch. +} + +static void +printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) +{ + assert(V < (1 << 12) && "Not a valid so_imm value!"); + unsigned Imm = V; + + O << Imm; +} + +/// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit +/// immediate in bits 0-7. +void PIC16AsmPrinter:: +printSOImmOperand(const MachineInstr *MI, int OpNum) +{ + const MachineOperand &MO = MI->getOperand(OpNum); + assert(MO.isImmediate() && "Not a valid so_imm value!"); + printSOImm(O, MO.getImm(), TAI); +} + + +void PIC16AsmPrinter:: printAddrModeOperand(const MachineInstr *MI, int Op) +{ + const MachineOperand &MO1 = MI->getOperand(Op); + const MachineOperand &MO2 = MI->getOperand(Op+1); + + if (MO2.isFrameIndex ()) { + printOperand(MI, Op+1); + return; + } + + if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right. + printOperand(MI, Op); + return; + } + + // If this is Stack Slot + if (MO1.isRegister()) { + if(strcmp(TM.getRegisterInfo()->get(MO1.getReg()).Name, "SP")==0) + { + O << CurrentFnName <<"_"<< MO2.getImm(); + return; + } + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; + O << "+"; + O << MO2.getImm(); + O << "]"; + return; + } + + O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).Name; + O << "]"; +} + + +void PIC16AsmPrinter:: printRegisterList(const MachineInstr *MI, int opNum) +{ + O << "{"; + for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) { + printOperand(MI, i); + if (i != e-1) O << ", "; + } + O << "}"; +} + +void PIC16AsmPrinter:: +printCPInstOperand(const MachineInstr *MI, int OpNo, const char *Modifier) +{ + assert(Modifier && "This operand only works with a modifier!"); + + // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the + // data itself. + if (!strcmp(Modifier, "label")) { + unsigned ID = MI->getOperand(OpNo).getImm(); + O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() + << '_' << ID << ":\n"; + } else { + assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE"); + unsigned CPI = MI->getOperand(OpNo).getIndex(); + + const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun? + MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI]; + + if (MCPE.isMachineConstantPoolEntry()) + EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); + else { + EmitGlobalConstant(MCPE.Val.ConstVal); + // remember to emit the weak reference + if (const GlobalValue *GV = dyn_cast<GlobalValue>(MCPE.Val.ConstVal)) + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + } + } +} + + +bool PIC16AsmPrinter:: doInitialization(Module &M) +{ + // Emit initial debug information. + // DW.BeginModule(&M); + + bool Result = AsmPrinter::doInitialization(M); + return Result; +} + +bool PIC16AsmPrinter:: doFinalization(Module &M) +{ + const TargetData *TD = TM.getTargetData(); + + for (Module::const_global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { + if (!I->hasInitializer()) // External global require no code + continue; + + if (EmitSpecialLLVMGlobal(I)) { + continue; + } + + std::string name = Mang->getValueName(I); + Constant *C = I->getInitializer(); + const Type *Type = C->getType(); + unsigned Size = TD->getABITypeSize(Type); + unsigned Align = TD->getPreferredAlignmentLog(I); + + const char *VisibilityDirective = NULL; + if (I->hasHiddenVisibility()) + VisibilityDirective = TAI->getHiddenDirective(); + else if (I->hasProtectedVisibility()) + VisibilityDirective = TAI->getProtectedDirective(); + + if (VisibilityDirective) + O << VisibilityDirective << name << "\n"; + + if (C->isNullValue()) { + if (I->hasExternalLinkage()) { + if (const char *Directive = TAI->getZeroFillDirective()) { + O << "\t.globl\t" << name << "\n"; + O << Directive << "__DATA__, __common, " << name << ", " + << Size << ", " << Align << "\n"; + continue; + } + } + + if (!I->hasSection() && + (I->hasInternalLinkage() || I->hasWeakLinkage() || + I->hasLinkOnceLinkage())) { + if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it. + if (!NoZerosInBSS && TAI->getBSSSection()) + SwitchToDataSection(M.getModuleIdentifier().c_str(), I); + else + SwitchToDataSection(TAI->getDataSection(), I); + if (TAI->getLCOMMDirective() != NULL) { + if (I->hasInternalLinkage()) { + O << TAI->getLCOMMDirective() << name << "," << Size; + } else + O << TAI->getCOMMDirective() << name << "," << Size; + } else { + if (I->hasInternalLinkage()) + O << "\t.local\t" << name << "\n"; + + O << TAI->getCOMMDirective() <<"\t" << name << " " <<"RES"<< " " + << Size; + O << "\n\t\tGLOBAL" <<" "<< name; + if (TAI->getCOMMDirectiveTakesAlignment()) + O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align); + } + continue; + } + } + + switch (I->getLinkage()) + { + case GlobalValue::AppendingLinkage: + { + // FIXME: appending linkage variables should go into a section of + // their name or something. For now, just emit them as external. + // Fall through + } + case GlobalValue::ExternalLinkage: + { + O << "\t.globl " << name << "\n"; + // FALL THROUGH + } + case GlobalValue::InternalLinkage: + { + if (I->isConstant()) { + const ConstantArray *CVA = dyn_cast<ConstantArray>(C); + if (TAI->getCStringSection() && CVA && CVA->isCString()) { + SwitchToDataSection(TAI->getCStringSection(), I); + break; + } + } + break; + } + default: + { + assert(0 && "Unknown linkage type!"); + break; + } + } // end switch. + + EmitAlignment(Align, I); + O << name << ":\t\t\t\t" << TAI->getCommentString() << " " << I->getName() + << "\n"; + + // If the initializer is a extern weak symbol, remember to emit the weak + // reference! + if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + + EmitGlobalConstant(C); + O << '\n'; + } // end for. + + O << "\n "<< "END"; + return AsmPrinter::doFinalization(M); +} + +void PIC16AsmPrinter:: +SwitchToTextSection(const char *NewSection, const GlobalValue *GV) +{ + O << "\n"; + if (NewSection && *NewSection) { + std::string codeSection = "code_"; + codeSection += NewSection; + codeSection += " "; + codeSection += "CODE"; + AsmPrinter::SwitchToTextSection(codeSection.c_str(),GV); + } + else + AsmPrinter::SwitchToTextSection(NewSection,GV); +} + +void PIC16AsmPrinter:: +SwitchToDataSection(const char *NewSection, const GlobalValue *GV) +{ + //Need to append index for page + O << "\n"; + if (NewSection && *NewSection) { + std::string dataSection ="udata_"; + dataSection+=NewSection; + if (dataSection.substr(dataSection.length()-2).compare(".o") == 0) { + dataSection = dataSection.substr(0,dataSection.length()-2); + } + dataSection += " "; + dataSection += "UDATA"; + AsmPrinter::SwitchToDataSection(dataSection.c_str(),GV); + } + else + AsmPrinter::SwitchToDataSection(NewSection,GV); +} + +void PIC16AsmPrinter:: +SwitchToDataOvrSection(const char *NewSection, const GlobalValue *GV) +{ + O << "\n"; + if (NewSection && *NewSection) { + std::string dataSection = "frame_"; + dataSection += NewSection; + if (dataSection.substr(dataSection.length()-2).compare(".o") == 0) { + dataSection = dataSection.substr(0,dataSection.length()-2); + } + dataSection += "_"; + dataSection += CurrentFnName; + dataSection += " "; + dataSection += "UDATA_OVR"; + AsmPrinter::SwitchToDataSection(dataSection.c_str(),GV); + } + else + AsmPrinter::SwitchToDataSection(NewSection,GV); +} diff --git a/lib/Target/PIC16/PIC16CallingConv.td b/lib/Target/PIC16/PIC16CallingConv.td new file mode 100644 index 0000000000..bcd5f7c83d --- /dev/null +++ b/lib/Target/PIC16/PIC16CallingConv.td @@ -0,0 +1,17 @@ +//===- PIC16CallingConv.td - Calling Conventions Sparc -----*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This describes the calling conventions for the PIC16 architectures. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Return Value Calling Conventions +//===----------------------------------------------------------------------===// + diff --git a/lib/Target/PIC16/PIC16ConstantPoolValue.cpp b/lib/Target/PIC16/PIC16ConstantPoolValue.cpp new file mode 100644 index 0000000000..6e324f9e4d --- /dev/null +++ b/lib/Target/PIC16/PIC16ConstantPoolValue.cpp @@ -0,0 +1,88 @@ +//===- PIC16ConstantPoolValue.cpp - PIC16 constantpool value --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the PIC16 specific constantpool value class. +// +//===----------------------------------------------------------------------===// + +#include "PIC16ConstantPoolValue.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/GlobalValue.h" +#include "llvm/Type.h" +using namespace llvm; + +PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv, unsigned id, + PIC16CP::PIC16CPKind k, + unsigned char PCAdj, + const char *Modif, bool AddCA) + : MachineConstantPoolValue((const Type*)gv->getType()), + GV(gv), S(NULL), LabelId(id), Kind(k), PCAdjust(PCAdj), + Modifier(Modif), AddCurrentAddress(AddCA) {} + +PIC16ConstantPoolValue::PIC16ConstantPoolValue(const char *s, unsigned id, + PIC16CP::PIC16CPKind k, + unsigned char PCAdj, + const char *Modif, bool AddCA) + : MachineConstantPoolValue((const Type*)Type::Int32Ty), + GV(NULL), S(s), LabelId(id), Kind(k), PCAdjust(PCAdj), + Modifier(Modif), AddCurrentAddress(AddCA) {} + +PIC16ConstantPoolValue::PIC16ConstantPoolValue(GlobalValue *gv, + PIC16CP::PIC16CPKind k, + const char *Modif) + : MachineConstantPoolValue((const Type*)Type::Int32Ty), + GV(gv), S(NULL), LabelId(0), Kind(k), PCAdjust(0), + Modifier(Modif) {} + +int PIC16ConstantPoolValue::getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) { + unsigned AlignMask = (1 << Alignment)-1; + const std::vector<MachineConstantPoolEntry> Constants = CP->getConstants(); + for (unsigned i = 0, e = Constants.size(); i != e; ++i) { + if (Constants[i].isMachineConstantPoolEntry() && + (Constants[i].Offset & AlignMask) == 0) { + PIC16ConstantPoolValue *CPV = + (PIC16ConstantPoolValue *)Constants[i].Val.MachineCPVal; + if (CPV->GV == GV && + CPV->S == S && + CPV->LabelId == LabelId && + CPV->Kind == Kind && + CPV->PCAdjust == PCAdjust) + return i; + } + } + + return -1; +} + +void +PIC16ConstantPoolValue::AddSelectionDAGCSEId(FoldingSetNodeID &ID) { + ID.AddPointer(GV); + ID.AddPointer(S); + ID.AddInteger(LabelId); + ID.AddInteger((unsigned)Kind); + ID.AddInteger(PCAdjust); +} + +void PIC16ConstantPoolValue::print(std::ostream &O) const { + if (GV) + O << GV->getName(); + else + O << S; + if (isNonLazyPointer()) O << "$non_lazy_ptr"; + else if (isStub()) O << "$stub"; + if (Modifier) O << "(" << Modifier << ")"; + if (PCAdjust != 0) { + O << "-(LPIC" << LabelId << "+" + << (unsigned)PCAdjust; + if (AddCurrentAddress) + O << "-."; + O << ")"; + } +} diff --git a/lib/Target/PIC16/PIC16ConstantPoolValue.h b/lib/Target/PIC16/PIC16ConstantPoolValue.h new file mode 100644 index 0000000000..04d4a17e68 --- /dev/null +++ b/lib/Target/PIC16/PIC16ConstantPoolValue.h @@ -0,0 +1,75 @@ +//===- PIC16ConstantPoolValue.h - PIC16 constantpool value ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the PIC16 specific constantpool value class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_PIC16_CONSTANTPOOLVALUE_H +#define LLVM_TARGET_PIC16_CONSTANTPOOLVALUE_H + +#include "llvm/CodeGen/MachineConstantPool.h" + +namespace llvm { + +namespace PIC16CP { + enum PIC16CPKind { + CPValue, + CPNonLazyPtr, + CPStub + }; +} + +/// PIC16ConstantPoolValue - PIC16 specific constantpool value. This is used to +/// represent PC relative displacement between the address of the load +/// instruction and the global value being loaded, i.e. (&GV-(LPIC+8)). +class PIC16ConstantPoolValue : public MachineConstantPoolValue { + GlobalValue *GV; // GlobalValue being loaded. + const char *S; // ExtSymbol being loaded. + unsigned LabelId; // Label id of the load. + PIC16CP::PIC16CPKind Kind; // non_lazy_ptr or stub? + unsigned char PCAdjust; // Extra adjustment if constantpool is pc relative. + // 8 for PIC16 + const char *Modifier; // GV modifier i.e. (&GV(modifier)-(LPIC+8)) + bool AddCurrentAddress; + +public: + PIC16ConstantPoolValue(GlobalValue *gv, unsigned id, + PIC16CP::PIC16CPKind Kind = PIC16CP::CPValue, + unsigned char PCAdj = 0, const char *Modifier = NULL, + bool AddCurrentAddress = false); + PIC16ConstantPoolValue(const char *s, unsigned id, + PIC16CP::PIC16CPKind Kind = PIC16CP::CPValue,< |