forked from OSchip/llvm-project
Per discussion with Sanjiv, remove the PIC16 target from mainline. When/if
it comes back, it will be largely a rewrite, so keeping the old codebase in tree isn't helping anyone. llvm-svn: 116190
This commit is contained in:
parent
29e78ac923
commit
1ef5e84c31
|
@ -64,7 +64,6 @@ set(LLVM_ALL_TARGETS
|
||||||
Mips
|
Mips
|
||||||
MBlaze
|
MBlaze
|
||||||
MSP430
|
MSP430
|
||||||
PIC16
|
|
||||||
PowerPC
|
PowerPC
|
||||||
PTX
|
PTX
|
||||||
Sparc
|
Sparc
|
||||||
|
@ -342,11 +341,6 @@ foreach(t ${LLVM_TARGETS_TO_BUILD})
|
||||||
set(CURRENT_LLVM_TARGET)
|
set(CURRENT_LLVM_TARGET)
|
||||||
endforeach(t)
|
endforeach(t)
|
||||||
|
|
||||||
# PIC16 contains an odd library:
|
|
||||||
if( LLVM_TARGETS_TO_BUILD MATCHES ".*PIC16.*" )
|
|
||||||
add_subdirectory(lib/Target/PIC16/PIC16Passes)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Produce llvm/Config/AsmPrinters.def
|
# Produce llvm/Config/AsmPrinters.def
|
||||||
configure_file(
|
configure_file(
|
||||||
${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/AsmPrinters.def.in
|
${LLVM_MAIN_INCLUDE_DIR}/llvm/Config/AsmPrinters.def.in
|
||||||
|
|
|
@ -197,8 +197,6 @@ elseif (LLVM_NATIVE_ARCH MATCHES "arm")
|
||||||
set(LLVM_NATIVE_ARCH ARM)
|
set(LLVM_NATIVE_ARCH ARM)
|
||||||
elseif (LLVM_NATIVE_ARCH MATCHES "mips")
|
elseif (LLVM_NATIVE_ARCH MATCHES "mips")
|
||||||
set(LLVM_NATIVE_ARCH Mips)
|
set(LLVM_NATIVE_ARCH Mips)
|
||||||
elseif (LLVM_NATIVE_ARCH MATCHES "pic16")
|
|
||||||
set(LLVM_NATIVE_ARCH "PIC16")
|
|
||||||
elseif (LLVM_NATIVE_ARCH MATCHES "xcore")
|
elseif (LLVM_NATIVE_ARCH MATCHES "xcore")
|
||||||
set(LLVM_NATIVE_ARCH XCore)
|
set(LLVM_NATIVE_ARCH XCore)
|
||||||
elseif (LLVM_NATIVE_ARCH MATCHES "msp430")
|
elseif (LLVM_NATIVE_ARCH MATCHES "msp430")
|
||||||
|
|
|
@ -34,7 +34,7 @@ set(MSVC_LIB_DEPS_LLVMMBlazeAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMM
|
||||||
set(MSVC_LIB_DEPS_LLVMMBlazeCodeGen LLVMCodeGen LLVMCore LLVMMBlazeInfo LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
set(MSVC_LIB_DEPS_LLVMMBlazeCodeGen LLVMCodeGen LLVMCore LLVMMBlazeInfo LLVMMC LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||||
set(MSVC_LIB_DEPS_LLVMMBlazeInfo LLVMSupport)
|
set(MSVC_LIB_DEPS_LLVMMBlazeInfo LLVMSupport)
|
||||||
set(MSVC_LIB_DEPS_LLVMMC LLVMSupport LLVMSystem)
|
set(MSVC_LIB_DEPS_LLVMMC LLVMSupport LLVMSystem)
|
||||||
set(MSVC_LIB_DEPS_LLVMMCDisassembler LLVMARMAsmParser LLVMARMCodeGen LLVMARMDisassembler LLVMARMInfo LLVMAlphaAsmPrinter LLVMAlphaCodeGen LLVMAlphaInfo LLVMBlackfinAsmPrinter LLVMBlackfinCodeGen LLVMBlackfinInfo LLVMCBackend LLVMCBackendInfo LLVMCellSPUAsmPrinter LLVMCellSPUCodeGen LLVMCellSPUInfo LLVMCppBackend LLVMCppBackendInfo LLVMMBlazeAsmPrinter LLVMMBlazeCodeGen LLVMMBlazeInfo LLVMMC LLVMMCParser LLVMMSP430CodeGen LLVMMSP430Info LLVMMipsAsmPrinter LLVMMipsCodeGen LLVMMipsInfo LLVMPIC16AsmPrinter LLVMPIC16CodeGen LLVMPIC16Info LLVMPTXAsmPrinter LLVMPTXCodeGen LLVMPTXInfo LLVMPowerPCAsmPrinter LLVMPowerPCCodeGen LLVMPowerPCInfo LLVMSparcAsmPrinter LLVMSparcCodeGen LLVMSparcInfo LLVMSupport LLVMSystem LLVMSystemZAsmPrinter LLVMSystemZCodeGen LLVMSystemZInfo LLVMX86AsmParser LLVMX86CodeGen LLVMX86Disassembler LLVMX86Info LLVMXCoreAsmPrinter LLVMXCoreCodeGen LLVMXCoreInfo)
|
set(MSVC_LIB_DEPS_LLVMMCDisassembler LLVMARMAsmParser LLVMARMCodeGen LLVMARMDisassembler LLVMARMInfo LLVMAlphaAsmPrinter LLVMAlphaCodeGen LLVMAlphaInfo LLVMBlackfinAsmPrinter LLVMBlackfinCodeGen LLVMBlackfinInfo LLVMCBackend LLVMCBackendInfo LLVMCellSPUAsmPrinter LLVMCellSPUCodeGen LLVMCellSPUInfo LLVMCppBackend LLVMCppBackendInfo LLVMMBlazeAsmPrinter LLVMMBlazeCodeGen LLVMMBlazeInfo LLVMMC LLVMMCParser LLVMMSP430CodeGen LLVMMSP430Info LLVMMipsAsmPrinter LLVMMipsCodeGen LLVMMipsInfo LLVMPTXAsmPrinter LLVMPTXCodeGen LLVMPTXInfo LLVMPowerPCAsmPrinter LLVMPowerPCCodeGen LLVMPowerPCInfo LLVMSparcAsmPrinter LLVMSparcCodeGen LLVMSparcInfo LLVMSupport LLVMSystem LLVMSystemZAsmPrinter LLVMSystemZCodeGen LLVMSystemZInfo LLVMX86AsmParser LLVMX86CodeGen LLVMX86Disassembler LLVMX86Info LLVMXCoreAsmPrinter LLVMXCoreCodeGen LLVMXCoreInfo)
|
||||||
set(MSVC_LIB_DEPS_LLVMMCParser LLVMMC LLVMSupport)
|
set(MSVC_LIB_DEPS_LLVMMCParser LLVMMC LLVMSupport)
|
||||||
set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMMC LLVMSupport)
|
set(MSVC_LIB_DEPS_LLVMMSP430AsmPrinter LLVMMC LLVMSupport)
|
||||||
set(MSVC_LIB_DEPS_LLVMMSP430CodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430AsmPrinter LLVMMSP430Info LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
set(MSVC_LIB_DEPS_LLVMMSP430CodeGen LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMSP430AsmPrinter LLVMMSP430Info LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||||
|
@ -42,10 +42,6 @@ set(MSVC_LIB_DEPS_LLVMMSP430Info LLVMSupport)
|
||||||
set(MSVC_LIB_DEPS_LLVMMipsAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsCodeGen LLVMMipsInfo LLVMSupport LLVMTarget)
|
set(MSVC_LIB_DEPS_LLVMMipsAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMMipsCodeGen LLVMMipsInfo LLVMSupport LLVMTarget)
|
||||||
set(MSVC_LIB_DEPS_LLVMMipsCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMMipsInfo LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
set(MSVC_LIB_DEPS_LLVMMipsCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMMipsInfo LLVMSelectionDAG LLVMSupport LLVMSystem LLVMTarget)
|
||||||
set(MSVC_LIB_DEPS_LLVMMipsInfo LLVMSupport)
|
set(MSVC_LIB_DEPS_LLVMMipsInfo LLVMSupport)
|
||||||
set(MSVC_LIB_DEPS_LLVMPIC16AsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMMC LLVMPIC16CodeGen LLVMPIC16Info LLVMSupport LLVMTarget)
|
|
||||||
set(MSVC_LIB_DEPS_LLVMPIC16CodeGen LLVMAnalysis LLVMCodeGen LLVMCore LLVMMC LLVMPIC16Info LLVMSelectionDAG LLVMSupport LLVMTarget)
|
|
||||||
set(MSVC_LIB_DEPS_LLVMPIC16Info LLVMSupport)
|
|
||||||
set(MSVC_LIB_DEPS_LLVMPIC16Passes LLVMCore LLVMSupport LLVMSystem LLVMTransformUtils LLVMipa)
|
|
||||||
set(MSVC_LIB_DEPS_LLVMPTXAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMPTXCodeGen LLVMPTXInfo LLVMSupport)
|
set(MSVC_LIB_DEPS_LLVMPTXAsmPrinter LLVMAsmPrinter LLVMCodeGen LLVMCore LLVMPTXCodeGen LLVMPTXInfo LLVMSupport)
|
||||||
set(MSVC_LIB_DEPS_LLVMPTXCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMPTXInfo LLVMSelectionDAG LLVMSupport LLVMTarget)
|
set(MSVC_LIB_DEPS_LLVMPTXCodeGen LLVMCodeGen LLVMCore LLVMMC LLVMPTXInfo LLVMSelectionDAG LLVMSupport LLVMTarget)
|
||||||
set(MSVC_LIB_DEPS_LLVMPTXInfo LLVMSupport)
|
set(MSVC_LIB_DEPS_LLVMPTXInfo LLVMSupport)
|
||||||
|
|
|
@ -2356,7 +2356,6 @@ else
|
||||||
alpha*-*) llvm_cv_target_arch="Alpha" ;;
|
alpha*-*) llvm_cv_target_arch="Alpha" ;;
|
||||||
arm*-*) llvm_cv_target_arch="ARM" ;;
|
arm*-*) llvm_cv_target_arch="ARM" ;;
|
||||||
mips-*) llvm_cv_target_arch="Mips" ;;
|
mips-*) llvm_cv_target_arch="Mips" ;;
|
||||||
pic16-*) llvm_cv_target_arch="PIC16" ;;
|
|
||||||
xcore-*) llvm_cv_target_arch="XCore" ;;
|
xcore-*) llvm_cv_target_arch="XCore" ;;
|
||||||
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
msp430-*) llvm_cv_target_arch="MSP430" ;;
|
||||||
s390x-*) llvm_cv_target_arch="SystemZ" ;;
|
s390x-*) llvm_cv_target_arch="SystemZ" ;;
|
||||||
|
@ -4817,8 +4816,6 @@ else
|
||||||
ARM) TARGET_HAS_JIT=1
|
ARM) TARGET_HAS_JIT=1
|
||||||
;;
|
;;
|
||||||
Mips) TARGET_HAS_JIT=0
|
Mips) TARGET_HAS_JIT=0
|
||||||
;;
|
|
||||||
PIC16) TARGET_HAS_JIT=0
|
|
||||||
;;
|
;;
|
||||||
XCore) TARGET_HAS_JIT=0
|
XCore) TARGET_HAS_JIT=0
|
||||||
;;
|
;;
|
||||||
|
@ -4959,7 +4956,7 @@ if test "$enableval" = host-only ; then
|
||||||
enableval=host
|
enableval=host
|
||||||
fi
|
fi
|
||||||
case "$enableval" in
|
case "$enableval" in
|
||||||
all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU PIC16 XCore MSP430 SystemZ Blackfin CBackend CppBackend MBlaze PTX" ;;
|
all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha ARM Mips CellSPU XCore MSP430 SystemZ Blackfin CBackend CppBackend MBlaze PTX" ;;
|
||||||
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
*)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do
|
||||||
case "$a_target" in
|
case "$a_target" in
|
||||||
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;;
|
||||||
|
@ -4970,7 +4967,6 @@ case "$enableval" in
|
||||||
arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;;
|
arm) TARGETS_TO_BUILD="ARM $TARGETS_TO_BUILD" ;;
|
||||||
mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||||
spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
||||||
pic16) TARGETS_TO_BUILD="PIC16 $TARGETS_TO_BUILD" ;;
|
|
||||||
xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||||
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||||
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
systemz) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||||
|
@ -4989,7 +4985,6 @@ case "$enableval" in
|
||||||
Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
Mips) TARGETS_TO_BUILD="Mips $TARGETS_TO_BUILD" ;;
|
||||||
MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
MBlaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;;
|
||||||
CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
CellSPU|SPU) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;;
|
||||||
PIC16) TARGETS_TO_BUILD="PIC16 $TARGETS_TO_BUILD" ;;
|
|
||||||
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
XCore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;;
|
||||||
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
MSP430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;;
|
||||||
s390x) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
s390x) TARGETS_TO_BUILD="SystemZ $TARGETS_TO_BUILD" ;;
|
||||||
|
|
|
@ -1103,7 +1103,7 @@ components, please contact us on the <a
|
||||||
href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVMdev list</a>.</p>
|
href="http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev">LLVMdev list</a>.</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The Alpha, Blackfin, CellSPU, MicroBlaze, MSP430, MIPS, PIC16, SystemZ
|
<li>The Alpha, Blackfin, CellSPU, MicroBlaze, MSP430, MIPS, SystemZ
|
||||||
and XCore backends are experimental.</li>
|
and XCore backends are experimental.</li>
|
||||||
<li><tt>llc</tt> "<tt>-filetype=obj</tt>" is experimental on all targets
|
<li><tt>llc</tt> "<tt>-filetype=obj</tt>" is experimental on all targets
|
||||||
other than darwin-i386 and darwin-x86_64.</li>
|
other than darwin-i386 and darwin-x86_64.</li>
|
||||||
|
|
|
@ -32,8 +32,7 @@ namespace llvm {
|
||||||
enum SectionVariant {
|
enum SectionVariant {
|
||||||
SV_COFF = 0,
|
SV_COFF = 0,
|
||||||
SV_ELF,
|
SV_ELF,
|
||||||
SV_MachO,
|
SV_MachO
|
||||||
SV_PIC16
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -297,7 +297,7 @@ ComputeReloadLoc(MachineBasicBlock::iterator const InsertLoc,
|
||||||
const TargetLowering *TL = MF.getTarget().getTargetLowering();
|
const TargetLowering *TL = MF.getTarget().getTargetLowering();
|
||||||
|
|
||||||
if (!TL->isTypeLegal(TL->getPointerTy()))
|
if (!TL->isTypeLegal(TL->getPointerTy()))
|
||||||
// Believe it or not, this is true on PIC16.
|
// Believe it or not, this is true on 16-bit targets like PIC16.
|
||||||
return InsertLoc;
|
return InsertLoc;
|
||||||
|
|
||||||
const TargetRegisterClass *ptrRegClass =
|
const TargetRegisterClass *ptrRegClass =
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
include_directories(
|
|
||||||
${CMAKE_CURRENT_BINARY_DIR}/..
|
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/..
|
|
||||||
)
|
|
||||||
|
|
||||||
add_llvm_library(LLVMPIC16AsmPrinter
|
|
||||||
PIC16AsmPrinter.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_dependencies(LLVMPIC16AsmPrinter PIC16CodeGenTable_gen)
|
|
|
@ -1,15 +0,0 @@
|
||||||
##===- lib/Target/PIC16/AsmPrinter/Makefile ----------------*- Makefile -*-===##
|
|
||||||
#
|
|
||||||
# The LLVM Compiler Infrastructure
|
|
||||||
#
|
|
||||||
# This file is distributed under the University of Illinois Open Source
|
|
||||||
# License. See LICENSE.TXT for details.
|
|
||||||
#
|
|
||||||
##===----------------------------------------------------------------------===##
|
|
||||||
LEVEL = ../../../..
|
|
||||||
LIBRARYNAME = LLVMPIC16AsmPrinter
|
|
||||||
|
|
||||||
# Hack: we need to include 'main' pic16 target directory to grab private headers
|
|
||||||
CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
|
|
||||||
|
|
||||||
include $(LEVEL)/Makefile.common
|
|
|
@ -1,512 +0,0 @@
|
||||||
//===-- PIC16AsmPrinter.cpp - PIC16 LLVM assembly writer ------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains a printer that converts from our internal representation
|
|
||||||
// of machine-dependent LLVM code to PIC16 assembly language.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16ABINames.h"
|
|
||||||
#include "PIC16AsmPrinter.h"
|
|
||||||
#include "PIC16Section.h"
|
|
||||||
#include "PIC16MCAsmInfo.h"
|
|
||||||
#include "PIC16MachineFunctionInfo.h"
|
|
||||||
#include "llvm/DerivedTypes.h"
|
|
||||||
#include "llvm/Function.h"
|
|
||||||
#include "llvm/Module.h"
|
|
||||||
#include "llvm/CodeGen/MachineFrameInfo.h"
|
|
||||||
#include "llvm/CodeGen/MachineModuleInfo.h"
|
|
||||||
#include "llvm/MC/MCStreamer.h"
|
|
||||||
#include "llvm/MC/MCSymbol.h"
|
|
||||||
#include "llvm/Target/Mangler.h"
|
|
||||||
#include "llvm/Target/TargetRegistry.h"
|
|
||||||
#include "llvm/Target/TargetLoweringObjectFile.h"
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
#include "llvm/ADT/SmallString.h"
|
|
||||||
#include <cstring>
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
#include "PIC16GenAsmWriter.inc"
|
|
||||||
|
|
||||||
PIC16AsmPrinter::PIC16AsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
|
|
||||||
: AsmPrinter(TM, Streamer), DbgInfo(Streamer, TM.getMCAsmInfo()) {
|
|
||||||
PMAI = static_cast<const PIC16MCAsmInfo*>(TM.getMCAsmInfo());
|
|
||||||
PTOF = &getObjFileLowering();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16AsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|
||||||
SmallString<128> Str;
|
|
||||||
raw_svector_ostream OS(Str);
|
|
||||||
printInstruction(MI, OS);
|
|
||||||
|
|
||||||
OutStreamer.EmitRawText(OS.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getFunctionColor(const Function *F) {
|
|
||||||
if (F->hasSection()) {
|
|
||||||
std::string Sectn = F->getSection();
|
|
||||||
std::string StrToFind = "Overlay=";
|
|
||||||
std::string::size_type Pos = Sectn.find(StrToFind);
|
|
||||||
|
|
||||||
// Retreive the color number if the key is found.
|
|
||||||
if (Pos != std::string::npos) {
|
|
||||||
Pos += StrToFind.length();
|
|
||||||
std::string Color = "";
|
|
||||||
char c = Sectn.at(Pos);
|
|
||||||
// A Color can only consist of digits.
|
|
||||||
while (c >= '0' && c<= '9') {
|
|
||||||
Color.append(1,c);
|
|
||||||
Pos++;
|
|
||||||
if (Pos >= Sectn.length())
|
|
||||||
break;
|
|
||||||
c = Sectn.at(Pos);
|
|
||||||
}
|
|
||||||
return atoi(Color.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Color was not set for function, so return -1.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Color the Auto section of the given function.
|
|
||||||
void PIC16AsmPrinter::ColorAutoSection(const Function *F) {
|
|
||||||
std::string SectionName = PAN::getAutosSectionName(CurrentFnSym->getName());
|
|
||||||
PIC16Section* Section = PTOF->findPIC16Section(SectionName);
|
|
||||||
if (Section != NULL) {
|
|
||||||
int Color = getFunctionColor(F);
|
|
||||||
if (Color >= 0)
|
|
||||||
Section->setColor(Color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// runOnMachineFunction - This emits the frame section, autos section and
|
|
||||||
/// assembly for each instruction. Also takes care of function begin debug
|
|
||||||
/// directive and file begin debug directive (if required) for the function.
|
|
||||||
///
|
|
||||||
bool PIC16AsmPrinter::runOnMachineFunction(MachineFunction &MF) {
|
|
||||||
// This calls the base class function required to be called at beginning
|
|
||||||
// of runOnMachineFunction.
|
|
||||||
SetupMachineFunction(MF);
|
|
||||||
|
|
||||||
// Put the color information from function to its auto section.
|
|
||||||
const Function *F = MF.getFunction();
|
|
||||||
ColorAutoSection(F);
|
|
||||||
|
|
||||||
// Emit the function frame (args and temps).
|
|
||||||
EmitFunctionFrame(MF);
|
|
||||||
|
|
||||||
DbgInfo.BeginFunction(MF);
|
|
||||||
|
|
||||||
// Now emit the instructions of function in its code section.
|
|
||||||
const MCSection *fCodeSection =
|
|
||||||
getObjFileLowering().SectionForCode(CurrentFnSym->getName(),
|
|
||||||
PAN::isISR(F->getSection()));
|
|
||||||
|
|
||||||
// Start the Code Section.
|
|
||||||
OutStreamer.SwitchSection(fCodeSection);
|
|
||||||
|
|
||||||
// Emit the frame address of the function at the beginning of code.
|
|
||||||
OutStreamer.EmitRawText("\tretlw low(" +
|
|
||||||
Twine(PAN::getFrameLabel(CurrentFnSym->getName())) +
|
|
||||||
")");
|
|
||||||
OutStreamer.EmitRawText("\tretlw high(" +
|
|
||||||
Twine(PAN::getFrameLabel(CurrentFnSym->getName())) +
|
|
||||||
")");
|
|
||||||
|
|
||||||
// Emit function start label.
|
|
||||||
OutStreamer.EmitLabel(CurrentFnSym);
|
|
||||||
|
|
||||||
DebugLoc CurDL;
|
|
||||||
// Print out code for the function.
|
|
||||||
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
|
|
||||||
// Print a label for the basic block.
|
|
||||||
if (I != MF.begin())
|
|
||||||
EmitBasicBlockStart(I);
|
|
||||||
|
|
||||||
// Print a basic block.
|
|
||||||
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
|
|
||||||
II != E; ++II) {
|
|
||||||
// Emit the line directive if source line changed.
|
|
||||||
DebugLoc DL = II->getDebugLoc();
|
|
||||||
if (!DL.isUnknown() && DL != CurDL) {
|
|
||||||
DbgInfo.ChangeDebugLoc(MF, DL);
|
|
||||||
CurDL = DL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print the assembly for the instruction.
|
|
||||||
EmitInstruction(II);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit function end debug directives.
|
|
||||||
DbgInfo.EndFunction(MF);
|
|
||||||
|
|
||||||
return false; // we didn't modify anything.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// printOperand - print operand of insn.
|
|
||||||
void PIC16AsmPrinter::printOperand(const MachineInstr *MI, int opNum,
|
|
||||||
raw_ostream &O) {
|
|
||||||
const MachineOperand &MO = MI->getOperand(opNum);
|
|
||||||
const Function *F = MI->getParent()->getParent()->getFunction();
|
|
||||||
|
|
||||||
switch (MO.getType()) {
|
|
||||||
case MachineOperand::MO_Register:
|
|
||||||
{
|
|
||||||
// For indirect load/store insns, the fsr name is printed as INDF.
|
|
||||||
std::string RegName = getRegisterName(MO.getReg());
|
|
||||||
if ((MI->getOpcode() == PIC16::load_indirect) ||
|
|
||||||
(MI->getOpcode() == PIC16::store_indirect))
|
|
||||||
RegName.replace (0, 3, "INDF");
|
|
||||||
O << RegName;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
|
|
||||||
case MachineOperand::MO_Immediate:
|
|
||||||
O << (int)MO.getImm();
|
|
||||||
return;
|
|
||||||
|
|
||||||
case MachineOperand::MO_GlobalAddress: {
|
|
||||||
MCSymbol *Sym = Mang->getSymbol(MO.getGlobal());
|
|
||||||
// FIXME: currently we do not have a memcpy def coming in the module
|
|
||||||
// by any chance, as we do not link in those as .bc lib. So these calls
|
|
||||||
// are always external and it is safe to emit an extern.
|
|
||||||
if (PAN::isMemIntrinsic(Sym->getName()))
|
|
||||||
LibcallDecls.insert(Sym->getName());
|
|
||||||
|
|
||||||
O << *Sym;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MachineOperand::MO_ExternalSymbol: {
|
|
||||||
const char *Sname = MO.getSymbolName();
|
|
||||||
std::string Printname = Sname;
|
|
||||||
|
|
||||||
// Intrinsic stuff needs to be renamed if we are printing IL fn.
|
|
||||||
if (PAN::isIntrinsicStuff(Printname)) {
|
|
||||||
if (PAN::isISR(F->getSection())) {
|
|
||||||
Printname = PAN::Rename(Sname);
|
|
||||||
}
|
|
||||||
// Record these decls, we need to print them in asm as extern.
|
|
||||||
LibcallDecls.insert(Printname);
|
|
||||||
}
|
|
||||||
|
|
||||||
O << Printname;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case MachineOperand::MO_MachineBasicBlock:
|
|
||||||
O << *MO.getMBB()->getSymbol();
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
llvm_unreachable(" Operand type not supported.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// printCCOperand - Print the cond code operand.
|
|
||||||
///
|
|
||||||
void PIC16AsmPrinter::printCCOperand(const MachineInstr *MI, int opNum,
|
|
||||||
raw_ostream &O) {
|
|
||||||
int CC = (int)MI->getOperand(opNum).getImm();
|
|
||||||
O << PIC16CondCodeToString((PIC16CC::CondCodes)CC);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// printLibcallDecls - print the extern declarations for compiler
|
|
||||||
/// intrinsics.
|
|
||||||
///
|
|
||||||
void PIC16AsmPrinter::printLibcallDecls() {
|
|
||||||
// If no libcalls used, return.
|
|
||||||
if (LibcallDecls.empty()) return;
|
|
||||||
|
|
||||||
OutStreamer.AddComment("External decls for libcalls - BEGIN");
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
|
|
||||||
for (std::set<std::string>::const_iterator I = LibcallDecls.begin(),
|
|
||||||
E = LibcallDecls.end(); I != E; I++)
|
|
||||||
OutStreamer.EmitRawText(MAI->getExternDirective() + Twine(*I));
|
|
||||||
|
|
||||||
OutStreamer.AddComment("External decls for libcalls - END");
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// doInitialization - Perform Module level initializations here.
|
|
||||||
/// One task that we do here is to sectionize all global variables.
|
|
||||||
/// The MemSelOptimizer pass depends on the sectionizing.
|
|
||||||
///
|
|
||||||
bool PIC16AsmPrinter::doInitialization(Module &M) {
|
|
||||||
bool Result = AsmPrinter::doInitialization(M);
|
|
||||||
|
|
||||||
// Every asmbly contains these std headers.
|
|
||||||
OutStreamer.EmitRawText(StringRef("\n#include p16f1xxx.inc"));
|
|
||||||
OutStreamer.EmitRawText(StringRef("#include stdmacros.inc"));
|
|
||||||
|
|
||||||
// Set the section names for all globals.
|
|
||||||
for (Module::global_iterator I = M.global_begin(), E = M.global_end();
|
|
||||||
I != E; ++I) {
|
|
||||||
|
|
||||||
// Record External Var Decls.
|
|
||||||
if (I->isDeclaration()) {
|
|
||||||
ExternalVarDecls.push_back(I);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Record Exteranl Var Defs.
|
|
||||||
if (I->hasExternalLinkage() || I->hasCommonLinkage()) {
|
|
||||||
ExternalVarDefs.push_back(I);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sectionify actual data.
|
|
||||||
if (!I->hasAvailableExternallyLinkage()) {
|
|
||||||
const MCSection *S = getObjFileLowering().SectionForGlobal(I, Mang, TM);
|
|
||||||
|
|
||||||
I->setSection(((const PIC16Section *)S)->getName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DbgInfo.BeginModule(M);
|
|
||||||
EmitFunctionDecls(M);
|
|
||||||
EmitUndefinedVars(M);
|
|
||||||
EmitDefinedVars(M);
|
|
||||||
EmitIData(M);
|
|
||||||
EmitUData(M);
|
|
||||||
EmitRomData(M);
|
|
||||||
EmitSharedUdata(M);
|
|
||||||
EmitUserSections(M);
|
|
||||||
return Result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Emit extern decls for functions imported from other modules, and emit
|
|
||||||
/// global declarations for function defined in this module and which are
|
|
||||||
/// available to other modules.
|
|
||||||
///
|
|
||||||
void PIC16AsmPrinter::EmitFunctionDecls(Module &M) {
|
|
||||||
// Emit declarations for external functions.
|
|
||||||
OutStreamer.AddComment("Function Declarations - BEGIN");
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
for (Module::iterator I = M.begin(), E = M.end(); I != E; I++) {
|
|
||||||
if (I->isIntrinsic() || I->getName() == "@abort")
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!I->isDeclaration() && !I->hasExternalLinkage())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
MCSymbol *Sym = Mang->getSymbol(I);
|
|
||||||
|
|
||||||
// Do not emit memcpy, memset, and memmove here.
|
|
||||||
// Calls to these routines can be generated in two ways,
|
|
||||||
// 1. User calling the standard lib function
|
|
||||||
// 2. Codegen generating these calls for llvm intrinsics.
|
|
||||||
// In the first case a prototype is alread availale, while in
|
|
||||||
// second case the call is via and externalsym and the prototype is missing.
|
|
||||||
// So declarations for these are currently always getting printing by
|
|
||||||
// tracking both kind of references in printInstrunction.
|
|
||||||
if (I->isDeclaration() && PAN::isMemIntrinsic(Sym->getName())) continue;
|
|
||||||
|
|
||||||
const char *directive = I->isDeclaration() ? MAI->getExternDirective() :
|
|
||||||
MAI->getGlobalDirective();
|
|
||||||
|
|
||||||
OutStreamer.EmitRawText(directive + Twine(Sym->getName()));
|
|
||||||
OutStreamer.EmitRawText(directive +
|
|
||||||
Twine(PAN::getRetvalLabel(Sym->getName())));
|
|
||||||
OutStreamer.EmitRawText(directive +
|
|
||||||
Twine(PAN::getArgsLabel(Sym->getName())));
|
|
||||||
}
|
|
||||||
|
|
||||||
OutStreamer.AddComment("Function Declarations - END");
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit variables imported from other Modules.
|
|
||||||
void PIC16AsmPrinter::EmitUndefinedVars(Module &M) {
|
|
||||||
std::vector<const GlobalVariable*> Items = ExternalVarDecls;
|
|
||||||
if (!Items.size()) return;
|
|
||||||
|
|
||||||
OutStreamer.AddComment("Imported Variables - BEGIN");
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
for (unsigned j = 0; j < Items.size(); j++)
|
|
||||||
OutStreamer.EmitRawText(MAI->getExternDirective() +
|
|
||||||
Twine(Mang->getSymbol(Items[j])->getName()));
|
|
||||||
|
|
||||||
OutStreamer.AddComment("Imported Variables - END");
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit variables defined in this module and are available to other modules.
|
|
||||||
void PIC16AsmPrinter::EmitDefinedVars(Module &M) {
|
|
||||||
std::vector<const GlobalVariable*> Items = ExternalVarDefs;
|
|
||||||
if (!Items.size()) return;
|
|
||||||
|
|
||||||
OutStreamer.AddComment("Exported Variables - BEGIN");
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
|
|
||||||
for (unsigned j = 0; j < Items.size(); j++)
|
|
||||||
OutStreamer.EmitRawText(MAI->getGlobalDirective() +
|
|
||||||
Twine(Mang->getSymbol(Items[j])->getName()));
|
|
||||||
OutStreamer.AddComment("Exported Variables - END");
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit initialized data placed in ROM.
|
|
||||||
void PIC16AsmPrinter::EmitRomData(Module &M) {
|
|
||||||
EmitSingleSection(PTOF->ROMDATASection());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit Shared section udata.
|
|
||||||
void PIC16AsmPrinter::EmitSharedUdata(Module &M) {
|
|
||||||
EmitSingleSection(PTOF->SHAREDUDATASection());
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PIC16AsmPrinter::doFinalization(Module &M) {
|
|
||||||
EmitAllAutos(M);
|
|
||||||
printLibcallDecls();
|
|
||||||
DbgInfo.EndModule(M);
|
|
||||||
OutStreamer.EmitRawText(StringRef("\tEND"));
|
|
||||||
return AsmPrinter::doFinalization(M);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16AsmPrinter::EmitFunctionFrame(MachineFunction &MF) {
|
|
||||||
const Function *F = MF.getFunction();
|
|
||||||
const TargetData *TD = TM.getTargetData();
|
|
||||||
PIC16MachineFunctionInfo *FuncInfo = MF.getInfo<PIC16MachineFunctionInfo>();
|
|
||||||
|
|
||||||
// Emit the data section name.
|
|
||||||
|
|
||||||
PIC16Section *fPDataSection =
|
|
||||||
const_cast<PIC16Section *>(getObjFileLowering().
|
|
||||||
SectionForFrame(CurrentFnSym->getName()));
|
|
||||||
|
|
||||||
fPDataSection->setColor(getFunctionColor(F));
|
|
||||||
OutStreamer.SwitchSection(fPDataSection);
|
|
||||||
|
|
||||||
// Emit function frame label
|
|
||||||
OutStreamer.EmitRawText(PAN::getFrameLabel(CurrentFnSym->getName()) +
|
|
||||||
Twine(":"));
|
|
||||||
|
|
||||||
const Type *RetType = F->getReturnType();
|
|
||||||
unsigned RetSize = 0;
|
|
||||||
if (RetType->getTypeID() != Type::VoidTyID)
|
|
||||||
RetSize = TD->getTypeAllocSize(RetType);
|
|
||||||
|
|
||||||
//Emit function return value space
|
|
||||||
// FIXME: Do not emit RetvalLable when retsize is zero. To do this
|
|
||||||
// we will need to avoid printing a global directive for Retval label
|
|
||||||
// in emitExternandGloblas.
|
|
||||||
if(RetSize > 0)
|
|
||||||
OutStreamer.EmitRawText(PAN::getRetvalLabel(CurrentFnSym->getName()) +
|
|
||||||
Twine(" RES ") + Twine(RetSize));
|
|
||||||
else
|
|
||||||
OutStreamer.EmitRawText(PAN::getRetvalLabel(CurrentFnSym->getName()) +
|
|
||||||
Twine(":"));
|
|
||||||
|
|
||||||
// Emit variable to hold the space for function arguments
|
|
||||||
unsigned ArgSize = 0;
|
|
||||||
for (Function::const_arg_iterator argi = F->arg_begin(),
|
|
||||||
arge = F->arg_end(); argi != arge ; ++argi) {
|
|
||||||
const Type *Ty = argi->getType();
|
|
||||||
ArgSize += TD->getTypeAllocSize(Ty);
|
|
||||||
}
|
|
||||||
|
|
||||||
OutStreamer.EmitRawText(PAN::getArgsLabel(CurrentFnSym->getName()) +
|
|
||||||
Twine(" RES ") + Twine(ArgSize));
|
|
||||||
|
|
||||||
// Emit temporary space
|
|
||||||
int TempSize = FuncInfo->getTmpSize();
|
|
||||||
if (TempSize > 0)
|
|
||||||
OutStreamer.EmitRawText(PAN::getTempdataLabel(CurrentFnSym->getName()) +
|
|
||||||
Twine(" RES ") + Twine(TempSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIC16AsmPrinter::EmitInitializedDataSection(const PIC16Section *S) {
|
|
||||||
/// Emit Section header.
|
|
||||||
OutStreamer.SwitchSection(S);
|
|
||||||
|
|
||||||
std::vector<const GlobalVariable*> Items = S->Items;
|
|
||||||
for (unsigned j = 0; j < Items.size(); j++) {
|
|
||||||
Constant *C = Items[j]->getInitializer();
|
|
||||||
int AddrSpace = Items[j]->getType()->getAddressSpace();
|
|
||||||
OutStreamer.EmitRawText(Mang->getSymbol(Items[j])->getName());
|
|
||||||
EmitGlobalConstant(C, AddrSpace);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print all IDATA sections.
|
|
||||||
void PIC16AsmPrinter::EmitIData(Module &M) {
|
|
||||||
EmitSectionList (M, PTOF->IDATASections());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16AsmPrinter::
|
|
||||||
EmitUninitializedDataSection(const PIC16Section *S) {
|
|
||||||
const TargetData *TD = TM.getTargetData();
|
|
||||||
OutStreamer.SwitchSection(S);
|
|
||||||
std::vector<const GlobalVariable*> Items = S->Items;
|
|
||||||
for (unsigned j = 0; j < Items.size(); j++) {
|
|
||||||
Constant *C = Items[j]->getInitializer();
|
|
||||||
const Type *Ty = C->getType();
|
|
||||||
unsigned Size = TD->getTypeAllocSize(Ty);
|
|
||||||
OutStreamer.EmitRawText(Mang->getSymbol(Items[j])->getName() +
|
|
||||||
Twine(" RES ") + Twine(Size));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print all UDATA sections.
|
|
||||||
void PIC16AsmPrinter::EmitUData(Module &M) {
|
|
||||||
EmitSectionList (M, PTOF->UDATASections());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print all USER sections.
|
|
||||||
void PIC16AsmPrinter::EmitUserSections(Module &M) {
|
|
||||||
EmitSectionList (M, PTOF->USERSections());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print all AUTO sections.
|
|
||||||
void PIC16AsmPrinter::EmitAllAutos(Module &M) {
|
|
||||||
EmitSectionList (M, PTOF->AUTOSections());
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" void LLVMInitializePIC16AsmPrinter() {
|
|
||||||
RegisterAsmPrinter<PIC16AsmPrinter> X(ThePIC16Target);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit one data section using correct section emitter based on section type.
|
|
||||||
void PIC16AsmPrinter::EmitSingleSection(const PIC16Section *S) {
|
|
||||||
if (S == NULL) return;
|
|
||||||
|
|
||||||
switch (S->getType()) {
|
|
||||||
default: llvm_unreachable ("unknow user section type");
|
|
||||||
case UDATA:
|
|
||||||
case UDATA_SHR:
|
|
||||||
case UDATA_OVR:
|
|
||||||
EmitUninitializedDataSection(S);
|
|
||||||
break;
|
|
||||||
case IDATA:
|
|
||||||
case ROMDATA:
|
|
||||||
EmitInitializedDataSection(S);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emit a list of sections.
|
|
||||||
void PIC16AsmPrinter::
|
|
||||||
EmitSectionList(Module &M, const std::vector<PIC16Section *> &SList) {
|
|
||||||
for (unsigned i = 0; i < SList.size(); i++) {
|
|
||||||
// Exclude llvm specific metadata sections.
|
|
||||||
if (SList[i]->getName().find("llvm.") != std::string::npos)
|
|
||||||
continue;
|
|
||||||
OutStreamer.AddBlankLine();
|
|
||||||
EmitSingleSection(SList[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,88 +0,0 @@
|
||||||
//===-- PIC16AsmPrinter.h - PIC16 LLVM assembly writer ----------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains a printer that converts from our internal representation
|
|
||||||
// of machine-dependent LLVM code to PIC16 assembly language.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16ASMPRINTER_H
|
|
||||||
#define PIC16ASMPRINTER_H
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16TargetMachine.h"
|
|
||||||
#include "PIC16DebugInfo.h"
|
|
||||||
#include "PIC16MCAsmInfo.h"
|
|
||||||
#include "PIC16TargetObjectFile.h"
|
|
||||||
#include "llvm/Analysis/DebugInfo.h"
|
|
||||||
#include "llvm/CodeGen/AsmPrinter.h"
|
|
||||||
#include "llvm/Support/CommandLine.h"
|
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
#include <list>
|
|
||||||
#include <set>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
class LLVM_LIBRARY_VISIBILITY PIC16AsmPrinter : public AsmPrinter {
|
|
||||||
public:
|
|
||||||
explicit PIC16AsmPrinter(TargetMachine &TM, MCStreamer &Streamer);
|
|
||||||
private:
|
|
||||||
virtual const char *getPassName() const {
|
|
||||||
return "PIC16 Assembly Printer";
|
|
||||||
}
|
|
||||||
|
|
||||||
const PIC16TargetObjectFile &getObjFileLowering() const {
|
|
||||||
return (const PIC16TargetObjectFile &)AsmPrinter::getObjFileLowering();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool runOnMachineFunction(MachineFunction &F);
|
|
||||||
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
|
|
||||||
void printCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
|
|
||||||
void printInstruction(const MachineInstr *MI, raw_ostream &O);
|
|
||||||
static const char *getRegisterName(unsigned RegNo);
|
|
||||||
|
|
||||||
void EmitInstruction(const MachineInstr *MI);
|
|
||||||
void EmitFunctionDecls (Module &M);
|
|
||||||
void EmitUndefinedVars (Module &M);
|
|
||||||
void EmitDefinedVars (Module &M);
|
|
||||||
void EmitIData (Module &M);
|
|
||||||
void EmitUData (Module &M);
|
|
||||||
void EmitAllAutos (Module &M);
|
|
||||||
void EmitRomData (Module &M);
|
|
||||||
void EmitSharedUdata(Module &M);
|
|
||||||
void EmitUserSections (Module &M);
|
|
||||||
void EmitFunctionFrame(MachineFunction &MF);
|
|
||||||
void printLibcallDecls();
|
|
||||||
void EmitUninitializedDataSection(const PIC16Section *S);
|
|
||||||
void EmitInitializedDataSection(const PIC16Section *S);
|
|
||||||
void EmitSingleSection(const PIC16Section *S);
|
|
||||||
void EmitSectionList(Module &M,
|
|
||||||
const std::vector< PIC16Section *> &SList);
|
|
||||||
void ColorAutoSection(const Function *F);
|
|
||||||
protected:
|
|
||||||
bool doInitialization(Module &M);
|
|
||||||
bool doFinalization(Module &M);
|
|
||||||
|
|
||||||
/// EmitGlobalVariable - Emit the specified global variable and its
|
|
||||||
/// initializer to the output stream.
|
|
||||||
virtual void EmitGlobalVariable(const GlobalVariable *GV) {
|
|
||||||
// PIC16 doesn't use normal hooks for this.
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const PIC16TargetObjectFile *PTOF;
|
|
||||||
PIC16DbgInfo DbgInfo;
|
|
||||||
const PIC16MCAsmInfo *PMAI;
|
|
||||||
std::set<std::string> LibcallDecls; // Sorted & uniqued set of extern decls.
|
|
||||||
std::vector<const GlobalVariable *> ExternalVarDecls;
|
|
||||||
std::vector<const GlobalVariable *> ExternalVarDefs;
|
|
||||||
};
|
|
||||||
} // end of namespace
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,26 +0,0 @@
|
||||||
set(LLVM_TARGET_DEFINITIONS PIC16.td)
|
|
||||||
|
|
||||||
tablegen(PIC16GenRegisterInfo.h.inc -gen-register-desc-header)
|
|
||||||
tablegen(PIC16GenRegisterNames.inc -gen-register-enums)
|
|
||||||
tablegen(PIC16GenRegisterInfo.inc -gen-register-desc)
|
|
||||||
tablegen(PIC16GenInstrNames.inc -gen-instr-enums)
|
|
||||||
tablegen(PIC16GenInstrInfo.inc -gen-instr-desc)
|
|
||||||
tablegen(PIC16GenAsmWriter.inc -gen-asm-writer)
|
|
||||||
tablegen(PIC16GenDAGISel.inc -gen-dag-isel)
|
|
||||||
tablegen(PIC16GenCallingConv.inc -gen-callingconv)
|
|
||||||
tablegen(PIC16GenSubtarget.inc -gen-subtarget)
|
|
||||||
|
|
||||||
add_llvm_target(PIC16CodeGen
|
|
||||||
PIC16DebugInfo.cpp
|
|
||||||
PIC16InstrInfo.cpp
|
|
||||||
PIC16ISelDAGToDAG.cpp
|
|
||||||
PIC16ISelLowering.cpp
|
|
||||||
PIC16MemSelOpt.cpp
|
|
||||||
PIC16MCAsmInfo.cpp
|
|
||||||
PIC16RegisterInfo.cpp
|
|
||||||
PIC16Section.cpp
|
|
||||||
PIC16Subtarget.cpp
|
|
||||||
PIC16TargetMachine.cpp
|
|
||||||
PIC16TargetObjectFile.cpp
|
|
||||||
PIC16SelectionDAGInfo.cpp
|
|
||||||
)
|
|
|
@ -1,24 +0,0 @@
|
||||||
##===- lib/Target/PIC16/Makefile ---------------------------*- Makefile -*-===##
|
|
||||||
#
|
|
||||||
# The LLVM Compiler Infrastructure
|
|
||||||
#
|
|
||||||
# This file is distributed under the University of Illinois Open Source
|
|
||||||
# License. See LICENSE.TXT for details.
|
|
||||||
#
|
|
||||||
##===----------------------------------------------------------------------===##
|
|
||||||
|
|
||||||
LEVEL = ../../..
|
|
||||||
LIBRARYNAME = LLVMPIC16CodeGen
|
|
||||||
TARGET = PIC16
|
|
||||||
|
|
||||||
# Make sure that tblgen is run, first thing.
|
|
||||||
BUILT_SOURCES = PIC16GenRegisterInfo.h.inc PIC16GenRegisterNames.inc \
|
|
||||||
PIC16GenRegisterInfo.inc PIC16GenInstrNames.inc \
|
|
||||||
PIC16GenInstrInfo.inc PIC16GenAsmWriter.inc \
|
|
||||||
PIC16GenDAGISel.inc PIC16GenCallingConv.inc \
|
|
||||||
PIC16GenSubtarget.inc
|
|
||||||
|
|
||||||
DIRS = AsmPrinter TargetInfo PIC16Passes
|
|
||||||
|
|
||||||
include $(LEVEL)/Makefile.common
|
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
//===-- PIC16.h - Top-level interface for PIC16 representation --*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the entry points for global functions defined in
|
|
||||||
// the LLVM PIC16 back-end.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef LLVM_TARGET_PIC16_H
|
|
||||||
#define LLVM_TARGET_PIC16_H
|
|
||||||
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
#include <cassert>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
class PIC16TargetMachine;
|
|
||||||
class FunctionPass;
|
|
||||||
class MachineCodeEmitter;
|
|
||||||
class formatted_raw_ostream;
|
|
||||||
|
|
||||||
namespace PIC16CC {
|
|
||||||
enum CondCodes {
|
|
||||||
EQ,
|
|
||||||
NE,
|
|
||||||
LT,
|
|
||||||
LE,
|
|
||||||
GT,
|
|
||||||
GE,
|
|
||||||
ULT,
|
|
||||||
UGT,
|
|
||||||
ULE,
|
|
||||||
UGE
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
enum PIC16SectionType {
|
|
||||||
CODE,
|
|
||||||
UDATA,
|
|
||||||
IDATA,
|
|
||||||
ROMDATA,
|
|
||||||
UDATA_OVR,
|
|
||||||
UDATA_SHR
|
|
||||||
};
|
|
||||||
|
|
||||||
class ESNames {
|
|
||||||
std::vector<char*> stk;
|
|
||||||
ESNames() {}
|
|
||||||
public:
|
|
||||||
~ESNames() {
|
|
||||||
while (!stk.empty())
|
|
||||||
{
|
|
||||||
char* p = stk.back();
|
|
||||||
delete [] p;
|
|
||||||
stk.pop_back();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// External symbol names require memory to live till the program end.
|
|
||||||
// So we have to allocate it and keep. Push all such allocations into a
|
|
||||||
// vector so that they get freed up on termination.
|
|
||||||
inline static const char *createESName (const std::string &name) {
|
|
||||||
static ESNames esn;
|
|
||||||
char *tmpName = new char[name.size() + 1];
|
|
||||||
memcpy(tmpName, name.c_str(), name.size() + 1);
|
|
||||||
esn.stk.push_back(tmpName);
|
|
||||||
return tmpName;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
inline static const char *PIC16CondCodeToString(PIC16CC::CondCodes CC) {
|
|
||||||
switch (CC) {
|
|
||||||
default: llvm_unreachable("Unknown condition code");
|
|
||||||
case PIC16CC::NE: return "ne";
|
|
||||||
case PIC16CC::EQ: return "eq";
|
|
||||||
case PIC16CC::LT: return "lt";
|
|
||||||
case PIC16CC::ULT: return "lt";
|
|
||||||
case PIC16CC::LE: return "le";
|
|
||||||
case PIC16CC::ULE: return "le";
|
|
||||||
case PIC16CC::GT: return "gt";
|
|
||||||
case PIC16CC::UGT: return "gt";
|
|
||||||
case PIC16CC::GE: return "ge";
|
|
||||||
case PIC16CC::UGE: return "ge";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static bool isSignedComparison(PIC16CC::CondCodes CC) {
|
|
||||||
switch (CC) {
|
|
||||||
default: llvm_unreachable("Unknown condition code");
|
|
||||||
case PIC16CC::NE:
|
|
||||||
case PIC16CC::EQ:
|
|
||||||
case PIC16CC::LT:
|
|
||||||
case PIC16CC::LE:
|
|
||||||
case PIC16CC::GE:
|
|
||||||
case PIC16CC::GT:
|
|
||||||
return true;
|
|
||||||
case PIC16CC::ULT:
|
|
||||||
case PIC16CC::UGT:
|
|
||||||
case PIC16CC::ULE:
|
|
||||||
case PIC16CC::UGE:
|
|
||||||
return false; // condition codes for unsigned comparison.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FunctionPass *createPIC16ISelDag(PIC16TargetMachine &TM);
|
|
||||||
// Banksel optimizer pass.
|
|
||||||
FunctionPass *createPIC16MemSelOptimizerPass();
|
|
||||||
|
|
||||||
extern Target ThePIC16Target;
|
|
||||||
extern Target TheCooperTarget;
|
|
||||||
|
|
||||||
} // end namespace llvm;
|
|
||||||
|
|
||||||
// Defines symbolic names for PIC16 registers. This defines a mapping from
|
|
||||||
// register name to register number.
|
|
||||||
#include "PIC16GenRegisterNames.inc"
|
|
||||||
|
|
||||||
// Defines symbolic names for the PIC16 instructions.
|
|
||||||
#include "PIC16GenInstrNames.inc"
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,40 +0,0 @@
|
||||||
//===- PIC16.td - Describe the PIC16 Target Machine -----------*- tblgen -*-==//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// This is the top level entry point for the PIC16 target.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Target-independent interfaces
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
include "llvm/Target/Target.td"
|
|
||||||
|
|
||||||
include "PIC16RegisterInfo.td"
|
|
||||||
include "PIC16InstrInfo.td"
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Subtarget Features.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
def FeatureCooper : SubtargetFeature<"cooper", "IsCooper", "true",
|
|
||||||
"PIC16 Cooper ISA Support">;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 supported processors.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
def : Processor<"generic", NoItineraries, []>;
|
|
||||||
def : Processor<"cooper", NoItineraries, [FeatureCooper]>;
|
|
||||||
|
|
||||||
|
|
||||||
def PIC16InstrInfo : InstrInfo {}
|
|
||||||
|
|
||||||
def PIC16 : Target {
|
|
||||||
let InstructionSet = PIC16InstrInfo;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,399 +0,0 @@
|
||||||
//===-- PIC16ABINames.h - PIC16 Naming conventios for ABI----- --*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the functions to manage ABI Naming conventions for PIC16.
|
|
||||||
//
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef LLVM_TARGET_PIC16ABINAMES_H
|
|
||||||
#define LLVM_TARGET_PIC16ABINAMES_H
|
|
||||||
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
#include <cassert>
|
|
||||||
#include <sstream>
|
|
||||||
#include <cstring>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
class PIC16TargetMachine;
|
|
||||||
class FunctionPass;
|
|
||||||
class MachineCodeEmitter;
|
|
||||||
class formatted_raw_ostream;
|
|
||||||
|
|
||||||
// A Central class to manage all ABI naming conventions.
|
|
||||||
// PAN - [P]ic16 [A]BI [N]ames
|
|
||||||
class PAN {
|
|
||||||
public:
|
|
||||||
// Map the name of the symbol to its section name.
|
|
||||||
// Current ABI:
|
|
||||||
// -----------------------------------------------------
|
|
||||||
// ALL Names are prefixed with the symobl '@'.
|
|
||||||
// ------------------------------------------------------
|
|
||||||
// Global variables do not have any '.' in their names.
|
|
||||||
// These are maily function names and global variable names.
|
|
||||||
// Example - @foo, @i
|
|
||||||
// Static local variables - @<func>.<var>
|
|
||||||
// -------------------------------------------------------
|
|
||||||
// Functions and auto variables.
|
|
||||||
// Names are mangled as <prefix><funcname>.<tag>.<varname>
|
|
||||||
// Where <prefix> is '@' and <tag> is any one of
|
|
||||||
// the following
|
|
||||||
// .auto. - an automatic var of a function.
|
|
||||||
// .temp. - temproray data of a function.
|
|
||||||
// .ret. - return value label for a function.
|
|
||||||
// .frame. - Frame label for a function where retval, args
|
|
||||||
// and temps are stored.
|
|
||||||
// .args. - Label used to pass arguments to a direct call.
|
|
||||||
// Example - Function name: @foo
|
|
||||||
// Its frame: @foo.frame.
|
|
||||||
// Its retval: @foo.ret.
|
|
||||||
// Its local vars: @foo.auto.a
|
|
||||||
// Its temp data: @foo.temp.
|
|
||||||
// Its arg passing: @foo.args.
|
|
||||||
//----------------------------------------------
|
|
||||||
// Libcall - compiler generated libcall names must start with .lib.
|
|
||||||
// This id will be used to emit extern decls for libcalls.
|
|
||||||
// Example - libcall name: @.lib.sra.i8
|
|
||||||
// To pass args: @.lib.sra.i8.args.
|
|
||||||
// To return val: @.lib.sra.i8.ret.
|
|
||||||
//----------------------------------------------
|
|
||||||
// SECTION Names
|
|
||||||
// uninitialized globals - @udata.<num>.#
|
|
||||||
// initialized globals - @idata.<num>.#
|
|
||||||
// Program memory data - @romdata.#
|
|
||||||
// Variables with user defined section name - <user_defined_section>
|
|
||||||
// Variables with user defined address - @<var>.user_section.<address>.#
|
|
||||||
// Function frame - @<func>.frame_section.
|
|
||||||
// Function autos - @<func>.autos_section.
|
|
||||||
// Overlay sections - @<color>.##
|
|
||||||
// Declarations - Enclosed in comments. No section for them.
|
|
||||||
//----------------------------------------------------------
|
|
||||||
|
|
||||||
// Tags used to mangle different names.
|
|
||||||
enum TAGS {
|
|
||||||
PREFIX_SYMBOL,
|
|
||||||
GLOBAL,
|
|
||||||
STATIC_LOCAL,
|
|
||||||
AUTOS_LABEL,
|
|
||||||
FRAME_LABEL,
|
|
||||||
RET_LABEL,
|
|
||||||
ARGS_LABEL,
|
|
||||||
TEMPS_LABEL,
|
|
||||||
|
|
||||||
LIBCALL,
|
|
||||||
|
|
||||||
FRAME_SECTION,
|
|
||||||
AUTOS_SECTION,
|
|
||||||
CODE_SECTION,
|
|
||||||
USER_SECTION
|
|
||||||
};
|
|
||||||
|
|
||||||
// Textual names of the tags.
|
|
||||||
inline static const char *getTagName(TAGS tag) {
|
|
||||||
switch (tag) {
|
|
||||||
default: return "";
|
|
||||||
case PREFIX_SYMBOL: return "@";
|
|
||||||
case AUTOS_LABEL: return ".auto.";
|
|
||||||
case FRAME_LABEL: return ".frame.";
|
|
||||||
case TEMPS_LABEL: return ".temp.";
|
|
||||||
case ARGS_LABEL: return ".args.";
|
|
||||||
case RET_LABEL: return ".ret.";
|
|
||||||
case LIBCALL: return ".lib.";
|
|
||||||
case FRAME_SECTION: return ".frame_section.";
|
|
||||||
case AUTOS_SECTION: return ".autos_section.";
|
|
||||||
case CODE_SECTION: return ".code_section.";
|
|
||||||
case USER_SECTION: return ".user_section.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get tag type for the Symbol.
|
|
||||||
inline static TAGS getSymbolTag(const std::string &Sym) {
|
|
||||||
if (Sym.find(getTagName(TEMPS_LABEL)) != std::string::npos)
|
|
||||||
return TEMPS_LABEL;
|
|
||||||
|
|
||||||
if (Sym.find(getTagName(FRAME_LABEL)) != std::string::npos)
|
|
||||||
return FRAME_LABEL;
|
|
||||||
|
|
||||||
if (Sym.find(getTagName(RET_LABEL)) != std::string::npos)
|
|
||||||
return RET_LABEL;
|
|
||||||
|
|
||||||
if (Sym.find(getTagName(ARGS_LABEL)) != std::string::npos)
|
|
||||||
return ARGS_LABEL;
|
|
||||||
|
|
||||||
if (Sym.find(getTagName(AUTOS_LABEL)) != std::string::npos)
|
|
||||||
return AUTOS_LABEL;
|
|
||||||
|
|
||||||
if (Sym.find(getTagName(LIBCALL)) != std::string::npos)
|
|
||||||
return LIBCALL;
|
|
||||||
|
|
||||||
// It does not have any Tag. So its a true global or static local.
|
|
||||||
if (Sym.find(".") == std::string::npos)
|
|
||||||
return GLOBAL;
|
|
||||||
|
|
||||||
// If a . is there, then it may be static local.
|
|
||||||
// We should mangle these as well in clang.
|
|
||||||
if (Sym.find(".") != std::string::npos)
|
|
||||||
return STATIC_LOCAL;
|
|
||||||
|
|
||||||
assert (0 && "Could not determine Symbol's tag");
|
|
||||||
return PREFIX_SYMBOL; // Silence warning when assertions are turned off.
|
|
||||||
}
|
|
||||||
|
|
||||||
// addPrefix - add prefix symbol to a name if there isn't one already.
|
|
||||||
inline static std::string addPrefix (const std::string &Name) {
|
|
||||||
std::string prefix = getTagName (PREFIX_SYMBOL);
|
|
||||||
|
|
||||||
// If this name already has a prefix, nothing to do.
|
|
||||||
if (Name.compare(0, prefix.size(), prefix) == 0)
|
|
||||||
return Name;
|
|
||||||
|
|
||||||
return prefix + Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get mangled func name from a mangled sym name.
|
|
||||||
// In all cases func name is the first component before a '.'.
|
|
||||||
static inline std::string getFuncNameForSym(const std::string &Sym1) {
|
|
||||||
assert (getSymbolTag(Sym1) != GLOBAL && "not belongs to a function");
|
|
||||||
|
|
||||||
std::string Sym = addPrefix(Sym1);
|
|
||||||
|
|
||||||
// Position of the . after func name. That's where func name ends.
|
|
||||||
size_t func_name_end = Sym.find ('.');
|
|
||||||
|
|
||||||
return Sym.substr (0, func_name_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get Frame start label for a func.
|
|
||||||
static std::string getFrameLabel(const std::string &Func) {
|
|
||||||
std::string Func1 = addPrefix(Func);
|
|
||||||
std::string tag = getTagName(FRAME_LABEL);
|
|
||||||
return Func1 + tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the retval label for the given function.
|
|
||||||
static std::string getRetvalLabel(const std::string &Func) {
|
|
||||||
std::string Func1 = addPrefix(Func);
|
|
||||||
std::string tag = getTagName(RET_LABEL);
|
|
||||||
return Func1 + tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the argument label for the given function.
|
|
||||||
static std::string getArgsLabel(const std::string &Func) {
|
|
||||||
std::string Func1 = addPrefix(Func);
|
|
||||||
std::string tag = getTagName(ARGS_LABEL);
|
|
||||||
return Func1 + tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the tempdata label for the given function.
|
|
||||||
static std::string getTempdataLabel(const std::string &Func) {
|
|
||||||
std::string Func1 = addPrefix(Func);
|
|
||||||
std::string tag = getTagName(TEMPS_LABEL);
|
|
||||||
return Func1 + tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getFrameSectionName(const std::string &Func) {
|
|
||||||
std::string Func1 = addPrefix(Func);
|
|
||||||
std::string tag = getTagName(FRAME_SECTION);
|
|
||||||
return Func1 + tag + "#";
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getAutosSectionName(const std::string &Func) {
|
|
||||||
std::string Func1 = addPrefix(Func);
|
|
||||||
std::string tag = getTagName(AUTOS_SECTION);
|
|
||||||
return Func1 + tag + "#";
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getCodeSectionName(const std::string &Func) {
|
|
||||||
std::string Func1 = addPrefix(Func);
|
|
||||||
std::string tag = getTagName(CODE_SECTION);
|
|
||||||
return Func1 + tag + "#";
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getUserSectionName(const std::string &Name) {
|
|
||||||
std::string sname = addPrefix(Name);;
|
|
||||||
std::string tag = getTagName(USER_SECTION);
|
|
||||||
return sname + tag + "#";
|
|
||||||
}
|
|
||||||
|
|
||||||
// udata, romdata and idata section names are generated by a given number.
|
|
||||||
// @udata.<num>.#
|
|
||||||
static std::string getUdataSectionName(unsigned num,
|
|
||||||
std::string prefix = "") {
|
|
||||||
std::ostringstream o;
|
|
||||||
o << getTagName(PREFIX_SYMBOL) << prefix << "udata." << num
|
|
||||||
<< ".#";
|
|
||||||
return o.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getRomdataSectionName() {
|
|
||||||
return "romdata.#";
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getSharedUDataSectionName() {
|
|
||||||
std::ostringstream o;
|
|
||||||
o << getTagName(PREFIX_SYMBOL) << "udata_shr" << ".#";
|
|
||||||
return o.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getRomdataSectionName(unsigned num,
|
|
||||||
std::string prefix = "") {
|
|
||||||
std::ostringstream o;
|
|
||||||
o << getTagName(PREFIX_SYMBOL) << prefix << "romdata." << num
|
|
||||||
<< ".#";
|
|
||||||
return o.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getIdataSectionName(unsigned num,
|
|
||||||
std::string prefix = "") {
|
|
||||||
std::ostringstream o;
|
|
||||||
o << getTagName(PREFIX_SYMBOL) << prefix << "idata." << num
|
|
||||||
<< ".#";
|
|
||||||
return o.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline static bool isLocalName (const std::string &Name) {
|
|
||||||
if (getSymbolTag(Name) == AUTOS_LABEL)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
inline static bool isMemIntrinsic (const std::string &Name) {
|
|
||||||
if (Name.compare("@memcpy") == 0 || Name.compare("@memset") == 0 ||
|
|
||||||
Name.compare("@memmove") == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Currently names of libcalls are assigned during TargetLowering
|
|
||||||
// object construction. There is no provision to change the when the
|
|
||||||
// code for a function IL function being generated.
|
|
||||||
// So we have to change these names while printing assembly.
|
|
||||||
// We need to do that mainly for names related to intrinsics. This
|
|
||||||
// function returns true if a name needs to be cloned.
|
|
||||||
inline static bool isIntrinsicStuff(const std::string &Name) {
|
|
||||||
// Return true if the name contains LIBCALL marker, or a MemIntrinisc.
|
|
||||||
// these are mainly ARGS_LABEL, RET_LABEL, and the LIBCALL name itself.
|
|
||||||
if ((Name.find(getTagName(LIBCALL)) != std::string::npos)
|
|
||||||
|| isMemIntrinsic(Name))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rename the name for IL.
|
|
||||||
inline static std::string Rename(const std::string &Name) {
|
|
||||||
std::string Newname;
|
|
||||||
// If its a label (LIBCALL+Func+LABEL), change it to
|
|
||||||
// (LIBCALL+Func+IL+LABEL).
|
|
||||||
TAGS id = getSymbolTag(Name);
|
|
||||||
if (id == ARGS_LABEL || id == RET_LABEL) {
|
|
||||||
std::size_t pos = Name.find(getTagName(id));
|
|
||||||
Newname = Name.substr(0, pos) + ".IL" + getTagName(id);
|
|
||||||
return Newname;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Else, just append IL to name.
|
|
||||||
return Name + ".IL";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
inline static bool isLocalToFunc (std::string &Func, std::string &Var) {
|
|
||||||
if (! isLocalName(Var)) return false;
|
|
||||||
|
|
||||||
std::string Func1 = addPrefix(Func);
|
|
||||||
// Extract func name of the varilable.
|
|
||||||
const std::string &fname = getFuncNameForSym(Var);
|
|
||||||
|
|
||||||
if (fname.compare(Func1) == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Get the section for the given external symbol names.
|
|
||||||
// This tries to find the type (Tag) of the symbol from its mangled name
|
|
||||||
// and return appropriate section name for it.
|
|
||||||
static inline std::string getSectionNameForSym(const std::string &Sym1) {
|
|
||||||
std::string Sym = addPrefix(Sym1);
|
|
||||||
|
|
||||||
std::string SectionName;
|
|
||||||
|
|
||||||
std::string Fname = getFuncNameForSym (Sym);
|
|
||||||
TAGS id = getSymbolTag (Sym);
|
|
||||||
|
|
||||||
switch (id) {
|
|
||||||
default : assert (0 && "Could not determine external symbol type");
|
|
||||||
case FRAME_LABEL:
|
|
||||||
case RET_LABEL:
|
|
||||||
case TEMPS_LABEL:
|
|
||||||
case ARGS_LABEL: {
|
|
||||||
return getFrameSectionName(Fname);
|
|
||||||
}
|
|
||||||
case AUTOS_LABEL: {
|
|
||||||
return getAutosSectionName(Fname);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return Overlay Name for the section.
|
|
||||||
/// The ABI Convention is: @<Color>.##.<section_tag>
|
|
||||||
/// The section_tag is retrieved from the SectName parameter and
|
|
||||||
/// and Color is passed in parameter.
|
|
||||||
static inline std::string getOverlayName(std::string SectName, int Color) {
|
|
||||||
// FIXME: Only autos_section and frame_section are colored.
|
|
||||||
// So check and assert if the passed SectName does not have AUTOS_SECTION
|
|
||||||
// or FRAME_SECTION tag in it.
|
|
||||||
std::ostringstream o;
|
|
||||||
o << getTagName(PREFIX_SYMBOL) << Color << ".##"
|
|
||||||
<< SectName.substr(SectName.find("."));
|
|
||||||
|
|
||||||
return o.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return true if the current function is an ISR
|
|
||||||
inline static bool isISR(const std::string SectName) {
|
|
||||||
if (SectName.find("interrupt") != std::string::npos)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the address for ISR starts in rom.
|
|
||||||
inline static std::string getISRAddr(void) {
|
|
||||||
return "0x4";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the name of clone of a function.
|
|
||||||
static std::string getCloneFnName(const std::string &Func) {
|
|
||||||
return (Func + ".IL");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the name of clone of a variable.
|
|
||||||
static std::string getCloneVarName(const std::string &Fn,
|
|
||||||
const std::string &Var) {
|
|
||||||
std::string cloneVarName = Var;
|
|
||||||
// These vars are named like fun.auto.var.
|
|
||||||
// Just replace the function name, with clone function name.
|
|
||||||
std::string cloneFnName = getCloneFnName(Fn);
|
|
||||||
cloneVarName.replace(cloneVarName.find(Fn), Fn.length(), cloneFnName);
|
|
||||||
return cloneVarName;
|
|
||||||
}
|
|
||||||
}; // class PAN.
|
|
||||||
} // end namespace llvm;
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,490 +0,0 @@
|
||||||
|
|
||||||
//===-- PIC16DebugInfo.cpp - Implementation for PIC16 Debug Information ======//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the helper functions for representing debug information.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16ABINames.h"
|
|
||||||
#include "PIC16DebugInfo.h"
|
|
||||||
#include "llvm/GlobalVariable.h"
|
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
|
||||||
#include "llvm/MC/MCAsmInfo.h"
|
|
||||||
#include "llvm/MC/MCStreamer.h"
|
|
||||||
#include "llvm/Support/DebugLoc.h"
|
|
||||||
#include "llvm/ADT/SmallString.h"
|
|
||||||
#include "llvm/ADT/StringExtras.h"
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
/// PopulateDebugInfo - Populate the TypeNo, Aux[] and TagName from Ty.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::PopulateDebugInfo (DIType Ty, unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TagName) {
|
|
||||||
if (Ty.isBasicType())
|
|
||||||
PopulateBasicTypeInfo (Ty, TypeNo);
|
|
||||||
else if (Ty.isCompositeType())
|
|
||||||
PopulateCompositeTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
|
|
||||||
else if (Ty.isDerivedType())
|
|
||||||
PopulateDerivedTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
|
|
||||||
else {
|
|
||||||
TypeNo = PIC16Dbg::T_NULL;
|
|
||||||
HasAux = false;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PopulateBasicTypeInfo- Populate TypeNo for basic type from Ty.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::PopulateBasicTypeInfo (DIType Ty, unsigned short &TypeNo) {
|
|
||||||
std::string Name = Ty.getName();
|
|
||||||
unsigned short BaseTy = GetTypeDebugNumber(Name);
|
|
||||||
TypeNo = TypeNo << PIC16Dbg::S_BASIC;
|
|
||||||
TypeNo = TypeNo | (0xffff & BaseTy);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PopulateDerivedTypeInfo - Populate TypeNo, Aux[], TagName for derived type
|
|
||||||
/// from Ty. Derived types are mostly pointers.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TagName) {
|
|
||||||
|
|
||||||
switch(Ty.getTag())
|
|
||||||
{
|
|
||||||
case dwarf::DW_TAG_pointer_type:
|
|
||||||
TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
|
|
||||||
TypeNo = TypeNo | PIC16Dbg::DT_PTR;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We also need to encode the information about the base type of
|
|
||||||
// pointer in TypeNo.
|
|
||||||
DIType BaseType = DIDerivedType(Ty).getTypeDerivedFrom();
|
|
||||||
PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PopulateArrayTypeInfo - Populate TypeNo, Aux[] for array from Ty.
|
|
||||||
void PIC16DbgInfo::PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TagName) {
|
|
||||||
|
|
||||||
DICompositeType CTy = DICompositeType(Ty);
|
|
||||||
DIArray Elements = CTy.getTypeArray();
|
|
||||||
unsigned short size = 1;
|
|
||||||
unsigned short Dimension[4]={0,0,0,0};
|
|
||||||
for (unsigned i = 0, N = Elements.getNumElements(); i < N; ++i) {
|
|
||||||
DIDescriptor Element = Elements.getElement(i);
|
|
||||||
if (Element.getTag() == dwarf::DW_TAG_subrange_type) {
|
|
||||||
TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
|
|
||||||
TypeNo = TypeNo | PIC16Dbg::DT_ARY;
|
|
||||||
DISubrange SubRange = DISubrange(Element);
|
|
||||||
Dimension[i] = SubRange.getHi() - SubRange.getLo() + 1;
|
|
||||||
// Each dimension is represented by 2 bytes starting at byte 9.
|
|
||||||
Aux[8+i*2+0] = Dimension[i];
|
|
||||||
Aux[8+i*2+1] = Dimension[i] >> 8;
|
|
||||||
size = size * Dimension[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
HasAux = true;
|
|
||||||
// In auxillary entry for array, 7th and 8th byte represent array size.
|
|
||||||
Aux[6] = size & 0xff;
|
|
||||||
Aux[7] = size >> 8;
|
|
||||||
DIType BaseType = CTy.getTypeDerivedFrom();
|
|
||||||
PopulateDebugInfo(BaseType, TypeNo, HasAux, Aux, TagName);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PopulateStructOrUnionTypeInfo - Populate TypeNo, Aux[] , TagName for
|
|
||||||
/// structure or union.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::PopulateStructOrUnionTypeInfo (DIType Ty,
|
|
||||||
unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TagName) {
|
|
||||||
DICompositeType CTy = DICompositeType(Ty);
|
|
||||||
TypeNo = TypeNo << PIC16Dbg::S_BASIC;
|
|
||||||
if (Ty.getTag() == dwarf::DW_TAG_structure_type)
|
|
||||||
TypeNo = TypeNo | PIC16Dbg::T_STRUCT;
|
|
||||||
else
|
|
||||||
TypeNo = TypeNo | PIC16Dbg::T_UNION;
|
|
||||||
TagName = CTy.getName();
|
|
||||||
// UniqueSuffix is .number where number is obtained from
|
|
||||||
// llvm.dbg.composite<number>.
|
|
||||||
// FIXME: This will break when composite type is not represented by
|
|
||||||
// llvm.dbg.composite* global variable. Since we need to revisit
|
|
||||||
// PIC16DebugInfo implementation anyways after the MDNodes based
|
|
||||||
// framework is done, let us continue with the way it is.
|
|
||||||
std::string UniqueSuffix = "." + Ty->getNameStr().substr(18);
|
|
||||||
TagName += UniqueSuffix;
|
|
||||||
unsigned short size = CTy.getSizeInBits()/8;
|
|
||||||
// 7th and 8th byte represent size.
|
|
||||||
HasAux = true;
|
|
||||||
Aux[6] = size & 0xff;
|
|
||||||
Aux[7] = size >> 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PopulateEnumTypeInfo - Populate TypeNo for enum from Ty.
|
|
||||||
void PIC16DbgInfo::PopulateEnumTypeInfo (DIType Ty, unsigned short &TypeNo) {
|
|
||||||
TypeNo = TypeNo << PIC16Dbg::S_BASIC;
|
|
||||||
TypeNo = TypeNo | PIC16Dbg::T_ENUM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PopulateCompositeTypeInfo - Populate TypeNo, Aux[] and TagName for
|
|
||||||
/// composite types from Ty.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::PopulateCompositeTypeInfo (DIType Ty, unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TagName) {
|
|
||||||
switch (Ty.getTag()) {
|
|
||||||
case dwarf::DW_TAG_array_type: {
|
|
||||||
PopulateArrayTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case dwarf:: DW_TAG_union_type:
|
|
||||||
case dwarf::DW_TAG_structure_type: {
|
|
||||||
PopulateStructOrUnionTypeInfo (Ty, TypeNo, HasAux, Aux, TagName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case dwarf::DW_TAG_enumeration_type: {
|
|
||||||
PopulateEnumTypeInfo (Ty, TypeNo);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
TypeNo = TypeNo << PIC16Dbg::S_DERIVED;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// GetTypeDebugNumber - Get debug type number for given type.
|
|
||||||
///
|
|
||||||
unsigned PIC16DbgInfo::GetTypeDebugNumber(std::string &type) {
|
|
||||||
if (type == "char")
|
|
||||||
return PIC16Dbg::T_CHAR;
|
|
||||||
else if (type == "short")
|
|
||||||
return PIC16Dbg::T_SHORT;
|
|
||||||
else if (type == "int")
|
|
||||||
return PIC16Dbg::T_INT;
|
|
||||||
else if (type == "long")
|
|
||||||
return PIC16Dbg::T_LONG;
|
|
||||||
else if (type == "unsigned char")
|
|
||||||
return PIC16Dbg::T_UCHAR;
|
|
||||||
else if (type == "unsigned short")
|
|
||||||
return PIC16Dbg::T_USHORT;
|
|
||||||
else if (type == "unsigned int")
|
|
||||||
return PIC16Dbg::T_UINT;
|
|
||||||
else if (type == "unsigned long")
|
|
||||||
return PIC16Dbg::T_ULONG;
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// GetStorageClass - Get storage class for give debug variable.
|
|
||||||
///
|
|
||||||
short PIC16DbgInfo::getStorageClass(DIGlobalVariable DIGV) {
|
|
||||||
short ClassNo;
|
|
||||||
if (PAN::isLocalName(DIGV.getName())) {
|
|
||||||
// Generating C_AUTO here fails due to error in linker. Change it once
|
|
||||||
// linker is fixed.
|
|
||||||
ClassNo = PIC16Dbg::C_STAT;
|
|
||||||
}
|
|
||||||
else if (DIGV.isLocalToUnit())
|
|
||||||
ClassNo = PIC16Dbg::C_STAT;
|
|
||||||
else
|
|
||||||
ClassNo = PIC16Dbg::C_EXT;
|
|
||||||
return ClassNo;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// BeginModule - Emit necessary debug info to start a Module and do other
|
|
||||||
/// required initializations.
|
|
||||||
void PIC16DbgInfo::BeginModule(Module &M) {
|
|
||||||
// Emit file directive for module.
|
|
||||||
DebugInfoFinder DbgFinder;
|
|
||||||
DbgFinder.processModule(M);
|
|
||||||
if (DbgFinder.compile_unit_count() != 0) {
|
|
||||||
// FIXME : What if more then one CUs are present in a module ?
|
|
||||||
MDNode *CU = *DbgFinder.compile_unit_begin();
|
|
||||||
EmitDebugDirectives = true;
|
|
||||||
SwitchToCU(CU);
|
|
||||||
}
|
|
||||||
// Emit debug info for decls of composite types.
|
|
||||||
EmitCompositeTypeDecls(M);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Helper to find first valid debug loc for a function.
|
|
||||||
///
|
|
||||||
static const DebugLoc GetDebugLocForFunction(const MachineFunction &MF) {
|
|
||||||
DebugLoc DL;
|
|
||||||
for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
|
|
||||||
II != E; ++II) {
|
|
||||||
DL = II->getDebugLoc();
|
|
||||||
if (!DL.isUnknown())
|
|
||||||
return DL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return DL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// BeginFunction - Emit necessary debug info to start a function.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::BeginFunction(const MachineFunction &MF) {
|
|
||||||
if (! EmitDebugDirectives) return;
|
|
||||||
|
|
||||||
// Retreive the first valid debug Loc and process it.
|
|
||||||
const DebugLoc &DL = GetDebugLocForFunction(MF);
|
|
||||||
// Emit debug info only if valid debug info is available.
|
|
||||||
if (!DL.isUnknown()) {
|
|
||||||
ChangeDebugLoc(MF, DL, true);
|
|
||||||
EmitFunctBeginDI(MF.getFunction());
|
|
||||||
}
|
|
||||||
// Set current line to 0 so that.line directive is genearted after .bf.
|
|
||||||
CurLine = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ChangeDebugLoc - Take necessary steps when DebugLoc changes.
|
|
||||||
/// CurFile and CurLine may change as a result of this.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::ChangeDebugLoc(const MachineFunction &MF,
|
|
||||||
const DebugLoc &DL, bool IsInBeginFunction) {
|
|
||||||
if (!EmitDebugDirectives) return;
|
|
||||||
assert(!DL.isUnknown() && "can't change to invalid debug loc");
|
|
||||||
|
|
||||||
SwitchToCU(DL.getScope(MF.getFunction()->getContext()));
|
|
||||||
SwitchToLine(DL.getLine(), IsInBeginFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// SwitchToLine - Emit line directive for a new line.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::SwitchToLine(unsigned Line, bool IsInBeginFunction) {
|
|
||||||
if (CurLine == Line) return;
|
|
||||||
if (!IsInBeginFunction)
|
|
||||||
OS.EmitRawText("\n\t.line " + Twine(Line));
|
|
||||||
CurLine = Line;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EndFunction - Emit .ef for end of function.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EndFunction(const MachineFunction &MF) {
|
|
||||||
if (! EmitDebugDirectives) return;
|
|
||||||
const DebugLoc &DL = GetDebugLocForFunction(MF);
|
|
||||||
// Emit debug info only if valid debug info is available.
|
|
||||||
if (!DL.isUnknown())
|
|
||||||
EmitFunctEndDI(MF.getFunction(), CurLine);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EndModule - Emit .eof for end of module.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EndModule(Module &M) {
|
|
||||||
if (! EmitDebugDirectives) return;
|
|
||||||
EmitVarDebugInfo(M);
|
|
||||||
if (CurFile != "") OS.EmitRawText(StringRef("\n\t.eof"));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EmitCompositeTypeElements - Emit debug information for members of a
|
|
||||||
/// composite type.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EmitCompositeTypeElements (DICompositeType CTy,
|
|
||||||
std::string SuffixNo) {
|
|
||||||
unsigned long Value = 0;
|
|
||||||
DIArray Elements = CTy.getTypeArray();
|
|
||||||
for (unsigned i = 0, N = Elements.getNumElements(); i < N; i++) {
|
|
||||||
DIDescriptor Element = Elements.getElement(i);
|
|
||||||
unsigned short TypeNo = 0;
|
|
||||||
bool HasAux = false;
|
|
||||||
int ElementAux[PIC16Dbg::AuxSize] = { 0 };
|
|
||||||
std::string TagName = "";
|
|
||||||
DIDerivedType DITy(Element);
|
|
||||||
unsigned short ElementSize = DITy.getSizeInBits()/8;
|
|
||||||
// Get mangleddd name for this structure/union element.
|
|
||||||
std::string MangMemName = DITy.getName().str() + SuffixNo;
|
|
||||||
PopulateDebugInfo(DITy, TypeNo, HasAux, ElementAux, TagName);
|
|
||||||
short Class = 0;
|
|
||||||
if( CTy.getTag() == dwarf::DW_TAG_union_type)
|
|
||||||
Class = PIC16Dbg::C_MOU;
|
|
||||||
else if (CTy.getTag() == dwarf::DW_TAG_structure_type)
|
|
||||||
Class = PIC16Dbg::C_MOS;
|
|
||||||
EmitSymbol(MangMemName.c_str(), Class, TypeNo, Value);
|
|
||||||
if (CTy.getTag() == dwarf::DW_TAG_structure_type)
|
|
||||||
Value += ElementSize;
|
|
||||||
if (HasAux)
|
|
||||||
EmitAuxEntry(MangMemName.c_str(), ElementAux, PIC16Dbg::AuxSize, TagName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EmitCompositeTypeDecls - Emit composite type declarations like structure
|
|
||||||
/// and union declarations.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EmitCompositeTypeDecls(Module &M) {
|
|
||||||
DebugInfoFinder DbgFinder;
|
|
||||||
DbgFinder.processModule(M);
|
|
||||||
for (DebugInfoFinder::iterator I = DbgFinder.type_begin(),
|
|
||||||
E = DbgFinder.type_end(); I != E; ++I) {
|
|
||||||
DICompositeType CTy(*I);
|
|
||||||
if (!CTy.Verify())
|
|
||||||
continue;
|
|
||||||
if (CTy.getTag() == dwarf::DW_TAG_union_type ||
|
|
||||||
CTy.getTag() == dwarf::DW_TAG_structure_type ) {
|
|
||||||
// Get the number after llvm.dbg.composite and make UniqueSuffix from
|
|
||||||
// it.
|
|
||||||
std::string DIVar = CTy->getNameStr();
|
|
||||||
std::string UniqueSuffix = "." + DIVar.substr(18);
|
|
||||||
std::string MangledCTyName = CTy.getName().str() + UniqueSuffix;
|
|
||||||
unsigned short size = CTy.getSizeInBits()/8;
|
|
||||||
int Aux[PIC16Dbg::AuxSize] = {0};
|
|
||||||
// 7th and 8th byte represent size of structure/union.
|
|
||||||
Aux[6] = size & 0xff;
|
|
||||||
Aux[7] = size >> 8;
|
|
||||||
// Emit .def for structure/union tag.
|
|
||||||
if( CTy.getTag() == dwarf::DW_TAG_union_type)
|
|
||||||
EmitSymbol(MangledCTyName.c_str(), PIC16Dbg::C_UNTAG);
|
|
||||||
else if (CTy.getTag() == dwarf::DW_TAG_structure_type)
|
|
||||||
EmitSymbol(MangledCTyName.c_str(), PIC16Dbg::C_STRTAG);
|
|
||||||
|
|
||||||
// Emit auxiliary debug information for structure/union tag.
|
|
||||||
EmitAuxEntry(MangledCTyName.c_str(), Aux, PIC16Dbg::AuxSize);
|
|
||||||
|
|
||||||
// Emit members.
|
|
||||||
EmitCompositeTypeElements (CTy, UniqueSuffix);
|
|
||||||
|
|
||||||
// Emit mangled Symbol for end of structure/union.
|
|
||||||
std::string EOSSymbol = ".eos" + UniqueSuffix;
|
|
||||||
EmitSymbol(EOSSymbol.c_str(), PIC16Dbg::C_EOS);
|
|
||||||
EmitAuxEntry(EOSSymbol.c_str(), Aux, PIC16Dbg::AuxSize,
|
|
||||||
MangledCTyName.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// EmitFunctBeginDI - Emit .bf for function.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EmitFunctBeginDI(const Function *F) {
|
|
||||||
std::string FunctName = F->getName();
|
|
||||||
if (EmitDebugDirectives) {
|
|
||||||
std::string FunctBeginSym = ".bf." + FunctName;
|
|
||||||
std::string BlockBeginSym = ".bb." + FunctName;
|
|
||||||
|
|
||||||
int BFAux[PIC16Dbg::AuxSize] = {0};
|
|
||||||
BFAux[4] = CurLine;
|
|
||||||
BFAux[5] = CurLine >> 8;
|
|
||||||
|
|
||||||
// Emit debug directives for beginning of function.
|
|
||||||
EmitSymbol(FunctBeginSym, PIC16Dbg::C_FCN);
|
|
||||||
EmitAuxEntry(FunctBeginSym, BFAux, PIC16Dbg::AuxSize);
|
|
||||||
|
|
||||||
EmitSymbol(BlockBeginSym, PIC16Dbg::C_BLOCK);
|
|
||||||
EmitAuxEntry(BlockBeginSym, BFAux, PIC16Dbg::AuxSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EmitFunctEndDI - Emit .ef for function end.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EmitFunctEndDI(const Function *F, unsigned Line) {
|
|
||||||
std::string FunctName = F->getName();
|
|
||||||
if (EmitDebugDirectives) {
|
|
||||||
std::string FunctEndSym = ".ef." + FunctName;
|
|
||||||
std::string BlockEndSym = ".eb." + FunctName;
|
|
||||||
|
|
||||||
// Emit debug directives for end of function.
|
|
||||||
EmitSymbol(BlockEndSym, PIC16Dbg::C_BLOCK);
|
|
||||||
int EFAux[PIC16Dbg::AuxSize] = {0};
|
|
||||||
// 5th and 6th byte stand for line number.
|
|
||||||
EFAux[4] = CurLine;
|
|
||||||
EFAux[5] = CurLine >> 8;
|
|
||||||
EmitAuxEntry(BlockEndSym, EFAux, PIC16Dbg::AuxSize);
|
|
||||||
EmitSymbol(FunctEndSym, PIC16Dbg::C_FCN);
|
|
||||||
EmitAuxEntry(FunctEndSym, EFAux, PIC16Dbg::AuxSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EmitAuxEntry - Emit Auxiliary debug information.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EmitAuxEntry(const std::string VarName, int Aux[], int Num,
|
|
||||||
std::string TagName) {
|
|
||||||
std::string Tmp;
|
|
||||||
// TagName is emitted in case of structure/union objects.
|
|
||||||
if (!TagName.empty()) Tmp += ", " + TagName;
|
|
||||||
|
|
||||||
for (int i = 0; i<Num; i++)
|
|
||||||
Tmp += "," + utostr(Aux[i] & 0xff);
|
|
||||||
|
|
||||||
OS.EmitRawText("\n\t.dim " + Twine(VarName) + ", 1" + Tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EmitSymbol - Emit .def for a symbol. Value is offset for the member.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EmitSymbol(std::string Name, short Class,
|
|
||||||
unsigned short Type, unsigned long Value) {
|
|
||||||
std::string Tmp;
|
|
||||||
if (Value > 0)
|
|
||||||
Tmp = ", value = " + utostr(Value);
|
|
||||||
|
|
||||||
OS.EmitRawText("\n\t.def " + Twine(Name) + ", type = " + utostr(Type) +
|
|
||||||
", class = " + utostr(Class) + Tmp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EmitVarDebugInfo - Emit debug information for all variables.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EmitVarDebugInfo(Module &M) {
|
|
||||||
DebugInfoFinder DbgFinder;
|
|
||||||
DbgFinder.processModule(M);
|
|
||||||
|
|
||||||
for (DebugInfoFinder::iterator I = DbgFinder.global_variable_begin(),
|
|
||||||
E = DbgFinder.global_variable_end(); I != E; ++I) {
|
|
||||||
DIGlobalVariable DIGV(*I);
|
|
||||||
DIType Ty = DIGV.getType();
|
|
||||||
unsigned short TypeNo = 0;
|
|
||||||
bool HasAux = false;
|
|
||||||
int Aux[PIC16Dbg::AuxSize] = { 0 };
|
|
||||||
std::string TagName = "";
|
|
||||||
std::string VarName = DIGV.getName();
|
|
||||||
VarName = MAI->getGlobalPrefix() + VarName;
|
|
||||||
PopulateDebugInfo(Ty, TypeNo, HasAux, Aux, TagName);
|
|
||||||
// Emit debug info only if type information is availaible.
|
|
||||||
if (TypeNo != PIC16Dbg::T_NULL) {
|
|
||||||
OS.EmitRawText("\t.type " + Twine(VarName) + ", " + Twine(TypeNo));
|
|
||||||
short ClassNo = getStorageClass(DIGV);
|
|
||||||
OS.EmitRawText("\t.class " + Twine(VarName) + ", " + Twine(ClassNo));
|
|
||||||
if (HasAux)
|
|
||||||
EmitAuxEntry(VarName, Aux, PIC16Dbg::AuxSize, TagName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// SwitchToCU - Switch to a new compilation unit.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::SwitchToCU(MDNode *CU) {
|
|
||||||
// Get the file path from CU.
|
|
||||||
DICompileUnit cu(CU);
|
|
||||||
std::string DirName = cu.getDirectory();
|
|
||||||
std::string FileName = cu.getFilename();
|
|
||||||
std::string FilePath = DirName + "/" + FileName;
|
|
||||||
|
|
||||||
// Nothing to do if source file is still same.
|
|
||||||
if ( FilePath == CurFile ) return;
|
|
||||||
|
|
||||||
// Else, close the current one and start a new.
|
|
||||||
if (CurFile != "")
|
|
||||||
OS.EmitRawText(StringRef("\t.eof"));
|
|
||||||
OS.EmitRawText("\n\t.file\t\"" + Twine(FilePath) + "\"");
|
|
||||||
CurFile = FilePath;
|
|
||||||
CurLine = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// EmitEOF - Emit .eof for end of file.
|
|
||||||
///
|
|
||||||
void PIC16DbgInfo::EmitEOF() {
|
|
||||||
if (CurFile != "")
|
|
||||||
OS.EmitRawText(StringRef("\t.EOF"));
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,156 +0,0 @@
|
||||||
//===-- PIC16DebugInfo.h - Interfaces for PIC16 Debug Information ============//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the helper functions for representing debug information.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16DBG_H
|
|
||||||
#define PIC16DBG_H
|
|
||||||
|
|
||||||
#include "llvm/Analysis/DebugInfo.h"
|
|
||||||
#include "llvm/Module.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
class MachineFunction;
|
|
||||||
class DebugLoc;
|
|
||||||
class MCStreamer;
|
|
||||||
|
|
||||||
namespace PIC16Dbg {
|
|
||||||
enum VarType {
|
|
||||||
T_NULL,
|
|
||||||
T_VOID,
|
|
||||||
T_CHAR,
|
|
||||||
T_SHORT,
|
|
||||||
T_INT,
|
|
||||||
T_LONG,
|
|
||||||
T_FLOAT,
|
|
||||||
T_DOUBLE,
|
|
||||||
T_STRUCT,
|
|
||||||
T_UNION,
|
|
||||||
T_ENUM,
|
|
||||||
T_MOE,
|
|
||||||
T_UCHAR,
|
|
||||||
T_USHORT,
|
|
||||||
T_UINT,
|
|
||||||
T_ULONG
|
|
||||||
};
|
|
||||||
enum DerivedType {
|
|
||||||
DT_NONE,
|
|
||||||
DT_PTR,
|
|
||||||
DT_FCN,
|
|
||||||
DT_ARY
|
|
||||||
};
|
|
||||||
enum TypeSize {
|
|
||||||
S_BASIC = 5,
|
|
||||||
S_DERIVED = 3
|
|
||||||
};
|
|
||||||
enum DbgClass {
|
|
||||||
C_NULL,
|
|
||||||
C_AUTO,
|
|
||||||
C_EXT,
|
|
||||||
C_STAT,
|
|
||||||
C_REG,
|
|
||||||
C_EXTDEF,
|
|
||||||
C_LABEL,
|
|
||||||
C_ULABEL,
|
|
||||||
C_MOS,
|
|
||||||
C_ARG,
|
|
||||||
C_STRTAG,
|
|
||||||
C_MOU,
|
|
||||||
C_UNTAG,
|
|
||||||
C_TPDEF,
|
|
||||||
C_USTATIC,
|
|
||||||
C_ENTAG,
|
|
||||||
C_MOE,
|
|
||||||
C_REGPARM,
|
|
||||||
C_FIELD,
|
|
||||||
C_AUTOARG,
|
|
||||||
C_LASTENT,
|
|
||||||
C_BLOCK = 100,
|
|
||||||
C_FCN,
|
|
||||||
C_EOS,
|
|
||||||
C_FILE,
|
|
||||||
C_LINE,
|
|
||||||
C_ALIAS,
|
|
||||||
C_HIDDEN,
|
|
||||||
C_EOF,
|
|
||||||
C_LIST,
|
|
||||||
C_SECTION,
|
|
||||||
C_EFCN = 255
|
|
||||||
};
|
|
||||||
enum SymbolSize {
|
|
||||||
AuxSize =20
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class PIC16DbgInfo {
|
|
||||||
MCStreamer &OS;
|
|
||||||
const MCAsmInfo *MAI;
|
|
||||||
std::string CurFile;
|
|
||||||
unsigned CurLine;
|
|
||||||
|
|
||||||
// EmitDebugDirectives is set if debug information is available. Default
|
|
||||||
// value for it is false.
|
|
||||||
bool EmitDebugDirectives;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PIC16DbgInfo(MCStreamer &os, const MCAsmInfo *T) : OS(os), MAI(T) {
|
|
||||||
CurFile = "";
|
|
||||||
CurLine = 0;
|
|
||||||
EmitDebugDirectives = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void BeginModule (Module &M);
|
|
||||||
void BeginFunction (const MachineFunction &MF);
|
|
||||||
void ChangeDebugLoc (const MachineFunction &MF, const DebugLoc &DL,
|
|
||||||
bool IsInBeginFunction = false);
|
|
||||||
void EndFunction (const MachineFunction &MF);
|
|
||||||
void EndModule (Module &M);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SwitchToCU (MDNode *CU);
|
|
||||||
void SwitchToLine (unsigned Line, bool IsInBeginFunction = false);
|
|
||||||
|
|
||||||
void PopulateDebugInfo (DIType Ty, unsigned short &TypeNo, bool &HasAux,
|
|
||||||
int Aux[], std::string &TypeName);
|
|
||||||
void PopulateBasicTypeInfo (DIType Ty, unsigned short &TypeNo);
|
|
||||||
void PopulateDerivedTypeInfo (DIType Ty, unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TypeName);
|
|
||||||
|
|
||||||
void PopulateCompositeTypeInfo (DIType Ty, unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TypeName);
|
|
||||||
void PopulateArrayTypeInfo (DIType Ty, unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TypeName);
|
|
||||||
|
|
||||||
void PopulateStructOrUnionTypeInfo (DIType Ty, unsigned short &TypeNo,
|
|
||||||
bool &HasAux, int Aux[],
|
|
||||||
std::string &TypeName);
|
|
||||||
void PopulateEnumTypeInfo (DIType Ty, unsigned short &TypeNo);
|
|
||||||
|
|
||||||
unsigned GetTypeDebugNumber(std::string &Type);
|
|
||||||
short getStorageClass(DIGlobalVariable DIGV);
|
|
||||||
void EmitFunctBeginDI(const Function *F);
|
|
||||||
void EmitCompositeTypeDecls(Module &M);
|
|
||||||
void EmitCompositeTypeElements (DICompositeType CTy, std::string Suffix);
|
|
||||||
void EmitFunctEndDI(const Function *F, unsigned Line);
|
|
||||||
void EmitAuxEntry(const std::string VarName, int Aux[],
|
|
||||||
int num = PIC16Dbg::AuxSize, std::string TagName = "");
|
|
||||||
inline void EmitSymbol(std::string Name, short Class,
|
|
||||||
unsigned short Type = PIC16Dbg::T_NULL,
|
|
||||||
unsigned long Value = 0);
|
|
||||||
void EmitVarDebugInfo(Module &M);
|
|
||||||
void EmitEOF();
|
|
||||||
};
|
|
||||||
} // end namespace llvm;
|
|
||||||
#endif
|
|
|
@ -1,49 +0,0 @@
|
||||||
//===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file defines an instruction selector for the PIC16 target.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define DEBUG_TYPE "pic16-isel"
|
|
||||||
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include "PIC16ISelDAGToDAG.h"
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
/// createPIC16ISelDag - This pass converts a legalized DAG into a
|
|
||||||
/// PIC16-specific DAG, ready for instruction scheduling.
|
|
||||||
FunctionPass *llvm::createPIC16ISelDag(PIC16TargetMachine &TM) {
|
|
||||||
return new PIC16DAGToDAGISel(TM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Select - Select instructions not customized! Used for
|
|
||||||
/// expanded, promoted and normal instructions.
|
|
||||||
SDNode* PIC16DAGToDAGISel::Select(SDNode *N) {
|
|
||||||
|
|
||||||
// Select the default instruction.
|
|
||||||
SDNode *ResNode = SelectCode(N);
|
|
||||||
|
|
||||||
return ResNode;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// SelectDirectAddr - Match a direct address for DAG.
|
|
||||||
// A direct address could be a globaladdress or externalsymbol.
|
|
||||||
bool PIC16DAGToDAGISel::SelectDirectAddr(SDValue N, SDValue &Address) {
|
|
||||||
// Return true if TGA or ES.
|
|
||||||
if (N.getOpcode() == ISD::TargetGlobalAddress
|
|
||||||
|| N.getOpcode() == ISD::TargetExternalSymbol) {
|
|
||||||
Address = N;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
//===-- PIC16ISelDAGToDAG.cpp - A dag to dag inst selector for PIC16 ------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file defines an instruction selector for the PIC16 target.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define DEBUG_TYPE "pic16-isel"
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16RegisterInfo.h"
|
|
||||||
#include "PIC16TargetMachine.h"
|
|
||||||
#include "PIC16MachineFunctionInfo.h"
|
|
||||||
#include "llvm/CodeGen/SelectionDAGISel.h"
|
|
||||||
#include "llvm/Support/Compiler.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
#include "llvm/Support/Debug.h"
|
|
||||||
#include "llvm/Intrinsics.h"
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
class LLVM_LIBRARY_VISIBILITY PIC16DAGToDAGISel : public SelectionDAGISel {
|
|
||||||
|
|
||||||
/// TM - Keep a reference to PIC16TargetMachine.
|
|
||||||
const PIC16TargetMachine &TM;
|
|
||||||
|
|
||||||
/// PIC16Lowering - This object fully describes how to lower LLVM code to an
|
|
||||||
/// PIC16-specific SelectionDAG.
|
|
||||||
const PIC16TargetLowering &PIC16Lowering;
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit PIC16DAGToDAGISel(PIC16TargetMachine &tm) :
|
|
||||||
SelectionDAGISel(tm),
|
|
||||||
TM(tm), PIC16Lowering(*TM.getTargetLowering()) {}
|
|
||||||
|
|
||||||
// Pass Name
|
|
||||||
virtual const char *getPassName() const {
|
|
||||||
return "PIC16 DAG->DAG Pattern Instruction Selection";
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
// Include the pieces autogenerated from the target description.
|
|
||||||
#include "PIC16GenDAGISel.inc"
|
|
||||||
|
|
||||||
SDNode *Select(SDNode *N);
|
|
||||||
|
|
||||||
// Match direct address complex pattern.
|
|
||||||
bool SelectDirectAddr(SDValue N, SDValue &Address);
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,253 +0,0 @@
|
||||||
//===-- PIC16ISelLowering.h - PIC16 DAG Lowering Interface ------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file defines the interfaces that PIC16 uses to lower LLVM code into a
|
|
||||||
// selection DAG.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16ISELLOWERING_H
|
|
||||||
#define PIC16ISELLOWERING_H
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16Subtarget.h"
|
|
||||||
#include "llvm/CodeGen/SelectionDAG.h"
|
|
||||||
#include "llvm/Target/TargetLowering.h"
|
|
||||||
#include <map>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
namespace PIC16ISD {
|
|
||||||
enum NodeType {
|
|
||||||
// Start the numbering from where ISD NodeType finishes.
|
|
||||||
FIRST_NUMBER = ISD::BUILTIN_OP_END,
|
|
||||||
|
|
||||||
Lo, // Low 8-bits of GlobalAddress.
|
|
||||||
Hi, // High 8-bits of GlobalAddress.
|
|
||||||
PIC16Load,
|
|
||||||
PIC16LdArg, // This is replica of PIC16Load but used to load function
|
|
||||||
// arguments and is being used for facilitating for some
|
|
||||||
// store removal optimizations.
|
|
||||||
|
|
||||||
PIC16LdWF,
|
|
||||||
PIC16Store,
|
|
||||||
PIC16StWF,
|
|
||||||
Banksel,
|
|
||||||
MTLO, // Move to low part of FSR
|
|
||||||
MTHI, // Move to high part of FSR
|
|
||||||
MTPCLATH, // Move to PCLATCH
|
|
||||||
PIC16Connect, // General connector for PIC16 nodes
|
|
||||||
BCF,
|
|
||||||
LSLF, // PIC16 Logical shift left
|
|
||||||
LRLF, // PIC16 Logical shift right
|
|
||||||
RLF, // Rotate left through carry
|
|
||||||
RRF, // Rotate right through carry
|
|
||||||
CALL, // PIC16 Call instruction
|
|
||||||
CALLW, // PIC16 CALLW instruction
|
|
||||||
SUBCC, // Compare for equality or inequality.
|
|
||||||
SELECT_ICC, // Pseudo to be caught in scheduler and expanded to brcond.
|
|
||||||
BRCOND, // Conditional branch.
|
|
||||||
RET, // Return.
|
|
||||||
Dummy
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep track of different address spaces.
|
|
||||||
enum AddressSpace {
|
|
||||||
RAM_SPACE = 0, // RAM address space
|
|
||||||
ROM_SPACE = 1 // ROM address space number is 1
|
|
||||||
};
|
|
||||||
enum PIC16Libcall {
|
|
||||||
MUL_I8 = RTLIB::UNKNOWN_LIBCALL + 1,
|
|
||||||
SRA_I8,
|
|
||||||
SLL_I8,
|
|
||||||
SRL_I8,
|
|
||||||
PIC16UnknownCall
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===--------------------------------------------------------------------===//
|
|
||||||
// TargetLowering Implementation
|
|
||||||
//===--------------------------------------------------------------------===//
|
|
||||||
class PIC16TargetLowering : public TargetLowering {
|
|
||||||
public:
|
|
||||||
explicit PIC16TargetLowering(PIC16TargetMachine &TM);
|
|
||||||
|
|
||||||
/// getTargetNodeName - This method returns the name of a target specific
|
|
||||||
/// DAG node.
|
|
||||||
virtual const char *getTargetNodeName(unsigned Opcode) const;
|
|
||||||
/// getSetCCResultType - Return the ISD::SETCC ValueType
|
|
||||||
virtual MVT::SimpleValueType getSetCCResultType(EVT ValType) const;
|
|
||||||
virtual MVT::SimpleValueType getCmpLibcallReturnType() const;
|
|
||||||
SDValue LowerShift(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
SDValue LowerMUL(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
SDValue LowerADD(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
SDValue LowerSUB(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
SDValue LowerBinOp(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
// Call returns
|
|
||||||
SDValue
|
|
||||||
LowerDirectCallReturn(SDValue RetLabel, SDValue Chain, SDValue InFlag,
|
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
||||||
DebugLoc dl, SelectionDAG &DAG,
|
|
||||||
SmallVectorImpl<SDValue> &InVals) const;
|
|
||||||
SDValue
|
|
||||||
LowerIndirectCallReturn(SDValue Chain, SDValue InFlag,
|
|
||||||
SDValue DataAddr_Lo, SDValue DataAddr_Hi,
|
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
||||||
DebugLoc dl, SelectionDAG &DAG,
|
|
||||||
SmallVectorImpl<SDValue> &InVals) const;
|
|
||||||
|
|
||||||
// Call arguments
|
|
||||||
SDValue
|
|
||||||
LowerDirectCallArguments(SDValue ArgLabel, SDValue Chain, SDValue InFlag,
|
|
||||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
||||||
const SmallVectorImpl<SDValue> &OutVals,
|
|
||||||
DebugLoc dl, SelectionDAG &DAG) const;
|
|
||||||
|
|
||||||
SDValue
|
|
||||||
LowerIndirectCallArguments(SDValue Chain, SDValue InFlag,
|
|
||||||
SDValue DataAddr_Lo, SDValue DataAddr_Hi,
|
|
||||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
||||||
const SmallVectorImpl<SDValue> &OutVals,
|
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
||||||
DebugLoc dl, SelectionDAG &DAG) const;
|
|
||||||
|
|
||||||
SDValue LowerBR_CC(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
SDValue getPIC16Cmp(SDValue LHS, SDValue RHS, unsigned OrigCC, SDValue &CC,
|
|
||||||
SelectionDAG &DAG, DebugLoc dl) const;
|
|
||||||
virtual MachineBasicBlock *
|
|
||||||
EmitInstrWithCustomInserter(MachineInstr *MI,
|
|
||||||
MachineBasicBlock *MBB) const;
|
|
||||||
|
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
|
|
||||||
virtual void ReplaceNodeResults(SDNode *N,
|
|
||||||
SmallVectorImpl<SDValue> &Results,
|
|
||||||
SelectionDAG &DAG) const;
|
|
||||||
virtual void LowerOperationWrapper(SDNode *N,
|
|
||||||
SmallVectorImpl<SDValue> &Results,
|
|
||||||
SelectionDAG &DAG) const;
|
|
||||||
|
|
||||||
virtual SDValue
|
|
||||||
LowerFormalArguments(SDValue Chain,
|
|
||||||
CallingConv::ID CallConv,
|
|
||||||
bool isVarArg,
|
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
||||||
DebugLoc dl, SelectionDAG &DAG,
|
|
||||||
SmallVectorImpl<SDValue> &InVals) const;
|
|
||||||
|
|
||||||
virtual SDValue
|
|
||||||
LowerCall(SDValue Chain, SDValue Callee,
|
|
||||||
CallingConv::ID CallConv, bool isVarArg, bool &isTailCall,
|
|
||||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
||||||
const SmallVectorImpl<SDValue> &OutVals,
|
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins,
|
|
||||||
DebugLoc dl, SelectionDAG &DAG,
|
|
||||||
SmallVectorImpl<SDValue> &InVals) const;
|
|
||||||
|
|
||||||
virtual SDValue
|
|
||||||
LowerReturn(SDValue Chain,
|
|
||||||
CallingConv::ID CallConv, bool isVarArg,
|
|
||||||
const SmallVectorImpl<ISD::OutputArg> &Outs,
|
|
||||||
const SmallVectorImpl<SDValue> &OutVals,
|
|
||||||
DebugLoc dl, SelectionDAG &DAG) const;
|
|
||||||
|
|
||||||
SDValue ExpandStore(SDNode *N, SelectionDAG &DAG) const;
|
|
||||||
SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG) const;
|
|
||||||
SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) const;
|
|
||||||
SDValue ExpandExternalSymbol(SDNode *N, SelectionDAG &DAG) const;
|
|
||||||
SDValue ExpandFrameIndex(SDNode *N, SelectionDAG &DAG) const;
|
|
||||||
|
|
||||||
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
|
||||||
SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
|
||||||
SDValue PerformStoreCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
|
||||||
|
|
||||||
// This function returns the Tmp Offset for FrameIndex. If any TmpOffset
|
|
||||||
// already exists for the FI then it returns the same else it creates the
|
|
||||||
// new offset and returns.
|
|
||||||
unsigned GetTmpOffsetForFI(unsigned FI, unsigned slot_size,
|
|
||||||
MachineFunction &MF) const;
|
|
||||||
void ResetTmpOffsetMap(SelectionDAG &DAG) const;
|
|
||||||
void InitReservedFrameCount(const Function *F,
|
|
||||||
SelectionDAG &DAG) const;
|
|
||||||
|
|
||||||
/// getFunctionAlignment - Return the Log2 alignment of this function.
|
|
||||||
virtual unsigned getFunctionAlignment(const Function *) const {
|
|
||||||
// FIXME: The function never seems to be aligned.
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
protected:
|
|
||||||
std::pair<const TargetRegisterClass*, uint8_t>
|
|
||||||
findRepresentativeClass(EVT VT) const;
|
|
||||||
private:
|
|
||||||
// If the Node is a BUILD_PAIR representing a direct Address,
|
|
||||||
// then this function will return true.
|
|
||||||
bool isDirectAddress(const SDValue &Op) const;
|
|
||||||
|
|
||||||
// If the Node is a DirectAddress in ROM_SPACE then this
|
|
||||||
// function will return true
|
|
||||||
bool isRomAddress(const SDValue &Op) const;
|
|
||||||
|
|
||||||
// Extract the Lo and Hi component of Op.
|
|
||||||
void GetExpandedParts(SDValue Op, SelectionDAG &DAG, SDValue &Lo,
|
|
||||||
SDValue &Hi) const;
|
|
||||||
|
|
||||||
|
|
||||||
// Load pointer can be a direct or indirect address. In PIC16 direct
|
|
||||||
// addresses need Banksel and Indirect addresses need to be loaded to
|
|
||||||
// FSR first. Handle address specific cases here.
|
|
||||||
void LegalizeAddress(SDValue Ptr, SelectionDAG &DAG, SDValue &Chain,
|
|
||||||
SDValue &NewPtr, unsigned &Offset, DebugLoc dl) const;
|
|
||||||
|
|
||||||
// FrameIndex should be broken down into ExternalSymbol and FrameOffset.
|
|
||||||
void LegalizeFrameIndex(SDValue Op, SelectionDAG &DAG, SDValue &ES,
|
|
||||||
int &Offset) const;
|
|
||||||
|
|
||||||
// For indirect calls data address of the callee frame need to be
|
|
||||||
// extracted. This function fills the arguments DataAddr_Lo and
|
|
||||||
// DataAddr_Hi with the address of the callee frame.
|
|
||||||
void GetDataAddress(DebugLoc dl, SDValue Callee, SDValue &Chain,
|
|
||||||
SDValue &DataAddr_Lo, SDValue &DataAddr_Hi,
|
|
||||||
SelectionDAG &DAG) const;
|
|
||||||
|
|
||||||
// We can not have both operands of a binary operation in W.
|
|
||||||
// This function is used to put one operand on stack and generate a load.
|
|
||||||
SDValue ConvertToMemOperand(SDValue Op, SelectionDAG &DAG,
|
|
||||||
DebugLoc dl) const;
|
|
||||||
|
|
||||||
// This function checks if we need to put an operand of an operation on
|
|
||||||
// stack and generate a load or not.
|
|
||||||
// DAG parameter is required to access DAG information during
|
|
||||||
// analysis.
|
|
||||||
bool NeedToConvertToMemOp(SDValue Op, unsigned &MemOp,
|
|
||||||
SelectionDAG &DAG) const;
|
|
||||||
|
|
||||||
/// Subtarget - Keep a pointer to the PIC16Subtarget around so that we can
|
|
||||||
/// make the right decision when generating code for different targets.
|
|
||||||
const PIC16Subtarget *Subtarget;
|
|
||||||
|
|
||||||
|
|
||||||
// Extending the LIB Call framework of LLVM
|
|
||||||
// to hold the names of PIC16Libcalls.
|
|
||||||
const char *PIC16LibcallNames[PIC16ISD::PIC16UnknownCall];
|
|
||||||
|
|
||||||
// To set and retrieve the lib call names.
|
|
||||||
void setPIC16LibcallName(PIC16ISD::PIC16Libcall Call, const char *Name);
|
|
||||||
const char *getPIC16LibcallName(PIC16ISD::PIC16Libcall Call) const;
|
|
||||||
|
|
||||||
// Make PIC16 Libcall.
|
|
||||||
SDValue MakePIC16Libcall(PIC16ISD::PIC16Libcall Call, EVT RetVT,
|
|
||||||
const SDValue *Ops, unsigned NumOps, bool isSigned,
|
|
||||||
SelectionDAG &DAG, DebugLoc dl) const;
|
|
||||||
|
|
||||||
// Check if operation has a direct load operand.
|
|
||||||
inline bool isDirectLoad(const SDValue Op) const;
|
|
||||||
};
|
|
||||||
} // namespace llvm
|
|
||||||
|
|
||||||
#endif // PIC16ISELLOWERING_H
|
|
|
@ -1,117 +0,0 @@
|
||||||
//===- PIC16InstrFormats.td - PIC16 Instruction Formats-------*- tblgen -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Describe PIC16 instructions format
|
|
||||||
//
|
|
||||||
// All the possible PIC16 fields are:
|
|
||||||
//
|
|
||||||
// opcode - operation code.
|
|
||||||
// f - 7-bit register file address.
|
|
||||||
// d - 1-bit direction specifier
|
|
||||||
// k - 8/11 bit literals
|
|
||||||
// b - 3 bits bit num specifier
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// Generic PIC16 Format
|
|
||||||
// PIC16 Instructions are 14-bit wide.
|
|
||||||
|
|
||||||
// FIXME: Add Cooper Specific Formats if any.
|
|
||||||
|
|
||||||
class PIC16Inst<dag outs, dag ins, string asmstr, list<dag> pattern>
|
|
||||||
: Instruction {
|
|
||||||
field bits<14> Inst;
|
|
||||||
|
|
||||||
let Namespace = "PIC16";
|
|
||||||
dag OutOperandList = outs;
|
|
||||||
dag InOperandList = ins;
|
|
||||||
let AsmString = asmstr;
|
|
||||||
let Pattern = pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Byte Oriented instruction class in PIC16 : <|opcode|d|f|>
|
|
||||||
// opcode = 6 bits.
|
|
||||||
// d = direction = 1 bit.
|
|
||||||
// f = file register address = 7 bits.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
class ByteFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
|
|
||||||
list<dag> pattern>
|
|
||||||
:PIC16Inst<outs, ins, asmstr, pattern> {
|
|
||||||
bits<1> d;
|
|
||||||
bits<7> f;
|
|
||||||
|
|
||||||
let Inst{13-8} = opcode;
|
|
||||||
|
|
||||||
let Inst{7} = d;
|
|
||||||
let Inst{6-0} = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Bit Oriented instruction class in PIC16 : <|opcode|b|f|>
|
|
||||||
// opcode = 4 bits.
|
|
||||||
// b = bit specifier = 3 bits.
|
|
||||||
// f = file register address = 7 bits.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
class BitFormat<bits<4> opcode, dag outs, dag ins, string asmstr,
|
|
||||||
list<dag> pattern>
|
|
||||||
: PIC16Inst<outs, ins, asmstr, pattern> {
|
|
||||||
bits<3> b;
|
|
||||||
bits<7> f;
|
|
||||||
|
|
||||||
let Inst{13-10} = opcode;
|
|
||||||
|
|
||||||
let Inst{9-7} = b;
|
|
||||||
let Inst{6-0} = f;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Literal Format instruction class in PIC16 : <|opcode|k|>
|
|
||||||
// opcode = 6 bits
|
|
||||||
// k = literal = 8 bits
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
class LiteralFormat<bits<6> opcode, dag outs, dag ins, string asmstr,
|
|
||||||
list<dag> pattern>
|
|
||||||
: PIC16Inst<outs, ins, asmstr, pattern> {
|
|
||||||
bits<8> k;
|
|
||||||
|
|
||||||
let Inst{13-8} = opcode;
|
|
||||||
|
|
||||||
let Inst{7-0} = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Control Format instruction class in PIC16 : <|opcode|k|>
|
|
||||||
// opcode = 3 bits.
|
|
||||||
// k = jump address = 11 bits.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
class ControlFormat<bits<3> opcode, dag outs, dag ins, string asmstr,
|
|
||||||
list<dag> pattern>
|
|
||||||
: PIC16Inst<outs, ins, asmstr, pattern> {
|
|
||||||
bits<11> k;
|
|
||||||
|
|
||||||
let Inst{13-11} = opcode;
|
|
||||||
|
|
||||||
let Inst{10-0} = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Pseudo instruction class in PIC16
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
class Pseudo<dag outs, dag ins, string asmstr, list<dag> pattern>
|
|
||||||
: PIC16Inst<outs, ins, asmstr, pattern> {
|
|
||||||
let Inst{13-6} = 0;
|
|
||||||
}
|
|
|
@ -1,224 +0,0 @@
|
||||||
//===- PIC16InstrInfo.cpp - PIC16 Instruction Information -----------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the PIC16 implementation of the TargetInstrInfo class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16ABINames.h"
|
|
||||||
#include "PIC16InstrInfo.h"
|
|
||||||
#include "PIC16TargetMachine.h"
|
|
||||||
#include "PIC16GenInstrInfo.inc"
|
|
||||||
#include "llvm/Function.h"
|
|
||||||
#include "llvm/ADT/STLExtras.h"
|
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
||||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
// FIXME: Add the subtarget support on this constructor.
|
|
||||||
PIC16InstrInfo::PIC16InstrInfo(PIC16TargetMachine &tm)
|
|
||||||
: TargetInstrInfoImpl(PIC16Insts, array_lengthof(PIC16Insts)),
|
|
||||||
TM(tm),
|
|
||||||
RegInfo(*this, *TM.getSubtargetImpl()) {}
|
|
||||||
|
|
||||||
|
|
||||||
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
|
||||||
/// store to a stack slot, return the virtual or physical register number of
|
|
||||||
/// the source reg along with the FrameIndex of the loaded stack slot.
|
|
||||||
/// If not, return 0. This predicate must return 0 if the instruction has
|
|
||||||
/// any side effects other than storing to the stack slot.
|
|
||||||
unsigned PIC16InstrInfo::isStoreToStackSlot(const MachineInstr *MI,
|
|
||||||
int &FrameIndex) const {
|
|
||||||
if (MI->getOpcode() == PIC16::movwf
|
|
||||||
&& MI->getOperand(0).isReg()
|
|
||||||
&& MI->getOperand(1).isSymbol()) {
|
|
||||||
FrameIndex = MI->getOperand(1).getIndex();
|
|
||||||
return MI->getOperand(0).getReg();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
|
||||||
/// load from a stack slot, return the virtual or physical register number of
|
|
||||||
/// the dest reg along with the FrameIndex of the stack slot.
|
|
||||||
/// If not, return 0. This predicate must return 0 if the instruction has
|
|
||||||
/// any side effects other than storing to the stack slot.
|
|
||||||
unsigned PIC16InstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
|
|
||||||
int &FrameIndex) const {
|
|
||||||
if (MI->getOpcode() == PIC16::movf
|
|
||||||
&& MI->getOperand(0).isReg()
|
|
||||||
&& MI->getOperand(1).isSymbol()) {
|
|
||||||
FrameIndex = MI->getOperand(1).getIndex();
|
|
||||||
return MI->getOperand(0).getReg();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void PIC16InstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator I,
|
|
||||||
unsigned SrcReg, bool isKill, int FI,
|
|
||||||
const TargetRegisterClass *RC,
|
|
||||||
const TargetRegisterInfo *TRI) const {
|
|
||||||
const PIC16TargetLowering *PTLI = TM.getTargetLowering();
|
|
||||||
DebugLoc DL;
|
|
||||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
|
||||||
|
|
||||||
const Function *Func = MBB.getParent()->getFunction();
|
|
||||||
const std::string FuncName = Func->getName();
|
|
||||||
|
|
||||||
const char *tmpName = ESNames::createESName(PAN::getTempdataLabel(FuncName));
|
|
||||||
|
|
||||||
// On the order of operands here: think "movwf SrcReg, tmp_slot, offset".
|
|
||||||
if (RC == PIC16::GPRRegisterClass) {
|
|
||||||
//MachineFunction &MF = *MBB.getParent();
|
|
||||||
//MachineRegisterInfo &RI = MF.getRegInfo();
|
|
||||||
BuildMI(MBB, I, DL, get(PIC16::movwf))
|
|
||||||
.addReg(SrcReg, getKillRegState(isKill))
|
|
||||||
.addImm(PTLI->GetTmpOffsetForFI(FI, 1, *MBB.getParent()))
|
|
||||||
.addExternalSymbol(tmpName)
|
|
||||||
.addImm(1); // Emit banksel for it.
|
|
||||||
}
|
|
||||||
else if (RC == PIC16::FSR16RegisterClass) {
|
|
||||||
// This is a 16-bit register and the frameindex given by llvm is of
|
|
||||||
// size two here. Break this index N into two zero based indexes and
|
|
||||||
// put one into the map. The second one is always obtained by adding 1
|
|
||||||
// to the first zero based index. In fact it is going to use 3 slots
|
|
||||||
// as saving FSRs corrupts W also and hence we need to save/restore W also.
|
|
||||||
|
|
||||||
unsigned opcode = (SrcReg == PIC16::FSR0) ? PIC16::save_fsr0
|
|
||||||
: PIC16::save_fsr1;
|
|
||||||
BuildMI(MBB, I, DL, get(opcode))
|
|
||||||
.addReg(SrcReg, getKillRegState(isKill))
|
|
||||||
.addImm(PTLI->GetTmpOffsetForFI(FI, 3, *MBB.getParent()))
|
|
||||||
.addExternalSymbol(tmpName)
|
|
||||||
.addImm(1); // Emit banksel for it.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
llvm_unreachable("Can't store this register to stack slot");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16InstrInfo::loadRegFromStackSlot(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator I,
|
|
||||||
unsigned DestReg, int FI,
|
|
||||||
const TargetRegisterClass *RC,
|
|
||||||
const TargetRegisterInfo *TRI) const {
|
|
||||||
const PIC16TargetLowering *PTLI = TM.getTargetLowering();
|
|
||||||
DebugLoc DL;
|
|
||||||
if (I != MBB.end()) DL = I->getDebugLoc();
|
|
||||||
|
|
||||||
const Function *Func = MBB.getParent()->getFunction();
|
|
||||||
const std::string FuncName = Func->getName();
|
|
||||||
|
|
||||||
const char *tmpName = ESNames::createESName(PAN::getTempdataLabel(FuncName));
|
|
||||||
|
|
||||||
// On the order of operands here: think "movf FrameIndex, W".
|
|
||||||
if (RC == PIC16::GPRRegisterClass) {
|
|
||||||
//MachineFunction &MF = *MBB.getParent();
|
|
||||||
//MachineRegisterInfo &RI = MF.getRegInfo();
|
|
||||||
BuildMI(MBB, I, DL, get(PIC16::movf), DestReg)
|
|
||||||
.addImm(PTLI->GetTmpOffsetForFI(FI, 1, *MBB.getParent()))
|
|
||||||
.addExternalSymbol(tmpName)
|
|
||||||
.addImm(1); // Emit banksel for it.
|
|
||||||
}
|
|
||||||
else if (RC == PIC16::FSR16RegisterClass) {
|
|
||||||
// This is a 16-bit register and the frameindex given by llvm is of
|
|
||||||
// size two here. Break this index N into two zero based indexes and
|
|
||||||
// put one into the map. The second one is always obtained by adding 1
|
|
||||||
// to the first zero based index. In fact it is going to use 3 slots
|
|
||||||
// as saving FSRs corrupts W also and hence we need to save/restore W also.
|
|
||||||
|
|
||||||
unsigned opcode = (DestReg == PIC16::FSR0) ? PIC16::restore_fsr0
|
|
||||||
: PIC16::restore_fsr1;
|
|
||||||
BuildMI(MBB, I, DL, get(opcode), DestReg)
|
|
||||||
.addImm(PTLI->GetTmpOffsetForFI(FI, 3, *MBB.getParent()))
|
|
||||||
.addExternalSymbol(tmpName)
|
|
||||||
.addImm(1); // Emit banksel for it.
|
|
||||||
}
|
|
||||||
else
|
|
||||||
llvm_unreachable("Can't load this register from stack slot");
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
|
||||||
unsigned DestReg, unsigned SrcReg,
|
|
||||||
bool KillSrc) const {
|
|
||||||
unsigned Opc;
|
|
||||||
if (PIC16::FSR16RegClass.contains(DestReg, SrcReg))
|
|
||||||
Opc = PIC16::copy_fsr;
|
|
||||||
else if (PIC16::GPRRegClass.contains(DestReg, SrcReg))
|
|
||||||
Opc = PIC16::copy_w;
|
|
||||||
else
|
|
||||||
llvm_unreachable("Impossible reg-to-reg copy");
|
|
||||||
|
|
||||||
BuildMI(MBB, I, DL, get(Opc), DestReg)
|
|
||||||
.addReg(SrcReg, getKillRegState(KillSrc));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// InsertBranch - Insert a branch into the end of the specified
|
|
||||||
/// MachineBasicBlock. This operands to this method are the same as those
|
|
||||||
/// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch
|
|
||||||
/// returns success and when an unconditional branch (TBB is non-null, FBB is
|
|
||||||
/// null, Cond is empty) needs to be inserted. It returns the number of
|
|
||||||
/// instructions inserted.
|
|
||||||
unsigned PIC16InstrInfo::
|
|
||||||
InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
||||||
MachineBasicBlock *FBB,
|
|
||||||
const SmallVectorImpl<MachineOperand> &Cond,
|
|
||||||
DebugLoc DL) const {
|
|
||||||
// Shouldn't be a fall through.
|
|
||||||
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
|
|
||||||
|
|
||||||
if (FBB == 0) { // One way branch.
|
|
||||||
if (Cond.empty()) {
|
|
||||||
// Unconditional branch?
|
|
||||||
BuildMI(&MBB, DL, get(PIC16::br_uncond)).addMBB(TBB);
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: If the there are some conditions specified then conditional branch
|
|
||||||
// should be generated.
|
|
||||||
// For the time being no instruction is being generated therefore
|
|
||||||
// returning NULL.
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PIC16InstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock *&TBB,
|
|
||||||
MachineBasicBlock *&FBB,
|
|
||||||
SmallVectorImpl<MachineOperand> &Cond,
|
|
||||||
bool AllowModify) const {
|
|
||||||
MachineBasicBlock::iterator I = MBB.end();
|
|
||||||
if (I == MBB.begin())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Get the terminator instruction.
|
|
||||||
--I;
|
|
||||||
while (I->isDebugValue()) {
|
|
||||||
if (I == MBB.begin())
|
|
||||||
return true;
|
|
||||||
--I;
|
|
||||||
}
|
|
||||||
// Handle unconditional branches. If the unconditional branch's target is
|
|
||||||
// successor basic block then remove the unconditional branch.
|
|
||||||
if (I->getOpcode() == PIC16::br_uncond && AllowModify) {
|
|
||||||
if (MBB.isLayoutSuccessor(I->getOperand(0).getMBB())) {
|
|
||||||
TBB = 0;
|
|
||||||
I->eraseFromParent();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
|
@ -1,76 +0,0 @@
|
||||||
//===- PIC16InstrInfo.h - PIC16 Instruction Information----------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the niversity of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the PIC16 implementation of the TargetInstrInfo class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16INSTRUCTIONINFO_H
|
|
||||||
#define PIC16INSTRUCTIONINFO_H
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16RegisterInfo.h"
|
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
|
|
||||||
class PIC16InstrInfo : public TargetInstrInfoImpl
|
|
||||||
{
|
|
||||||
PIC16TargetMachine &TM;
|
|
||||||
const PIC16RegisterInfo RegInfo;
|
|
||||||
public:
|
|
||||||
explicit PIC16InstrInfo(PIC16TargetMachine &TM);
|
|
||||||
|
|
||||||
virtual const PIC16RegisterInfo &getRegisterInfo() const { return RegInfo; }
|
|
||||||
|
|
||||||
/// isLoadFromStackSlot - If the specified machine instruction is a direct
|
|
||||||
/// load from a stack slot, return the virtual or physical register number of
|
|
||||||
/// the destination along with the FrameIndex of the loaded stack slot. If
|
|
||||||
/// not, return 0. This predicate must return 0 if the instruction has
|
|
||||||
/// any side effects other than loading from the stack slot.
|
|
||||||
virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
|
|
||||||
int &FrameIndex) const;
|
|
||||||
|
|
||||||
/// isStoreToStackSlot - If the specified machine instruction is a direct
|
|
||||||
/// store to a stack slot, return the virtual or physical register number of
|
|
||||||
/// the source reg along with the FrameIndex of the loaded stack slot. If
|
|
||||||
/// not, return 0. This predicate must return 0 if the instruction has
|
|
||||||
/// any side effects other than storing to the stack slot.
|
|
||||||
virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
|
|
||||||
int &FrameIndex) const;
|
|
||||||
|
|
||||||
virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator MBBI,
|
|
||||||
unsigned SrcReg, bool isKill, int FrameIndex,
|
|
||||||
const TargetRegisterClass *RC,
|
|
||||||
const TargetRegisterInfo *TRI) const;
|
|
||||||
|
|
||||||
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator MBBI,
|
|
||||||
unsigned DestReg, int FrameIndex,
|
|
||||||
const TargetRegisterClass *RC,
|
|
||||||
const TargetRegisterInfo *TRI) const;
|
|
||||||
virtual void copyPhysReg(MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator I, DebugLoc DL,
|
|
||||||
unsigned DestReg, unsigned SrcReg,
|
|
||||||
bool KillSrc) const;
|
|
||||||
virtual
|
|
||||||
unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
|
|
||||||
MachineBasicBlock *FBB,
|
|
||||||
const SmallVectorImpl<MachineOperand> &Cond,
|
|
||||||
DebugLoc DL) const;
|
|
||||||
virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
|
|
||||||
MachineBasicBlock *&FBB,
|
|
||||||
SmallVectorImpl<MachineOperand> &Cond,
|
|
||||||
bool AllowModify) const;
|
|
||||||
};
|
|
||||||
} // namespace llvm
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,540 +0,0 @@
|
||||||
//===- PIC16InstrInfo.td - PIC16 Instruction defs -------------*- tblgen-*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file describes the PIC16 instructions in TableGen format.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 Specific Type Constraints.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
class SDTCisI8<int OpNum> : SDTCisVT<OpNum, i8>;
|
|
||||||
class SDTCisI16<int OpNum> : SDTCisVT<OpNum, i16>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 Specific Type Profiles.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// Generic type profiles for i8/i16 unary/binary operations.
|
|
||||||
// Taking one i8 or i16 and producing void.
|
|
||||||
def SDTI8VoidOp : SDTypeProfile<0, 1, [SDTCisI8<0>]>;
|
|
||||||
def SDTI16VoidOp : SDTypeProfile<0, 1, [SDTCisI16<0>]>;
|
|
||||||
|
|
||||||
// Taking one value and producing an output of same type.
|
|
||||||
def SDTI8UnaryOp : SDTypeProfile<1, 1, [SDTCisI8<0>, SDTCisI8<1>]>;
|
|
||||||
def SDTI16UnaryOp : SDTypeProfile<1, 1, [SDTCisI16<0>, SDTCisI16<1>]>;
|
|
||||||
|
|
||||||
// Taking two values and producing an output of same type.
|
|
||||||
def SDTI8BinOp : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>]>;
|
|
||||||
def SDTI16BinOp : SDTypeProfile<1, 2, [SDTCisI16<0>, SDTCisI16<1>,
|
|
||||||
SDTCisI16<2>]>;
|
|
||||||
|
|
||||||
// Node specific type profiles.
|
|
||||||
def SDT_PIC16Load : SDTypeProfile<1, 3, [SDTCisI8<0>, SDTCisI8<1>,
|
|
||||||
SDTCisI8<2>, SDTCisI8<3>]>;
|
|
||||||
|
|
||||||
def SDT_PIC16Store : SDTypeProfile<0, 4, [SDTCisI8<0>, SDTCisI8<1>,
|
|
||||||
SDTCisI8<2>, SDTCisI8<3>]>;
|
|
||||||
|
|
||||||
def SDT_PIC16Connect : SDTypeProfile<1, 2, [SDTCisI8<0>, SDTCisI8<1>,
|
|
||||||
SDTCisI8<2>]>;
|
|
||||||
|
|
||||||
// PIC16ISD::CALL type prorile
|
|
||||||
def SDT_PIC16call : SDTypeProfile<0, -1, [SDTCisInt<0>]>;
|
|
||||||
def SDT_PIC16callw : SDTypeProfile<1, -1, [SDTCisInt<0>]>;
|
|
||||||
|
|
||||||
// PIC16ISD::BRCOND
|
|
||||||
def SDT_PIC16Brcond: SDTypeProfile<0, 2,
|
|
||||||
[SDTCisVT<0, OtherVT>, SDTCisI8<1>]>;
|
|
||||||
|
|
||||||
// PIC16ISD::BRCOND
|
|
||||||
def SDT_PIC16Selecticc: SDTypeProfile<1, 3,
|
|
||||||
[SDTCisI8<0>, SDTCisI8<1>, SDTCisI8<2>,
|
|
||||||
SDTCisI8<3>]>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 addressing modes matching via DAG.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
def diraddr : ComplexPattern<i8, 1, "SelectDirectAddr", [], []>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 Specific Node Definitions.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
def PIC16callseq_start : SDNode<"ISD::CALLSEQ_START", SDTI8VoidOp,
|
|
||||||
[SDNPHasChain, SDNPOutFlag]>;
|
|
||||||
def PIC16callseq_end : SDNode<"ISD::CALLSEQ_END", SDTI8VoidOp,
|
|
||||||
[SDNPHasChain, SDNPOptInFlag, SDNPOutFlag]>;
|
|
||||||
|
|
||||||
// Low 8-bits of GlobalAddress.
|
|
||||||
def PIC16Lo : SDNode<"PIC16ISD::Lo", SDTI8BinOp>;
|
|
||||||
|
|
||||||
// High 8-bits of GlobalAddress.
|
|
||||||
def PIC16Hi : SDNode<"PIC16ISD::Hi", SDTI8BinOp>;
|
|
||||||
|
|
||||||
// The MTHI and MTLO nodes are used only to match them in the incoming
|
|
||||||
// DAG for replacement by corresponding set_fsrhi, set_fsrlo insntructions.
|
|
||||||
// These nodes are not used for defining any instructions.
|
|
||||||
def MTLO : SDNode<"PIC16ISD::MTLO", SDTI8UnaryOp>;
|
|
||||||
def MTHI : SDNode<"PIC16ISD::MTHI", SDTI8UnaryOp>;
|
|
||||||
def MTPCLATH : SDNode<"PIC16ISD::MTPCLATH", SDTI8UnaryOp>;
|
|
||||||
|
|
||||||
// Node to generate Bank Select for a GlobalAddress.
|
|
||||||
def Banksel : SDNode<"PIC16ISD::Banksel", SDTI8UnaryOp>;
|
|
||||||
|
|
||||||
// Node to match a direct store operation.
|
|
||||||
def PIC16Store : SDNode<"PIC16ISD::PIC16Store", SDT_PIC16Store, [SDNPHasChain]>;
|
|
||||||
def PIC16StWF : SDNode<"PIC16ISD::PIC16StWF", SDT_PIC16Store,
|
|
||||||
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
|
||||||
|
|
||||||
// Node to match a direct load operation.
|
|
||||||
def PIC16Load : SDNode<"PIC16ISD::PIC16Load", SDT_PIC16Load, [SDNPHasChain]>;
|
|
||||||
def PIC16LdArg : SDNode<"PIC16ISD::PIC16LdArg", SDT_PIC16Load, [SDNPHasChain]>;
|
|
||||||
def PIC16LdWF : SDNode<"PIC16ISD::PIC16LdWF", SDT_PIC16Load,
|
|
||||||
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
|
||||||
def PIC16Connect: SDNode<"PIC16ISD::PIC16Connect", SDT_PIC16Connect, []>;
|
|
||||||
|
|
||||||
// Node to match PIC16 call
|
|
||||||
def PIC16call : SDNode<"PIC16ISD::CALL", SDT_PIC16call,
|
|
||||||
[SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
|
|
||||||
def PIC16callw : SDNode<"PIC16ISD::CALLW", SDT_PIC16callw,
|
|
||||||
[SDNPHasChain , SDNPOptInFlag, SDNPOutFlag]>;
|
|
||||||
|
|
||||||
// Node to match a comparison instruction.
|
|
||||||
def PIC16Subcc : SDNode<"PIC16ISD::SUBCC", SDTI8BinOp, [SDNPOutFlag]>;
|
|
||||||
|
|
||||||
// Node to match a conditional branch.
|
|
||||||
def PIC16Brcond : SDNode<"PIC16ISD::BRCOND", SDT_PIC16Brcond,
|
|
||||||
[SDNPHasChain, SDNPInFlag]>;
|
|
||||||
|
|
||||||
def PIC16Selecticc : SDNode<"PIC16ISD::SELECT_ICC", SDT_PIC16Selecticc,
|
|
||||||
[SDNPInFlag]>;
|
|
||||||
|
|
||||||
def PIC16ret : SDNode<"PIC16ISD::RET", SDTNone, [SDNPHasChain]>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 Operand Definitions.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
def i8mem : Operand<i8>;
|
|
||||||
def brtarget: Operand<OtherVT>;
|
|
||||||
|
|
||||||
// Operand for printing out a condition code.
|
|
||||||
let PrintMethod = "printCCOperand" in
|
|
||||||
def CCOp : Operand<i8>;
|
|
||||||
|
|
||||||
include "PIC16InstrFormats.td"
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 Common Classes.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// W = W Op F : Load the value from F and do Op to W.
|
|
||||||
let Constraints = "$src = $dst", mayLoad = 1 in
|
|
||||||
class BinOpFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
|
||||||
ByteFormat<OpCode, (outs GPR:$dst),
|
|
||||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
|
||||||
!strconcat(OpcStr, " $ptrlo + $offset, W"),
|
|
||||||
[(set GPR:$dst, (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
|
|
||||||
(i8 imm:$ptrhi),
|
|
||||||
(i8 imm:$offset))))]>;
|
|
||||||
|
|
||||||
// F = F Op W : Load the value from F, do op with W and store in F.
|
|
||||||
// This insn class is not marked as TwoAddress because the reg is
|
|
||||||
// being used as a source operand only. (Remember a TwoAddress insn
|
|
||||||
// needs a copy.)
|
|
||||||
let mayStore = 1 in
|
|
||||||
class BinOpWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
|
||||||
ByteFormat<OpCode, (outs),
|
|
||||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
|
||||||
!strconcat(OpcStr, " $ptrlo + $offset, F"),
|
|
||||||
[(PIC16Store (OpNode GPR:$src, (PIC16Load diraddr:$ptrlo,
|
|
||||||
(i8 imm:$ptrhi),
|
|
||||||
(i8 imm:$offset))),
|
|
||||||
diraddr:$ptrlo,
|
|
||||||
(i8 imm:$ptrhi), (i8 imm:$offset)
|
|
||||||
)]>;
|
|
||||||
|
|
||||||
// W = W Op L : Do Op of L with W and place result in W.
|
|
||||||
let Constraints = "$src = $dst" in
|
|
||||||
class BinOpWL<bits<6> opcode, string OpcStr, SDNode OpNode> :
|
|
||||||
LiteralFormat<opcode, (outs GPR:$dst),
|
|
||||||
(ins GPR:$src, i8imm:$literal),
|
|
||||||
!strconcat(OpcStr, " $literal"),
|
|
||||||
[(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 Instructions.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// Pseudo-instructions.
|
|
||||||
def ADJCALLSTACKDOWN : Pseudo<(outs), (ins i8imm:$amt),
|
|
||||||
"!ADJCALLSTACKDOWN $amt",
|
|
||||||
[(PIC16callseq_start imm:$amt)]>;
|
|
||||||
|
|
||||||
def ADJCALLSTACKUP : Pseudo<(outs), (ins i8imm:$amt),
|
|
||||||
"!ADJCALLSTACKUP $amt",
|
|
||||||
[(PIC16callseq_end imm:$amt)]>;
|
|
||||||
|
|
||||||
//-----------------------------------
|
|
||||||
// Vaious movlw insn patterns.
|
|
||||||
//-----------------------------------
|
|
||||||
let isReMaterializable = 1 in {
|
|
||||||
// Move 8-bit literal to W.
|
|
||||||
def movlw : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src),
|
|
||||||
"movlw $src",
|
|
||||||
[(set GPR:$dst, (i8 imm:$src))]>;
|
|
||||||
|
|
||||||
// Move a Lo(TGA) to W.
|
|
||||||
def movlw_lo_1 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
|
|
||||||
"movlw LOW(${src} + ${src2})",
|
|
||||||
[(set GPR:$dst, (PIC16Lo tglobaladdr:$src, imm:$src2 ))]>;
|
|
||||||
|
|
||||||
// Move a Lo(TES) to W.
|
|
||||||
def movlw_lo_2 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
|
|
||||||
"movlw LOW(${src} + ${src2})",
|
|
||||||
[(set GPR:$dst, (PIC16Lo texternalsym:$src, imm:$src2 ))]>;
|
|
||||||
|
|
||||||
// Move a Hi(TGA) to W.
|
|
||||||
def movlw_hi_1 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
|
|
||||||
"movlw HIGH(${src} + ${src2})",
|
|
||||||
[(set GPR:$dst, (PIC16Hi tglobaladdr:$src, imm:$src2))]>;
|
|
||||||
|
|
||||||
// Move a Hi(TES) to W.
|
|
||||||
def movlw_hi_2 : BitFormat<12, (outs GPR:$dst), (ins i8imm:$src, i8imm:$src2),
|
|
||||||
"movlw HIGH(${src} + ${src2})",
|
|
||||||
[(set GPR:$dst, (PIC16Hi texternalsym:$src, imm:$src2))]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------
|
|
||||||
// FSR setting insns.
|
|
||||||
//-------------------
|
|
||||||
// These insns are matched via a DAG replacement pattern.
|
|
||||||
def set_fsrlo:
|
|
||||||
ByteFormat<0, (outs FSR16:$fsr),
|
|
||||||
(ins GPR:$val),
|
|
||||||
"movwf ${fsr}L",
|
|
||||||
[]>;
|
|
||||||
|
|
||||||
let Constraints = "$src = $dst" in
|
|
||||||
def set_fsrhi:
|
|
||||||
ByteFormat<0, (outs FSR16:$dst),
|
|
||||||
(ins FSR16:$src, GPR:$val),
|
|
||||||
"movwf ${dst}H",
|
|
||||||
[]>;
|
|
||||||
|
|
||||||
def set_pclath:
|
|
||||||
ByteFormat<0, (outs PCLATHR:$dst),
|
|
||||||
(ins GPR:$val),
|
|
||||||
"movwf ${dst}",
|
|
||||||
[(set PCLATHR:$dst , (MTPCLATH GPR:$val))]>;
|
|
||||||
|
|
||||||
//----------------------------
|
|
||||||
// copyPhysReg
|
|
||||||
// copyPhysReg insns. These are dummy. They should always be deleted
|
|
||||||
// by the optimizer and never be present in the final generated code.
|
|
||||||
// if they are, then we have to write correct macros for these insns.
|
|
||||||
//----------------------------
|
|
||||||
def copy_fsr:
|
|
||||||
Pseudo<(outs FSR16:$dst), (ins FSR16:$src), "copy_fsr $dst, $src", []>;
|
|
||||||
|
|
||||||
def copy_w:
|
|
||||||
Pseudo<(outs GPR:$dst), (ins GPR:$src), "copy_w $dst, $src", []>;
|
|
||||||
|
|
||||||
class SAVE_FSR<string OpcStr>:
|
|
||||||
Pseudo<(outs),
|
|
||||||
(ins FSR16:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
|
||||||
!strconcat(OpcStr, " $ptrlo, $offset"),
|
|
||||||
[]>;
|
|
||||||
|
|
||||||
def save_fsr0: SAVE_FSR<"save_fsr0">;
|
|
||||||
def save_fsr1: SAVE_FSR<"save_fsr1">;
|
|
||||||
|
|
||||||
class RESTORE_FSR<string OpcStr>:
|
|
||||||
Pseudo<(outs FSR16:$dst),
|
|
||||||
(ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
|
||||||
!strconcat(OpcStr, " $ptrlo, $offset"),
|
|
||||||
[]>;
|
|
||||||
|
|
||||||
def restore_fsr0: RESTORE_FSR<"restore_fsr0">;
|
|
||||||
def restore_fsr1: RESTORE_FSR<"restore_fsr1">;
|
|
||||||
|
|
||||||
//--------------------------
|
|
||||||
// Store to memory
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
// Direct store.
|
|
||||||
// Input operands are: val = W, ptrlo = GA, offset = offset, ptrhi = banksel.
|
|
||||||
let mayStore = 1 in
|
|
||||||
class MOVWF_INSN<bits<6> OpCode, SDNode OpNodeDest, SDNode Op>:
|
|
||||||
ByteFormat<0, (outs),
|
|
||||||
(ins GPR:$val, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
|
||||||
"movwf ${ptrlo} + ${offset}",
|
|
||||||
[(Op GPR:$val, OpNodeDest:$ptrlo, (i8 imm:$ptrhi),
|
|
||||||
(i8 imm:$offset))]>;
|
|
||||||
|
|
||||||
// Store W to a Global Address.
|
|
||||||
def movwf : MOVWF_INSN<0, tglobaladdr, PIC16Store>;
|
|
||||||
|
|
||||||
// Store W to an External Symobol.
|
|
||||||
def movwf_1 : MOVWF_INSN<0, texternalsym, PIC16Store>;
|
|
||||||
|
|
||||||
// Store with InFlag and OutFlag
|
|
||||||
// This is same as movwf_1 but has a flag. A flag is required to
|
|
||||||
// order the stores while passing the params to function.
|
|
||||||
def movwf_2 : MOVWF_INSN<0, texternalsym, PIC16StWF>;
|
|
||||||
|
|
||||||
// Indirect store. Matched via a DAG replacement pattern.
|
|
||||||
def store_indirect :
|
|
||||||
ByteFormat<0, (outs),
|
|
||||||
(ins GPR:$val, FSR16:$fsr, i8imm:$offset),
|
|
||||||
"movwi $offset[$fsr]",
|
|
||||||
[]>;
|
|
||||||
|
|
||||||
//----------------------------
|
|
||||||
// Load from memory
|
|
||||||
//----------------------------
|
|
||||||
// Direct load.
|
|
||||||
// Input Operands are: ptrlo = GA, offset = offset, ptrhi = banksel.
|
|
||||||
// Output: dst = W
|
|
||||||
let Defs = [STATUS], mayLoad = 1 in
|
|
||||||
class MOVF_INSN<bits<6> OpCode, SDNode OpNodeSrc, SDNode Op>:
|
|
||||||
ByteFormat<0, (outs GPR:$dst),
|
|
||||||
(ins i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
|
||||||
"movf ${ptrlo} + ${offset}, W",
|
|
||||||
[(set GPR:$dst,
|
|
||||||
(Op OpNodeSrc:$ptrlo, (i8 imm:$ptrhi),
|
|
||||||
(i8 imm:$offset)))]>;
|
|
||||||
|
|
||||||
// Load from a GA.
|
|
||||||
def movf : MOVF_INSN<0, tglobaladdr, PIC16Load>;
|
|
||||||
|
|
||||||
// Load from an ES.
|
|
||||||
def movf_1 : MOVF_INSN<0, texternalsym, PIC16Load>;
|
|
||||||
def movf_1_1 : MOVF_INSN<0, texternalsym, PIC16LdArg>;
|
|
||||||
|
|
||||||
// Load with InFlag and OutFlag
|
|
||||||
// This is same as movf_1 but has a flag. A flag is required to
|
|
||||||
// order the loads while copying the return value of a function.
|
|
||||||
def movf_2 : MOVF_INSN<0, texternalsym, PIC16LdWF>;
|
|
||||||
|
|
||||||
// Indirect load. Matched via a DAG replacement pattern.
|
|
||||||
def load_indirect :
|
|
||||||
ByteFormat<0, (outs GPR:$dst),
|
|
||||||
(ins FSR16:$fsr, i8imm:$offset),
|
|
||||||
"moviw $offset[$fsr]",
|
|
||||||
[]>;
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
// Bitwise operations patterns
|
|
||||||
//--------------------------
|
|
||||||
// W = W op [F]
|
|
||||||
let Defs = [STATUS] in {
|
|
||||||
def OrFW : BinOpFW<0, "iorwf", or>;
|
|
||||||
def XOrFW : BinOpFW<0, "xorwf", xor>;
|
|
||||||
def AndFW : BinOpFW<0, "andwf", and>;
|
|
||||||
|
|
||||||
// F = W op [F]
|
|
||||||
def OrWF : BinOpWF<0, "iorwf", or>;
|
|
||||||
def XOrWF : BinOpWF<0, "xorwf", xor>;
|
|
||||||
def AndWF : BinOpWF<0, "andwf", and>;
|
|
||||||
|
|
||||||
//-------------------------
|
|
||||||
// Various add/sub patterns.
|
|
||||||
//-------------------------
|
|
||||||
|
|
||||||
// W = W + [F]
|
|
||||||
def addfw_1: BinOpFW<0, "addwf", add>;
|
|
||||||
def addfw_2: BinOpFW<0, "addwf", addc>;
|
|
||||||
|
|
||||||
let Uses = [STATUS] in
|
|
||||||
def addfwc: BinOpFW<0, "addwfc", adde>; // With Carry.
|
|
||||||
|
|
||||||
// F = W + [F]
|
|
||||||
def addwf_1: BinOpWF<0, "addwf", add>;
|
|
||||||
def addwf_2: BinOpWF<0, "addwf", addc>;
|
|
||||||
let Uses = [STATUS] in
|
|
||||||
def addwfc: BinOpWF<0, "addwfc", adde>; // With Carry.
|
|
||||||
}
|
|
||||||
|
|
||||||
// W -= [F] ; load from F and sub the value from W.
|
|
||||||
let Constraints = "$src = $dst", mayLoad = 1 in
|
|
||||||
class SUBFW<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
|
||||||
ByteFormat<OpCode, (outs GPR:$dst),
|
|
||||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
|
||||||
!strconcat(OpcStr, " $ptrlo + $offset, W"),
|
|
||||||
[(set GPR:$dst, (OpNode (PIC16Load diraddr:$ptrlo,
|
|
||||||
(i8 imm:$ptrhi), (i8 imm:$offset)),
|
|
||||||
GPR:$src))]>;
|
|
||||||
let Defs = [STATUS] in {
|
|
||||||
def subfw_1: SUBFW<0, "subwf", sub>;
|
|
||||||
def subfw_2: SUBFW<0, "subwf", subc>;
|
|
||||||
|
|
||||||
let Uses = [STATUS] in
|
|
||||||
def subfwb: SUBFW<0, "subwfb", sube>; // With Borrow.
|
|
||||||
|
|
||||||
}
|
|
||||||
let Defs = [STATUS], isTerminator = 1 in
|
|
||||||
def subfw_cc: SUBFW<0, "subwf", PIC16Subcc>;
|
|
||||||
|
|
||||||
// [F] -= W ;
|
|
||||||
let mayStore = 1 in
|
|
||||||
class SUBWF<bits<6> OpCode, string OpcStr, SDNode OpNode>:
|
|
||||||
ByteFormat<OpCode, (outs),
|
|
||||||
(ins GPR:$src, i8imm:$offset, i8mem:$ptrlo, i8imm:$ptrhi),
|
|
||||||
!strconcat(OpcStr, " $ptrlo + $offset"),
|
|
||||||
[(PIC16Store (OpNode (PIC16Load diraddr:$ptrlo,
|
|
||||||
(i8 imm:$ptrhi), (i8 imm:$offset)),
|
|
||||||
GPR:$src), diraddr:$ptrlo,
|
|
||||||
(i8 imm:$ptrhi), (i8 imm:$offset))]>;
|
|
||||||
|
|
||||||
let Defs = [STATUS] in {
|
|
||||||
def subwf_1: SUBWF<0, "subwf", sub>;
|
|
||||||
def subwf_2: SUBWF<0, "subwf", subc>;
|
|
||||||
|
|
||||||
let Uses = [STATUS] in
|
|
||||||
def subwfb: SUBWF<0, "subwfb", sube>; // With Borrow.
|
|
||||||
|
|
||||||
def subwf_cc: SUBWF<0, "subwf", PIC16Subcc>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// addlw
|
|
||||||
let Defs = [STATUS] in {
|
|
||||||
def addlw_1 : BinOpWL<0, "addlw", add>;
|
|
||||||
def addlw_2 : BinOpWL<0, "addlw", addc>;
|
|
||||||
|
|
||||||
let Uses = [STATUS] in
|
|
||||||
def addlwc : BinOpWL<0, "addlwc", adde>; // With Carry. (Assembler macro).
|
|
||||||
|
|
||||||
// bitwise operations involving a literal and w.
|
|
||||||
def andlw : BinOpWL<0, "andlw", and>;
|
|
||||||
def xorlw : BinOpWL<0, "xorlw", xor>;
|
|
||||||
def orlw : BinOpWL<0, "iorlw", or>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// sublw
|
|
||||||
// W = C - W ; sub W from literal. (Without borrow).
|
|
||||||
let Constraints = "$src = $dst" in
|
|
||||||
class SUBLW<bits<6> opcode, string OpcStr, SDNode OpNode> :
|
|
||||||
LiteralFormat<opcode, (outs GPR:$dst),
|
|
||||||
(ins GPR:$src, i8imm:$literal),
|
|
||||||
!strconcat(OpcStr, " $literal"),
|
|
||||||
[(set GPR:$dst, (OpNode (i8 imm:$literal), GPR:$src))]>;
|
|
||||||
// subwl
|
|
||||||
// W = W - C ; sub literal from W (Without borrow).
|
|
||||||
let Constraints = "$src = $dst" in
|
|
||||||
class SUBWL<bits<6> opcode, string OpcStr, SDNode OpNode> :
|
|
||||||
LiteralFormat<opcode, (outs GPR:$dst),
|
|
||||||
(ins GPR:$src, i8imm:$literal),
|
|
||||||
!strconcat(OpcStr, " $literal"),
|
|
||||||
[(set GPR:$dst, (OpNode GPR:$src, (i8 imm:$literal)))]>;
|
|
||||||
|
|
||||||
let Defs = [STATUS] in {
|
|
||||||
def sublw_1 : SUBLW<0, "sublw", sub>;
|
|
||||||
def sublw_2 : SUBLW<0, "sublw", subc>;
|
|
||||||
def sublw_3 : SUBLW<0, "sublwb", sube>; // With borrow (Assembler macro).
|
|
||||||
|
|
||||||
def sublw_4 : SUBWL<0, "subwl", sub>; // Assembler macro replace with addlw
|
|
||||||
def sublw_5 : SUBWL<0, "subwl", subc>; // Assembler macro replace with addlw
|
|
||||||
def sublw_6 : SUBWL<0, "subwlb", sube>; // With borrow (Assembler macro).
|
|
||||||
}
|
|
||||||
let Defs = [STATUS], isTerminator = 1 in
|
|
||||||
def sublw_cc : SUBLW<0, "sublw", PIC16Subcc>;
|
|
||||||
|
|
||||||
// Call instruction.
|
|
||||||
let isCall = 1,
|
|
||||||
Defs = [W, FSR0, FSR1] in {
|
|
||||||
def CALL: LiteralFormat<0x1, (outs), (ins i8imm:$func),
|
|
||||||
//"call ${func} + 2",
|
|
||||||
"call ${func}",
|
|
||||||
[(PIC16call diraddr:$func)]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isCall = 1,
|
|
||||||
Defs = [W, FSR0, FSR1] in {
|
|
||||||
def CALL_1: LiteralFormat<0x1, (outs), (ins GPR:$func, PCLATHR:$pc),
|
|
||||||
"callw",
|
|
||||||
[(PIC16call (PIC16Connect GPR:$func, PCLATHR:$pc))]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let isCall = 1,
|
|
||||||
Defs = [FSR0, FSR1] in {
|
|
||||||
def CALLW: LiteralFormat<0x1, (outs GPR:$dest),
|
|
||||||
(ins GPR:$func, PCLATHR:$pc),
|
|
||||||
"callw",
|
|
||||||
[(set GPR:$dest, (PIC16callw (PIC16Connect GPR:$func, PCLATHR:$pc)))]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let Uses = [STATUS], isBranch = 1, isTerminator = 1, hasDelaySlot = 0 in
|
|
||||||
def pic16brcond: ControlFormat<0x0, (outs), (ins brtarget:$dst, CCOp:$cc),
|
|
||||||
"b$cc $dst",
|
|
||||||
[(PIC16Brcond bb:$dst, imm:$cc)]>;
|
|
||||||
|
|
||||||
// Unconditional branch.
|
|
||||||
let isBranch = 1, isTerminator = 1, hasDelaySlot = 0 in
|
|
||||||
def br_uncond: ControlFormat<0x0, (outs), (ins brtarget:$dst),
|
|
||||||
"goto $dst",
|
|
||||||
[(br bb:$dst)]>;
|
|
||||||
|
|
||||||
// SELECT_CC_* - Used to implement the SELECT_CC DAG operation. Expanded after
|
|
||||||
// instruction selection into a branch sequence.
|
|
||||||
let usesCustomInserter = 1 in { // Expanded after instruction selection.
|
|
||||||
def SELECT_CC_Int_ICC
|
|
||||||
: Pseudo<(outs GPR:$dst), (ins GPR:$T, GPR:$F, i8imm:$Cond),
|
|
||||||
"; SELECT_CC_Int_ICC PSEUDO!",
|
|
||||||
[(set GPR:$dst, (PIC16Selecticc GPR:$T, GPR:$F,
|
|
||||||
imm:$Cond))]>;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Banksel.
|
|
||||||
def banksel :
|
|
||||||
Pseudo<(outs),
|
|
||||||
(ins i8mem:$ptr),
|
|
||||||
"banksel $ptr",
|
|
||||||
[]>;
|
|
||||||
|
|
||||||
def pagesel :
|
|
||||||
Pseudo<(outs),
|
|
||||||
(ins i8mem:$ptr),
|
|
||||||
"movlp $ptr",
|
|
||||||
[]>;
|
|
||||||
|
|
||||||
|
|
||||||
// Return insn.
|
|
||||||
let isTerminator = 1, isBarrier = 1, isReturn = 1 in
|
|
||||||
def Return :
|
|
||||||
ControlFormat<0, (outs), (ins), "return", [(PIC16ret)]>;
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// PIC16 Replacment Patterns.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
// Identify an indirect store and select insns for it.
|
|
||||||
def : Pat<(PIC16Store GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
|
|
||||||
imm:$offset),
|
|
||||||
(store_indirect GPR:$val,
|
|
||||||
(set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
|
|
||||||
imm:$offset)>;
|
|
||||||
|
|
||||||
def : Pat<(PIC16StWF GPR:$val, (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
|
|
||||||
imm:$offset),
|
|
||||||
(store_indirect GPR:$val,
|
|
||||||
(set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
|
|
||||||
imm:$offset)>;
|
|
||||||
|
|
||||||
// Identify an indirect load and select insns for it.
|
|
||||||
def : Pat<(PIC16Load (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
|
|
||||||
imm:$offset),
|
|
||||||
(load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
|
|
||||||
imm:$offset)>;
|
|
||||||
|
|
||||||
def : Pat<(PIC16LdWF (MTLO GPR:$loaddr), (MTHI GPR:$hiaddr),
|
|
||||||
imm:$offset),
|
|
||||||
(load_indirect (set_fsrhi (set_fsrlo GPR:$loaddr), GPR:$hiaddr),
|
|
||||||
imm:$offset)>;
|
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
//===-- PIC16MCAsmInfo.cpp - PIC16 asm properties -------------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the declarations of the PIC16MCAsmInfo properties.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16MCAsmInfo.h"
|
|
||||||
|
|
||||||
// FIXME: Layering violation to get enums and static function, should be moved
|
|
||||||
// to separate headers.
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16ABINames.h"
|
|
||||||
#include "PIC16ISelLowering.h"
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
PIC16MCAsmInfo::PIC16MCAsmInfo(const Target &T, StringRef TT) {
|
|
||||||
CommentString = ";";
|
|
||||||
GlobalPrefix = PAN::getTagName(PAN::PREFIX_SYMBOL);
|
|
||||||
GlobalDirective = "\tglobal\t";
|
|
||||||
ExternDirective = "\textern\t";
|
|
||||||
|
|
||||||
Data8bitsDirective = " db ";
|
|
||||||
Data16bitsDirective = " dw ";
|
|
||||||
Data32bitsDirective = " dl ";
|
|
||||||
Data64bitsDirective = NULL;
|
|
||||||
ZeroDirective = NULL;
|
|
||||||
AsciiDirective = " dt ";
|
|
||||||
AscizDirective = NULL;
|
|
||||||
|
|
||||||
RomData8bitsDirective = " dw ";
|
|
||||||
RomData16bitsDirective = " rom_di ";
|
|
||||||
RomData32bitsDirective = " rom_dl ";
|
|
||||||
HasSetDirective = false;
|
|
||||||
|
|
||||||
// Set it to false because we weed to generate c file name and not bc file
|
|
||||||
// name.
|
|
||||||
HasSingleParameterDotFile = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *PIC16MCAsmInfo::getDataASDirective(unsigned Size,
|
|
||||||
unsigned AS) const {
|
|
||||||
if (AS != PIC16ISD::ROM_SPACE)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
switch (Size) {
|
|
||||||
case 8: return RomData8bitsDirective;
|
|
||||||
case 16: return RomData16bitsDirective;
|
|
||||||
case 32: return RomData32bitsDirective;
|
|
||||||
default: return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
//=====-- 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, StringRef TT);
|
|
||||||
|
|
||||||
virtual const char *getDataASDirective(unsigned size, unsigned AS) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace llvm
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,52 +0,0 @@
|
||||||
//====- PIC16MachineFuctionInfo.h - PIC16 machine function info -*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file declares PIC16-specific per-machine-function information.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16MACHINEFUNCTIONINFO_H
|
|
||||||
#define PIC16MACHINEFUNCTIONINFO_H
|
|
||||||
|
|
||||||
#include "llvm/CodeGen/MachineFunction.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
/// PIC16MachineFunctionInfo - This class is derived from MachineFunction
|
|
||||||
/// private PIC16 target-specific information for each MachineFunction.
|
|
||||||
class PIC16MachineFunctionInfo : public MachineFunctionInfo {
|
|
||||||
// The frameindexes generated for spill/reload are stack based.
|
|
||||||
// This maps maintain zero based indexes for these FIs.
|
|
||||||
std::map<unsigned, unsigned> FiTmpOffsetMap;
|
|
||||||
unsigned TmpSize;
|
|
||||||
|
|
||||||
// These are the frames for return value and argument passing
|
|
||||||
// These FrameIndices will be expanded to foo.frame external symbol
|
|
||||||
// and all others will be expanded to foo.tmp external symbol.
|
|
||||||
unsigned ReservedFrameCount;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PIC16MachineFunctionInfo()
|
|
||||||
: TmpSize(0), ReservedFrameCount(0) {}
|
|
||||||
|
|
||||||
explicit PIC16MachineFunctionInfo(MachineFunction &MF)
|
|
||||||
: TmpSize(0), ReservedFrameCount(0) {}
|
|
||||||
|
|
||||||
std::map<unsigned, unsigned> &getFiTmpOffsetMap() { return FiTmpOffsetMap; }
|
|
||||||
|
|
||||||
unsigned getTmpSize() const { return TmpSize; }
|
|
||||||
void setTmpSize(unsigned Size) { TmpSize = Size; }
|
|
||||||
|
|
||||||
unsigned getReservedFrameCount() const { return ReservedFrameCount; }
|
|
||||||
void setReservedFrameCount(unsigned Count) { ReservedFrameCount = Count; }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // End llvm namespace
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,254 +0,0 @@
|
||||||
//===-- PIC16MemSelOpt.cpp - PIC16 banksel optimizer --------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file defines the pass which optimizes the emitting of banksel
|
|
||||||
// instructions before accessing data memory. This currently works within
|
|
||||||
// a basic block only and keep tracks of the last accessed memory bank.
|
|
||||||
// If memory access continues to be in the same bank it just makes banksel
|
|
||||||
// immediate, which is a part of the insn accessing the data memory, from 1
|
|
||||||
// to zero. The asm printer emits a banksel only if that immediate is 1.
|
|
||||||
//
|
|
||||||
// FIXME: this is not implemented yet. The banksel pass only works on local
|
|
||||||
// basic blocks.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define DEBUG_TYPE "pic16-codegen"
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16ABINames.h"
|
|
||||||
#include "PIC16InstrInfo.h"
|
|
||||||
#include "PIC16MCAsmInfo.h"
|
|
||||||
#include "PIC16TargetMachine.h"
|
|
||||||
#include "llvm/CodeGen/MachineFunctionPass.h"
|
|
||||||
#include "llvm/CodeGen/MachineInstrBuilder.h"
|
|
||||||
#include "llvm/CodeGen/Passes.h"
|
|
||||||
#include "llvm/Target/TargetInstrInfo.h"
|
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
#include "llvm/GlobalValue.h"
|
|
||||||
#include "llvm/DerivedTypes.h"
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
struct MemSelOpt : public MachineFunctionPass {
|
|
||||||
static char ID;
|
|
||||||
MemSelOpt() : MachineFunctionPass(ID) {}
|
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
||||||
AU.addPreservedID(MachineLoopInfoID);
|
|
||||||
AU.addPreservedID(MachineDominatorsID);
|
|
||||||
MachineFunctionPass::getAnalysisUsage(AU);
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool runOnMachineFunction(MachineFunction &MF);
|
|
||||||
|
|
||||||
virtual const char *getPassName() const {
|
|
||||||
return "PIC16 Memsel Optimizer";
|
|
||||||
}
|
|
||||||
|
|
||||||
bool processBasicBlock(MachineFunction &MF, MachineBasicBlock &MBB);
|
|
||||||
bool processInstruction(MachineInstr *MI);
|
|
||||||
|
|
||||||
private:
|
|
||||||
const TargetInstrInfo *TII; // Machine instruction info.
|
|
||||||
MachineBasicBlock *MBB; // Current basic block
|
|
||||||
std::string CurBank;
|
|
||||||
int PageChanged;
|
|
||||||
|
|
||||||
};
|
|
||||||
char MemSelOpt::ID = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
FunctionPass *llvm::createPIC16MemSelOptimizerPass() {
|
|
||||||
return new MemSelOpt();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// runOnMachineFunction - Loop over all of the basic blocks, transforming FP
|
|
||||||
/// register references into FP stack references.
|
|
||||||
///
|
|
||||||
bool MemSelOpt::runOnMachineFunction(MachineFunction &MF) {
|
|
||||||
TII = MF.getTarget().getInstrInfo();
|
|
||||||
bool Changed = false;
|
|
||||||
for (MachineFunction::iterator I = MF.begin(), E = MF.end();
|
|
||||||
I != E; ++I) {
|
|
||||||
Changed |= processBasicBlock(MF, *I);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// processBasicBlock - Loop over all of the instructions in the basic block,
|
|
||||||
/// transforming FP instructions into their stack form.
|
|
||||||
///
|
|
||||||
bool MemSelOpt::processBasicBlock(MachineFunction &MF, MachineBasicBlock &BB) {
|
|
||||||
bool Changed = false;
|
|
||||||
MBB = &BB;
|
|
||||||
|
|
||||||
// Let us assume that when entering a basic block now bank is selected.
|
|
||||||
// Ideally we should look at the predecessors for this information.
|
|
||||||
CurBank="";
|
|
||||||
PageChanged=0;
|
|
||||||
|
|
||||||
MachineBasicBlock::iterator I;
|
|
||||||
for (I = BB.begin(); I != BB.end(); ++I) {
|
|
||||||
Changed |= processInstruction(I);
|
|
||||||
|
|
||||||
// if the page has changed insert a page sel before
|
|
||||||
// any instruction that needs one
|
|
||||||
if (PageChanged == 1)
|
|
||||||
{
|
|
||||||
// Restore the page if it was changed, before leaving the basic block,
|
|
||||||
// because it may be required by the goto terminator or the fall thru
|
|
||||||
// basic blcok.
|
|
||||||
// If the terminator is return, we don't need to restore since there
|
|
||||||
// is no goto or fall thru basic block.
|
|
||||||
if ((I->getOpcode() == PIC16::sublw_3) || //macro has goto
|
|
||||||
(I->getOpcode() == PIC16::sublw_6) || //macro has goto
|
|
||||||
(I->getOpcode() == PIC16::addlwc) || //macro has goto
|
|
||||||
(TII->get(I->getOpcode()).isBranch()))
|
|
||||||
{
|
|
||||||
DebugLoc dl = I->getDebugLoc();
|
|
||||||
BuildMI(*MBB, I, dl, TII->get(PIC16::pagesel)).addExternalSymbol("$");
|
|
||||||
Changed = true;
|
|
||||||
PageChanged = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The basic block is over, but if we did not find any goto yet,
|
|
||||||
// we haven't restored the page.
|
|
||||||
// Restore the page if it was changed, before leaving the basic block,
|
|
||||||
// because it may be required by fall thru basic blcok.
|
|
||||||
// If the terminator is return, we don't need to restore since there
|
|
||||||
// is fall thru basic block.
|
|
||||||
if (PageChanged == 1) {
|
|
||||||
// save the end pointer before we move back to last insn.
|
|
||||||
MachineBasicBlock::iterator J = I;
|
|
||||||
I--;
|
|
||||||
const TargetInstrDesc &TID = TII->get(I->getOpcode());
|
|
||||||
if (! TID.isReturn())
|
|
||||||
{
|
|
||||||
DebugLoc dl = I->getDebugLoc();
|
|
||||||
BuildMI(*MBB, J, dl,
|
|
||||||
TII->get(PIC16::pagesel)).addExternalSymbol("$");
|
|
||||||
Changed = true;
|
|
||||||
PageChanged = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return Changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MemSelOpt::processInstruction(MachineInstr *MI) {
|
|
||||||
bool Changed = false;
|
|
||||||
|
|
||||||
unsigned NumOperands = MI->getNumOperands();
|
|
||||||
if (NumOperands == 0) return false;
|
|
||||||
|
|
||||||
|
|
||||||
// If this insn is not going to access any memory, return.
|
|
||||||
const TargetInstrDesc &TID = TII->get(MI->getOpcode());
|
|
||||||
if (!(TID.isBranch() || TID.isCall() || TID.mayLoad() || TID.mayStore()))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// The first thing we should do is that record if banksel/pagesel are
|
|
||||||
// changed in an unknown way. This can happend via any type of call.
|
|
||||||
// We do it here first before scanning of MemOp / BBOp as the indirect
|
|
||||||
// call insns do not have any operands, but they still may change bank/page.
|
|
||||||
if (TID.isCall()) {
|
|
||||||
// Record that we have changed the page, so that we can restore it
|
|
||||||
// before basic block ends.
|
|
||||||
// We require to signal that a page anc bank change happened even for
|
|
||||||
// indirect calls.
|
|
||||||
PageChanged = 1;
|
|
||||||
|
|
||||||
// When a call is made, there may be banksel for variables in callee.
|
|
||||||
// Hence the banksel in caller needs to be reset.
|
|
||||||
CurBank = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan for the memory address operand.
|
|
||||||
// FIXME: Should we use standard interfaces like memoperands_iterator,
|
|
||||||
// hasMemOperand() etc ?
|
|
||||||
int MemOpPos = -1;
|
|
||||||
int BBOpPos = -1;
|
|
||||||
for (unsigned i = 0; i < NumOperands; i++) {
|
|
||||||
MachineOperand Op = MI->getOperand(i);
|
|
||||||
if (Op.getType() == MachineOperand::MO_GlobalAddress ||
|
|
||||||
Op.getType() == MachineOperand::MO_ExternalSymbol) {
|
|
||||||
// We found one mem operand. Next one may be BS.
|
|
||||||
MemOpPos = i;
|
|
||||||
}
|
|
||||||
if (Op.getType() == MachineOperand::MO_MachineBasicBlock) {
|
|
||||||
// We found one BB operand. Next one may be pagesel.
|
|
||||||
BBOpPos = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we did not find an insn accessing memory. Continue.
|
|
||||||
if ((MemOpPos == -1) &&
|
|
||||||
(BBOpPos == -1))
|
|
||||||
return false;
|
|
||||||
assert ((BBOpPos != MemOpPos) && "operand can only be of one type");
|
|
||||||
|
|
||||||
|
|
||||||
// If this is a pagesel material, handle it first.
|
|
||||||
// CALL and br_ucond insns use MemOp (GA or ES) and not BBOp.
|
|
||||||
// Pagesel is required only for a direct call.
|
|
||||||
if ((MI->getOpcode() == PIC16::CALL)) {
|
|
||||||
// Get the BBOp.
|
|
||||||
MachineOperand &MemOp = MI->getOperand(MemOpPos);
|
|
||||||
DebugLoc dl = MI->getDebugLoc();
|
|
||||||
BuildMI(*MBB, MI, dl, TII->get(PIC16::pagesel)).addOperand(MemOp);
|
|
||||||
|
|
||||||
// CALL and br_ucond needs only pagesel. so we are done.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pagesel is handled. Now, add a Banksel if needed.
|
|
||||||
if (MemOpPos == -1) return Changed;
|
|
||||||
// Get the MemOp.
|
|
||||||
MachineOperand &Op = MI->getOperand(MemOpPos);
|
|
||||||
|
|
||||||
// Get the section name(NewBank) for MemOp.
|
|
||||||
// This assumes that the section names for globals are already set by
|
|
||||||
// AsmPrinter->doInitialization.
|
|
||||||
std::string NewBank = CurBank;
|
|
||||||
bool hasExternalLinkage = false;
|
|
||||||
if (Op.getType() == MachineOperand::MO_GlobalAddress &&
|
|
||||||
Op.getGlobal()->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE) {
|
|
||||||
if (Op.getGlobal()->hasExternalLinkage())
|
|
||||||
hasExternalLinkage= true;
|
|
||||||
NewBank = Op.getGlobal()->getSection();
|
|
||||||
} else if (Op.getType() == MachineOperand::MO_ExternalSymbol) {
|
|
||||||
// External Symbol is generated for temp data and arguments. They are
|
|
||||||
// in fpdata.<functionname>.# section.
|
|
||||||
std::string Sym = Op.getSymbolName();
|
|
||||||
NewBank = PAN::getSectionNameForSym(Sym);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the section is shared section, do not emit banksel.
|
|
||||||
if (NewBank == PAN::getSharedUDataSectionName())
|
|
||||||
return Changed;
|
|
||||||
|
|
||||||
// If the previous and new section names are same, we don't need to
|
|
||||||
// emit banksel.
|
|
||||||
if (NewBank.compare(CurBank) != 0 || hasExternalLinkage) {
|
|
||||||
DebugLoc dl = MI->getDebugLoc();
|
|
||||||
BuildMI(*MBB, MI, dl, TII->get(PIC16::banksel)).
|
|
||||||
addOperand(Op);
|
|
||||||
Changed = true;
|
|
||||||
CurBank = NewBank;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Changed;
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
add_llvm_library(LLVMPIC16Passes
|
|
||||||
PIC16Cloner.cpp
|
|
||||||
PIC16Overlay.cpp
|
|
||||||
)
|
|
|
@ -1,15 +0,0 @@
|
||||||
##===- lib/Target/PIC16/PIC16Passes/Makefile -----------*- Makefile -*-===##
|
|
||||||
#
|
|
||||||
# The LLVM Compiler Infrastructure
|
|
||||||
#
|
|
||||||
# This file is distributed under the University of Illinois Open Source
|
|
||||||
# License. See LICENSE.TXT for details.
|
|
||||||
#
|
|
||||||
##===----------------------------------------------------------------------===##
|
|
||||||
LEVEL = ../../../..
|
|
||||||
TARGET = PIC16
|
|
||||||
LIBRARYNAME = LLVMPIC16Passes
|
|
||||||
BUILD_ARCHIVE = 1
|
|
||||||
|
|
||||||
include $(LEVEL)/Makefile.common
|
|
||||||
|
|
|
@ -1,299 +0,0 @@
|
||||||
//===-- PIC16Cloner.cpp - PIC16 LLVM Cloner for shared functions -*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains code to clone all functions that are shared between
|
|
||||||
// the main line code (ML) and interrupt line code (IL). It clones all such
|
|
||||||
// shared functions and their automatic global vars by adding the .IL suffix.
|
|
||||||
//
|
|
||||||
// This pass is supposed to be run on the linked .bc module.
|
|
||||||
// It traveses the module call graph twice. Once starting from the main function
|
|
||||||
// and marking each reached function as "ML". Again, starting from the ISR
|
|
||||||
// and cloning any reachable function that was marked as "ML". After cloning
|
|
||||||
// the function, it remaps all the call sites in IL functions to call the
|
|
||||||
// cloned functions.
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "llvm/Analysis/CallGraph.h"
|
|
||||||
#include "llvm/Pass.h"
|
|
||||||
#include "llvm/Module.h"
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
#include "llvm/Transforms/Utils/Cloning.h"
|
|
||||||
#include "PIC16Cloner.h"
|
|
||||||
#include "../PIC16ABINames.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
using std::vector;
|
|
||||||
using std::string;
|
|
||||||
using std::map;
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
char PIC16Cloner::ID = 0;
|
|
||||||
|
|
||||||
ModulePass *createPIC16ClonerPass() { return new PIC16Cloner(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
// We currently intend to run these passes in opt, which does not have any
|
|
||||||
// diagnostic support. So use these functions for now. In future
|
|
||||||
// we will probably write our own driver tool.
|
|
||||||
//
|
|
||||||
void PIC16Cloner::reportError(string ErrorString) {
|
|
||||||
errs() << "ERROR : " << ErrorString << "\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16Cloner::
|
|
||||||
reportError (string ErrorString, vector<string> &Values) {
|
|
||||||
unsigned ValCount = Values.size();
|
|
||||||
string TargetString;
|
|
||||||
for (unsigned i=0; i<ValCount; ++i) {
|
|
||||||
TargetString = "%";
|
|
||||||
TargetString += ((char)i + '0');
|
|
||||||
ErrorString.replace(ErrorString.find(TargetString), TargetString.length(),
|
|
||||||
Values[i]);
|
|
||||||
}
|
|
||||||
errs() << "ERROR : " << ErrorString << "\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Entry point
|
|
||||||
//
|
|
||||||
bool PIC16Cloner::runOnModule(Module &M) {
|
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
|
||||||
|
|
||||||
// Search for the "main" and "ISR" functions.
|
|
||||||
CallGraphNode *mainCGN = NULL, *isrCGN = NULL;
|
|
||||||
for (CallGraph::iterator it = CG.begin() ; it != CG.end(); it++)
|
|
||||||
{
|
|
||||||
// External calling node doesn't have any function associated with it.
|
|
||||||
if (! it->first)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (it->first->getName().str() == "main") {
|
|
||||||
mainCGN = it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PAN::isISR(it->first->getSection())) {
|
|
||||||
isrCGN = it->second;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't search further if we've found both.
|
|
||||||
if (mainCGN && isrCGN)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have nothing to do if any of the main or ISR is missing.
|
|
||||||
if (! mainCGN || ! isrCGN) return false;
|
|
||||||
|
|
||||||
// Time for some diagnostics.
|
|
||||||
// See if the main itself is interrupt function then report an error.
|
|
||||||
if (PAN::isISR(mainCGN->getFunction()->getSection())) {
|
|
||||||
reportError("Function 'main' can't be interrupt function");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Mark all reachable functions from main as ML.
|
|
||||||
markCallGraph(mainCGN, "ML");
|
|
||||||
|
|
||||||
// And then all the functions reachable from ISR will be cloned.
|
|
||||||
cloneSharedFunctions(isrCGN);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mark all reachable functions from the given node, with the given mark.
|
|
||||||
//
|
|
||||||
void PIC16Cloner::markCallGraph(CallGraphNode *CGN, string StringMark) {
|
|
||||||
// Mark the top node first.
|
|
||||||
Function *thisF = CGN->getFunction();
|
|
||||||
|
|
||||||
thisF->setSection(StringMark);
|
|
||||||
|
|
||||||
// Mark all the called functions
|
|
||||||
for(CallGraphNode::iterator cgn_it = CGN->begin();
|
|
||||||
cgn_it != CGN->end(); ++cgn_it) {
|
|
||||||
Function *CalledF = cgn_it->second->getFunction();
|
|
||||||
|
|
||||||
// If calling an external function then CallGraphNode
|
|
||||||
// will not be associated with any function.
|
|
||||||
if (! CalledF)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Issue diagnostic if interrupt function is being called.
|
|
||||||
if (PAN::isISR(CalledF->getSection())) {
|
|
||||||
vector<string> Values;
|
|
||||||
Values.push_back(CalledF->getName().str());
|
|
||||||
reportError("Interrupt function (%0) can't be called", Values);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Has already been mark
|
|
||||||
if (CalledF->getSection().find(StringMark) != string::npos) {
|
|
||||||
// Should we do anything here?
|
|
||||||
} else {
|
|
||||||
// Mark now
|
|
||||||
CalledF->setSection(StringMark);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Before going any further mark all the called function by current
|
|
||||||
// function.
|
|
||||||
markCallGraph(cgn_it->second ,StringMark);
|
|
||||||
} // end of loop of all called functions.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// For PIC16, automatic variables of a function are emitted as globals.
|
|
||||||
// Clone the auto variables of a function and put them in VMap,
|
|
||||||
// this VMap will be used while
|
|
||||||
// Cloning the code of function itself.
|
|
||||||
//
|
|
||||||
void PIC16Cloner::CloneAutos(Function *F) {
|
|
||||||
// We'll need to update module's globals list as well. So keep a reference
|
|
||||||
// handy.
|
|
||||||
Module *M = F->getParent();
|
|
||||||
Module::GlobalListType &Globals = M->getGlobalList();
|
|
||||||
|
|
||||||
// Clear the leftovers in VMap by any previous cloning.
|
|
||||||
VMap.clear();
|
|
||||||
|
|
||||||
// Find the auto globls for this function and clone them, and put them
|
|
||||||
// in VMap.
|
|
||||||
std::string FnName = F->getName().str();
|
|
||||||
std::string VarName, ClonedVarName;
|
|
||||||
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
|
|
||||||
I != E; ++I) {
|
|
||||||
VarName = I->getName().str();
|
|
||||||
if (PAN::isLocalToFunc(FnName, VarName)) {
|
|
||||||
// Auto variable for current function found. Clone it.
|
|
||||||
const GlobalVariable *GV = I;
|
|
||||||
|
|
||||||
const Type *InitTy = GV->getInitializer()->getType();
|
|
||||||
GlobalVariable *ClonedGV =
|
|
||||||
new GlobalVariable(InitTy, false, GV->getLinkage(),
|
|
||||||
GV->getInitializer());
|
|
||||||
ClonedGV->setName(PAN::getCloneVarName(FnName, VarName));
|
|
||||||
// Add these new globals to module's globals list.
|
|
||||||
Globals.push_back(ClonedGV);
|
|
||||||
|
|
||||||
// Update VMap.
|
|
||||||
VMap[GV] = ClonedGV;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Clone all functions that are reachable from ISR and are already
|
|
||||||
// marked as ML.
|
|
||||||
//
|
|
||||||
void PIC16Cloner::cloneSharedFunctions(CallGraphNode *CGN) {
|
|
||||||
|
|
||||||
// Check all the called functions from ISR.
|
|
||||||
for(CallGraphNode::iterator cgn_it = CGN->begin();
|
|
||||||
cgn_it != CGN->end(); ++cgn_it) {
|
|
||||||
Function *CalledF = cgn_it->second->getFunction();
|
|
||||||
|
|
||||||
// If calling an external function then CallGraphNode
|
|
||||||
// will not be associated with any function.
|
|
||||||
if (!CalledF)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// Issue diagnostic if interrupt function is being called.
|
|
||||||
if (PAN::isISR(CalledF->getSection())) {
|
|
||||||
vector<string> Values;
|
|
||||||
Values.push_back(CalledF->getName().str());
|
|
||||||
reportError("Interrupt function (%0) can't be called", Values);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (CalledF->getSection().find("ML") != string::npos) {
|
|
||||||
// Function is alternatively marked. It should be a shared one.
|
|
||||||
// Create IL copy. Passing called function as first argument
|
|
||||||
// and the caller as the second argument.
|
|
||||||
|
|
||||||
// Before making IL copy, first ensure that this function has a
|
|
||||||
// body. If the function does have a body. It can't be cloned.
|
|
||||||
// Such a case may occur when the function has been declarated
|
|
||||||
// in the C source code but its body exists in assembly file.
|
|
||||||
if (!CalledF->isDeclaration()) {
|
|
||||||
Function *cf = cloneFunction(CalledF);
|
|
||||||
remapAllSites(CGN->getFunction(), CalledF, cf);
|
|
||||||
} else {
|
|
||||||
// It is called only from ISR. Still mark it as we need this info
|
|
||||||
// in code gen while calling intrinsics.Function is not marked.
|
|
||||||
CalledF->setSection("IL");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Before going any further clone all the shared function reachaable
|
|
||||||
// by current function.
|
|
||||||
cloneSharedFunctions(cgn_it->second);
|
|
||||||
} // end of loop of all called functions.
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone the given function and return it.
|
|
||||||
// Note: it uses the VMap member of the class, which is already populated
|
|
||||||
// by cloneAutos by the time we reach here.
|
|
||||||
// FIXME: Should we just pass VMap's ref as a parameter here? rather
|
|
||||||
// than keeping the VMap as a member.
|
|
||||||
Function *
|
|
||||||
PIC16Cloner::cloneFunction(Function *OrgF) {
|
|
||||||
Function *ClonedF;
|
|
||||||
|
|
||||||
// See if we already cloned it. Return that.
|
|
||||||
cloned_map_iterator cm_it = ClonedFunctionMap.find(OrgF);
|
|
||||||
if(cm_it != ClonedFunctionMap.end()) {
|
|
||||||
ClonedF = cm_it->second;
|
|
||||||
return ClonedF;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clone does not exist.
|
|
||||||
// First clone the autos, and populate VMap.
|
|
||||||
CloneAutos(OrgF);
|
|
||||||
|
|
||||||
// Now create the clone.
|
|
||||||
ClonedF = CloneFunction(OrgF, VMap, /*ModuleLevelChanges=*/false);
|
|
||||||
|
|
||||||
// The new function should be for interrupt line. Therefore should have
|
|
||||||
// the name suffixed with IL and section attribute marked with IL.
|
|
||||||
ClonedF->setName(PAN::getCloneFnName(OrgF->getName()));
|
|
||||||
ClonedF->setSection("IL");
|
|
||||||
|
|
||||||
// Add the newly created function to the module.
|
|
||||||
OrgF->getParent()->getFunctionList().push_back(ClonedF);
|
|
||||||
|
|
||||||
// Update the ClonedFunctionMap to record this cloning activity.
|
|
||||||
ClonedFunctionMap[OrgF] = ClonedF;
|
|
||||||
|
|
||||||
return ClonedF;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Remap the call sites of shared functions, that are in IL.
|
|
||||||
// Change the IL call site of a shared function to its clone.
|
|
||||||
//
|
|
||||||
void PIC16Cloner::
|
|
||||||
remapAllSites(Function *Caller, Function *OrgF, Function *Clone) {
|
|
||||||
// First find the caller to update. If the caller itself is cloned
|
|
||||||
// then use the cloned caller. Otherwise use it.
|
|
||||||
cloned_map_iterator cm_it = ClonedFunctionMap.find(Caller);
|
|
||||||
if (cm_it != ClonedFunctionMap.end())
|
|
||||||
Caller = cm_it->second;
|
|
||||||
|
|
||||||
// For the lack of a better call site finding mechanism, iterate over
|
|
||||||
// all insns to find the uses of original fn.
|
|
||||||
for (Function::iterator BI = Caller->begin(); BI != Caller->end(); ++BI) {
|
|
||||||
BasicBlock &BB = *BI;
|
|
||||||
for (BasicBlock::iterator II = BB.begin(); II != BB.end(); ++II) {
|
|
||||||
if (II->getNumOperands() > 0 && II->getOperand(0) == OrgF)
|
|
||||||
II->setOperand(0, Clone);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
//===-- PIC16Cloner.h - PIC16 LLVM Cloner for shared functions --*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains declaration of a cloner class clone all functions that
|
|
||||||
// are shared between the main line code (ML) and interrupt line code (IL).
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16CLONER_H
|
|
||||||
#define PIC16CLONER_H
|
|
||||||
|
|
||||||
#include "llvm/ADT/ValueMap.h"
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
using std::vector;
|
|
||||||
using std::string;
|
|
||||||
using std::map;
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
// forward classes.
|
|
||||||
class Value;
|
|
||||||
class Function;
|
|
||||||
class Module;
|
|
||||||
class ModulePass;
|
|
||||||
class CallGraph;
|
|
||||||
class CallGraphNode;
|
|
||||||
class AnalysisUsage;
|
|
||||||
|
|
||||||
class PIC16Cloner : public ModulePass {
|
|
||||||
public:
|
|
||||||
static char ID; // Class identification
|
|
||||||
PIC16Cloner() : ModulePass(ID) {}
|
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
|
||||||
AU.addRequired<CallGraph>();
|
|
||||||
}
|
|
||||||
virtual bool runOnModule(Module &M);
|
|
||||||
|
|
||||||
private: // Functions
|
|
||||||
// Mark reachable functions for the MainLine or InterruptLine.
|
|
||||||
void markCallGraph(CallGraphNode *CGN, string StringMark);
|
|
||||||
|
|
||||||
// Clone auto variables of function specified.
|
|
||||||
void CloneAutos(Function *F);
|
|
||||||
|
|
||||||
// Clone the body of a function.
|
|
||||||
Function *cloneFunction(Function *F);
|
|
||||||
|
|
||||||
// Clone all shared functions.
|
|
||||||
void cloneSharedFunctions(CallGraphNode *isrCGN);
|
|
||||||
|
|
||||||
// Remap all call sites to the shared function.
|
|
||||||
void remapAllSites(Function *Caller, Function *OrgF, Function *Clone);
|
|
||||||
|
|
||||||
// Error reporting for PIC16Pass
|
|
||||||
void reportError(string ErrorString, vector<string> &Values);
|
|
||||||
void reportError(string ErrorString);
|
|
||||||
|
|
||||||
private: //data
|
|
||||||
// Records if the interrupt function has already been found.
|
|
||||||
// If more than one interrupt function is found then an error
|
|
||||||
// should be thrown.
|
|
||||||
bool foundISR;
|
|
||||||
|
|
||||||
// This ValueMap maps the auto variables of the original functions with
|
|
||||||
// the corresponding cloned auto variable of the cloned function.
|
|
||||||
// This value map is passed during the function cloning so that all the
|
|
||||||
// uses of auto variables be updated properly.
|
|
||||||
ValueMap<const Value*, Value*> VMap;
|
|
||||||
|
|
||||||
// Map of a already cloned functions.
|
|
||||||
map<Function *, Function *> ClonedFunctionMap;
|
|
||||||
typedef map<Function *, Function *>::iterator cloned_map_iterator;
|
|
||||||
};
|
|
||||||
} // End of anonymous namespace
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,182 +0,0 @@
|
||||||
//===-- PIC16Overlay.cpp - Implementation for PIC16 Frame Overlay===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the PIC16 Frame Overlay implementation.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
|
|
||||||
#include "llvm/Analysis/CallGraph.h"
|
|
||||||
#include "llvm/Pass.h"
|
|
||||||
#include "llvm/Module.h"
|
|
||||||
#include "llvm/Instructions.h"
|
|
||||||
#include "llvm/Value.h"
|
|
||||||
#include "PIC16Overlay.h"
|
|
||||||
#include "llvm/Function.h"
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <sstream>
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
char PIC16Overlay::ID = 0;
|
|
||||||
ModulePass *createPIC16OverlayPass() { return new PIC16Overlay(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16Overlay::getAnalysisUsage(AnalysisUsage &AU) const {
|
|
||||||
AU.setPreservesAll();
|
|
||||||
AU.addRequired<CallGraph>();
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16Overlay::DFSTraverse(CallGraphNode *CGN, unsigned Depth) {
|
|
||||||
// Do not set any color for external calling node.
|
|
||||||
if (Depth != 0 && CGN->getFunction()) {
|
|
||||||
unsigned Color = getColor(CGN->getFunction());
|
|
||||||
|
|
||||||
// Handle indirectly called functions
|
|
||||||
if (Color >= PIC16OVERLAY::StartIndirectCallColor ||
|
|
||||||
Depth >= PIC16OVERLAY::StartIndirectCallColor) {
|
|
||||||
// All functions called from an indirectly called function are given
|
|
||||||
// an unique color.
|
|
||||||
if (Color < PIC16OVERLAY::StartIndirectCallColor &&
|
|
||||||
Depth >= PIC16OVERLAY::StartIndirectCallColor)
|
|
||||||
setColor(CGN->getFunction(), Depth);
|
|
||||||
|
|
||||||
for (unsigned int i = 0; i < CGN->size(); i++)
|
|
||||||
DFSTraverse((*CGN)[i], ++IndirectCallColor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Just return if the node already has a color greater than the current
|
|
||||||
// depth. A node must be colored with the maximum depth that it has.
|
|
||||||
if (Color >= Depth)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Depth = ModifyDepthForInterrupt(CGN, Depth);
|
|
||||||
setColor(CGN->getFunction(), Depth);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Color all children of this node with color depth+1.
|
|
||||||
for (unsigned int i = 0; i < CGN->size(); i++)
|
|
||||||
DFSTraverse((*CGN)[i], Depth+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PIC16Overlay::ModifyDepthForInterrupt(CallGraphNode *CGN,
|
|
||||||
unsigned Depth) {
|
|
||||||
Function *Fn = CGN->getFunction();
|
|
||||||
|
|
||||||
// Return original Depth if function or section for function do not exist.
|
|
||||||
if (!Fn || !Fn->hasSection())
|
|
||||||
return Depth;
|
|
||||||
|
|
||||||
// Return original Depth if this function is not marked as interrupt.
|
|
||||||
if (Fn->getSection().find("interrupt") == string::npos)
|
|
||||||
return Depth;
|
|
||||||
|
|
||||||
Depth = Depth + InterruptDepth;
|
|
||||||
return Depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16Overlay::setColor(Function *Fn, unsigned Color) {
|
|
||||||
std::string Section = "";
|
|
||||||
if (Fn->hasSection())
|
|
||||||
Section = Fn->getSection();
|
|
||||||
|
|
||||||
size_t Pos = Section.find(OverlayStr);
|
|
||||||
|
|
||||||
// Convert Color to string.
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << Color;
|
|
||||||
std::string ColorString = ss.str();
|
|
||||||
|
|
||||||
// If color is already set then reset it with the new value. Else append
|
|
||||||
// the Color string to section.
|
|
||||||
if (Pos != std::string::npos) {
|
|
||||||
Pos += OverlayStr.length();
|
|
||||||
char c = Section.at(Pos);
|
|
||||||
unsigned OldColorLength = 0;
|
|
||||||
while (c >= '0' && c<= '9') {
|
|
||||||
OldColorLength++;
|
|
||||||
if (Pos < Section.length() - 1)
|
|
||||||
Pos++;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
c = Section.at(Pos);
|
|
||||||
}
|
|
||||||
// Replace old color with new one.
|
|
||||||
Section.replace(Pos-OldColorLength +1, OldColorLength, ColorString);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Append Color information to section string.
|
|
||||||
if (Fn->hasSection())
|
|
||||||
Section.append(" ");
|
|
||||||
Section.append(OverlayStr + ColorString);
|
|
||||||
}
|
|
||||||
Fn->setSection(Section);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PIC16Overlay::getColor(Function *Fn) {
|
|
||||||
int Color = 0;
|
|
||||||
if (!Fn->hasSection())
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
std::string Section = Fn->getSection();
|
|
||||||
size_t Pos = Section.find(OverlayStr);
|
|
||||||
|
|
||||||
// Return 0 if Color is not set.
|
|
||||||
if (Pos == std::string::npos)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
// Set Pos to after "Overlay=".
|
|
||||||
Pos += OverlayStr.length();
|
|
||||||
char c = Section.at(Pos);
|
|
||||||
std::string ColorString = "";
|
|
||||||
|
|
||||||
// Find the string representing Color. A Color can only consist of digits.
|
|
||||||
while (c >= '0' && c<= '9') {
|
|
||||||
ColorString.append(1,c);
|
|
||||||
if (Pos < Section.length() - 1)
|
|
||||||
Pos++;
|
|
||||||
else
|
|
||||||
break;
|
|
||||||
c = Section.at(Pos);
|
|
||||||
}
|
|
||||||
Color = atoi(ColorString.c_str());
|
|
||||||
|
|
||||||
return Color;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PIC16Overlay::runOnModule(Module &M) {
|
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
|
||||||
CallGraphNode *ECN = CG.getExternalCallingNode();
|
|
||||||
|
|
||||||
MarkIndirectlyCalledFunctions(M);
|
|
||||||
// Since External Calling Node is the base function, do a depth first
|
|
||||||
// traversal of CallGraph with ECN as root. Each node with be marked with
|
|
||||||
// a color that is max(color(callers)) + 1.
|
|
||||||
if(ECN) {
|
|
||||||
DFSTraverse(ECN, 0);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16Overlay::MarkIndirectlyCalledFunctions(Module &M) {
|
|
||||||
// If the use of a function is not a call instruction then this
|
|
||||||
// function might be called indirectly. In that case give it
|
|
||||||
// an unique color.
|
|
||||||
for (Module::iterator MI = M.begin(), E = M.end(); MI != E; ++MI) {
|
|
||||||
for (Value::use_iterator I = MI->use_begin(), E = MI->use_end(); I != E;
|
|
||||||
++I) {
|
|
||||||
User *U = *I;
|
|
||||||
if ((!isa<CallInst>(U) && !isa<InvokeInst>(U))
|
|
||||||
|| !CallSite(cast<Instruction>(U)).isCallee(I)) {
|
|
||||||
setColor(MI, ++IndirectCallColor);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,60 +0,0 @@
|
||||||
//===-- PIC16Overlay.h - Interface for PIC16 Frame Overlay -*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the PIC16 Overlay infrastructure.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16FRAMEOVERLAY_H
|
|
||||||
#define PIC16FRAMEOVERLAY_H
|
|
||||||
|
|
||||||
|
|
||||||
using std::string;
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
// Forward declarations.
|
|
||||||
class Function;
|
|
||||||
class Module;
|
|
||||||
class ModulePass;
|
|
||||||
class AnalysisUsage;
|
|
||||||
class CallGraphNode;
|
|
||||||
class CallGraph;
|
|
||||||
|
|
||||||
namespace PIC16OVERLAY {
|
|
||||||
enum OverlayConsts {
|
|
||||||
StartInterruptColor = 200,
|
|
||||||
StartIndirectCallColor = 300
|
|
||||||
};
|
|
||||||
}
|
|
||||||
class PIC16Overlay : public ModulePass {
|
|
||||||
std::string OverlayStr;
|
|
||||||
unsigned InterruptDepth;
|
|
||||||
unsigned IndirectCallColor;
|
|
||||||
public:
|
|
||||||
static char ID; // Class identification
|
|
||||||
PIC16Overlay() : ModulePass(ID) {
|
|
||||||
OverlayStr = "Overlay=";
|
|
||||||
InterruptDepth = PIC16OVERLAY::StartInterruptColor;
|
|
||||||
IndirectCallColor = PIC16OVERLAY::StartIndirectCallColor;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
|
||||||
virtual bool runOnModule(Module &M);
|
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned getColor(Function *Fn);
|
|
||||||
void setColor(Function *Fn, unsigned Color);
|
|
||||||
unsigned ModifyDepthForInterrupt(CallGraphNode *CGN, unsigned Depth);
|
|
||||||
void MarkIndirectlyCalledFunctions(Module &M);
|
|
||||||
void DFSTraverse(CallGraphNode *CGN, unsigned Depth);
|
|
||||||
};
|
|
||||||
} // End of namespace
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,84 +0,0 @@
|
||||||
//===- PIC16RegisterInfo.cpp - PIC16 Register Information -----------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the PIC16 implementation of the TargetRegisterInfo class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define DEBUG_TYPE "pic16-reg-info"
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16RegisterInfo.h"
|
|
||||||
#include "llvm/ADT/BitVector.h"
|
|
||||||
#include "llvm/Support/ErrorHandling.h"
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
PIC16RegisterInfo::PIC16RegisterInfo(const TargetInstrInfo &tii,
|
|
||||||
const PIC16Subtarget &st)
|
|
||||||
: PIC16GenRegisterInfo(PIC16::ADJCALLSTACKDOWN, PIC16::ADJCALLSTACKUP),
|
|
||||||
TII(tii),
|
|
||||||
ST(st) {}
|
|
||||||
|
|
||||||
#include "PIC16GenRegisterInfo.inc"
|
|
||||||
|
|
||||||
/// PIC16 Callee Saved Registers
|
|
||||||
const unsigned* PIC16RegisterInfo::
|
|
||||||
getCalleeSavedRegs(const MachineFunction *MF) const {
|
|
||||||
static const unsigned CalleeSavedRegs[] = { 0 };
|
|
||||||
return CalleeSavedRegs;
|
|
||||||
}
|
|
||||||
|
|
||||||
BitVector PIC16RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
|
||||||
BitVector Reserved(getNumRegs());
|
|
||||||
return Reserved;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PIC16RegisterInfo::hasFP(const MachineFunction &MF) const {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PIC16RegisterInfo::
|
|
||||||
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
|
||||||
RegScavenger *RS) const
|
|
||||||
{ /* NOT YET IMPLEMENTED */ }
|
|
||||||
|
|
||||||
void PIC16RegisterInfo::emitPrologue(MachineFunction &MF) const
|
|
||||||
{ /* NOT YET IMPLEMENTED */ }
|
|
||||||
|
|
||||||
void PIC16RegisterInfo::
|
|
||||||
emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
|
||||||
{ /* NOT YET IMPLEMENTED */ }
|
|
||||||
|
|
||||||
int PIC16RegisterInfo::
|
|
||||||
getDwarfRegNum(unsigned RegNum, bool isEH) const {
|
|
||||||
llvm_unreachable("Not keeping track of debug information yet!!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PIC16RegisterInfo::getFrameRegister(const MachineFunction &MF) const {
|
|
||||||
llvm_unreachable("PIC16 Does not have any frame register");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned PIC16RegisterInfo::getRARegister() const {
|
|
||||||
llvm_unreachable("PIC16 Does not have any return address register");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function eliminates ADJCALLSTACKDOWN,
|
|
||||||
// ADJCALLSTACKUP pseudo instructions
|
|
||||||
void PIC16RegisterInfo::
|
|
||||||
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator I) const {
|
|
||||||
// Simply discard ADJCALLSTACKDOWN,
|
|
||||||
// ADJCALLSTACKUP instructions.
|
|
||||||
MBB.erase(I);
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,64 +0,0 @@
|
||||||
//===- PIC16RegisterInfo.h - PIC16 Register Information Impl ----*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file contains the PIC16 implementation of the TargetRegisterInfo class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16REGISTERINFO_H
|
|
||||||
#define PIC16REGISTERINFO_H
|
|
||||||
|
|
||||||
#include "PIC16GenRegisterInfo.h.inc"
|
|
||||||
#include "llvm/Target/TargetRegisterInfo.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
// Forward Declarations.
|
|
||||||
class PIC16Subtarget;
|
|
||||||
class TargetInstrInfo;
|
|
||||||
|
|
||||||
class PIC16RegisterInfo : public PIC16GenRegisterInfo {
|
|
||||||
private:
|
|
||||||
const TargetInstrInfo &TII;
|
|
||||||
const PIC16Subtarget &ST;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PIC16RegisterInfo(const TargetInstrInfo &tii,
|
|
||||||
const PIC16Subtarget &st);
|
|
||||||
|
|
||||||
|
|
||||||
//------------------------------------------------------
|
|
||||||
// Pure virtual functions from TargetRegisterInfo
|
|
||||||
//------------------------------------------------------
|
|
||||||
|
|
||||||
// PIC16 callee saved registers
|
|
||||||
virtual const unsigned*
|
|
||||||
getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
void eliminateCallFramePseudoInstr(MachineFunction &MF,
|
|
||||||
MachineBasicBlock &MBB,
|
|
||||||
MachineBasicBlock::iterator I) const;
|
|
||||||
|
|
||||||
virtual void emitPrologue(MachineFunction &MF) const;
|
|
||||||
virtual void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
|
|
||||||
virtual int getDwarfRegNum(unsigned RegNum, bool isEH) const;
|
|
||||||
virtual unsigned getFrameRegister(const MachineFunction &MF) const;
|
|
||||||
virtual unsigned getRARegister() const;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,33 +0,0 @@
|
||||||
//===- PIC16RegisterInfo.td - PIC16 Register defs ------------*- tblgen -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
// Declarations that describe the PIC16 register file
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
class PIC16Reg<string n> : Register<n> {
|
|
||||||
let Namespace = "PIC16";
|
|
||||||
}
|
|
||||||
|
|
||||||
// PIC16 Registers.
|
|
||||||
def W : PIC16Reg<"W">;
|
|
||||||
def FSR0 : PIC16Reg<"FSR0">;
|
|
||||||
def FSR1 : PIC16Reg<"FSR1">;
|
|
||||||
def BS : PIC16Reg<"BS">;
|
|
||||||
def PCLATH : PIC16Reg<"PCLATH">;
|
|
||||||
|
|
||||||
def STATUS : PIC16Reg<"STATUS">;
|
|
||||||
|
|
||||||
// PIC16 Register classes.
|
|
||||||
def GPR : RegisterClass<"PIC16", [i8], 8, [W]>;
|
|
||||||
def FSR16 : RegisterClass<"PIC16", [i16], 8, [FSR0, FSR1]>;
|
|
||||||
def BSR : RegisterClass<"PIC16", [i8], 8, [BS]>;
|
|
||||||
def PCLATHR : RegisterClass<"PIC16", [i8], 8, [PCLATH]>;
|
|
||||||
def STATUSR : RegisterClass<"PIC16", [i8], 8, [STATUS]>;
|
|
||||||
|
|
|
@ -1,108 +0,0 @@
|
||||||
//===-- PIC16Section.cpp - PIC16 Section ----------- --------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16ABINames.h"
|
|
||||||
#include "PIC16Section.h"
|
|
||||||
#include "llvm/MC/MCContext.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
|
|
||||||
// This is the only way to create a PIC16Section. Sections created here
|
|
||||||
// do not need to be explicitly deleted as they are managed by auto_ptrs.
|
|
||||||
PIC16Section *PIC16Section::Create(StringRef Name, PIC16SectionType Ty,
|
|
||||||
StringRef Address, int Color,
|
|
||||||
MCContext &Ctx) {
|
|
||||||
|
|
||||||
/// Determine the internal SectionKind info.
|
|
||||||
/// Users of PIC16Section class should not need to know the internal
|
|
||||||
/// SectionKind. They should work only with PIC16SectionType.
|
|
||||||
///
|
|
||||||
/// PIC16 Terminology for section kinds is as below.
|
|
||||||
/// UDATA - BSS
|
|
||||||
/// IDATA - initialized data (equiv to Metadata)
|
|
||||||
/// ROMDATA - ReadOnly.
|
|
||||||
/// UDATA_OVR - Sections that can be overlaid. Section of such type is
|
|
||||||
/// used to contain function autos an frame. We can think of
|
|
||||||
/// it as equiv to llvm ThreadBSS)
|
|
||||||
/// UDATA_SHR - Shared RAM. Memory area that is mapped to all banks.
|
|
||||||
|
|
||||||
SectionKind K;
|
|
||||||
switch (Ty) {
|
|
||||||
default: llvm_unreachable ("can not create unknown section type");
|
|
||||||
case UDATA_OVR: {
|
|
||||||
K = SectionKind::getThreadBSS();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case UDATA_SHR:
|
|
||||||
case UDATA: {
|
|
||||||
K = SectionKind::getBSS();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ROMDATA:
|
|
||||||
case IDATA: {
|
|
||||||
K = SectionKind::getMetadata();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case CODE: {
|
|
||||||
K = SectionKind::getText();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy strings into context allocated memory so they get free'd when the
|
|
||||||
// context is destroyed.
|
|
||||||
char *NameCopy = static_cast<char*>(Ctx.Allocate(Name.size(), 1));
|
|
||||||
memcpy(NameCopy, Name.data(), Name.size());
|
|
||||||
char *AddressCopy = static_cast<char*>(Ctx.Allocate(Address.size(), 1));
|
|
||||||
memcpy(AddressCopy, Address.data(), Address.size());
|
|
||||||
|
|
||||||
// Create the Section.
|
|
||||||
PIC16Section *S =
|
|
||||||
new (Ctx) PIC16Section(StringRef(NameCopy, Name.size()), K,
|
|
||||||
StringRef(AddressCopy, Address.size()), Color);
|
|
||||||
S->T = Ty;
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
// A generic way to print all types of sections.
|
|
||||||
void PIC16Section::PrintSwitchToSection(const MCAsmInfo &MAI,
|
|
||||||
raw_ostream &OS) const {
|
|
||||||
|
|
||||||
// If the section is overlaid(i.e. it has a color), print overlay name for
|
|
||||||
// it. Otherwise print its normal name.
|
|
||||||
if (Color != -1)
|
|
||||||
OS << PAN::getOverlayName(getName(), Color) << '\t';
|
|
||||||
else
|
|
||||||
OS << getName() << '\t';
|
|
||||||
|
|
||||||
// Print type.
|
|
||||||
switch (getType()) {
|
|
||||||
default : llvm_unreachable ("unknown section type");
|
|
||||||
case UDATA: OS << "UDATA"; break;
|
|
||||||
case IDATA: OS << "IDATA"; break;
|
|
||||||
case ROMDATA: OS << "ROMDATA"; break;
|
|
||||||
case UDATA_SHR: OS << "UDATA_SHR"; break;
|
|
||||||
case UDATA_OVR: OS << "UDATA_OVR"; break;
|
|
||||||
case CODE: OS << "CODE"; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
OS << '\t';
|
|
||||||
|
|
||||||
// Print Address.
|
|
||||||
OS << Address;
|
|
||||||
|
|
||||||
OS << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PIC16Section::UseCodeAlign() const {
|
|
||||||
return isCODE_Type();
|
|
||||||
}
|
|
|
@ -1,101 +0,0 @@
|
||||||
//===- PIC16Section.h - PIC16-specific section representation -*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file declares the PIC16Section class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef LLVM_PIC16SECTION_H
|
|
||||||
#define LLVM_PIC16SECTION_H
|
|
||||||
|
|
||||||
#include "llvm/MC/MCSection.h"
|
|
||||||
#include "llvm/GlobalVariable.h"
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
/// PIC16Section - Represents a physical section in PIC16 COFF.
|
|
||||||
/// Contains data objects.
|
|
||||||
///
|
|
||||||
class PIC16Section : public MCSection {
|
|
||||||
/// PIC16 Sections does not really use the SectionKind class to
|
|
||||||
/// to distinguish between various types of sections. PIC16 maintain
|
|
||||||
/// its own Section Type info. See the PIC16SectionType enum in PIC16.h
|
|
||||||
/// for various section types.
|
|
||||||
PIC16SectionType T;
|
|
||||||
|
|
||||||
/// Name of the section to uniquely identify it.
|
|
||||||
StringRef Name;
|
|
||||||
|
|
||||||
/// User can specify an address at which a section should be placed.
|
|
||||||
/// Negative value here means user hasn't specified any.
|
|
||||||
StringRef Address;
|
|
||||||
|
|
||||||
/// Overlay information - Sections with same color can be overlaid on
|
|
||||||
/// one another.
|
|
||||||
int Color;
|
|
||||||
|
|
||||||
/// Total size of all data objects contained here.
|
|
||||||
unsigned Size;
|
|
||||||
|
|
||||||
PIC16Section(StringRef name, SectionKind K, StringRef addr, int color)
|
|
||||||
: MCSection(SV_PIC16, K), Name(name), Address(addr),
|
|
||||||
Color(color), Size(0) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Return the name of the section.
|
|
||||||
StringRef getName() const { return Name; }
|
|
||||||
|
|
||||||
/// Return the Address of the section.
|
|
||||||
StringRef getAddress() const { return Address; }
|
|
||||||
|
|
||||||
/// Return the Color of the section.
|
|
||||||
int getColor() const { return Color; }
|
|
||||||
void setColor(int color) { Color = color; }
|
|
||||||
|
|
||||||
/// Return the size of the section.
|
|
||||||
unsigned getSize() const { return Size; }
|
|
||||||
void setSize(unsigned size) { Size = size; }
|
|
||||||
|
|
||||||
/// Conatined data objects.
|
|
||||||
// FIXME: This vector is leaked because sections are allocated with a
|
|
||||||
// BumpPtrAllocator.
|
|
||||||
std::vector<const GlobalVariable *>Items;
|
|
||||||
|
|
||||||
/// Check section type.
|
|
||||||
bool isUDATA_Type() const { return T == UDATA; }
|
|
||||||
bool isIDATA_Type() const { return T == IDATA; }
|
|
||||||
bool isROMDATA_Type() const { return T == ROMDATA; }
|
|
||||||
bool isUDATA_OVR_Type() const { return T == UDATA_OVR; }
|
|
||||||
bool isUDATA_SHR_Type() const { return T == UDATA_SHR; }
|
|
||||||
bool isCODE_Type() const { return T == CODE; }
|
|
||||||
|
|
||||||
PIC16SectionType getType() const { return T; }
|
|
||||||
|
|
||||||
/// This would be the only way to create a section.
|
|
||||||
static PIC16Section *Create(StringRef Name, PIC16SectionType Ty,
|
|
||||||
StringRef Address, int Color,
|
|
||||||
MCContext &Ctx);
|
|
||||||
|
|
||||||
/// Override this as PIC16 has its own way of printing switching
|
|
||||||
/// to a section.
|
|
||||||
virtual void PrintSwitchToSection(const MCAsmInfo &MAI,
|
|
||||||
raw_ostream &OS) const;
|
|
||||||
|
|
||||||
virtual bool UseCodeAlign() const;
|
|
||||||
|
|
||||||
static bool classof(const MCSection *S) {
|
|
||||||
return S->getVariant() == SV_PIC16;
|
|
||||||
}
|
|
||||||
static bool classof(const PIC16Section *) { return true; }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,23 +0,0 @@
|
||||||
//===-- PIC16SelectionDAGInfo.cpp - PIC16 SelectionDAG Info ---------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements the PIC16SelectionDAGInfo class.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#define DEBUG_TYPE "pic16-selectiondag-info"
|
|
||||||
#include "PIC16TargetMachine.h"
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
PIC16SelectionDAGInfo::PIC16SelectionDAGInfo(const PIC16TargetMachine &TM)
|
|
||||||
: TargetSelectionDAGInfo(TM) {
|
|
||||||
}
|
|
||||||
|
|
||||||
PIC16SelectionDAGInfo::~PIC16SelectionDAGInfo() {
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
//===-- PIC16SelectionDAGInfo.h - PIC16 SelectionDAG Info -------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file defines the PIC16 subclass for TargetSelectionDAGInfo.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16SELECTIONDAGINFO_H
|
|
||||||
#define PIC16SELECTIONDAGINFO_H
|
|
||||||
|
|
||||||
#include "llvm/Target/TargetSelectionDAGInfo.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
class PIC16TargetMachine;
|
|
||||||
|
|
||||||
class PIC16SelectionDAGInfo : public TargetSelectionDAGInfo {
|
|
||||||
public:
|
|
||||||
explicit PIC16SelectionDAGInfo(const PIC16TargetMachine &TM);
|
|
||||||
~PIC16SelectionDAGInfo();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,27 +0,0 @@
|
||||||
//===- PIC16Subtarget.cpp - PIC16 Subtarget Information -------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file implements the PIC16 specific subclass of TargetSubtarget.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16Subtarget.h"
|
|
||||||
#include "PIC16GenSubtarget.inc"
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
PIC16Subtarget::PIC16Subtarget(const std::string &TT, const std::string &FS,
|
|
||||||
bool Cooper)
|
|
||||||
:IsCooper(Cooper)
|
|
||||||
{
|
|
||||||
std::string CPU = "generic";
|
|
||||||
|
|
||||||
// Parse features string.
|
|
||||||
ParseSubtargetFeatures(FS, CPU);
|
|
||||||
}
|
|
|
@ -1,44 +0,0 @@
|
||||||
//=====-- PIC16Subtarget.h - Define Subtarget for the PIC16 ---*- C++ -*--====//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file declares the PIC16 specific subclass of TargetSubtarget.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef PIC16SUBTARGET_H
|
|
||||||
#define PIC16SUBTARGET_H
|
|
||||||
|
|
||||||
#include "llvm/Target/TargetSubtarget.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
class PIC16Subtarget : public TargetSubtarget {
|
|
||||||
|
|
||||||
// IsCooper - Target ISA is Cooper.
|
|
||||||
bool IsCooper;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// This constructor initializes the data members to match that
|
|
||||||
/// of the specified triple.
|
|
||||||
///
|
|
||||||
PIC16Subtarget(const std::string &TT, const std::string &FS, bool Cooper);
|
|
||||||
|
|
||||||
/// isCooper - Returns true if the target ISA is Cooper.
|
|
||||||
bool isCooper() const { return IsCooper; }
|
|
||||||
|
|
||||||
/// ParseSubtargetFeatures - Parses features string setting specified
|
|
||||||
/// subtarget options. Definition of function is auto generated by tblgen.
|
|
||||||
std::string ParseSubtargetFeatures(const std::string &FS,
|
|
||||||
const std::string &CPU);
|
|
||||||
};
|
|
||||||
} // End llvm namespace
|
|
||||||
|
|
||||||
#endif // PIC16SUBTARGET_H
|
|
|
@ -1,55 +0,0 @@
|
||||||
//===-- PIC16TargetMachine.cpp - Define TargetMachine for PIC16 -----------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// Top-level implementation for the PIC16 target.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16MCAsmInfo.h"
|
|
||||||
#include "PIC16TargetMachine.h"
|
|
||||||
#include "llvm/PassManager.h"
|
|
||||||
#include "llvm/CodeGen/Passes.h"
|
|
||||||
#include "llvm/Target/TargetRegistry.h"
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
extern "C" void LLVMInitializePIC16Target() {
|
|
||||||
// Register the target. Curretnly the codegen works for
|
|
||||||
// enhanced pic16 mid-range.
|
|
||||||
RegisterTargetMachine<PIC16TargetMachine> X(ThePIC16Target);
|
|
||||||
RegisterAsmInfo<PIC16MCAsmInfo> A(ThePIC16Target);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// PIC16TargetMachine - Enhanced PIC16 mid-range Machine. May also represent
|
|
||||||
// a Traditional Machine if 'Trad' is true.
|
|
||||||
PIC16TargetMachine::PIC16TargetMachine(const Target &T, const std::string &TT,
|
|
||||||
const std::string &FS, bool Trad)
|
|
||||||
: LLVMTargetMachine(T, TT),
|
|
||||||
Subtarget(TT, FS, Trad),
|
|
||||||
DataLayout("e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-n8"),
|
|
||||||
InstrInfo(*this), TLInfo(*this), TSInfo(*this),
|
|
||||||
FrameInfo(TargetFrameInfo::StackGrowsUp, 8, 0) { }
|
|
||||||
|
|
||||||
|
|
||||||
bool PIC16TargetMachine::addInstSelector(PassManagerBase &PM,
|
|
||||||
CodeGenOpt::Level OptLevel) {
|
|
||||||
// Install an instruction selector.
|
|
||||||
PM.add(createPIC16ISelDag(*this));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PIC16TargetMachine::addPreEmitPass(PassManagerBase &PM,
|
|
||||||
CodeGenOpt::Level OptLevel) {
|
|
||||||
PM.add(createPIC16MemSelOptimizerPass());
|
|
||||||
return true; // -print-machineinstr should print after this.
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,70 +0,0 @@
|
||||||
//===-- PIC16TargetMachine.h - Define TargetMachine for PIC16 ---*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// This file declares the PIC16 specific subclass of TargetMachine.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef PIC16_TARGETMACHINE_H
|
|
||||||
#define PIC16_TARGETMACHINE_H
|
|
||||||
|
|
||||||
#include "PIC16InstrInfo.h"
|
|
||||||
#include "PIC16ISelLowering.h"
|
|
||||||
#include "PIC16SelectionDAGInfo.h"
|
|
||||||
#include "PIC16RegisterInfo.h"
|
|
||||||
#include "PIC16Subtarget.h"
|
|
||||||
#include "llvm/Target/TargetData.h"
|
|
||||||
#include "llvm/Target/TargetFrameInfo.h"
|
|
||||||
#include "llvm/Target/TargetMachine.h"
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
|
|
||||||
/// PIC16TargetMachine
|
|
||||||
///
|
|
||||||
class PIC16TargetMachine : public LLVMTargetMachine {
|
|
||||||
PIC16Subtarget Subtarget;
|
|
||||||
const TargetData DataLayout; // Calculates type size & alignment
|
|
||||||
PIC16InstrInfo InstrInfo;
|
|
||||||
PIC16TargetLowering TLInfo;
|
|
||||||
PIC16SelectionDAGInfo TSInfo;
|
|
||||||
|
|
||||||
// PIC16 does not have any call stack frame, therefore not having
|
|
||||||
// any PIC16 specific FrameInfo class.
|
|
||||||
TargetFrameInfo FrameInfo;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PIC16TargetMachine(const Target &T, const std::string &TT,
|
|
||||||
const std::string &FS, bool Cooper = false);
|
|
||||||
|
|
||||||
virtual const TargetFrameInfo *getFrameInfo() const { return &FrameInfo; }
|
|
||||||
virtual const PIC16InstrInfo *getInstrInfo() const { return &InstrInfo; }
|
|
||||||
virtual const TargetData *getTargetData() const { return &DataLayout;}
|
|
||||||
virtual const PIC16Subtarget *getSubtargetImpl() const { return &Subtarget; }
|
|
||||||
|
|
||||||
virtual const PIC16RegisterInfo *getRegisterInfo() const {
|
|
||||||
return &(InstrInfo.getRegisterInfo());
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const PIC16TargetLowering *getTargetLowering() const {
|
|
||||||
return &TLInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual const PIC16SelectionDAGInfo* getSelectionDAGInfo() const {
|
|
||||||
return &TSInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool addInstSelector(PassManagerBase &PM,
|
|
||||||
CodeGenOpt::Level OptLevel);
|
|
||||||
virtual bool addPreEmitPass(PassManagerBase &PM, CodeGenOpt::Level OptLevel);
|
|
||||||
}; // PIC16TargetMachine.
|
|
||||||
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,384 +0,0 @@
|
||||||
//===-- PIC16TargetObjectFile.cpp - PIC16 object files --------------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16TargetObjectFile.h"
|
|
||||||
#include "PIC16TargetMachine.h"
|
|
||||||
#include "PIC16Section.h"
|
|
||||||
#include "llvm/DerivedTypes.h"
|
|
||||||
#include "llvm/Module.h"
|
|
||||||
#include "llvm/MC/MCSection.h"
|
|
||||||
#include "llvm/MC/MCContext.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
|
|
||||||
PIC16TargetObjectFile::PIC16TargetObjectFile() {
|
|
||||||
}
|
|
||||||
|
|
||||||
PIC16TargetObjectFile::~PIC16TargetObjectFile() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find a pic16 section. Return null if not found. Do not create one.
|
|
||||||
PIC16Section *PIC16TargetObjectFile::
|
|
||||||
findPIC16Section(const std::string &Name) const {
|
|
||||||
/// Return if we have an already existing one.
|
|
||||||
PIC16Section *Entry = SectionsByName[Name];
|
|
||||||
if (Entry)
|
|
||||||
return Entry;
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Find a pic16 section. If not found, create one.
|
|
||||||
PIC16Section *PIC16TargetObjectFile::
|
|
||||||
getPIC16Section(const std::string &Name, PIC16SectionType Ty,
|
|
||||||
const std::string &Address, int Color) const {
|
|
||||||
|
|
||||||
/// Return if we have an already existing one.
|
|
||||||
PIC16Section *&Entry = SectionsByName[Name];
|
|
||||||
if (Entry)
|
|
||||||
return Entry;
|
|
||||||
|
|
||||||
|
|
||||||
Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
|
|
||||||
return Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find a standard pic16 data section. If not found, create one and keep
|
|
||||||
/// track of it by adding it to appropriate std section list.
|
|
||||||
PIC16Section *PIC16TargetObjectFile::
|
|
||||||
getPIC16DataSection(const std::string &Name, PIC16SectionType Ty,
|
|
||||||
const std::string &Address, int Color) const {
|
|
||||||
|
|
||||||
/// Return if we have an already existing one.
|
|
||||||
PIC16Section *&Entry = SectionsByName[Name];
|
|
||||||
if (Entry)
|
|
||||||
return Entry;
|
|
||||||
|
|
||||||
|
|
||||||
/// Else create a new one and add it to appropriate section list.
|
|
||||||
Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
|
|
||||||
|
|
||||||
switch (Ty) {
|
|
||||||
default: llvm_unreachable ("unknow standard section type.");
|
|
||||||
case UDATA: UDATASections_.push_back(Entry); break;
|
|
||||||
case IDATA: IDATASections_.push_back(Entry); break;
|
|
||||||
case ROMDATA: ROMDATASection_ = Entry; break;
|
|
||||||
case UDATA_SHR: SHAREDUDATASection_ = Entry; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Find a standard pic16 autos section. If not found, create one and keep
|
|
||||||
/// track of it by adding it to appropriate std section list.
|
|
||||||
PIC16Section *PIC16TargetObjectFile::
|
|
||||||
getPIC16AutoSection(const std::string &Name, PIC16SectionType Ty,
|
|
||||||
const std::string &Address, int Color) const {
|
|
||||||
|
|
||||||
/// Return if we have an already existing one.
|
|
||||||
PIC16Section *&Entry = SectionsByName[Name];
|
|
||||||
if (Entry)
|
|
||||||
return Entry;
|
|
||||||
|
|
||||||
|
|
||||||
/// Else create a new one and add it to appropriate section list.
|
|
||||||
Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
|
|
||||||
|
|
||||||
assert (Ty == UDATA_OVR && "incorrect section type for autos");
|
|
||||||
AUTOSections_.push_back(Entry);
|
|
||||||
|
|
||||||
return Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find a pic16 user section. If not found, create one and keep
|
|
||||||
/// track of it by adding it to appropriate std section list.
|
|
||||||
PIC16Section *PIC16TargetObjectFile::
|
|
||||||
getPIC16UserSection(const std::string &Name, PIC16SectionType Ty,
|
|
||||||
const std::string &Address, int Color) const {
|
|
||||||
|
|
||||||
/// Return if we have an already existing one.
|
|
||||||
PIC16Section *&Entry = SectionsByName[Name];
|
|
||||||
if (Entry)
|
|
||||||
return Entry;
|
|
||||||
|
|
||||||
|
|
||||||
/// Else create a new one and add it to appropriate section list.
|
|
||||||
Entry = PIC16Section::Create(Name, Ty, Address, Color, getContext());
|
|
||||||
|
|
||||||
USERSections_.push_back(Entry);
|
|
||||||
|
|
||||||
return Entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Do some standard initialization.
|
|
||||||
void PIC16TargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &tm){
|
|
||||||
TargetLoweringObjectFile::Initialize(Ctx, tm);
|
|
||||||
TM = &tm;
|
|
||||||
|
|
||||||
ROMDATASection_ = NULL;
|
|
||||||
SHAREDUDATASection_ = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// allocateUDATA - Allocate a un-initialized global to an existing or new UDATA
|
|
||||||
/// section and return that section.
|
|
||||||
const MCSection *
|
|
||||||
PIC16TargetObjectFile::allocateUDATA(const GlobalVariable *GV) const {
|
|
||||||
assert(GV->hasInitializer() && "This global doesn't need space");
|
|
||||||
const Constant *C = GV->getInitializer();
|
|
||||||
assert(C->isNullValue() && "Unitialized globals has non-zero initializer");
|
|
||||||
|
|
||||||
// Find how much space this global needs.
|
|
||||||
const TargetData *TD = TM->getTargetData();
|
|
||||||
const Type *Ty = C->getType();
|
|
||||||
unsigned ValSize = TD->getTypeAllocSize(Ty);
|
|
||||||
|
|
||||||
// Go through all UDATA Sections and assign this variable
|
|
||||||
// to the first available section having enough space.
|
|
||||||
PIC16Section *Found = NULL;
|
|
||||||
for (unsigned i = 0; i < UDATASections_.size(); i++) {
|
|
||||||
if (DataBankSize - UDATASections_[i]->getSize() >= ValSize) {
|
|
||||||
Found = UDATASections_[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No UDATA section spacious enough was found. Crate a new one.
|
|
||||||
if (!Found) {
|
|
||||||
std::string name = PAN::getUdataSectionName(UDATASections_.size());
|
|
||||||
Found = getPIC16DataSection(name.c_str(), UDATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the GV into this UDATA section.
|
|
||||||
Found->Items.push_back(GV);
|
|
||||||
Found->setSize(Found->getSize() + ValSize);
|
|
||||||
return Found;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// allocateIDATA - allocate an initialized global into an existing
|
|
||||||
/// or new section and return that section.
|
|
||||||
const MCSection *
|
|
||||||
PIC16TargetObjectFile::allocateIDATA(const GlobalVariable *GV) const{
|
|
||||||
assert(GV->hasInitializer() && "This global doesn't need space");
|
|
||||||
const Constant *C = GV->getInitializer();
|
|
||||||
assert(!C->isNullValue() && "initialized globals has zero initializer");
|
|
||||||
assert(GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE &&
|
|
||||||
"can allocate initialized RAM data only");
|
|
||||||
|
|
||||||
// Find how much space this global needs.
|
|
||||||
const TargetData *TD = TM->getTargetData();
|
|
||||||
const Type *Ty = C->getType();
|
|
||||||
unsigned ValSize = TD->getTypeAllocSize(Ty);
|
|
||||||
|
|
||||||
// Go through all IDATA Sections and assign this variable
|
|
||||||
// to the first available section having enough space.
|
|
||||||
PIC16Section *Found = NULL;
|
|
||||||
for (unsigned i = 0; i < IDATASections_.size(); i++) {
|
|
||||||
if (DataBankSize - IDATASections_[i]->getSize() >= ValSize) {
|
|
||||||
Found = IDATASections_[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// No IDATA section spacious enough was found. Crate a new one.
|
|
||||||
if (!Found) {
|
|
||||||
std::string name = PAN::getIdataSectionName(IDATASections_.size());
|
|
||||||
Found = getPIC16DataSection(name.c_str(), IDATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Insert the GV into this IDATA.
|
|
||||||
Found->Items.push_back(GV);
|
|
||||||
Found->setSize(Found->getSize() + ValSize);
|
|
||||||
return Found;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate a program memory variable into ROMDATA section.
|
|
||||||
const MCSection *
|
|
||||||
PIC16TargetObjectFile::allocateROMDATA(const GlobalVariable *GV) const {
|
|
||||||
|
|
||||||
std::string name = PAN::getRomdataSectionName();
|
|
||||||
PIC16Section *S = getPIC16DataSection(name.c_str(), ROMDATA);
|
|
||||||
|
|
||||||
S->Items.push_back(GV);
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the section for an automatic variable of a function.
|
|
||||||
// For PIC16 they are globals only with mangled names.
|
|
||||||
const MCSection *
|
|
||||||
PIC16TargetObjectFile::allocateAUTO(const GlobalVariable *GV) const {
|
|
||||||
|
|
||||||
const std::string name = PAN::getSectionNameForSym(GV->getName());
|
|
||||||
PIC16Section *S = getPIC16AutoSection(name.c_str());
|
|
||||||
|
|
||||||
S->Items.push_back(GV);
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Override default implementation to put the true globals into
|
|
||||||
// multiple data sections if required.
|
|
||||||
const MCSection *
|
|
||||||
PIC16TargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV1,
|
|
||||||
SectionKind Kind,
|
|
||||||
Mangler *Mang,
|
|
||||||
const TargetMachine &TM) const {
|
|
||||||
// We select the section based on the initializer here, so it really
|
|
||||||
// has to be a GlobalVariable.
|
|
||||||
const GlobalVariable *GV = dyn_cast<GlobalVariable>(GV1);
|
|
||||||
if (!GV)
|
|
||||||
return TargetLoweringObjectFile::SelectSectionForGlobal(GV1, Kind, Mang,TM);
|
|
||||||
|
|
||||||
assert(GV->hasInitializer() && "A def without initializer?");
|
|
||||||
|
|
||||||
// First, if this is an automatic variable for a function, get the section
|
|
||||||
// name for it and return.
|
|
||||||
std::string name = GV->getName();
|
|
||||||
if (PAN::isLocalName(name))
|
|
||||||
return allocateAUTO(GV);
|
|
||||||
|
|
||||||
// See if this is an uninitialized global.
|
|
||||||
const Constant *C = GV->getInitializer();
|
|
||||||
if (C->isNullValue())
|
|
||||||
return allocateUDATA(GV);
|
|
||||||
|
|
||||||
// If this is initialized data in RAM. Put it in the correct IDATA section.
|
|
||||||
if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
|
|
||||||
return allocateIDATA(GV);
|
|
||||||
|
|
||||||
// This is initialized data in rom, put it in the readonly section.
|
|
||||||
if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
|
|
||||||
return allocateROMDATA(GV);
|
|
||||||
|
|
||||||
// Else let the default implementation take care of it.
|
|
||||||
return TargetLoweringObjectFile::SelectSectionForGlobal(GV, Kind, Mang,TM);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// getExplicitSectionGlobal - Allow the target to completely override
|
|
||||||
/// section assignment of a global.
|
|
||||||
const MCSection *PIC16TargetObjectFile::
|
|
||||||
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
|
|
||||||
Mangler *Mang, const TargetMachine &TM) const {
|
|
||||||
assert(GV->hasSection());
|
|
||||||
|
|
||||||
if (const GlobalVariable *GVar = cast<GlobalVariable>(GV)) {
|
|
||||||
std::string SectName = GVar->getSection();
|
|
||||||
// If address for a variable is specified, get the address and create
|
|
||||||
// section.
|
|
||||||
// FIXME: move this attribute checking in PAN.
|
|
||||||
std::string AddrStr = "Address=";
|
|
||||||
if (SectName.compare(0, AddrStr.length(), AddrStr) == 0) {
|
|
||||||
std::string SectAddr = SectName.substr(AddrStr.length());
|
|
||||||
if (SectAddr.compare("NEAR") == 0)
|
|
||||||
return allocateSHARED(GVar, Mang);
|
|
||||||
else
|
|
||||||
return allocateAtGivenAddress(GVar, SectAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the section specified with section attribute.
|
|
||||||
return allocateInGivenSection(GVar);
|
|
||||||
}
|
|
||||||
|
|
||||||
return getPIC16DataSection(GV->getSection().c_str(), UDATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
const MCSection *
|
|
||||||
PIC16TargetObjectFile::allocateSHARED(const GlobalVariable *GV,
|
|
||||||
Mangler *Mang) const {
|
|
||||||
// Make sure that this is an uninitialized global.
|
|
||||||
assert(GV->hasInitializer() && "This global doesn't need space");
|
|
||||||
if (!GV->getInitializer()->isNullValue()) {
|
|
||||||
// FIXME: Generate a warning in this case that near qualifier will be
|
|
||||||
// ignored.
|
|
||||||
return SelectSectionForGlobal(GV, SectionKind::getDataRel(), Mang, *TM);
|
|
||||||
}
|
|
||||||
std::string Name = PAN::getSharedUDataSectionName();
|
|
||||||
|
|
||||||
PIC16Section *SharedUDataSect = getPIC16DataSection(Name.c_str(), UDATA_SHR);
|
|
||||||
// Insert the GV into shared section.
|
|
||||||
SharedUDataSect->Items.push_back(GV);
|
|
||||||
return SharedUDataSect;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Interface used by AsmPrinter to get a code section for a function.
|
|
||||||
const PIC16Section *
|
|
||||||
PIC16TargetObjectFile::SectionForCode(const std::string &FnName,
|
|
||||||
bool isISR) const {
|
|
||||||
const std::string &sec_name = PAN::getCodeSectionName(FnName);
|
|
||||||
// If it is ISR, its code section starts at a specific address.
|
|
||||||
if (isISR)
|
|
||||||
return getPIC16Section(sec_name, CODE, PAN::getISRAddr());
|
|
||||||
return getPIC16Section(sec_name, CODE);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Interface used by AsmPrinter to get a frame section for a function.
|
|
||||||
const PIC16Section *
|
|
||||||
PIC16TargetObjectFile::SectionForFrame(const std::string &FnName) const {
|
|
||||||
const std::string &sec_name = PAN::getFrameSectionName(FnName);
|
|
||||||
return getPIC16Section(sec_name, UDATA_OVR);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate a global var in existing or new section of given name.
|
|
||||||
const MCSection *
|
|
||||||
PIC16TargetObjectFile::allocateInGivenSection(const GlobalVariable *GV) const {
|
|
||||||
// Determine the type of section that we need to create.
|
|
||||||
PIC16SectionType SecTy;
|
|
||||||
|
|
||||||
// See if this is an uninitialized global.
|
|
||||||
const Constant *C = GV->getInitializer();
|
|
||||||
if (C->isNullValue())
|
|
||||||
SecTy = UDATA;
|
|
||||||
// If this is initialized data in RAM. Put it in the correct IDATA section.
|
|
||||||
else if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
|
|
||||||
SecTy = IDATA;
|
|
||||||
// This is initialized data in rom, put it in the readonly section.
|
|
||||||
else if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
|
|
||||||
SecTy = ROMDATA;
|
|
||||||
else
|
|
||||||
llvm_unreachable ("Could not determine section type for global");
|
|
||||||
|
|
||||||
PIC16Section *S = getPIC16UserSection(GV->getSection().c_str(), SecTy);
|
|
||||||
S->Items.push_back(GV);
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate a global var in a new absolute sections at given address.
|
|
||||||
const MCSection *
|
|
||||||
PIC16TargetObjectFile::allocateAtGivenAddress(const GlobalVariable *GV,
|
|
||||||
const std::string &Addr) const {
|
|
||||||
// Determine the type of section that we need to create.
|
|
||||||
PIC16SectionType SecTy;
|
|
||||||
|
|
||||||
// See if this is an uninitialized global.
|
|
||||||
const Constant *C = GV->getInitializer();
|
|
||||||
if (C->isNullValue())
|
|
||||||
SecTy = UDATA;
|
|
||||||
// If this is initialized data in RAM. Put it in the correct IDATA section.
|
|
||||||
else if (GV->getType()->getAddressSpace() == PIC16ISD::RAM_SPACE)
|
|
||||||
SecTy = IDATA;
|
|
||||||
// This is initialized data in rom, put it in the readonly section.
|
|
||||||
else if (GV->getType()->getAddressSpace() == PIC16ISD::ROM_SPACE)
|
|
||||||
SecTy = ROMDATA;
|
|
||||||
else
|
|
||||||
llvm_unreachable ("Could not determine section type for global");
|
|
||||||
|
|
||||||
std::string Prefix = GV->getNameStr() + "." + Addr + ".";
|
|
||||||
std::string SName = PAN::getUserSectionName(Prefix);
|
|
||||||
PIC16Section *S = getPIC16UserSection(SName.c_str(), SecTy, Addr.c_str());
|
|
||||||
S->Items.push_back(GV);
|
|
||||||
return S;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -1,168 +0,0 @@
|
||||||
//===-- PIC16TargetObjectFile.h - PIC16 Object Info -------------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#ifndef LLVM_TARGET_PIC16_TARGETOBJECTFILE_H
|
|
||||||
#define LLVM_TARGET_PIC16_TARGETOBJECTFILE_H
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "PIC16ABINames.h"
|
|
||||||
#include "llvm/Target/TargetLoweringObjectFile.h"
|
|
||||||
#include "llvm/ADT/StringMap.h"
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace llvm {
|
|
||||||
class GlobalVariable;
|
|
||||||
class Module;
|
|
||||||
class PIC16TargetMachine;
|
|
||||||
class PIC16Section;
|
|
||||||
|
|
||||||
enum { DataBankSize = 80 };
|
|
||||||
|
|
||||||
/// PIC16 Splits the global data into mulitple udata and idata sections.
|
|
||||||
/// Each udata and idata section needs to contain a list of globals that
|
|
||||||
/// they contain, in order to avoid scanning over all the global values
|
|
||||||
/// again and printing only those that match the current section.
|
|
||||||
/// Keeping values inside the sections make printing a section much easier.
|
|
||||||
///
|
|
||||||
/// FIXME: MOVE ALL THIS STUFF TO PIC16Section.
|
|
||||||
///
|
|
||||||
|
|
||||||
/// PIC16TargetObjectFile - PIC16 Object file. Contains data and code
|
|
||||||
/// sections.
|
|
||||||
// PIC16 Object File has two types of sections.
|
|
||||||
// 1. Standard Sections
|
|
||||||
// 1.1 un-initialized global data
|
|
||||||
// 1.2 initialized global data
|
|
||||||
// 1.3 program memory data
|
|
||||||
// 1.4 local variables of functions.
|
|
||||||
// 2. User defined sections
|
|
||||||
// 2.1 Objects placed in a specific section. (By _Section() macro)
|
|
||||||
// 2.2 Objects placed at a specific address. (By _Address() macro)
|
|
||||||
class PIC16TargetObjectFile : public TargetLoweringObjectFile {
|
|
||||||
/// SectionsByName - Bindings of names to allocated sections.
|
|
||||||
mutable StringMap<PIC16Section*> SectionsByName;
|
|
||||||
|
|
||||||
const TargetMachine *TM;
|
|
||||||
|
|
||||||
/// Lists of sections.
|
|
||||||
/// Standard Data Sections.
|
|
||||||
mutable std::vector<PIC16Section *> UDATASections_;
|
|
||||||
mutable std::vector<PIC16Section *> IDATASections_;
|
|
||||||
mutable PIC16Section * ROMDATASection_;
|
|
||||||
mutable PIC16Section * SHAREDUDATASection_;
|
|
||||||
|
|
||||||
/// Standard Auto Sections.
|
|
||||||
mutable std::vector<PIC16Section *> AUTOSections_;
|
|
||||||
|
|
||||||
/// User specified sections.
|
|
||||||
mutable std::vector<PIC16Section *> USERSections_;
|
|
||||||
|
|
||||||
|
|
||||||
/// Find or Create a PIC16 Section, without adding it to any
|
|
||||||
/// section list.
|
|
||||||
PIC16Section *getPIC16Section(const std::string &Name,
|
|
||||||
PIC16SectionType Ty,
|
|
||||||
const std::string &Address = "",
|
|
||||||
int Color = -1) const;
|
|
||||||
|
|
||||||
/// Convenience functions. These wrappers also take care of adding
|
|
||||||
/// the newly created section to the appropriate sections list.
|
|
||||||
|
|
||||||
/// Find or Create PIC16 Standard Data Section.
|
|
||||||
PIC16Section *getPIC16DataSection(const std::string &Name,
|
|
||||||
PIC16SectionType Ty,
|
|
||||||
const std::string &Address = "",
|
|
||||||
int Color = -1) const;
|
|
||||||
|
|
||||||
/// Find or Create PIC16 Standard Auto Section.
|
|
||||||
PIC16Section *getPIC16AutoSection(const std::string &Name,
|
|
||||||
PIC16SectionType Ty = UDATA_OVR,
|
|
||||||
const std::string &Address = "",
|
|
||||||
int Color = -1) const;
|
|
||||||
|
|
||||||
/// Find or Create PIC16 Standard Auto Section.
|
|
||||||
PIC16Section *getPIC16UserSection(const std::string &Name,
|
|
||||||
PIC16SectionType Ty,
|
|
||||||
const std::string &Address = "",
|
|
||||||
int Color = -1) const;
|
|
||||||
|
|
||||||
/// Allocate Un-initialized data to a standard UDATA section.
|
|
||||||
const MCSection *allocateUDATA(const GlobalVariable *GV) const;
|
|
||||||
|
|
||||||
/// Allocate Initialized data to a standard IDATA section.
|
|
||||||
const MCSection *allocateIDATA(const GlobalVariable *GV) const;
|
|
||||||
|
|
||||||
/// Allocate ROM data to the standard ROMDATA section.
|
|
||||||
const MCSection *allocateROMDATA(const GlobalVariable *GV) const;
|
|
||||||
|
|
||||||
/// Allocate an AUTO variable to an AUTO section.
|
|
||||||
const MCSection *allocateAUTO(const GlobalVariable *GV) const;
|
|
||||||
|
|
||||||
/// Allocate DATA in user specified section.
|
|
||||||
const MCSection *allocateInGivenSection(const GlobalVariable *GV) const;
|
|
||||||
|
|
||||||
/// Allocate DATA at user specified address.
|
|
||||||
const MCSection *allocateAtGivenAddress(const GlobalVariable *GV,
|
|
||||||
const std::string &Addr) const;
|
|
||||||
|
|
||||||
/// Allocate a shared variable to SHARED section.
|
|
||||||
const MCSection *allocateSHARED(const GlobalVariable *GV,
|
|
||||||
Mangler *Mang) const;
|
|
||||||
|
|
||||||
public:
|
|
||||||
PIC16TargetObjectFile();
|
|
||||||
~PIC16TargetObjectFile();
|
|
||||||
void Initialize(MCContext &Ctx, const TargetMachine &TM);
|
|
||||||
|
|
||||||
/// Return the section with the given Name. Null if not found.
|
|
||||||
PIC16Section *findPIC16Section(const std::string &Name) const;
|
|
||||||
|
|
||||||
/// Override section allocations for user specified sections.
|
|
||||||
virtual const MCSection *
|
|
||||||
getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind,
|
|
||||||
Mangler *Mang, const TargetMachine &TM) const;
|
|
||||||
|
|
||||||
/// Select sections for Data and Auto variables(globals).
|
|
||||||
virtual const MCSection *SelectSectionForGlobal(const GlobalValue *GV,
|
|
||||||
SectionKind Kind,
|
|
||||||
Mangler *Mang,
|
|
||||||
const TargetMachine&) const;
|
|
||||||
|
|
||||||
|
|
||||||
/// Return a code section for a function.
|
|
||||||
const PIC16Section *SectionForCode (const std::string &FnName,
|
|
||||||
bool isISR) const;
|
|
||||||
|
|
||||||
/// Return a frame section for a function.
|
|
||||||
const PIC16Section *SectionForFrame (const std::string &FnName) const;
|
|
||||||
|
|
||||||
/// Accessors for various section lists.
|
|
||||||
const std::vector<PIC16Section *> &UDATASections() const {
|
|
||||||
return UDATASections_;
|
|
||||||
}
|
|
||||||
const std::vector<PIC16Section *> &IDATASections() const {
|
|
||||||
return IDATASections_;
|
|
||||||
}
|
|
||||||
const PIC16Section *ROMDATASection() const {
|
|
||||||
return ROMDATASection_;
|
|
||||||
}
|
|
||||||
const PIC16Section *SHAREDUDATASection() const {
|
|
||||||
return SHAREDUDATASection_;
|
|
||||||
}
|
|
||||||
const std::vector<PIC16Section *> &AUTOSections() const {
|
|
||||||
return AUTOSections_;
|
|
||||||
}
|
|
||||||
const std::vector<PIC16Section *> &USERSections() const {
|
|
||||||
return USERSections_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} // end namespace llvm
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,7 +0,0 @@
|
||||||
include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. )
|
|
||||||
|
|
||||||
add_llvm_library(LLVMPIC16Info
|
|
||||||
PIC16TargetInfo.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
add_dependencies(LLVMPIC16Info PIC16CodeGenTable_gen)
|
|
|
@ -1,15 +0,0 @@
|
||||||
##===- 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
|
|
|
@ -1,22 +0,0 @@
|
||||||
//===-- PIC16TargetInfo.cpp - PIC16 Target Implementation -----------------===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open Source
|
|
||||||
// License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "PIC16.h"
|
|
||||||
#include "llvm/Module.h"
|
|
||||||
#include "llvm/Target/TargetRegistry.h"
|
|
||||||
using namespace llvm;
|
|
||||||
|
|
||||||
Target llvm::ThePIC16Target, llvm::TheCooperTarget;
|
|
||||||
|
|
||||||
extern "C" void LLVMInitializePIC16TargetInfo() {
|
|
||||||
RegisterTarget<Triple::pic16> X(ThePIC16Target, "pic16",
|
|
||||||
"PIC16 14-bit [experimental]");
|
|
||||||
|
|
||||||
RegisterTarget<> Y(TheCooperTarget, "cooper", "PIC16 Cooper [experimental]");
|
|
||||||
}
|
|
|
@ -1,32 +0,0 @@
|
||||||
; RUN: llc < %s -march=pic16 | FileCheck %s
|
|
||||||
; XFAIL: vg_leak
|
|
||||||
|
|
||||||
target datalayout = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-f32:32:32"
|
|
||||||
target triple = "pic16-"
|
|
||||||
@i = global i32 -10, align 1 ; <i32*> [#uses=1]
|
|
||||||
@j = global i32 -20, align 1 ; <i32*> [#uses=1]
|
|
||||||
@pc = global i8* inttoptr (i64 160 to i8*), align 1 ; <i8**> [#uses=3]
|
|
||||||
@main.auto.k = internal global i32 0 ; <i32*> [#uses=2]
|
|
||||||
|
|
||||||
define void @main() nounwind {
|
|
||||||
entry:
|
|
||||||
%tmp = load i32* @i ; <i32> [#uses=1]
|
|
||||||
%tmp1 = load i32* @j ; <i32> [#uses=1]
|
|
||||||
%add = add i32 %tmp, %tmp1 ; <i32> [#uses=1]
|
|
||||||
store i32 %add, i32* @main.auto.k
|
|
||||||
%tmp2 = load i32* @main.auto.k ; <i32> [#uses=1]
|
|
||||||
%add3 = add i32 %tmp2, 32 ; <i32> [#uses=1]
|
|
||||||
%conv = trunc i32 %add3 to i8 ; <i8> [#uses=1]
|
|
||||||
%tmp4 = load i8** @pc ; <i8*> [#uses=1]
|
|
||||||
store i8 %conv, i8* %tmp4
|
|
||||||
%tmp5 = load i8** @pc ; <i8*> [#uses=1]
|
|
||||||
%tmp6 = load i8* %tmp5 ; <i8> [#uses=1]
|
|
||||||
%conv7 = sext i8 %tmp6 to i16 ; <i16> [#uses=1]
|
|
||||||
%sub = sub i16 %conv7, 1 ; <i16> [#uses=1]
|
|
||||||
%conv8 = trunc i16 %sub to i8 ; <i8> [#uses=1]
|
|
||||||
%tmp9 = load i8** @pc ; <i8*> [#uses=1]
|
|
||||||
store i8 %conv8, i8* %tmp9
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
; CHECK: movf @i + 0, W
|
|
|
@ -1,36 +0,0 @@
|
||||||
; RUN: llc -march=pic16 < %s
|
|
||||||
; PR5558
|
|
||||||
|
|
||||||
define i64 @_strtoll_r(i16 %base) nounwind {
|
|
||||||
entry:
|
|
||||||
br i1 undef, label %if.then, label %if.end27
|
|
||||||
|
|
||||||
if.then: ; preds = %do.end
|
|
||||||
br label %if.end27
|
|
||||||
|
|
||||||
if.end27: ; preds = %if.then, %do.end
|
|
||||||
%cond66 = select i1 undef, i64 -9223372036854775808, i64 9223372036854775807 ; <i64> [#uses=3]
|
|
||||||
%conv69 = sext i16 %base to i64 ; <i64> [#uses=1]
|
|
||||||
%div = udiv i64 %cond66, %conv69 ; <i64> [#uses=1]
|
|
||||||
br label %for.cond
|
|
||||||
|
|
||||||
for.cond: ; preds = %if.end116, %if.end27
|
|
||||||
br i1 undef, label %if.then152, label %if.then93
|
|
||||||
|
|
||||||
if.then93: ; preds = %for.cond
|
|
||||||
br i1 undef, label %if.end116, label %if.then152
|
|
||||||
|
|
||||||
if.end116: ; preds = %if.then93
|
|
||||||
%cmp123 = icmp ugt i64 undef, %div ; <i1> [#uses=1]
|
|
||||||
%or.cond = or i1 undef, %cmp123 ; <i1> [#uses=0]
|
|
||||||
br label %for.cond
|
|
||||||
|
|
||||||
if.then152: ; preds = %if.then93, %for.cond
|
|
||||||
br i1 undef, label %if.end182, label %if.then172
|
|
||||||
|
|
||||||
if.then172: ; preds = %if.then152
|
|
||||||
ret i64 %cond66
|
|
||||||
|
|
||||||
if.end182: ; preds = %if.then152
|
|
||||||
ret i64 %cond66
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
; RUN: llc < %s -march=pic16
|
|
||||||
; XFAIL: *
|
|
||||||
; This fails because PIC16 doesn't define a (xor reg, reg) pattern.
|
|
||||||
;
|
|
||||||
|
|
||||||
@c612.auto.a.b = internal global i1 false ; <i1*> [#uses=2]
|
|
||||||
@c612.auto.A.b = internal global i1 false ; <i1*> [#uses=2]
|
|
||||||
|
|
||||||
define void @c612() nounwind {
|
|
||||||
entry:
|
|
||||||
%tmp3.b = load i1* @c612.auto.a.b ; <i1> [#uses=1]
|
|
||||||
%tmp3 = zext i1 %tmp3.b to i16 ; <i16> [#uses=1]
|
|
||||||
%tmp4.b = load i1* @c612.auto.A.b ; <i1> [#uses=1]
|
|
||||||
%tmp4 = select i1 %tmp4.b, i16 2, i16 0 ; <i16> [#uses=1]
|
|
||||||
%cmp5 = icmp ne i16 %tmp3, %tmp4 ; <i1> [#uses=1]
|
|
||||||
%conv7 = zext i1 %cmp5 to i8 ; <i8> [#uses=1]
|
|
||||||
tail call void @expectWrap(i8 %conv7, i8 2)
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @expectWrap(i8 %boolresult, i8 %errCode) nounwind {
|
|
||||||
entry:
|
|
||||||
%tobool = icmp eq i8 %boolresult, 0 ; <i1> [#uses=1]
|
|
||||||
br i1 %tobool, label %if.then, label %if.end
|
|
||||||
|
|
||||||
if.then: ; preds = %entry
|
|
||||||
tail call void @exit(i16 1)
|
|
||||||
unreachable
|
|
||||||
|
|
||||||
if.end: ; preds = %entry
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define i16 @main() nounwind {
|
|
||||||
entry:
|
|
||||||
tail call void @c612()
|
|
||||||
ret i16 0
|
|
||||||
}
|
|
||||||
|
|
||||||
declare void @exit(i16) noreturn nounwind
|
|
|
@ -1,45 +0,0 @@
|
||||||
; RUN: llc < %s -march=pic16 | grep "extern" | grep "@.lib.unordered.f32" | count 3
|
|
||||||
; XFAIL: vg_leak
|
|
||||||
|
|
||||||
@pc = global i8* inttoptr (i64 160 to i8*), align 1 ; <i8**> [#uses=2]
|
|
||||||
@aa = common global i16 0, align 1 ; <i16*> [#uses=0]
|
|
||||||
@c6214.auto.d = internal global float 0.000000e+00, align 4 ; <float*> [#uses=1]
|
|
||||||
@c6214.auto.l = internal global float 0.000000e+00, align 4 ; <float*> [#uses=1]
|
|
||||||
|
|
||||||
define float @dvalue(float %f) nounwind {
|
|
||||||
entry:
|
|
||||||
ret float %f
|
|
||||||
}
|
|
||||||
|
|
||||||
define void @_assert(i16 %line, i16 %result) nounwind {
|
|
||||||
entry:
|
|
||||||
%add = add i16 %line, %result ; <i16> [#uses=1]
|
|
||||||
%conv = trunc i16 %add to i8 ; <i8> [#uses=1]
|
|
||||||
%tmp2 = load i8** @pc ; <i8*> [#uses=1]
|
|
||||||
store i8 %conv, i8* %tmp2
|
|
||||||
ret void
|
|
||||||
}
|
|
||||||
|
|
||||||
define i16 @main() nounwind {
|
|
||||||
entry:
|
|
||||||
%retval = alloca i16, align 1 ; <i16*> [#uses=2]
|
|
||||||
store i16 0, i16* %retval
|
|
||||||
call void @c6214()
|
|
||||||
%0 = load i16* %retval ; <i16> [#uses=1]
|
|
||||||
ret i16 %0
|
|
||||||
}
|
|
||||||
|
|
||||||
define internal void @c6214() nounwind {
|
|
||||||
entry:
|
|
||||||
%call = call float @dvalue(float 0x3FF3C0CA40000000) ; <float> [#uses=3]
|
|
||||||
store float %call, float* @c6214.auto.d
|
|
||||||
store float %call, float* @c6214.auto.l
|
|
||||||
%cmp = fcmp ord float %call, 0.000000e+00 ; <i1> [#uses=1]
|
|
||||||
%conv = zext i1 %cmp to i16 ; <i16> [#uses=1]
|
|
||||||
call void @_assert(i16 10, i16 %conv)
|
|
||||||
%tmp3 = load i8** @pc ; <i8*> [#uses=2]
|
|
||||||
%tmp4 = load i8* %tmp3 ; <i8> [#uses=1]
|
|
||||||
%sub = add i8 %tmp4, -10 ; <i8> [#uses=1]
|
|
||||||
store i8 %sub, i8* %tmp3
|
|
||||||
ret void
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
;RUN: llvm-as < %s | llc -march=pic16
|
|
||||||
|
|
||||||
@aa = global i16 55, align 1 ; <i16*> [#uses=1]
|
|
||||||
@bb = global i16 44, align 1 ; <i16*> [#uses=1]
|
|
||||||
@PORTD = external global i8 ; <i8*> [#uses=1]
|
|
||||||
|
|
||||||
define void @foo() nounwind {
|
|
||||||
entry:
|
|
||||||
%tmp = volatile load i16* @aa ; <i16> [#uses=1]
|
|
||||||
%tmp1 = volatile load i16* @bb ; <i16> [#uses=1]
|
|
||||||
%sub = sub i16 %tmp, %tmp1 ; <i16> [#uses=1]
|
|
||||||
%conv = trunc i16 %sub to i8 ; <i8> [#uses=1]
|
|
||||||
store i8 %conv, i8* @PORTD
|
|
||||||
ret void
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
; RUN: llvm-as < %s | llc -march=pic16 | FileCheck %s
|
|
||||||
|
|
||||||
;CHECK: #include p16f1xxx.inc
|
|
||||||
;CHECK: #include stdmacros.inc
|
|
||||||
|
|
||||||
define void @foo() nounwind {
|
|
||||||
entry:
|
|
||||||
ret void
|
|
||||||
}
|
|
|
@ -1,5 +0,0 @@
|
||||||
load_lib llvm.exp
|
|
||||||
|
|
||||||
if { [llvm_supports_target PIC16] } {
|
|
||||||
RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{ll,c,cpp}]]
|
|
||||||
}
|
|
|
@ -1,6 +0,0 @@
|
||||||
; RUN: llc < %s -march=pic16 | FileCheck %s
|
|
||||||
; XFAIL: vg_leak
|
|
||||||
|
|
||||||
@G1 = common global i16 0, section "usersection", align 1
|
|
||||||
; CHECK: usersection UDATA
|
|
||||||
; CHECK: @G1 RES 2
|
|
|
@ -1,18 +0,0 @@
|
||||||
; RUN: llc < %s -march=pic16 | FileCheck %s
|
|
||||||
; XFAIL: vg_leak
|
|
||||||
|
|
||||||
@G1 = global i32 4712, section "Address=412"
|
|
||||||
; CHECK: @G1.412..user_section.# IDATA 412
|
|
||||||
; CHECK: @G1
|
|
||||||
; CHECK: dl 4712
|
|
||||||
|
|
||||||
@G2 = global i32 0, section "Address=412"
|
|
||||||
; CHECK: @G2.412..user_section.# UDATA 412
|
|
||||||
; CHECK: @G2 RES 4
|
|
||||||
|
|
||||||
@G3 = addrspace(1) constant i32 4712, section "Address=412"
|
|
||||||
; CHECK: @G3.412..user_section.# ROMDATA 412
|
|
||||||
; CHECK: @G3
|
|
||||||
; CHECK: rom_dl 4712
|
|
||||||
|
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
; RUN: llvm-as < %s | llc -march=pic16 | FileCheck %s
|
|
||||||
|
|
||||||
@a = common global i16 0, align 1 ; <i16*> [#uses=2]
|
|
||||||
|
|
||||||
define void @foo() nounwind {
|
|
||||||
entry:
|
|
||||||
%tmp = load i16* @a ; <i16> [#uses=1]
|
|
||||||
%add = add nsw i16 %tmp, 1 ; <i16> [#uses=1]
|
|
||||||
store i16 %add, i16* @a
|
|
||||||
;CHECK: movlw 1
|
|
||||||
;CHECK: addwf @a + 0, F
|
|
||||||
ret void
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
; RUN: llc < %s -march=pic16
|
|
||||||
; XFAIL: vg_leak
|
|
||||||
|
|
||||||
@main.auto.c = internal global i8 0 ; <i8*> [#uses=1]
|
|
||||||
|
|
||||||
define i16 @main() nounwind {
|
|
||||||
entry:
|
|
||||||
%tmp = load i8* @main.auto.c ; <i8> [#uses=1]
|
|
||||||
%conv = sext i8 %tmp to i16 ; <i16> [#uses=1]
|
|
||||||
ret i16 %conv
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
; RUN: llvm-as < %s | llc -march=pic16 | FileCheck %s
|
|
||||||
|
|
||||||
@pi = common global i16* null, align 1 ; <i16**> [#uses=1]
|
|
||||||
|
|
||||||
define void @foo() nounwind {
|
|
||||||
entry:
|
|
||||||
%tmp = load i16** @pi ; <i16*> [#uses=1]
|
|
||||||
store i16 1, i16* %tmp
|
|
||||||
; CHECK: movwi {{[0-1]}}[INDF{{[0-1]}}]
|
|
||||||
; CHECK: movwi {{[0-1]}}[INDF{{[0-1]}}]
|
|
||||||
ret void
|
|
||||||
}
|
|
|
@ -9,6 +9,6 @@
|
||||||
|
|
||||||
LEVEL=../../..
|
LEVEL=../../..
|
||||||
|
|
||||||
PARALLEL_DIRS := Hello Simple mcc16 Skeleton
|
PARALLEL_DIRS := Hello Simple Skeleton
|
||||||
|
|
||||||
include $(LEVEL)/Makefile.common
|
include $(LEVEL)/Makefile.common
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
#include "llvm/System/Path.h"
|
|
||||||
#include "llvm/Support/CommandLine.h"
|
|
||||||
#include "llvm/Support/raw_ostream.h"
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace llvmc {
|
|
||||||
extern char *ProgramName;
|
|
||||||
|
|
||||||
namespace autogenerated {
|
|
||||||
extern llvm::cl::opt<std::string> Parameter_p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
using namespace llvm;
|
|
||||||
using namespace llvmc;
|
|
||||||
|
|
||||||
// Returns the platform specific directory separator via #ifdefs.
|
|
||||||
// FIXME: This currently work on linux and windows only. It does not
|
|
||||||
// work on other unices.
|
|
||||||
static std::string GetDirSeparator() {
|
|
||||||
#if __linux__ || __APPLE__
|
|
||||||
return "/";
|
|
||||||
#else
|
|
||||||
return "\\";
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace hooks {
|
|
||||||
// Get preprocessor define for the part.
|
|
||||||
// It is __partname format in lower case.
|
|
||||||
std::string
|
|
||||||
GetLowerCasePartDefine(void) {
|
|
||||||
std::string Partname;
|
|
||||||
if (autogenerated::Parameter_p.empty()) {
|
|
||||||
Partname = "16f1xxx";
|
|
||||||
} else {
|
|
||||||
Partname = autogenerated::Parameter_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LowerCase;
|
|
||||||
for (unsigned i = 0; i < Partname.size(); i++) {
|
|
||||||
LowerCase.push_back(std::tolower(Partname[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return "__" + LowerCase;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
GetUpperCasePartDefine(void) {
|
|
||||||
std::string Partname;
|
|
||||||
if (autogenerated::Parameter_p.empty()) {
|
|
||||||
Partname = "16f1xxx";
|
|
||||||
} else {
|
|
||||||
Partname = autogenerated::Parameter_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string UpperCase;
|
|
||||||
for (unsigned i = 0; i < Partname.size(); i++) {
|
|
||||||
UpperCase.push_back(std::toupper(Partname[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return "__" + UpperCase;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the dir where c16 executables reside.
|
|
||||||
std::string GetBinDir() {
|
|
||||||
// Construct a Path object from the program name.
|
|
||||||
void *P = (void*) (intptr_t) GetBinDir;
|
|
||||||
sys::Path ProgramFullPath
|
|
||||||
= sys::Path::GetMainExecutable(llvmc::ProgramName, P);
|
|
||||||
|
|
||||||
// Get the dir name for the program. It's last component should be 'bin'.
|
|
||||||
std::string BinDir = ProgramFullPath.getDirname();
|
|
||||||
|
|
||||||
// llvm::errs() << "BinDir: " << BinDir << '\n';
|
|
||||||
return BinDir + GetDirSeparator();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the Top-level Installation dir for c16.
|
|
||||||
std::string GetInstallDir() {
|
|
||||||
sys::Path BinDirPath = sys::Path(GetBinDir());
|
|
||||||
|
|
||||||
// Go one more level up to get the install dir.
|
|
||||||
std::string InstallDir = BinDirPath.getDirname();
|
|
||||||
|
|
||||||
return InstallDir + GetDirSeparator();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the dir where the c16 header files reside.
|
|
||||||
std::string GetStdHeadersDir() {
|
|
||||||
return GetInstallDir() + "include";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the dir where the assembler header files reside.
|
|
||||||
std::string GetStdAsmHeadersDir() {
|
|
||||||
return GetInstallDir() + "inc";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the dir where the linker scripts reside.
|
|
||||||
std::string GetStdLinkerScriptsDir() {
|
|
||||||
return GetInstallDir() + "lkr";
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the dir where startup code, intrinsics and lib reside.
|
|
||||||
std::string GetStdLibsDir() {
|
|
||||||
return GetInstallDir() + "lib";
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,57 +0,0 @@
|
||||||
//===--- Main.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===//
|
|
||||||
//
|
|
||||||
// The LLVM Compiler Infrastructure
|
|
||||||
//
|
|
||||||
// This file is distributed under the University of Illinois Open
|
|
||||||
// Source License. See LICENSE.TXT for details.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
//
|
|
||||||
// Usually this file just includes CompilerDriver/Main.inc, but here we apply
|
|
||||||
// some trickery to make the built-in '-save-temps' option hidden and enable
|
|
||||||
// '--temp-dir' by default.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
#include "llvm/CompilerDriver/BuiltinOptions.h"
|
|
||||||
#include "llvm/CompilerDriver/Main.h"
|
|
||||||
|
|
||||||
#include "llvm/System/Path.h"
|
|
||||||
#include "llvm/Config/config.h"
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "PIC16.inc"
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
// Modify the PACKAGE_VERSION to use build number in top level configure file.
|
|
||||||
void PIC16VersionPrinter(void) {
|
|
||||||
std::cout << "MPLAB C16 1.0 " << PACKAGE_VERSION << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
|
|
||||||
// HACK
|
|
||||||
SaveTemps.setHiddenFlag(llvm::cl::Hidden);
|
|
||||||
TempDirname.setHiddenFlag(llvm::cl::Hidden);
|
|
||||||
Languages.setHiddenFlag(llvm::cl::Hidden);
|
|
||||||
DryRun.setHiddenFlag(llvm::cl::Hidden);
|
|
||||||
|
|
||||||
llvm::cl::SetVersionPrinter(PIC16VersionPrinter);
|
|
||||||
|
|
||||||
// Ask for a standard temp dir, but just cache its basename., and delete it.
|
|
||||||
llvm::sys::Path tempDir;
|
|
||||||
tempDir = llvm::sys::Path::GetTemporaryDirectory();
|
|
||||||
TempDirname = tempDir.getBasename();
|
|
||||||
tempDir.eraseFromDisk(true);
|
|
||||||
|
|
||||||
// We are creating a temp dir in current dir, with the cached name.
|
|
||||||
// But before that remove if one already exists with that name..
|
|
||||||
tempDir = TempDirname;
|
|
||||||
tempDir.eraseFromDisk(true);
|
|
||||||
|
|
||||||
return llvmc::Main(argc, argv);
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
##===- llvmc/examples/mcc16/Makefile -----------------------*- Makefile -*-===##
|
|
||||||
#
|
|
||||||
# The LLVM Compiler Infrastructure
|
|
||||||
#
|
|
||||||
# This file is distributed under the University of Illinois Open Source
|
|
||||||
# License. See LICENSE.TXT for details.
|
|
||||||
#
|
|
||||||
##===----------------------------------------------------------------------===##
|
|
||||||
|
|
||||||
LEVEL = ../../../..
|
|
||||||
|
|
||||||
LLVMC_BASED_DRIVER = mcc16
|
|
||||||
BUILT_SOURCES = PIC16.inc
|
|
||||||
|
|
||||||
include $(LEVEL)/Makefile.common
|
|
|
@ -1,234 +0,0 @@
|
||||||
//===- PIC16.td - PIC16 toolchain driver -------------------*- tablegen -*-===//
|
|
||||||
//
|
|
||||||
// A basic driver for the PIC16 toolchain.
|
|
||||||
//
|
|
||||||
//===----------------------------------------------------------------------===//
|
|
||||||
|
|
||||||
include "llvm/CompilerDriver/Common.td"
|
|
||||||
|
|
||||||
// Options
|
|
||||||
|
|
||||||
def OptionList : OptionList<[
|
|
||||||
(switch_option "g",
|
|
||||||
(help "Enable Debugging")),
|
|
||||||
(switch_option "E",
|
|
||||||
(help "Stop after preprocessing, do not compile")),
|
|
||||||
(switch_option "S",
|
|
||||||
(help "Stop after compilation, do not assemble")),
|
|
||||||
(switch_option "bc",
|
|
||||||
(help "Stop after b-code generation, do not compile")),
|
|
||||||
(switch_option "c",
|
|
||||||
(help "Stop after assemble, do not link")),
|
|
||||||
(prefix_option "p",
|
|
||||||
(help "Specify part name")),
|
|
||||||
(prefix_list_option "I",
|
|
||||||
(help "Add a directory to include path")),
|
|
||||||
(prefix_list_option "L",
|
|
||||||
(help "Add a directory to library path")),
|
|
||||||
(prefix_list_option "K",
|
|
||||||
(help "Add a directory to linker script search path")),
|
|
||||||
(parameter_option "l",
|
|
||||||
(help "Specify a library to link")),
|
|
||||||
(parameter_option "k",
|
|
||||||
(help "Specify a linker script")),
|
|
||||||
(parameter_option "m",
|
|
||||||
(help "Generate linker map file with the given name")),
|
|
||||||
(prefix_list_option "D",
|
|
||||||
(help "Define a macro")),
|
|
||||||
(switch_option "X",
|
|
||||||
(help "Do not invoke mp2hex to create an output hex file.")),
|
|
||||||
(switch_option "O0",
|
|
||||||
(help "Do not optimize")),
|
|
||||||
(switch_option "O1",
|
|
||||||
(help "Optimization Level 1.")),
|
|
||||||
(switch_option "O2",
|
|
||||||
(help "Optimization Level 2.")),
|
|
||||||
(switch_option "O3",
|
|
||||||
(help "Optimization Level 3.")),
|
|
||||||
(switch_option "Od",
|
|
||||||
(help "Perform Debug-safe Optimizations only.")),
|
|
||||||
(switch_option "w",
|
|
||||||
(help "Disable all warnings.")),
|
|
||||||
// (switch_option "O1",
|
|
||||||
// (help "Optimization level 1")),
|
|
||||||
// (switch_option "O2",
|
|
||||||
// (help "Optimization level 2. (Default)")),
|
|
||||||
// (parameter_option "pre-RA-sched",
|
|
||||||
// (help "Example of an option that is passed to llc")),
|
|
||||||
(parameter_option "regalloc",
|
|
||||||
(help "Register allocator to use (possible values: simple, linearscan, pbqp, local; default=linearscan)")),
|
|
||||||
(prefix_list_option "Wa,", (comma_separated),
|
|
||||||
(help "Pass options to assembler (Run 'gpasm -help' for assembler options)")),
|
|
||||||
(prefix_list_option "Wl,", (comma_separated),
|
|
||||||
(help "Pass options to linker (Run 'mplink -help' for linker options)"))
|
|
||||||
// (prefix_list_option "Wllc,",
|
|
||||||
// (help "Pass options to llc")),
|
|
||||||
// (prefix_list_option "Wo,",
|
|
||||||
// (help "Pass options to llvm-ld"))
|
|
||||||
]>;
|
|
||||||
|
|
||||||
// Tools
|
|
||||||
class clang_based<string language, string cmd, string ext_E> : Tool<
|
|
||||||
[(in_language language),
|
|
||||||
(out_language "llvm-bitcode"),
|
|
||||||
(output_suffix "bc"),
|
|
||||||
(command cmd),
|
|
||||||
(actions (case
|
|
||||||
(and (multiple_input_files),
|
|
||||||
(or (switch_on "S"), (switch_on "c"))),
|
|
||||||
(error "cannot specify -o with -c or -S with multiple files"),
|
|
||||||
(switch_on "E"), [(forward "E"),
|
|
||||||
(stop_compilation), (output_suffix ext_E)],
|
|
||||||
(and (switch_on "E"), (empty "o")), (no_out_file),
|
|
||||||
(switch_on "bc"),[(stop_compilation), (output_suffix "bc")],
|
|
||||||
(switch_on "g"), (append_cmd "-g"),
|
|
||||||
(switch_on "w"), (append_cmd "-w"),
|
|
||||||
(switch_on "O1"), (append_cmd ""),
|
|
||||||
(switch_on "O2"), (append_cmd ""),
|
|
||||||
(switch_on "O3"), (append_cmd ""),
|
|
||||||
(switch_on "Od"), (append_cmd ""),
|
|
||||||
(not_empty "D"), (forward "D"),
|
|
||||||
(not_empty "I"), (forward "I"),
|
|
||||||
(switch_on "O0"), (append_cmd "-O0"),
|
|
||||||
(default), (append_cmd "-O1")))
|
|
||||||
// (sink)
|
|
||||||
]>;
|
|
||||||
|
|
||||||
def clang_cc : clang_based<"c", "$CALL(GetBinDir)clang -cc1 -I $CALL(GetStdHeadersDir) -D $CALL(GetLowerCasePartDefine) -D $CALL(GetUpperCasePartDefine) -triple=pic16- -emit-llvm-bc ", "i">;
|
|
||||||
|
|
||||||
//def clang_cc : Tool<[
|
|
||||||
// (in_language "c"),
|
|
||||||
// (out_language "llvm-bitcode"),
|
|
||||||
// (output_suffix "bc"),
|
|
||||||
// (cmd_line "$CALL(GetBinDir)clang-cc -I $CALL(GetStdHeadersDir) -triple=pic16- -emit-llvm-bc "),
|
|
||||||
// (cmd_line kkkkk
|
|
||||||
// (actions (case
|
|
||||||
// (switch_on "g"), (append_cmd "g"),
|
|
||||||
// (not_empty "I"), (forward "I"))),
|
|
||||||
// (sink)
|
|
||||||
//]>;
|
|
||||||
|
|
||||||
|
|
||||||
// pre-link-and-lto step.
|
|
||||||
def llvm_ld : Tool<[
|
|
||||||
(in_language "llvm-bitcode"),
|
|
||||||
(out_language "llvm-bitcode"),
|
|
||||||
(output_suffix "bc"),
|
|
||||||
(command "$CALL(GetBinDir)llvm-ld -L $CALL(GetStdLibsDir) -disable-licm-promotion -l std"),
|
|
||||||
(out_file_option "-b"),
|
|
||||||
(actions (case
|
|
||||||
(switch_on "O0"), (append_cmd "-disable-opt"),
|
|
||||||
(switch_on "O1"), (append_cmd "-disable-opt"),
|
|
||||||
// Whenever O3 is not specified on the command line, default i.e. disable-inlining will always be added.
|
|
||||||
(switch_on "O2"), (append_cmd ""),
|
|
||||||
(switch_on "O3"), (append_cmd ""),
|
|
||||||
(default), (append_cmd "-disable-inlining"))),
|
|
||||||
(join)
|
|
||||||
]>;
|
|
||||||
|
|
||||||
// optimize single file
|
|
||||||
def llvm_ld_optimizer : Tool<[
|
|
||||||
(in_language "llvm-bitcode"),
|
|
||||||
(out_language "llvm-bitcode"),
|
|
||||||
(output_suffix "bc"),
|
|
||||||
// FIXME: we are still not disabling licm-promotion.
|
|
||||||
// -disable-licm-promotion and building stdn library causes c16-71 to fail.
|
|
||||||
(command "$CALL(GetBinDir)llvm-ld "),
|
|
||||||
(out_file_option "-b"),
|
|
||||||
(actions (case
|
|
||||||
(switch_on "O0"), (append_cmd "-disable-opt"),
|
|
||||||
(switch_on "O1"), (append_cmd "-disable-opt"),
|
|
||||||
// Whenever O3 is not specified on the command line, default i.e. disable-inlining will always be added.
|
|
||||||
(switch_on "O2"), (append_cmd ""),
|
|
||||||
(switch_on "O3"), (append_cmd ""),
|
|
||||||
(default), (append_cmd "-disable-inlining")))
|
|
||||||
]>;
|
|
||||||
|
|
||||||
// optimizer step.
|
|
||||||
def pic16passes : Tool<[
|
|
||||||
(in_language "llvm-bitcode"),
|
|
||||||
(out_language "llvm-bitcode"),
|
|
||||||
(output_suffix "obc"),
|
|
||||||
(command "$CALL(GetBinDir)opt -pic16cloner -pic16overlay -f"),
|
|
||||||
(actions (case
|
|
||||||
(switch_on "O0"), (append_cmd "-disable-opt")))
|
|
||||||
]>;
|
|
||||||
|
|
||||||
def llc : Tool<[
|
|
||||||
(in_language "llvm-bitcode"),
|
|
||||||
(out_language "assembler"),
|
|
||||||
(output_suffix "s"),
|
|
||||||
(command "$CALL(GetBinDir)llc -march=pic16 -disable-jump-tables -pre-RA-sched=list-burr -f"),
|
|
||||||
(actions (case
|
|
||||||
(switch_on "S"), (stop_compilation),
|
|
||||||
// (not_empty "Wllc,"), (unpack_values "Wllc,"),
|
|
||||||
// (not_empty "pre-RA-sched"), (forward "pre-RA-sched")))
|
|
||||||
(not_empty "regalloc"), (forward "regalloc"),
|
|
||||||
(empty "regalloc"), (append_cmd "-regalloc=linearscan")))
|
|
||||||
]>;
|
|
||||||
|
|
||||||
def gpasm : Tool<[
|
|
||||||
(in_language "assembler"),
|
|
||||||
(out_language "object-code"),
|
|
||||||
(output_suffix "o"),
|
|
||||||
(command "$CALL(GetBinDir)gpasm -z -r decimal -I $CALL(GetStdAsmHeadersDir) -C -c -w 2"),
|
|
||||||
(actions (case
|
|
||||||
(switch_on "c"), (stop_compilation),
|
|
||||||
(switch_on "g"), (append_cmd "-g"),
|
|
||||||
(not_empty "p"), (forward "p"),
|
|
||||||
(empty "p"), (append_cmd "-p 16f1xxx"),
|
|
||||||
(not_empty "Wa,"), (forward_value "Wa,")))
|
|
||||||
]>;
|
|
||||||
|
|
||||||
def mplink : Tool<[
|
|
||||||
(in_language "object-code"),
|
|
||||||
(out_language "executable"),
|
|
||||||
(output_suffix "cof"),
|
|
||||||
(command "$CALL(GetBinDir)mplink -e -k $CALL(GetStdLinkerScriptsDir) -l $CALL(GetStdLibsDir) intrinsics.lib stdn.lib"),
|
|
||||||
(actions (case
|
|
||||||
(not_empty "Wl,"), (forward_value "Wl,"),
|
|
||||||
(switch_on "X"), (append_cmd "-x"),
|
|
||||||
(not_empty "L"), (forward_as "L", "-l"),
|
|
||||||
(not_empty "K"), (forward_as "K", "-k"),
|
|
||||||
(not_empty "m"), (forward "m"),
|
|
||||||
(not_empty "p"), [(forward "p"), (append_cmd "-c")],
|
|
||||||
(empty "p"), (append_cmd "-p 16f1xxx -c"),
|
|
||||||
// (not_empty "l"), [(unpack_values "l"),(append_cmd ".lib")])),
|
|
||||||
(not_empty "k"), (forward "k"),
|
|
||||||
(not_empty "l"), (forward "l"))),
|
|
||||||
(join)
|
|
||||||
]>;
|
|
||||||
|
|
||||||
// Language map
|
|
||||||
|
|
||||||
def LanguageMap : LanguageMap<[
|
|
||||||
(lang_to_suffixes "c", "c"),
|
|
||||||
(lang_to_suffixes "c-cpp-output", "i"),
|
|
||||||
(lang_to_suffixes "assembler", "s"),
|
|
||||||
(lang_to_suffixes "assembler-with-cpp", "S"),
|
|
||||||
(lang_to_suffixes "llvm-assembler", "ll"),
|
|
||||||
(lang_to_suffixes "llvm-bitcode", "bc"),
|
|
||||||
(lang_to_suffixes "object-code", "o"),
|
|
||||||
(lang_to_suffixes "executable", "cof")
|
|
||||||
]>;
|
|
||||||
|
|
||||||
// Compilation graph
|
|
||||||
|
|
||||||
def CompilationGraph : CompilationGraph<[
|
|
||||||
(edge "root", "clang_cc"),
|
|
||||||
(edge "root", "llvm_ld"),
|
|
||||||
(optional_edge "root", "llvm_ld_optimizer",
|
|
||||||
(case (switch_on "S"), (inc_weight),
|
|
||||||
(switch_on "c"), (inc_weight))),
|
|
||||||
(edge "root", "gpasm"),
|
|
||||||
(edge "root", "mplink"),
|
|
||||||
(edge "clang_cc", "llvm_ld"),
|
|
||||||
(optional_edge "clang_cc", "llvm_ld_optimizer",
|
|
||||||
(case (switch_on "S"), (inc_weight),
|
|
||||||
(switch_on "c"), (inc_weight))),
|
|
||||||
(edge "llvm_ld", "pic16passes"),
|
|
||||||
(edge "llvm_ld_optimizer", "pic16passes"),
|
|
||||||
(edge "pic16passes", "llc"),
|
|
||||||
(edge "llc", "gpasm"),
|
|
||||||
(edge "gpasm", "mplink")
|
|
||||||
]>;
|
|
|
@ -1,75 +0,0 @@
|
||||||
This is a basic compiler driver for the PIC16 toolchain that shows how to create
|
|
||||||
your own llvmc-based drivers. It is based on the examples/Skeleton template.
|
|
||||||
|
|
||||||
The PIC16 toolchain looks like this:
|
|
||||||
|
|
||||||
clang-cc (FE) -> llvm-ld (optimizer) -> llc (codegen) -> native-as -> native-ld
|
|
||||||
|
|
||||||
Following features were requested by Sanjiv:
|
|
||||||
|
|
||||||
From: Sanjiv Gupta <sanjiv.gupta <at> microchip.com>
|
|
||||||
Subject: Re: llvmc for PIC16
|
|
||||||
Newsgroups: gmane.comp.compilers.llvm.devel
|
|
||||||
Date: 2009-06-05 06:51:14 GMT
|
|
||||||
|
|
||||||
The salient features that we want to have in the driver are:
|
|
||||||
1. llvm-ld will be used as "The Optimizer".
|
|
||||||
2. If the user has specified to generate the final executable, then
|
|
||||||
llvm-ld should run on all the .bc files generated by clang and create a
|
|
||||||
single optimized .bc file for further tools.
|
|
||||||
3. -Wo <options> - pass optimizations to the llvm-ld
|
|
||||||
4. mcc16 -Wl <options> - pass options to native linker.
|
|
||||||
5. mcc16 -Wa <options> - pass options to native assembler.
|
|
||||||
|
|
||||||
Here are some example command lines and sample command invocations as to
|
|
||||||
what should be done.
|
|
||||||
|
|
||||||
$ mcc16 -S foo.c
|
|
||||||
// [clang-cc foo.c] -> foo.bc
|
|
||||||
// [llvm-ld foo.bc] -> foo.opt.bc
|
|
||||||
// [llc foo.opt.bc] -> foo.s
|
|
||||||
|
|
||||||
$ mcc16 -S foo.c bar.c
|
|
||||||
// [clang-cc foo.c] -> foo.bc
|
|
||||||
// [llvm-ld foo.bc] -> foo.opt.bc
|
|
||||||
// [llc foo.opt.bc] -> foo.s
|
|
||||||
// [clang-cc bar.c] -> bar.bc
|
|
||||||
// [llvm-ld bar.bc] -> bar.opt.bc
|
|
||||||
// [llc bar.opt.bc] -> bar.s
|
|
||||||
|
|
||||||
** Use of -g causes llvm-ld to run with -disable-opt
|
|
||||||
$ mcc16 -S -g foo.c
|
|
||||||
// [clang-cc foo.c] -> foo.bc
|
|
||||||
// [llvm-ld -disable-opt foo.bc] -> foo.opt.bc
|
|
||||||
// [llc foo.opt.bc] -> foo.s
|
|
||||||
|
|
||||||
** -I is passed to clang-cc, -pre-RA-sched=list-burr to llc.
|
|
||||||
$ mcc16 -S -g -I ../include -pre-RA-sched=list-burr foo.c
|
|
||||||
// [clang-cc -I ../include foo.c] -> foo.bc
|
|
||||||
// [llvm-ld -disable-opt foo.bc] -> foo.opt.bc
|
|
||||||
// [llc -pre-RA-sched=list-burr foo.opt.bc] -> foo.s
|
|
||||||
|
|
||||||
** -Wo passes options to llvm-ld
|
|
||||||
$ mcc16 -Wo=opt1,opt2 -S -I ../include -pre-RA-sched=list-burr foo.c
|
|
||||||
// [clang-cc -I ../include foo.c] -> foo.bc
|
|
||||||
// [llvm-ld -opt1 -opt2 foo.bc] -> foo.opt.bc
|
|
||||||
// [llc -pre-RA-sched=list-burr foo.opt.bc] -> foo.s
|
|
||||||
|
|
||||||
** -Wa passes options to native as.
|
|
||||||
$ mcc16 -c foo.c -Wa=opt1
|
|
||||||
// [clang-cc foo.c] -> foo.bc
|
|
||||||
// [llvm-ld foo.bc] -> foo.opt.bc
|
|
||||||
// [llc foo.opt.bc] -> foo.s
|
|
||||||
// [native-as -opt1 foo.s] -> foo.o
|
|
||||||
|
|
||||||
$ mcc16 -Wo=opt1 -Wl=opt2 -Wa=opt3 foo.c bar.c
|
|
||||||
// [clang-cc foo.c] -> foo.bc
|
|
||||||
// [clang-cc bar.c] -> bar.bc
|
|
||||||
// [llvm-ld -opt1 foo.bc bar.bc] -> a.out.bc
|
|
||||||
// [llc a.out.bc] -> a.out.s
|
|
||||||
// [native-as -opt3 a.out.s] -> a.out.o
|
|
||||||
// [native-ld -opt2 a.out.o] -> a.out
|
|
||||||
|
|
||||||
Is this achievable by a tablegen based driver ?
|
|
||||||
|
|
||||||
- Sanjiv
|
|
|
@ -107,7 +107,6 @@ if ($PEROBJ) {
|
||||||
$libpath =~ s/^TransformUtils/Transforms\/Utils/;
|
$libpath =~ s/^TransformUtils/Transforms\/Utils/;
|
||||||
$libpath =~ s/^ipa/Analysis\/IPA/;
|
$libpath =~ s/^ipa/Analysis\/IPA/;
|
||||||
$libpath =~ s/^ipo/Transforms\/IPO/;
|
$libpath =~ s/^ipo/Transforms\/IPO/;
|
||||||
$libpath =~ s/^pic16passes/Target\/PIC16\/PIC16Passes/;
|
|
||||||
$libpath = "lib/".$libpath."/";
|
$libpath = "lib/".$libpath."/";
|
||||||
open DEFS, "$nmPath -sg $Directory/$lib|";
|
open DEFS, "$nmPath -sg $Directory/$lib|";
|
||||||
while (<DEFS>) {
|
while (<DEFS>) {
|
||||||
|
@ -150,7 +149,6 @@ if ($PEROBJ) {
|
||||||
$libpath =~ s/^TransformUtils/Transforms\/Utils/;
|
$libpath =~ s/^TransformUtils/Transforms\/Utils/;
|
||||||
$libpath =~ s/^ipa/Analysis\/IPA/;
|
$libpath =~ s/^ipa/Analysis\/IPA/;
|
||||||
$libpath =~ s/^ipo/Transforms\/IPO/;
|
$libpath =~ s/^ipo/Transforms\/IPO/;
|
||||||
$libpath =~ s/^pic16passes/Target\/PIC16\/PIC16Passes/;
|
|
||||||
$libpath = "lib/".$libpath."/";
|
$libpath = "lib/".$libpath."/";
|
||||||
open UDEFS, "$nmPath -Aup $Directory/$lib|";
|
open UDEFS, "$nmPath -Aup $Directory/$lib|";
|
||||||
while (<UDEFS>) {
|
while (<UDEFS>) {
|
||||||
|
|
Loading…
Reference in New Issue