diff options
author | Richard Osborne <richard@xmos.com> | 2008-11-07 10:59:00 +0000 |
---|---|---|
committer | Richard Osborne <richard@xmos.com> | 2008-11-07 10:59:00 +0000 |
commit | b25baef26f03b9909b65dd5f762b38f93000445d (patch) | |
tree | f03bc8e40b55feab99b0f32e4428d215fa45f988 | |
parent | 4df60f5491ff35c8a48c2cf14e18a33c9793b3bb (diff) |
Add XCore backend.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@58838 91177308-0d34-0410-b5e6-96231b3b80d8
27 files changed, 4989 insertions, 26 deletions
diff --git a/autoconf/configure.ac b/autoconf/configure.ac index f2c7714a2a..2054548979 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -225,6 +225,7 @@ AC_CACHE_CHECK([target architecture],[llvm_cv_target_arch], arm-*) llvm_cv_target_arch="ARM" ;; mips-*) llvm_cv_target_arch="Mips" ;; pic16-*) llvm_cv_target_arch="PIC16" ;; + xcore-*) llvm_cv_target_arch="XCore" ;; *) llvm_cv_target_arch="Unknown" ;; esac]) @@ -332,6 +333,7 @@ else ARM) AC_SUBST(TARGET_HAS_JIT,0) ;; Mips) AC_SUBST(TARGET_HAS_JIT,0) ;; PIC16) AC_SUBST(TARGET_HAS_JIT,0) ;; + XCore) AC_SUBST(TARGET_HAS_JIT,0) ;; *) AC_SUBST(TARGET_HAS_JIT,0) ;; esac fi @@ -381,7 +383,7 @@ AC_ARG_ENABLE([targets],AS_HELP_STRING([--enable-targets], [Build specific host targets: all,host-only,{target-name} (default=all)]),, enableval=all) case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha IA64 ARM Mips CellSPU PIC16 CBackend MSIL CppBackend" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha IA64 ARM Mips CellSPU PIC16 XCore CBackend MSIL CppBackend" ;; host-only) case "$llvm_cv_target_arch" in x86) TARGETS_TO_BUILD="X86" ;; @@ -394,6 +396,7 @@ case "$enableval" in Mips) TARGETS_TO_BUILD="Mips" ;; CellSPU|SPU) TARGETS_TO_BUILD="CellSPU" ;; PIC16) TARGETS_TO_BUILD="PIC16" ;; + XCore) TARGETS_TO_BUILD="XCore" ;; *) AC_MSG_ERROR([Can not set target to build]) ;; esac ;; @@ -409,6 +412,7 @@ case "$enableval" in mips) TARGETS_TO_BUILD="Mips $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" ;; cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; msil) TARGETS_TO_BUILD="MSIL $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; @@ -2389,6 +2389,7 @@ else arm-*) llvm_cv_target_arch="ARM" ;; mips-*) llvm_cv_target_arch="Mips" ;; pic16-*) llvm_cv_target_arch="PIC16" ;; + xcore-*) llvm_cv_target_arch="XCore" ;; *) llvm_cv_target_arch="Unknown" ;; esac fi @@ -4811,6 +4812,8 @@ else ;; PIC16) TARGET_HAS_JIT=0 ;; + XCore) TARGET_HAS_JIT=0 + ;; *) TARGET_HAS_JIT=0 ;; esac @@ -4892,7 +4895,7 @@ else fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha IA64 ARM Mips CellSPU PIC16 CBackend MSIL CppBackend" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC Alpha IA64 ARM Mips CellSPU PIC16 XCore CBackend MSIL CppBackend" ;; host-only) case "$llvm_cv_target_arch" in x86) TARGETS_TO_BUILD="X86" ;; @@ -4905,6 +4908,7 @@ case "$enableval" in Mips) TARGETS_TO_BUILD="Mips" ;; CellSPU|SPU) TARGETS_TO_BUILD="CellSPU" ;; PIC16) TARGETS_TO_BUILD="PIC16" ;; + XCore) TARGETS_TO_BUILD="XCore" ;; *) { { echo "$as_me:$LINENO: error: Can not set target to build" >&5 echo "$as_me: error: Can not set target to build" >&2;} { (exit 1); exit 1; }; } ;; @@ -4922,6 +4926,7 @@ echo "$as_me: error: Can not set target to build" >&2;} mips) TARGETS_TO_BUILD="Mips $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" ;; cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; msil) TARGETS_TO_BUILD="MSIL $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; @@ -10827,7 +10832,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 10830 "configure" +#line 10835 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12971,7 +12976,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 12974 "configure"' > conftest.$ac_ext + echo '#line 12979 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -14689,11 +14694,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14692: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14697: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14696: \$? = $ac_status" >&5 + echo "$as_me:14701: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -14957,11 +14962,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:14960: $lt_compile\"" >&5) + (eval echo "\"\$as_me:14965: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:14964: \$? = $ac_status" >&5 + echo "$as_me:14969: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -15061,11 +15066,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:15064: $lt_compile\"" >&5) + (eval echo "\"\$as_me:15069: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:15068: \$? = $ac_status" >&5 + echo "$as_me:15073: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -17513,7 +17518,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 17516 "configure" +#line 17521 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -17613,7 +17618,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 17616 "configure" +#line 17621 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -19981,11 +19986,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:19984: $lt_compile\"" >&5) + (eval echo "\"\$as_me:19989: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:19988: \$? = $ac_status" >&5 + echo "$as_me:19993: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -20085,11 +20090,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:20088: $lt_compile\"" >&5) + (eval echo "\"\$as_me:20093: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:20092: \$? = $ac_status" >&5 + echo "$as_me:20097: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -21655,11 +21660,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:21658: $lt_compile\"" >&5) + (eval echo "\"\$as_me:21663: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:21662: \$? = $ac_status" >&5 + echo "$as_me:21667: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -21759,11 +21764,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:21762: $lt_compile\"" >&5) + (eval echo "\"\$as_me:21767: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:21766: \$? = $ac_status" >&5 + echo "$as_me:21771: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized @@ -23994,11 +23999,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:23997: $lt_compile\"" >&5) + (eval echo "\"\$as_me:24002: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:24001: \$? = $ac_status" >&5 + echo "$as_me:24006: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -24262,11 +24267,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:24265: $lt_compile\"" >&5) + (eval echo "\"\$as_me:24270: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:24269: \$? = $ac_status" >&5 + echo "$as_me:24274: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. @@ -24366,11 +24371,11 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:24369: $lt_compile\"" >&5) + (eval echo "\"\$as_me:24374: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:24373: \$? = $ac_status" >&5 + echo "$as_me:24378: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized diff --git a/lib/Target/XCore/CMakeLists.txt b/lib/Target/XCore/CMakeLists.txt new file mode 100644 index 0000000000..a7aba14a7a --- /dev/null +++ b/lib/Target/XCore/CMakeLists.txt @@ -0,0 +1,23 @@ +set(LLVM_TARGET_DEFINITIONS XCore.td) + +tablegen(XCoreGenRegisterInfo.h.inc -gen-register-desc-header) +tablegen(XCoreGenRegisterNames.inc -gen-register-enums) +tablegen(XCoreGenRegisterInfo.inc -gen-register-desc) +tablegen(XCoreGenInstrNames.inc -gen-instr-enums) +tablegen(XCoreGenInstrInfo.inc -gen-instr-desc) +tablegen(XCoreGenAsmWriter.inc -gen-asm-writer) +tablegen(XCoreGenDAGISel.inc -gen-dag-isel) +tablegen(XCoreGenCallingConv.inc -gen-callingconv) +tablegen(XCoreGenSubtarget.inc -gen-subtarget) + +add_llvm_target(XCore + XCoreAsmPrinter.cpp + XCoreFrameInfo.cpp + XCoreInstrInfo.cpp + XCoreISelDAGToDAG.cpp + XCoreISelLowering.cpp + XCoreRegisterInfo.cpp + XCoreSubtarget.cpp + XCoreTargetAsmInfo.cpp + XCoreTargetMachine.cpp + ) diff --git a/lib/Target/XCore/README.txt b/lib/Target/XCore/README.txt new file mode 100644 index 0000000000..deaeb0f2a9 --- /dev/null +++ b/lib/Target/XCore/README.txt @@ -0,0 +1,8 @@ +To-do +----- + +* Instruction encodings +* Tailcalls +* Investigate loop alignment +* Add builtins +* Make better use of lmul / macc diff --git a/lib/Target/XCore/XCore.h b/lib/Target/XCore/XCore.h new file mode 100644 index 0000000000..347ac47ac3 --- /dev/null +++ b/lib/Target/XCore/XCore.h @@ -0,0 +1,38 @@ +//===-- XCore.h - Top-level interface for XCore 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 +// XCore back-end. +// +//===----------------------------------------------------------------------===// + +#ifndef TARGET_XCORE_H +#define TARGET_XCORE_H + +namespace llvm { + class FunctionPass; + class TargetMachine; + class XCoreTargetMachine; + class raw_ostream; + + FunctionPass *createXCoreISelDag(XCoreTargetMachine &TM); + FunctionPass *createXCoreCodePrinterPass(raw_ostream &OS, + XCoreTargetMachine &TM); +} // end namespace llvm; + +// Defines symbolic names for XCore registers. This defines a mapping from +// register name to register number. +// +#include "XCoreGenRegisterNames.inc" + +// Defines symbolic names for the XCore instructions. +// +#include "XCoreGenInstrNames.inc" + +#endif diff --git a/lib/Target/XCore/XCore.td b/lib/Target/XCore/XCore.td new file mode 100644 index 0000000000..39c4226b61 --- /dev/null +++ b/lib/Target/XCore/XCore.td @@ -0,0 +1,62 @@ +//===- XCore.td - Describe the XCore Target Machine --------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Target-independent interfaces which we are implementing +//===----------------------------------------------------------------------===// + +include "../Target.td" + +//===----------------------------------------------------------------------===// +// Descriptions +//===----------------------------------------------------------------------===// + +include "XCoreRegisterInfo.td" +include "XCoreInstrInfo.td" +include "XCoreCallingConv.td" + +def XCoreInstrInfo : InstrInfo { + let TSFlagsFields = []; + let TSFlagsShifts = []; +} + +//===----------------------------------------------------------------------===// +// XCore Subtarget features. +//===----------------------------------------------------------------------===// + +def FeatureXS1A + : SubtargetFeature<"xs1a", "IsXS1A", "true", + "Enable XS1A instructions">; + +def FeatureXS1B + : SubtargetFeature<"xs1b", "IsXS1B", "true", + "Enable XS1B instructions">; + +//===----------------------------------------------------------------------===// +// XCore processors supported. +//===----------------------------------------------------------------------===// + +class Proc<string Name, list<SubtargetFeature> Features> + : Processor<Name, NoItineraries, Features>; + +def : Proc<"generic", [FeatureXS1A]>; +def : Proc<"xs1a-generic", [FeatureXS1A]>; +def : Proc<"xs1b-generic", [FeatureXS1B]>; + +//===----------------------------------------------------------------------===// +// Declare the target which we are implementing +//===----------------------------------------------------------------------===// + +def XCore : Target { + // Pull in Instruction Info: + let InstructionSet = XCoreInstrInfo; +} diff --git a/lib/Target/XCore/XCoreAsmPrinter.cpp b/lib/Target/XCore/XCoreAsmPrinter.cpp new file mode 100644 index 0000000000..519b38bdfa --- /dev/null +++ b/lib/Target/XCore/XCoreAsmPrinter.cpp @@ -0,0 +1,459 @@ +//===-- XCoreAsmPrinter.cpp - XCore 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 the XAS-format XCore assembly language. +// +//===----------------------------------------------------------------------===// + +#define DEBUG_TYPE "asm-printer" +#include "XCore.h" +#include "XCoreInstrInfo.h" +#include "XCoreSubtarget.h" +#include "XCoreTargetMachine.h" +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/Module.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/DwarfWriter.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/Target/TargetAsmInfo.h" +#include "llvm/Target/TargetData.h" +#include "llvm/Support/Mangler.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/ADT/StringExtras.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/raw_ostream.h" +#include <algorithm> +#include <cctype> +using namespace llvm; + +STATISTIC(EmittedInsts, "Number of machine instrs printed"); + +static cl::opt<std::string> FileDirective("xcore-file-directive", cl::Optional, + cl::desc("Output a file directive into the assembly file"), + cl::Hidden, + cl::value_desc("filename"), + cl::init("")); + +static cl::opt<unsigned> MaxThreads("xcore-max-threads", cl::Optional, + cl::desc("Maximum number of threads (for emulation thread-local storage)"), + cl::Hidden, + cl::value_desc("number"), + cl::init(8)); + +namespace { + struct VISIBILITY_HIDDEN XCoreAsmPrinter : public AsmPrinter { + XCoreAsmPrinter(raw_ostream &O, XCoreTargetMachine &TM, + const TargetAsmInfo *T) + : AsmPrinter(O, TM, T), DW(O, this, T), + Subtarget(*TM.getSubtargetImpl()) { } + + DwarfWriter DW; + const XCoreSubtarget &Subtarget; + + virtual const char *getPassName() const { + return "XCore Assembly Printer"; + } + + void printMemOperand(const MachineInstr *MI, int opNum); + void printOperand(const MachineInstr *MI, int opNum); + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + + void emitFileDirective(const std::string &filename); + void emitGlobalDirective(const std::string &name); + void emitExternDirective(const std::string &name); + + void emitArrayBound(const std::string &name, const GlobalVariable *GV); + void emitGlobal(const GlobalVariable *GV); + + void emitFunctionStart(MachineFunction &MF); + void emitFunctionEnd(MachineFunction &MF); + + bool printInstruction(const MachineInstr *MI); // autogenerated. + void printMachineInstruction(const MachineInstr *MI); + bool runOnMachineFunction(MachineFunction &F); + bool doInitialization(Module &M); + bool doFinalization(Module &M); + + void getAnalysisUsage(AnalysisUsage &AU) const { + AsmPrinter::getAnalysisUsage(AU); + AU.setPreservesAll(); + AU.addRequired<MachineModuleInfo>(); + } + }; +} // end of anonymous namespace + +#include "XCoreGenAsmWriter.inc" + +/// createXCoreCodePrinterPass - Returns a pass that prints the XCore +/// assembly code for a MachineFunction to the given output stream, +/// using the given target machine description. This should work +/// regardless of whether the function is in SSA form. +/// +FunctionPass *llvm::createXCoreCodePrinterPass(raw_ostream &o, + XCoreTargetMachine &tm) { + return new XCoreAsmPrinter(o, tm, tm.getTargetAsmInfo()); +} + +// PrintEscapedString - Print each character of the specified string, escaping +// it if it is not printable or if it is an escape char. +static void PrintEscapedString(const std::string &Str, raw_ostream &Out) { + for (unsigned i = 0, e = Str.size(); i != e; ++i) { + unsigned char C = Str[i]; + if (isprint(C) && C != '"' && C != '\\') { + Out << C; + } else { + Out << '\\' + << (char) ((C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A')) + << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A')); + } + } +} + +void XCoreAsmPrinter:: +emitFileDirective(const std::string &name) +{ + O << "\t.file\t\""; + PrintEscapedString(name, O); + O << "\"\n"; +} + +void XCoreAsmPrinter:: +emitGlobalDirective(const std::string &name) +{ + O << TAI->getGlobalDirective() << name; + O << "\n"; +} + +void XCoreAsmPrinter:: +emitExternDirective(const std::string &name) +{ + O << "\t.extern\t" << name; + O << '\n'; +} + +void XCoreAsmPrinter:: +emitArrayBound(const std::string &name, const GlobalVariable *GV) +{ + assert((GV->hasExternalLinkage() || + GV->hasWeakLinkage()) || + GV->hasLinkOnceLinkage() && "Unexpected linkage"); + if (const ArrayType *ATy = dyn_cast<ArrayType>( + cast<PointerType>(GV->getType())->getElementType())) + { + O << TAI->getGlobalDirective() << name << ".globound" << "\n"; + O << TAI->getSetDirective() << name << ".globound" << "," + << ATy->getNumElements() << "\n"; + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { + // TODO Use COMDAT groups for LinkOnceLinkage + O << TAI->getWeakDefDirective() << name << ".globound" << "\n"; + } + } +} + +void XCoreAsmPrinter:: +emitGlobal(const GlobalVariable *GV) +{ + const TargetData *TD = TM.getTargetData(); + + if (GV->hasInitializer()) { + // Check to see if this is a special global used by LLVM, if so, emit it. + if (EmitSpecialLLVMGlobal(GV)) + return; + + SwitchToSection(TAI->SectionForGlobal(GV)); + + std::string name = Mang->getValueName(GV); + Constant *C = GV->getInitializer(); + unsigned Align = (unsigned)TD->getPreferredTypeAlignmentShift(C->getType()); + + // Mark the start of the global + O << "\t.cc_top " << name << ".data," << name << "\n"; + + switch (GV->getLinkage()) { + case GlobalValue::AppendingLinkage: + cerr << "AppendingLinkage is not supported by this target!\n"; + abort(); + case GlobalValue::LinkOnceLinkage: + case GlobalValue::WeakLinkage: + case GlobalValue::ExternalLinkage: + emitArrayBound(name, GV); + emitGlobalDirective(name); + // TODO Use COMDAT groups for LinkOnceLinkage + if (GV->hasWeakLinkage() || GV->hasLinkOnceLinkage()) { + O << TAI->getWeakDefDirective() << name << "\n"; + } + // FALL THROUGH + case GlobalValue::InternalLinkage: + break; + case GlobalValue::GhostLinkage: + cerr << "Should not have any unmaterialized functions!\n"; + abort(); + case GlobalValue::DLLImportLinkage: + cerr << "DLLImport linkage is not supported by this target!\n"; + abort(); + case GlobalValue::DLLExportLinkage: + cerr << "DLLExport linkage is not supported by this target!\n"; + abort(); + default: + assert(0 && "Unknown linkage type!"); + } + + EmitAlignment(Align, GV, 2); + + unsigned Size = TD->getABITypeSize(C->getType()); + if (GV->isThreadLocal()) { + Size *= MaxThreads; + } + if (TAI->hasDotTypeDotSizeDirective()) { + O << "\t.type " << name << ",@object\n"; + O << "\t.size " << name << "," << Size << "\n"; + } + O << name << ":\n"; + + EmitGlobalConstant(C); + if (GV->isThreadLocal()) { + for (unsigned i = 1; i < MaxThreads; ++i) { + EmitGlobalConstant(C); + } + } + if (Size < 4) { + // The ABI requires that unsigned scalar types smaller than 32 bits + // are are padded to 32 bits. + EmitZeros(4 - Size); + } + + // Mark the end of the global + O << "\t.cc_bottom " << name << ".data\n"; + } else { + if (GV->hasExternalWeakLinkage()) + ExtWeakSymbols.insert(GV); + } +} + +/// Emit the directives on the start of functions +void XCoreAsmPrinter:: +emitFunctionStart(MachineFunction &MF) +{ + // Print out the label for the function. + const Function *F = MF.getFunction(); + + SwitchToSection(TAI->SectionForGlobal(F)); + + // Mark the start of the function + O << "\t.cc_top " << CurrentFnName << ".function," << CurrentFnName << "\n"; + + switch (F->getLinkage()) { + default: assert(0 && "Unknown linkage type!"); + case Function::InternalLinkage: // Symbols default to internal. + break; + case Function::ExternalLinkage: + emitGlobalDirective(CurrentFnName); + break; + case Function::LinkOnceLinkage: + case Function::WeakLinkage: + // TODO Use COMDAT groups for LinkOnceLinkage + O << TAI->getGlobalDirective() << CurrentFnName << "\n"; + O << TAI->getWeakDefDirective() << CurrentFnName << "\n"; + break; + } + // (1 << 1) byte aligned + EmitAlignment(1, F, 1); + if (TAI->hasDotTypeDotSizeDirective()) { + O << "\t.type " << CurrentFnName << ",@function\n"; + } + O << CurrentFnName << ":\n"; +} + +/// Emit the directives on the end of functions +void XCoreAsmPrinter:: +emitFunctionEnd(MachineFunction &MF) +{ + // Mark the end of the function + O << "\t.cc_bottom " << CurrentFnName << ".function\n"; +} + +/// runOnMachineFunction - This uses the printMachineInstruction() +/// method to print assembly for each instruction. +/// +bool XCoreAsmPrinter::runOnMachineFunction(MachineFunction &MF) +{ + SetupMachineFunction(MF); + + // Print out constants referenced by the function + EmitConstantPool(MF.getConstantPool()); + + // Print out jump tables referenced by the function + EmitJumpTableInfo(MF.getJumpTableInfo(), MF); + + // What's my mangled name? + CurrentFnName = Mang->getValueName(MF.getFunction()); + + // Emit the function start directives + emitFunctionStart(MF); + + // Emit pre-function debug information. + DW.BeginFunction(&MF); + + // Print out code for the function. + for (MachineFunction::const_iterator I = MF.begin(), E = MF.end(); + I != E; ++I) { + + // Print a label for the basic block. + if (I != MF.begin()) { + printBasicBlockLabel(I, true , true); + O << '\n'; + } + + for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end(); + II != E; ++II) { + // Print the assembly for the instruction. + O << "\t"; + printMachineInstruction(II); + } + + // Each Basic Block is separated by a newline + O << '\n'; + } + + // Emit function end directives + emitFunctionEnd(MF); + + // Emit post-function debug information. + DW.EndFunction(&MF); + + // We didn't modify anything. + return false; +} + +void XCoreAsmPrinter::printMemOperand(const MachineInstr *MI, int opNum) +{ + printOperand(MI, opNum); + + if (MI->getOperand(opNum+1).isImm() + && MI->getOperand(opNum+1).getImm() == 0) + return; + + O << "+"; + printOperand(MI, opNum+1); +} + +void XCoreAsmPrinter::printOperand(const MachineInstr *MI, int opNum) { + const MachineOperand &MO = MI->getOperand(opNum); + switch (MO.getType()) { + case MachineOperand::MO_Register: + if (TargetRegisterInfo::isPhysicalRegister(MO.getReg())) + O << TM.getRegisterInfo()->get(MO.getReg()).AsmName; + else + assert(0 && "not |