diff options
23 files changed, 15 insertions, 4028 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e4da7140b..33dd12314d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,7 +72,6 @@ set(LLVM_LIBDIR_SUFFIX "" CACHE STRING "Define suffix of library directory name set(LLVM_ALL_TARGETS ARM - CBackend CellSPU CppBackend Hexagon diff --git a/autoconf/configure.ac b/autoconf/configure.ac index c0027191d7..b21d3d9318 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -632,7 +632,7 @@ if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX Hexagon" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CppBackend MBlaze PTX Hexagon" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -645,7 +645,6 @@ case "$enableval" in spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; - cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; @@ -723,21 +722,6 @@ AC_SUBST(LLVM_ENUM_ASM_PRINTERS) AC_SUBST(LLVM_ENUM_ASM_PARSERS) AC_SUBST(LLVM_ENUM_DISASSEMBLERS) -dnl Prevent the CBackend from using printf("%a") for floating point so older -dnl C compilers that cannot deal with the 0x0p+0 hex floating point format -dnl can still compile the CBE's output -AC_ARG_ENABLE([cbe-printf-a],AS_HELP_STRING([--enable-cbe-printf-a], - [Enable C Backend output with hex floating point via %a (default is YES)]),, - enableval=default) -case "$enableval" in - yes) AC_SUBST(ENABLE_CBE_PRINTF_A,[1]) ;; - no) AC_SUBST(ENABLE_CBE_PRINTF_A,[0]) ;; - default) AC_SUBST(ENABLE_CBE_PRINTF_A,[1]) ;; - *) AC_MSG_ERROR([Invalid setting for --enable-cbe-printf-a. Use "yes" or "no"]) ;; -esac -AC_DEFINE_UNQUOTED([ENABLE_CBE_PRINTF_A],$ENABLE_CBE_PRINTF_A, - [Define if CBE is enabled for printf %a output]) - dnl Override the option to use for optimized builds. AC_ARG_WITH(optimize-option, AS_HELP_STRING([--with-optimize-option], @@ -705,7 +705,6 @@ LLVM_ENUM_TARGETS LLVM_ENUM_ASM_PRINTERS LLVM_ENUM_ASM_PARSERS LLVM_ENUM_DISASSEMBLERS -ENABLE_CBE_PRINTF_A OPTIMIZE_OPTION EXTRA_OPTIONS EXTRA_LD_OPTIONS @@ -1422,8 +1421,6 @@ Optional Features: target1,target2,... Valid targets are: host, x86, x86_64, sparc, powerpc, arm, mips, spu, hexagon, xcore, msp430, ptx, cbe, and cpp (default=all) - --enable-cbe-printf-a Enable C Backend output with hex floating point via - %a (default is YES) --enable-bindings Build specific language bindings: all,auto,none,{binding-name} (default=auto) --enable-libffi Check for the presence of libffi (default is NO) @@ -5310,7 +5307,7 @@ if test "$enableval" = host-only ; then enableval=host fi case "$enableval" in - all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CBackend CppBackend MBlaze PTX Hexagon" ;; + all) TARGETS_TO_BUILD="X86 Sparc PowerPC ARM Mips CellSPU XCore MSP430 CppBackend MBlaze PTX Hexagon" ;; *)for a_target in `echo $enableval|sed -e 's/,/ /g' ` ; do case "$a_target" in x86) TARGETS_TO_BUILD="X86 $TARGETS_TO_BUILD" ;; @@ -5323,7 +5320,6 @@ case "$enableval" in spu) TARGETS_TO_BUILD="CellSPU $TARGETS_TO_BUILD" ;; xcore) TARGETS_TO_BUILD="XCore $TARGETS_TO_BUILD" ;; msp430) TARGETS_TO_BUILD="MSP430 $TARGETS_TO_BUILD" ;; - cbe) TARGETS_TO_BUILD="CBackend $TARGETS_TO_BUILD" ;; cpp) TARGETS_TO_BUILD="CppBackend $TARGETS_TO_BUILD" ;; hexagon) TARGETS_TO_BUILD="Hexagon $TARGETS_TO_BUILD" ;; mblaze) TARGETS_TO_BUILD="MBlaze $TARGETS_TO_BUILD" ;; @@ -5420,30 +5416,6 @@ done -# Check whether --enable-cbe-printf-a was given. -if test "${enable_cbe_printf_a+set}" = set; then - enableval=$enable_cbe_printf_a; -else - enableval=default -fi - -case "$enableval" in - yes) ENABLE_CBE_PRINTF_A=1 - ;; - no) ENABLE_CBE_PRINTF_A=0 - ;; - default) ENABLE_CBE_PRINTF_A=1 - ;; - *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-cbe-printf-a. Use \"yes\" or \"no\"" >&5 -echo "$as_me: error: Invalid setting for --enable-cbe-printf-a. Use \"yes\" or \"no\"" >&2;} - { (exit 1); exit 1; }; } ;; -esac - -cat >>confdefs.h <<_ACEOF -#define ENABLE_CBE_PRINTF_A $ENABLE_CBE_PRINTF_A -_ACEOF - - # Check whether --with-optimize-option was given. if test "${with_optimize_option+set}" = set; then @@ -10402,7 +10374,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<EOF -#line 10405 "configure" +#line 10377 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -13686,7 +13658,6 @@ echo "$as_me: error: /* | [A-Za-z]:[\\/]*) INTEL_JITEVENTS_INCDIR=$withval/include INTEL_JITEVENTS_LIBDIR=$withval/$llvm_intel_jitevents_archdir ;; *) ;; - esac @@ -22186,7 +22157,6 @@ LLVM_ENUM_TARGETS!$LLVM_ENUM_TARGETS$ac_delim LLVM_ENUM_ASM_PRINTERS!$LLVM_ENUM_ASM_PRINTERS$ac_delim LLVM_ENUM_ASM_PARSERS!$LLVM_ENUM_ASM_PARSERS$ac_delim LLVM_ENUM_DISASSEMBLERS!$LLVM_ENUM_DISASSEMBLERS$ac_delim -ENABLE_CBE_PRINTF_A!$ENABLE_CBE_PRINTF_A$ac_delim OPTIMIZE_OPTION!$OPTIMIZE_OPTION$ac_delim EXTRA_OPTIONS!$EXTRA_OPTIONS$ac_delim EXTRA_LD_OPTIONS!$EXTRA_LD_OPTIONS$ac_delim @@ -22275,7 +22245,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 93; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 92; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/docs/ExtendingLLVM.html b/docs/ExtendingLLVM.html index ca8d3e990b..f8ba19545b 100644 --- a/docs/ExtendingLLVM.html +++ b/docs/ExtendingLLVM.html @@ -105,19 +105,6 @@ function and then be turned into an instruction if warranted.</p> support for it. Generally you must do the following steps:</p> <dl> -<dt>Add support to the C backend in <tt>lib/Target/CBackend/</tt></dt> - -<dd>Depending on the intrinsic, there are a few ways to implement this. For - most intrinsics, it makes sense to add code to lower your intrinsic in - <tt>LowerIntrinsicCall</tt> in <tt>lib/CodeGen/IntrinsicLowering.cpp</tt>. - Second, if it makes sense to lower the intrinsic to an expanded sequence of - C code in all cases, just emit the expansion in <tt>visitCallInst</tt> in - <tt>Writer.cpp</tt>. If the intrinsic has some way to express it with GCC - (or any other compiler) extensions, it can be conditionally supported based - on the compiler compiling the CBE output (see <tt>llvm.prefetch</tt> for an - example). Third, if the intrinsic really has no way to be lowered, just - have the code generator emit code that prints an error message and calls - abort if executed.</dd> <dt>Add support to the .td file for the target(s) of your choice in <tt>lib/Target/*/*.td</tt>.</dt> diff --git a/docs/GettingStarted.html b/docs/GettingStarted.html index 4d41208ea5..575ec04a86 100644 --- a/docs/GettingStarted.html +++ b/docs/GettingStarted.html @@ -1389,7 +1389,7 @@ different <a href="#tools">tools</a>.</p> <dd> This directory contains files that describe various target architectures for code generation. For example, the <tt>llvm/lib/Target/X86</tt> directory holds the X86 machine description while - <tt>llvm/lib/Target/CBackend</tt> implements the LLVM-to-C converter.</dd> + <tt>llvm/lib/Target/ARM</tt> implements the ARM backend.</dd> <dt><tt><b>llvm/lib/CodeGen/</b></tt></dt> <dd> This directory contains the major parts of the code generator: Instruction diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 723a5f68bb..3095fabd7b 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -12,9 +12,6 @@ /* Directories clang will search for headers */ #undef C_INCLUDE_DIRS -/* Define if CBE is enabled for printf %a output */ -#undef ENABLE_CBE_PRINTF_A - /* Define if position independent code is enabled */ #undef ENABLE_PIC diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp deleted file mode 100644 index b6b209eb06..0000000000 --- a/lib/Target/CBackend/CBackend.cpp +++ /dev/null @@ -1,3616 +0,0 @@ -//===-- CBackend.cpp - Library for converting LLVM code to C --------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This library converts LLVM code to C code, compilable by GCC and other C -// compilers. -// -//===----------------------------------------------------------------------===// - -#include "CTargetMachine.h" -#include "llvm/CallingConv.h" -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/Module.h" -#include "llvm/Instructions.h" -#include "llvm/Pass.h" -#include "llvm/PassManager.h" -#include "llvm/Intrinsics.h" -#include "llvm/IntrinsicInst.h" -#include "llvm/InlineAsm.h" -#include "llvm/ADT/StringExtras.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Analysis/ConstantsScanner.h" -#include "llvm/Analysis/FindUsedTypes.h" -#include "llvm/Analysis/LoopInfo.h" -#include "llvm/Analysis/ValueTracking.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/IntrinsicLowering.h" -#include "llvm/Target/Mangler.h" -#include "llvm/Transforms/Scalar.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCInstrInfo.h" -#include "llvm/MC/MCObjectFileInfo.h" -#include "llvm/MC/MCRegisterInfo.h" -#include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" -#include "llvm/Target/TargetData.h" -#include "llvm/Support/CallSite.h" -#include "llvm/Support/CFG.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Support/GetElementPtrTypeIterator.h" -#include "llvm/Support/InstVisitor.h" -#include "llvm/Support/MathExtras.h" -#include "llvm/Support/TargetRegistry.h" -#include "llvm/Support/Host.h" -#include "llvm/Config/config.h" -#include <algorithm> -// Some ms header decided to define setjmp as _setjmp, undo this for this file. -#ifdef _MSC_VER -#undef setjmp -#endif -using namespace llvm; - -extern "C" void LLVMInitializeCBackendTarget() { - // Register the target. - RegisterTargetMachine<CTargetMachine> X(TheCBackendTarget); -} - -namespace { - class CBEMCAsmInfo : public MCAsmInfo { - public: - CBEMCAsmInfo() { - GlobalPrefix = ""; - PrivateGlobalPrefix = ""; - } - }; - - /// CWriter - This class is the main chunk of code that converts an LLVM - /// module to a C translation unit. - class CWriter : public FunctionPass, public InstVisitor<CWriter> { - formatted_raw_ostream &Out; - IntrinsicLowering *IL; - Mangler *Mang; - LoopInfo *LI; - const Module *TheModule; - const MCAsmInfo* TAsm; - const MCRegisterInfo *MRI; - const MCObjectFileInfo *MOFI; - MCContext *TCtx; - const TargetData* TD; - - std::map<const ConstantFP *, unsigned> FPConstantMap; - std::set<Function*> intrinsicPrototypesAlreadyGenerated; - std::set<const Argument*> ByValParams; - unsigned FPCounter; - unsigned OpaqueCounter; - DenseMap<const Value*, unsigned> AnonValueNumbers; - unsigned NextAnonValueNumber; - - /// UnnamedStructIDs - This contains a unique ID for each struct that is - /// either anonymous or has no name. - DenseMap<StructType*, unsigned> UnnamedStructIDs; - - public: - static char ID; - explicit CWriter(formatted_raw_ostream &o) - : FunctionPass(ID), Out(o), IL(0), Mang(0), LI(0), - TheModule(0), TAsm(0), MRI(0), MOFI(0), TCtx(0), TD(0), - OpaqueCounter(0), NextAnonValueNumber(0) { - initializeLoopInfoPass(*PassRegistry::getPassRegistry()); - FPCounter = 0; - } - - virtual const char *getPassName() const { return "C backend"; } - - void getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<LoopInfo>(); - AU.setPreservesAll(); - } - - virtual bool doInitialization(Module &M); - - bool runOnFunction(Function &F) { - // Do not codegen any 'available_externally' functions at all, they have - // definitions outside the translation unit. - if (F.hasAvailableExternallyLinkage()) - return false; - - LI = &getAnalysis<LoopInfo>(); - - // Get rid of intrinsics we can't handle. - lowerIntrinsics(F); - - // Output all floating point constants that cannot be printed accurately. - printFloatingPointConstants(F); - - printFunction(F); - return false; - } - - virtual bool doFinalization(Module &M) { - // Free memory... - delete IL; - delete TD; - delete Mang; - delete TCtx; - delete TAsm; - delete MRI; - delete MOFI; - FPConstantMap.clear(); - ByValParams.clear(); - intrinsicPrototypesAlreadyGenerated.clear(); - UnnamedStructIDs.clear(); - return false; - } - - raw_ostream &printType(raw_ostream &Out, Type *Ty, - bool isSigned = false, - const std::string &VariableName = "", - bool IgnoreName = false, - const AttrListPtr &PAL = AttrListPtr()); - raw_ostream &printSimpleType(raw_ostream &Out, Type *Ty, - bool isSigned, - const std::string &NameSoFar = ""); - - void printStructReturnPointerFunctionType(raw_ostream &Out, - const AttrListPtr &PAL, - PointerType *Ty); - - std::string getStructName(StructType *ST); - - /// writeOperandDeref - Print the result of dereferencing the specified - /// operand with '*'. This is equivalent to printing '*' then using - /// writeOperand, but avoids excess syntax in some cases. - void writeOperandDeref(Value *Operand) { - if (isAddressExposed(Operand)) { - // Already something with an address exposed. - writeOperandInternal(Operand); - } else { - Out << "*("; - writeOperand(Operand); - Out << ")"; - } - } - - void writeOperand(Value *Operand, bool Static = false); - void writeInstComputationInline(Instruction &I); - void writeOperandInternal(Value *Operand, bool Static = false); - void writeOperandWithCast(Value* Operand, unsigned Opcode); - void writeOperandWithCast(Value* Operand, const ICmpInst &I); - bool writeInstructionCast(const Instruction &I); - - void writeMemoryAccess(Value *Operand, Type *OperandType, - bool IsVolatile, unsigned Alignment); - - private : - std::string InterpretASMConstraint(InlineAsm::ConstraintInfo& c); - - void lowerIntrinsics(Function &F); - /// Prints the definition of the intrinsic function F. Supports the - /// intrinsics which need to be explicitly defined in the CBackend. - void printIntrinsicDefinition(const Function &F, raw_ostream &Out); - - void printModuleTypes(); - void printContainedStructs(Type *Ty, SmallPtrSet<Type *, 16> &); - void printFloatingPointConstants(Function &F); - void printFloatingPointConstants(const Constant *C); - void printFunctionSignature(const Function *F, bool Prototype); - - void printFunction(Function &); - void printBasicBlock(BasicBlock *BB); - void printLoop(Loop *L); - - void printCast(unsigned opcode, Type *SrcTy, Type *DstTy); - void printConstant(Constant *CPV, bool Static); - void printConstantWithCast(Constant *CPV, unsigned Opcode); - bool printConstExprCast(const ConstantExpr *CE, bool Static); - void printConstantArray(ConstantArray *CPA, bool Static); - void printConstantVector(ConstantVector *CV, bool Static); - void printConstantDataSequential(ConstantDataSequential *CDS, bool Static); - - - /// isAddressExposed - Return true if the specified value's name needs to - /// have its address taken in order to get a C value of the correct type. - /// This happens for global variables, byval parameters, and direct allocas. - bool isAddressExposed(const Value *V) const { - if (const Argument *A = dyn_cast<Argument>(V)) - return ByValParams.count(A); - return isa<GlobalVariable>(V) || isDirectAlloca(V); - } - - // isInlinableInst - Attempt to inline instructions into their uses to build - // trees as much as possible. To do this, we have to consistently decide - // what is acceptable to inline, so that variable declarations don't get - // printed and an extra copy of the expr is not emitted. - // - static bool isInlinableInst(const Instruction &I) { - // Always inline cmp instructions, even if they are shared by multiple - // expressions. GCC generates horrible code if we don't. - if (isa<CmpInst>(I)) - return true; - - // Must be an expression, must be used exactly once. If it is dead, we - // emit it inline where it would go. - if (I.getType() == Type::getVoidTy(I.getContext()) || !I.hasOneUse() || - isa<TerminatorInst>(I) || isa<CallInst>(I) || isa<PHINode>(I) || - isa<LoadInst>(I) || isa<VAArgInst>(I) || isa<InsertElementInst>(I) || - isa<InsertValueInst>(I)) - // Don't inline a load across a store or other bad things! - return false; - - // Must not be used in inline asm, extractelement, or shufflevector. - if (I.hasOneUse()) { - const Instruction &User = cast<Instruction>(*I.use_back()); - if (isInlineAsm(User) || isa<ExtractElementInst>(User) || - isa<ShuffleVectorInst>(User)) - return false; - } - - // Only inline instruction it if it's use is in the same BB as the inst. - return I.getParent() == cast<Instruction>(I.use_back())->getParent(); - } - - // isDirectAlloca - Define fixed sized allocas in the entry block as direct - // variables which are accessed with the & operator. This causes GCC to - // generate significantly better code than to emit alloca calls directly. - // - static const AllocaInst *isDirectAlloca(const Value *V) { - const AllocaInst *AI = dyn_cast<AllocaInst>(V); - if (!AI) return 0; - if (AI->isArrayAllocation()) - return 0; // FIXME: we can also inline fixed size array allocas! - if (AI->getParent() != &AI->getParent()->getParent()->getEntryBlock()) - return 0; - return AI; - } - - // isInlineAsm - Check if the instruction is a call to an inline asm chunk. - static bool isInlineAsm(const Instruction& I) { - if (const CallInst *CI = dyn_cast<CallInst>(&I)) - return isa<InlineAsm>(CI->getCalledValue()); - return false; - } - - // Instruction visitation functions - friend class InstVisitor<CWriter>; - - void visitReturnInst(ReturnInst &I); - void visitBranchInst(BranchInst &I); - void visitSwitchInst(SwitchInst &I); - void visitIndirectBrInst(IndirectBrInst &I); - void visitInvokeInst(InvokeInst &I) { - llvm_unreachable("Lowerinvoke pass didn't work!"); - } - void visitResumeInst(ResumeInst &I) { - llvm_unreachable("DwarfEHPrepare pass didn't work!"); - } - void visitUnreachableInst(UnreachableInst &I); - - void visitPHINode(PHINode &I); - void visitBinaryOperator(Instruction &I); - void visitICmpInst(ICmpInst &I); - void visitFCmpInst(FCmpInst &I); - - void visitCastInst (CastInst &I); - void visitSelectInst(SelectInst &I); - void visitCallInst (CallInst &I); - void visitInlineAsm(CallInst &I); - bool visitBuiltinCall(CallInst &I, Intrinsic::ID ID, bool &WroteCallee); - - void visitAllocaInst(AllocaInst &I); - void visitLoadInst (LoadInst &I); - void visitStoreInst (StoreInst &I); - void visitGetElementPtrInst(GetElementPtrInst &I); - void visitVAArgInst (VAArgInst &I); - - void visitInsertElementInst(InsertElementInst &I); - void visitExtractElementInst(ExtractElementInst &I); - void visitShuffleVectorInst(ShuffleVectorInst &SVI); - - void visitInsertValueInst(InsertValueInst &I); - void visitExtractValueInst(ExtractValueInst &I); - - void visitInstruction(Instruction &I) { -#ifndef NDEBUG - errs() << "C Writer does not know about " << I; -#endif - llvm_unreachable(0); - } - - void outputLValue(Instruction *I) { - Out << " " << GetValueName(I) << " = "; - } - - bool isGotoCodeNecessary(BasicBlock *From, BasicBlock *To); - void printPHICopiesForSuccessor(BasicBlock *CurBlock, - BasicBlock *Successor, unsigned Indent); - void printBranchToBlock(BasicBlock *CurBlock, BasicBlock *SuccBlock, - unsigned Indent); - void printGEPExpression(Value *Ptr, gep_type_iterator I, - gep_type_iterator E, bool Static); - - std::string GetValueName(const Value *Operand); - }; -} - -char CWriter::ID = 0; - - - -static std::string CBEMangle(const std::string &S) { - std::string Result; - - for (unsigned i = 0, e = S.size(); i != e; ++i) - if (isalnum(S[i]) || S[i] == '_') { - Result += S[i]; - } else { - Result += '_'; - Result += 'A'+(S[i]&15); - Result += 'A'+((S[i]>>4)&15); - Result += '_'; - } - return Result; -} - -std::string CWriter::getStructName(StructType *ST) { - if (!ST->isLiteral() && !ST->getName().empty()) - return CBEMangle("l_"+ST->getName().str()); - - return "l_unnamed_" + utostr(UnnamedStructIDs[ST]); -} - - -/// printStructReturnPointerFunctionType - This is like printType for a struct -/// return type, except, instead of printing the type as void (*)(Struct*, ...) -/// print it as "Struct (*)(...)", for struct return functions. -void CWriter::printStructReturnPointerFunctionType(raw_ostream &Out, - const AttrListPtr &PAL, - PointerType *TheTy) { - FunctionType *FTy = cast<FunctionType>(TheTy->getElementType()); - std::string tstr; - raw_string_ostream FunctionInnards(tstr); - FunctionInnards << " (*) ("; - bool PrintedType = false; - - FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end(); - Type *RetTy = cast<PointerType>(*I)->getElementType(); - unsigned Idx = 1; - for (++I, ++Idx; I != E; ++I, ++Idx) { - if (PrintedType) - FunctionInnards << ", "; - Type *ArgTy = *I; - if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { - assert(ArgTy->isPointerTy()); - ArgTy = cast<PointerType>(ArgTy)->getElementType(); - } - printType(FunctionInnards, ArgTy, - /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), ""); - PrintedType = true; - } - if (FTy->isVarArg()) { - if (!PrintedType) - FunctionInnards << " int"; //dummy argument for empty vararg functs - FunctionInnards << ", ..."; - } else if (!PrintedType) { - FunctionInnards << "void"; - } - FunctionInnards << ')'; - printType(Out, RetTy, - /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), FunctionInnards.str()); -} - -raw_ostream & -CWriter::printSimpleType(raw_ostream &Out, Type *Ty, bool isSigned, - const std::string &NameSoFar) { - assert((Ty->isPrimitiveType() || Ty->isIntegerTy() || Ty->isVectorTy()) && - "Invalid type for printSimpleType"); - switch (Ty->getTypeID()) { - case Type::VoidTyID: return Out << "void " << NameSoFar; - case Type::IntegerTyID: { - unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); - if (NumBits == 1) - return Out << "bool " << NameSoFar; - else if (NumBits <= 8) - return Out << (isSigned?"signed":"unsigned") << " char " << NameSoFar; - else if (NumBits <= 16) - return Out << (isSigned?"signed":"unsigned") << " short " << NameSoFar; - else if (NumBits <= 32) - return Out << (isSigned?"signed":"unsigned") << " int " << NameSoFar; - else if (NumBits <= 64) - return Out << (isSigned?"signed":"unsigned") << " long long "<< NameSoFar; - else { - assert(NumBits <= 128 && "Bit widths > 128 not implemented yet"); - return Out << (isSigned?"llvmInt128":"llvmUInt128") << " " << NameSoFar; - } - } - case Type::FloatTyID: return Out << "float " << NameSoFar; - case Type::DoubleTyID: return Out << "double " << NameSoFar; - // Lacking emulation of FP80 on PPC, etc., we assume whichever of these is - // present matches host 'long double'. - case Type::X86_FP80TyID: - case Type::PPC_FP128TyID: - case Type::FP128TyID: return Out << "long double " << NameSoFar; - - case Type::X86_MMXTyID: - return printSimpleType(Out, Type::getInt32Ty(Ty->getContext()), isSigned, - " __attribute__((vector_size(64))) " + NameSoFar); - - case Type::VectorTyID: { - VectorType *VTy = cast<VectorType>(Ty); - return printSimpleType(Out, VTy->getElementType(), isSigned, - " __attribute__((vector_size(" + - utostr(TD->getTypeAllocSize(VTy)) + " ))) " + NameSoFar); - } - - default: -#ifndef NDEBUG - errs() << "Unknown primitive type: " << *Ty << "\n"; -#endif - llvm_unreachable(0); - } -} - -// Pass the Type* and the variable name and this prints out the variable -// declaration. -// -raw_ostream &CWriter::printType(raw_ostream &Out, Type *Ty, - bool isSigned, const std::string &NameSoFar, - bool IgnoreName, const AttrListPtr &PAL) { - if (Ty->isPrimitiveType() || Ty->isIntegerTy() || Ty->isVectorTy()) { - printSimpleType(Out, Ty, isSigned, NameSoFar); - return Out; - } - - switch (Ty->getTypeID()) { - case Type::FunctionTyID: { - FunctionType *FTy = cast<FunctionType>(Ty); - std::string tstr; - raw_string_ostream FunctionInnards(tstr); - FunctionInnards << " (" << NameSoFar << ") ("; - unsigned Idx = 1; - for (FunctionType::param_iterator I = FTy->param_begin(), - E = FTy->param_end(); I != E; ++I) { - Type *ArgTy = *I; - if (PAL.paramHasAttr(Idx, Attribute::ByVal)) { - assert(ArgTy->isPointerTy()); - ArgTy = cast<PointerType>(ArgTy)->getElementType(); - } - if (I != FTy->param_begin()) - FunctionInnards << ", "; - printType(FunctionInnards, ArgTy, - /*isSigned=*/PAL.paramHasAttr(Idx, Attribute::SExt), ""); - ++Idx; - } - if (FTy->isVarArg()) { - if (!FTy->getNumParams()) - FunctionInnards << " int"; //dummy argument for empty vaarg functs - FunctionInnards << ", ..."; - } else if (!FTy->getNumParams()) { - FunctionInnards << "void"; - } - FunctionInnards << ')'; - printType(Out, FTy->getReturnType(), - /*isSigned=*/PAL.paramHasAttr(0, Attribute::SExt), FunctionInnards.str()); - return Out; - } - case Type::StructTyID: { - StructType *STy = cast<StructType>(Ty); - - // Check to see if the type is named. - if (!IgnoreName) - return Out << getStructName(STy) << ' ' << NameSoFar; - - Out << NameSoFar + " {\n"; - unsigned Idx = 0; - for (StructType::element_iterator I = STy->element_begin(), - E = STy->element_end(); I != E; ++I) { - Out << " "; - printType(Out, *I, false, "field" + utostr(Idx++)); - Out << ";\n"; - } - Out << '}'; - if (STy->isPacked()) - Out << " __attribute__ ((packed))"; - return Out; - } - - case Type::PointerTyID: { - PointerType *PTy = cast<PointerType>(Ty); - std::string ptrName = "*" + NameSoFar; - - if (PTy->getElementType()->isArrayTy() || - PTy->getElementType()->isVectorTy()) - ptrName = "(" + ptrName + ")"; - - if (!PAL.isEmpty()) - // Must be a function ptr cast! - return printType(Out, PTy->getElementType(), false, ptrName, true, PAL); - return printType(Out, PTy->getElementType(), false, ptrName); - } - - case Type::ArrayTyID: { - ArrayType *ATy = cast<ArrayType>(Ty); - unsigned NumElements = ATy->getNumElements(); - if (NumElements == 0) NumElements = 1; - // Arrays are wrapped in structs to allow them to have normal - // value semantics (avoiding the array "decay"). - Out << NameSoFar << " { "; - printType(Out, ATy->getElementType(), false, - "array[" + utostr(NumElements) + "]"); - return Out << "; }"; - } - - default: - llvm_unreachable("Unhandled case in getTypeProps!"); - } -} - -void CWriter::printConstantArray(ConstantArray *CPA, bool Static) { - Out << "{ "; - printConstant(cast<Constant>(CPA->getOperand(0)), Static); - for (unsigned i = 1, e = CPA->getNumOperands(); i != e; ++i) { - Out << ", "; - printConstant(cast<Constant>(CPA->getOperand(i)), Static); - } - Out << " }"; -} - -void CWriter::printConstantVector(ConstantVector *CP, bool Static) { - Out << "{ "; - printConstant(cast<Constant>(CP->getOperand(0)), Static); - for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) { - Out << ", "; - printConstant(cast<Constant>(CP->getOperand(i)), Static); - } - Out << " }"; -} - -void CWriter::printConstantDataSequential(ConstantDataSequential *CDS, - bool Static) { - // As a special case, print the array as a string if it is an array of - // ubytes or an array of sbytes with positive values. - // - if (CDS->isCString()) { - Out << '\"'; - // Keep track of whether the last number was a hexadecimal escape. - bool LastWasHex = false; - - StringRef Bytes = CDS->getAsCString(); - - // Do not include the last character, which we know is null - for (unsigned i = 0, e = Bytes.size(); i != e; ++i) { - unsigned char C = Bytes[i]; - - // Print it out literally if it is a printable character. The only thing - // to be careful about is when the last letter output was a hex escape - // code, in which case we have to be careful not to print out hex digits - // explicitly (the C compiler thinks it is a continuation of the previ |