PIC16AsmPrinter.cpp [plain text]
#include "PIC16AsmPrinter.h"
#include "PIC16TargetAsmInfo.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/Support/raw_ostream.h"
#include "llvm/Support/Mangler.h"
#include "llvm/CodeGen/DwarfWriter.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
using namespace llvm;
#include "PIC16GenAsmWriter.inc"
inline static bool isLocalToFunc (std::string &FuncName, std::string &VarName) {
if (VarName.find(FuncName + ".auto.") != std::string::npos
|| VarName.find(FuncName + ".arg.") != std::string::npos)
return true;
return false;
}
inline static bool isLocalName (std::string &Name) {
if (Name.find(".auto.") != std::string::npos
|| Name.find(".arg.") != std::string::npos)
return true;
return false;
}
bool PIC16AsmPrinter::printMachineInstruction(const MachineInstr *MI) {
std::string NewBank = "";
unsigned Operands = MI->getNumOperands();
if (Operands > 1) {
unsigned BankSelVar = 0;
MachineOperand Op = MI->getOperand(BankSelVar);
while (BankSelVar < Operands-1) {
Op = MI->getOperand(BankSelVar);
if ((Op.getType() == MachineOperand::MO_GlobalAddress) ||
(Op.getType() == MachineOperand::MO_ExternalSymbol))
break;
BankSelVar++;
}
if (BankSelVar < Operands-1) {
unsigned OpType = Op.getType();
if (OpType == MachineOperand::MO_GlobalAddress )
NewBank = Op.getGlobal()->getSection();
else {
std::string ESName = Op.getSymbolName();
int index = ESName.find_first_of(".");
std::string FnName = ESName.substr(0,index);
NewBank = "fpdata." + FnName +".#";
}
const MachineOperand &BS = MI->getOperand(BankSelVar+1);
if ((BS.getType() == MachineOperand::MO_Immediate
&& (int)BS.getImm() == 1)
&& ((Op.isGlobal() && Op.getGlobal()->hasExternalLinkage()) ||
(NewBank.compare(CurBank) != 0))) {
O << "\tbanksel ";
printOperand(MI, BankSelVar);
O << "\n";
CurBank = NewBank;
}
}
}
printInstruction(MI);
return true;
}
bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
this->MF = &MF;
SetupMachineFunction(MF);
const Function *F = MF.getFunction();
CurrentFnName = Mang->getValueName(F);
emitFunctionData(MF);
std::string codeSection;
codeSection = "code." + CurrentFnName + ".# " + "CODE";
const Section *fCodeSection = TAI->getNamedSection(codeSection.c_str(),
SectionFlags::Code);
O << "\n";
SwitchToSection (fCodeSection);
O << " retlw low(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n";
O << " retlw high(" << FunctionLabelBegin<< CurrentFnName << ".frame)\n";
O << CurrentFnName << ":\n";
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
I != E; ++I) {
if (I != MF.begin()) {
printBasicBlockLabel(I, true);
O << '\n';
}
CurBank = "";
unsigned CurLine = 0;
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
II != E; ++II) {
const DebugLoc DL = II->getDebugLoc();
if (!DL.isUnknown()) {
unsigned line = MF.getDebugLocTuple(DL).Line;
if (line != CurLine) {
O << "\t.line " << line << "\n";
CurLine = line;
}
}
printMachineInstruction(II);
}
}
return false; }
FunctionPass *llvm::createPIC16CodePrinterPass(raw_ostream &o,
PIC16TargetMachine &tm,
CodeGenOpt::Level OptLevel,
bool verbose) {
return new PIC16AsmPrinter(o, tm, tm.getTargetAsmInfo(), OptLevel, verbose);
}
void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum) {
const MachineOperand &MO = MI->getOperand(opNum);
switch (MO.getType()) {
case MachineOperand::MO_Register:
if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
else
assert(0 && "not implemented");
return;
case MachineOperand::MO_Immediate:
O << (int)MO.getImm();
return;
case MachineOperand::MO_GlobalAddress: {
std::string Name = Mang->getValueName(MO.getGlobal());
if (isLocalName(Name))
O << FunctionLabelBegin << Mang->getValueName(MO.getGlobal());
else
O << Mang->getValueName(MO.getGlobal());
break;
}
case MachineOperand::MO_ExternalSymbol: {
std::string Name = MO.getSymbolName();
if (Name.find("__intrinsics.") != std::string::npos)
O << MO.getSymbolName();
else
O << FunctionLabelBegin << MO.getSymbolName();
break;
}
case MachineOperand::MO_MachineBasicBlock:
printBasicBlockLabel(MO.getMBB());
return;
default:
assert(0 && " Operand type not supported.");
}
}
void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum) {
int CC = (int)MI->getOperand(opNum).getImm();
O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
}
bool PIC16AsmPrinter::doInitialization (Module &M) {
bool Result = AsmPrinter::doInitialization(M);
O << "\t#include P16F1937.INC\n";
MachineModuleInfo *MMI = getAnalysisIfAvailable<MachineModuleInfo>();
assert(MMI);
DwarfWriter *DW = getAnalysisIfAvailable<DwarfWriter>();
assert(DW && "Dwarf Writer is not available");
DW->BeginModule(&M, MMI, O, this, TAI);
EmitExternsAndGlobals (M);
EmitInitData (M);
EmitUnInitData(M);
EmitRomData(M);
return Result;
}
void PIC16AsmPrinter::EmitExternsAndGlobals (Module &M) {
O << "section.0" <<"\n";
for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
std::string Name = Mang->getValueName(I);
if (Name.compare("abort") == 0)
continue;
if (Name.find("llvm.") != std::string::npos)
continue;
if (I->isDeclaration()) {
O << "\textern " <<Name << "\n";
O << "\textern " << FunctionLabelBegin << Name << ".retval\n";
O << "\textern " << FunctionLabelBegin << Name << ".args\n";
}
else if (I->hasExternalLinkage()) {
O << "\tglobal " << Name << "\n";
O << "\tglobal " << FunctionLabelBegin << Name << ".retval\n";
O << "\tglobal " << FunctionLabelBegin<< Name << ".args\n";
}
}
O << "\t#include C16IntrinsicCalls.INC\n";
for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
I != E; I++) {
std::string Name = Mang->getValueName(I);
if (isLocalName (Name))
continue;
if (I->isDeclaration())
O << "\textern "<< Name << "\n";
else if (I->hasCommonLinkage() || I->hasExternalLinkage())
O << "\tglobal "<< Name << "\n";
}
}
void PIC16AsmPrinter::EmitInitData (Module &M) {
SwitchToSection(TAI->getDataSection());
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasInitializer()) continue;
Constant *C = I->getInitializer();
const PointerType *PtrTy = I->getType();
int AddrSpace = PtrTy->getAddressSpace();
if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::RAM_SPACE)) {
if (EmitSpecialLLVMGlobal(I))
continue;
std::string Name = Mang->getValueName(I);
if (isLocalName(Name))
continue;
I->setSection(TAI->getDataSection()->getName());
O << Name;
EmitGlobalConstant(C, AddrSpace);
}
}
}
void PIC16AsmPrinter::EmitRomData (Module &M)
{
SwitchToSection(TAI->getReadOnlySection());
IsRomData = true;
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasInitializer()) continue;
Constant *C = I->getInitializer();
const PointerType *PtrTy = I->getType();
int AddrSpace = PtrTy->getAddressSpace();
if ((!C->isNullValue()) && (AddrSpace == PIC16ISD::ROM_SPACE)) {
if (EmitSpecialLLVMGlobal(I))
continue;
std::string name = Mang->getValueName(I);
if (name.find(".") != std::string::npos)
continue;
I->setSection(TAI->getReadOnlySection()->getName());
O << name;
EmitGlobalConstant(C, AddrSpace);
O << "\n";
}
}
IsRomData = false;
}
void PIC16AsmPrinter::EmitUnInitData (Module &M)
{
SwitchToSection(TAI->getBSSSection_());
const TargetData *TD = TM.getTargetData();
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
I != E; ++I) {
if (!I->hasInitializer()) continue;
Constant *C = I->getInitializer();
if (C->isNullValue()) {
if (EmitSpecialLLVMGlobal(I))
continue;
std::string name = Mang->getValueName(I);
if (name.find(".") != std::string::npos)
continue;
I->setSection(TAI->getBSSSection_()->getName());
const Type *Ty = C->getType();
unsigned Size = TD->getTypePaddedSize(Ty);
O << name << " " <<"RES"<< " " << Size ;
O << "\n";
}
}
}
bool PIC16AsmPrinter::doFinalization(Module &M) {
O << "\t" << "END\n";
bool Result = AsmPrinter::doFinalization(M);
return Result;
}
void PIC16AsmPrinter::emitFunctionData(MachineFunction &MF) {
const Function *F = MF.getFunction();
std::string FuncName = Mang->getValueName(F);
Module *M = const_cast<Module *>(F->getParent());
const TargetData *TD = TM.getTargetData();
unsigned FrameSize = 0;
O << "\n";
std::string SectionName = "fpdata." + CurrentFnName + ".# " + "UDATA_OVR";
const Section *fPDataSection = TAI->getNamedSection(SectionName.c_str(),
SectionFlags::Writeable);
SwitchToSection(fPDataSection);
O << FunctionLabelBegin << CurrentFnName << ".frame:\n";
const Type *RetType = F->getReturnType();
unsigned RetSize = 0;
if (RetType->getTypeID() != Type::VoidTyID)
RetSize = TD->getTypePaddedSize(RetType);
if(RetSize > 0)
O << FunctionLabelBegin << CurrentFnName << ".retval RES " << RetSize
<< "\n";
else
O << FunctionLabelBegin << CurrentFnName << ".retval:\n";
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->getTypePaddedSize(Ty);
}
O << FunctionLabelBegin << CurrentFnName << ".args RES " << ArgSize
<< "\n";
int TempSize = PTLI->GetTmpSize();
if (TempSize > 0 )
O << FunctionLabelBegin << CurrentFnName << ".tmp RES " << TempSize
<<"\n";
O << "\n";
std::string SecNameLocals = "fadata." + CurrentFnName + ".# " + "UDATA_OVR";
const Section *fADataSection = TAI->getNamedSection(SecNameLocals.c_str(),
SectionFlags::Writeable);
SwitchToSection(fADataSection);
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
I != E; ++I) {
std::string VarName = Mang->getValueName(I);
if (! isLocalToFunc(FuncName, VarName))
continue;
I->setSection("fadata." + CurrentFnName + ".#");
Constant *C = I->getInitializer();
const Type *Ty = C->getType();
unsigned Size = TD->getTypePaddedSize(Ty);
FrameSize += Size;
O << FunctionLabelBegin << VarName << " RES " << Size << "\n";
}
}