diff --git a/.gitignore b/.gitignore index a17e2716a5e90ee10ac32c19c3fc2f29f953f286..09b3395deae54cb0cd7145f2d75374090aa7bdb0 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,6 @@ Output *.cmi *.cmx llvm-install -Makefile.config Makefile.llvmbuild META.llvm config.log diff --git a/hpvm/projects/llvm-cbe/lib/Target/CBackend/CBackend.cpp b/hpvm/projects/llvm-cbe/lib/Target/CBackend/CBackend.cpp index a5fddb967dbd96befef3af7d01fe6c42fd16462c..c61573a13abcc09b1db10d86e141264a8b1c1760 100644 --- a/hpvm/projects/llvm-cbe/lib/Target/CBackend/CBackend.cpp +++ b/hpvm/projects/llvm-cbe/lib/Target/CBackend/CBackend.cpp @@ -14,14 +14,14 @@ #include "CBackend.h" #include "llvm/Analysis/ValueTracking.h" -#include "llvm/CodeGen/TargetLowering.h" -#include "llvm/Config/config.h" #include "llvm/IR/InstIterator.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/Host.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/Host.h" +#include "llvm/CodeGen/TargetLowering.h" +#include "llvm/Config/config.h" #include "llvm/Transforms/Utils.h" #include <algorithm> @@ -29,14 +29,16 @@ #include <iostream> + //#include "PHINodePass.h" -// Jackson Korba 9/29/14 +//Jackson Korba 9/29/14 #ifndef DEBUG_TYPE #define DEBUG_TYPE "" #endif -// End Modification +//End Modification +#define DEBUG(x) x // Some ms header decided to define setjmp as _setjmp, undo this for this file // since we don't need it #ifdef setjmp @@ -51,8 +53,7 @@ extern "C" void LLVMInitializeCBackendTarget() { char CWriter::ID = 0; -// extra (invalid) Ops tags for tracking unary ops as a special case of the -// available binary ops +// extra (invalid) Ops tags for tracking unary ops as a special case of the available binary ops enum UnaryOps { BinaryNeg = Instruction::OtherOpsEnd + 1, BinaryNot, @@ -61,16 +62,19 @@ enum UnaryOps { static bool isEmptyType(Type *Ty) { if (StructType *STy = dyn_cast<StructType>(Ty)) return STy->getNumElements() == 0 || - std::all_of(STy->element_begin(), STy->element_end(), - [](Type *T) { return isEmptyType(T); }); + std::all_of(STy->element_begin(), STy->element_end(), [](Type *T){ return isEmptyType(T); }); if (VectorType *VTy = dyn_cast<VectorType>(Ty)) - return VTy->getNumElements() == 0 || isEmptyType(VTy->getElementType()); + return VTy->getNumElements() == 0 || + isEmptyType(VTy->getElementType()); if (ArrayType *ATy = dyn_cast<ArrayType>(Ty)) - return ATy->getNumElements() == 0 || isEmptyType(ATy->getElementType()); + return ATy->getNumElements() == 0 || + isEmptyType(ATy->getElementType()); return Ty->isVoidTy(); } -bool CWriter::isEmptyType(Type *Ty) const { return ::isEmptyType(Ty); } +bool CWriter::isEmptyType(Type *Ty) const { + return ::isEmptyType(Ty); +} /// 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. @@ -95,19 +99,19 @@ bool CWriter::isInlinableInst(Instruction &I) const { if (isa<GetElementPtrInst>(I)) { for (User *U : I.users()) { if (!(isa<LoadInst>(U) || isa<StoreInst>(U))) { - // DEBUG(errs() << "GEP user not a Load/Store!\n"); + DEBUG(errs() << "GEP user not a Load/Store!\n"); return false; } } - // DEBUG(errs() << "All users of GEP are loads/stores, mark it - // inlinable!\n"); + DEBUG(errs() << "All users of GEP are loads/stores, mark it inlinable!\n"); return true; } // Must be an expression, must be used exactly once. If it is dead, we // emit it inline where it would go. - if (isEmptyType(I.getType()) || !I.hasOneUse() || I.isTerminator() || - isa<CallInst>(I) || isa<PHINode>(I) || isa<LoadInst>(I) || - isa<VAArgInst>(I) || isa<InsertElementInst>(I) || isa<InsertValueInst>(I)) + if (isEmptyType(I.getType()) || !I.hasOneUse() || + I.isTerminator() || 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; @@ -127,20 +131,19 @@ bool CWriter::isInlinableInst(Instruction &I) const { // generate significantly better code than to emit alloca calls directly. // AllocaInst *CWriter::isDirectAlloca(Value *V) const { - // DEBUG(errs() << "Checking if " << *V << " is a direct alloca!\n"); + DEBUG(errs() << "Checking if " << *V << " is a direct alloca!\n"); AllocaInst *AI = dyn_cast<AllocaInst>(V); - if (!AI) - return 0; + if (!AI) return 0; // Modification to inline fixed size array alloca! if (AI->isArrayAllocation()) - return AI; // FIXME: we can also inline fixed size array allocas! + return AI; // 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. -bool CWriter::isInlineAsm(Instruction &I) const { +bool CWriter::isInlineAsm(Instruction& I) const { if (CallInst *CI = dyn_cast<CallInst>(&I)) return isa<InlineAsm>(CI->getCalledValue()); return false; @@ -158,28 +161,25 @@ bool CWriter::runOnFunction(Function &F) { PDT = &getAnalysis<PostDominatorTreeWrapperPass>().getPostDomTree(); // Adding Scalar Evolution Pass for loop induction variable SE = &getAnalysis<ScalarEvolutionWrapperPass>().getSE(); - // Adding Dominator Tree Pass + //Adding Dominator Tree Pass DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); // Adding Assumption Cache AC = &getAnalysis<AssumptionCacheTracker>().getAssumptionCache(F); // Adding IVUsers Pass for loop recongnition // IU = &getAnalysis<IVUsersWrapperPass>().getIU(); - BasicBlock *entry = &(F.getEntryBlock()); - for (df_iterator<BasicBlock *> BI = df_begin(entry), BE = df_end(entry); - BI != BE; ++BI) { + BasicBlock* entry = &(F.getEntryBlock()); + for (df_iterator<BasicBlock*> BI = df_begin(entry), BE = df_end(entry); BI!=BE; ++BI) { BasicBlock *BB = *BI; if (Loop *L = LI->getLoopFor(&*BB)) { - if (simplifyLoop(L, DT, LI, SE, AC, nullptr, /*true*/ false)) { - // DEBUG(errs() << "Simplified loop!\n" << *L << "\n"); + if(simplifyLoop(L, DT, LI, SE, AC, nullptr, /*true*/false)) { + DEBUG(errs() << "Simplified loop!\n" << *L << "\n"); } } } // Get rid of intrinsics we can't handle. lowerIntrinsics(F); - // Output all floating point constants that cannot be printed accurately. - printFloatingPointConstants(F); printFunction(F); @@ -196,15 +196,15 @@ static std::string CBEMangle(const std::string &S) { Result += S[i]; } else { Result += '_'; - Result += 'A' + (S[i] & 15); - Result += 'A' + ((S[i] >> 4) & 15); + Result += 'A'+(S[i]&15); + Result += 'A'+((S[i]>>4)&15); Result += '_'; } return Result; } -raw_ostream &CWriter::printTypeString(raw_ostream &Out, Type *Ty, - bool isSigned) { +raw_ostream & +CWriter::printTypeString(raw_ostream &Out, Type *Ty, bool isSigned) { if (StructType *ST = dyn_cast<StructType>(Ty)) { assert(!isEmptyType(ST)); TypedefDeclTypes.insert(Ty); @@ -224,51 +224,46 @@ raw_ostream &CWriter::printTypeString(raw_ostream &Out, Type *Ty, } switch (Ty->getTypeID()) { - case Type::VoidTyID: - return Out << "void"; - case Type::IntegerTyID: { - unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); - if (NumBits == 1) - return Out << "bool"; - else { - assert(NumBits <= 128 && "Bit widths > 128 not implemented yet"); - return Out << (isSigned ? "i" : "u") << NumBits; - } - } - case Type::FloatTyID: - return Out << "f32"; - case Type::DoubleTyID: - return Out << "f64"; - case Type::X86_FP80TyID: - return Out << "f80"; - case Type::PPC_FP128TyID: - case Type::FP128TyID: - return Out << "f128"; - - case Type::X86_MMXTyID: - return Out << (isSigned ? "i32y2" : "u32y2"); - - case Type::VectorTyID: { - TypedefDeclTypes.insert(Ty); - VectorType *VTy = cast<VectorType>(Ty); - assert(VTy->getNumElements() != 0); - printTypeString(Out, VTy->getElementType(), isSigned); - return Out << "x" << VTy->getNumElements(); - } - - case Type::ArrayTyID: { - TypedefDeclTypes.insert(Ty); - ArrayType *ATy = cast<ArrayType>(Ty); - assert(ATy->getNumElements() != 0); - printTypeString(Out, ATy->getElementType(), isSigned); - return Out << "a" << ATy->getNumElements(); - } + case Type::VoidTyID: return Out << "void"; + case Type::IntegerTyID: { + unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); + if (NumBits == 1) + return Out << "bool"; + else { + assert(NumBits <= 128 && "Bit widths > 128 not implemented yet"); + return Out << (isSigned?"i":"u") << NumBits; + } + } + case Type::FloatTyID: return Out << "f32"; + case Type::DoubleTyID: return Out << "f64"; + case Type::X86_FP80TyID: return Out << "f80"; + case Type::PPC_FP128TyID: + case Type::FP128TyID: return Out << "f128"; + + case Type::X86_MMXTyID: + return Out << (isSigned ? "i32y2" : "u32y2"); + + case Type::VectorTyID: { + TypedefDeclTypes.insert(Ty); + VectorType *VTy = cast<VectorType>(Ty); + assert(VTy->getNumElements() != 0); + printTypeString(Out, VTy->getElementType(), isSigned); + return Out << "x" << VTy->getNumElements(); + } + + case Type::ArrayTyID: { + TypedefDeclTypes.insert(Ty); + ArrayType *ATy = cast<ArrayType>(Ty); + assert(ATy->getNumElements() != 0); + printTypeString(Out, ATy->getElementType(), isSigned); + return Out << "a" << ATy->getNumElements(); + } - default: + default: #ifndef NDEBUG - errs() << "Unknown primitive type: " << *Ty << "\n"; + errs() << "Unknown primitive type: " << *Ty << "\n"; #endif - llvm_unreachable(0); + llvm_unreachable(0); } } @@ -283,9 +278,8 @@ std::string CWriter::getStructName(StructType *ST) { return "struct l_unnamed_" + utostr(id); } -std::string -CWriter::getFunctionName(FunctionType *FT, - std::pair<AttributeList, CallingConv::ID> PAL) { +std::string CWriter::getFunctionName(FunctionType *FT, + std::pair<AttributeList, CallingConv::ID> PAL) { unsigned &id = UnnamedFunctionIDs[std::make_pair(FT, PAL)]; if (id == 0) id = ++NextFunctionNumber; @@ -299,8 +293,7 @@ std::string CWriter::getArrayName(ArrayType *AT) { // value semantics (avoiding the array "decay"). assert(!isEmptyType(AT)); printTypeName(ArrayInnards, AT->getElementType(), false); - return "struct l_array_" + utostr(AT->getNumElements()) + '_' + - CBEMangle(ArrayInnards.str()); + return "struct l_array_" + utostr(AT->getNumElements()) + '_' + CBEMangle(ArrayInnards.str()); } std::string CWriter::getVectorName(VectorType *VT, bool Aligned) { @@ -311,125 +304,95 @@ std::string CWriter::getVectorName(VectorType *VT, bool Aligned) { // if (Aligned) // Out << "__MSALIGN__(" << TD->getABITypeAlignment(VT) << ") "; printTypeName(VectorInnards, VT->getElementType(), false); - return "struct l_vector_" + utostr(VT->getNumElements()) + '_' + - CBEMangle(VectorInnards.str()); + return "struct l_vector_" + utostr(VT->getNumElements()) + '_' + CBEMangle(VectorInnards.str()); } + static const std::string getCmpPredicateName(CmpInst::Predicate P) { switch (P) { - case FCmpInst::FCMP_FALSE: - return "0"; - case FCmpInst::FCMP_OEQ: - return "oeq"; - case FCmpInst::FCMP_OGT: - return "ogt"; - case FCmpInst::FCMP_OGE: - return "oge"; - case FCmpInst::FCMP_OLT: - return "olt"; - case FCmpInst::FCMP_OLE: - return "ole"; - case FCmpInst::FCMP_ONE: - return "one"; - case FCmpInst::FCMP_ORD: - return "ord"; - case FCmpInst::FCMP_UNO: - return "uno"; - case FCmpInst::FCMP_UEQ: - return "ueq"; - case FCmpInst::FCMP_UGT: - return "ugt"; - case FCmpInst::FCMP_UGE: - return "uge"; - case FCmpInst::FCMP_ULT: - return "ult"; - case FCmpInst::FCMP_ULE: - return "ule"; - case FCmpInst::FCMP_UNE: - return "une"; - case FCmpInst::FCMP_TRUE: - return "1"; - case ICmpInst::ICMP_EQ: - return "eq"; - case ICmpInst::ICMP_NE: - return "ne"; - case ICmpInst::ICMP_ULE: - return "ule"; - case ICmpInst::ICMP_SLE: - return "sle"; - case ICmpInst::ICMP_UGE: - return "uge"; - case ICmpInst::ICMP_SGE: - return "sge"; - case ICmpInst::ICMP_ULT: - return "ult"; - case ICmpInst::ICMP_SLT: - return "slt"; - case ICmpInst::ICMP_UGT: - return "ugt"; - case ICmpInst::ICMP_SGT: - return "sgt"; - default: + case FCmpInst::FCMP_FALSE: return "0"; + case FCmpInst::FCMP_OEQ: return "oeq"; + case FCmpInst::FCMP_OGT: return "ogt"; + case FCmpInst::FCMP_OGE: return "oge"; + case FCmpInst::FCMP_OLT: return "olt"; + case FCmpInst::FCMP_OLE: return "ole"; + case FCmpInst::FCMP_ONE: return "one"; + case FCmpInst::FCMP_ORD: return "ord"; + case FCmpInst::FCMP_UNO: return "uno"; + case FCmpInst::FCMP_UEQ: return "ueq"; + case FCmpInst::FCMP_UGT: return "ugt"; + case FCmpInst::FCMP_UGE: return "uge"; + case FCmpInst::FCMP_ULT: return "ult"; + case FCmpInst::FCMP_ULE: return "ule"; + case FCmpInst::FCMP_UNE: return "une"; + case FCmpInst::FCMP_TRUE: return "1"; + case ICmpInst::ICMP_EQ: return "eq"; + case ICmpInst::ICMP_NE: return "ne"; + case ICmpInst::ICMP_ULE: return "ule"; + case ICmpInst::ICMP_SLE: return "sle"; + case ICmpInst::ICMP_UGE: return "uge"; + case ICmpInst::ICMP_SGE: return "sge"; + case ICmpInst::ICMP_ULT: return "ult"; + case ICmpInst::ICMP_SLT: return "slt"; + case ICmpInst::ICMP_UGT: return "ugt"; + case ICmpInst::ICMP_SGT: return "sgt"; + default: #ifndef NDEBUG - errs() << "Invalid icmp predicate!" << P; + errs() << "Invalid icmp predicate!" << P; #endif - llvm_unreachable(0); + llvm_unreachable(0); } } -raw_ostream &CWriter::printSimpleType(raw_ostream &Out, Type *Ty, - bool isSigned) { + +raw_ostream & +CWriter::printSimpleType(raw_ostream &Out, Type *Ty, bool isSigned) { assert((Ty->isSingleValueType() || Ty->isVoidTy()) && - "Invalid type for printSimpleType"); + "Invalid type for printSimpleType"); switch (Ty->getTypeID()) { - case Type::VoidTyID: - return Out << "void"; - case Type::IntegerTyID: { - unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); - if (NumBits == 1) - return Out << "bool"; - else if (NumBits <= 8) - return Out << (isSigned ? "char" : "uchar"); - else if (NumBits <= 16) - return Out << (isSigned ? "short" : "ushort"); - else if (NumBits <= 32) - return Out << (isSigned ? "int" : "uint"); // !!FIX ME - else if (NumBits <= 64) - return Out << (isSigned ? "long" : "ulong"); - else { - assert(NumBits <= 128 && "Bit widths > 128 not implemented yet"); - return Out << (isSigned ? "int128_t" : "uint128_t"); - } - } - case Type::FloatTyID: - return Out << "float"; - case Type::DoubleTyID: - return Out << "double"; - // 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"; - - case Type::X86_MMXTyID: - return Out << (isSigned ? "int" : "uint") - << " __attribute__((vector_size(8)))"; - - default: + case Type::VoidTyID: return Out << "void"; + case Type::IntegerTyID: { + unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); + if (NumBits == 1) + return Out << "bool"; + else if (NumBits <= 8) + return Out << (isSigned?"char":"uchar"); + else if (NumBits <= 16) + return Out << (isSigned?"short":"ushort"); + else if (NumBits <= 32) + return Out << (isSigned?"int":"uint"); // !!FIX ME + else if (NumBits <= 64) + return Out << (isSigned?"long":"ulong"); + else { + assert(NumBits <= 128 && "Bit widths > 128 not implemented yet"); + return Out << (isSigned?"int128_t":"uint128_t"); + } + } + case Type::FloatTyID: return Out << "float"; + case Type::DoubleTyID: return Out << "double"; + // 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"; + + case Type::X86_MMXTyID: + return Out << (isSigned?"int":"uint") << " __attribute__((vector_size(8)))"; + + default: #ifndef NDEBUG - errs() << "Unknown primitive type: " << *Ty << "\n"; + errs() << "Unknown primitive type: " << *Ty << "\n"; #endif - llvm_unreachable(0); + llvm_unreachable(0); } } // Pass the Type* and the variable name and this prints out the variable // declaration. // -raw_ostream & -CWriter::printTypeName(raw_ostream &Out, Type *Ty, bool isSigned, - std::pair<AttributeList, CallingConv::ID> PAL) { +raw_ostream &CWriter::printTypeName(raw_ostream &Out, Type *Ty, + bool isSigned, + std::pair<AttributeList, CallingConv::ID> PAL) { if (Ty->isSingleValueType() || Ty->isVoidTy()) { if (!Ty->isPointerTy() && !Ty->isVectorTy()) @@ -440,40 +403,39 @@ CWriter::printTypeName(raw_ostream &Out, Type *Ty, bool isSigned, return Out << "void"; switch (Ty->getTypeID()) { - case Type::FunctionTyID: { - FunctionType *FTy = cast<FunctionType>(Ty); - return Out << getFunctionName(FTy, PAL); - } - case Type::StructTyID: { - TypedefDeclTypes.insert(Ty); - return Out << getStructName(cast<StructType>(Ty)); - } - - case Type::PointerTyID: { - Type *ElTy = Ty->getPointerElementType(); - return printTypeName(Out, ElTy, false) << '*'; - } - - case Type::ArrayTyID: { - TypedefDeclTypes.insert(Ty); - return Out << getArrayName(cast<ArrayType>(Ty)); - } - - case Type::VectorTyID: { - TypedefDeclTypes.insert(Ty); - return Out << getVectorName(cast<VectorType>(Ty), true); - } + case Type::FunctionTyID: { + FunctionType *FTy = cast<FunctionType>(Ty); + return Out << getFunctionName(FTy, PAL); + } + case Type::StructTyID: { + TypedefDeclTypes.insert(Ty); + return Out << getStructName(cast<StructType>(Ty)); + } + + case Type::PointerTyID: { + Type *ElTy = Ty->getPointerElementType(); + return printTypeName(Out, ElTy, false) << '*'; + } + + case Type::ArrayTyID: { + TypedefDeclTypes.insert(Ty); + return Out << getArrayName(cast<ArrayType>(Ty)); + } + + case Type::VectorTyID: { + TypedefDeclTypes.insert(Ty); + return Out << getVectorName(cast<VectorType>(Ty), true); + } - default: + default: #ifndef NDEBUG - errs() << "Unexpected type: " << *Ty << "\n"; + errs() << "Unexpected type: " << *Ty << "\n"; #endif - llvm_unreachable(0); + llvm_unreachable(0); } } -raw_ostream &CWriter::printTypeNameUnaligned(raw_ostream &Out, Type *Ty, - bool isSigned) { +raw_ostream &CWriter::printTypeNameUnaligned(raw_ostream &Out, Type *Ty, bool isSigned) { if (VectorType *VTy = dyn_cast<VectorType>(Ty)) { // MSVC doesn't handle __declspec(align) on parameters, // but we specify it for Vector (hoping the compiler will vectorize it) @@ -484,15 +446,13 @@ raw_ostream &CWriter::printTypeNameUnaligned(raw_ostream &Out, Type *Ty, return printTypeName(Out, Ty, isSigned); } -raw_ostream &CWriter::printStructDeclaration(raw_ostream &Out, - StructType *STy) { +raw_ostream &CWriter::printStructDeclaration(raw_ostream &Out, StructType *STy) { if (STy->isPacked()) Out << "#ifdef _MSC_VER\n#pragma pack(push, 1)\n#endif\n"; Out << getStructName(STy) << " {\n"; unsigned Idx = 0; for (StructType::element_iterator I = STy->element_begin(), - E = STy->element_end(); - I != E; ++I, Idx++) { + E = STy->element_end(); I != E; ++I, Idx++) { Out << " "; bool empty = isEmptyType(*I); if (empty) @@ -512,23 +472,21 @@ raw_ostream &CWriter::printStructDeclaration(raw_ostream &Out, return Out; } -raw_ostream &CWriter::printFunctionDeclaration( - raw_ostream &Out, FunctionType *Ty, - std::pair<AttributeList, CallingConv::ID> PAL) { +raw_ostream &CWriter::printFunctionDeclaration(raw_ostream &Out, FunctionType *Ty, + std::pair<AttributeList, CallingConv::ID> PAL){ Out << "typedef "; printFunctionProto(Out, Ty, PAL, getFunctionName(Ty, PAL), NULL, false); return Out << ";\n"; } -raw_ostream & -CWriter::printFunctionProto(raw_ostream &Out, FunctionType *FTy, - std::pair<AttributeList, CallingConv::ID> Attrs, - const std::string &Name, - Function::arg_iterator ArgList, bool isKernel) { +raw_ostream &CWriter::printFunctionProto(raw_ostream &Out, FunctionType *FTy, + std::pair<AttributeList, CallingConv::ID> Attrs, + const std::string &Name, + Function::arg_iterator ArgList, + bool isKernel) { - // NOTE: AttributeSet is replaced by 'AttributeList' at function level in - // LLVM-9 + // NOTE: AttributeSet is replaced by 'AttributeList' at function level in LLVM-9 AttributeList &PAL = Attrs.first; if (PAL.hasAttribute(AttributeList::FunctionIndex, Attribute::NoReturn)) @@ -539,7 +497,7 @@ CWriter::printFunctionProto(raw_ostream &Out, FunctionType *FTy, // Should this function actually return a struct by-value? bool isStructReturn = PAL.hasAttribute(1, Attribute::StructRet) || - PAL.hasAttribute(2, Attribute::StructRet); + PAL.hasAttribute(2, Attribute::StructRet); // Get the return type for the function. Type *RetTy; if (!isStructReturn) @@ -549,25 +507,24 @@ CWriter::printFunctionProto(raw_ostream &Out, FunctionType *FTy, RetTy = cast<PointerType>(FTy->getParamType(0))->getElementType(); } printTypeName(Out, RetTy, - /*isSigned=*/ - PAL.hasAttribute(AttributeList::ReturnIndex, Attribute::SExt)); + /*isSigned=*/PAL.hasAttribute(AttributeList::ReturnIndex, Attribute::SExt)); Out << "/* Processing Function: " << Name << ": " << Attrs.second << "*/\n"; switch (Attrs.second) { - case CallingConv::C: - break; - case CallingConv::X86_StdCall: - Out << " __stdcall"; - break; - case CallingConv::X86_FastCall: - Out << " __fastcall"; - break; - case CallingConv::X86_ThisCall: - Out << " __thiscall"; - break; - default: - // assert(0 && "Encountered Unhandled Calling Convention"); - break; + case CallingConv::C: + break; + case CallingConv::X86_StdCall: + Out << " __stdcall"; + break; + case CallingConv::X86_FastCall: + Out << " __fastcall"; + break; + case CallingConv::X86_ThisCall: + Out << " __thiscall"; + break; + default: + // assert(0 && "Encountered Unhandled Calling Convention"); + break; } Out << ' ' << Name << '('; @@ -575,8 +532,7 @@ CWriter::printFunctionProto(raw_ostream &Out, FunctionType *FTy, bool PrintedArg = false; FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end(); - // Function::arg_iterator ArgName = ArgList ? ArgList->begin() : - // Function::arg_iterator(); + //Function::arg_iterator ArgName = ArgList ? ArgList->begin() : Function::arg_iterator(); // NOTE: ArgumentLists not supported in LLVM-9 Function::arg_iterator ArgName = ArgList ? ArgList : Function::arg_iterator(); @@ -587,10 +543,8 @@ CWriter::printFunctionProto(raw_ostream &Out, FunctionType *FTy, assert(I != E && "Invalid struct return function!"); ++I; ++Idx; - // CHECK: very confused as to how next loop starts from first Function - // Param? - if (ArgList) - ++ArgName; + // CHECK: very confused as to how next loop starts from first Function Param? + if (ArgList) ++ArgName; } for (; I != E; ++I) { @@ -604,27 +558,27 @@ CWriter::printFunctionProto(raw_ostream &Out, FunctionType *FTy, if (PointerType *PTy = dyn_cast<PointerType>(ArgTy)) { unsigned AddrSpace = PTy->getAddressSpace(); - // DEBUG(errs() << "AddrSpace for " << Idx << " = " << AddrSpace << "\n"); - switch (AddrSpace) { - case GLOBAL_ADDRSPACE: - Out << "__global "; - break; - case SHARED_ADDRSPACE: - Out << "__local "; - break; - case CONSTANT_ADDRSPACE: - Out << "__constant "; - break; - case PRIVATE_ADDRSPACE: - Out << "__private "; - break; - default: - break; + DEBUG(errs() << "AddrSpace for " << Idx << " = " << AddrSpace << "\n"); + switch(AddrSpace) { + case GLOBAL_ADDRSPACE: + Out << "__global "; + break; + case SHARED_ADDRSPACE: + Out << "__local "; + break; + case CONSTANT_ADDRSPACE: + Out << "__constant "; + break; + case PRIVATE_ADDRSPACE: + Out << "__private "; + break; + default: + break; } } printTypeNameUnaligned(Out, ArgTy, - /*isSigned=*/PAL.hasAttribute(Idx, Attribute::SExt)); + /*isSigned=*/PAL.hasAttribute(Idx, Attribute::SExt)); PrintedArg = true; bool noalias = false; if (PAL.hasAttribute(Idx, Attribute::NoAlias)) { @@ -633,16 +587,15 @@ CWriter::printFunctionProto(raw_ostream &Out, FunctionType *FTy, ++Idx; if (ArgList) { - Out << ' ' << (noalias ? " restrict " : "") << GetValueName(&*ArgName); + Out << ' ' << (noalias ? " restrict " : "") << GetValueName(&*ArgName); ++ArgName; } } if (FTy->isVarArg()) { if (!PrintedArg) { - Out << "int"; // dummy argument for empty vaarg functs - if (ArgList) - Out << " vararg_dummy_arg"; + Out << "int"; //dummy argument for empty vaarg functs + if (ArgList) Out << " vararg_dummy_arg"; } Out << ", ..."; } else if (!PrintedArg) { @@ -662,20 +615,16 @@ raw_ostream &CWriter::printArrayDeclaration(raw_ostream &Out, ArrayType *ATy) { return Out; } -raw_ostream &CWriter::printVectorDeclaration(raw_ostream &Out, - VectorType *VTy) { +raw_ostream &CWriter::printVectorDeclaration(raw_ostream &Out, VectorType *VTy) { assert(!isEmptyType(VTy)); // Vectors are printed like arrays Out << getVectorName(VTy, false) << " {\n "; printTypeName(Out, VTy->getElementType()); - Out << " vector[" << utostr(VTy->getNumElements()) - << "];\n} __attribute__((aligned(" << TD->getABITypeAlignment(VTy) - << ")));\n"; + Out << " vector[" << utostr(VTy->getNumElements()) << "];\n} __attribute__((aligned(" << TD->getABITypeAlignment(VTy) << ")));\n"; return Out; } -void CWriter::printConstantArray(ConstantArray *CPA, - enum OperandContext Context) { +void CWriter::printConstantArray(ConstantArray *CPA, enum OperandContext Context) { printConstant(cast<Constant>(CPA->getOperand(0)), Context); for (unsigned i = 1, e = CPA->getNumOperands(); i != e; ++i) { Out << ", "; @@ -683,8 +632,7 @@ void CWriter::printConstantArray(ConstantArray *CPA, } } -void CWriter::printConstantVector(ConstantVector *CP, - enum OperandContext Context) { +void CWriter::printConstantVector(ConstantVector *CP, enum OperandContext Context) { printConstant(cast<Constant>(CP->getOperand(0)), Context); for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) { Out << ", "; @@ -692,8 +640,7 @@ void CWriter::printConstantVector(ConstantVector *CP, } } -void CWriter::printConstantDataSequential(ConstantDataSequential *CDS, - enum OperandContext Context) { +void CWriter::printConstantDataSequential(ConstantDataSequential *CDS, enum OperandContext Context) { printConstant(CDS->getElementAsConstant(0), Context); for (unsigned i = 1, e = CDS->getNumElements(); i != e; ++i) { Out << ", "; @@ -705,10 +652,8 @@ bool CWriter::printConstantString(Constant *C, enum OperandContext Context) { // 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. ConstantDataSequential *CDS = dyn_cast<ConstantDataSequential>(C); - if (!CDS || !CDS->isCString()) - return false; - if (Context != ContextStatic) - return false; // TODO + if (!CDS || !CDS->isCString()) return false; + if (Context != ContextStatic) return false; // TODO Out << "{ \""; // Keep track of whether the last number was a hexadecimal escape. @@ -735,34 +680,19 @@ bool CWriter::printConstantString(Constant *C, enum OperandContext Context) { } else { LastWasHex = false; switch (C) { - case '\n': - Out << "\\n"; - break; - case '\t': - Out << "\\t"; - break; - case '\r': - Out << "\\r"; - break; - case '\v': - Out << "\\v"; - break; - case '\a': - Out << "\\a"; - break; - case '\"': - Out << "\\\""; - break; - case '\'': - Out << "\\\'"; - break; - default: - Out << "\\x"; - Out << (char)((C / 16 < 10) ? (C / 16 + '0') : (C / 16 - 10 + 'A')); - Out << (char)(((C & 15) < 10) ? ((C & 15) + '0') - : ((C & 15) - 10 + 'A')); - LastWasHex = true; - break; + case '\n': Out << "\\n"; break; + case '\t': Out << "\\t"; break; + case '\r': Out << "\\r"; break; + case '\v': Out << "\\v"; break; + case '\a': Out << "\\a"; break; + case '\"': Out << "\\\""; break; + case '\'': Out << "\\\'"; break; + default: + Out << "\\x"; + Out << (char)(( C/16 < 10) ? ( C/16 +'0') : ( C/16 -10+'A')); + Out << (char)(((C&15) < 10) ? ((C&15)+'0') : ((C&15)-10+'A')); + LastWasHex = true; + break; } } } @@ -770,6 +700,7 @@ bool CWriter::printConstantString(Constant *C, enum OperandContext Context) { return true; } + // isFPCSafeToPrint - Returns true if we may assume that CFP may be written out // textually as a double (rather than as a reference to a stack-allocated // variable). We decide this by converting CFP to a string and back into a @@ -780,7 +711,7 @@ bool CWriter::printConstantString(Constant *C, enum OperandContext Context) { // // TODO copied from CppBackend, new code should use raw_ostream -static inline std::string ftostr(const APFloat &V) { +static inline std::string ftostr(const APFloat& V) { std::string Buf; if (&V.getSemantics() == &APFloat::IEEEdouble()) { raw_string_ostream(Buf) << V.convertToDouble(); @@ -798,13 +729,14 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) { if (CFP->getType() != Type::getFloatTy(CFP->getContext()) && CFP->getType() != Type::getDoubleTy(CFP->getContext())) return false; - APFloat APF = APFloat(CFP->getValueAPF()); // copy + APFloat APF = APFloat(CFP->getValueAPF()); // copy if (CFP->getType() == Type::getFloatTy(CFP->getContext())) APF.convert(APFloat::IEEEdouble(), APFloat::rmNearestTiesToEven, &ignored); #if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A char Buffer[100]; sprintf(Buffer, "%a", APF.convertToDouble()); - if (!strncmp(Buffer, "0x", 2) || !strncmp(Buffer, "-0x", 3) || + if (!strncmp(Buffer, "0x", 2) || + !strncmp(Buffer, "-0x", 3) || !strncmp(Buffer, "+0x", 3)) return APF.bitwiseIsEqual(APFloat(atof(Buffer))); return false; @@ -831,249 +763,211 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) { void CWriter::printCast(unsigned opc, Type *SrcTy, Type *DstTy) { // Print the destination type cast switch (opc) { - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::IntToPtr: - case Instruction::Trunc: - case Instruction::BitCast: - case Instruction::FPExt: - case Instruction::FPTrunc: // For these the DstTy sign doesn't matter - Out << '('; - printTypeName(Out, DstTy); - Out << ')'; - break; - case Instruction::ZExt: - case Instruction::PtrToInt: - case Instruction::FPToUI: // For these, make sure we get an unsigned dest - Out << '('; - printSimpleType(Out, DstTy, false); - Out << ')'; - break; - case Instruction::SExt: - case Instruction::FPToSI: // For these, make sure we get a signed dest - Out << '('; - printSimpleType(Out, DstTy, true); - Out << ')'; - break; - default: - llvm_unreachable("Invalid cast opcode"); + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::IntToPtr: + case Instruction::Trunc: + case Instruction::BitCast: + case Instruction::FPExt: + case Instruction::FPTrunc: // For these the DstTy sign doesn't matter + Out << '('; + printTypeName(Out, DstTy); + Out << ')'; + break; + case Instruction::ZExt: + case Instruction::PtrToInt: + case Instruction::FPToUI: // For these, make sure we get an unsigned dest + Out << '('; + printSimpleType(Out, DstTy, false); + Out << ')'; + break; + case Instruction::SExt: + case Instruction::FPToSI: // For these, make sure we get a signed dest + Out << '('; + printSimpleType(Out, DstTy, true); + Out << ')'; + break; + default: + llvm_unreachable("Invalid cast opcode"); } // Print the source type cast switch (opc) { - case Instruction::UIToFP: - case Instruction::ZExt: - Out << '('; - printSimpleType(Out, SrcTy, false); - Out << ')'; - break; - case Instruction::SIToFP: - case Instruction::SExt: - Out << '('; - printSimpleType(Out, SrcTy, true); - Out << ')'; - break; - case Instruction::IntToPtr: - case Instruction::PtrToInt: - // Avoid "cast to pointer from integer of different size" warnings - Out << "(uintptr_t)"; - break; - case Instruction::Trunc: - case Instruction::BitCast: - case Instruction::FPExt: - case Instruction::FPTrunc: - case Instruction::FPToSI: - case Instruction::FPToUI: - break; // These don't need a source cast. - default: - llvm_unreachable("Invalid cast opcode"); + case Instruction::UIToFP: + case Instruction::ZExt: + Out << '('; + printSimpleType(Out, SrcTy, false); + Out << ')'; + break; + case Instruction::SIToFP: + case Instruction::SExt: + Out << '('; + printSimpleType(Out, SrcTy, true); + Out << ')'; + break; + case Instruction::IntToPtr: + case Instruction::PtrToInt: + // Avoid "cast to pointer from integer of different size" warnings + Out << "(uintptr_t)"; + break; + case Instruction::Trunc: + case Instruction::BitCast: + case Instruction::FPExt: + case Instruction::FPTrunc: + case Instruction::FPToSI: + case Instruction::FPToUI: + break; // These don't need a source cast. + default: + llvm_unreachable("Invalid cast opcode"); } } // printConstant - The LLVM Constant to C Constant converter. void CWriter::printConstant(Constant *CPV, enum OperandContext Context) { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(CPV)) { - assert(CE->getType()->isIntegerTy() || CE->getType()->isFloatingPointTy() || - CE->getType()->isPointerTy()); // TODO: VectorType are valid here, - // but not supported + assert(CE->getType()->isIntegerTy() || CE->getType()->isFloatingPointTy() || CE->getType()->isPointerTy()); // TODO: VectorType are valid here, but not supported GetElementPtrInst *GEPI; switch (CE->getOpcode()) { - case Instruction::Trunc: - case Instruction::ZExt: - case Instruction::SExt: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPToUI: - case Instruction::FPToSI: - case Instruction::PtrToInt: - case Instruction::IntToPtr: - case Instruction::BitCast: - Out << "("; - printCast(CE->getOpcode(), CE->getOperand(0)->getType(), CE->getType()); - if (CE->getOpcode() == Instruction::SExt && - CE->getOperand(0)->getType() == Type::getInt1Ty(CPV->getContext())) { - // Make sure we really sext from bool here by subtracting from 0 - Out << "0-"; - } - printConstant(CE->getOperand(0), ContextCasted); - if (CE->getType() == Type::getInt1Ty(CPV->getContext()) && - (CE->getOpcode() == Instruction::Trunc || - CE->getOpcode() == Instruction::FPToUI || - CE->getOpcode() == Instruction::FPToSI || - CE->getOpcode() == Instruction::PtrToInt)) { - // Make sure we really truncate to bool here by anding with 1 - Out << "&1u"; - } - Out << ')'; - return; + case Instruction::Trunc: + case Instruction::ZExt: + case Instruction::SExt: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::BitCast: + Out << "("; + printCast(CE->getOpcode(), CE->getOperand(0)->getType(), CE->getType()); + if (CE->getOpcode() == Instruction::SExt && + CE->getOperand(0)->getType() == Type::getInt1Ty(CPV->getContext())) { + // Make sure we really sext from bool here by subtracting from 0 + Out << "0-"; + } + printConstant(CE->getOperand(0), ContextCasted); + if (CE->getType() == Type::getInt1Ty(CPV->getContext()) && + (CE->getOpcode() == Instruction::Trunc || + CE->getOpcode() == Instruction::FPToUI || + CE->getOpcode() == Instruction::FPToSI || + CE->getOpcode() == Instruction::PtrToInt)) { + // Make sure we really truncate to bool here by anding with 1 + Out << "&1u"; + } + Out << ')'; + return; - case Instruction::GetElementPtr: - Out << "("; - // DEBUG(errs() << "\n----------\nCE: " << *CE << "\n"); - GEPI = dyn_cast<GetElementPtrInst>(CE->getAsInstruction()); - // DEBUG(errs() << "GEPI: " << *GEPI << "\n"); - printGEPExpression(CE->getOperand(0), gep_type_begin(CPV), - gep_type_end(CPV), - CE->getOperand(0)->getType()->isArrayTy(), GEPI); - delete (GEPI); - // DEBUG(errs() << "Deleted GEPI!\n"); - Out << ")"; - return; - case Instruction::Select: - Out << '('; - printConstant(CE->getOperand(0), ContextCasted); - Out << '?'; - printConstant(CE->getOperand(1), ContextNormal); - Out << ':'; - printConstant(CE->getOperand(2), ContextNormal); - Out << ')'; - return; - case Instruction::Add: - case Instruction::FAdd: - case Instruction::Sub: - case Instruction::FSub: - case Instruction::Mul: - case Instruction::FMul: - case Instruction::SDiv: - case Instruction::UDiv: - case Instruction::FDiv: - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - case Instruction::And: - case Instruction::Or: - case Instruction::Xor: - case Instruction::ICmp: - case Instruction::Shl: - case Instruction::LShr: - case Instruction::AShr: { - Out << '('; - bool NeedsClosingParens = printConstExprCast(CE); - printConstantWithCast(CE->getOperand(0), CE->getOpcode()); - switch (CE->getOpcode()) { + case Instruction::GetElementPtr: + Out << "("; + DEBUG(errs() << "\n----------\nCE: " << *CE << "\n"); + GEPI = dyn_cast<GetElementPtrInst>(CE->getAsInstruction()); + DEBUG(errs() << "GEPI: " << *GEPI << "\n"); + printGEPExpression(CE->getOperand(0), gep_type_begin(CPV), gep_type_end(CPV), CE->getOperand(0)->getType()->isArrayTy(), GEPI); + delete(GEPI); + DEBUG(errs() << "Deleted GEPI!\n"); + Out << ")"; + return; + case Instruction::Select: + Out << '('; + printConstant(CE->getOperand(0), ContextCasted); + Out << '?'; + printConstant(CE->getOperand(1), ContextNormal); + Out << ':'; + printConstant(CE->getOperand(2), ContextNormal); + Out << ')'; + return; case Instruction::Add: case Instruction::FAdd: - Out << " + "; - break; case Instruction::Sub: case Instruction::FSub: - Out << " - "; - break; case Instruction::Mul: case Instruction::FMul: - Out << " * "; - break; + case Instruction::SDiv: + case Instruction::UDiv: + case Instruction::FDiv: case Instruction::URem: case Instruction::SRem: case Instruction::FRem: - Out << " % "; - break; - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::FDiv: - Out << " / "; - break; case Instruction::And: - Out << " & "; - break; case Instruction::Or: - Out << " | "; - break; case Instruction::Xor: - Out << " ^ "; - break; + case Instruction::ICmp: case Instruction::Shl: - Out << " << "; - break; case Instruction::LShr: case Instruction::AShr: - Out << " >> "; - break; - case Instruction::ICmp: - switch (CE->getPredicate()) { - case ICmpInst::ICMP_EQ: - Out << " == "; - break; - case ICmpInst::ICMP_NE: - Out << " != "; - break; - case ICmpInst::ICMP_SLT: - case ICmpInst::ICMP_ULT: - Out << " < "; - break; - case ICmpInst::ICMP_SLE: - case ICmpInst::ICMP_ULE: - Out << " <= "; - break; - case ICmpInst::ICMP_SGT: - case ICmpInst::ICMP_UGT: - Out << " > "; - break; - case ICmpInst::ICMP_SGE: - case ICmpInst::ICMP_UGE: - Out << " >= "; - break; - default: - llvm_unreachable("Illegal ICmp predicate"); + { + Out << '('; + bool NeedsClosingParens = printConstExprCast(CE); + printConstantWithCast(CE->getOperand(0), CE->getOpcode()); + switch (CE->getOpcode()) { + case Instruction::Add: + case Instruction::FAdd: Out << " + "; break; + case Instruction::Sub: + case Instruction::FSub: Out << " - "; break; + case Instruction::Mul: + case Instruction::FMul: Out << " * "; break; + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: Out << " % "; break; + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: Out << " / "; break; + case Instruction::And: Out << " & "; break; + case Instruction::Or: Out << " | "; break; + case Instruction::Xor: Out << " ^ "; break; + case Instruction::Shl: Out << " << "; break; + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; + case Instruction::ICmp: + switch (CE->getPredicate()) { + case ICmpInst::ICMP_EQ: Out << " == "; break; + case ICmpInst::ICMP_NE: Out << " != "; break; + case ICmpInst::ICMP_SLT: + case ICmpInst::ICMP_ULT: Out << " < "; break; + case ICmpInst::ICMP_SLE: + case ICmpInst::ICMP_ULE: Out << " <= "; break; + case ICmpInst::ICMP_SGT: + case ICmpInst::ICMP_UGT: Out << " > "; break; + case ICmpInst::ICMP_SGE: + case ICmpInst::ICMP_UGE: Out << " >= "; break; + default: llvm_unreachable("Illegal ICmp predicate"); + } + break; + default: llvm_unreachable("Illegal opcode here!"); + } + printConstantWithCast(CE->getOperand(1), CE->getOpcode()); + if (NeedsClosingParens) + Out << "))"; + Out << ')'; + return; } - break; + case Instruction::FCmp: { + Out << '('; + bool NeedsClosingParens = printConstExprCast(CE); + if (CE->getPredicate() == FCmpInst::FCMP_FALSE) + Out << "0"; + else if (CE->getPredicate() == FCmpInst::FCMP_TRUE) + Out << "1"; + else { + Out << "llvm_fcmp_" << getCmpPredicateName((CmpInst::Predicate)CE->getPredicate()) << "("; + printConstant(CE->getOperand(0), ContextCasted); + Out << ", "; + printConstant(CE->getOperand(1), ContextCasted); + Out << ")"; + } + if (NeedsClosingParens) + Out << "))"; + Out << ')'; + return; + } default: - llvm_unreachable("Illegal opcode here!"); - } - printConstantWithCast(CE->getOperand(1), CE->getOpcode()); - if (NeedsClosingParens) - Out << "))"; - Out << ')'; - return; - } - case Instruction::FCmp: { - Out << '('; - bool NeedsClosingParens = printConstExprCast(CE); - if (CE->getPredicate() == FCmpInst::FCMP_FALSE) - Out << "0"; - else if (CE->getPredicate() == FCmpInst::FCMP_TRUE) - Out << "1"; - else { - Out << "llvm_fcmp_" - << getCmpPredicateName((CmpInst::Predicate)CE->getPredicate()) - << "("; - printConstant(CE->getOperand(0), ContextCasted); - Out << ", "; - printConstant(CE->getOperand(1), ContextCasted); - Out << ")"; - } - if (NeedsClosingParens) - Out << "))"; - Out << ')'; - return; - } - default: #ifndef NDEBUG - errs() << "CWriter Error: Unhandled constant expression: " << *CE << "\n"; + errs() << "CWriter Error: Unhandled constant expression: " + << *CE << "\n"; #endif - llvm_unreachable(0); + llvm_unreachable(0); } } else if (isa<UndefValue>(CPV) && CPV->getType()->isSingleValueType()) { if (CPV->getType()->isVectorTy()) { @@ -1090,8 +984,7 @@ void CWriter::printConstant(Constant *CPV, enum OperandContext Context) { Constant *Zero = Constant::getNullValue(VT->getElementType()); unsigned NumElts = VT->getNumElements(); for (unsigned i = 0; i != NumElts; ++i) { - if (i) - Out << ", "; + if (i) Out << ", "; printConstant(Zero, ContextCasted); } Out << ")"; @@ -1105,10 +998,9 @@ void CWriter::printConstant(Constant *CPV, enum OperandContext Context) { } if (ConstantInt *CI = dyn_cast<ConstantInt>(CPV)) { - Type *Ty = CI->getType(); + Type* Ty = CI->getType(); unsigned ActiveBits = CI->getValue().getMinSignedBits(); - // DEBUG(errs() << "Here: " << *CI << ", " << *Ty << ", " << ActiveBits - // << "\n"); + DEBUG(errs() << "Here: " << *CI << ", " << *Ty << ", " << ActiveBits << "\n"); Out << CI->getSExtValue(); // if (Ty == Type::getInt1Ty(CPV->getContext())) { // Out << (CI->getZExtValue() ? '1' : '0'); @@ -1121,8 +1013,7 @@ void CWriter::printConstant(Constant *CPV, enum OperandContext Context) { // Out << CI->getSExtValue(); // most likely a shorter representation //// if (ActiveBits >= 32) //// Out << ")"; - // } else if (Ty->getPrimitiveSizeInBits() < 32 && Context == - // ContextNormal) { + // } else if (Ty->getPrimitiveSizeInBits() < 32 && Context == ContextNormal) { // Out << "(("; // printSimpleType(Out, Ty, false) << ')'; // if (CI->isMinValue(true)) @@ -1139,287 +1030,267 @@ void CWriter::printConstant(Constant *CPV, enum OperandContext Context) { //// const APInt &V = CI->getValue(); //// const APInt &Vlo = V.getLoBits(64); //// const APInt &Vhi = V.getHiBits(64); - //// Out << (Context == ContextStatic ? "UINT128_C" : - ///"llvm_ctor_u128"); / Out << "(UINT64_C(" << Vhi.getZExtValue() << - ///"), UINT64_C(" << Vlo.getZExtValue() << "))"; + //// Out << (Context == ContextStatic ? "UINT128_C" : "llvm_ctor_u128"); + //// Out << "(UINT64_C(" << Vhi.getZExtValue() << "), UINT64_C(" << Vlo.getZExtValue() << "))"; // } return; } switch (CPV->getType()->getTypeID()) { - case Type::FloatTyID: - case Type::DoubleTyID: - case Type::X86_FP80TyID: - case Type::PPC_FP128TyID: - case Type::FP128TyID: { - ConstantFP *FPC = cast<ConstantFP>(CPV); - std::map<const ConstantFP *, unsigned>::iterator I = - FPConstantMap.find(FPC); - if (I != FPConstantMap.end()) { - // Because of FP precision problems we must load from a stack allocated - // value that holds the value in hex. - Out << "(*(" - << (FPC->getType() == Type::getFloatTy(CPV->getContext()) - ? "float" - : FPC->getType() == Type::getDoubleTy(CPV->getContext()) - ? "double" - : "long double") - << "*)&FPConstant" << I->second << ')'; - } else { - double V; - if (FPC->getType() == Type::getFloatTy(CPV->getContext())) - V = FPC->getValueAPF().convertToFloat(); - else if (FPC->getType() == Type::getDoubleTy(CPV->getContext())) - V = FPC->getValueAPF().convertToDouble(); - else { - // Long double. Convert the number to double, discarding precision. - // This is not awesome, but it at least makes the CBE output somewhat - // useful. - APFloat Tmp = FPC->getValueAPF(); - bool LosesInfo; - Tmp.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo); - V = Tmp.convertToDouble(); - } - - if (std::isnan(V)) { - // The value is NaN - - // FIXME the actual NaN bits should be emitted. - // The prefix for a quiet NaN is 0x7FF8. For a signalling NaN, - // it's 0x7ff4. - const unsigned long QuietNaN = 0x7ff8UL; - // const unsigned long SignalNaN = 0x7ff4UL; - - // We need to grab the first part of the FP # - char Buffer[100]; - - uint64_t ll = DoubleToBits(V); - sprintf(Buffer, "0x%llx", static_cast<long long>(ll)); - - std::string Num(&Buffer[0], &Buffer[6]); - unsigned long Val = strtoul(Num.c_str(), 0, 16); - - if (FPC->getType() == Type::getFloatTy(FPC->getContext())) - Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "F(\"" << Buffer - << "\") /*nan*/ "; - else - Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "(\"" << Buffer - << "\") /*nan*/ "; - } else if (std::isinf(V)) { - // The value is Inf - if (V < 0) - Out << '-'; - Out << "LLVM_INF" - << (FPC->getType() == Type::getFloatTy(FPC->getContext()) ? "F" - : "") - << " /*inf*/ "; - } else { - std::string Num; + case Type::FloatTyID: + case Type::DoubleTyID: + case Type::X86_FP80TyID: + case Type::PPC_FP128TyID: + case Type::FP128TyID: { + ConstantFP *FPC = cast<ConstantFP>(CPV); + std::map<const ConstantFP*, unsigned>::iterator I = FPConstantMap.find(FPC); + if (I != FPConstantMap.end()) { + // Because of FP precision problems we must load from a stack allocated + // value that holds the value in hex. + Out << "(*(" << (FPC->getType() == Type::getFloatTy(CPV->getContext()) ? + "float" : + FPC->getType() == Type::getDoubleTy(CPV->getContext()) ? + "double" : + "long double") + << "*)&FPConstant" << I->second << ')'; + } else { + double V; + if (FPC->getType() == Type::getFloatTy(CPV->getContext())) + V = FPC->getValueAPF().convertToFloat(); + else if (FPC->getType() == Type::getDoubleTy(CPV->getContext())) + V = FPC->getValueAPF().convertToDouble(); + else { + // Long double. Convert the number to double, discarding precision. + // This is not awesome, but it at least makes the CBE output somewhat + // useful. + APFloat Tmp = FPC->getValueAPF(); + bool LosesInfo; + Tmp.convert(APFloat::IEEEdouble(), APFloat::rmTowardZero, &LosesInfo); + V = Tmp.convertToDouble(); + } + + if (std::isnan(V)) { + // The value is NaN + + // FIXME the actual NaN bits should be emitted. + // The prefix for a quiet NaN is 0x7FF8. For a signalling NaN, + // it's 0x7ff4. + const unsigned long QuietNaN = 0x7ff8UL; + //const unsigned long SignalNaN = 0x7ff4UL; + + // We need to grab the first part of the FP # + char Buffer[100]; + + uint64_t ll = DoubleToBits(V); + sprintf(Buffer, "0x%llx", static_cast<long long>(ll)); + + std::string Num(&Buffer[0], &Buffer[6]); + unsigned long Val = strtoul(Num.c_str(), 0, 16); + + if (FPC->getType() == Type::getFloatTy(FPC->getContext())) + Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "F(\"" + << Buffer << "\") /*nan*/ "; + else + Out << "LLVM_NAN" << (Val == QuietNaN ? "" : "S") << "(\"" + << Buffer << "\") /*nan*/ "; + } else if (std::isinf(V)) { + // The value is Inf + if (V < 0) Out << '-'; + Out << "LLVM_INF" << + (FPC->getType() == Type::getFloatTy(FPC->getContext()) ? "F" : "") + << " /*inf*/ "; + } else { + std::string Num; #if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A - // Print out the constant as a floating point number. - char Buffer[100]; - sprintf(Buffer, "%a", V); - Num = Buffer; + // Print out the constant as a floating point number. + char Buffer[100]; + sprintf(Buffer, "%a", V); + Num = Buffer; #else - Num = ftostr(FPC->getValueAPF()); + Num = ftostr(FPC->getValueAPF()); #endif - Out << Num; - } - } - break; - } - - case Type::ArrayTyID: { - if (printConstantString(CPV, Context)) - break; - ArrayType *AT = cast<ArrayType>(CPV->getType()); - assert(AT->getNumElements() != 0 && !isEmptyType(AT)); - if (Context != ContextStatic) { - CtorDeclTypes.insert(AT); - Out << "llvm_ctor_"; - printTypeString(Out, AT, false); - Out << "("; - Context = ContextCasted; - } else { - Out << "{ { "; // Arrays are wrapped in struct types. - } - if (ConstantArray *CA = dyn_cast<ConstantArray>(CPV)) { - printConstantArray(CA, Context); - } else if (ConstantDataSequential *CDS = - dyn_cast<ConstantDataSequential>(CPV)) { - printConstantDataSequential(CDS, Context); - } else { - assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)); - Constant *CZ = Constant::getNullValue(AT->getElementType()); - printConstant(CZ, Context); - for (unsigned i = 1, e = AT->getNumElements(); i != e; ++i) { - Out << ", "; - printConstant(CZ, Context); - } - } - Out << (Context == ContextStatic - ? " } }" - : ")"); // Arrays are wrapped in struct types. - break; - } - - case Type::VectorTyID: { - VectorType *VT = cast<VectorType>(CPV->getType()); - assert(VT->getNumElements() != 0 && !isEmptyType(VT)); - if (Context != ContextStatic) { - CtorDeclTypes.insert(VT); - Out << "llvm_ctor_"; - printTypeString(Out, VT, false); - Out << "("; - Context = ContextCasted; - } else { - Out << "{ "; - } - if (ConstantVector *CV = dyn_cast<ConstantVector>(CPV)) { - printConstantVector(CV, Context); - } else if (ConstantDataSequential *CDS = - dyn_cast<ConstantDataSequential>(CPV)) { - printConstantDataSequential(CDS, Context); - } else { - assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)); - Constant *CZ = Constant::getNullValue(VT->getElementType()); - printConstant(CZ, Context); - for (unsigned i = 1, e = VT->getNumElements(); i != e; ++i) { - Out << ", "; - printConstant(CZ, Context); - } - } - Out << (Context == ContextStatic ? " }" : ")"); - break; - } - - case Type::StructTyID: { - StructType *ST = cast<StructType>(CPV->getType()); - assert(!isEmptyType(ST)); - if (Context != ContextStatic) { - CtorDeclTypes.insert(ST); - Out << "llvm_ctor_"; - printTypeString(Out, ST, false); - Out << "("; - Context = ContextCasted; - } else { - Out << "{ "; - } - - if (isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)) { - bool printed = false; - for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { - Type *ElTy = ST->getElementType(i); - if (isEmptyType(ElTy)) - continue; - if (printed) - Out << ", "; - printConstant(Constant::getNullValue(ElTy), Context); - printed = true; - } - assert(printed); - } else { - bool printed = false; - for (unsigned i = 0, e = CPV->getNumOperands(); i != e; ++i) { - Constant *C = cast<Constant>(CPV->getOperand(i)); - if (isEmptyType(C->getType())) - continue; - if (printed) - Out << ", "; - printConstant(C, Context); - printed = true; - } - assert(printed); - } - Out << (Context == ContextStatic ? " }" : ")"); - break; - } - - case Type::PointerTyID: - if (isa<ConstantPointerNull>(CPV)) { - Out << "(("; - printTypeName(Out, CPV->getType()); // sign doesn't matter - Out << ")/*NULL*/0)"; - break; - } else if (GlobalValue *GV = dyn_cast<GlobalValue>(CPV)) { - writeOperand(GV); - break; - } - // FALL THROUGH - default: + Out << Num; + } + } + break; + } + + case Type::ArrayTyID: { + if (printConstantString(CPV, Context)) break; + ArrayType *AT = cast<ArrayType>(CPV->getType()); + assert(AT->getNumElements() != 0 && !isEmptyType(AT)); + if (Context != ContextStatic) { + CtorDeclTypes.insert(AT); + Out << "llvm_ctor_"; + printTypeString(Out, AT, false); + Out << "("; + Context = ContextCasted; + } else { + Out << "{ { "; // Arrays are wrapped in struct types. + } + if (ConstantArray *CA = dyn_cast<ConstantArray>(CPV)) { + printConstantArray(CA, Context); + } else if (ConstantDataSequential *CDS = + dyn_cast<ConstantDataSequential>(CPV)) { + printConstantDataSequential(CDS, Context); + } else { + assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)); + Constant *CZ = Constant::getNullValue(AT->getElementType()); + printConstant(CZ, Context); + for (unsigned i = 1, e = AT->getNumElements(); i != e; ++i) { + Out << ", "; + printConstant(CZ, Context); + } + } + Out << (Context == ContextStatic ? " } }" : ")"); // Arrays are wrapped in struct types. + break; + } + + case Type::VectorTyID: { + VectorType *VT = cast<VectorType>(CPV->getType()); + assert(VT->getNumElements() != 0 && !isEmptyType(VT)); + if (Context != ContextStatic) { + CtorDeclTypes.insert(VT); + Out << "llvm_ctor_"; + printTypeString(Out, VT, false); + Out << "("; + Context = ContextCasted; + } else { + Out << "{ "; + } + if (ConstantVector *CV = dyn_cast<ConstantVector>(CPV)) { + printConstantVector(CV, Context); + } else if (ConstantDataSequential *CDS = + dyn_cast<ConstantDataSequential>(CPV)) { + printConstantDataSequential(CDS, Context); + } else { + assert(isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)); + Constant *CZ = Constant::getNullValue(VT->getElementType()); + printConstant(CZ, Context); + for (unsigned i = 1, e = VT->getNumElements(); i != e; ++i) { + Out << ", "; + printConstant(CZ, Context); + } + } + Out << (Context == ContextStatic ? " }" : ")"); + break; + } + + case Type::StructTyID: { + StructType *ST = cast<StructType>(CPV->getType()); + assert(!isEmptyType(ST)); + if (Context != ContextStatic) { + CtorDeclTypes.insert(ST); + Out << "llvm_ctor_"; + printTypeString(Out, ST, false); + Out << "("; + Context = ContextCasted; + } else { + Out << "{ "; + } + + if (isa<ConstantAggregateZero>(CPV) || isa<UndefValue>(CPV)) { + bool printed = false; + for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) { + Type *ElTy = ST->getElementType(i); + if (isEmptyType(ElTy)) continue; + if (printed) Out << ", "; + printConstant(Constant::getNullValue(ElTy), Context); + printed = true; + } + assert(printed); + } else { + bool printed = false; + for (unsigned i = 0, e = CPV->getNumOperands(); i != e; ++i) { + Constant *C = cast<Constant>(CPV->getOperand(i)); + if (isEmptyType(C->getType())) continue; + if (printed) Out << ", "; + printConstant(C, Context); + printed = true; + } + assert(printed); + } + Out << (Context == ContextStatic ? " }" : ")"); + break; + } + + case Type::PointerTyID: + if (isa<ConstantPointerNull>(CPV)) { + Out << "(("; + printTypeName(Out, CPV->getType()); // sign doesn't matter + Out << ")/*NULL*/0)"; + break; + } else if (GlobalValue *GV = dyn_cast<GlobalValue>(CPV)) { + writeOperand(GV); + break; + } + // FALL THROUGH + default: #ifndef NDEBUG - errs() << "Unknown constant type: " << *CPV << "\n"; + errs() << "Unknown constant type: " << *CPV << "\n"; #endif - llvm_unreachable(0); + llvm_unreachable(0); } } // Some constant expressions need to be casted back to the original types // because their operands were casted to the expected type. This function takes // care of detecting that case and printing the cast for the ConstantExpr. -bool CWriter::printConstExprCast(ConstantExpr *CE) { +bool CWriter::printConstExprCast(ConstantExpr* CE) { bool NeedsExplicitCast = false; Type *Ty = CE->getOperand(0)->getType(); bool TypeIsSigned = false; switch (CE->getOpcode()) { - case Instruction::Add: - case Instruction::Sub: - case Instruction::Mul: - // We need to cast integer arithmetic so that it is always performed - // as unsigned, to avoid undefined behavior on overflow. - case Instruction::LShr: - case Instruction::URem: - case Instruction::UDiv: - NeedsExplicitCast = true; - break; - case Instruction::AShr: - case Instruction::SRem: - case Instruction::SDiv: - NeedsExplicitCast = true; - TypeIsSigned = true; - break; - case Instruction::SExt: - Ty = CE->getType(); - NeedsExplicitCast = true; - TypeIsSigned = true; - break; - case Instruction::ZExt: - case Instruction::Trunc: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPToUI: - case Instruction::FPToSI: - case Instruction::PtrToInt: - case Instruction::IntToPtr: - case Instruction::BitCast: - Ty = CE->getType(); - NeedsExplicitCast = true; - break; - default: - break; - } - if (NeedsExplicitCast) { - Out << "(("; - printTypeName(Out, Ty, TypeIsSigned); // not integer, sign doesn't matter - Out << ")("; - } - return NeedsExplicitCast; -} - -// Print a constant assuming that it is the operand for a given Opcode. The -// opcodes that care about sign need to cast their operands to the expected -// type before the operation proceeds. This function does the casting. -void CWriter::printConstantWithCast(Constant *CPV, unsigned Opcode) { - - // Extract the operand's type, we'll need it. - Type *OpTy = CPV->getType(); - assert(OpTy->isIntegerTy() || - OpTy->isFloatingPointTy()); // TODO: VectorType are valid here, but not - // supported - - // Indicate whether to do the cast or not. + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + // We need to cast integer arithmetic so that it is always performed + // as unsigned, to avoid undefined behavior on overflow. + case Instruction::LShr: + case Instruction::URem: + case Instruction::UDiv: NeedsExplicitCast = true; break; + case Instruction::AShr: + case Instruction::SRem: + case Instruction::SDiv: NeedsExplicitCast = true; TypeIsSigned = true; break; + case Instruction::SExt: + Ty = CE->getType(); + NeedsExplicitCast = true; + TypeIsSigned = true; + break; + case Instruction::ZExt: + case Instruction::Trunc: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::PtrToInt: + case Instruction::IntToPtr: + case Instruction::BitCast: + Ty = CE->getType(); + NeedsExplicitCast = true; + break; + default: break; + } + if (NeedsExplicitCast) { + Out << "(("; + printTypeName(Out, Ty, TypeIsSigned); // not integer, sign doesn't matter + Out << ")("; + } + return NeedsExplicitCast; +} + +// Print a constant assuming that it is the operand for a given Opcode. The +// opcodes that care about sign need to cast their operands to the expected +// type before the operation proceeds. This function does the casting. +void CWriter::printConstantWithCast(Constant* CPV, unsigned Opcode) { + + // Extract the operand's type, we'll need it. + Type* OpTy = CPV->getType(); + assert(OpTy->isIntegerTy() || OpTy->isFloatingPointTy()); // TODO: VectorType are valid here, but not supported + + // Indicate whether to do the cast or not. bool shouldCast; bool typeIsSigned; opcodeNeedsCast(Opcode, shouldCast, typeIsSigned); @@ -1437,7 +1308,7 @@ void CWriter::printConstantWithCast(Constant *CPV, unsigned Opcode) { } std::string CWriter::GetValueName(Value *Operand) { - // DEBUG(errs() << "In getvaluename: " << *Operand << "\n"); + DEBUG(errs() << "In getvaluename: " << *Operand << "\n"); // Resolve potential alias. if (GlobalAlias *GA = dyn_cast<GlobalAlias>(Operand)) { @@ -1460,7 +1331,8 @@ std::string CWriter::GetValueName(Value *Operand) { std::string VarName; VarName.reserve(Name.capacity()); - for (std::string::iterator I = Name.begin(), E = Name.end(); I != E; ++I) { + for (std::string::iterator I = Name.begin(), E = Name.end(); + I != E; ++I) { unsigned char ch = *I; if (!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || @@ -1484,7 +1356,7 @@ void CWriter::writeInstComputationInline(Instruction &I) { unsigned mask = 0; Type *Ty = I.getType(); if (Ty->isIntegerTy()) { - IntegerType *ITy = static_cast<IntegerType *>(Ty); + IntegerType *ITy = static_cast<IntegerType*>(Ty); if (!ITy->isPowerOf2ByteWidth()) mask = ITy->getBitMask(); } @@ -1502,20 +1374,20 @@ void CWriter::writeInstComputationInline(Instruction &I) { Out << ")&" << mask << ")"; } -void CWriter::writeOperandInternal(Value *Operand, - enum OperandContext Context) { - // DEBUG(errs() << "In write operand internal: " << *Operand << "\n"); + +void CWriter::writeOperandInternal(Value *Operand, enum OperandContext Context) { + DEBUG(errs() << "In write operand internal: " << *Operand << "\n"); if (Instruction *I = dyn_cast<Instruction>(Operand)) // Should we inline this instruction to build a tree? if (isInlinableInst(*I) && !isDirectAlloca(I)) { - // DEBUG(errs() << "isInlinableInst & NOT isDirectAlloca\n" << "\n"); + DEBUG(errs() << "isInlinableInst & NOT isDirectAlloca\n" << "\n"); Out << '('; writeInstComputationInline(*I); Out << ')'; return; } - Constant *CPV = dyn_cast<Constant>(Operand); + Constant* CPV = dyn_cast<Constant>(Operand); if (CPV && !isa<GlobalValue>(CPV)) printConstant(CPV, Context); @@ -1523,14 +1395,12 @@ void CWriter::writeOperandInternal(Value *Operand, Out << GetValueName(Operand); } -void CWriter::writeOperand(Value *Operand, enum OperandContext Context, - bool arrayAccess) { - // DEBUG(errs() << "In write operand: " << *Operand << "; ArrayAccess = " << - // arrayAccess << "\n"); +void CWriter::writeOperand(Value *Operand, enum OperandContext Context, bool arrayAccess) { + DEBUG(errs() << "In write operand: " << *Operand << "; ArrayAccess = " << arrayAccess << "\n"); bool isAddressImplicit = isAddressExposed(Operand); if (isAddressImplicit && !arrayAccess) { DEBUG(errs() << "isAddressImplicit & NOT arrayAccess!\n"); - Out << "(&"; // Global variables are referenced as their addresses by llvm + Out << "(&"; // Global variables are referenced as their addresses by llvm } writeOperandInternal(Operand, Context); @@ -1559,27 +1429,26 @@ void CWriter::writeOperandDeref(Value *Operand) { bool CWriter::writeInstructionCast(Instruction &I) { Type *Ty = I.getOperand(0)->getType(); switch (I.getOpcode()) { - case Instruction::Add: - case Instruction::Sub: - case Instruction::Mul: - // We need to cast integer arithmetic so that it is always performed - // as unsigned, to avoid undefined behavior on overflow. - case Instruction::LShr: - case Instruction::URem: - case Instruction::UDiv: - Out << "(("; - printSimpleType(Out, Ty, false); - Out << ")("; - return true; - case Instruction::AShr: - case Instruction::SRem: - case Instruction::SDiv: - Out << "(("; - printSimpleType(Out, Ty, true); - Out << ")("; - return true; - default: - break; + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + // We need to cast integer arithmetic so that it is always performed + // as unsigned, to avoid undefined behavior on overflow. + case Instruction::LShr: + case Instruction::URem: + case Instruction::UDiv: + Out << "(("; + printSimpleType(Out, Ty, false); + Out << ")("; + return true; + case Instruction::AShr: + case Instruction::SRem: + case Instruction::SDiv: + Out << "(("; + printSimpleType(Out, Ty, true); + Out << ")("; + return true; + default: break; } return false; } @@ -1587,8 +1456,7 @@ bool CWriter::writeInstructionCast(Instruction &I) { // Write the operand with a cast to another type based on the Opcode being used. // This will be used in cases where an instruction has specific type // requirements (usually signedness) for its operands. -void CWriter::opcodeNeedsCast( - unsigned Opcode, +void CWriter::opcodeNeedsCast(unsigned Opcode, // Indicate whether to do the cast or not. bool &shouldCast, // Indicate whether the cast should be to a signed type or not. @@ -1598,34 +1466,34 @@ void CWriter::opcodeNeedsCast( // the new type to which the operand should be casted by setting the value // of OpTy. If we change OpTy, also set shouldCast to true. switch (Opcode) { - default: - // for most instructions, it doesn't matter - shouldCast = false; - castIsSigned = false; - break; - case Instruction::Add: - case Instruction::Sub: - case Instruction::Mul: - // We need to cast integer arithmetic so that it is always performed - // as unsigned, to avoid undefined behavior on overflow. - case Instruction::LShr: - case Instruction::UDiv: - case Instruction::URem: // Cast to unsigned first - shouldCast = true; - castIsSigned = false; - break; - case Instruction::GetElementPtr: - case Instruction::AShr: - case Instruction::SDiv: - case Instruction::SRem: // Cast to signed first - shouldCast = true; - castIsSigned = true; - break; + default: + // for most instructions, it doesn't matter + shouldCast = false; + castIsSigned = false; + break; + case Instruction::Add: + case Instruction::Sub: + case Instruction::Mul: + // We need to cast integer arithmetic so that it is always performed + // as unsigned, to avoid undefined behavior on overflow. + case Instruction::LShr: + case Instruction::UDiv: + case Instruction::URem: // Cast to unsigned first + shouldCast = true; + castIsSigned = false; + break; + case Instruction::GetElementPtr: + case Instruction::AShr: + case Instruction::SDiv: + case Instruction::SRem: // Cast to signed first + shouldCast = true; + castIsSigned = true; + break; } } -void CWriter::writeOperandWithCast(Value *Operand, unsigned Opcode) { - // DEBUG(errs() << "Here: " << *Operand << "\n"); +void CWriter::writeOperandWithCast(Value* Operand, unsigned Opcode) { + DEBUG(errs() << "Here: " << *Operand << "\n"); // Write out the casted operand if we should, otherwise just write the // operand. @@ -1642,12 +1510,12 @@ void CWriter::writeOperandWithCast(Value *Operand, unsigned Opcode) { // writeOperand(Operand, ContextCasted); // Out << ")"; // } else - writeOperand(Operand, ContextNormal /*ContextCasted*/); + writeOperand(Operand, ContextNormal/*ContextCasted*/); } // Write the operand with a cast to another type based on the icmp predicate // being used. -void CWriter::writeOperandWithCast(Value *Operand, ICmpInst &Cmp) { +void CWriter::writeOperandWithCast(Value* Operand, ICmpInst &Cmp) { // This has to do a cast to ensure the operand has the right signedness. // Also, if the operand is a pointer, we make sure to cast to an integer when // doing the comparison both for signedness and so that the C compiler doesn't @@ -1666,7 +1534,7 @@ void CWriter::writeOperandWithCast(Value *Operand, ICmpInst &Cmp) { bool castIsSigned = Cmp.isSigned(); // If the operand was a pointer, convert to a large integer type. - Type *OpTy = Operand->getType(); + Type* OpTy = Operand->getType(); if (OpTy->isPointerTy()) OpTy = TD->getIntPtrType(Operand->getContext()); @@ -1680,64 +1548,61 @@ void CWriter::writeOperandWithCast(Value *Operand, ICmpInst &Cmp) { // generateCompilerSpecificCode - This is where we add conditional compilation // directives to cater to specific compilers as need be. // -static void generateCompilerSpecificCode(raw_ostream &Out, - const DataLayout *TD) { +static void generateCompilerSpecificCode(raw_ostream& Out, + const DataLayout *TD) { // Alloca is hard to get, and we don't want to include stdlib.h here. Out << "/* get a declaration for alloca */\n" - << "#if defined(__CYGWIN__) || defined(__MINGW32__)\n" - << "#define alloca(x) __builtin_alloca((x))\n" - << "#define _alloca(x) __builtin_alloca((x))\n" - << "#elif defined(__APPLE__)\n" - << "extern void *__builtin_alloca(unsigned long);\n" - << "#define alloca(x) __builtin_alloca(x)\n" - << "#define longjmp _longjmp\n" - << "#define setjmp _setjmp\n" - << "#elif defined(__sun__)\n" - << "#if defined(__sparcv9)\n" - << "extern void *__builtin_alloca(unsigned long);\n" - << "#else\n" - << "extern void *__builtin_alloca(unsigned int);\n" - << "#endif\n" - << "#define alloca(x) __builtin_alloca(x)\n" - << "#elif defined(__FreeBSD__) || defined(__NetBSD__) || " - "defined(__OpenBSD__) || defined(__DragonFly__) || defined(__arm__)\n" - << "#define alloca(x) __builtin_alloca(x)\n" - << "#elif defined(_MSC_VER)\n" - << "#define alloca(x) _alloca(x)\n" - << "#else\n" - << "#include <alloca.h>\n" - << "#endif\n\n"; + << "#if defined(__CYGWIN__) || defined(__MINGW32__)\n" + << "#define alloca(x) __builtin_alloca((x))\n" + << "#define _alloca(x) __builtin_alloca((x))\n" + << "#elif defined(__APPLE__)\n" + << "extern void *__builtin_alloca(unsigned long);\n" + << "#define alloca(x) __builtin_alloca(x)\n" + << "#define longjmp _longjmp\n" + << "#define setjmp _setjmp\n" + << "#elif defined(__sun__)\n" + << "#if defined(__sparcv9)\n" + << "extern void *__builtin_alloca(unsigned long);\n" + << "#else\n" + << "extern void *__builtin_alloca(unsigned int);\n" + << "#endif\n" + << "#define alloca(x) __builtin_alloca(x)\n" + << "#elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__arm__)\n" + << "#define alloca(x) __builtin_alloca(x)\n" + << "#elif defined(_MSC_VER)\n" + << "#define alloca(x) _alloca(x)\n" + << "#else\n" + << "#include <alloca.h>\n" + << "#endif\n\n"; // On Mac OS X, "external weak" is spelled "__attribute__((weak_import))". Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" - << "#define __EXTERNAL_WEAK__ __attribute__((weak_import))\n" - << "#elif defined(__GNUC__)\n" - << "#define __EXTERNAL_WEAK__ __attribute__((weak))\n" - << "#else\n" - << "#define __EXTERNAL_WEAK__\n" - << "#endif\n\n"; + << "#define __EXTERNAL_WEAK__ __attribute__((weak_import))\n" + << "#elif defined(__GNUC__)\n" + << "#define __EXTERNAL_WEAK__ __attribute__((weak))\n" + << "#else\n" + << "#define __EXTERNAL_WEAK__\n" + << "#endif\n\n"; // For now, turn off the weak linkage attribute on Mac OS X. (See above.) Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" - << "#define __ATTRIBUTE_WEAK__\n" - << "#elif defined(__GNUC__)\n" - << "#define __ATTRIBUTE_WEAK__ __attribute__((weak))\n" - << "#else\n" - << "#define __ATTRIBUTE_WEAK__\n" - << "#endif\n\n"; + << "#define __ATTRIBUTE_WEAK__\n" + << "#elif defined(__GNUC__)\n" + << "#define __ATTRIBUTE_WEAK__ __attribute__((weak))\n" + << "#else\n" + << "#define __ATTRIBUTE_WEAK__\n" + << "#endif\n\n"; // Add hidden visibility support. FIXME: APPLE_CC? Out << "#if defined(__GNUC__)\n" - << "#define __HIDDEN__ __attribute__((visibility(\"hidden\")))\n" - << "#endif\n\n"; + << "#define __HIDDEN__ __attribute__((visibility(\"hidden\")))\n" + << "#endif\n\n"; // Define unaligned-load helper macro Out << "#ifdef _MSC_VER\n"; - Out << "#define __UNALIGNED_LOAD__(type, align, op) *((type " - "__unaligned*)op)\n"; + Out << "#define __UNALIGNED_LOAD__(type, align, op) *((type __unaligned*)op)\n"; Out << "#else\n"; - Out << "#define __UNALIGNED_LOAD__(type, align, op) ((struct { type data " - "__attribute__((packed, aligned(align))); }*)op)->data\n"; + Out << "#define __UNALIGNED_LOAD__(type, align, op) ((struct { type data __attribute__((packed, aligned(align))); }*)op)->data\n"; Out << "#endif\n\n"; // Define unaligned-load helper macro @@ -1788,144 +1653,110 @@ static void generateCompilerSpecificCode(raw_ostream &Out, // // Similar to __builtin_inf, except the return type is float. Out << "#ifdef __GNUC__\n" - << "#define LLVM_NAN(NanStr) __builtin_nan(NanStr) /* Double */\n" - << "#define LLVM_NANF(NanStr) __builtin_nanf(NanStr) /* Float */\n" - //<< "#define LLVM_NANS(NanStr) __builtin_nans(NanStr) /* Double */\n" - //<< "#define LLVM_NANSF(NanStr) __builtin_nansf(NanStr) /* Float */\n" - << "#define LLVM_INF __builtin_inf() /* Double */\n" - << "#define LLVM_INFF __builtin_inff() /* Float */\n" - << "#define LLVM_PREFETCH(addr,rw,locality) " - "__builtin_prefetch(addr,rw,locality)\n" - << "#define __ATTRIBUTE_CTOR__ __attribute__((constructor))\n" - << "#define __ATTRIBUTE_DTOR__ __attribute__((destructor))\n" - << "#else\n" - << "#define LLVM_NAN(NanStr) ((double)NAN) /* Double */\n" - << "#define LLVM_NANF(NanStr) ((float)NAN)) /* Float */\n" - //<< "#define LLVM_NANS(NanStr) ((double)NAN) /* Double */\n" - //<< "#define LLVM_NANSF(NanStr) ((single)NAN) /* Float */\n" - << "#define LLVM_INF ((double)INFINITY) /* Double */\n" - << "#define LLVM_INFF ((float)INFINITY) /* Float */\n" - << "#define LLVM_PREFETCH(addr,rw,locality) /* PREFETCH */\n" - << "#define __ATTRIBUTE_CTOR__ \"__attribute__((constructor)) not " - "supported on this compiler\"\n" - << "#define __ATTRIBUTE_DTOR__ \"__attribute__((destructor)) not " - "supported on this compiler\"\n" - << "#endif\n\n"; - - Out << "#if !defined(__GNUC__) || __GNUC__ < 4 /* Old GCC's, or compilers " - "not GCC */ \n" - << "#define __builtin_stack_save() 0 /* not implemented */\n" - << "#define __builtin_stack_restore(X) /* noop */\n" - << "#endif\n\n"; + << "#define LLVM_NAN(NanStr) __builtin_nan(NanStr) /* Double */\n" + << "#define LLVM_NANF(NanStr) __builtin_nanf(NanStr) /* Float */\n" + //<< "#define LLVM_NANS(NanStr) __builtin_nans(NanStr) /* Double */\n" + //<< "#define LLVM_NANSF(NanStr) __builtin_nansf(NanStr) /* Float */\n" + << "#define LLVM_INF __builtin_inf() /* Double */\n" + << "#define LLVM_INFF __builtin_inff() /* Float */\n" + << "#define LLVM_PREFETCH(addr,rw,locality) " + "__builtin_prefetch(addr,rw,locality)\n" + << "#define __ATTRIBUTE_CTOR__ __attribute__((constructor))\n" + << "#define __ATTRIBUTE_DTOR__ __attribute__((destructor))\n" + << "#else\n" + << "#define LLVM_NAN(NanStr) ((double)NAN) /* Double */\n" + << "#define LLVM_NANF(NanStr) ((float)NAN)) /* Float */\n" + //<< "#define LLVM_NANS(NanStr) ((double)NAN) /* Double */\n" + //<< "#define LLVM_NANSF(NanStr) ((single)NAN) /* Float */\n" + << "#define LLVM_INF ((double)INFINITY) /* Double */\n" + << "#define LLVM_INFF ((float)INFINITY) /* Float */\n" + << "#define LLVM_PREFETCH(addr,rw,locality) /* PREFETCH */\n" + << "#define __ATTRIBUTE_CTOR__ \"__attribute__((constructor)) not supported on this compiler\"\n" + << "#define __ATTRIBUTE_DTOR__ \"__attribute__((destructor)) not supported on this compiler\"\n" + << "#endif\n\n"; + + Out << "#if !defined(__GNUC__) || __GNUC__ < 4 /* Old GCC's, or compilers not GCC */ \n" + << "#define __builtin_stack_save() 0 /* not implemented */\n" + << "#define __builtin_stack_restore(X) /* noop */\n" + << "#endif\n\n"; // Output typedefs for 128-bit integers - Out << "#if defined(__GNUC__) && defined(__LP64__) /* 128-bit integer types " - "*/\n" - << "typedef int __attribute__((mode(TI))) int128_t;\n" - << "typedef unsigned __attribute__((mode(TI))) uint128_t;\n" - << "#define UINT128_C(hi, lo) (((uint128_t)(hi) << 64) | " - "(uint128_t)(lo))\n" - << "static __forceinline uint128_t llvm_ctor_u128(ulong hi, ulong lo) {" - << " return UINT128_C(hi, lo); }\n" - << "static __forceinline bool llvm_icmp_eq_u128(uint128_t l, uint128_t " - "r) {" - << " return l == r; }\n" - << "static __forceinline bool llvm_icmp_ne_u128(uint128_t l, uint128_t " - "r) {" - << " return l != r; }\n" - << "static __forceinline bool llvm_icmp_ule_u128(uint128_t l, uint128_t " - "r) {" - << " return l <= r; }\n" - << "static __forceinline bool llvm_icmp_sle_i128(int128_t l, int128_t r) " - "{" - << " return l <= r; }\n" - << "static __forceinline bool llvm_icmp_uge_u128(uint128_t l, uint128_t " - "r) {" - << " return l >= r; }\n" - << "static __forceinline bool llvm_icmp_sge_i128(int128_t l, int128_t r) " - "{" - << " return l >= r; }\n" - << "static __forceinline bool llvm_icmp_ult_u128(uint128_t l, uint128_t " - "r) {" - << " return l < r; }\n" - << "static __forceinline bool llvm_icmp_slt_i128(int128_t l, int128_t r) " - "{" - << " return l < r; }\n" - << "static __forceinline bool llvm_icmp_ugt_u128(uint128_t l, uint128_t " - "r) {" - << " return l > r; }\n" - << "static __forceinline bool llvm_icmp_sgt_i128(int128_t l, int128_t r) " - "{" - << " return l > r; }\n" - - << "#else /* manual 128-bit types */\n" - // TODO: field order should be reversed for big-endian - << "typedef struct { ulong lo; ulong hi; } uint128_t;\n" - << "typedef uint128_t int128_t;\n" - << "#define UINT128_C(hi, lo) {(lo), (hi)}\n" // only use in Static - // context - << "static __forceinline uint128_t llvm_ctor_u128(ulong hi, ulong lo) {" - << " uint128_t r; r.lo = lo; r.hi = hi; return r; }\n" - << "static __forceinline bool llvm_icmp_eq_u128(uint128_t l, uint128_t " - "r) {" - << " return l.hi == r.hi && l.lo == r.lo; }\n" - << "static __forceinline bool llvm_icmp_ne_u128(uint128_t l, uint128_t " - "r) {" - << " return l.hi != r.hi || l.lo != r.lo; }\n" - << "static __forceinline bool llvm_icmp_ule_u128(uint128_t l, uint128_t " - "r) {" - << " return l.hi < r.hi ? 1 : (l.hi == r.hi ? l.lo <= l.lo : 0); }\n" - << "static __forceinline bool llvm_icmp_sle_i128(int128_t l, int128_t r) " - "{" - << " return (long)l.hi < (long)r.hi ? 1 : (l.hi == r.hi ? (long)l.lo <= " - "(long)l.lo : 0); }\n" - << "static __forceinline bool llvm_icmp_uge_u128(uint128_t l, uint128_t " - "r) {" - << " return l.hi > r.hi ? 1 : (l.hi == r.hi ? l.lo >= l.hi : 0); }\n" - << "static __forceinline bool llvm_icmp_sge_i128(int128_t l, int128_t r) " - "{" - << " return (long)l.hi > (long)r.hi ? 1 : (l.hi == r.hi ? (long)l.lo >= " - "(long)l.lo : 0); }\n" - << "static __forceinline bool llvm_icmp_ult_u128(uint128_t l, uint128_t " - "r) {" - << " return l.hi < r.hi ? 1 : (l.hi == r.hi ? l.lo < l.hi : 0); }\n" - << "static __forceinline bool llvm_icmp_slt_i128(int128_t l, int128_t r) " - "{" - << " return (long)l.hi < (long)r.hi ? 1 : (l.hi == r.hi ? (long)l.lo < " - "(long)l.lo : 0); }\n" - << "static __forceinline bool llvm_icmp_ugt_u128(uint128_t l, uint128_t " - "r) {" - << " return l.hi > r.hi ? 1 : (l.hi == r.hi ? l.lo > l.hi : 0); }\n" - << "static __forceinline bool llvm_icmp_sgt_i128(int128_t l, int128_t r) " - "{" - << " return (long)l.hi > (long)r.hi ? 1 : (l.hi == r.hi ? (long)l.lo > " - "(long)l.lo : 0); }\n" - << "#define __emulate_i128\n" - << "#endif\n\n"; + Out << "#if defined(__GNUC__) && defined(__LP64__) /* 128-bit integer types */\n" + << "typedef int __attribute__((mode(TI))) int128_t;\n" + << "typedef unsigned __attribute__((mode(TI))) uint128_t;\n" + << "#define UINT128_C(hi, lo) (((uint128_t)(hi) << 64) | (uint128_t)(lo))\n" + << "static __forceinline uint128_t llvm_ctor_u128(ulong hi, ulong lo) {" + << " return UINT128_C(hi, lo); }\n" + << "static __forceinline bool llvm_icmp_eq_u128(uint128_t l, uint128_t r) {" + << " return l == r; }\n" + << "static __forceinline bool llvm_icmp_ne_u128(uint128_t l, uint128_t r) {" + << " return l != r; }\n" + << "static __forceinline bool llvm_icmp_ule_u128(uint128_t l, uint128_t r) {" + << " return l <= r; }\n" + << "static __forceinline bool llvm_icmp_sle_i128(int128_t l, int128_t r) {" + << " return l <= r; }\n" + << "static __forceinline bool llvm_icmp_uge_u128(uint128_t l, uint128_t r) {" + << " return l >= r; }\n" + << "static __forceinline bool llvm_icmp_sge_i128(int128_t l, int128_t r) {" + << " return l >= r; }\n" + << "static __forceinline bool llvm_icmp_ult_u128(uint128_t l, uint128_t r) {" + << " return l < r; }\n" + << "static __forceinline bool llvm_icmp_slt_i128(int128_t l, int128_t r) {" + << " return l < r; }\n" + << "static __forceinline bool llvm_icmp_ugt_u128(uint128_t l, uint128_t r) {" + << " return l > r; }\n" + << "static __forceinline bool llvm_icmp_sgt_i128(int128_t l, int128_t r) {" + << " return l > r; }\n" + + << "#else /* manual 128-bit types */\n" + // TODO: field order should be reversed for big-endian + << "typedef struct { ulong lo; ulong hi; } uint128_t;\n" + << "typedef uint128_t int128_t;\n" + << "#define UINT128_C(hi, lo) {(lo), (hi)}\n" // only use in Static context + << "static __forceinline uint128_t llvm_ctor_u128(ulong hi, ulong lo) {" + << " uint128_t r; r.lo = lo; r.hi = hi; return r; }\n" + << "static __forceinline bool llvm_icmp_eq_u128(uint128_t l, uint128_t r) {" + << " return l.hi == r.hi && l.lo == r.lo; }\n" + << "static __forceinline bool llvm_icmp_ne_u128(uint128_t l, uint128_t r) {" + << " return l.hi != r.hi || l.lo != r.lo; }\n" + << "static __forceinline bool llvm_icmp_ule_u128(uint128_t l, uint128_t r) {" + << " return l.hi < r.hi ? 1 : (l.hi == r.hi ? l.lo <= l.lo : 0); }\n" + << "static __forceinline bool llvm_icmp_sle_i128(int128_t l, int128_t r) {" + << " return (long)l.hi < (long)r.hi ? 1 : (l.hi == r.hi ? (long)l.lo <= (long)l.lo : 0); }\n" + << "static __forceinline bool llvm_icmp_uge_u128(uint128_t l, uint128_t r) {" + << " return l.hi > r.hi ? 1 : (l.hi == r.hi ? l.lo >= l.hi : 0); }\n" + << "static __forceinline bool llvm_icmp_sge_i128(int128_t l, int128_t r) {" + << " return (long)l.hi > (long)r.hi ? 1 : (l.hi == r.hi ? (long)l.lo >= (long)l.lo : 0); }\n" + << "static __forceinline bool llvm_icmp_ult_u128(uint128_t l, uint128_t r) {" + << " return l.hi < r.hi ? 1 : (l.hi == r.hi ? l.lo < l.hi : 0); }\n" + << "static __forceinline bool llvm_icmp_slt_i128(int128_t l, int128_t r) {" + << " return (long)l.hi < (long)r.hi ? 1 : (l.hi == r.hi ? (long)l.lo < (long)l.lo : 0); }\n" + << "static __forceinline bool llvm_icmp_ugt_u128(uint128_t l, uint128_t r) {" + << " return l.hi > r.hi ? 1 : (l.hi == r.hi ? l.lo > l.hi : 0); }\n" + << "static __forceinline bool llvm_icmp_sgt_i128(int128_t l, int128_t r) {" + << " return (long)l.hi > (long)r.hi ? 1 : (l.hi == r.hi ? (long)l.lo > (long)l.lo : 0); }\n" + << "#define __emulate_i128\n" + << "#endif\n\n"; // We output GCC specific attributes to preserve 'linkonce'ness on globals. // If we aren't being compiled with GCC, just drop these attributes. Out << "#ifdef _MSC_VER /* Can only support \"linkonce\" vars with GCC */\n" - << "#define __attribute__(X)\n" - << "#endif\n\n"; + << "#define __attribute__(X)\n" + << "#endif\n\n"; } /// FindStaticTors - Given a static ctor/dtor list, unpack its contents into /// the StaticTors set. -static void FindStaticTors(GlobalVariable *GV, - std::set<Function *> &StaticTors) { +static void FindStaticTors(GlobalVariable *GV, std::set<Function*> &StaticTors){ ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer()); - if (!InitList) - return; + if (!InitList) return; for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) - if (ConstantStruct *CS = - dyn_cast<ConstantStruct>(InitList->getOperand(i))) { - if (CS->getNumOperands() != 2) - return; // Not array of 2-element structs. + if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){ + if (CS->getNumOperands() != 2) return; // Not array of 2-element structs. if (CS->getOperand(1)->isNullValue()) - return; // Found a null terminator, exit printing. + return; // Found a null terminator, exit printing. Constant *FP = CS->getOperand(1); if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP)) if (CE->isCast()) @@ -1937,8 +1768,7 @@ static void FindStaticTors(GlobalVariable *GV, enum SpecialGlobalClass { NotSpecial = 0, - GlobalCtors, - GlobalDtors, + GlobalCtors, GlobalDtors, NotPrinted }; @@ -1955,8 +1785,9 @@ static SpecialGlobalClass getGlobalVariableClass(GlobalVariable *GV) { // Otherwise, if it is other metadata, don't print it. This catches things // like debug information. - if (StringRef(GV->getSection()) == "llvm.metadata") { - // DEBUG(errs() << "Printing Metada!\n" << *GV << "\n"); + if (StringRef(GV->getSection()) == "llvm.metadata") + { + DEBUG(errs() << "Printing Metada!\n" << *GV << "\n"); return NotPrinted; } return NotSpecial; @@ -1965,7 +1796,7 @@ static SpecialGlobalClass getGlobalVariableClass(GlobalVariable *GV) { // 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 char *Str, unsigned Length, - raw_ostream &Out) { + raw_ostream &Out) { for (unsigned i = 0; i != Length; ++i) { unsigned char C = Str[i]; if (isprint(C) && C != '\\' && C != '"') @@ -1992,10 +1823,9 @@ bool CWriter::doInitialization(Module &M) { TD = new DataLayout(&M); IL = new IntrinsicLowering(*TD); - // CHECK: Looking at lib/CodeGen/IntrinsicsLowering.cpp this func not - // supported This func creates defs which are created once each call is - // referenced anyway - // IL->AddPrototypes(M); + // CHECK: Looking at lib/CodeGen/IntrinsicsLowering.cpp this func not supported + // This func creates defs which are created once each call is referenced anyway + //IL->AddPrototypes(M); #if 0 std::string Triple = TheModule->getTargetTriple(); @@ -2007,7 +1837,7 @@ bool CWriter::doInitialization(Module &M) { TAsm = Match->createMCAsmInfo(Triple); #endif TAsm = new CBEMCAsmInfo(); - MRI = new MCRegisterInfo(); + MRI = new MCRegisterInfo(); TCtx = new MCContext(TAsm, MRI, NULL); return false; } @@ -2053,18 +1883,17 @@ bool CWriter::doFinalization(Module &M) { void CWriter::generateHeader(Module &M) { // Keep track of which functions are static ctors/dtors so they can have // an attribute added to their prototypes. - std::set<Function *> StaticCtors, StaticDtors; - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; - ++I) { + std::set<Function*> StaticCtors, StaticDtors; + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { switch (getGlobalVariableClass(&*I)) { - default: - break; - case GlobalCtors: - FindStaticTors(&*I, StaticCtors); - break; - case GlobalDtors: - FindStaticTors(&*I, StaticDtors); - break; + default: break; + case GlobalCtors: + FindStaticTors(&*I, StaticCtors); + break; + case GlobalDtors: + FindStaticTors(&*I, StaticDtors); + break; } } @@ -2074,9 +1903,8 @@ void CWriter::generateHeader(Module &M) { // Out << "#include <setjmp.h>\n"; // Unwind support // Out << "#include <limits.h>\n"; // With overflow intrinsics support. // Out << "#include <stdint.h>\n"; // Sized integer support - // Out << "#include <math.h>\n"; // definitions for some math - // functions and numeric constants Out << "#include <APInt-C.h>\n"; // - // Implementations of many llvm intrinsics + // Out << "#include <math.h>\n"; // definitions for some math functions and numeric constants + // Out << "#include <APInt-C.h>\n"; // Implementations of many llvm intrinsics // // Provide a definition for `bool' if not compiling with a C++ compiler. // Out << "#ifndef __cplusplus\ntypedef unsigned char bool;\n#endif\n"; // Out << "\n"; @@ -2084,24 +1912,24 @@ void CWriter::generateHeader(Module &M) { // generateCompilerSpecificCode(Out, TD); Out << "\n\n/* Support for floating point constants */\n" - << "typedef ulong ConstantDoubleTy;\n" - << "typedef uint ConstantFloatTy;\n" - << "typedef struct { ulong f1; ushort f2; " - "ushort pad[3]; } ConstantFP80Ty;\n" - // This is used for both kinds of 128-bit long double; meaning differs. - << "typedef struct { ulong f1; ulong f2; }" - " ConstantFP128Ty;\n" - << "\n\n/* OpenCL Pragmas */\n" - << "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" - << "#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable\n" - << "#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable\n" - << "\n\n/* Global Declarations */\n"; + << "typedef ulong ConstantDoubleTy;\n" + << "typedef uint ConstantFloatTy;\n" + << "typedef struct { ulong f1; ushort f2; " + "ushort pad[3]; } ConstantFP80Ty;\n" + // This is used for both kinds of 128-bit long double; meaning differs. + << "typedef struct { ulong f1; ulong f2; }" + " ConstantFP128Ty;\n" + << "\n\n/* OpenCL Pragmas */\n" + << "#pragma OPENCL EXTENSION cl_khr_fp64 : enable\n" + << "#pragma OPENCL EXTENSION cl_khr_int64_base_atomics : enable\n" + << "#pragma OPENCL EXTENSION cl_khr_int64_extended_atomics : enable\n" + << "\n\n/* Global Declarations */\n"; // First output all the declarations for the program, because C requires // Functions & globals to be declared before they are used. if (!M.getModuleInlineAsm().empty()) { Out << "\n/* Module asm statements */\n" - << "__asm__ ("; + << "__asm__ ("; // Split the string into lines, to make it easier to read the .ll file. std::string Asm = M.getModuleInlineAsm(); @@ -2111,22 +1939,22 @@ void CWriter::generateHeader(Module &M) { // We found a newline, print the portion of the asm string from the // last newline up to this newline. Out << "\""; - PrintEscapedString( - std::string(Asm.begin() + CurPos, Asm.begin() + NewLine), Out); + PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.begin()+NewLine), + Out); Out << "\\n\"\n"; - CurPos = NewLine + 1; + CurPos = NewLine+1; NewLine = Asm.find_first_of('\n', CurPos); } Out << "\""; - PrintEscapedString(std::string(Asm.begin() + CurPos, Asm.end()), Out); + PrintEscapedString(std::string(Asm.begin()+CurPos, Asm.end()), Out); Out << "\");\n" - << "/* End Module asm statements */\n"; + << "/* End Module asm statements */\n"; } // collect any remaining types raw_null_ostream NullOut; - for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; - ++I) { + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { // Ignore special globals, such as debug info. if (getGlobalVariableClass(&*I)) continue; @@ -2138,9 +1966,8 @@ void CWriter::generateHeader(Module &M) { if (!M.global_empty()) { Out << "\n/* External Global Variable Declarations */\n"; for (Module::global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) { - if (!I->isDeclaration() || - isEmptyType(I->getType()->getPointerElementType())) + I != E; ++I) { + if (!I->isDeclaration() || isEmptyType(I->getType()->getPointerElementType())) continue; if (I->hasDLLImportStorageClass()) @@ -2160,8 +1987,8 @@ void CWriter::generateHeader(Module &M) { Type *ElTy = I->getType()->getElementType(); unsigned Alignment = I->getAlignment(); - bool IsOveraligned = - Alignment && Alignment > TD->getABITypeAlignment(ElTy); + bool IsOveraligned = Alignment && + Alignment > TD->getABITypeAlignment(ElTy); // if (IsOveraligned) // Out << "__MSALIGN__(" << Alignment << ") "; printTypeName(Out, ElTy, false) << ' ' << GetValueName(&*I); @@ -2178,53 +2005,64 @@ void CWriter::generateHeader(Module &M) { Out << "\n/* Function Declarations */\n"; // Store the intrinsics which will be declared/defined below. - SmallVector<Function *, 16> intrinsicsToDefine; + SmallVector<Function*, 16> intrinsicsToDefine; for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { // Don't print declarations for intrinsic functions. // Store the used intrinsics, which need to be explicitly defined. if (I->isIntrinsic()) { switch (I->getIntrinsicID()) { - default: - continue; - case Intrinsic::uadd_with_overflow: - case Intrinsic::sadd_with_overflow: - case Intrinsic::usub_with_overflow: - case Intrinsic::ssub_with_overflow: - case Intrinsic::umul_with_overflow: - case Intrinsic::smul_with_overflow: - case Intrinsic::bswap: - case Intrinsic::ceil: - case Intrinsic::ctlz: - case Intrinsic::ctpop: - case Intrinsic::cttz: - case Intrinsic::fabs: - case Intrinsic::floor: - case Intrinsic::fma: - case Intrinsic::fmuladd: - case Intrinsic::pow: - case Intrinsic::powi: - case Intrinsic::rint: - case Intrinsic::sqrt: - case Intrinsic::trunc: - intrinsicsToDefine.push_back(&*I); - continue; + default: + continue; + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::umul_with_overflow: + case Intrinsic::smul_with_overflow: + case Intrinsic::bswap: + case Intrinsic::ceil: + case Intrinsic::ctlz: + case Intrinsic::ctpop: + case Intrinsic::cttz: + case Intrinsic::fabs: + case Intrinsic::floor: + case Intrinsic::fma: + case Intrinsic::fmuladd: + case Intrinsic::pow: + case Intrinsic::powi: + case Intrinsic::rint: + case Intrinsic::sqrt: + case Intrinsic::trunc: + intrinsicsToDefine.push_back(&*I); + continue; } } // Skip a few functions that have already been defined in headers - if (I->getName() == "setjmp" || I->getName() == "longjmp" || - I->getName() == "_setjmp" || I->getName() == "siglongjmp" || - I->getName() == "sigsetjmp" || I->getName() == "pow" || - I->getName() == "powf" || I->getName() == "sqrt" || - I->getName() == "sqrtf" || I->getName() == "trunc" || - I->getName() == "truncf" || I->getName() == "rint" || - I->getName() == "rintf" || I->getName() == "floor" || - I->getName() == "floorf" || I->getName() == "ceil" || - I->getName() == "ceilf" || I->getName() == "alloca" || - I->getName() == "_alloca" || I->getName() == "_chkstk" || - I->getName() == "__chkstk" || I->getName() == "___chkstk_ms") - continue; + if (I->getName() == "setjmp" || + I->getName() == "longjmp" || + I->getName() == "_setjmp" || + I->getName() == "siglongjmp" || + I->getName() == "sigsetjmp" || + I->getName() == "pow" || + I->getName() == "powf" || + I->getName() == "sqrt" || + I->getName() == "sqrtf" || + I->getName() == "trunc" || + I->getName() == "truncf" || + I->getName() == "rint" || + I->getName() == "rintf" || + I->getName() == "floor" || + I->getName() == "floorf" || + I->getName() == "ceil" || + I->getName() == "ceilf" || + I->getName() == "alloca" || + I->getName() == "_alloca" || + I->getName() == "_chkstk" || + I->getName() == "__chkstk" || + I->getName() == "___chkstk_ms") + continue; if (I->hasDLLImportStorageClass()) Out << "__declspec(dllimport) "; @@ -2257,7 +2095,7 @@ void CWriter::generateHeader(Module &M) { if (!M.global_empty()) { Out << "\n\n/* Global Variable Definitions and Initialization */\n"; for (Module::global_iterator I = M.global_begin(), E = M.global_end(); - I != E; ++I) { + I != E; ++I) { declareOneGlobalVariable(&*I); } } @@ -2265,10 +2103,9 @@ void CWriter::generateHeader(Module &M) { // Alias declarations... if (!M.alias_empty()) { Out << "\n/* External Alias Declarations */\n"; - for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; - ++I) { - assert(!I->isDeclaration() && - !isEmptyType(I->getType()->getPointerElementType())); + for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); + I != E; ++I) { + assert(!I->isDeclaration() && !isEmptyType(I->getType()->getPointerElementType())); if (I->hasLocalLinkage()) continue; // Internal Global @@ -2283,8 +2120,8 @@ void CWriter::generateHeader(Module &M) { Type *ElTy = I->getType()->getElementType(); unsigned Alignment = I->getAlignment(); - bool IsOveraligned = - Alignment && Alignment > TD->getABITypeAlignment(ElTy); + bool IsOveraligned = Alignment && + Alignment > TD->getABITypeAlignment(ElTy); // if (IsOveraligned) // Out << "__MSALIGN__(" << Alignment << ") "; // GetValueName would resolve the alias, which is not what we want, @@ -2339,11 +2176,9 @@ void CWriter::generateHeader(Module &M) { Out << "return 1; }\n"; // Loop over all select operations - for (std::set<Type *>::iterator it = SelectDeclTypes.begin(), - end = SelectDeclTypes.end(); - it != end; ++it) { - // static __forceinline Rty llvm_select_u8x4(<bool x 4> condition, <u8 x 4> - // iftrue, <u8 x 4> ifnot) { + for (std::set<Type*>::iterator it = SelectDeclTypes.begin(), end = SelectDeclTypes.end(); + it != end; ++it) { + // static __forceinline Rty llvm_select_u8x4(<bool x 4> condition, <u8 x 4> iftrue, <u8 x 4> ifnot) { // Rty r = { // condition[0] ? iftrue[0] : ifnot[0], // condition[1] ? iftrue[1] : ifnot[1], @@ -2358,11 +2193,7 @@ void CWriter::generateHeader(Module &M) { printTypeString(Out, *it, false); Out << "("; if (isa<VectorType>(*it)) - printTypeNameUnaligned( - Out, - VectorType::get(Type::getInt1Ty((*it)->getContext()), - (*it)->getVectorNumElements()), - false); + printTypeNameUnaligned(Out, VectorType::get(Type::getInt1Ty((*it)->getContext()), (*it)->getVectorNumElements()), false); else Out << "bool"; Out << " condition, "; @@ -2375,22 +2206,19 @@ void CWriter::generateHeader(Module &M) { if (isa<VectorType>(*it)) { unsigned n, l = (*it)->getVectorNumElements(); for (n = 0; n < l; n++) { - Out << " r.vector[" << n << "] = condition.vector[" << n - << "] ? iftrue.vector[" << n << "] : ifnot.vector[" << n << "];\n"; + Out << " r.vector[" << n << "] = condition.vector[" << n << "] ? iftrue.vector[" << n << "] : ifnot.vector[" << n << "];\n"; } - } else { + } + else { Out << " r = condition ? iftrue : ifnot;\n"; } Out << " return r;\n}\n"; } // Loop over all compare operations - for (std::set<std::pair<CmpInst::Predicate, VectorType *>>::iterator - it = CmpDeclTypes.begin(), - end = CmpDeclTypes.end(); - it != end; ++it) { - // static __forceinline <bool x 4> llvm_icmp_ge_u8x4(<u8 x 4> l, <u8 x 4> r) - // { + for (std::set< std::pair<CmpInst::Predicate, VectorType*> >::iterator it = CmpDeclTypes.begin(), end = CmpDeclTypes.end(); + it != end; ++it) { + // static __forceinline <bool x 4> llvm_icmp_ge_u8x4(<u8 x 4> l, <u8 x 4> r) { // Rty c = { // l[0] >= r[0], // l[1] >= r[1], @@ -2400,8 +2228,7 @@ void CWriter::generateHeader(Module &M) { // return c; // } unsigned n, l = (*it).second->getVectorNumElements(); - VectorType *RTy = - VectorType::get(Type::getInt1Ty((*it).second->getContext()), l); + VectorType *RTy = VectorType::get(Type::getInt1Ty((*it).second->getContext()), l); bool isSigned = CmpInst::isSigned((*it).first); Out << "static __forceinline "; printTypeName(Out, RTy, isSigned); @@ -2421,38 +2248,25 @@ void CWriter::generateHeader(Module &M) { for (n = 0; n < l; n++) { Out << " c.vector[" << n << "] = "; if (CmpInst::isFPPredicate((*it).first)) { - Out << "llvm_fcmp_ " << getCmpPredicateName((*it).first) << "(l.vector[" - << n << "], r.vector[" << n << "]);\n"; + Out << "llvm_fcmp_ " << getCmpPredicateName((*it).first) << "(l.vector[" << n << "], r.vector[" << n << "]);\n"; } else { Out << "l.vector[" << n << "]"; switch ((*it).first) { - case CmpInst::ICMP_EQ: - Out << " == "; - break; - case CmpInst::ICMP_NE: - Out << " != "; - break; - case CmpInst::ICMP_ULE: - case CmpInst::ICMP_SLE: - Out << " <= "; - break; - case CmpInst::ICMP_UGE: - case CmpInst::ICMP_SGE: - Out << " >= "; - break; - case CmpInst::ICMP_ULT: - case CmpInst::ICMP_SLT: - Out << " < "; - break; - case CmpInst::ICMP_UGT: - case CmpInst::ICMP_SGT: - Out << " > "; - break; - default: + case CmpInst::ICMP_EQ: Out << " == "; break; + case CmpInst::ICMP_NE: Out << " != "; break; + case CmpInst::ICMP_ULE: + case CmpInst::ICMP_SLE: Out << " <= "; break; + case CmpInst::ICMP_UGE: + case CmpInst::ICMP_SGE: Out << " >= "; break; + case CmpInst::ICMP_ULT: + case CmpInst::ICMP_SLT: Out << " < "; break; + case CmpInst::ICMP_UGT: + case CmpInst::ICMP_SGT: Out << " > "; break; + default: #ifndef NDEBUG - errs() << "Invalid icmp predicate!" << (*it).first; + errs() << "Invalid icmp predicate!" << (*it).first; #endif - llvm_unreachable(0); + llvm_unreachable(0); } Out << "r.vector[" << n << "];\n"; } @@ -2461,13 +2275,9 @@ void CWriter::generateHeader(Module &M) { } // Loop over all (vector) cast operations - for (std::set< - std::pair<CastInst::CastOps, std::pair<Type *, Type *>>>::iterator - it = CastOpDeclTypes.begin(), - end = CastOpDeclTypes.end(); - it != end; ++it) { - // static __forceinline <u32 x 4> llvm_ZExt_u8x4_u32x4(<u8 x 4> in) { // - // Src->isVector == Dst->isVector + for (std::set<std::pair<CastInst::CastOps, std::pair<Type*, Type*>>>::iterator it = CastOpDeclTypes.begin(), end = CastOpDeclTypes.end(); + it != end; ++it) { + // static __forceinline <u32 x 4> llvm_ZExt_u8x4_u32x4(<u8 x 4> in) { // Src->isVector == Dst->isVector // Rty out = { // in[0], // in[1], @@ -2476,8 +2286,7 @@ void CWriter::generateHeader(Module &M) { // }; // return out; // } - // static __forceinline u32 llvm_BitCast_u8x4_u32(<u8 x 4> in) { // - // Src->bitsSize == Dst->bitsSize + // static __forceinline u32 llvm_BitCast_u8x4_u32(<u8 x 4> in) { // Src->bitsSize == Dst->bitsSize // union { // <u8 x 4> in; // u32 out; @@ -2490,18 +2299,18 @@ void CWriter::generateHeader(Module &M) { Type *DstTy = (*it).second.second; bool SrcSigned, DstSigned; switch (opcode) { - default: - SrcSigned = false; - DstSigned = false; - case Instruction::SIToFP: - SrcSigned = true; - DstSigned = false; - case Instruction::FPToSI: - SrcSigned = false; - DstSigned = true; - case Instruction::SExt: - SrcSigned = true; - DstSigned = true; + default: + SrcSigned = false; + DstSigned = false; + case Instruction::SIToFP: + SrcSigned = true; + DstSigned = false; + case Instruction::FPToSI: + SrcSigned = false; + DstSigned = true; + case Instruction::SExt: + SrcSigned = true; + DstSigned = true; } Out << "static __forceinline "; @@ -2540,34 +2349,20 @@ void CWriter::generateHeader(Module &M) { Out << " out;\n"; Out << " LLVM"; switch (opcode) { - case Instruction::UIToFP: - Out << "UItoFP"; - break; - case Instruction::SIToFP: - Out << "SItoFP"; - break; - case Instruction::Trunc: - Out << "Trunc"; - break; - // case Instruction::FPExt: - // case Instruction::FPTrunc: - case Instruction::ZExt: - Out << "ZExt"; - break; - case Instruction::FPToUI: - Out << "FPtoUI"; - break; - case Instruction::SExt: - Out << "SExt"; - break; - case Instruction::FPToSI: - Out << "FPtoSI"; - break; - default: - llvm_unreachable("Invalid cast opcode for i128"); + case Instruction::UIToFP: Out << "UItoFP"; break; + case Instruction::SIToFP: Out << "SItoFP"; break; + case Instruction::Trunc: Out << "Trunc"; break; + //case Instruction::FPExt: + //case Instruction::FPTrunc: + case Instruction::ZExt: Out << "ZExt"; break; + case Instruction::FPToUI: Out << "FPtoUI"; break; + case Instruction::SExt: Out << "SExt"; break; + case Instruction::FPToSI: Out << "FPtoSI"; break; + default: + llvm_unreachable("Invalid cast opcode for i128"); } Out << "(" << SrcTy->getPrimitiveSizeInBits() << ", &in, " - << DstTy->getPrimitiveSizeInBits() << ", &out);\n"; + << DstTy->getPrimitiveSizeInBits() << ", &out);\n"; Out << " return out;\n"; Out << "#endif\n"; Out << "}\n"; @@ -2575,12 +2370,9 @@ void CWriter::generateHeader(Module &M) { } // Loop over all simple vector operations - for (std::set<std::pair<unsigned, Type *>>::iterator - it = InlineOpDeclTypes.begin(), - end = InlineOpDeclTypes.end(); - it != end; ++it) { - // static __forceinline <u32 x 4> llvm_BinOp_u32x4(<u32 x 4> a, <u32 x 4> b) - // { + for (std::set<std::pair<unsigned, Type*>>::iterator it = InlineOpDeclTypes.begin(), end = InlineOpDeclTypes.end(); + it != end; ++it) { + // static __forceinline <u32 x 4> llvm_BinOp_u32x4(<u32 x 4> a, <u32 x 4> b) { // Rty r = { // a[0] OP b[0], // a[1] OP b[1], @@ -2624,7 +2416,7 @@ void CWriter::generateHeader(Module &M) { // C can't handle non-power-of-two integer types unsigned mask = 0; if (ElemTy->isIntegerTy()) { - IntegerType *ITy = static_cast<IntegerType *>(ElemTy); + IntegerType *ITy = static_cast<IntegerType*>(ElemTy); if (!ITy->isPowerOf2ByteWidth()) mask = ITy->getBitMask(); } @@ -2646,54 +2438,34 @@ void CWriter::generateHeader(Module &M) { Out << "fmodf(a.vector[" << n << "], b.vector[" << n << "])"; else if (ElemTy->isDoubleTy()) Out << "fmod(a.vector[" << n << "], b.vector[" << n << "])"; - else // all 3 flavors of long double + else // all 3 flavors of long double Out << "fmodl(a.vector[" << n << "], b.vector[" << n << "])"; } else { Out << "a.vector[" << n << "]"; switch (opcode) { - case Instruction::Add: - case Instruction::FAdd: - Out << " + "; - break; - case Instruction::Sub: - case Instruction::FSub: - Out << " - "; - break; - case Instruction::Mul: - case Instruction::FMul: - Out << " * "; - break; - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - Out << " % "; - break; - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::FDiv: - Out << " / "; - break; - case Instruction::And: - Out << " & "; - break; - case Instruction::Or: - Out << " | "; - break; - case Instruction::Xor: - Out << " ^ "; - break; - case Instruction::Shl: - Out << " << "; - break; - case Instruction::LShr: - case Instruction::AShr: - Out << " >> "; - break; - default: + case Instruction::Add: + case Instruction::FAdd: Out << " + "; break; + case Instruction::Sub: + case Instruction::FSub: Out << " - "; break; + case Instruction::Mul: + case Instruction::FMul: Out << " * "; break; + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: Out << " % "; break; + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: Out << " / "; break; + case Instruction::And: Out << " & "; break; + case Instruction::Or: Out << " | "; break; + case Instruction::Xor: Out << " ^ "; break; + case Instruction::Shl : Out << " << "; break; + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; + default: #ifndef NDEBUG - errs() << "Invalid operator type!" << opcode; + errs() << "Invalid operator type!" << opcode; #endif - llvm_unreachable(0); + llvm_unreachable(0); } Out << "b.vector[" << n << "]"; } @@ -2714,44 +2486,24 @@ void CWriter::generateHeader(Module &M) { } else { Out << "a"; switch (opcode) { - case Instruction::Add: - Out << " + "; - break; - case Instruction::Sub: - Out << " - "; - break; - case Instruction::Mul: - Out << " * "; - break; - case Instruction::URem: - case Instruction::SRem: - Out << " % "; - break; - case Instruction::UDiv: - case Instruction::SDiv: - Out << " / "; - break; - case Instruction::And: - Out << " & "; - break; - case Instruction::Or: - Out << " | "; - break; - case Instruction::Xor: - Out << " ^ "; - break; - case Instruction::Shl: - Out << " << "; - break; - case Instruction::LShr: - case Instruction::AShr: - Out << " >> "; - break; - default: + case Instruction::Add: Out << " + "; break; + case Instruction::Sub: Out << " - "; break; + case Instruction::Mul: Out << " * "; break; + case Instruction::URem: + case Instruction::SRem: Out << " % "; break; + case Instruction::UDiv: + case Instruction::SDiv: Out << " / "; break; + case Instruction::And: Out << " & "; break; + case Instruction::Or: Out << " | "; break; + case Instruction::Xor: Out << " ^ "; break; + case Instruction::Shl: Out << " << "; break; + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; + default: #ifndef NDEBUG - errs() << "Invalid operator type!" << opcode; + errs() << "Invalid operator type!" << opcode; #endif - llvm_unreachable(0); + llvm_unreachable(0); } Out << "b;\n"; } @@ -2773,8 +2525,7 @@ void CWriter::generateHeader(Module &M) { } else if (opcode == Instruction::Xor) { Out << " r.hi = a.hi ^ b.hi;\n"; Out << " r.lo = a.lo ^ b.lo;\n"; - } else if (opcode == - Instruction::Shl) { // reminder: undef behavior if b >= 128 + } else if (opcode == Instruction::Shl) { // reminder: undef behavior if b >= 128 Out << " if (b.lo >= 64) {\n"; Out << " r.hi = (a.lo << (b.lo - 64));\n"; Out << " r.lo = 0;\n"; @@ -2789,44 +2540,26 @@ void CWriter::generateHeader(Module &M) { // everything that hasn't been manually implemented above Out << " LLVM"; switch (opcode) { - // case BinaryNeg: Out << "Neg"; break; - // case BinaryNot: Out << "FlipAllBits"; break; - case Instruction::Add: - Out << "Add"; - break; - case Instruction::Sub: - Out << "Sub"; - break; - case Instruction::Mul: - Out << "Mul"; - break; - case Instruction::URem: - Out << "URem"; - break; - case Instruction::SRem: - Out << "SRem"; - break; - case Instruction::UDiv: - Out << "UDiv"; - break; - case Instruction::SDiv: - Out << "SDiv"; - break; - // case Instruction::And: Out << "And"; break; - // case Instruction::Or: Out << "Or"; break; - // case Instruction::Xor: Out << "Xor"; break; - // case Instruction::Shl: Out << "Shl"; break; - case Instruction::LShr: - Out << "LShr"; - break; - case Instruction::AShr: - Out << "AShr"; - break; - default: + //case BinaryNeg: Out << "Neg"; break; + //case BinaryNot: Out << "FlipAllBits"; break; + case Instruction::Add: Out << "Add"; break; + case Instruction::Sub: Out << "Sub"; break; + case Instruction::Mul: Out << "Mul"; break; + case Instruction::URem: Out << "URem"; break; + case Instruction::SRem: Out << "SRem"; break; + case Instruction::UDiv: Out << "UDiv"; break; + case Instruction::SDiv: Out << "SDiv"; break; + //case Instruction::And: Out << "And"; break; + //case Instruction::Or: Out << "Or"; break; + //case Instruction::Xor: Out << "Xor"; break; + //case Instruction::Shl: Out << "Shl"; break; + case Instruction::LShr: Out << "LShr"; break; + case Instruction::AShr: Out << "AShr"; break; + default: #ifndef NDEBUG - errs() << "Invalid operator type!" << opcode; + errs() << "Invalid operator type!" << opcode; #endif - llvm_unreachable(0); + llvm_unreachable(0); } Out << "(16, &a, &b, &r);\n"; } @@ -2846,54 +2579,34 @@ void CWriter::generateHeader(Module &M) { Out << "fmodf(a, b)"; else if (ElemTy->isDoubleTy()) Out << "fmod(a, b)"; - else // all 3 flavors of long double + else // all 3 flavors of long double Out << "fmodl(a, b)"; } else { Out << "a"; switch (opcode) { - case Instruction::Add: - case Instruction::FAdd: - Out << " + "; - break; - case Instruction::Sub: - case Instruction::FSub: - Out << " - "; - break; - case Instruction::Mul: - case Instruction::FMul: - Out << " * "; - break; - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - Out << " % "; - break; - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::FDiv: - Out << " / "; - break; - case Instruction::And: - Out << " & "; - break; - case Instruction::Or: - Out << " | "; - break; - case Instruction::Xor: - Out << " ^ "; - break; - case Instruction::Shl: - Out << " << "; - break; - case Instruction::LShr: - case Instruction::AShr: - Out << " >> "; - break; - default: + case Instruction::Add: + case Instruction::FAdd: Out << " + "; break; + case Instruction::Sub: + case Instruction::FSub: Out << " - "; break; + case Instruction::Mul: + case Instruction::FMul: Out << " * "; break; + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: Out << " % "; break; + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: Out << " / "; break; + case Instruction::And: Out << " & "; break; + case Instruction::Or: Out << " | "; break; + case Instruction::Xor: Out << " ^ "; break; + case Instruction::Shl : Out << " << "; break; + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; + default: #ifndef NDEBUG - errs() << "Invalid operator type!" << opcode; + errs() << "Invalid operator type!" << opcode; #endif - llvm_unreachable(0); + llvm_unreachable(0); } Out << "b"; if (mask) @@ -2905,11 +2618,9 @@ void CWriter::generateHeader(Module &M) { } // Loop over all inline constructors - for (std::set<Type *>::iterator it = CtorDeclTypes.begin(), - end = CtorDeclTypes.end(); - it != end; ++it) { - // static __forceinline <u32 x 4> llvm_ctor_u32x4(u32 x1, u32 x2, u32 x3, - // u32 x4) { + for (std::set<Type*>::iterator it = CtorDeclTypes.begin(), end = CtorDeclTypes.end(); + it != end; ++it) { + // static __forceinline <u32 x 4> llvm_ctor_u32x4(u32 x1, u32 x2, u32 x3, u32 x4) { // Rty r = { // x1, x2, x3, x4 // }; @@ -2923,12 +2634,10 @@ void CWriter::generateHeader(Module &M) { StructType *STy = dyn_cast<StructType>(*it); ArrayType *ATy = dyn_cast<ArrayType>(*it); VectorType *VTy = dyn_cast<VectorType>(*it); - unsigned e = (STy ? STy->getNumElements() - : (ATy ? ATy->getNumElements() : VTy->getNumElements())); + unsigned e = (STy ? STy->getNumElements() : (ATy ? ATy->getNumElements() : VTy->getNumElements())); bool printed = false; for (unsigned i = 0; i != e; ++i) { - Type *ElTy = - STy ? STy->getElementType(i) : (*it)->getSequentialElementType(); + Type *ElTy = STy ? STy->getElementType(i) : (*it)->getSequentialElementType(); if (isEmptyType(ElTy)) Out << " /* "; else if (printed) @@ -2944,8 +2653,7 @@ void CWriter::generateHeader(Module &M) { printTypeName(Out, *it); Out << " r;"; for (unsigned i = 0; i != e; ++i) { - Type *ElTy = - STy ? STy->getElementType(i) : (*it)->getSequentialElementType(); + Type *ElTy = STy ? STy->getElementType(i) : (*it)->getSequentialElementType(); if (isEmptyType(ElTy)) continue; if (STy) @@ -2961,9 +2669,9 @@ void CWriter::generateHeader(Module &M) { } // Emit definitions of the intrinsics. - for (SmallVector<Function *, 16>::iterator I = intrinsicsToDefine.begin(), - E = intrinsicsToDefine.end(); - I != E; ++I) { + for (SmallVector<Function*, 16>::iterator + I = intrinsicsToDefine.begin(), + E = intrinsicsToDefine.end(); I != E; ++I) { printIntrinsicDefinition(**I, Out); } @@ -2971,7 +2679,7 @@ void CWriter::generateHeader(Module &M) { Out << "\n\n/* Function Bodies */\n"; } -void CWriter::declareOneGlobalVariable(GlobalVariable *I) { +void CWriter::declareOneGlobalVariable(GlobalVariable* I) { if (I->isDeclaration() || isEmptyType(I->getType()->getPointerElementType())) return; @@ -2993,7 +2701,8 @@ void CWriter::declareOneGlobalVariable(GlobalVariable *I) { Type *ElTy = I->getType()->getElementType(); unsigned Alignment = I->getAlignment(); - bool IsOveraligned = Alignment && Alignment > TD->getABITypeAlignment(ElTy); + bool IsOveraligned = Alignment && + Alignment > TD->getABITypeAlignment(ElTy); // if (IsOveraligned) // Out << "__MSALIGN__(" << Alignment << ") "; printTypeName(Out, ElTy, false) << ' ' << GetValueName(I); @@ -3017,13 +2726,13 @@ void CWriter::declareOneGlobalVariable(GlobalVariable *I) { // and common, so we disable this optimization. // FIXME common linkage should avoid this problem. if (!I->getInitializer()->isNullValue()) { - Out << " = "; + Out << " = " ; writeOperand(I->getInitializer(), ContextStatic); } else if (I->hasWeakLinkage()) { // We have to specify an initializer, but it doesn't have to be // complete. If the value is an aggregate, print out { 0 }, and let // the compiler figure out the rest of the zeros. - Out << " = "; + Out << " = " ; if (I->getInitializer()->getType()->isStructTy() || I->getInitializer()->getType()->isVectorTy()) { Out << "{ 0 }"; @@ -3047,8 +2756,7 @@ void CWriter::printFloatingPointConstants(Function &F) { // precision. // for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) - for (Instruction::op_iterator I_Op = I->op_begin(), E_Op = I->op_end(); - I_Op != E_Op; ++I_Op) + for (Instruction::op_iterator I_Op = I->op_begin(), E_Op = I->op_end(); I_Op != E_Op; ++I_Op) if (const Constant *C = dyn_cast<Constant>(I_Op)) printFloatingPointConstants(C); Out << '\n'; @@ -3071,39 +2779,44 @@ void CWriter::printFloatingPointConstants(const Constant *C) { FPConstantMap.count(FPC)) return; - FPConstantMap[FPC] = FPCounter; // Number the FP constants + FPConstantMap[FPC] = FPCounter; // Number the FP constants if (FPC->getType() == Type::getDoubleTy(FPC->getContext())) { double Val = FPC->getValueAPF().convertToDouble(); uint64_t i = FPC->getValueAPF().bitcastToAPInt().getZExtValue(); - Out << "static const ConstantDoubleTy FPConstant" << FPCounter++ << " = 0x" - << utohexstr(i) << "ULL; /* " << Val << " */\n"; + Out << "const ConstantDoubleTy FPConstant" << FPCounter++ + << " = 0x" << utohexstr(i) + << "ULL; /* " << Val << " */\n"; } else if (FPC->getType() == Type::getFloatTy(FPC->getContext())) { float Val = FPC->getValueAPF().convertToFloat(); - uint32_t i = (uint32_t)FPC->getValueAPF().bitcastToAPInt().getZExtValue(); - Out << "static const ConstantFloatTy FPConstant" << FPCounter++ << " = 0x" - << utohexstr(i) << "U; /* " << Val << " */\n"; + uint32_t i = (uint32_t)FPC->getValueAPF().bitcastToAPInt(). + getZExtValue(); + Out << "const ConstantFloatTy FPConstant" << FPCounter++ + << " = 0x" << utohexstr(i) + << "U; /* " << Val << " */\n"; } else if (FPC->getType() == Type::getX86_FP80Ty(FPC->getContext())) { // api needed to prevent premature destruction const APInt api = FPC->getValueAPF().bitcastToAPInt(); const uint64_t *p = api.getRawData(); - Out << "static const ConstantFP80Ty FPConstant" << FPCounter++ << " = { 0x" - << utohexstr(p[0]) << "ULL, 0x" << utohexstr((uint16_t)p[1]) - << ",{0,0,0}" - << "}; /* Long double constant */\n"; + Out << "const ConstantFP80Ty FPConstant" << FPCounter++ + << " = { 0x" << utohexstr(p[0]) + << "ULL, 0x" << utohexstr((uint16_t)p[1]) << ",{0,0,0}" + << "}; /* Long double constant */\n"; } else if (FPC->getType() == Type::getPPC_FP128Ty(FPC->getContext()) || - FPC->getType() == Type::getFP128Ty(FPC->getContext())) { + FPC->getType() == Type::getFP128Ty(FPC->getContext())) { const APInt api = FPC->getValueAPF().bitcastToAPInt(); const uint64_t *p = api.getRawData(); - Out << "static const ConstantFP128Ty FPConstant" << FPCounter++ << " = { 0x" - << utohexstr(p[0]) << ", 0x" << utohexstr(p[1]) - << "}; /* Long double constant */\n"; + Out << "const ConstantFP128Ty FPConstant" << FPCounter++ + << " = { 0x" + << utohexstr(p[0]) << ", 0x" << utohexstr(p[1]) + << "}; /* Long double constant */\n"; } else { llvm_unreachable("Unknown float type!"); } } + /// printSymbolTable - Run through symbol table looking for type names. If a /// type name is found, emit its declaration... /// @@ -3117,7 +2830,7 @@ void CWriter::printModuleTypes(raw_ostream &Out) { Out << "} llvmBitCastUnion;\n"; // Keep track of which types have been printed so far. - std::set<Type *> TypesPrinted; + std::set<Type*> TypesPrinted; // Loop over all structures then push them into the stack so they are // printed in the correct order. @@ -3126,9 +2839,8 @@ void CWriter::printModuleTypes(raw_ostream &Out) { // forward-declare all structs here first { - std::set<Type *> TypesPrinted; - for (auto it = TypedefDeclTypes.begin(), end = TypedefDeclTypes.end(); - it != end; ++it) { + std::set<Type*> TypesPrinted; + for (auto it = TypedefDeclTypes.begin(), end = TypedefDeclTypes.end(); it != end; ++it) { forwardDeclareStructs(Out, *it, TypesPrinted); } } @@ -3136,35 +2848,31 @@ void CWriter::printModuleTypes(raw_ostream &Out) { // forward-declare all function pointer typedefs (Issue #2) { - std::set<Type *> TypesPrinted; - for (auto it = TypedefDeclTypes.begin(), end = TypedefDeclTypes.end(); - it != end; ++it) { + std::set<Type*> TypesPrinted; + for (auto it = TypedefDeclTypes.begin(), end = TypedefDeclTypes.end(); it != end; ++it) { forwardDeclareFunctionTypedefs(Out, *it, TypesPrinted); } } + Out << "\n/* Types Definitions */\n"; - for (auto it = TypedefDeclTypes.begin(), end = TypedefDeclTypes.end(); - it != end; ++it) { + for (auto it = TypedefDeclTypes.begin(), end = TypedefDeclTypes.end(); it != end; ++it) { printContainedTypes(Out, *it, TypesPrinted); } Out << "\n/* Function definitions */\n"; // Question: Is UnnamedFunctionIDs ever non-empty? - for (DenseMap< - std::pair<FunctionType *, std::pair<AttributeList, CallingConv::ID>>, - unsigned>::iterator I = UnnamedFunctionIDs.begin(), - E = UnnamedFunctionIDs.end(); - I != E; ++I) { + for (DenseMap<std::pair<FunctionType*, + std::pair<AttributeList, CallingConv::ID> >, unsigned>::iterator + I = UnnamedFunctionIDs.begin(), E = UnnamedFunctionIDs.end(); + I != E; ++I) { Out << '\n'; - std::pair<FunctionType *, std::pair<AttributeList, CallingConv::ID>> F = - I->first; + std::pair<FunctionType*, std::pair<AttributeList, CallingConv::ID> > F = I->first; if (F.second.first == AttributeList() && F.second.second == CallingConv::C) - if (!TypesPrinted.insert(F.first).second) - continue; // already printed this above + if (!TypesPrinted.insert(F.first).second) continue; // already printed this above // FIXME: Removing apparently unused function call - need to check printFunctionDeclaration(Out, F.first, F.second); @@ -3172,9 +2880,9 @@ void CWriter::printModuleTypes(raw_ostream &Out) { // We may have collected some intrinsic prototypes to emit. // Emit them now, before the function that uses them is emitted - for (std::vector<Function *>::iterator I = prototypesToGen.begin(), - E = prototypesToGen.end(); - I != E; ++I) { + for (std::vector<Function*>::iterator + I = prototypesToGen.begin(), E = prototypesToGen.end(); + I != E; ++I) { Out << '\n'; Function *F = *I; printFunctionProto(Out, F); @@ -3182,12 +2890,9 @@ void CWriter::printModuleTypes(raw_ostream &Out) { } } -void CWriter::forwardDeclareStructs(raw_ostream &Out, Type *Ty, - std::set<Type *> &TypesPrinted) { - if (!TypesPrinted.insert(Ty).second) - return; - if (isEmptyType(Ty)) - return; +void CWriter::forwardDeclareStructs(raw_ostream &Out, Type *Ty, std::set<Type*> &TypesPrinted) { + if (!TypesPrinted.insert(Ty).second) return; + if (isEmptyType(Ty)) return; for (auto I = Ty->subtype_begin(); I != Ty->subtype_end(); ++I) { forwardDeclareStructs(Out, *I, TypesPrinted); @@ -3198,12 +2903,9 @@ void CWriter::forwardDeclareStructs(raw_ostream &Out, Type *Ty, } } -void CWriter::forwardDeclareFunctionTypedefs(raw_ostream &Out, Type *Ty, - std::set<Type *> &TypesPrinted) { - if (!TypesPrinted.insert(Ty).second) - return; - if (isEmptyType(Ty)) - return; +void CWriter::forwardDeclareFunctionTypedefs(raw_ostream &Out, Type *Ty, std::set<Type*> &TypesPrinted) { + if (!TypesPrinted.insert(Ty).second) return; + if (isEmptyType(Ty)) return; for (auto I = Ty->subtype_begin(); I != Ty->subtype_end(); ++I) { forwardDeclareFunctionTypedefs(Out, *I, TypesPrinted); @@ -3218,17 +2920,15 @@ void CWriter::forwardDeclareFunctionTypedefs(raw_ostream &Out, Type *Ty, // this one depends on. // void CWriter::printContainedTypes(raw_ostream &Out, Type *Ty, - std::set<Type *> &TypesPrinted) { + std::set<Type*> &TypesPrinted) { // Check to see if we have already printed this struct. - if (!TypesPrinted.insert(Ty).second) - return; + if (!TypesPrinted.insert(Ty).second) return; // Skip empty structs - if (isEmptyType(Ty)) - return; + if (isEmptyType(Ty)) return; // Print all contained types first. - for (Type::subtype_iterator I = Ty->subtype_begin(), E = Ty->subtype_end(); - I != E; ++I) + for (Type::subtype_iterator I = Ty->subtype_begin(), + E = Ty->subtype_end(); I != E; ++I) printContainedTypes(Out, *I, TypesPrinted); if (StructType *ST = dyn_cast<StructType>(Ty)) { @@ -3249,23 +2949,22 @@ static inline bool isFPIntBitCast(Instruction &I) { Type *SrcTy = I.getOperand(0)->getType(); Type *DstTy = I.getType(); return (SrcTy->isFloatingPointTy() && DstTy->isIntegerTy()) || - (DstTy->isFloatingPointTy() && SrcTy->isIntegerTy()); + (DstTy->isFloatingPointTy() && SrcTy->isIntegerTy()); } void CWriter::printFunction(Function &F) { bool isKernel = false; - if (NamedMDNode *KernelMD = - F.getParent()->getNamedMetadata("opencl.kernels")) { + if (NamedMDNode * KernelMD = F.getParent()->getNamedMetadata("opencl.kernels")) { for (auto iter : KernelMD->operands()) { - // DEBUG( errs() << "Kernel Metadata: " << *iter << "\n"); + DEBUG( errs() << "Kernel Metadata: " << *iter << "\n"); const MDOperand *KernelMDOp = iter->operands().begin(); Metadata *KMD = KernelMDOp->get(); - if (ValueAsMetadata *KMDVAM = dyn_cast<ValueAsMetadata>(KMD)) { + if(ValueAsMetadata *KMDVAM = dyn_cast<ValueAsMetadata>(KMD)){ Value *KMDVal = KMDVAM->getValue(); Function *KMDFunc = dyn_cast<Function>(KMDVal); - if (KMDFunc == &F) { - // DEBUG(errs() << "-->Kernel Func: " << KMDFunc->getName() << "\n"); + if(KMDFunc == &F) { + DEBUG(errs() << "-->Kernel Func: " << KMDFunc->getName() << "\n"); isKernel = true; } } @@ -3276,15 +2975,12 @@ void CWriter::printFunction(Function &F) { bool isStructReturn = F.hasStructRetAttr(); assert(!F.isDeclaration()); - if (F.hasDLLImportStorageClass()) - Out << "__declspec(dllimport) "; - if (F.hasDLLExportStorageClass()) - Out << "__declspec(dllexport) "; - if (F.hasLocalLinkage()) - Out << "static "; - printFunctionProto( - Out, F.getFunctionType(), - std::make_pair(F.getAttributes(), F.getCallingConv()), GetValueName(&F), + if (F.hasDLLImportStorageClass()) Out << "__declspec(dllimport) "; + if (F.hasDLLExportStorageClass()) Out << "__declspec(dllexport) "; + if (F.hasLocalLinkage()) Out << "static "; + printFunctionProto(Out, F.getFunctionType(), + std::make_pair(F.getAttributes(), F.getCallingConv()), + GetValueName(&F), F.arg_begin(), // NOTE: replacing ArgumentList (LLVM-4) with arg iterator //&F.getArgumentList(), isKernel); @@ -3294,25 +2990,27 @@ void CWriter::printFunction(Function &F) { // If this is a struct return function, handle the result with magic. if (isStructReturn) { Type *StructTy = - cast<PointerType>(F.arg_begin()->getType())->getElementType(); + cast<PointerType>(F.arg_begin()->getType())->getElementType(); Out << " "; - printTypeName(Out, StructTy, false) - << " StructReturn; /* Struct return temporary */\n"; + printTypeName(Out, StructTy, false) << " StructReturn; /* Struct return temporary */\n"; Out << " "; printTypeName(Out, F.arg_begin()->getType(), false); Out << GetValueName(&*F.arg_begin()) << " = &StructReturn;\n"; } + + // Output all floating point constants that cannot be printed accurately. + printFloatingPointConstants(F); bool PrintedVar = false; // print local variable information for the function for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) { if (AllocaInst *AI = isDirectAlloca(&*I)) { - // DEBUG(errs() << "Processing alloca inst: " << *AI << "\n"); + DEBUG(errs() << "Processing alloca inst: " << *AI << "\n"); unsigned Alignment = AI->getAlignment(); - bool IsOveraligned = Alignment && Alignment > TD->getABITypeAlignment( - AI->getAllocatedType()); + bool IsOveraligned = Alignment && + Alignment > TD->getABITypeAlignment(AI->getAllocatedType()); Out << " "; // if (IsOveraligned) // Out << "__MSALIGN__(" << Alignment << ") "; @@ -3321,22 +3019,21 @@ void CWriter::printFunction(Function &F) { if (IsOveraligned) Out << " __attribute__((aligned(" << Alignment << ")))"; if (AI->isArrayAllocation()) { - // DEBUG(errs() << "Alloca is an array allocation!\n"); - unsigned arraySize = - dyn_cast<ConstantInt>(AI->getArraySize())->getZExtValue(); + DEBUG(errs() << "Alloca is an array allocation!\n"); + unsigned arraySize = dyn_cast<ConstantInt>(AI->getArraySize())->getZExtValue(); Out << "[" << arraySize << "]"; } Out << "; /* Address-exposed local */\n"; PrintedVar = true; - } else if (!isEmptyType(I->getType()) && !isInlinableInst(*I)) { + } else if (!isEmptyType(I->getType()) && + !isInlinableInst(*I)) { Out << " "; printTypeName(Out, I->getType(), false) << ' ' << GetValueName(&*I); Out << ";\n"; - if (isa<PHINode>(*I)) { // Print out PHI node temporaries as well... + if (isa<PHINode>(*I)) { // Print out PHI node temporaries as well... Out << " "; - printTypeName(Out, I->getType(), false) - << ' ' << (GetValueName(&*I) + "__PHI_TEMPORARY"); + printTypeName(Out, I->getType(), false) << ' ' << (GetValueName(&*I)+"__PHI_TEMPORARY"); Out << ";\n"; } PrintedVar = true; @@ -3346,7 +3043,7 @@ void CWriter::printFunction(Function &F) { // variable to hold the result of the BitCast. if (isFPIntBitCast(*I)) { Out << " llvmBitCastUnion " << GetValueName(&*I) - << "__BITCAST_TEMPORARY;\n"; + << "__BITCAST_TEMPORARY;\n"; PrintedVar = true; } } @@ -3357,13 +3054,11 @@ void CWriter::printFunction(Function &F) { // print the basic blocks // for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) { - std::set<BasicBlock *> VisitSet; - BasicBlock *entry = &(F.getEntryBlock()); - // starting printing from entry, then CFG traversal will print the reachable - // blocks. + std::set<BasicBlock*> VisitSet; + BasicBlock* entry = &(F.getEntryBlock()); + // starting printing from entry, then CFG traversal will print the reachable blocks. printBBorLoop(entry); - // for (df_iterator<BasicBlock*> BI = df_begin(entry), BE = df_end(entry); - // BI!=BE; ++BI) { + // for (df_iterator<BasicBlock*> BI = df_begin(entry), BE = df_end(entry); BI!=BE; ++BI) { // BasicBlock *BB = *BI; // printBBorLoop(BB); // if(VisitedBlocks.find(BB) == VisitedBlocks.end()) { @@ -3380,29 +3075,29 @@ void CWriter::printFunction(Function &F) { Out << "}\n\n"; } -bool CWriter::extractIndVarChain(Instruction *Inst, - std::stack<Instruction *> *IndVarChain, - Instruction *Branch, unsigned indent) { - // Traverse def-use chain of induction variable to make sure that - // it ends at the branch. Keep stack of all instructions leading there. - for (User *U : Inst->users()) { - // DEBUG(errs() << std::string(indent, '-')); - // DEBUG(errs() << "->Found user: " << *U << "\n"); - if (Instruction *UInst = dyn_cast<Instruction>(U)) { - if (UInst == Branch) { - // DEBUG(errs() << "Found correct path, returning!\n"); + +bool CWriter::extractIndVarChain(Instruction *Inst, std::stack<Instruction*> *IndVarChain, Instruction *Branch, unsigned indent) { + //Traverse def-use chain of induction variable to make sure that + //it ends at the branch. Keep stack of all instructions leading there. + for(User *U : Inst->users()) { + DEBUG(errs() << std::string(indent, '-')); + DEBUG(errs() << "->Found user: " << *U << "\n"); + if(Instruction *UInst = dyn_cast<Instruction>(U)) { + if(UInst == Branch) { + DEBUG(errs() << "Found correct path, returning!\n"); return true; - } else if (isa<PHINode>(UInst)) { - // DEBUG(errs() << "Reached a PHI Node => Wrong path! - // Returning!\n"); + } + else if (isa<PHINode>(UInst)) { + DEBUG(errs() << "Reached a PHI Node => Wrong path! Returning!\n"); continue; - } else { + } + else { IndVarChain->push(UInst); - if (extractIndVarChain(UInst, IndVarChain, Branch, indent + 2)) { + if(extractIndVarChain(UInst, IndVarChain, Branch, indent+2)) { return true; - } else { - // DEBUG(errs() << "Wrong path, popping: " << - // *(IndVarChain->top()) << "\n"); + } + else { + DEBUG(errs() << "Wrong path, popping: " << *(IndVarChain->top()) << "\n"); IndVarChain->pop(); } } @@ -3412,74 +3107,66 @@ bool CWriter::extractIndVarChain(Instruction *Inst, return false; } -bool CWriter::findLoopBranch(BranchInst **LBranch, BasicBlock *CurBlock, - BasicBlock *LHeader, - std::set<BasicBlock *> *visitSet) { +bool CWriter::findLoopBranch(BranchInst **LBranch, BasicBlock* CurBlock, BasicBlock* LHeader, std::set<BasicBlock*>*visitSet) { bool result = false; - // DEBUG(errs() << "Finding loop branch in " << CurBlock->getName() << - // "!\n"); - if (BranchInst *LBranchTemp = - dyn_cast<BranchInst>(CurBlock->getTerminator())) { - // DEBUG(errs() << "Branch: " << *LBranchTemp << "\n"); - if (LBranchTemp->isConditional()) { - if (LBranchTemp->getSuccessor(0) == LHeader || - LBranchTemp->getSuccessor(1) == LHeader) { + DEBUG(errs() << "Finding loop branch in " << CurBlock->getName() << "!\n"); + if(BranchInst *LBranchTemp = dyn_cast<BranchInst>(CurBlock->getTerminator())) { + DEBUG(errs() << "Branch: " << *LBranchTemp << "\n"); + if(LBranchTemp->isConditional()) { + if(LBranchTemp->getSuccessor(0) == LHeader || LBranchTemp->getSuccessor(1) == LHeader) { *LBranch = LBranchTemp; - // DEBUG(errs() << "Found Loop branch: " << **LBranch << "\n"); + DEBUG(errs() << "Found Loop branch: " << **LBranch << "\n"); result = true; } else { - BasicBlock *NextBlock1 = LBranchTemp->getSuccessor(0); - BasicBlock *NextBlock2 = LBranchTemp->getSuccessor(1); - if (visitSet->find(NextBlock1) == visitSet->end()) { - // DEBUG(errs() << "Visiting unvisited node: " << - // NextBlock1->getName() << "\n"); + BasicBlock* NextBlock1 = LBranchTemp->getSuccessor(0); + BasicBlock* NextBlock2 = LBranchTemp->getSuccessor(1); + if(visitSet->find(NextBlock1) == visitSet->end()) { + DEBUG(errs() << "Visiting unvisited node: " << NextBlock1->getName() << "\n"); visitSet->insert(NextBlock1); result |= findLoopBranch(LBranch, NextBlock1, LHeader, visitSet); } - if (visitSet->find(NextBlock2) == visitSet->end()) { - // DEBUG(errs() << "Visiting unvisited node: " << - // NextBlock2->getName() << "\n"); + if(visitSet->find(NextBlock2) == visitSet->end()) { + DEBUG(errs() << "Visiting unvisited node: " << NextBlock2->getName() << "\n"); visitSet->insert(NextBlock2); result |= findLoopBranch(LBranch, NextBlock2, LHeader, visitSet); } } } else { - if (LBranchTemp->getSuccessor(0) == LHeader) { + if(LBranchTemp->getSuccessor(0) == LHeader) { *LBranch = LBranchTemp; - // DEBUG(errs() << "Found Loop branch: " << **LBranch << "\n"); + DEBUG(errs() << "Found Loop branch: " << **LBranch << "\n"); result = true; } else { BasicBlock *NextBlock = LBranchTemp->getSuccessor(0); - if (visitSet->find(NextBlock) == visitSet->end()) { - // DEBUG(errs() << "Visiting unvisited node: " << - // NextBlock->getName() << "\n"); + if(visitSet->find(NextBlock) == visitSet->end()) { + DEBUG(errs() << "Visiting unvisited node: " << NextBlock->getName() << "\n"); visitSet->insert(NextBlock); result |= findLoopBranch(LBranch, NextBlock, LHeader, visitSet); } } } } - return result; + return result; } bool CWriter::traverseUseDefChain(Instruction *I, PHINode *PI) { - // DEBUG(errs() << "traversing: " << *I << "\n"); + DEBUG(errs() << "traversing: " << *I << "\n"); bool result = false; - if (PHINode *PHI = dyn_cast<PHINode>(I)) { + if(PHINode *PHI = dyn_cast<PHINode>(I)) { if (PI == PHI) { - // DEBUG(errs() << "returning true\n"); + DEBUG(errs() << "returning true\n"); result = true; } else { - // DEBUG(errs() << "returning false\n"); + DEBUG(errs() << "returning false\n"); return false; } } else { for (Use &U : I->operands()) { - if (Instruction *UInst = dyn_cast<Instruction>(U)) { + if(Instruction *UInst = dyn_cast<Instruction>(U)) { result |= traverseUseDefChain(UInst, PI); - } + } } } return result; @@ -3489,2395 +3176,2260 @@ void CWriter::printLoop(Loop *L) { PredicatedScalarEvolution PSE(*SE, *L); Out << "\n\n/* Processing Loop Block: " << L->getName() << " */\n"; + DEBUG(errs() << "\n\n/* Processing Loop Block: " << L->getName() << " */\n"); - // if(simplifyLoop(L, DT, LI, SE, AC, true)) { - // DEBUG(errs() << "Simplified loop!\n" << *L << "\n"); - // } PHINode *InductionVariable; // auto *LoopLatch = L->getLoopLatch(); - auto *ExitingBlock = L->getExitingBlock(); - // DEBUG(errs() << "Exiting Block: " << ExitingBlock->getName() << "\n"); - auto *ExitingBranch = ExitingBlock->getTerminator(); - // DEBUG(errs() << "Exiting Branch: " << *ExitingBranch << "\n"); InductionDescriptor ID; - if (L->getLoopPreheader() == nullptr) { - // DEBUG(errs() << "Loop has no preheader!\n"); - } - // DEBUG(errs() << "Looking for induction variables\n"); - // if (PHINode *IndVar = L->getCanonicalInductionVariable()) { - // InductionVariable = IndVar; - // DEBUG(errs() << "Found canonical induction variable:\n" << *IndVar << - // "\n"); - // } + DEBUG(errs() << "Looking for induction variables\n"); bool found = false; - for (auto I = L->getHeader()->begin(); isa<PHINode>(I); ++I) { - PHINode *PHI = cast<PHINode>(I); - // DEBUG(errs() << "Phi Node: " << *PHI << "\n"); - if (InductionDescriptor::isInductionPHI(PHI, L, PSE, ID)) { - // DEBUG(errs() << "Found induction: " << *PHI << "\n"); - InductionVariable = PHI; - found = true; - break; - } - } + if (PHINode *IndVar = L->getCanonicalInductionVariable()) { + InductionVariable = IndVar; + found = true; + DEBUG(errs() << "Found canonical induction variable:\n" << *IndVar << "\n"); + } else { + for (auto I = L->getHeader()->begin(); isa<PHINode>(I); ++I) { + PHINode *PHI = cast<PHINode>(I); + DEBUG(errs() << "Phi Node: " << *PHI << "\n"); + if(InductionDescriptor::isInductionPHI(PHI,L,PSE,ID)) { + DEBUG(errs() << "Found induction: " << *PHI << "\n"); + InductionVariable = PHI; + found = true; + break; + } + } + } + + if(!found) { + llvm_unreachable("Couldn't find induction Variable in loop!\n"); + } + + LInductionVars.insert(InductionVariable); + LoopIndVarsMap.insert(std::pair<Loop*, PHINode*>(L,InductionVariable)); + + Value *IV = dyn_cast<Value>(InductionVariable); + std::string IVName = GetValueName(IV); + + Optional<Loop::LoopBounds> OLB = L->getBounds(*SE); + if(OLB.hasValue()) { + Loop::LoopBounds LB = OLB.getValue(); + Value *StartValue = &(LB.getInitialIVValue()); + Instruction *StepInstruction = &(LB.getStepInst()); + Value *StepValue = LB.getStepValue(); + Value *FinalValue = &(LB.getFinalIVValue()); + ICmpInst::Predicate LoopPredicate = LB.getCanonicalPredicate(); + std::string BranchPredicate; + switch(LoopPredicate) { + case ICmpInst::ICMP_EQ: BranchPredicate = " == "; break; + case ICmpInst::ICMP_NE: BranchPredicate = " != "; break; + case ICmpInst::ICMP_ULE: + case ICmpInst::ICMP_SLE: BranchPredicate = " < "; break; + case ICmpInst::ICMP_UGE: + case ICmpInst::ICMP_SGE: BranchPredicate = " > "; break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_SLT: BranchPredicate = " <= "; break; + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_SGT: BranchPredicate = " >= "; break; + default: llvm_unreachable("Illegal ICmp predicate"); + } + DEBUG( + errs() << "Found a Loop Bounds Object!\n"; + errs() << "IV: " << *IV<< "\n"; + errs() << "StartValue: " << *StartValue<< "\n"; + errs() << "StepInstruction: " << *StepInstruction<< "\n"; + errs() << "StepValue: " << *StepValue<< "\n"; + errs() << "FinalValue: " << *FinalValue<< "\n"; + errs() << "Branch Predicate: " << BranchPredicate<< "\n"; + errs() << "Direction: " << ((LB.getDirection() == Loop::LoopBounds::Direction::Increasing) ? "increasing" : "decreasing") << "\n"; + ) + + std::string startStr; + if (ConstantInt *startConst = dyn_cast<ConstantInt>(StartValue)) { + startStr = std::to_string(startConst->getSExtValue()); + } else { + startStr = GetValueName(StartValue); + } + std::string finalStr; + if (ConstantInt *finalConst = dyn_cast<ConstantInt>(FinalValue)) { + finalStr = std::to_string(finalConst->getSExtValue()); + } else { + finalStr = GetValueName(FinalValue); + } + std::string stepStr; + if (ConstantInt *stepConst = dyn_cast<ConstantInt>(StepValue)) { + stepStr = std::to_string(stepConst->getSExtValue()); + } else { + stepStr = GetValueName(StepValue); + } + + DEBUG( + errs() << "\n for ( " << IVName << " = " << startStr << "; " + << IVName << BranchPredicate << finalStr << "; " + << IVName << " = " << IVName << " + " << stepStr << ") {\n"; + ) + + Out << "\n for ( " << IVName << " = " << startStr << "; " + << IVName << BranchPredicate << finalStr << "; " + << IVName << " = " << IVName << " + " << stepStr << ") {\n"; + + } else { + llvm_unreachable("No Loop Bounds!"); + DEBUG(errs() << "could not find a loop bounds object, searching for bounds manually!\n"); + auto *ExitingBlock = L->getExitingBlock(); + DEBUG(errs() << "Exiting Block: " << ExitingBlock->getName() << "\n"); + auto *ExitingBranch = ExitingBlock->getTerminator(); + DEBUG(errs() << "Exiting Branch: " << *ExitingBranch << "\n"); + Value *StartValue = ID.getStartValue(); + const SCEV *Step = ID.getStep(); + // unsigned IterationCount = SE->getSmallConstantMaxTripCount(L); + + std::string IVOp; + + if (const SCEVConstant *stepConst = dyn_cast<SCEVConstant>(Step)) { + if(stepConst->getAPInt().isNonNegative()) { + IVOp = " + "; + } + } + + + std::string BranchPredicate; + ICmpInst *BranchCondition = dyn_cast<ICmpInst>(dyn_cast<BranchInst>(ExitingBranch)->getCondition()); + switch(BranchCondition->getPredicate()) { + case ICmpInst::ICMP_EQ: BranchPredicate = " != "; break; + case ICmpInst::ICMP_NE: BranchPredicate = " == "; break; + case ICmpInst::ICMP_ULE: + case ICmpInst::ICMP_SLE: BranchPredicate = " > "; break; + case ICmpInst::ICMP_UGE: + case ICmpInst::ICMP_SGE: BranchPredicate = " < "; break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_SLT: BranchPredicate = " >= "; break; + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_SGT: BranchPredicate = " <= "; break; + default: llvm_unreachable("Illegal ICmp predicate"); + } + + DEBUG(errs() << "Branch Condition: " << *BranchCondition << "\n"); + + std::string compLHS, compRHS; + Value *CondOp1 = BranchCondition->getOperand(0); + DEBUG(errs() << "CondOp1: " << *CondOp1 << "\n"); + if (Constant *constOp1 = dyn_cast<Constant>(CondOp1)) { + DEBUG(errs() << "Condition Operand is a constant, inserting it as is.\n"); + compLHS = (constOp1->getUniqueInteger()).toString(10,1); + } else { + DEBUG(errs() << "Condition Operand is not a constant, "); + if(traverseUseDefChain(dyn_cast<Instruction>(CondOp1), InductionVariable)) { + DEBUG(errs() << "it is the IV.\n"); + compLHS = GetValueName(IV); + } else { + DEBUG(errs() << "it is another variable.\n"); + compLHS = GetValueName(CondOp1); + } + } + Value *CondOp2 = BranchCondition->getOperand(1); + DEBUG(errs() << "CondOp2: " << *CondOp2 << "\n"); + if (Constant *constOp2 = dyn_cast<Constant>(CondOp2)) { + DEBUG(errs() << "Condition Operand is a constant, inserting it as is.\n"); + compRHS = (constOp2->getUniqueInteger()).toString(10,1); + } else { + DEBUG(errs() << "Condition Operand is not a constant.\n"); + if(traverseUseDefChain(dyn_cast<Instruction>(CondOp2), InductionVariable)) { + DEBUG(errs() << "It is the IV.\n"); + compRHS = GetValueName(IV); + } else { + DEBUG(errs() << "It is another variable.\n"); + compRHS = GetValueName(CondOp2); + } + } + + std::string startStr; + if (Constant *startConst = dyn_cast<Constant>(StartValue)) { + startStr = (startConst->getUniqueInteger()).toString(10,1); + } else { + startStr = GetValueName(StartValue); + } + + + DEBUG(errs() << " for ( " << IVName << " = " << startStr << "; " + << compLHS << BranchPredicate << compRHS << "; " + << IVName << " = " << IVName << IVOp << *Step << ") {\n"); + + Out << "\n for ( " << IVName << " = " << startStr << "; " + << compLHS << BranchPredicate << compRHS << "; " + << IVName << " = " << IVName << IVOp << *Step << ") {\n"; + } + + + BasicBlock *BB = L->getHeader(); + // printBBorLoop(BB); + printBasicBlock(BB); + // Loop *BBLoop = LI->getLoopFor(BB); + // if (BBLoop == L) + // printBasicBlock(BB); + // else if (BB == BBLoop->getHeader() && BBLoop->getParentLoop() == L) + // printLoop(BBLoop); + + // Out << " do { /* Syntactic loop '" << L->getHeader()->getName() + // << "' to make GCC happy */\n"; + // for (unsigned i = 0, e = L->getBlocks().size(); i != e; ++i) { + // BasicBlock *BB = L->getBlocks()[i]; + // Loop *BBLoop = LI->getLoopFor(BB); + // if (BBLoop == L) + // printBasicBlock(BB); + // else if (BB == BBLoop->getHeader() && BBLoop->getParentLoop() == L) + // printLoop(BBLoop); + // } + // Out << " } \n"; +} - if (!found) { - llvm_unreachable("Couldn't find induction Variable in loop!\n"); - } +void CWriter::printBasicBlock(BasicBlock *BB) { + DEBUG(errs() << "\n\nProcessing Basic Block: " << BB->getName() << "\n"); + Out << "\n\n/* Processing Basic Block: " << BB->getName() << " */\n"; + + // Don't print the label for the basic block if there are no uses, or if + // the only terminator use is the predecessor basic block's terminator. + // We have to scan the use list because PHI nodes use basic blocks too but + // do not require a label to be generated. + // + bool NeedsLabel = false; + for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) + if (isGotoCodeNecessary(*PI, BB)) { + NeedsLabel = true; + break; + } + + // if (NeedsLabel) Out << "/* " << GetValueName(BB) << ": */\n"; + Out << "/* " << GetValueName(BB) << ": */\n"; + + // Output all of the instructions in the basic block... + for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E; + ++II) { + Instruction *I = &*II; + DEBUG(errs() << "*********Processing: " << *I << "\n"); + bool skip = false; + for(Use &U : I->operands()) { + Value *v = U.get(); + if(PHINode *PN = dyn_cast<PHINode>(v)) { + if (LInductionVars.find(PN) != LInductionVars.end()) { + bool UserPHI = false; + bool UserCMP = false; + bool UserOTHER = false; + DEBUG(errs() << "Instruction uses induction variable\n"); + for (User *IUser : I->users()) { + if (Instruction *UserInst = dyn_cast<Instruction>(IUser)) { + DEBUG(errs() << "User: " << *UserInst << "\n"); + if (dyn_cast<PHINode>(UserInst)) { + UserPHI = true; + } else if (dyn_cast<ICmpInst>(UserInst)) { + UserCMP = true; + } else { + UserOTHER = true; + } + // skip = true; + // break; + } + } + if (UserPHI && UserCMP && !UserOTHER) { + skip = true; + } + } + } + if (skip) + break; + } + if(skip){ + DEBUG(errs() << "Skipping instruction that increments Induction Variable!\n"); + Out << "/* Skipped induction variable use: " << *I << " */\n"; + continue; + } + if(PHINode *PN = dyn_cast<PHINode>(I)) { + if (LInductionVars.find(PN) != LInductionVars.end()) { + DEBUG(errs() << "Skipping PHINode for Induction Variable!\n"); + Out << "/* PHINode of induction variable was here */\n"; + continue; + } + } + if (!isInlinableInst(*II) && !isDirectAlloca(&*II)) { + if (!isEmptyType(II->getType()) && + !isInlineAsm(*II)) + outputLValue(&*II); + else + Out << " "; + writeInstComputationInline(*II); + Out << ";\n"; + } else { + DEBUG(errs() << "Skipping inlinable or direct alloca!\n"); + } + } + + // Don't emit prefix or suffix for the terminator. + visit(*BB->getTerminator()); +} - LInductionVars.insert(InductionVariable); - LoopIndVarsMap.insert(std::pair<Loop *, PHINode *>(L, InductionVariable)); - - Value *IV = dyn_cast<Value>(InductionVariable); - std::string IVName = GetValueName(IV); - - Optional<Loop::LoopBounds> OLB = L->getBounds(*SE); - if (OLB.hasValue()) { - Loop::LoopBounds LB = OLB.getValue(); - Value *StartValue = &(LB.getInitialIVValue()); - Instruction *StepInstruction = &(LB.getStepInst()); - Value *StepValue = LB.getStepValue(); - Value *FinalValue = &(LB.getFinalIVValue()); - ICmpInst::Predicate LoopPredicate = LB.getCanonicalPredicate(); - std::string BranchPredicate; - switch (LoopPredicate) { - case ICmpInst::ICMP_EQ: - BranchPredicate = " == "; - break; - case ICmpInst::ICMP_NE: - BranchPredicate = " != "; - break; - case ICmpInst::ICMP_ULE: - case ICmpInst::ICMP_SLE: - BranchPredicate = " < "; - break; - case ICmpInst::ICMP_UGE: - case ICmpInst::ICMP_SGE: - BranchPredicate = " > "; - break; - case ICmpInst::ICMP_ULT: - case ICmpInst::ICMP_SLT: - BranchPredicate = " <= "; - break; - case ICmpInst::ICMP_UGT: - case ICmpInst::ICMP_SGT: - BranchPredicate = " >= "; - break; - default: - llvm_unreachable("Illegal ICmp predicate"); - } - errs() << "IV: " << *IV << "\n"; - errs() << "StartValue: " << *StartValue << "\n"; - errs() << "StepInstruction: " << *StepInstruction << "\n"; - errs() << "StepValue: " << *StepValue << "\n"; - errs() << "FinalValue: " << *FinalValue << "\n"; - errs() << "Branch Predicate: " << BranchPredicate << "\n"; - errs() << "Direction: " - << ((LB.getDirection() == Loop::LoopBounds::Direction::Increasing) - ? "increasing" - : "decreasing") - << "\n"; - - std::string startStr; - if (ConstantInt *startConst = dyn_cast<ConstantInt>(StartValue)) { - startStr = std::to_string(startConst->getSExtValue()); - } else { - startStr = GetValueName(StartValue); - } - std::string finalStr; - if (ConstantInt *finalConst = dyn_cast<ConstantInt>(FinalValue)) { - finalStr = std::to_string(finalConst->getSExtValue()); - } else { - finalStr = GetValueName(FinalValue); - } - std::string stepStr; - if (ConstantInt *stepConst = dyn_cast<ConstantInt>(StepValue)) { - stepStr = std::to_string(stepConst->getSExtValue()); - } else { - stepStr = GetValueName(StepValue); - } - errs() << "\n for ( " << IVName << " = " << startStr << "; " << IVName - << BranchPredicate << finalStr << "; " << IVName << " = " << IVName - << " + " << stepStr << ") {\n"; +// Specific Instruction type classes... note that all of the casts are +// necessary because we use the instruction classes as opaque types... +// +void CWriter::visitReturnInst(ReturnInst &I) { + // If this is a struct return function, return the temporary struct. + bool isStructReturn = I.getParent()->getParent()->hasStructRetAttr(); + + if (isStructReturn) { + Out << " return StructReturn;\n"; + return; + } + + // Don't output a void return if this is the last basic block in the function + // unless that would make the basic block empty + if (I.getNumOperands() == 0 && + &*--I.getParent()->getParent()->end() == I.getParent() && + &*I.getParent()->begin() != &I) { + return; + } + + Out << " return"; + if (I.getNumOperands()) { + Out << ' '; + writeOperand(I.getOperand(0), ContextCasted); + } + Out << ";\n"; +} - Out << "\n for ( " << IVName << " = " << startStr << "; " << IVName - << BranchPredicate << finalStr << "; " << IVName << " = " << IVName - << " + " << stepStr << ") {\n"; +void CWriter::visitSwitchInst(SwitchInst &SI) { + Value* Cond = SI.getCondition(); + unsigned NumBits = cast<IntegerType>(Cond->getType())->getBitWidth(); + + if (SI.getNumCases() == 0) { // unconditional branch + printPHICopiesForSuccessor (SI.getParent(), SI.getDefaultDest(), 2); + printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2); + Out << "\n"; + + } else if (NumBits <= 64) { // model as a switch statement + Out << " switch ("; + writeOperand(Cond); + Out << ") {\n default:\n"; + printPHICopiesForSuccessor (SI.getParent(), SI.getDefaultDest(), 2); + printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2); + + + // CHECK: Needs much testing + for (auto Case : SI.cases()) { + ConstantInt* CaseVal = Case.getCaseValue(); + BasicBlock* Succ = Case.getCaseSuccessor(); + Out << " case "; + writeOperand(CaseVal); + Out << ":\n"; + printPHICopiesForSuccessor (SI.getParent(), Succ, 2); + if (isGotoCodeNecessary(SI.getParent(), Succ)) + printBranchToBlock(SI.getParent(), Succ, 2); + else + Out << " break;\n"; + } + Out << " }\n"; + + } else { // model as a series of if statements + Out << " "; + // CHECK: Needs much testing + for (auto Case : SI.cases()) { + Out << "if ("; + ConstantInt* CaseVal = Case.getCaseValue(); + BasicBlock* Succ = Case.getCaseSuccessor(); + ICmpInst *icmp = new ICmpInst(CmpInst::ICMP_EQ, Cond, CaseVal); + visitICmpInst(*icmp); + delete icmp; + Out << ") {\n"; + printPHICopiesForSuccessor (SI.getParent(), Succ, 2); + printBranchToBlock(SI.getParent(), Succ, 2); + Out << " } else "; + } + Out << "{\n"; + printPHICopiesForSuccessor (SI.getParent(), SI.getDefaultDest(), 2); + printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2); + Out << " }\n"; + } + Out << "\n"; +} - } else { - llvm_unreachable("No Loop Bounds!"); - Value *StartValue = ID.getStartValue(); - const SCEV *Step = ID.getStep(); - // unsigned IterationCount = SE->getSmallConstantMaxTripCount(L); - // DEBUG(errs() << "StartValue: " << *StartValue << "\nStep: " << *Step << - // "\nIterationCount: " << IterationCount << "\n"); - - std::string IVOp; - - if (const SCEVConstant *stepConst = dyn_cast<SCEVConstant>(Step)) { - if (stepConst->getAPInt().isNonNegative()) { - IVOp = " + "; - } - } +void CWriter::visitIndirectBrInst(IndirectBrInst &IBI) { + Out << " goto *(void*)("; + writeOperand(IBI.getOperand(0)); + Out << ");\n"; +} - std::string BranchPredicate; - ICmpInst *BranchCondition = - dyn_cast<ICmpInst>(dyn_cast<BranchInst>(ExitingBranch)->getCondition()); - switch (BranchCondition->getPredicate()) { - case ICmpInst::ICMP_EQ: - BranchPredicate = " != "; - break; - case ICmpInst::ICMP_NE: - BranchPredicate = " == "; - break; - case ICmpInst::ICMP_ULE: - case ICmpInst::ICMP_SLE: - BranchPredicate = " > "; - break; - case ICmpInst::ICMP_UGE: - case ICmpInst::ICMP_SGE: - BranchPredicate = " < "; - break; - case ICmpInst::ICMP_ULT: - case ICmpInst::ICMP_SLT: - BranchPredicate = " >= "; - break; - case ICmpInst::ICMP_UGT: - case ICmpInst::ICMP_SGT: - BranchPredicate = " <= "; - break; - default: - llvm_unreachable("Illegal ICmp predicate"); - } +void CWriter::visitUnreachableInst(UnreachableInst &I) { + Out << " __builtin_unreachable();\n\n"; +} - // DEBUG(errs() << "Branch Condition: " << *BranchCondition << "\n"); +bool CWriter::isGotoCodeNecessary(BasicBlock *From, BasicBlock *To) { + /// FIXME: This should be reenabled, but loop reordering safe!! + return true; - std::string compLHS, compRHS; - Value *CondOp1 = BranchCondition->getOperand(0); - // DEBUG(errs() << "CondOp1: " << *CondOp1 << "\n"); - if (Constant *constOp1 = dyn_cast<Constant>(CondOp1)) { - // DEBUG(errs() << "Condition Operand is a constant, inserting it as - // is.\n"); - compLHS = (constOp1->getUniqueInteger()).toString(10, 1); - } else { - // DEBUG(errs() << "Condition Operand is not a constant, "); - if (traverseUseDefChain(dyn_cast<Instruction>(CondOp1), - InductionVariable)) { - // DEBUG(errs() << "it is the IV.\n"); - compLHS = GetValueName(IV); - } else { - // DEBUG(errs() << "it is another variable.\n"); - compLHS = GetValueName(CondOp1); - } - } - Value *CondOp2 = BranchCondition->getOperand(1); - // DEBUG(errs() << "CondOp2: " << *CondOp2 << "\n"); - if (Constant *constOp2 = dyn_cast<Constant>(CondOp2)) { - // DEBUG(errs() << "Condition Operand is a constant, inserting it as - // is.\n"); - compRHS = (constOp2->getUniqueInteger()).toString(10, 1); - } else { - // DEBUG(errs() << "Condition Operand is not a constant.\n"); - if (traverseUseDefChain(dyn_cast<Instruction>(CondOp2), - InductionVariable)) { - // DEBUG(errs() << "It is the IV.\n"); - compRHS = GetValueName(IV); - } else { - // DEBUG(errs() << "It is another variable.\n"); - compRHS = GetValueName(CondOp2); - } - } + if (std::next(Function::iterator(From)) != Function::iterator(To)) + return true; // Not the direct successor, we need a goto. - std::string startStr; - if (Constant *startConst = dyn_cast<Constant>(StartValue)) { - startStr = (startConst->getUniqueInteger()).toString(10, 1); - } else { - startStr = GetValueName(StartValue); - } + //isa<SwitchInst>(From->getTerminator()) - // DEBUG(errs() << " for ( " << IVName << " = " << startStr << "; " - // << compLHS << BranchPredicate << compRHS << "; " - // << IVName << " = " << IVName << IVOp << *Step << ") {\n"); + if (LI->getLoopFor(From) != LI->getLoopFor(To)) + return true; + return false; +} - Out << "\n for ( " << IVName << " = " << startStr << "; " << compLHS - << BranchPredicate << compRHS << "; " << IVName << " = " << IVName - << IVOp << *Step << ") {\n"; - } +void CWriter::printPHICopiesForSuccessor (BasicBlock *CurBlock, + BasicBlock *Successor, + unsigned Indent) { + Out << "/* Printing PHIs for " << CurBlock->getName() << "->" << Successor->getName() << " */\n"; + DEBUG(errs() << "/* Printing PHIs for " << CurBlock->getName() << "->" << Successor->getName() << " */\n"); + for (BasicBlock::iterator I = Successor->begin(); isa<PHINode>(I); ++I) { + PHINode *PN = cast<PHINode>(I); + if(LInductionVars.find(PN) == LInductionVars.end()) { + Out << "/* Printing phi node: " << *PN << " */\n"; + DEBUG(errs() << "/* Printing phi node: " << *PN << " */\n"); + // Now we have to do the printing. + Value *IV = PN->getIncomingValueForBlock(CurBlock); + if (!isa<UndefValue>(IV) && !isEmptyType(IV->getType())) { + Out << std::string(Indent, ' '); + Out << " " << GetValueName(&*I) << "__PHI_TEMPORARY = "; + writeOperand(IV, ContextCasted); + Out << "; /* for PHI node */\n"; + } + } else { + Out << "/* Skipping (indvar) phi node: " << *PN << " */\n"; + DEBUG(errs() << "/* Skipping (indvar) phi node: " << *PN << " */\n"); + } + } +} - BasicBlock *BB = L->getHeader(); - // printBBorLoop(BB); - printBasicBlock(BB); - // Loop *BBLoop = LI->getLoopFor(BB); - // if (BBLoop == L) - // printBasicBlock(BB); - // else if (BB == BBLoop->getHeader() && BBLoop->getParentLoop() == L) - // printLoop(BBLoop); - - // Out << " do { /* Syntactic loop '" << L->getHeader()->getName() - // << "' to make GCC happy */\n"; - // for (unsigned i = 0, e = L->getBlocks().size(); i != e; ++i) { - // BasicBlock *BB = L->getBlocks()[i]; - // Loop *BBLoop = LI->getLoopFor(BB); - // if (BBLoop == L) - // printBasicBlock(BB); - // else if (BB == BBLoop->getHeader() && BBLoop->getParentLoop() == L) - // printLoop(BBLoop); - // } - // Out << " } \n"; +void CWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ, + unsigned Indent) { + if (isGotoCodeNecessary(CurBB, Succ)) { + Out << std::string(Indent, ' ') << " goto "; + writeOperand(Succ); + Out << ";\n"; + } } -void CWriter::printBasicBlock(BasicBlock *BB) { - // DEBUG(errs() << "\n\nProcessing Basic Block: " << BB->getName() << "\n"); - Out << "\n\n/* Processing Basic Block: " << BB->getName() << " */\n"; +void CWriter::printBBorLoop (BasicBlock *BB) { + DEBUG(errs() << "\nPrinting: " << BB->getName() << "\n"); + Out << "\n/* Printing: " << BB->getName() << " */\n"; + if(VisitedBlocks.find(BB)!=VisitedBlocks.end() && ReplicateBlocks.find(BB)==ReplicateBlocks.end()) { + DEBUG(errs() << "This BB has already been printed and is not marked for replication! exiting!\n"); + Out << "/* This BB has already been printed and is not marked for replication! exiting! */\n"; + } else if(!ImmPostDommBlocks.empty() && ImmPostDommBlocks.top() == BB) { + DEBUG(errs() << "Reached block that is top of stack, return instead!\n"); + Out << "/* " << BB->getName() << " is top of stack, return instead! */\n"; + // ImmPostDommBlocks.pop(); + } else { + VisitedBlocks.insert(BB); + if(Loop *LL = LI->getLoopFor(BB)) { + if (LL->getHeader() == BB) + printLoop(LL); + else + printBasicBlock(BB); + } else { + printBasicBlock(BB); + } + } - // Don't print the label for the basic block if there are no uses, or if - // the only terminator use is the predecessor basic block's terminator. - // We have to scan the use list because PHI nodes use basic blocks too but - // do not require a label to be generated. - // - bool NeedsLabel = false; - for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) - if (isGotoCodeNecessary(*PI, BB)) { - NeedsLabel = true; - break; - } +} - // if (NeedsLabel) Out << "/* " << GetValueName(BB) << ": */\n"; - Out << "/* " << GetValueName(BB) << ": */\n"; +bool CWriter::compareBlocks(BasicBlock *CurrBlock, BasicBlock *CompBlock, BasicBlock *ImmPostDomm) { + CompVisitedBlocks.insert(CurrBlock); + DEBUG(errs() << "--Comparing " << CurrBlock->getName() << " with " << CompBlock->getName() << "\n"); + if (CurrBlock == ImmPostDomm) { + DEBUG(errs() << "----Reached Post Dominator, returning false!\n"); + return false; + } else if (CurrBlock == CompBlock) { + DEBUG(errs() << "----Found a match! " << CurrBlock->getName() << " == " << CompBlock->getName() << "\n"); + return true; + } else { + bool res = false; + for (auto succ: successors(CurrBlock)) { + if (CompVisitedBlocks.find(succ) == CompVisitedBlocks.end()) { + DEBUG(errs() << "----Visiting successor " << succ->getName() << " of " << CurrBlock->getName() << "\n"); + res = res || compareBlocks(succ, CompBlock, ImmPostDomm); + } else { + DEBUG(errs() << "----Skipping successor " << succ->getName() << " of " << CurrBlock->getName() << "\n"); + } + } + return res; + } +} - // Output all of the instructions in the basic block... - for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E; ++II) { - Instruction *I = &*II; - // DEBUG(errs() << "*********Processing: " << *I << "\n"); - bool skip = false; - for (Use &U : I->operands()) { - Value *v = U.get(); - if (PHINode *PN = dyn_cast<PHINode>(v)) { - if (LInductionVars.find(PN) != LInductionVars.end()) { - bool UserPHI = false; - bool UserCMP = false; - bool UserOTHER = false; - //// DEBUG(errs() << "Instruction uses induction - /// variable\n"); - for (User *IUser : I->users()) { - if (Instruction *UserInst = dyn_cast<Instruction>(IUser)) { - // DEBUG(errs() << "User: " << *UserInst << "\n"); - if (dyn_cast<PHINode>(UserInst)) { - UserPHI = true; - } else if (dyn_cast<ICmpInst>(UserInst)) { - UserCMP = true; - } else { - UserOTHER = true; - } - // skip = true; - // break; - } - } - if (UserPHI && UserCMP && !UserOTHER) { - skip = true; - } - } - } - if (skip) - break; - } - if (skip) { - // DEBUG(errs() << "Skipping instruction that increments Induction - // Variable!\n"); - Out << "/* Skipped induction variable use: " << *I << " */\n"; - continue; - } - if (PHINode *PN = dyn_cast<PHINode>(I)) { - if (LInductionVars.find(PN) != LInductionVars.end()) { - // DEBUG(errs() << "Skipping PHINode for Induction Variable!\n"); - Out << "/* PHINode of induction variable was here */\n"; - continue; - } - } - if (!isInlinableInst(*II) && !isDirectAlloca(&*II)) { - if (!isEmptyType(II->getType()) && !isInlineAsm(*II)) - outputLValue(&*II); - else - Out << " "; - writeInstComputationInline(*II); - Out << ";\n"; - } else { - // DEBUG(errs() << "Skipping inlinable or direct alloca!\n"); - } - } - - // Don't emit prefix or suffix for the terminator. - visit(*BB->getTerminator()); -} - -// Specific Instruction type classes... note that all of the casts are -// necessary because we use the instruction classes as opaque types... -// -void CWriter::visitReturnInst(ReturnInst &I) { - // If this is a struct return function, return the temporary struct. - bool isStructReturn = I.getParent()->getParent()->hasStructRetAttr(); - - if (isStructReturn) { - Out << " return StructReturn;\n"; - return; - } - - // Don't output a void return if this is the last basic block in the function - // unless that would make the basic block empty - if (I.getNumOperands() == 0 && - &*--I.getParent()->getParent()->end() == I.getParent() && - &*I.getParent()->begin() != &I) { - return; - } - - Out << " return"; - if (I.getNumOperands()) { - Out << ' '; - writeOperand(I.getOperand(0), ContextCasted); - } - Out << ";\n"; -} - -void CWriter::visitSwitchInst(SwitchInst &SI) { - Value *Cond = SI.getCondition(); - unsigned NumBits = cast<IntegerType>(Cond->getType())->getBitWidth(); - - if (SI.getNumCases() == 0) { // unconditional branch - printPHICopiesForSuccessor(SI.getParent(), SI.getDefaultDest(), 2); - printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2); - Out << "\n"; - - } else if (NumBits <= 64) { // model as a switch statement - Out << " switch ("; - writeOperand(Cond); - Out << ") {\n default:\n"; - printPHICopiesForSuccessor(SI.getParent(), SI.getDefaultDest(), 2); - printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2); - - // CHECK: Needs much testing - for (auto Case : SI.cases()) { - ConstantInt *CaseVal = Case.getCaseValue(); - BasicBlock *Succ = Case.getCaseSuccessor(); - Out << " case "; - writeOperand(CaseVal); - Out << ":\n"; - printPHICopiesForSuccessor(SI.getParent(), Succ, 2); - if (isGotoCodeNecessary(SI.getParent(), Succ)) - printBranchToBlock(SI.getParent(), Succ, 2); - else - Out << " break;\n"; - } - Out << " }\n"; - - } else { // model as a series of if statements - Out << " "; - // CHECK: Needs much testing - for (auto Case : SI.cases()) { - Out << "if ("; - ConstantInt *CaseVal = Case.getCaseValue(); - BasicBlock *Succ = Case.getCaseSuccessor(); - ICmpInst *icmp = new ICmpInst(CmpInst::ICMP_EQ, Cond, CaseVal); - visitICmpInst(*icmp); - delete icmp; - Out << ") {\n"; - printPHICopiesForSuccessor(SI.getParent(), Succ, 2); - printBranchToBlock(SI.getParent(), Succ, 2); - Out << " } else "; - } - Out << "{\n"; - printPHICopiesForSuccessor(SI.getParent(), SI.getDefaultDest(), 2); - printBranchToBlock(SI.getParent(), SI.getDefaultDest(), 2); - Out << " }\n"; - } - Out << "\n"; -} - -void CWriter::visitIndirectBrInst(IndirectBrInst &IBI) { - Out << " goto *(void*)("; - writeOperand(IBI.getOperand(0)); - Out << ");\n"; -} - -void CWriter::visitUnreachableInst(UnreachableInst &I) { - Out << " __builtin_unreachable();\n\n"; -} - -bool CWriter::isGotoCodeNecessary(BasicBlock *From, BasicBlock *To) { - /// FIXME: This should be reenabled, but loop reordering safe!! - return true; - - if (std::next(Function::iterator(From)) != Function::iterator(To)) - return true; // Not the direct successor, we need a goto. - - // isa<SwitchInst>(From->getTerminator()) - - if (LI->getLoopFor(From) != LI->getLoopFor(To)) - return true; - return false; -} - -void CWriter::printPHICopiesForSuccessor(BasicBlock *CurBlock, - BasicBlock *Successor, - unsigned Indent) { - Out << "/* Printing PHIs for " << CurBlock->getName() << "->" - << Successor->getName() << " */\n"; - for (BasicBlock::iterator I = Successor->begin(); isa<PHINode>(I); ++I) { - PHINode *PN = cast<PHINode>(I); - if (LInductionVars.find(PN) == LInductionVars.end()) { - Out << "/* Printing phi node: " << *PN << " */\n"; - // Now we have to do the printing. - Value *IV = PN->getIncomingValueForBlock(CurBlock); - if (!isa<UndefValue>(IV) && !isEmptyType(IV->getType())) { - Out << std::string(Indent, ' '); - Out << " " << GetValueName(&*I) << "__PHI_TEMPORARY = "; - writeOperand(IV, ContextCasted); - Out << "; /* for PHI node */\n"; - } - } else { - Out << "/* Skipping phi node: " << *PN << " */\n"; - } - } -} - -void CWriter::printBranchToBlock(BasicBlock *CurBB, BasicBlock *Succ, - unsigned Indent) { - if (isGotoCodeNecessary(CurBB, Succ)) { - Out << std::string(Indent, ' ') << " goto "; - writeOperand(Succ); - Out << ";\n"; - } -} - -void CWriter::printBBorLoop(BasicBlock *BB) { - // DEBUG(errs() << "\nPrinting: " << BB->getName() << "\n"); - Out << "\n/* Printing: " << BB->getName() << " */\n"; - if (VisitedBlocks.find(BB) != VisitedBlocks.end() && - ReplicateBlocks.find(BB) == ReplicateBlocks.end()) { - // DEBUG(errs() << "This BB has already been printed and is not marked for - // replication! exiting!\n"); - Out << "/* This BB has already been printed and is not marked for " - "replication! exiting! */\n"; - } else if (!ImmPostDommBlocks.empty() && ImmPostDommBlocks.top() == BB) { - // DEBUG(errs() << "Reached block that is top of stack, return instead!\n"); - Out << "/* " << BB->getName() << " is top of stack, return instead! */\n"; - // ImmPostDommBlocks.pop(); - } else { - VisitedBlocks.insert(BB); - if (Loop *LL = LI->getLoopFor(BB)) { - if (LL->getHeader() == BB) - printLoop(LL); - else - printBasicBlock(BB); - } else { - printBasicBlock(BB); - } - } -} - -bool CWriter::compareBlocks(BasicBlock *CurrBlock, BasicBlock *CompBlock, - BasicBlock *ImmPostDomm) { - CompVisitedBlocks.insert(CurrBlock); - // DEBUG(errs() << "--Comparing " << CurrBlock->getName() << " with " << - // CompBlock->getName() << "\n"); - if (CurrBlock == ImmPostDomm) { - // DEBUG(errs() << "----Reached Post Dominator, returning false!\n"); - return false; - } else if (CurrBlock == CompBlock) { - // DEBUG(errs() << "----Found a match! " << CurrBlock->getName() << " == " - // << CompBlock->getName() << "\n"); - return true; - } else { - bool res = false; - for (auto succ : successors(CurrBlock)) { - if (CompVisitedBlocks.find(succ) == CompVisitedBlocks.end()) { - // DEBUG(errs() << "----Visiting successor " << succ->getName() << " of - // " << CurrBlock->getName() << "\n"); - res = res || compareBlocks(succ, CompBlock, ImmPostDomm); - } else { - // DEBUG(errs() << "----Skipping successor " << succ->getName() << " of - // " << CurrBlock->getName() << "\n"); - } - } - return res; - } -} - -bool CWriter::findMatch(BasicBlock *CurrBlock, BasicBlock *CompBlock, - BasicBlock *ImmPostDomm) { - if (CompBlock == ImmPostDomm) { - // DEBUG(errs() << "Reached PostDomm; returning!\n"); - return false; - } - FindVisitedBlocks.insert(CompBlock); - // DEBUG(errs() << "Finding match between " << CompBlock->getName() << " & " - // << CurrBlock->getName() << "\n"); - bool compareResult = compareBlocks(CurrBlock, CompBlock, ImmPostDomm); - CompVisitedBlocks.clear(); - if (compareResult) { - // DEBUG(errs() << "Match found, marking " << CompBlock->getName() << " for - // replication!\n"); - // Flag for replication - ReplicateBlocks.insert(CompBlock); - return true; - } else { - bool res = false; - for (auto succ : successors(CompBlock)) { - if (FindVisitedBlocks.find(succ) == FindVisitedBlocks.end()) { - // DEBUG(errs() << "Visiting successor " << succ->getName() << " of " << - // CompBlock->getName() << "\n"); - res = res || findMatch(CurrBlock, succ, ImmPostDomm); - if (res == true) - break; - } else { - // DEBUG(errs() << "Skipping successor " << succ->getName() << " of " << - // CompBlock->getName() << "\n"); - } - } - return res; - } +bool CWriter::findMatch(BasicBlock *CurrBlock, BasicBlock *CompBlock, BasicBlock *ImmPostDomm) { + if (CompBlock == ImmPostDomm) { + DEBUG(errs() << "Reached PostDomm; returning!\n"); + return false; + } + FindVisitedBlocks.insert(CompBlock); + DEBUG(errs() << "Finding match between " << CompBlock->getName() << " & " << CurrBlock->getName() << "\n"); + bool compareResult = compareBlocks(CurrBlock, CompBlock, ImmPostDomm); + CompVisitedBlocks.clear(); + if (compareResult){ + DEBUG(errs() << "Match found, marking " << CompBlock->getName() << " for replication!\n"); + // Flag for replication + ReplicateBlocks.insert(CompBlock); + return true; + } else { + bool res = false; + for (auto succ: successors(CompBlock)) { + if(FindVisitedBlocks.find(succ) == FindVisitedBlocks.end()) { + DEBUG(errs() << "Visiting successor " << succ->getName() << " of " << CompBlock->getName() << "\n"); + res = res || findMatch(CurrBlock, succ, ImmPostDomm); + if (res == true) break; + } else { + DEBUG(errs() << "Skipping successor " << succ->getName() << " of " << CompBlock->getName() << "\n"); + } + } + return res; + } } // Branch instruction printing - Avoid printing out a branch to a basic block // that immediately succeeds the current one. // void CWriter::visitBranchInst(BranchInst &I) { - errs() << "Visiting Branch Instruction: " << I << "\n"; - Out << "\n/* Branch: " << I << " */\n"; - - if (I.isConditional()) { - BasicBlock *BB0 = I.getSuccessor(0); - BasicBlock *BB1 = I.getSuccessor(1); - BasicBlock *ImmPostDomm = PDT->findNearestCommonDominator(BB0, BB1); - - // Iterate over all BBs in then & else to find a matching BB - // If found, mark it for replication - if (ImmPostDomm != BB1 && ImmPostDomm != BB0) { - findMatch(BB0, BB1, ImmPostDomm); - FindVisitedBlocks.clear(); - } - if (Loop *L = LI->getLoopFor(I.getParent())) { - if (L == LI->getLoopFor(BB0) && !(L == LI->getLoopFor(BB1))) { - errs() << "This is a loop branch!\n"; - Out << "/* This is a loop branch! */\n"; - // BB0 is in the loop. Print it if it hsn't been printed - if (VisitedBlocks.find(BB0) != VisitedBlocks.end()) { - errs() << "Branching back to header: " << BB0->getName() << "\n"; - errs() << "This is the end of the loop, closing!\n"; - Out << "/* Branching back to header: " << BB0->getName() << " */\n"; - Out << "/* Closing loop! */\n"; - // BB0 is the loop header. CLose the loop then print BB1. - printPHICopiesForSuccessor(I.getParent(), BB0, 2); - Out << " }\n"; - printPHICopiesForSuccessor(I.getParent(), BB1, 2); - printBBorLoop(BB1); - } else { - errs() << "Not branching to header! Branching to: " << BB0->getName() - << "\n"; - // BB0 is not the loop header. That means we are entering loop body - - llvm_unreachable("loop branch unhandled!\n"); - } - } else if (L == LI->getLoopFor(BB1) && !(L == LI->getLoopFor(BB0))) { - errs() << "This is a loop branch!\n"; - Out << "/* This is a loop branch! */\n"; - if (VisitedBlocks.find(BB1) != VisitedBlocks.end()) { - errs() << "Branching back to header: " << BB1->getName() << "\n"; - errs() << "This is the end of the loop, closing!\n"; - Out << "/* Branching back to header: " << BB1->getName() << " */\n"; - Out << "/* Closing loop! */\n"; - // BB0 is the loop header. CLose the loop then print BB1. - printPHICopiesForSuccessor(I.getParent(), BB1, 2); - Out << " }\n"; - printPHICopiesForSuccessor(I.getParent(), BB0, 2); - printBBorLoop(BB0); - } else { - errs() << "Not branching to header! Branching to: " << BB1->getName() - << "\n"; - // BB1 is not the loop header. That means we are entering loop body - llvm_unreachable("loop branch unhandled!\n"); - } - } else { - errs() << "This is a conditional statement within a loop!\n"; - Out << "/* This is a conditional statement within a loop! */\n"; - errs() << ImmPostDomm->getName() - << " is the immediate post dominator of " << BB0->getName() - << " and " << BB1->getName() << "\n"; - if (VisitedBlocks.find(ImmPostDomm) != VisitedBlocks.end()) { - errs() << "Not pushing " << ImmPostDomm->getName() - << " because it has already been visited!\n"; - } else { - errs() << "Pushing " << ImmPostDomm->getName() << " onto stack!\n"; - ImmPostDommBlocks.push(ImmPostDomm); - } - - bool noElse = false; - if (BB1 == ImmPostDomm) { - noElse = true; - } - Out << " if ("; - writeOperand(I.getCondition(), ContextCasted); - Out << ") { /* " << I << "*/\n"; - printPHICopiesForSuccessor(I.getParent(), BB0, 2); - printBBorLoop(BB0); - errs() << "Back to handling " << I.getParent()->getName() << ": " << I - << "\n"; - Out << "/* Back to handling " << I.getParent()->getName() << ": " << I - << " */\n"; - if (!noElse) { - errs() << "Printing else!\n"; - Out << " } else { /*" << I << "*/\n"; - printPHICopiesForSuccessor(I.getParent(), BB1, 2); - ElseBlocks.push(BB1); - ElseBranches.push(&I); - printBBorLoop(BB1); - errs() << "Back to handling " << I.getParent()->getName() << ": " << I - << "\n"; - errs() << "Check to see if else block is closed!\n"; - Out << "/* Back to handling " << I.getParent()->getName() << ": " << I - << " */\n"; - Out << "/* Check to see if else block is closed! */\n"; - if (!ElseBlocks.empty() && ElseBlocks.top() == BB1) { - errs() << "Else block not closed, need to close braces!\n"; - Out << "/* Else block not closed, need to close braces! */\n"; - Out << "} /* closing " << *(ElseBranches.top()) << " */\n"; - ElseBranches.pop(); - ElseBlocks.pop(); - } - if (!ImmPostDommBlocks.empty() && - ImmPostDommBlocks.top() == ImmPostDomm) { - errs() << "Will now pop post dom them handle it!\n"; - ImmPostDommBlocks.pop(); - printBBorLoop(ImmPostDomm); - } else { - errs() - << "*!*!*!*!*!*!Not sure what is happening here!*!*!*!*!*!*!\n"; - } - } else { - errs() << "No else block. Adding one for phis, then moving to " - << BB1->getName() << "!\n"; - Out << "/* (3913) No else block. Adding one for phis, then moving to " - << BB1->getName() << "! */\n"; - Out << " } /* closing " << I << "*/\n"; - errs() << "Will now pop post dom them handle it!\n"; - ImmPostDommBlocks.pop(); - Out << "else {\n"; - printPHICopiesForSuccessor(I.getParent(), BB1, 2); - Out << "}\n"; - printBBorLoop(BB1); - } - } - } else { - errs() << "This is a conditional statement!\n"; - errs() << ImmPostDomm->getName() << " is the immediate post dominator of " - << BB0->getName() << " and " << BB1->getName() << "\n"; - if (VisitedBlocks.find(ImmPostDomm) != VisitedBlocks.end()) { - errs() << "Not pushing " << ImmPostDomm->getName() - << " because it has already been visited!\n"; - } else { - errs() << "Pushing " << ImmPostDomm->getName() << " onto stack!\n"; - ImmPostDommBlocks.push(ImmPostDomm); - } - bool noElse = false; - if (BB1 == ImmPostDomm) { - noElse = true; - } - Out << " if ("; - writeOperand(I.getCondition(), ContextCasted); - Out << ") { /* " << I << "*/\n"; - printPHICopiesForSuccessor(I.getParent(), BB0, 2); - printBBorLoop(BB0); - errs() << "Back to handling " << I.getParent()->getName() << ": " << I - << "\n"; - Out << "/* Back to handling " << I.getParent()->getName() << ": " << I - << " */\n"; - if (!noElse) { - errs() << "Printing else!\n"; - Out << "/* Printing else! */\n"; - Out << " } else { /*" << I << "*/\n"; - printPHICopiesForSuccessor(I.getParent(), BB1, 2); - ElseBlocks.push(BB1); - ElseBranches.push(&I); - printBBorLoop(BB1); - errs() << "Back to handling " << I.getParent()->getName() << ": " << I - << "\n"; - errs() << "Check to see if else block is closed!\n"; - Out << "/* Back to handling " << I.getParent()->getName() << ": " << I - << " */\n"; - Out << "/* Check to see if else block is closed! */\n"; - if (!ElseBlocks.empty() && ElseBlocks.top() == BB1) { - errs() << "Else block not closed, need to close braces!\n"; - Out << "/* Else block not closed, need to close braces! */\n"; - Out << "} /* closing " << *(ElseBranches.top()) << " */\n"; - ElseBranches.pop(); - ElseBlocks.pop(); - } - if (!ImmPostDommBlocks.empty() && - ImmPostDommBlocks.top() == ImmPostDomm) { - errs() << "Will now pop post dom them handle it!\n"; - ImmPostDommBlocks.pop(); - printBBorLoop(ImmPostDomm); - } else { - errs() - << "*!*!*!*!*!*!Not sure what is happening here!*!*!*!*!*!*!\n"; - } - } else { - errs() << "No else block. Adding one for phis, then moving to " - << BB1->getName() << "!\n"; - Out << "/* (3985) No else block. Adding one for phis, then moving to " - << BB1->getName() << "! */\n"; - Out << " } /* closing " << I << "*/\n"; - errs() << "Will now pop post dom them handle it!\n"; - ImmPostDommBlocks.pop(); - Out << "else {\n"; - printPHICopiesForSuccessor(I.getParent(), BB1, 2); - Out << "}\n"; - printBBorLoop(BB1); - } - } - } else { - errs() << "This is an unconditional branch!\n"; - BasicBlock *BB = I.getSuccessor(0); - printPHICopiesForSuccessor(I.getParent(), BB, 2); - if (!ElseBlocks.empty() && I.getParent() == ElseBlocks.top()) { - errs() << "Branch marks end of else block, need to close braces!\n"; - Out << "/* Branch marks end of else block, need to close braces! */\n"; - Out << "} /* closing " << *(ElseBranches.top()) << " */\n"; - ElseBranches.pop(); - ElseBlocks.pop(); - } - printBBorLoop(BB); - } - Out << "\n"; + errs() << "Visiting Branch Instruction: " << I <<"\n"; + Out << "\n/* Branch: " << I << " */\n"; + + if (I.isConditional()) { + BasicBlock *BB0 = I.getSuccessor(0); + BasicBlock *BB1 = I.getSuccessor(1); + BasicBlock *ImmPostDomm = PDT->findNearestCommonDominator(BB0,BB1); + + // Iterate over all BBs in then & else to find a matching BB + // If found, mark it for replication + if (ImmPostDomm != BB1 && ImmPostDomm != BB0) { + findMatch(BB0, BB1, ImmPostDomm); + FindVisitedBlocks.clear(); + } + if(Loop *L = LI->getLoopFor(I.getParent())) { + if(L == LI->getLoopFor(BB0) && !(L == LI->getLoopFor(BB1))) { + errs() << "This is a loop branch!\n"; + Out << "/* This is a loop branch! */\n"; + //BB0 is in the loop. Print it if it hsn't been printed + if(VisitedBlocks.find(BB0) != VisitedBlocks.end()) { + errs() << "Branching back to header: " << BB0->getName() << "\n"; + errs() << "This is the end of the loop, closing!\n"; + Out << "/* Branching back to header: " << BB0->getName() << " */\n"; + Out << "/* Closing loop! */\n"; + //BB0 is the loop header. CLose the loop then print BB1. + printPHICopiesForSuccessor (I.getParent(), BB0, 2); + Out << " }\n"; + printPHICopiesForSuccessor (I.getParent(), BB1, 2); + printBBorLoop(BB1); + } else { + errs() << "Not branching to header! Branching to: " << BB0->getName() << "\n"; + //BB0 is not the loop header. That means we are entering loop body + + llvm_unreachable("loop branch unhandled!\n"); + } + } else if(L == LI->getLoopFor(BB1) && !(L == LI->getLoopFor(BB0))) { + errs() << "This is a loop branch!\n"; + Out << "/* This is a loop branch! */\n"; + if(VisitedBlocks.find(BB1) != VisitedBlocks.end()) { + errs() << "Branching back to header: " << BB1->getName() << "\n"; + errs() << "This is the end of the loop, closing!\n"; + Out << "/* Branching back to header: " << BB1->getName() << " */\n"; + Out << "/* Closing loop! */\n"; + //BB0 is the loop header. CLose the loop then print BB1. + printPHICopiesForSuccessor (I.getParent(), BB1, 2); + Out << " }\n"; + printPHICopiesForSuccessor (I.getParent(), BB0, 2); + printBBorLoop(BB0); + } else { + errs() << "Not branching to header! Branching to: " << BB1->getName() << "\n"; + //BB1 is not the loop header. That means we are entering loop body + llvm_unreachable("loop branch unhandled!\n"); + } + } else { + errs() << "This is a conditional statement within a loop!\n"; + Out << "/* This is a conditional statement within a loop! */\n"; + errs() << ImmPostDomm->getName() << " is the immediate post dominator of " << BB0->getName() << " and " << BB1->getName() << "\n"; + if(VisitedBlocks.find(ImmPostDomm) != VisitedBlocks.end()) { + errs() << "Not pushing " << ImmPostDomm->getName() << " because it has already been visited!\n"; + } else { + errs() << "Pushing " << ImmPostDomm->getName() << " onto stack!\n"; + ImmPostDommBlocks.push(ImmPostDomm); + } + + bool noElse = false; + if(BB1 == ImmPostDomm) { + noElse = true; + } + Out << " if ("; + writeOperand(I.getCondition(), ContextCasted); + Out << ") { /* " << I << "*/\n"; + printPHICopiesForSuccessor (I.getParent(), BB0, 2); + printBBorLoop(BB0); + errs() << "Back to handling " << I.getParent()->getName() << ": " << I << "\n"; + Out << "/* Back to handling " << I.getParent()->getName() << ": " << I << " */\n"; + if (!noElse) { + errs() << "Printing else!\n"; + Out << " } else { /*" << I << "*/\n"; + printPHICopiesForSuccessor (I.getParent(), BB1, 2); + ElseBlocks.push(BB1); + ElseBranches.push(&I); + printBBorLoop(BB1); + errs() << "Back to handling " << I.getParent()->getName() << ": " << I << "\n"; + errs() << "Check to see if else block is closed!\n"; + Out << "/* Back to handling " << I.getParent()->getName() << ": " << I << " */\n" ; + Out << "/* Check to see if else block is closed! */\n" ; + if(!ElseBlocks.empty() && ElseBlocks.top() == BB1) { + errs() << "Else block not closed, need to close braces!\n"; + Out << "/* Else block not closed, need to close braces! */\n" ; + Out << "} /* closing " << *(ElseBranches.top()) << " */\n"; + ElseBranches.pop(); + ElseBlocks.pop(); + } + if(!ImmPostDommBlocks.empty() && ImmPostDommBlocks.top() == ImmPostDomm) { + errs() << "Will now pop post dom them handle it!\n"; + ImmPostDommBlocks.pop(); + printBBorLoop(ImmPostDomm); + } else { + errs() << "*!*!*!*!*!*!Not sure what is happening here!*!*!*!*!*!*!\n"; + } + } else { + errs() << "No else block. Adding one for phis, then moving to " << BB1->getName() << "!\n"; + Out << "/* (3913) No else block. Adding one for phis, then moving to " << BB1->getName() << "! */\n"; + Out << " } /* closing " << I << "*/\n"; + errs() << "Will now pop post dom them handle it!\n"; + ImmPostDommBlocks.pop(); + Out << "else {\n"; + printPHICopiesForSuccessor (I.getParent(), BB1, 2); + Out << "}\n"; + printBBorLoop(BB1); + } + } + } else { + errs() << "This is a conditional statement!\n"; + errs() << ImmPostDomm->getName() << " is the immediate post dominator of " << BB0->getName() << " and " << BB1->getName() << "\n"; + if(VisitedBlocks.find(ImmPostDomm) != VisitedBlocks.end()) { + errs() << "Not pushing " << ImmPostDomm->getName() << " because it has already been visited!\n"; + } else { + errs() << "Pushing " << ImmPostDomm->getName() << " onto stack!\n"; + ImmPostDommBlocks.push(ImmPostDomm); + } + bool noElse = false; + if(BB1 == ImmPostDomm) { + noElse = true; + } + Out << " if ("; + writeOperand(I.getCondition(), ContextCasted); + Out << ") { /* " << I << "*/\n"; + printPHICopiesForSuccessor (I.getParent(), BB0, 2); + printBBorLoop(BB0); + errs() << "Back to handling " << I.getParent()->getName() << ": " << I << "\n"; + Out << "/* Back to handling " << I.getParent()->getName() << ": " << I << " */\n" ; + if (!noElse) { + errs() << "Printing else!\n"; + Out << "/* Printing else! */\n" ; + Out << " } else { /*" << I << "*/\n"; + printPHICopiesForSuccessor (I.getParent(), BB1, 2); + ElseBlocks.push(BB1); + ElseBranches.push(&I); + printBBorLoop(BB1); + errs() << "Back to handling " << I.getParent()->getName() << ": " << I << "\n"; + errs() << "Check to see if else block is closed!\n"; + Out << "/* Back to handling " << I.getParent()->getName() << ": " << I << " */\n"; + Out << "/* Check to see if else block is closed! */\n"; + if(!ElseBlocks.empty() && ElseBlocks.top() == BB1) { + errs() << "Else block not closed, need to close braces!\n"; + Out << "/* Else block not closed, need to close braces! */\n"; + Out << "} /* closing " << *(ElseBranches.top()) << " */\n"; + ElseBranches.pop(); + ElseBlocks.pop(); + } + if(!ImmPostDommBlocks.empty() && ImmPostDommBlocks.top() == ImmPostDomm) { + errs() << "Will now pop post dom them handle it!\n"; + ImmPostDommBlocks.pop(); + printBBorLoop(ImmPostDomm); + } else { + errs() << "*!*!*!*!*!*!Not sure what is happening here!*!*!*!*!*!*!\n"; + } + } else { + errs() << "No else block. Adding one for phis, then moving to " << BB1->getName() << "!\n"; + Out << "/* (3985) No else block. Adding one for phis, then moving to " << BB1->getName() << "! */\n"; + Out << " } /* closing " << I << "*/\n"; + errs() << "Will now pop post dom them handle it!\n"; + ImmPostDommBlocks.pop(); + Out << "else {\n"; + printPHICopiesForSuccessor (I.getParent(), BB1, 2); + Out << "}\n"; + printBBorLoop(BB1); + } + } + } else { + errs() << "This is an unconditional branch!\n"; + BasicBlock *BB = I.getSuccessor(0); + printPHICopiesForSuccessor (I.getParent(), BB, 2); + if (!ElseBlocks.empty() && I.getParent() == ElseBlocks.top()) { + errs() << "Branch marks end of else block, need to close braces!\n"; + Out << "/* Branch marks end of else block, need to close braces! */\n"; + Out << "} /* closing " << *(ElseBranches.top()) << " */\n"; + ElseBranches.pop(); + ElseBlocks.pop(); + } + printBBorLoop(BB); + } + Out << "\n"; } // PHI nodes get copied into temporary values at the end of predecessor basic // blocks. We now need to copy these temporary values into the REAL value for // the PHI. void CWriter::visitPHINode(PHINode &I) { - if (LInductionVars.find(&I) == LInductionVars.end()) { - writeOperand(&I); - Out << "__PHI_TEMPORARY"; - } else { - // DEBUG(errs() << "Skipping PHI node for induction variable!\n"); - } + if (LInductionVars.find(&I) == LInductionVars.end()) { + writeOperand(&I); + Out << "__PHI_TEMPORARY"; + } + else { + DEBUG(errs() << "Skipping PHI node for induction variable!\n"); + } } + // NOTE: Moving LLVM-4 Binary Op functions here bool isNeg(const Value *V) { - if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) - if (Bop->getOpcode() == Instruction::Sub) - if (Constant *C = dyn_cast<Constant>(Bop->getOperand(0))) - return C->isNegativeZeroValue(); - return false; + if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) + if (Bop->getOpcode() == Instruction::Sub) + if (Constant *C = dyn_cast<Constant>(Bop->getOperand(0))) + return C->isNegativeZeroValue(); + return false; } bool isFNeg(const Value *V, bool IgnoreZeroSign) { - if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) - if (Bop->getOpcode() == Instruction::FSub) - if (Constant *C = dyn_cast<Constant>(Bop->getOperand(0))) { - if (!IgnoreZeroSign) - IgnoreZeroSign = cast<Instruction>(V)->hasNoSignedZeros(); - return !IgnoreZeroSign ? C->isNegativeZeroValue() : C->isZeroValue(); - } - return false; + if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) + if (Bop->getOpcode() == Instruction::FSub) + if (Constant *C = dyn_cast<Constant>(Bop->getOperand(0))) { + if (!IgnoreZeroSign) + IgnoreZeroSign = cast<Instruction>(V)->hasNoSignedZeros(); + return !IgnoreZeroSign ? C->isNegativeZeroValue() : C->isZeroValue(); + } + return false; } + Value *getNegArgument(Value *BinOp) { - return cast<BinaryOperator>(BinOp)->getOperand(1); + return cast<BinaryOperator>(BinOp)->getOperand(1); } const Value *getNegArgument(const Value *BinOp) { - return getNegArgument(const_cast<Value *>(BinOp)); + return getNegArgument(const_cast<Value*>(BinOp)); } Value *getFNegArgument(Value *BinOp) { - return cast<BinaryOperator>(BinOp)->getOperand(1); + return cast<BinaryOperator>(BinOp)->getOperand(1); } const Value *getFNegArgument(const Value *BinOp) { - return getFNegArgument(const_cast<Value *>(BinOp)); + return getFNegArgument(const_cast<Value*>(BinOp)); } static inline bool isConstantAllOnes(const Value *V) { - if (const Constant *C = dyn_cast<Constant>(V)) - return C->isAllOnesValue(); - return false; + if (const Constant *C = dyn_cast<Constant>(V)) + return C->isAllOnesValue(); + return false; } bool isNot(const Value *V) { - if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) - return (Bop->getOpcode() == Instruction::Xor && - (isConstantAllOnes(Bop->getOperand(1)) || - isConstantAllOnes(Bop->getOperand(0)))); - return false; + if (const BinaryOperator *Bop = dyn_cast<BinaryOperator>(V)) + return (Bop->getOpcode() == Instruction::Xor && + (isConstantAllOnes(Bop->getOperand(1)) || + isConstantAllOnes(Bop->getOperand(0)))); + return false; } + Value *getNotArgument(Value *BinOp) { - assert(isNot(BinOp) && "getNotArgument on non-'not' instruction!"); - BinaryOperator *BO = cast<BinaryOperator>(BinOp); - Value *Op0 = BO->getOperand(0); - Value *Op1 = BO->getOperand(1); - if (isConstantAllOnes(Op0)) - return Op1; - - assert(isConstantAllOnes(Op1)); - return Op0; + assert(isNot(BinOp) && "getNotArgument on non-'not' instruction!"); + BinaryOperator *BO = cast<BinaryOperator>(BinOp); + Value *Op0 = BO->getOperand(0); + Value *Op1 = BO->getOperand(1); + if (isConstantAllOnes(Op0)) return Op1; + + assert(isConstantAllOnes(Op1)); + return Op0; } const Value *getNotArgument(const Value *BinOp) { - return getNotArgument(const_cast<Value *>(BinOp)); + return getNotArgument(const_cast<Value*>(BinOp)); } -void CWriter::visitBinaryOperator(BinaryOperator &I) { - // binary instructions, shift instructions, setCond instructions. - assert(!I.getType()->isPointerTy()); - // DEBUG(errs() << "visiting binary operator!\n" ); - - // // We must cast the results of binary operations which might be promoted. - // bool needsCast = false; - // if ((I.getType() == Type::getInt8Ty(I.getContext())) || - // (I.getType() == Type::getInt16Ty(I.getContext())) - // || (I.getType() == Type::getFloatTy(I.getContext()))) { - // // types too small to work with directly - // needsCast = true; - // } else if (I.getType()->getPrimitiveSizeInBits() > 64) { - // // types too big to work with directly - // needsCast = true; - // } - // bool shouldCast; - // bool castIsSigned; - // opcodeNeedsCast(I.getOpcode(), shouldCast, castIsSigned); - // - // if (I.getType()->isVectorTy() || needsCast || shouldCast) { - // - // DEBUG( - // if(needsCast) errs() << "****Needs Cast: \n" << I << "\n"; - // else if(shouldCast) errs() << "****Should Cast: \n" << I << "\n"; - // else if(I.getType()->isVectorTy()) errs() << "****Is Vector Type: \n" - // << I << "\n"; - // ); - // - // Type *VTy = I.getOperand(0)->getType(); - // unsigned opcode; - // if (BinaryOperator::isNeg(&I)) { - // opcode = BinaryNeg; - // Out << "llvm_neg_"; - // printTypeString(Out, VTy, false); - // Out << "("; - // writeOperand(BinaryOperator::getNegArgument(&I), ContextCasted); - // } else if (BinaryOperator::isFNeg(&I)) { - // opcode = BinaryNeg; - // Out << "llvm_neg_"; - // printTypeString(Out, VTy, false); - // Out << "("; - // writeOperand(BinaryOperator::getFNegArgument(&I), ContextCasted); - // } else if (BinaryOperator::isNot(&I)) { - // opcode = BinaryNot; - // Out << "llvm_not_"; - // printTypeString(Out, VTy, false); - // Out << "("; - // writeOperand(BinaryOperator::getNotArgument(&I), ContextCasted); - // } else { - // opcode = I.getOpcode(); - // Out << "llvm_" << Instruction::getOpcodeName(opcode) << "_"; - // printTypeString(Out, VTy, false); - // Out << "("; - // writeOperand(I.getOperand(0), ContextCasted); - // Out << ", "; - // writeOperand(I.getOperand(1), ContextCasted); - // } - // Out << ")"; - // InlineOpDeclTypes.insert(std::pair<unsigned, Type*>(opcode, VTy)); - // return; - // } - // If this is a negation operation, print it out as such. For FP, we don't - // want to print "-0.0 - X". - // if (BinaryOperator::isNeg(&I)) { - if (isNeg(&I)) { - Out << "-("; - writeOperand(getNegArgument(&I)); - Out << ")"; - } - // else if (BinaryOperator::isFNeg(&I)) { - else if (isFNeg(&I, true)) { - Out << "-("; - writeOperand(getFNegArgument(&I)); - Out << ")"; - } else if (isNot(&I)) { - Out << "~("; - writeOperand(getNotArgument(&I)); - Out << ")"; - } else if (I.getOpcode() == Instruction::FRem) { - // Output a call to fmod/fmodf instead of emitting a%b - if (I.getType() == Type::getFloatTy(I.getContext())) - Out << "fmodf("; - else if (I.getType() == Type::getDoubleTy(I.getContext())) - Out << "fmod("; - else // all 3 flavors of long double - Out << "fmodl("; - writeOperand(I.getOperand(0), ContextCasted); - Out << ", "; - writeOperand(I.getOperand(1), ContextCasted); - Out << ")"; - } else { - // Write out the cast of the instruction's value back to the proper type - // if necessary. - // bool NeedsClosingParens = writeInstructionCast(I); - // Certain instructions require the operand to be forced to a specific type - // so we use writeOperandWithCast here instead of writeOperand. Similarly - // below for operand 1 - writeOperandWithCast(I.getOperand(0), I.getOpcode()); - switch (I.getOpcode()) { - case Instruction::Add: - case Instruction::FAdd: - Out << " + "; - break; - case Instruction::Sub: - case Instruction::FSub: - Out << " - "; - break; - case Instruction::Mul: - case Instruction::FMul: - Out << " * "; - break; - case Instruction::URem: - case Instruction::SRem: - case Instruction::FRem: - Out << " % "; - break; - case Instruction::UDiv: - case Instruction::SDiv: - case Instruction::FDiv: - Out << " / "; - break; - case Instruction::And: - Out << " & "; - break; - case Instruction::Or: - Out << " | "; - break; - case Instruction::Xor: - Out << " ^ "; - break; - case Instruction::Shl: - Out << " << "; - break; - case Instruction::LShr: - case Instruction::AShr: - Out << " >> "; - break; - default: +void CWriter::visitBinaryOperator(BinaryOperator &I) { + // binary instructions, shift instructions, setCond instructions. + assert(!I.getType()->isPointerTy()); + DEBUG(errs() << "visiting binary operator!\n" ); + + // // We must cast the results of binary operations which might be promoted. + // bool needsCast = false; + // if ((I.getType() == Type::getInt8Ty(I.getContext())) || + // (I.getType() == Type::getInt16Ty(I.getContext())) + // || (I.getType() == Type::getFloatTy(I.getContext()))) { + // // types too small to work with directly + // needsCast = true; + // } else if (I.getType()->getPrimitiveSizeInBits() > 64) { + // // types too big to work with directly + // needsCast = true; + // } + // bool shouldCast; + // bool castIsSigned; + // opcodeNeedsCast(I.getOpcode(), shouldCast, castIsSigned); + // + // if (I.getType()->isVectorTy() || needsCast || shouldCast) { + // + // DEBUG( + // if(needsCast) errs() << "****Needs Cast: \n" << I << "\n"; + // else if(shouldCast) errs() << "****Should Cast: \n" << I << "\n"; + // else if(I.getType()->isVectorTy()) errs() << "****Is Vector Type: \n" << I << "\n"; + // ); + // + // Type *VTy = I.getOperand(0)->getType(); + // unsigned opcode; + // if (BinaryOperator::isNeg(&I)) { + // opcode = BinaryNeg; + // Out << "llvm_neg_"; + // printTypeString(Out, VTy, false); + // Out << "("; + // writeOperand(BinaryOperator::getNegArgument(&I), ContextCasted); + // } else if (BinaryOperator::isFNeg(&I)) { + // opcode = BinaryNeg; + // Out << "llvm_neg_"; + // printTypeString(Out, VTy, false); + // Out << "("; + // writeOperand(BinaryOperator::getFNegArgument(&I), ContextCasted); + // } else if (BinaryOperator::isNot(&I)) { + // opcode = BinaryNot; + // Out << "llvm_not_"; + // printTypeString(Out, VTy, false); + // Out << "("; + // writeOperand(BinaryOperator::getNotArgument(&I), ContextCasted); + // } else { + // opcode = I.getOpcode(); + // Out << "llvm_" << Instruction::getOpcodeName(opcode) << "_"; + // printTypeString(Out, VTy, false); + // Out << "("; + // writeOperand(I.getOperand(0), ContextCasted); + // Out << ", "; + // writeOperand(I.getOperand(1), ContextCasted); + // } + // Out << ")"; + // InlineOpDeclTypes.insert(std::pair<unsigned, Type*>(opcode, VTy)); + // return; + // } + + // If this is a negation operation, print it out as such. For FP, we don't + // want to print "-0.0 - X". + + //if (BinaryOperator::isNeg(&I)) { + if (isNeg(&I)) { + Out << "-("; + writeOperand(getNegArgument(&I)); + Out << ")"; + } + //else if (BinaryOperator::isFNeg(&I)) { + else if (isFNeg(&I, true)) { + Out << "-("; + writeOperand(getFNegArgument(&I)); + Out << ")"; + } else if (isNot(&I)) { + Out << "~("; + writeOperand(getNotArgument(&I)); + Out << ")"; + } else if (I.getOpcode() == Instruction::FRem) { + // Output a call to fmod/fmodf instead of emitting a%b + if (I.getType() == Type::getFloatTy(I.getContext())) + Out << "fmodf("; + else if (I.getType() == Type::getDoubleTy(I.getContext())) + Out << "fmod("; + else // all 3 flavors of long double + Out << "fmodl("; + writeOperand(I.getOperand(0), ContextCasted); + Out << ", "; + writeOperand(I.getOperand(1), ContextCasted); + Out << ")"; + } else { + + // Write out the cast of the instruction's value back to the proper type + // if necessary. + // bool NeedsClosingParens = writeInstructionCast(I); + + // Certain instructions require the operand to be forced to a specific type + // so we use writeOperandWithCast here instead of writeOperand. Similarly + // below for operand 1 + writeOperandWithCast(I.getOperand(0), I.getOpcode()); + + switch (I.getOpcode()) { + case Instruction::Add: + case Instruction::FAdd: Out << " + "; break; + case Instruction::Sub: + case Instruction::FSub: Out << " - "; break; + case Instruction::Mul: + case Instruction::FMul: Out << " * "; break; + case Instruction::URem: + case Instruction::SRem: + case Instruction::FRem: Out << " % "; break; + case Instruction::UDiv: + case Instruction::SDiv: + case Instruction::FDiv: Out << " / "; break; + case Instruction::And: Out << " & "; break; + case Instruction::Or: Out << " | "; break; + case Instruction::Xor: Out << " ^ "; break; + case Instruction::Shl : Out << " << "; break; + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; + default: #ifndef NDEBUG - errs() << "Invalid operator type!" << I; + errs() << "Invalid operator type!" << I; #endif - llvm_unreachable(0); - } + llvm_unreachable(0); + } - writeOperandWithCast(I.getOperand(1), I.getOpcode()); - // if (NeedsClosingParens) - // Out << "))"; - } + writeOperandWithCast(I.getOperand(1), I.getOpcode()); + // if (NeedsClosingParens) + // Out << "))"; + } } void CWriter::visitICmpInst(ICmpInst &I) { - if (I.getType()->isVectorTy() || - I.getOperand(0)->getType()->getPrimitiveSizeInBits() > 64) { - Out << "llvm_icmp_" << getCmpPredicateName(I.getPredicate()) << "_"; - printTypeString(Out, I.getOperand(0)->getType(), I.isSigned()); - Out << "("; - writeOperand(I.getOperand(0), ContextCasted); - Out << ", "; - writeOperand(I.getOperand(1), ContextCasted); - Out << ")"; - if (VectorType *VTy = dyn_cast<VectorType>(I.getOperand(0)->getType())) { - CmpDeclTypes.insert( - std::pair<CmpInst::Predicate, VectorType *>(I.getPredicate(), VTy)); - TypedefDeclTypes.insert( - I.getType()); // insert type not necessarily visible above - } - return; - } - - // Write out the cast of the instruction's value back to the proper type - // if necessary. - bool NeedsClosingParens = writeInstructionCast(I); - - // Certain icmp predicate require the operand to be forced to a specific type - // so we use writeOperandWithCast here instead of writeOperand. Similarly - // below for operand 1 - writeOperandWithCast(I.getOperand(0), I); - - switch (I.getPredicate()) { - case ICmpInst::ICMP_EQ: - Out << " == "; - break; - case ICmpInst::ICMP_NE: - Out << " != "; - break; - case ICmpInst::ICMP_ULE: - case ICmpInst::ICMP_SLE: - Out << " <= "; - break; - case ICmpInst::ICMP_UGE: - case ICmpInst::ICMP_SGE: - Out << " >= "; - break; - case ICmpInst::ICMP_ULT: - case ICmpInst::ICMP_SLT: - Out << " < "; - break; - case ICmpInst::ICMP_UGT: - case ICmpInst::ICMP_SGT: - Out << " > "; - break; - default: + if (I.getType()->isVectorTy() + || I.getOperand(0)->getType()->getPrimitiveSizeInBits() > 64) { + Out << "llvm_icmp_" << getCmpPredicateName(I.getPredicate()) << "_"; + printTypeString(Out, I.getOperand(0)->getType(), I.isSigned()); + Out << "("; + writeOperand(I.getOperand(0), ContextCasted); + Out << ", "; + writeOperand(I.getOperand(1), ContextCasted); + Out << ")"; + if (VectorType *VTy = dyn_cast<VectorType>(I.getOperand(0)->getType())) { + CmpDeclTypes.insert(std::pair<CmpInst::Predicate, VectorType*>(I.getPredicate(), VTy)); + TypedefDeclTypes.insert(I.getType()); // insert type not necessarily visible above + } + return; + } + + // Write out the cast of the instruction's value back to the proper type + // if necessary. + bool NeedsClosingParens = writeInstructionCast(I); + + // Certain icmp predicate require the operand to be forced to a specific type + // so we use writeOperandWithCast here instead of writeOperand. Similarly + // below for operand 1 + writeOperandWithCast(I.getOperand(0), I); + + switch (I.getPredicate()) { + case ICmpInst::ICMP_EQ: Out << " == "; break; + case ICmpInst::ICMP_NE: Out << " != "; break; + case ICmpInst::ICMP_ULE: + case ICmpInst::ICMP_SLE: Out << " <= "; break; + case ICmpInst::ICMP_UGE: + case ICmpInst::ICMP_SGE: Out << " >= "; break; + case ICmpInst::ICMP_ULT: + case ICmpInst::ICMP_SLT: Out << " < "; break; + case ICmpInst::ICMP_UGT: + case ICmpInst::ICMP_SGT: Out << " > "; break; + default: #ifndef NDEBUG - errs() << "Invalid icmp predicate!" << I; + errs() << "Invalid icmp predicate!" << I; #endif - llvm_unreachable(0); - } + llvm_unreachable(0); + } - writeOperandWithCast(I.getOperand(1), I); - if (NeedsClosingParens) - Out << "))"; + writeOperandWithCast(I.getOperand(1), I); + if (NeedsClosingParens) + Out << "))"; } void CWriter::visitFCmpInst(FCmpInst &I) { - if (I.getType()->isVectorTy()) { - Out << "llvm_fcmp_" << getCmpPredicateName(I.getPredicate()) << "_"; - printTypeString(Out, I.getOperand(0)->getType(), I.isSigned()); - Out << "("; - writeOperand(I.getOperand(0), ContextCasted); - Out << ", "; - writeOperand(I.getOperand(1), ContextCasted); - Out << ")"; - if (VectorType *VTy = dyn_cast<VectorType>(I.getOperand(0)->getType())) { - CmpDeclTypes.insert( - std::pair<CmpInst::Predicate, VectorType *>(I.getPredicate(), VTy)); - TypedefDeclTypes.insert( - I.getType()); // insert type not necessarily visible above - } - return; - } - - Out << "llvm_fcmp_" << getCmpPredicateName(I.getPredicate()) << "("; - // Write the first operand - writeOperand(I.getOperand(0), ContextCasted); - Out << ", "; - // Write the second operand - writeOperand(I.getOperand(1), ContextCasted); - Out << ")"; + if (I.getType()->isVectorTy()) { + Out << "llvm_fcmp_" << getCmpPredicateName(I.getPredicate()) << "_"; + printTypeString(Out, I.getOperand(0)->getType(), I.isSigned()); + Out << "("; + writeOperand(I.getOperand(0), ContextCasted); + Out << ", "; + writeOperand(I.getOperand(1), ContextCasted); + Out << ")"; + if (VectorType *VTy = dyn_cast<VectorType>(I.getOperand(0)->getType())) { + CmpDeclTypes.insert(std::pair<CmpInst::Predicate, VectorType*>(I.getPredicate(), VTy)); + TypedefDeclTypes.insert(I.getType()); // insert type not necessarily visible above + } + return; + } + + Out << "llvm_fcmp_" << getCmpPredicateName(I.getPredicate()) << "("; + // Write the first operand + writeOperand(I.getOperand(0), ContextCasted); + Out << ", "; + // Write the second operand + writeOperand(I.getOperand(1), ContextCasted); + Out << ")"; } -static const char *getFloatBitCastField(Type *Ty) { - switch (Ty->getTypeID()) { - default: - llvm_unreachable("Invalid Type"); - case Type::FloatTyID: - return "Float"; - case Type::DoubleTyID: - return "Double"; - case Type::IntegerTyID: { - unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); - if (NumBits <= 32) - return "Int32"; - else - return "Int64"; - } - } +static const char * getFloatBitCastField(Type *Ty) { + switch (Ty->getTypeID()) { + default: llvm_unreachable("Invalid Type"); + case Type::FloatTyID: return "Float"; + case Type::DoubleTyID: return "Double"; + case Type::IntegerTyID: { + unsigned NumBits = cast<IntegerType>(Ty)->getBitWidth(); + if (NumBits <= 32) + return "Int32"; + else + return "Int64"; + } + } } void CWriter::visitCastInst(CastInst &I) { - // DEBUG(errs() << "This is a cast instruction!\n"); - Type *DstTy = I.getType(); - Type *SrcTy = I.getOperand(0)->getType(); - - if (DstTy->isVectorTy() || SrcTy->isVectorTy() || - DstTy->getPrimitiveSizeInBits() > 64 || - SrcTy->getPrimitiveSizeInBits() > 64) { - Out << "llvm_" << I.getOpcodeName() << "_"; - printTypeString(Out, SrcTy, false); - Out << "_"; - printTypeString(Out, DstTy, false); - Out << "("; - writeOperand(I.getOperand(0), ContextCasted); - Out << ")"; - CastOpDeclTypes.insert( - std::pair<Instruction::CastOps, std::pair<Type *, Type *>>( - I.getOpcode(), std::pair<Type *, Type *>(SrcTy, DstTy))); - return; - } - - if (isFPIntBitCast(I)) { - Out << '('; - // These int<->float and long<->double casts need to be handled specially - Out << GetValueName(&I) << "__BITCAST_TEMPORARY." - << getFloatBitCastField(I.getOperand(0)->getType()) << " = "; - writeOperand(I.getOperand(0), ContextCasted); - Out << ", " << GetValueName(&I) << "__BITCAST_TEMPORARY." - << getFloatBitCastField(I.getType()); - Out << ')'; - return; - } - - Out << '('; - printCast(I.getOpcode(), SrcTy, DstTy); - - // Make a sext from i1 work by subtracting the i1 from 0 (an int). - if (SrcTy == Type::getInt1Ty(I.getContext()) && - I.getOpcode() == Instruction::SExt) - Out << "0-"; - - writeOperand(I.getOperand(0), ContextCasted); - - if (DstTy == Type::getInt1Ty(I.getContext()) && - (I.getOpcode() == Instruction::Trunc || - I.getOpcode() == Instruction::FPToUI || - I.getOpcode() == Instruction::FPToSI || - I.getOpcode() == Instruction::PtrToInt)) { - // Make sure we really get a trunc to bool by anding the operand with 1 - Out << "&1u"; - } - Out << ')'; + DEBUG(errs() << "This is a cast instruction!\n"); + Type *DstTy = I.getType(); + Type *SrcTy = I.getOperand(0)->getType(); + + if (DstTy->isVectorTy() || SrcTy->isVectorTy() + || DstTy->getPrimitiveSizeInBits() > 64 + || SrcTy->getPrimitiveSizeInBits() > 64) { + Out << "llvm_" << I.getOpcodeName() << "_"; + printTypeString(Out, SrcTy, false); + Out << "_"; + printTypeString(Out, DstTy, false); + Out << "("; + writeOperand(I.getOperand(0), ContextCasted); + Out << ")"; + CastOpDeclTypes.insert(std::pair<Instruction::CastOps, std::pair<Type*, Type*> >(I.getOpcode(), std::pair<Type*, Type*>(SrcTy, DstTy))); + return; + } + + if (isFPIntBitCast(I)) { + Out << '('; + // These int<->float and long<->double casts need to be handled specially + Out << GetValueName(&I) << "__BITCAST_TEMPORARY." + << getFloatBitCastField(I.getOperand(0)->getType()) << " = "; + writeOperand(I.getOperand(0), ContextCasted); + Out << ", " << GetValueName(&I) << "__BITCAST_TEMPORARY." + << getFloatBitCastField(I.getType()); + Out << ')'; + return; + } + + Out << '('; + printCast(I.getOpcode(), SrcTy, DstTy); + + // Make a sext from i1 work by subtracting the i1 from 0 (an int). + if (SrcTy == Type::getInt1Ty(I.getContext()) && + I.getOpcode() == Instruction::SExt) + Out << "0-"; + + writeOperand(I.getOperand(0), ContextCasted); + + if (DstTy == Type::getInt1Ty(I.getContext()) && + (I.getOpcode() == Instruction::Trunc || + I.getOpcode() == Instruction::FPToUI || + I.getOpcode() == Instruction::FPToSI || + I.getOpcode() == Instruction::PtrToInt)) { + // Make sure we really get a trunc to bool by anding the operand with 1 + Out << "&1u"; + } + Out << ')'; } void CWriter::visitSelectInst(SelectInst &I) { - Out << "llvm_select_"; - printTypeString(Out, I.getType(), false); - Out << "("; - writeOperand(I.getCondition(), ContextCasted); - Out << ", "; - writeOperand(I.getTrueValue(), ContextCasted); - Out << ", "; - writeOperand(I.getFalseValue(), ContextCasted); - Out << ")"; - SelectDeclTypes.insert(I.getType()); - assert(I.getCondition()->getType()->isVectorTy() == - I.getType()->isVectorTy()); // TODO: might be scalarty == vectorty + Out << "llvm_select_"; + printTypeString(Out, I.getType(), false); + Out << "("; + writeOperand(I.getCondition(), ContextCasted); + Out << ", "; + writeOperand(I.getTrueValue(), ContextCasted); + Out << ", "; + writeOperand(I.getFalseValue(), ContextCasted); + Out << ")"; + SelectDeclTypes.insert(I.getType()); + assert(I.getCondition()->getType()->isVectorTy() == I.getType()->isVectorTy()); // TODO: might be scalarty == vectorty } // Returns the macro name or value of the max or min of an integer type // (as defined in limits.h). static void printLimitValue(IntegerType &Ty, bool isSigned, bool isMax, - raw_ostream &Out) { - const char *type; - const char *sprefix = ""; - - unsigned NumBits = Ty.getBitWidth(); - if (NumBits <= 8) { - type = "CHAR"; - sprefix = "S"; - } else if (NumBits <= 16) { - type = "SHRT"; - } else if (NumBits <= 32) { - type = "INT"; - } else if (NumBits <= 64) { - type = "LLONG"; - } else { - llvm_unreachable("Bit widths > 64 not implemented yet"); - } - - if (isSigned) - Out << sprefix << type << (isMax ? "_MAX" : "_MIN"); - else - Out << "U" << type << (isMax ? "_MAX" : "0"); + raw_ostream &Out) { + const char* type; + const char* sprefix = ""; + + unsigned NumBits = Ty.getBitWidth(); + if (NumBits <= 8) { + type = "CHAR"; + sprefix = "S"; + } else if (NumBits <= 16) { + type = "SHRT"; + } else if (NumBits <= 32) { + type = "INT"; + } else if (NumBits <= 64) { + type = "LLONG"; + } else { + llvm_unreachable("Bit widths > 64 not implemented yet"); + } + + if (isSigned) + Out << sprefix << type << (isMax ? "_MAX" : "_MIN"); + else + Out << "U" << type << (isMax ? "_MAX" : "0"); } #ifndef NDEBUG static bool isSupportedIntegerSize(IntegerType &T) { - return T.getBitWidth() == 8 || T.getBitWidth() == 16 || - T.getBitWidth() == 32 || T.getBitWidth() == 64 || - T.getBitWidth() == 128; + return T.getBitWidth() == 8 || T.getBitWidth() == 16 || + T.getBitWidth() == 32 || T.getBitWidth() == 64 || + T.getBitWidth() == 128; } #endif -void CWriter::printIntrinsicDefinition(FunctionType *funT, unsigned Opcode, - std::string OpName, raw_ostream &Out) { - Type *retT = funT->getReturnType(); - Type *elemT = funT->getParamType(0); - IntegerType *elemIntT = dyn_cast<IntegerType>(elemT); - char i, numParams = funT->getNumParams(); - bool isSigned; - switch (Opcode) { - default: - isSigned = false; - break; - case Intrinsic::sadd_with_overflow: - case Intrinsic::ssub_with_overflow: - case Intrinsic::smul_with_overflow: - isSigned = true; - break; - } - assert(numParams > 0 && numParams < 26); - - if (isa<VectorType>(retT)) { - // this looks general, but is only actually used for ctpop, ctlz, cttz - Type **devecFunParams = (Type **)alloca(sizeof(Type *) * numParams); - for (i = 0; i < numParams; i++) { - devecFunParams[(int)i] = funT->params()[(int)i]->getScalarType(); - } - FunctionType *devecFunT = FunctionType::get( - funT->getReturnType()->getScalarType(), - makeArrayRef(devecFunParams, numParams), funT->isVarArg()); - printIntrinsicDefinition(devecFunT, Opcode, OpName + "_devec", Out); - } +void CWriter::printIntrinsicDefinition(FunctionType *funT, + unsigned Opcode, std::string OpName, raw_ostream &Out) { + Type *retT = funT->getReturnType(); + Type *elemT = funT->getParamType(0); + IntegerType *elemIntT = dyn_cast<IntegerType>(elemT); + char i, numParams = funT->getNumParams(); + bool isSigned; + switch (Opcode) { + default: + isSigned = false; + break; + case Intrinsic::sadd_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::smul_with_overflow: + isSigned = true; + break; + } + assert(numParams > 0 && numParams < 26); + + if (isa<VectorType>(retT)) { + // this looks general, but is only actually used for ctpop, ctlz, cttz + Type* *devecFunParams = (Type**)alloca(sizeof(Type*) * numParams); + for (i = 0; i < numParams; i++) { + devecFunParams[(int)i] = funT->params()[(int)i]->getScalarType(); + } + FunctionType *devecFunT = FunctionType::get(funT->getReturnType()->getScalarType(), + makeArrayRef(devecFunParams, numParams), funT->isVarArg()); + printIntrinsicDefinition(devecFunT, Opcode, OpName + "_devec", Out); + } + + // static __forceinline Rty _llvm_op_ixx(unsigned ixx a, unsigned ixx b) { + // Rty r; + // <opcode here> + // return r; + // } + Out << "static __forceinline "; + printTypeName(Out, retT); + Out << " "; + Out << OpName; + Out << "("; + for (i = 0; i < numParams; i++) { + switch (Opcode) { + // optional intrinsic validity assertion checks + default: + // default case: assume all parameters must have the same type + assert(elemT == funT->getParamType(i)); + break; + case Intrinsic::ctlz: + case Intrinsic::cttz: + case Intrinsic::powi: + break; + } + printTypeNameUnaligned(Out, funT->getParamType(i), isSigned); + Out << " " << (char)('a' + i); + if (i != numParams - 1) Out << ", "; + } + Out << ") {\n "; + printTypeName(Out, retT); + Out << " r;\n"; + + if (isa<VectorType>(retT)) { + for (i = 0; i < numParams; i++) { + Out << " r.vector[" << (int)i << "] = " << OpName << "_devec("; + for (char j = 0; j < numParams; j++) { + Out << (char)('a' + j); + if (isa<VectorType>(funT->params()[j])) + Out << ".vector[" << (int)i << "]"; + if (j != numParams - 1) Out << ", "; + } + Out << ");\n"; + } + } + else if (elemIntT) { + // handle integer ops + assert(isSupportedIntegerSize(*elemIntT) && + "CBackend does not support arbitrary size integers."); + switch (Opcode) { + default: +#ifndef NDEBUG + errs() << "Unsupported Intrinsic!" << Opcode; +#endif + llvm_unreachable(0); + + case Intrinsic::uadd_with_overflow: + // r.field0 = a + b; + // r.field1 = (r.field0 < a); + assert(cast<StructType>(retT)->getElementType(0) == elemT); + Out << " r.field0 = a + b;\n"; + Out << " r.field1 = (a >= -b);\n"; + break; + + case Intrinsic::sadd_with_overflow: + // r.field0 = a + b; + // r.field1 = (b > 0 && a > XX_MAX - b) || + // (b < 0 && a < XX_MIN - b); + assert(cast<StructType>(retT)->getElementType(0) == elemT); + Out << " r.field0 = a + b;\n"; + Out << " r.field1 = (b >= 0 ? a > "; + printLimitValue(*elemIntT, true, true, Out); + Out << " - b : a < "; + printLimitValue(*elemIntT, true, false, Out); + Out << " - b);\n"; + break; + + case Intrinsic::usub_with_overflow: + assert(cast<StructType>(retT)->getElementType(0) == elemT); + Out << " r.field0 = a - b;\n"; + Out << " r.field1 = (a < b);\n"; + break; + + case Intrinsic::ssub_with_overflow: + assert(cast<StructType>(retT)->getElementType(0) == elemT); + Out << " r.field0 = a - b;\n"; + Out << " r.field1 = (b <= 0 ? a > "; + printLimitValue(*elemIntT, true, true, Out); + Out << " + b : a < "; + printLimitValue(*elemIntT, true, false, Out); + Out << " + b);\n"; + break; + + case Intrinsic::umul_with_overflow: + assert(cast<StructType>(retT)->getElementType(0) == elemT); + Out << " r.field1 = LLVMMul_uov(8 * sizeof(a), &a, &b, &r.field0);\n"; + break; + + case Intrinsic::smul_with_overflow: + assert(cast<StructType>(retT)->getElementType(0) == elemT); + Out << " r.field1 = LLVMMul_sov(8 * sizeof(a), &a, &b, &r.field0);\n"; + break; + + case Intrinsic::bswap: + assert(retT == elemT); + Out << " LLVMFlipAllBits(8 * sizeof(a), &a, &r);\n"; + break; + + case Intrinsic::ctpop: + assert(retT == elemT); + Out << " r = "; + if (retT->getPrimitiveSizeInBits() > 64) + Out << "llvm_ctor_u128(0, "; + Out << "LLVMCountPopulation(8 * sizeof(a), &a)"; + if (retT->getPrimitiveSizeInBits() > 64) + Out << ")"; + Out << ";\n"; + break; + + case Intrinsic::ctlz: + assert(retT == elemT); + Out << " (void)b;\n r = "; + if (retT->getPrimitiveSizeInBits() > 64) + Out << "llvm_ctor_u128(0, "; + Out << "LLVMCountLeadingZeros(8 * sizeof(a), &a)"; + if (retT->getPrimitiveSizeInBits() > 64) + Out << ")"; + Out << ";\n"; + break; + + case Intrinsic::cttz: + assert(retT == elemT); + Out << " (void)b;\n r = "; + if (retT->getPrimitiveSizeInBits() > 64) + Out << "llvm_ctor_u128(0, "; + Out << "LLVMCountTrailingZeros(8 * sizeof(a), &a)"; + if (retT->getPrimitiveSizeInBits() > 64) + Out << ")"; + Out << ";\n"; + break; + } + + } else { + // handle FP ops + const char *suffix; + assert(retT == elemT); + if (elemT->isFloatTy() || elemT->isHalfTy()) { + suffix = "f"; + } else if (elemT->isDoubleTy()) { + suffix = ""; + } else if (elemT->isFP128Ty()) { + } else if (elemT->isX86_FP80Ty()) { + } else if (elemT->isPPC_FP128Ty()) { + suffix = "l"; + } else { +#ifndef NDEBUG + errs() << "Unsupported Intrinsic!" << Opcode; +#endif + llvm_unreachable(0); + } - // static __forceinline Rty _llvm_op_ixx(unsigned ixx a, unsigned ixx b) { - // Rty r; - // <opcode here> - // return r; - // } - Out << "static __forceinline "; - printTypeName(Out, retT); - Out << " "; - Out << OpName; - Out << "("; - for (i = 0; i < numParams; i++) { - switch (Opcode) { - // optional intrinsic validity assertion checks - default: - // default case: assume all parameters must have the same type - assert(elemT == funT->getParamType(i)); - break; - case Intrinsic::ctlz: - case Intrinsic::cttz: - case Intrinsic::powi: - break; - } - printTypeNameUnaligned(Out, funT->getParamType(i), isSigned); - Out << " " << (char)('a' + i); - if (i != numParams - 1) - Out << ", "; - } - Out << ") {\n "; - printTypeName(Out, retT); - Out << " r;\n"; - - if (isa<VectorType>(retT)) { - for (i = 0; i < numParams; i++) { - Out << " r.vector[" << (int)i << "] = " << OpName << "_devec("; - for (char j = 0; j < numParams; j++) { - Out << (char)('a' + j); - if (isa<VectorType>(funT->params()[j])) - Out << ".vector[" << (int)i << "]"; - if (j != numParams - 1) - Out << ", "; - } - Out << ");\n"; - } - } else if (elemIntT) { - // handle integer ops - assert(isSupportedIntegerSize(*elemIntT) && - "CBackend does not support arbitrary size integers."); - switch (Opcode) { - default: + switch (Opcode) { + default: #ifndef NDEBUG - errs() << "Unsupported Intrinsic!" << Opcode; + errs() << "Unsupported Intrinsic!" << Opcode; #endif - llvm_unreachable(0); - - case Intrinsic::uadd_with_overflow: - // r.field0 = a + b; - // r.field1 = (r.field0 < a); - assert(cast<StructType>(retT)->getElementType(0) == elemT); - Out << " r.field0 = a + b;\n"; - Out << " r.field1 = (a >= -b);\n"; - break; + llvm_unreachable(0); - case Intrinsic::sadd_with_overflow: - // r.field0 = a + b; - // r.field1 = (b > 0 && a > XX_MAX - b) || - // (b < 0 && a < XX_MIN - b); - assert(cast<StructType>(retT)->getElementType(0) == elemT); - Out << " r.field0 = a + b;\n"; - Out << " r.field1 = (b >= 0 ? a > "; - printLimitValue(*elemIntT, true, true, Out); - Out << " - b : a < "; - printLimitValue(*elemIntT, true, false, Out); - Out << " - b);\n"; - break; + case Intrinsic::ceil: + Out << " r = ceil" << suffix << "(a);\n"; + break; - case Intrinsic::usub_with_overflow: - assert(cast<StructType>(retT)->getElementType(0) == elemT); - Out << " r.field0 = a - b;\n"; - Out << " r.field1 = (a < b);\n"; - break; + case Intrinsic::fabs: + Out << " r = fabs" << suffix << "(a);\n"; + break; - case Intrinsic::ssub_with_overflow: - assert(cast<StructType>(retT)->getElementType(0) == elemT); - Out << " r.field0 = a - b;\n"; - Out << " r.field1 = (b <= 0 ? a > "; - printLimitValue(*elemIntT, true, true, Out); - Out << " + b : a < "; - printLimitValue(*elemIntT, true, false, Out); - Out << " + b);\n"; - break; + case Intrinsic::floor: + Out << " r = floor" << suffix << "(a);\n"; + break; - case Intrinsic::umul_with_overflow: - assert(cast<StructType>(retT)->getElementType(0) == elemT); - Out << " r.field1 = LLVMMul_uov(8 * sizeof(a), &a, &b, &r.field0);\n"; - break; + case Intrinsic::fma: + Out << " r = fma" << suffix << "(a, b, c);\n"; + break; - case Intrinsic::smul_with_overflow: - assert(cast<StructType>(retT)->getElementType(0) == elemT); - Out << " r.field1 = LLVMMul_sov(8 * sizeof(a), &a, &b, &r.field0);\n"; - break; + case Intrinsic::fmuladd: + Out << " r = a * b + c;\n"; + break; - case Intrinsic::bswap: - assert(retT == elemT); - Out << " LLVMFlipAllBits(8 * sizeof(a), &a, &r);\n"; - break; + case Intrinsic::pow: + case Intrinsic::powi: + Out << " r = pow" << suffix << "(a, b);\n"; + break; - case Intrinsic::ctpop: - assert(retT == elemT); - Out << " r = "; - if (retT->getPrimitiveSizeInBits() > 64) - Out << "llvm_ctor_u128(0, "; - Out << "LLVMCountPopulation(8 * sizeof(a), &a)"; - if (retT->getPrimitiveSizeInBits() > 64) - Out << ")"; - Out << ";\n"; - break; + case Intrinsic::rint: + Out << " r = rint" << suffix << "(a);\n"; + break; - case Intrinsic::ctlz: - assert(retT == elemT); - Out << " (void)b;\n r = "; - if (retT->getPrimitiveSizeInBits() > 64) - Out << "llvm_ctor_u128(0, "; - Out << "LLVMCountLeadingZeros(8 * sizeof(a), &a)"; - if (retT->getPrimitiveSizeInBits() > 64) - Out << ")"; - Out << ";\n"; - break; + case Intrinsic::sqrt: + Out << " r = sqrt" << "(a);\n"; + break; - case Intrinsic::cttz: - assert(retT == elemT); - Out << " (void)b;\n r = "; - if (retT->getPrimitiveSizeInBits() > 64) - Out << "llvm_ctor_u128(0, "; - Out << "LLVMCountTrailingZeros(8 * sizeof(a), &a)"; - if (retT->getPrimitiveSizeInBits() > 64) - Out << ")"; - Out << ";\n"; - break; - } + case Intrinsic::trunc: + Out << " r = trunc" << suffix << "(a);\n"; + break; - } else { - // handle FP ops - const char *suffix; - assert(retT == elemT); - if (elemT->isFloatTy() || elemT->isHalfTy()) { - suffix = "f"; - } else if (elemT->isDoubleTy()) { - suffix = ""; - } else if (elemT->isFP128Ty()) { - } else if (elemT->isX86_FP80Ty()) { - } else if (elemT->isPPC_FP128Ty()) { - suffix = "l"; - } else { -#ifndef NDEBUG - errs() << "Unsupported Intrinsic!" << Opcode; -#endif - llvm_unreachable(0); - } - - switch (Opcode) { - default: -#ifndef NDEBUG - errs() << "Unsupported Intrinsic!" << Opcode; -#endif - llvm_unreachable(0); - - case Intrinsic::ceil: - Out << " r = ceil" << suffix << "(a);\n"; - break; - - case Intrinsic::fabs: - Out << " r = fabs" << suffix << "(a);\n"; - break; - - case Intrinsic::floor: - Out << " r = floor" << suffix << "(a);\n"; - break; - - case Intrinsic::fma: - Out << " r = fma" << suffix << "(a, b, c);\n"; - break; - - case Intrinsic::fmuladd: - Out << " r = a * b + c;\n"; - break; - - case Intrinsic::pow: - case Intrinsic::powi: - Out << " r = pow" << suffix << "(a, b);\n"; - break; - - case Intrinsic::rint: - Out << " r = rint" << suffix << "(a);\n"; - break; - - case Intrinsic::sqrt: - Out << " r = sqrt" << suffix << "(a);\n"; - break; - - case Intrinsic::trunc: - Out << " r = trunc" << suffix << "(a);\n"; - break; - } - } + } + } - Out << " return r;\n}\n"; + Out << " return r;\n}\n"; } void CWriter::printIntrinsicDefinition(Function &F, raw_ostream &Out) { - FunctionType *funT = F.getFunctionType(); - unsigned Opcode = F.getIntrinsicID(); - std::string OpName = GetValueName(&F); - printIntrinsicDefinition(funT, Opcode, OpName, Out); + FunctionType *funT = F.getFunctionType(); + unsigned Opcode = F.getIntrinsicID(); + std::string OpName = GetValueName(&F); + printIntrinsicDefinition(funT, Opcode, OpName, Out); } void CWriter::lowerIntrinsics(Function &F) { - // Examine all the instructions in this function to find the intrinsics that - // need to be lowered. - for (Function::iterator BB = F.begin(), EE = F.end(); BB != EE; ++BB) - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E;) - if (CallInst *CI = dyn_cast<CallInst>(I++)) - if (Function *F = CI->getCalledFunction()) - switch (F->getIntrinsicID()) { - case Intrinsic::not_intrinsic: - case Intrinsic::vastart: - case Intrinsic::vacopy: - case Intrinsic::vaend: - case Intrinsic::returnaddress: - case Intrinsic::frameaddress: - case Intrinsic::setjmp: - case Intrinsic::longjmp: - case Intrinsic::sigsetjmp: - case Intrinsic::siglongjmp: - case Intrinsic::prefetch: - case Intrinsic::x86_sse_cmp_ss: - case Intrinsic::x86_sse_cmp_ps: - case Intrinsic::x86_sse2_cmp_sd: - case Intrinsic::x86_sse2_cmp_pd: - case Intrinsic::ppc_altivec_lvsl: - case Intrinsic::uadd_with_overflow: - case Intrinsic::sadd_with_overflow: - case Intrinsic::usub_with_overflow: - case Intrinsic::ssub_with_overflow: - case Intrinsic::umul_with_overflow: - case Intrinsic::smul_with_overflow: - case Intrinsic::bswap: - case Intrinsic::ceil: - case Intrinsic::ctlz: - case Intrinsic::ctpop: - case Intrinsic::cttz: - case Intrinsic::fabs: - case Intrinsic::floor: - case Intrinsic::fma: - case Intrinsic::fmuladd: - case Intrinsic::pow: - case Intrinsic::powi: - case Intrinsic::rint: - case Intrinsic::sqrt: - case Intrinsic::trunc: - case Intrinsic::trap: - case Intrinsic::stackprotector: - case Intrinsic::dbg_value: - case Intrinsic::dbg_declare: - // We directly implement these intrinsics - break; - default: - // All other intrinsic calls we must lower. - BasicBlock::iterator Before = E; - if (CI != &BB->front()) - Before = std::prev(BasicBlock::iterator(CI)); - - IL->LowerIntrinsicCall(CI); - if (Before != E) { // Move iterator to instruction after call - I = Before; - ++I; - } else { - I = BB->begin(); - } - // If the intrinsic got lowered to another call, and that call has - // a definition then we need to make sure its prototype is emitted - // before any calls to it. - if (CallInst *Call = dyn_cast<CallInst>(I)) - if (Function *NewF = Call->getCalledFunction()) - if (!NewF->isDeclaration()) - prototypesToGen.push_back(NewF); - - break; - } + // Examine all the instructions in this function to find the intrinsics that + // need to be lowered. + for (Function::iterator BB = F.begin(), EE = F.end(); BB != EE; ++BB) + for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) + if (CallInst *CI = dyn_cast<CallInst>(I++)) + if (Function *F = CI->getCalledFunction()) + switch (F->getIntrinsicID()) { + case Intrinsic::not_intrinsic: + case Intrinsic::vastart: + case Intrinsic::vacopy: + case Intrinsic::vaend: + case Intrinsic::returnaddress: + case Intrinsic::frameaddress: + case Intrinsic::setjmp: + case Intrinsic::longjmp: + case Intrinsic::sigsetjmp: + case Intrinsic::siglongjmp: + case Intrinsic::prefetch: + case Intrinsic::x86_sse_cmp_ss: + case Intrinsic::x86_sse_cmp_ps: + case Intrinsic::x86_sse2_cmp_sd: + case Intrinsic::x86_sse2_cmp_pd: + case Intrinsic::ppc_altivec_lvsl: + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::umul_with_overflow: + case Intrinsic::smul_with_overflow: + case Intrinsic::bswap: + case Intrinsic::ceil: + case Intrinsic::ctlz: + case Intrinsic::ctpop: + case Intrinsic::cttz: + case Intrinsic::fabs: + case Intrinsic::floor: + case Intrinsic::fma: + case Intrinsic::fmuladd: + case Intrinsic::pow: + case Intrinsic::powi: + case Intrinsic::rint: + case Intrinsic::sqrt: + case Intrinsic::trunc: + case Intrinsic::trap: + case Intrinsic::stackprotector: + case Intrinsic::dbg_value: + case Intrinsic::dbg_declare: + // We directly implement these intrinsics + break; + default: + // All other intrinsic calls we must lower. + BasicBlock::iterator Before = E; + if (CI != &BB->front()) + Before = std::prev(BasicBlock::iterator(CI)); + + IL->LowerIntrinsicCall(CI); + if (Before != E) { // Move iterator to instruction after call + I = Before; ++I; + } else { + I = BB->begin(); + } + // If the intrinsic got lowered to another call, and that call has + // a definition then we need to make sure its prototype is emitted + // before any calls to it. + if (CallInst *Call = dyn_cast<CallInst>(I)) + if (Function *NewF = Call->getCalledFunction()) + if (!NewF->isDeclaration()) + prototypesToGen.push_back(NewF); + + break; + } } void CWriter::visitCallInst(CallInst &I) { - if (isa<InlineAsm>(I.getCalledValue())) - return visitInlineAsm(I); - - // Handle intrinsic function calls first... - if (Function *F = I.getCalledFunction()) - if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) - if (visitBuiltinCall(I, ID)) - return; - - Value *Callee = I.getCalledValue(); - - PointerType *PTy = cast<PointerType>(Callee->getType()); - FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); - - // If this is a call to a struct-return function, assign to the first - // parameter instead of passing it to the call. - - // CHECK: If AttributeList replaces AttributeSet for CallInst - const AttributeList PAL = I.getAttributes(); - bool hasByVal = I.hasByValArgument(); - bool isStructRet = I.hasStructRetAttr(); - if (isStructRet) { - writeOperandDeref(I.getArgOperand(0)); - Out << " = "; - } - - if (I.isTailCall()) - Out << " /*tail*/ "; - - // If this is an indirect call to a struct return function, we need to cast - // the pointer. Ditto for indirect calls with byval arguments. - bool NeedsCast = - (hasByVal || isStructRet || I.getCallingConv() != CallingConv::C) && - !isa<Function>(Callee); - - // GCC is a real PITA. It does not permit codegening casts of functions to - // function pointers if they are in a call (it generates a trap instruction - // instead!). We work around this by inserting a cast to void* in between - // the function and the function pointer cast. Unfortunately, we can't just - // form the constant expression here, because the folder will immediately - // nuke it. - // - // Note finally, that this is completely unsafe. ANSI C does not guarantee - // that void* and function pointers have the same size. :( To deal with this - // in the common case, we handle casts where the number of arguments passed - // match exactly. - // - if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Callee)) - if (CE->isCast()) - if (Function *RF = dyn_cast<Function>(CE->getOperand(0))) { - NeedsCast = true; - Callee = RF; - } - - if (NeedsCast) { - // Ok, just cast the pointer type. - Out << "(("; - printTypeName(Out, I.getCalledValue()->getType()->getPointerElementType(), - false, std::make_pair(PAL, I.getCallingConv())); - Out << "*)(void*)"; - } - writeOperand(Callee, ContextCasted); - if (NeedsCast) - Out << ')'; - - Out << '('; - - bool PrintedArg = false; - if (FTy->isVarArg() && !FTy->getNumParams()) { - Out << "0 /*dummy arg*/"; - PrintedArg = true; - } - - unsigned NumDeclaredParams = FTy->getNumParams(); - CallSite CS(&I); - CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); - unsigned ArgNo = 0; - if (isStructRet) { // Skip struct return argument. - ++AI; - ++ArgNo; - } - - Function *F = I.getCalledFunction(); - if (F) { - StringRef Name = F->getName(); - // emit cast for the first argument to type expected by header prototype - // the jmp_buf type is an array, so the array-to-pointer decay adds the - // strange extra *'s - if (Name == "sigsetjmp") - Out << "*(sigjmp_buf*)"; - else if (Name == "setjmp") - Out << "*(jmp_buf*)"; - } - - for (; AI != AE; ++AI, ++ArgNo) { - if (PrintedArg) - Out << ", "; - if (ArgNo < NumDeclaredParams && - (*AI)->getType() != FTy->getParamType(ArgNo)) { - Out << '('; - printTypeNameUnaligned( - Out, FTy->getParamType(ArgNo), - /*isSigned=*/PAL.hasAttribute(ArgNo + 1, Attribute::SExt)); - Out << ')'; - } - // Check if the argument is expected to be passed by value. - if (I.getAttributes().hasAttribute(ArgNo + 1, Attribute::ByVal)) - writeOperandDeref(*AI); - else - writeOperand(*AI, ContextCasted); - PrintedArg = true; - } - Out << ')'; + if (isa<InlineAsm>(I.getCalledValue())) + return visitInlineAsm(I); + + // Handle intrinsic function calls first... + if (Function *F = I.getCalledFunction()) + if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) + if (visitBuiltinCall(I, ID)) + return; + + Value *Callee = I.getCalledValue(); + + PointerType *PTy = cast<PointerType>(Callee->getType()); + FunctionType *FTy = cast<FunctionType>(PTy->getElementType()); + + // If this is a call to a struct-return function, assign to the first + // parameter instead of passing it to the call. + + // CHECK: If AttributeList replaces AttributeSet for CallInst + const AttributeList PAL = I.getAttributes(); + bool hasByVal = I.hasByValArgument(); + bool isStructRet = I.hasStructRetAttr(); + if (isStructRet) { + writeOperandDeref(I.getArgOperand(0)); + Out << " = "; + } + + if (I.isTailCall()) Out << " /*tail*/ "; + + // If this is an indirect call to a struct return function, we need to cast + // the pointer. Ditto for indirect calls with byval arguments. + bool NeedsCast = (hasByVal || isStructRet || I.getCallingConv() != CallingConv::C) && !isa<Function>(Callee); + + // GCC is a real PITA. It does not permit codegening casts of functions to + // function pointers if they are in a call (it generates a trap instruction + // instead!). We work around this by inserting a cast to void* in between + // the function and the function pointer cast. Unfortunately, we can't just + // form the constant expression here, because the folder will immediately + // nuke it. + // + // Note finally, that this is completely unsafe. ANSI C does not guarantee + // that void* and function pointers have the same size. :( To deal with this + // in the common case, we handle casts where the number of arguments passed + // match exactly. + // + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Callee)) + if (CE->isCast()) + if (Function *RF = dyn_cast<Function>(CE->getOperand(0))) { + NeedsCast = true; + Callee = RF; + } + + if (NeedsCast) { + // Ok, just cast the pointer type. + Out << "(("; + printTypeName(Out, I.getCalledValue()->getType()->getPointerElementType(), false, std::make_pair(PAL, I.getCallingConv())); + Out << "*)(void*)"; + } + writeOperand(Callee, ContextCasted); + if (NeedsCast) Out << ')'; + + Out << '('; + + bool PrintedArg = false; + if (FTy->isVarArg() && !FTy->getNumParams()) { + Out << "0 /*dummy arg*/"; + PrintedArg = true; + } + + unsigned NumDeclaredParams = FTy->getNumParams(); + CallSite CS(&I); + CallSite::arg_iterator AI = CS.arg_begin(), AE = CS.arg_end(); + unsigned ArgNo = 0; + if (isStructRet) { // Skip struct return argument. + ++AI; + ++ArgNo; + } + + Function *F = I.getCalledFunction(); + if (F) { + StringRef Name = F->getName(); + // emit cast for the first argument to type expected by header prototype + // the jmp_buf type is an array, so the array-to-pointer decay adds the + // strange extra *'s + if (Name == "sigsetjmp") + Out << "*(sigjmp_buf*)"; + else if (Name == "setjmp") + Out << "*(jmp_buf*)"; + } + + for (; AI != AE; ++AI, ++ArgNo) { + if (PrintedArg) Out << ", "; + if (ArgNo < NumDeclaredParams && + (*AI)->getType() != FTy->getParamType(ArgNo)) { + Out << '('; + printTypeNameUnaligned(Out, FTy->getParamType(ArgNo), + /*isSigned=*/PAL.hasAttribute(ArgNo+1, Attribute::SExt)); + Out << ')'; + } + // Check if the argument is expected to be passed by value. + if (I.getAttributes().hasAttribute(ArgNo+1, Attribute::ByVal)) + writeOperandDeref(*AI); + else + writeOperand(*AI, ContextCasted); + PrintedArg = true; + } + Out << ')'; } /// visitBuiltinCall - Handle the call to the specified builtin. Returns true /// if the entire call is handled, return false if it wasn't handled bool CWriter::visitBuiltinCall(CallInst &I, Intrinsic::ID ID) { - switch (ID) { - default: { + switch (ID) { + default: { #ifndef NDEBUG - errs() << "Unknown LLVM intrinsic! " << I; + errs() << "Unknown LLVM intrinsic! " << I; #endif - llvm_unreachable(0); - return false; - } - - case Intrinsic::dbg_value: - case Intrinsic::dbg_declare: - return true; // ignore these intrinsics - case Intrinsic::vastart: - Out << "0; "; - - Out << "va_start(*(va_list*)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ", "; - // Output the last argument to the enclosing function. - if (I.getParent()->getParent()->arg_empty()) - Out << "vararg_dummy_arg"; - else - writeOperand(&*(I.getParent()->getParent()->arg_end() - 1)); - Out << ')'; - return true; - case Intrinsic::vaend: - if (!isa<ConstantPointerNull>(I.getArgOperand(0))) { - Out << "0; va_end(*(va_list*)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ')'; - } else { - Out << "va_end(*(va_list*)0)"; - } - return true; - case Intrinsic::vacopy: - Out << "0; "; - Out << "va_copy(*(va_list*)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ", *(va_list*)"; - writeOperand(I.getArgOperand(1), ContextCasted); - Out << ')'; - return true; - case Intrinsic::returnaddress: - Out << "__builtin_return_address("; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ')'; - return true; - case Intrinsic::frameaddress: - Out << "__builtin_frame_address("; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ')'; - return true; - case Intrinsic::setjmp: - Out << "setjmp(*(jmp_buf*)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ')'; - return true; - case Intrinsic::longjmp: - Out << "longjmp(*(jmp_buf*)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ", "; - writeOperand(I.getArgOperand(1), ContextCasted); - Out << ')'; - return true; - case Intrinsic::sigsetjmp: - Out << "sigsetjmp(*(sigjmp_buf*)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ','; - writeOperand(I.getArgOperand(1), ContextCasted); - Out << ')'; - return true; - case Intrinsic::siglongjmp: - Out << "siglongjmp(*(sigjmp_buf*)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ", "; - writeOperand(I.getArgOperand(1), ContextCasted); - Out << ')'; - return true; - case Intrinsic::prefetch: - Out << "LLVM_PREFETCH((const void *)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ", "; - writeOperand(I.getArgOperand(1), ContextCasted); - Out << ", "; - writeOperand(I.getArgOperand(2), ContextCasted); - Out << ")"; - return true; - case Intrinsic::stacksave: - // Emit this as: Val = 0; *((void**)&Val) = __builtin_stack_save() - // to work around GCC bugs (see PR1809). - Out << "0; *((void**)&" << GetValueName(&I) << ") = __builtin_stack_save()"; - return true; - case Intrinsic::x86_sse_cmp_ss: - case Intrinsic::x86_sse_cmp_ps: - case Intrinsic::x86_sse2_cmp_sd: - case Intrinsic::x86_sse2_cmp_pd: - Out << '('; - printTypeName(Out, I.getType()); - Out << ')'; - // Multiple GCC builtins multiplex onto this intrinsic. - switch (cast<ConstantInt>(I.getArgOperand(2))->getZExtValue()) { - default: - llvm_unreachable("Invalid llvm.x86.sse.cmp!"); - case 0: - Out << "__builtin_ia32_cmpeq"; - break; - case 1: - Out << "__builtin_ia32_cmplt"; - break; - case 2: - Out << "__builtin_ia32_cmple"; - break; - case 3: - Out << "__builtin_ia32_cmpunord"; - break; - case 4: - Out << "__builtin_ia32_cmpneq"; - break; - case 5: - Out << "__builtin_ia32_cmpnlt"; - break; - case 6: - Out << "__builtin_ia32_cmpnle"; - break; - case 7: - Out << "__builtin_ia32_cmpord"; - break; - } - if (ID == Intrinsic::x86_sse_cmp_ps || ID == Intrinsic::x86_sse2_cmp_pd) - Out << 'p'; - else - Out << 's'; - if (ID == Intrinsic::x86_sse_cmp_ss || ID == Intrinsic::x86_sse_cmp_ps) - Out << 's'; - else - Out << 'd'; - - Out << "("; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ", "; - writeOperand(I.getArgOperand(1), ContextCasted); - Out << ")"; - return true; - case Intrinsic::ppc_altivec_lvsl: - Out << '('; - printTypeName(Out, I.getType()); - Out << ')'; - Out << "__builtin_altivec_lvsl(0, (void*)"; - writeOperand(I.getArgOperand(0), ContextCasted); - Out << ")"; - return true; - case Intrinsic::stackprotector: - writeOperandDeref(I.getArgOperand(1)); - Out << " = "; - writeOperand(I.getArgOperand(0), ContextCasted); - return true; - case Intrinsic::uadd_with_overflow: - case Intrinsic::sadd_with_overflow: - case Intrinsic::usub_with_overflow: - case Intrinsic::ssub_with_overflow: - case Intrinsic::umul_with_overflow: - case Intrinsic::smul_with_overflow: - case Intrinsic::bswap: - case Intrinsic::ceil: - case Intrinsic::ctlz: - case Intrinsic::ctpop: - case Intrinsic::cttz: - case Intrinsic::fabs: - case Intrinsic::floor: - case Intrinsic::fma: - case Intrinsic::fmuladd: - case Intrinsic::pow: - case Intrinsic::powi: - case Intrinsic::rint: - case Intrinsic::sqrt: - case Intrinsic::trap: - case Intrinsic::trunc: - return false; // these use the normal function call emission - } + llvm_unreachable(0); + return false; + } + + case Intrinsic::dbg_value: + case Intrinsic::dbg_declare: + return true; // ignore these intrinsics + case Intrinsic::vastart: + Out << "0; "; + + Out << "va_start(*(va_list*)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ", "; + // Output the last argument to the enclosing function. + if (I.getParent()->getParent()->arg_empty()) + Out << "vararg_dummy_arg"; + else + writeOperand(&*(I.getParent()->getParent()->arg_end() - 1)); + Out << ')'; + return true; + case Intrinsic::vaend: + if (!isa<ConstantPointerNull>(I.getArgOperand(0))) { + Out << "0; va_end(*(va_list*)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ')'; + } else { + Out << "va_end(*(va_list*)0)"; + } + return true; + case Intrinsic::vacopy: + Out << "0; "; + Out << "va_copy(*(va_list*)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ", *(va_list*)"; + writeOperand(I.getArgOperand(1), ContextCasted); + Out << ')'; + return true; + case Intrinsic::returnaddress: + Out << "__builtin_return_address("; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ')'; + return true; + case Intrinsic::frameaddress: + Out << "__builtin_frame_address("; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ')'; + return true; + case Intrinsic::setjmp: + Out << "setjmp(*(jmp_buf*)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ')'; + return true; + case Intrinsic::longjmp: + Out << "longjmp(*(jmp_buf*)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ", "; + writeOperand(I.getArgOperand(1), ContextCasted); + Out << ')'; + return true; + case Intrinsic::sigsetjmp: + Out << "sigsetjmp(*(sigjmp_buf*)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ','; + writeOperand(I.getArgOperand(1), ContextCasted); + Out << ')'; + return true; + case Intrinsic::siglongjmp: + Out << "siglongjmp(*(sigjmp_buf*)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ", "; + writeOperand(I.getArgOperand(1), ContextCasted); + Out << ')'; + return true; + case Intrinsic::prefetch: + Out << "LLVM_PREFETCH((const void *)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ", "; + writeOperand(I.getArgOperand(1), ContextCasted); + Out << ", "; + writeOperand(I.getArgOperand(2), ContextCasted); + Out << ")"; + return true; + case Intrinsic::stacksave: + // Emit this as: Val = 0; *((void**)&Val) = __builtin_stack_save() + // to work around GCC bugs (see PR1809). + Out << "0; *((void**)&" << GetValueName(&I) + << ") = __builtin_stack_save()"; + return true; + case Intrinsic::x86_sse_cmp_ss: + case Intrinsic::x86_sse_cmp_ps: + case Intrinsic::x86_sse2_cmp_sd: + case Intrinsic::x86_sse2_cmp_pd: + Out << '('; + printTypeName(Out, I.getType()); + Out << ')'; + // Multiple GCC builtins multiplex onto this intrinsic. + switch (cast<ConstantInt>(I.getArgOperand(2))->getZExtValue()) { + default: llvm_unreachable("Invalid llvm.x86.sse.cmp!"); + case 0: Out << "__builtin_ia32_cmpeq"; break; + case 1: Out << "__builtin_ia32_cmplt"; break; + case 2: Out << "__builtin_ia32_cmple"; break; + case 3: Out << "__builtin_ia32_cmpunord"; break; + case 4: Out << "__builtin_ia32_cmpneq"; break; + case 5: Out << "__builtin_ia32_cmpnlt"; break; + case 6: Out << "__builtin_ia32_cmpnle"; break; + case 7: Out << "__builtin_ia32_cmpord"; break; + } + if (ID == Intrinsic::x86_sse_cmp_ps || ID == Intrinsic::x86_sse2_cmp_pd) + Out << 'p'; + else + Out << 's'; + if (ID == Intrinsic::x86_sse_cmp_ss || ID == Intrinsic::x86_sse_cmp_ps) + Out << 's'; + else + Out << 'd'; + + Out << "("; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ", "; + writeOperand(I.getArgOperand(1), ContextCasted); + Out << ")"; + return true; + case Intrinsic::ppc_altivec_lvsl: + Out << '('; + printTypeName(Out, I.getType()); + Out << ')'; + Out << "__builtin_altivec_lvsl(0, (void*)"; + writeOperand(I.getArgOperand(0), ContextCasted); + Out << ")"; + return true; + case Intrinsic::stackprotector: + writeOperandDeref(I.getArgOperand(1)); + Out << " = "; + writeOperand(I.getArgOperand(0), ContextCasted); + return true; + case Intrinsic::uadd_with_overflow: + case Intrinsic::sadd_with_overflow: + case Intrinsic::usub_with_overflow: + case Intrinsic::ssub_with_overflow: + case Intrinsic::umul_with_overflow: + case Intrinsic::smul_with_overflow: + case Intrinsic::bswap: + case Intrinsic::ceil: + case Intrinsic::ctlz: + case Intrinsic::ctpop: + case Intrinsic::cttz: + case Intrinsic::fabs: + case Intrinsic::floor: + case Intrinsic::fma: + case Intrinsic::fmuladd: + case Intrinsic::pow: + case Intrinsic::powi: + case Intrinsic::rint: + case Intrinsic::sqrt: + case Intrinsic::trap: + case Intrinsic::trunc: + return false; // these use the normal function call emission + } } -// This converts the llvm constraint string to something gcc is expecting. -// TODO: work out platform independent constraints and factor those out +//This converts the llvm constraint string to something gcc is expecting. +//TODO: work out platform independent constraints and factor those out // of the per target tables // handle multiple constraint codes -std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo &c) { - return TargetLowering::AsmOperandInfo(c).ConstraintCode; +std::string CWriter::InterpretASMConstraint(InlineAsm::ConstraintInfo& c) { + return TargetLowering::AsmOperandInfo(c).ConstraintCode; #if 0 - assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle"); - - // Grab the translation table from MCAsmInfo if it exists. - const MCRegisterInfo *MRI; - const MCAsmInfo *TargetAsm; - std::string Triple = TheModule->getTargetTriple(); - if (Triple.empty()) - Triple = llvm::sys::getDefaultTargetTriple(); - - std::string E; - if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) { - MRI = Match->createMCRegInfo(Triple); - TargetAsm = Match->createMCAsmInfo(*MRI, Triple); - } else { - return c.Codes[0]; - } - - const char *const *table = TargetAsm->getAsmCBE(); - - // Search the translation table if it exists. - for (int i = 0; table && table[i]; i += 2) - if (c.Codes[0] == table[i]) { - delete TargetAsm; - delete MRI; - return table[i+1]; - } - - // Default is identity. - delete TargetAsm; - delete MRI; - return c.Codes[0]; + assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle"); + + // Grab the translation table from MCAsmInfo if it exists. + const MCRegisterInfo *MRI; + const MCAsmInfo *TargetAsm; + std::string Triple = TheModule->getTargetTriple(); + if (Triple.empty()) + Triple = llvm::sys::getDefaultTargetTriple(); + + std::string E; + if (const Target *Match = TargetRegistry::lookupTarget(Triple, E)) { + MRI = Match->createMCRegInfo(Triple); + TargetAsm = Match->createMCAsmInfo(*MRI, Triple); + } else { + return c.Codes[0]; + } + + const char *const *table = TargetAsm->getAsmCBE(); + + // Search the translation table if it exists. + for (int i = 0; table && table[i]; i += 2) + if (c.Codes[0] == table[i]) { + delete TargetAsm; + delete MRI; + return table[i+1]; + } + + // Default is identity. + delete TargetAsm; + delete MRI; + return c.Codes[0]; #endif } -// TODO: import logic from AsmPrinter.cpp +//TODO: import logic from AsmPrinter.cpp static std::string gccifyAsm(std::string asmstr) { - for (std::string::size_type i = 0; i != asmstr.size(); ++i) - if (asmstr[i] == '\n') - asmstr.replace(i, 1, "\\n"); - else if (asmstr[i] == '\t') - asmstr.replace(i, 1, "\\t"); - else if (asmstr[i] == '$') { - if (asmstr[i + 1] == '{') { - std::string::size_type a = asmstr.find_first_of(':', i + 1); - std::string::size_type b = asmstr.find_first_of('}', i + 1); - std::string n = "%" + asmstr.substr(a + 1, b - a - 1) + - asmstr.substr(i + 2, a - i - 2); - asmstr.replace(i, b - i + 1, n); - i += n.size() - 1; - } else - asmstr.replace(i, 1, "%"); - } else if (asmstr[i] == '%') // grr - { - asmstr.replace(i, 1, "%%"); - ++i; - } - - return asmstr; + for (std::string::size_type i = 0; i != asmstr.size(); ++i) + if (asmstr[i] == '\n') + asmstr.replace(i, 1, "\\n"); + else if (asmstr[i] == '\t') + asmstr.replace(i, 1, "\\t"); + else if (asmstr[i] == '$') { + if (asmstr[i + 1] == '{') { + std::string::size_type a = asmstr.find_first_of(':', i + 1); + std::string::size_type b = asmstr.find_first_of('}', i + 1); + std::string n = "%" + + asmstr.substr(a + 1, b - a - 1) + + asmstr.substr(i + 2, a - i - 2); + asmstr.replace(i, b - i + 1, n); + i += n.size() - 1; + } else + asmstr.replace(i, 1, "%"); + } + else if (asmstr[i] == '%')//grr + { asmstr.replace(i, 1, "%%"); ++i;} + + return asmstr; } -// TODO: assumptions about what consume arguments from the call are likely wrong +//TODO: assumptions about what consume arguments from the call are likely wrong // handle communitivity void CWriter::visitInlineAsm(CallInst &CI) { - InlineAsm *as = cast<InlineAsm>(CI.getCalledValue()); - InlineAsm::ConstraintInfoVector Constraints = as->ParseConstraints(); - - std::vector<std::pair<Value *, int>> ResultVals; - if (CI.getType() == Type::getVoidTy(CI.getContext())) - ; - else if (StructType *ST = dyn_cast<StructType>(CI.getType())) { - for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) - ResultVals.push_back(std::make_pair(&CI, (int)i)); - } else { - ResultVals.push_back(std::make_pair(&CI, -1)); - } - - // Fix up the asm string for gcc and emit it. - Out << "__asm__ volatile (\"" << gccifyAsm(as->getAsmString()) << "\"\n"; - Out << " :"; - - unsigned ValueCount = 0; - bool IsFirst = true; - - // Convert over all the output constraints. - for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), - E = Constraints.end(); - I != E; ++I) { - - if (I->Type != InlineAsm::isOutput) { - ++ValueCount; - continue; // Ignore non-output constraints. - } - - assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); - std::string C = InterpretASMConstraint(*I); - if (C.empty()) - continue; - - if (!IsFirst) { - Out << ", "; - IsFirst = false; - } - - // Unpack the dest. - Value *DestVal; - int DestValNo = -1; - - if (ValueCount < ResultVals.size()) { - DestVal = ResultVals[ValueCount].first; - DestValNo = ResultVals[ValueCount].second; - } else - DestVal = CI.getArgOperand(ValueCount - ResultVals.size()); - - if (I->isEarlyClobber) - C = "&" + C; - - Out << "\"=" << C << "\"(" << GetValueName(DestVal); - if (DestValNo != -1) - Out << ".field" << DestValNo; // Multiple retvals. - Out << ")"; - ++ValueCount; - } - - // Convert over all the input constraints. - Out << "\n :"; - IsFirst = true; - ValueCount = 0; - for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), - E = Constraints.end(); - I != E; ++I) { - if (I->Type != InlineAsm::isInput) { - ++ValueCount; - continue; // Ignore non-input constraints. - } - - assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); - std::string C = InterpretASMConstraint(*I); - if (C.empty()) - continue; - - if (!IsFirst) { - Out << ", "; - IsFirst = false; - } - - assert(ValueCount >= ResultVals.size() && "Input can't refer to result"); - Value *SrcVal = CI.getArgOperand(ValueCount - ResultVals.size()); - - Out << "\"" << C << "\"("; - if (!I->isIndirect) - writeOperand(SrcVal); - else - writeOperandDeref(SrcVal); - Out << ")"; - } - - // Convert over the clobber constraints. - IsFirst = true; - for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), - E = Constraints.end(); - I != E; ++I) { - if (I->Type != InlineAsm::isClobber) - continue; // Ignore non-input constraints. - - assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); - std::string C = InterpretASMConstraint(*I); - if (C.empty()) - continue; - - if (!IsFirst) { - Out << ", "; - IsFirst = false; - } - - Out << '\"' << C << '"'; - } - - Out << ")"; + InlineAsm* as = cast<InlineAsm>(CI.getCalledValue()); + InlineAsm::ConstraintInfoVector Constraints = as->ParseConstraints(); + + std::vector<std::pair<Value*, int> > ResultVals; + if (CI.getType() == Type::getVoidTy(CI.getContext())) + ; + else if (StructType *ST = dyn_cast<StructType>(CI.getType())) { + for (unsigned i = 0, e = ST->getNumElements(); i != e; ++i) + ResultVals.push_back(std::make_pair(&CI, (int)i)); + } else { + ResultVals.push_back(std::make_pair(&CI, -1)); + } + + // Fix up the asm string for gcc and emit it. + Out << "__asm__ volatile (\"" << gccifyAsm(as->getAsmString()) << "\"\n"; + Out << " :"; + + unsigned ValueCount = 0; + bool IsFirst = true; + + // Convert over all the output constraints. + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + + if (I->Type != InlineAsm::isOutput) { + ++ValueCount; + continue; // Ignore non-output constraints. + } + + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + if (!IsFirst) { + Out << ", "; + IsFirst = false; + } + + // Unpack the dest. + Value *DestVal; + int DestValNo = -1; + + if (ValueCount < ResultVals.size()) { + DestVal = ResultVals[ValueCount].first; + DestValNo = ResultVals[ValueCount].second; + } else + DestVal = CI.getArgOperand(ValueCount-ResultVals.size()); + + if (I->isEarlyClobber) + C = "&"+C; + + Out << "\"=" << C << "\"(" << GetValueName(DestVal); + if (DestValNo != -1) + Out << ".field" << DestValNo; // Multiple retvals. + Out << ")"; + ++ValueCount; + } + + + // Convert over all the input constraints. + Out << "\n :"; + IsFirst = true; + ValueCount = 0; + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + if (I->Type != InlineAsm::isInput) { + ++ValueCount; + continue; // Ignore non-input constraints. + } + + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + if (!IsFirst) { + Out << ", "; + IsFirst = false; + } + + assert(ValueCount >= ResultVals.size() && "Input can't refer to result"); + Value *SrcVal = CI.getArgOperand(ValueCount-ResultVals.size()); + + Out << "\"" << C << "\"("; + if (!I->isIndirect) + writeOperand(SrcVal); + else + writeOperandDeref(SrcVal); + Out << ")"; + } + + // Convert over the clobber constraints. + IsFirst = true; + for (InlineAsm::ConstraintInfoVector::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + if (I->Type != InlineAsm::isClobber) + continue; // Ignore non-input constraints. + + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string C = InterpretASMConstraint(*I); + if (C.empty()) continue; + + if (!IsFirst) { + Out << ", "; + IsFirst = false; + } + + Out << '\"' << C << '"'; + } + + Out << ")"; } void CWriter::visitAllocaInst(AllocaInst &I) { - Out << '('; - printTypeName(Out, I.getType()); - Out << ") alloca(sizeof("; - printTypeName(Out, I.getType()->getElementType()); - if (I.isArrayAllocation()) { - Out << ") * ("; - writeOperand(I.getArraySize(), ContextCasted); - } - Out << "))"; + Out << '('; + printTypeName(Out, I.getType()); + Out << ") alloca(sizeof("; + printTypeName(Out, I.getType()->getElementType()); + if (I.isArrayAllocation()) { + Out << ") * (" ; + writeOperand(I.getArraySize(), ContextCasted); + } + Out << "))"; } void CWriter::printGEPExpression(Value *Ptr, gep_type_iterator I, - gep_type_iterator E, bool isArrayType, - GetElementPtrInst *GEPI) { - // DEBUG(errs() << "Printing GEP\n"); - // DEBUG(errs() << "\tPtr: " << *Ptr << "\n"); - // DEBUG(errs() << "\tGEPI: " << *GEPI <<"\n"); - // If there are no indices, just print out the pointer. - if (I == E) { - // DEBUG(errs() << "I==E: Calling writeOperand()\n"); - writeOperand(Ptr); - return; - } - - // Find out if the last index is into a vector. If so, we have to print this - // specially. Since vectors can't have elements of indexable type, only the - // last index could possibly be of a vector element. - VectorType *LastIndexIsVector = 0; - { - for (gep_type_iterator TmpI = I; TmpI != E; ++TmpI) - // LastIndexIsVector = dyn_cast<VectorType>(TmpI.getCurTy()); - // CHECK: This change needs thorough testing - LastIndexIsVector = dyn_cast<VectorType>(TmpI.getIndexedType()); - } - Out << "("; - - // If the last index is into a vector, we can't print it as &a[i][j] because - // we can't index into a vector with j in GCC. Instead, emit this as - // (((float*)&a[i])+j) - // TODO: this is no longer true now that we don't represent vectors using - // gcc-extentions - if (LastIndexIsVector) { - // DEBUG(errs() << "LastIndexIsVector\n"); - Out << "(("; - printTypeName(Out, - PointerType::getUnqual(LastIndexIsVector->getElementType())); - Out << ")("; - } - bool isArrayAccess = false; - - if (GEPStack.size() > 0 && GEPStack.top() == GEPI) { - // DEBUG(errs() << "Processing load-specific GEP\n"); - GEPStack.pop(); - isArrayAccess = true; - } else { - // DEBUG(errs() << "I'm hereee!\n"); - Out << '&'; - } - // DEBUG(errs() << "Here!\n"); - // If the first index is 0 (very typical) we can do a number of - // simplifications to clean up the code. - Value *FirstOp = I.getOperand(); - // DEBUG(errs() << "FirstOp: " << *(I.getOperand()) << "\n"); - if (!isa<Constant>(FirstOp) || !cast<Constant>(FirstOp)->isNullValue()) { - // DEBUG(errs() << "Calling writeoperand()\n"); - // First index isn't simple, print it the hard way. - writeOperand(Ptr, ContextNormal, isArrayAccess); - } else { - ++I; // Skip the zero index. - // DEBUG(errs() << "Skipping zero index\n"); - - // Okay, emit the first operand. If Ptr is something that is already address - // exposed, like a global, avoid emitting (&foo)[0], just emit foo instead. - if (isAddressExposed(Ptr)) { - // DEBUG(errs() << "Address exposed; calling writeoperandinternal()\n"); - writeOperandInternal(Ptr); - } - // else if (I != E && (I.getCurTy())->isStructTy()) { - // NOTE: This change needs to be tested more - else if (I != E && (I.isStruct())) { - // DEBUG(errs() << "Not address exposed; is struct type\n"); - // If we didn't already emit the first operand, see if we can print it as - // P->f instead of "P[0].f" - writeOperand(Ptr); - Out << "->field" << cast<ConstantInt>(I.getOperand())->getZExtValue(); - ++I; // eat the struct index as well. - } else { - // DEBUG(errs() << "In else; emitting *P\n"); - // Instead of emitting P[0][1], emit (*P)[1], which is more idiomatic. - Out << "(*"; - writeOperand(Ptr); - Out << ")"; - } - } - - Type *Agg = GEPI->getSourceElementType(); - unsigned CurIdx = 1; - for (; I != E; ++CurIdx, ++I) { - assert(I.getOperand() - ->getType() - ->isIntegerTy()); // TODO: indexing a Vector with a Vector is - // valid, but we don't support it here - // DEBUG(errs() << "Type: " << *Agg << "; operand: " << *(I.getOperand()) << - // "\n"); - if ((Agg->isStructTy())) { - // DEBUG(errs() << "Found a struct\n"); - Out << ".field" << cast<ConstantInt>(I.getOperand())->getZExtValue(); - } else if (Agg->isArrayTy()) { - // DEBUG(errs() << "Found an array!\n"); - Out << ".array["; - writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); - Out << ']'; - } else if (!Agg->isVectorTy()) { - // DEBUG(errs() << "Not a vector!\n"); - Out << '['; - writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); - Out << ']'; - } else { - // DEBUG(errs() << "In else!\n"); - // If the last index is into a vector, then print it out as "+j)". This - // works with the 'LastIndexIsVector' code above. - if (isa<Constant>(I.getOperand()) && - cast<Constant>(I.getOperand())->isNullValue()) { - Out << "))"; // avoid "+0". - } else { - Out << ")+("; - writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); - Out << "))"; - } - } - CompositeType *CT = dyn_cast<CompositeType>(Agg); - if (!CT || CT->isPointerTy()) { - // DEBUG(errs() << "Something wrong!!\n"); - break; - } - Value *Index = GEPI->getOperand(CurIdx); - if (!CT->indexValid(Index)) - if (!CT || CT->isPointerTy()) { - // DEBUG(errs() << "Something wrong 2!!\n"); - break; - } - Agg = CT->getTypeAtIndex(Index); - } - Out << ")"; - // DEBUG(errs() << "Leaving printGEPExpression\n"); -} - -void CWriter::writeMemoryAccess(Value *Operand, Type *OperandType, - bool IsVolatile, unsigned Alignment /*bytes*/) { - // DEBUG(errs() << *OperandType << "; " << *Operand << "\n"); - bool arrayAccess = false; - if (isa<GetElementPtrInst>(Operand)) { - // DEBUG(errs() << "ISA Get Element Pointer!\n"); - arrayAccess = true; - GEPStack.push(dyn_cast<GetElementPtrInst>(Operand)); - } - // if (isAddressExposed(Operand)) { - // DEBUG(errs() << "Is address exposed!!\n"); - // writeOperandInternal(Operand); - // return; - // } - - bool IsUnaligned = - Alignment && Alignment < TD->getABITypeAlignment(OperandType); - if (!arrayAccess) { - if (!IsUnaligned) - Out << '*'; - - else if (IsUnaligned) { - Out << "__UNALIGNED_LOAD__("; - printTypeNameUnaligned(Out, OperandType, false); - if (IsVolatile) - Out << " volatile"; - Out << ", " << Alignment << ", "; - } - - else if (IsVolatile) { - Out << "("; - printTypeName(Out, OperandType, false); - Out << "volatile"; - Out << "*)"; - } - } - - writeOperand(Operand, ContextNormal, arrayAccess); - - if (IsUnaligned) { - Out << ")"; - } -} - -void CWriter::visitLoadInst(LoadInst &I) { - // DEBUG(errs() << "Visiting Load instruction!\n"); - // DEBUG(errs() << "Visiting load: " << I << "\n"); - writeMemoryAccess(I.getOperand(0), I.getType(), I.isVolatile(), - I.getAlignment()); -} - -void CWriter::visitStoreInst(StoreInst &I) { - // DEBUG(errs() << "Visiting store instruction!\n"); - writeMemoryAccess(I.getPointerOperand(), I.getOperand(0)->getType(), - I.isVolatile(), I.getAlignment()); - Out << " = "; - Value *Operand = I.getOperand(0); - unsigned BitMask = 0; - if (IntegerType *ITy = dyn_cast<IntegerType>(Operand->getType())) - if (!ITy->isPowerOf2ByteWidth()) - // We have a bit width that doesn't match an even power-of-2 byte - // size. Consequently we must & the value with the type's bit mask - BitMask = ITy->getBitMask(); - if (BitMask) - Out << "(("; - writeOperand(Operand, BitMask ? ContextNormal : ContextCasted); - if (BitMask) - Out << ") & " << BitMask << ")"; -} - -void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) { - // DEBUG(errs() <<"Visiting GEP: " << I << "\n"); - printGEPExpression(I.getPointerOperand(), gep_type_begin(I), gep_type_end(I), - I.getSourceElementType()->isArrayTy(), &I); -} - -void CWriter::visitVAArgInst(VAArgInst &I) { - Out << "va_arg(*(va_list*)"; - writeOperand(I.getOperand(0), ContextCasted); - Out << ", "; - printTypeName(Out, I.getType()); - Out << ");\n "; -} - -void CWriter::visitInsertElementInst(InsertElementInst &I) { - // Start by copying the entire aggregate value into the result variable. - writeOperand(I.getOperand(0)); - Type *EltTy = I.getType()->getElementType(); - assert(I.getOperand(1)->getType() == EltTy); - if (isEmptyType(EltTy)) - return; - - // Then do the insert to update the field. - Out << ";\n "; - Out << GetValueName(&I) << ".vector["; - writeOperand(I.getOperand(2)); - Out << "] = "; - writeOperand(I.getOperand(1), ContextCasted); -} - -void CWriter::visitExtractElementInst(ExtractElementInst &I) { - assert(!isEmptyType(I.getType())); - if (isa<UndefValue>(I.getOperand(0))) { - Out << "("; - printTypeName(Out, I.getType()); - Out << ") 0/*UNDEF*/"; - } else { - Out << "("; - writeOperand(I.getOperand(0)); - Out << ").vector["; - writeOperand(I.getOperand(1)); - Out << "]"; - } -} - -// <result> = shufflevector <n x <ty>> <v1>, <n x <ty>> <v2>, <m x i32> <mask> -// ; yields <m x <ty>> -void CWriter::visitShuffleVectorInst(ShuffleVectorInst &SVI) { - VectorType *VT = SVI.getType(); - Type *EltTy = VT->getElementType(); - VectorType *InputVT = cast<VectorType>(SVI.getOperand(0)->getType()); - assert(!isEmptyType(VT)); - assert(InputVT->getElementType() == VT->getElementType()); - - CtorDeclTypes.insert(VT); - Out << "llvm_ctor_"; - printTypeString(Out, VT, false); - Out << "("; - - Constant *Zero = Constant::getNullValue(EltTy); - unsigned NumElts = VT->getNumElements(); - unsigned NumInputElts = InputVT->getNumElements(); // n - for (unsigned i = 0; i != NumElts; ++i) { - if (i) - Out << ", "; - int SrcVal = SVI.getMaskValue(i); - if ((unsigned)SrcVal >= NumInputElts * 2) { - Out << "/*undef*/"; - printConstant(Zero, ContextCasted); - } else { - // If SrcVal belongs [0, n - 1], it extracts value from <v1> - // If SrcVal belongs [n, 2 * n - 1], it extracts value from <v2> - // In C++, the value false is converted to zero and the value true is - // converted to one - Value *Op = SVI.getOperand((unsigned)SrcVal >= NumInputElts); - if (isa<Instruction>(Op)) { - // Do an extractelement of this value from the appropriate input. - Out << "("; - writeOperand(Op); - Out << ").vector["; - Out << ((unsigned)SrcVal >= NumInputElts ? SrcVal - NumInputElts - : SrcVal); - Out << "]"; - } else if (isa<ConstantAggregateZero>(Op) || isa<UndefValue>(Op)) { - printConstant(Zero, ContextCasted); - } else { - printConstant( - cast<ConstantVector>(Op)->getOperand(SrcVal & (NumElts - 1)), - ContextNormal); - } - } - } - Out << ")"; -} - -void CWriter::visitInsertValueInst(InsertValueInst &IVI) { - // Start by copying the entire aggregate value into the result variable. - writeOperand(IVI.getOperand(0)); - Type *EltTy = IVI.getOperand(1)->getType(); - if (isEmptyType(EltTy)) - return; - - // Then do the insert to update the field. - Out << ";\n "; - Out << GetValueName(&IVI); - for (const unsigned *b = IVI.idx_begin(), *i = b, *e = IVI.idx_end(); i != e; - ++i) { - Type *IndexedTy = ExtractValueInst::getIndexedType( - IVI.getOperand(0)->getType(), makeArrayRef(b, i)); - assert(IndexedTy); - if (IndexedTy->isArrayTy()) - Out << ".array[" << *i << "]"; - else - Out << ".field" << *i; - } - Out << " = "; - writeOperand(IVI.getOperand(1), ContextCasted); -} - -void CWriter::visitExtractValueInst(ExtractValueInst &EVI) { - Out << "("; - if (isa<UndefValue>(EVI.getOperand(0))) { - Out << "("; - printTypeName(Out, EVI.getType()); - Out << ") 0/*UNDEF*/"; - } else { - writeOperand(EVI.getOperand(0)); - for (const unsigned *b = EVI.idx_begin(), *i = b, *e = EVI.idx_end(); - i != e; ++i) { - Type *IndexedTy = ExtractValueInst::getIndexedType( - EVI.getOperand(0)->getType(), makeArrayRef(b, i)); - if (IndexedTy->isArrayTy()) - Out << ".array[" << *i << "]"; - else - Out << ".field" << *i; - } - } - Out << ")"; -} - -//===----------------------------------------------------------------------===// -// External Interface declaration -//===----------------------------------------------------------------------===// - -bool CTargetMachine::addPassesToEmitFile( - PassManagerBase &PM, raw_pwrite_stream &Out, raw_pwrite_stream *Out2, - CodeGenFileType FileType, bool DisableVerify, MachineModuleInfo *MMI) { - - if (FileType != TargetMachine::CGFT_AssemblyFile) - return true; - - PM.add(createGCLoweringPass()); - PM.add(createLowerInvokePass()); - PM.add(createCFGSimplificationPass()); // clean up after lower invoke. - PM.add(new CWriter(Out)); - return false; -} + gep_type_iterator E, bool isArrayType, GetElementPtrInst *GEPI) { + DEBUG(errs() << "Printing GEP\n"); + DEBUG(errs() << "\tPtr: " << *Ptr << "\n"); + DEBUG(errs() << "\tGEPI: " << *GEPI <<"\n"); + // If there are no indices, just print out the pointer. + if (I == E) { + DEBUG(errs() << "I==E: Calling writeOperand()\n"); + writeOperand(Ptr); + return; + } + + // Find out if the last index is into a vector. If so, we have to print this + // specially. Since vectors can't have elements of indexable type, only the + // last index could possibly be of a vector element. + VectorType *LastIndexIsVector = 0; + { + for (gep_type_iterator TmpI = I; TmpI != E; ++TmpI) + //LastIndexIsVector = dyn_cast<VectorType>(TmpI.getCurTy()); + // CHECK: This change needs thorough testing + LastIndexIsVector = dyn_cast<VectorType>(TmpI.getIndexedType()); + } + Out << "("; + + // If the last index is into a vector, we can't print it as &a[i][j] because + // we can't index into a vector with j in GCC. Instead, emit this as + // (((float*)&a[i])+j) + // TODO: this is no longer true now that we don't represent vectors using gcc-extentions + if (LastIndexIsVector) { + DEBUG(errs() << "LastIndexIsVector\n"); + Out << "(("; + printTypeName(Out, PointerType::getUnqual(LastIndexIsVector->getElementType())); + Out << ")("; + } + bool isArrayAccess = false; + + if (GEPStack.size() > 0 && GEPStack.top() == GEPI) { + DEBUG(errs() << "Processing load-specific GEP\n"); + GEPStack.pop(); + isArrayAccess = true; + } else { + DEBUG(errs() << "I'm hereee!\n"); + Out << '&'; + } + DEBUG(errs() << "Here!\n"); + // If the first index is 0 (very typical) we can do a number of + // simplifications to clean up the code. + Value *FirstOp = I.getOperand(); + DEBUG(errs() << "FirstOp: " << *(I.getOperand()) << "\n"); + if (!isa<Constant>(FirstOp) || !cast<Constant>(FirstOp)->isNullValue()) { + DEBUG(errs() << "Calling writeoperand()\n"); + // First index isn't simple, print it the hard way. + writeOperand(Ptr, ContextNormal, isArrayAccess); + } else { + ++I; // Skip the zero index. + DEBUG(errs() << "Skipping zero index\n"); + + // Okay, emit the first operand. If Ptr is something that is already address + // exposed, like a global, avoid emitting (&foo)[0], just emit foo instead. + if (isAddressExposed(Ptr)) { + DEBUG(errs() << "Address exposed; calling writeoperandinternal()\n"); + writeOperandInternal(Ptr); + } + //else if (I != E && (I.getCurTy())->isStructTy()) { + // NOTE: This change needs to be tested more + else if (I != E && (I.isStruct()) ) { + DEBUG(errs() << "Not address exposed; is struct type\n"); + // If we didn't already emit the first operand, see if we can print it as + // P->f instead of "P[0].f" + writeOperand(Ptr); + Out << "->field" << cast<ConstantInt>(I.getOperand())->getZExtValue(); + ++I; // eat the struct index as well. + } else { + DEBUG(errs() << "In else; emitting *P\n"); + // Instead of emitting P[0][1], emit (*P)[1], which is more idiomatic. + Out << "(*"; + writeOperand(Ptr); + Out << ")"; + } + } + + Type *Agg = GEPI->getSourceElementType(); + unsigned CurIdx = 1; + for (; I != E; ++CurIdx, ++I) { + assert(I.getOperand()->getType()->isIntegerTy()); // TODO: indexing a Vector with a Vector is valid, but we don't support it here + DEBUG(errs() << "Type: " << *Agg << "; operand: " << *(I.getOperand()) << "\n"); + if ((Agg->isStructTy())){ + DEBUG(errs() << "Found a struct\n"); + Out << ".field" << cast<ConstantInt>(I.getOperand())->getZExtValue(); + } else if (Agg->isArrayTy()) { + DEBUG(errs() << "Found an array!\n"); + Out << ".array["; + writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); + Out << ']'; + } else if (!Agg->isVectorTy()) { + DEBUG(errs() << "Not a vector!\n"); + Out << '['; + writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); + Out << ']'; + } else { + DEBUG(errs() << "In else!\n"); + // If the last index is into a vector, then print it out as "+j)". This + // works with the 'LastIndexIsVector' code above. + if (isa<Constant>(I.getOperand()) && + cast<Constant>(I.getOperand())->isNullValue()) { + Out << "))"; // avoid "+0". + } else { + Out << ")+("; + writeOperandWithCast(I.getOperand(), Instruction::GetElementPtr); + Out << "))"; + } + } + CompositeType *CT = dyn_cast<CompositeType>(Agg); + if (!CT || CT->isPointerTy()) + { + DEBUG(errs() << "Something wrong!!\n"); + break; + } + Value* Index = GEPI->getOperand(CurIdx); + if (!CT->indexValid(Index)) + if (!CT || CT->isPointerTy()) + { + DEBUG(errs() << "Something wrong 2!!\n"); + break; + } + Agg = CT->getTypeAtIndex(Index); + } + Out << ")"; + DEBUG(errs() << "Leaving printGEPExpression\n"); + } + + void CWriter::writeMemoryAccess(Value *Operand, Type *OperandType, + bool IsVolatile, unsigned Alignment /*bytes*/) { + DEBUG(errs() << *OperandType << "; " << *Operand << "\n"); + bool arrayAccess = false; + if(isa<GetElementPtrInst>(Operand)) { + DEBUG(errs() << "ISA Get Element Pointer!\n"); + arrayAccess = true; + GEPStack.push(dyn_cast<GetElementPtrInst>(Operand)); + } + // if (isAddressExposed(Operand)) { + // DEBUG(errs() << "Is address exposed!!\n"); + // writeOperandInternal(Operand); + // return; + // } + + bool IsUnaligned = Alignment && + Alignment < TD->getABITypeAlignment(OperandType); + if (!arrayAccess) { + if (!IsUnaligned) + Out << '*'; + + else if (IsUnaligned) { + Out << "__UNALIGNED_LOAD__("; + printTypeNameUnaligned(Out, OperandType, false); + if (IsVolatile) Out << " volatile"; + Out << ", " << Alignment << ", "; + } + + else if (IsVolatile) { + Out << "("; + printTypeName(Out, OperandType, false); + Out << "volatile"; + Out << "*)"; + } + } + + writeOperand(Operand,ContextNormal, arrayAccess ); + + if (IsUnaligned) { + Out << ")"; + } + } + + void CWriter::visitLoadInst(LoadInst &I) { + DEBUG(errs() << "Visiting Load instruction!\n"); + DEBUG(errs() << "Visiting load: " << I << "\n"); + writeMemoryAccess(I.getOperand(0), I.getType(), I.isVolatile(), + I.getAlignment()); + + } + + void CWriter::visitStoreInst(StoreInst &I) { + DEBUG(errs() << "Visiting store instruction!\n"); + writeMemoryAccess(I.getPointerOperand(), I.getOperand(0)->getType(), + I.isVolatile(), I.getAlignment()); + Out << " = "; + Value *Operand = I.getOperand(0); + unsigned BitMask = 0; + if (IntegerType* ITy = dyn_cast<IntegerType>(Operand->getType())) + if (!ITy->isPowerOf2ByteWidth()) + // We have a bit width that doesn't match an even power-of-2 byte + // size. Consequently we must & the value with the type's bit mask + BitMask = ITy->getBitMask(); + if (BitMask) + Out << "(("; + writeOperand(Operand, BitMask ? ContextNormal : ContextCasted); + if (BitMask) + Out << ") & " << BitMask << ")"; + } + + void CWriter::visitGetElementPtrInst(GetElementPtrInst &I) { + DEBUG(errs() <<"Visiting GEP: " << I << "\n"); + printGEPExpression(I.getPointerOperand(), gep_type_begin(I), + gep_type_end(I), I.getSourceElementType()->isArrayTy(), &I); + } + + void CWriter::visitVAArgInst(VAArgInst &I) { + Out << "va_arg(*(va_list*)"; + writeOperand(I.getOperand(0), ContextCasted); + Out << ", "; + printTypeName(Out, I.getType()); + Out << ");\n "; + } + + void CWriter::visitInsertElementInst(InsertElementInst &I) { + // Start by copying the entire aggregate value into the result variable. + writeOperand(I.getOperand(0)); + Type *EltTy = I.getType()->getElementType(); + assert(I.getOperand(1)->getType() == EltTy); + if (isEmptyType(EltTy)) return; + + // Then do the insert to update the field. + Out << ";\n "; + Out << GetValueName(&I) << ".vector["; + writeOperand(I.getOperand(2)); + Out << "] = "; + writeOperand(I.getOperand(1), ContextCasted); + } + + void CWriter::visitExtractElementInst(ExtractElementInst &I) { + assert(!isEmptyType(I.getType())); + if (isa<UndefValue>(I.getOperand(0))) { + Out << "("; + printTypeName(Out, I.getType()); + Out << ") 0/*UNDEF*/"; + } else { + Out << "("; + writeOperand(I.getOperand(0)); + Out << ").vector["; + writeOperand(I.getOperand(1)); + Out << "]"; + } + } + + // <result> = shufflevector <n x <ty>> <v1>, <n x <ty>> <v2>, <m x i32> <mask> + // ; yields <m x <ty>> + void CWriter::visitShuffleVectorInst(ShuffleVectorInst &SVI) { + VectorType *VT = SVI.getType(); + Type *EltTy = VT->getElementType(); + VectorType *InputVT = cast<VectorType>(SVI.getOperand(0)->getType()); + assert(!isEmptyType(VT)); + assert(InputVT->getElementType() == VT->getElementType()); + + CtorDeclTypes.insert(VT); + Out << "llvm_ctor_"; + printTypeString(Out, VT, false); + Out << "("; + + Constant *Zero = Constant::getNullValue(EltTy); + unsigned NumElts = VT->getNumElements(); + unsigned NumInputElts = InputVT->getNumElements(); // n + for (unsigned i = 0; i != NumElts; ++i) { + if (i) Out << ", "; + int SrcVal = SVI.getMaskValue(i); + if ((unsigned)SrcVal >= NumInputElts * 2) { + Out << "/*undef*/"; + printConstant(Zero, ContextCasted); + } else { + // If SrcVal belongs [0, n - 1], it extracts value from <v1> + // If SrcVal belongs [n, 2 * n - 1], it extracts value from <v2> + // In C++, the value false is converted to zero and the value true is + // converted to one + Value *Op = SVI.getOperand((unsigned)SrcVal >= NumInputElts); + if (isa<Instruction>(Op)) { + // Do an extractelement of this value from the appropriate input. + Out << "("; + writeOperand(Op); + Out << ").vector["; + Out << ((unsigned)SrcVal >= NumInputElts ? SrcVal - NumInputElts : SrcVal); + Out << "]"; + } else if (isa<ConstantAggregateZero>(Op) || isa<UndefValue>(Op)) { + printConstant(Zero, ContextCasted); + } else { + printConstant(cast<ConstantVector>(Op)->getOperand(SrcVal & + (NumElts-1)), + ContextNormal); + } + } + } + Out << ")"; + } + + void CWriter::visitInsertValueInst(InsertValueInst &IVI) { + // Start by copying the entire aggregate value into the result variable. + writeOperand(IVI.getOperand(0)); + Type *EltTy = IVI.getOperand(1)->getType(); + if (isEmptyType(EltTy)) return; + + // Then do the insert to update the field. + Out << ";\n "; + Out << GetValueName(&IVI); + for (const unsigned *b = IVI.idx_begin(), *i = b, *e = IVI.idx_end(); + i != e; ++i) { + Type *IndexedTy = + ExtractValueInst::getIndexedType(IVI.getOperand(0)->getType(), + makeArrayRef(b, i)); + assert(IndexedTy); + if (IndexedTy->isArrayTy()) + Out << ".array[" << *i << "]"; + else + Out << ".field" << *i; + } + Out << " = "; + writeOperand(IVI.getOperand(1), ContextCasted); + } + + void CWriter::visitExtractValueInst(ExtractValueInst &EVI) { + Out << "("; + if (isa<UndefValue>(EVI.getOperand(0))) { + Out << "("; + printTypeName(Out, EVI.getType()); + Out << ") 0/*UNDEF*/"; + } else { + writeOperand(EVI.getOperand(0)); + for (const unsigned *b = EVI.idx_begin(), *i = b, *e = EVI.idx_end(); + i != e; ++i) { + Type *IndexedTy = + ExtractValueInst::getIndexedType(EVI.getOperand(0)->getType(), + makeArrayRef(b, i)); + if (IndexedTy->isArrayTy()) + Out << ".array[" << *i << "]"; + else + Out << ".field" << *i; + } + } + Out << ")"; + } + + //===----------------------------------------------------------------------===// + // External Interface declaration + //===----------------------------------------------------------------------===// + + bool CTargetMachine::addPassesToEmitFile(PassManagerBase &PM, + raw_pwrite_stream &Out, + raw_pwrite_stream *Out2, + CodeGenFileType FileType, + bool DisableVerify, + MachineModuleInfo *MMI){ + + if (FileType != TargetMachine::CGFT_AssemblyFile) return true; + + PM.add(createGCLoweringPass()); + PM.add(createLowerInvokePass()); + PM.add(createCFGSimplificationPass()); // clean up after lower invoke. + PM.add(new CWriter(Out)); + return false; + } diff --git a/hpvm/test/hpvm-cava/Makefile.config b/hpvm/test/hpvm-cava/Makefile.config new file mode 100644 index 0000000000000000000000000000000000000000..ffb2942911313421ce9b9186a392578d7bcaf4c7 --- /dev/null +++ b/hpvm/test/hpvm-cava/Makefile.config @@ -0,0 +1,27 @@ +CUDA_PATH=/software/cuda-9.1 +CUDA_LIB_PATH=$(CUDA_PATH)/lib64 +OPENCL_PATH=/software/cuda-9.1 +OPENCL_LIB_PATH=$(OPENCL_PATH)/lib64 + +LLVM_SRC_ROOT=/home/aejjeh/work_dir/hpvm-release/hpvm/llvm/ +# NOTE: You may need to configure this based on your root path. +VISC_SRC_ROOT=$(LLVM_SRC_ROOT) + +VISC_BUILD_DIR =$(VISC_SRC_ROOT)/../build +CC = $(VISC_BUILD_DIR)/bin/clang +PLATFORM_CFLAGS = -I$(LLVM_SRC_ROOT)/include -I../include -I$(VISC_BUILD_DIR)/include +OCLBE = $(VISC_BUILD_DIR)/bin/llvm-cbe + +CXX = $(VISC_BUILD_DIR)/bin/clang++ +PLATFORM_CXXFLAGS = -I$(LLVM_SRC_ROOT)/include -I../include -I$(VISC_BUILD_DIR)/include + +LINKER = $(VISC_BUILD_DIR)/bin/clang++ +PLATFORM_LDFLAGS = -lm -lpthread -lrt -lOpenCL -L$(OPENCL_LIB_PATH) + +LLVM_LIB_PATH = $(VISC_BUILD_DIR)/lib +LLVM_BIN_PATH = $(VISC_BUILD_DIR)/bin + +OPT = $(LLVM_BIN_PATH)/opt +LLVM_LINK = $(LLVM_BIN_PATH)/llvm-link +LLVM_AS = $(LLVM_BIN_PATH)/llvm-as +LIT = $(LLVM_BIN_PATH)/llvm-lit \ No newline at end of file diff --git a/hpvm/test/pipeline/Makefile.config b/hpvm/test/pipeline/Makefile.config new file mode 100644 index 0000000000000000000000000000000000000000..ffb2942911313421ce9b9186a392578d7bcaf4c7 --- /dev/null +++ b/hpvm/test/pipeline/Makefile.config @@ -0,0 +1,27 @@ +CUDA_PATH=/software/cuda-9.1 +CUDA_LIB_PATH=$(CUDA_PATH)/lib64 +OPENCL_PATH=/software/cuda-9.1 +OPENCL_LIB_PATH=$(OPENCL_PATH)/lib64 + +LLVM_SRC_ROOT=/home/aejjeh/work_dir/hpvm-release/hpvm/llvm/ +# NOTE: You may need to configure this based on your root path. +VISC_SRC_ROOT=$(LLVM_SRC_ROOT) + +VISC_BUILD_DIR =$(VISC_SRC_ROOT)/../build +CC = $(VISC_BUILD_DIR)/bin/clang +PLATFORM_CFLAGS = -I$(LLVM_SRC_ROOT)/include -I../include -I$(VISC_BUILD_DIR)/include +OCLBE = $(VISC_BUILD_DIR)/bin/llvm-cbe + +CXX = $(VISC_BUILD_DIR)/bin/clang++ +PLATFORM_CXXFLAGS = -I$(LLVM_SRC_ROOT)/include -I../include -I$(VISC_BUILD_DIR)/include + +LINKER = $(VISC_BUILD_DIR)/bin/clang++ +PLATFORM_LDFLAGS = -lm -lpthread -lrt -lOpenCL -L$(OPENCL_LIB_PATH) + +LLVM_LIB_PATH = $(VISC_BUILD_DIR)/lib +LLVM_BIN_PATH = $(VISC_BUILD_DIR)/bin + +OPT = $(LLVM_BIN_PATH)/opt +LLVM_LINK = $(LLVM_BIN_PATH)/llvm-link +LLVM_AS = $(LLVM_BIN_PATH)/llvm-as +LIT = $(LLVM_BIN_PATH)/llvm-lit \ No newline at end of file diff --git a/hpvm/test/pipeline/datasets/formula1_scaled.mp4 b/hpvm/test/pipeline/datasets/formula1_scaled.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..1e0e3979fe0f1d2ca299313a1f404beeee6f9f3f Binary files /dev/null and b/hpvm/test/pipeline/datasets/formula1_scaled.mp4 differ