X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FTarget%2FCBackend%2FWriter.cpp;h=7c0d433676d101461e7b02edd48cef71aa68d3a8;hb=f5da13367f88f06e3b585dc2263ab6e9ca6c4bf8;hp=6bc3c504344dbcc356d04732706a10bccec86d9b;hpb=36c975c023add62efe1d6cd217d2a02ab01b1034;p=oota-llvm.git diff --git a/lib/Target/CBackend/Writer.cpp b/lib/Target/CBackend/Writer.cpp index 6bc3c504344..7c0d433676d 100644 --- a/lib/Target/CBackend/Writer.cpp +++ b/lib/Target/CBackend/Writer.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "CTargetMachine.h" +#include "llvm/CallingConv.h" #include "llvm/Constants.h" #include "llvm/DerivedTypes.h" #include "llvm/Module.h" @@ -21,12 +22,15 @@ #include "llvm/PassManager.h" #include "llvm/SymbolTable.h" #include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/InlineAsm.h" #include "llvm/Analysis/ConstantsScanner.h" #include "llvm/Analysis/FindUsedTypes.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/CodeGen/IntrinsicLowering.h" #include "llvm/Transforms/Scalar.h" #include "llvm/Target/TargetMachineRegistry.h" +#include "llvm/Target/TargetAsmInfo.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/CFG.h" #include "llvm/Support/GetElementPtrTypeIterator.h" @@ -38,18 +42,18 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Config/config.h" #include -#include -#include +#include using namespace llvm; namespace { // Register the target. RegisterTarget X("c", " C backend"); - /// NameAllUsedStructs - This pass inserts names for any unnamed structure - /// types that are used by the program. + /// CBackendNameAllUsedStructsAndMergeFunctions - This pass inserts names for + /// any unnamed structure types that are used by the program, and merges + /// external functions with the same name. /// - class CBackendNameAllUsedStructs : public ModulePass { + class CBackendNameAllUsedStructsAndMergeFunctions : public ModulePass { void getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); } @@ -65,15 +69,16 @@ namespace { /// module to a C translation unit. class CWriter : public FunctionPass, public InstVisitor { std::ostream &Out; - IntrinsicLowering &IL; + IntrinsicLowering IL; Mangler *Mang; LoopInfo *LI; const Module *TheModule; + const TargetAsmInfo* TAsm; std::map TypeNames; std::map FPConstantMap; public: - CWriter(std::ostream &o, IntrinsicLowering &il) : Out(o), IL(il) {} + CWriter(std::ostream &o) : Out(o), TAsm(0) {} virtual const char *getPassName() const { return "C backend"; } @@ -112,13 +117,20 @@ namespace { const std::string &VariableName = "", bool IgnoreName = false); + void printStructReturnPointerFunctionType(std::ostream &Out, + const PointerType *Ty); + void writeOperand(Value *Operand); + void writeOperandRaw(Value *Operand); void writeOperandInternal(Value *Operand); + void writeOperandWithCast(Value* Operand, unsigned Opcode); + bool writeInstructionCast(const Instruction &I); private : + std::string InterpretASMConstraint(InlineAsm::ConstraintInfo& c); + void lowerIntrinsics(Function &F); - bool nameAllUsedStructureTypes(Module &M); void printModule(Module *M); void printModuleTypes(const SymbolTable &ST); void printContainedStructs(const Type *Ty, std::set &); @@ -129,8 +141,12 @@ namespace { void printBasicBlock(BasicBlock *BB); void printLoop(Loop *L); + void printCast(unsigned opcode, const Type *SrcTy, const Type *DstTy); void printConstant(Constant *CPV); + void printConstantWithCast(Constant *CPV, unsigned Opcode); + bool printConstExprCast(const ConstantExpr *CE); void printConstantArray(ConstantArray *CPA); + void printConstantPacked(ConstantPacked *CP); // isInlinableInst - Attempt to inline instructions into their uses to build // trees as much as possible. To do this, we have to consistently decide @@ -150,6 +166,9 @@ namespace { // Don't inline a load across a store or other bad things! return false; + // Must not be used in inline asm + if (I.hasOneUse() && isInlineAsm(*I.use_back())) return false; + // Only inline instruction it it's use is in the same BB as the inst. return I.getParent() == cast(I.use_back())->getParent(); } @@ -167,7 +186,14 @@ namespace { return 0; return AI; } - + + // isInlineAsm - Check if the instruction is a call to an inline asm chunk + static bool isInlineAsm(const Instruction& I) { + if (isa(&I) && isa(I.getOperand(0))) + return true; + return false; + } + // Instruction visitation functions friend class InstVisitor; @@ -189,6 +215,7 @@ namespace { void visitCastInst (CastInst &I); void visitSelectInst(SelectInst &I); void visitCallInst (CallInst &I); + void visitInlineAsm(CallInst &I); void visitShiftInst(ShiftInst &I) { visitBinaryOperator(I); } void visitMallocInst(MallocInst &I); @@ -200,7 +227,7 @@ namespace { void visitVAArgInst (VAArgInst &I); void visitInstruction(Instruction &I) { - std::cerr << "C Writer does not know about " << I; + cerr << "C Writer does not know about " << I; abort(); } @@ -222,7 +249,7 @@ namespace { /// the program, and removes names from structure types that are not used by the /// program. /// -bool CBackendNameAllUsedStructs::runOnModule(Module &M) { +bool CBackendNameAllUsedStructsAndMergeFunctions::runOnModule(Module &M) { // Get a set of types that are used by the program... std::set UT = getAnalysis().getTypes(); @@ -254,9 +281,76 @@ bool CBackendNameAllUsedStructs::runOnModule(Module &M) { ++RenameCounter; Changed = true; } + + + // Loop over all external functions and globals. If we have two with + // identical names, merge them. + // FIXME: This code should disappear when we don't allow values with the same + // names when they have different types! + std::map ExtSymbols; + for (Module::iterator I = M.begin(), E = M.end(); I != E;) { + Function *GV = I++; + if (GV->isExternal() && GV->hasName()) { + std::pair::iterator, bool> X + = ExtSymbols.insert(std::make_pair(GV->getName(), GV)); + if (!X.second) { + // Found a conflict, replace this global with the previous one. + GlobalValue *OldGV = X.first->second; + GV->replaceAllUsesWith(ConstantExpr::getCast(OldGV, GV->getType())); + GV->eraseFromParent(); + Changed = true; + } + } + } + // Do the same for globals. + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E;) { + GlobalVariable *GV = I++; + if (GV->isExternal() && GV->hasName()) { + std::pair::iterator, bool> X + = ExtSymbols.insert(std::make_pair(GV->getName(), GV)); + if (!X.second) { + // Found a conflict, replace this global with the previous one. + GlobalValue *OldGV = X.first->second; + GV->replaceAllUsesWith(ConstantExpr::getCast(OldGV, GV->getType())); + GV->eraseFromParent(); + Changed = true; + } + } + } + return Changed; } +/// printStructReturnPointerFunctionType - This is like printType for a struct +/// return type, except, instead of printing the type as void (*)(Struct*, ...) +/// print it as "Struct (*)(...)", for struct return functions. +void CWriter::printStructReturnPointerFunctionType(std::ostream &Out, + const PointerType *TheTy) { + const FunctionType *FTy = cast(TheTy->getElementType()); + std::stringstream FunctionInnards; + FunctionInnards << " (*) ("; + bool PrintedType = false; + + FunctionType::param_iterator I = FTy->param_begin(), E = FTy->param_end(); + const Type *RetTy = cast(I->get())->getElementType(); + for (++I; I != E; ++I) { + if (PrintedType) + FunctionInnards << ", "; + printType(FunctionInnards, *I, ""); + PrintedType = true; + } + if (FTy->isVarArg()) { + if (PrintedType) + FunctionInnards << ", ..."; + } else if (!PrintedType) { + FunctionInnards << "void"; + } + FunctionInnards << ')'; + std::string tstr = FunctionInnards.str(); + printType(Out, RetTy, tstr); +} + // Pass the Type* and the variable name and this prints out the variable // declaration. @@ -279,7 +373,7 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, case Type::FloatTyID: return Out << "float " << NameSoFar; case Type::DoubleTyID: return Out << "double " << NameSoFar; default : - std::cerr << "Unknown primitive type: " << *Ty << "\n"; + cerr << "Unknown primitive type: " << *Ty << "\n"; abort(); } @@ -291,24 +385,24 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, switch (Ty->getTypeID()) { case Type::FunctionTyID: { - const FunctionType *MTy = cast(Ty); + const FunctionType *FTy = cast(Ty); std::stringstream FunctionInnards; FunctionInnards << " (" << NameSoFar << ") ("; - for (FunctionType::param_iterator I = MTy->param_begin(), - E = MTy->param_end(); I != E; ++I) { - if (I != MTy->param_begin()) + for (FunctionType::param_iterator I = FTy->param_begin(), + E = FTy->param_end(); I != E; ++I) { + if (I != FTy->param_begin()) FunctionInnards << ", "; printType(FunctionInnards, *I, ""); } - if (MTy->isVarArg()) { - if (MTy->getNumParams()) + if (FTy->isVarArg()) { + if (FTy->getNumParams()) FunctionInnards << ", ..."; - } else if (!MTy->getNumParams()) { + } else if (!FTy->getNumParams()) { FunctionInnards << "void"; } FunctionInnards << ')'; std::string tstr = FunctionInnards.str(); - printType(Out, MTy->getReturnType(), tstr); + printType(Out, FTy->getReturnType(), tstr); return Out; } case Type::StructTyID: { @@ -328,7 +422,8 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, const PointerType *PTy = cast(Ty); std::string ptrName = "*" + NameSoFar; - if (isa(PTy->getElementType())) + if (isa(PTy->getElementType()) || + isa(PTy->getElementType())) ptrName = "(" + ptrName + ")"; return printType(Out, PTy->getElementType(), ptrName); @@ -342,6 +437,14 @@ std::ostream &CWriter::printType(std::ostream &Out, const Type *Ty, NameSoFar + "[" + utostr(NumElements) + "]"); } + case Type::PackedTyID: { + const PackedType *PTy = cast(Ty); + unsigned NumElements = PTy->getNumElements(); + if (NumElements == 0) NumElements = 1; + return printType(Out, PTy->getElementType(), + NameSoFar + "[" + utostr(NumElements) + "]"); + } + case Type::OpaqueTyID: { static int Count = 0; std::string TyName = "struct opaque_" + itostr(Count++); @@ -377,7 +480,7 @@ void CWriter::printConstantArray(ConstantArray *CPA) { // Do not include the last character, which we know is null for (unsigned i = 0, e = CPA->getNumOperands()-1; i != e; ++i) { - unsigned char C = cast(CPA->getOperand(i))->getRawValue(); + unsigned char C = cast(CPA->getOperand(i))->getZExtValue(); // Print it out literally if it is a printable character. The only thing // to be careful about is when the last letter output was a hex escape @@ -425,6 +528,19 @@ void CWriter::printConstantArray(ConstantArray *CPA) { } } +void CWriter::printConstantPacked(ConstantPacked *CP) { + Out << '{'; + if (CP->getNumOperands()) { + Out << ' '; + printConstant(cast(CP->getOperand(0))); + for (unsigned i = 1, e = CP->getNumOperands(); i != e; ++i) { + Out << ", "; + printConstant(cast(CP->getOperand(i))); + } + } + Out << " }"; +} + // 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 @@ -434,7 +550,7 @@ void CWriter::printConstantArray(ConstantArray *CPA) { // only deal in IEEE FP). // static bool isFPCSafeToPrint(const ConstantFP *CFP) { -#if HAVE_PRINTF_A +#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A char Buffer[100]; sprintf(Buffer, "%a", CFP->getValue()); @@ -460,15 +576,79 @@ static bool isFPCSafeToPrint(const ConstantFP *CFP) { #endif } +/// Print out the casting for a cast operation. This does the double casting +/// necessary for conversion to the destination type, if necessary. +/// @returns true if a closing paren is necessary +/// @brief Print a cast +void CWriter::printCast(unsigned opc, const Type *SrcTy, const Type *DstTy) { + Out << '('; + printType(Out, DstTy); + Out << ')'; + switch (opc) { + case Instruction::UIToFP: + case Instruction::ZExt: + if (SrcTy->isSigned()) { + Out << '('; + printType(Out, SrcTy->getUnsignedVersion()); + Out << ')'; + } + break; + case Instruction::SIToFP: + case Instruction::SExt: + if (SrcTy->isUnsigned()) { + Out << '('; + printType(Out, SrcTy->getSignedVersion()); + Out << ')'; + } + break; + case Instruction::IntToPtr: + case Instruction::PtrToInt: + // Avoid "cast to pointer from integer of different size" warnings + Out << "(unsigned long)"; + break; + case Instruction::Trunc: + case Instruction::BitCast: + case Instruction::FPExt: + case Instruction::FPTrunc: + case Instruction::FPToSI: + case Instruction::FPToUI: + default: + break; + } +} + // printConstant - The LLVM Constant to C Constant converter. void CWriter::printConstant(Constant *CPV) { if (const ConstantExpr *CE = dyn_cast(CPV)) { switch (CE->getOpcode()) { - case Instruction::Cast: - Out << "(("; - printType(Out, CPV->getType()); - Out << ')'; + 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::BoolTy) { + // Make sure we really sext from bool here by subtracting from 0 + Out << "0-"; + } printConstant(CE->getOperand(0)); + if (CE->getType() == Type::BoolTy && + (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; @@ -490,8 +670,12 @@ void CWriter::printConstant(Constant *CPV) { case Instruction::Add: case Instruction::Sub: case Instruction::Mul: - case Instruction::Div: - case Instruction::Rem: + 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: @@ -502,15 +686,22 @@ void CWriter::printConstant(Constant *CPV) { case Instruction::SetGT: case Instruction::SetGE: case Instruction::Shl: - case Instruction::Shr: + case Instruction::LShr: + case Instruction::AShr: + { Out << '('; - printConstant(CE->getOperand(0)); + bool NeedsClosingParens = printConstExprCast(CE); + printConstantWithCast(CE->getOperand(0), CE->getOpcode()); switch (CE->getOpcode()) { case Instruction::Add: Out << " + "; break; case Instruction::Sub: Out << " - "; break; case Instruction::Mul: Out << " * "; break; - case Instruction::Div: Out << " / "; break; - case Instruction::Rem: 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; @@ -521,16 +712,20 @@ void CWriter::printConstant(Constant *CPV) { case Instruction::SetGT: Out << " > "; break; case Instruction::SetGE: Out << " >= "; break; case Instruction::Shl: Out << " << "; break; - case Instruction::Shr: Out << " >> "; break; + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; default: assert(0 && "Illegal opcode here!"); } - printConstant(CE->getOperand(1)); + printConstantWithCast(CE->getOperand(1), CE->getOpcode()); + if (NeedsClosingParens) + Out << "))"; Out << ')'; return; + } default: - std::cerr << "CWriter Error: Unhandled constant expression: " - << *CE << "\n"; + cerr << "CWriter Error: Unhandled constant expression: " + << *CE << "\n"; abort(); } } else if (isa(CPV) && CPV->getType()->isFirstClassType()) { @@ -542,30 +737,36 @@ void CWriter::printConstant(Constant *CPV) { switch (CPV->getType()->getTypeID()) { case Type::BoolTyID: - Out << (CPV == ConstantBool::False ? '0' : '1'); break; + Out << (cast(CPV)->getValue() ? '1' : '0'); + break; case Type::SByteTyID: case Type::ShortTyID: - Out << cast(CPV)->getValue(); break; + Out << cast(CPV)->getSExtValue(); + break; case Type::IntTyID: - if ((int)cast(CPV)->getValue() == (int)0x80000000) + if ((int)cast(CPV)->getSExtValue() == (int)0x80000000) Out << "((int)0x80000000U)"; // Handle MININT specially to avoid warning else - Out << cast(CPV)->getValue(); + Out << cast(CPV)->getSExtValue(); break; case Type::LongTyID: - if (cast(CPV)->isMinValue()) + if (cast(CPV)->isMinValue(true)) Out << "(/*INT64_MIN*/(-9223372036854775807LL)-1)"; else - Out << cast(CPV)->getValue() << "ll"; break; + Out << cast(CPV)->getSExtValue() << "ll"; + break; case Type::UByteTyID: case Type::UShortTyID: - Out << cast(CPV)->getValue(); break; + Out << cast(CPV)->getZExtValue(); + break; case Type::UIntTyID: - Out << cast(CPV)->getValue() << 'u'; break; + Out << cast(CPV)->getZExtValue() << 'u'; + break; case Type::ULongTyID: - Out << cast(CPV)->getValue() << "ull"; break; + Out << cast(CPV)->getZExtValue() << "ull"; + break; case Type::FloatTyID: case Type::DoubleTyID: { @@ -583,13 +784,13 @@ void CWriter::printConstant(Constant *CPV) { // 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; + //const unsigned long SignalNaN = 0x7ff4UL; // We need to grab the first part of the FP # char Buffer[100]; uint64_t ll = DoubleToBits(FPC->getValue()); - sprintf(Buffer, "0x%llx", (unsigned long long)ll); + sprintf(Buffer, "0x%llx", static_cast(ll)); std::string Num(&Buffer[0], &Buffer[6]); unsigned long Val = strtoul(Num.c_str(), 0, 16); @@ -607,7 +808,7 @@ void CWriter::printConstant(Constant *CPV) { << " /*inf*/ "; } else { std::string Num; -#if HAVE_PRINTF_A +#if HAVE_PRINTF_A && ENABLE_CBE_PRINTF_A // Print out the constant as a floating point number. char Buffer[100]; sprintf(Buffer, "%a", FPC->getValue()); @@ -640,6 +841,25 @@ void CWriter::printConstant(Constant *CPV) { } break; + case Type::PackedTyID: + if (isa(CPV) || isa(CPV)) { + const PackedType *AT = cast(CPV->getType()); + Out << '{'; + if (AT->getNumElements()) { + Out << ' '; + Constant *CZ = Constant::getNullValue(AT->getElementType()); + printConstant(CZ); + for (unsigned i = 1, e = AT->getNumElements(); i != e; ++i) { + Out << ", "; + printConstant(CZ); + } + } + Out << " }"; + } else { + printConstantPacked(cast(CPV)); + } + break; + case Type::StructTyID: if (isa(CPV) || isa(CPV)) { const StructType *ST = cast(CPV->getType()); @@ -679,11 +899,103 @@ void CWriter::printConstant(Constant *CPV) { } // FALL THROUGH default: - std::cerr << "Unknown constant type: " << *CPV << "\n"; + cerr << "Unknown constant type: " << *CPV << "\n"; abort(); } } +// 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(const ConstantExpr* CE) { + bool NeedsExplicitCast = false; + const Type *Ty = CE->getOperand(0)->getType(); + switch (CE->getOpcode()) { + case Instruction::LShr: + case Instruction::URem: + case Instruction::UDiv: + NeedsExplicitCast = Ty->isSigned(); break; + case Instruction::AShr: + case Instruction::SRem: + case Instruction::SDiv: + NeedsExplicitCast = Ty->isUnsigned(); break; + case Instruction::ZExt: + case Instruction::SExt: + 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 << "(("; + printType(Out, Ty); + 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. + const Type* OpTy = CPV->getType(); + + // Indicate whether to do the cast or not. + bool shouldCast = false; + + // Based on the Opcode for which this Constant is being written, determine + // 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 so it gets + // casted below. + switch (Opcode) { + default: + // for most instructions, it doesn't matter + break; + case Instruction::LShr: + case Instruction::UDiv: + case Instruction::URem: + // For UDiv/URem get correct type + if (OpTy->isSigned()) { + OpTy = OpTy->getUnsignedVersion(); + shouldCast = true; + } + break; + case Instruction::AShr: + case Instruction::SDiv: + case Instruction::SRem: + // For SDiv/SRem get correct type + if (OpTy->isUnsigned()) { + OpTy = OpTy->getSignedVersion(); + shouldCast = true; + } + break; + } + + // Write out the casted constant if we should, otherwise just write the + // operand. + if (shouldCast) { + Out << "(("; + printType(Out, OpTy); + Out << ")"; + printConstant(CPV); + Out << ")"; + } else + writeOperand(CPV); + +} + void CWriter::writeOperandInternal(Value *Operand) { if (Instruction *I = dyn_cast(Operand)) if (isInlinableInst(*I) && !isDirectAlloca(I)) { @@ -702,9 +1014,18 @@ void CWriter::writeOperandInternal(Value *Operand) { } } +void CWriter::writeOperandRaw(Value *Operand) { + Constant* CPV = dyn_cast(Operand); + if (CPV && !isa(CPV)) { + printConstant(CPV); + } else { + Out << Mang->getValueName(Operand); + } +} + void CWriter::writeOperand(Value *Operand) { if (isa(Operand) || isDirectAlloca(Operand)) - Out << "(&"; // Global variables are references as their addresses by llvm + Out << "(&"; // Global variables are referenced as their addresses by llvm writeOperandInternal(Operand); @@ -712,13 +1033,104 @@ void CWriter::writeOperand(Value *Operand) { Out << ')'; } +// Some instructions need to have their result value 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 Instruction. +bool CWriter::writeInstructionCast(const Instruction &I) { + bool NeedsExplicitCast = false; + const Type *Ty = I.getOperand(0)->getType(); + switch (I.getOpcode()) { + case Instruction::LShr: + case Instruction::URem: + case Instruction::UDiv: + NeedsExplicitCast = Ty->isSigned(); break; + case Instruction::AShr: + case Instruction::SRem: + case Instruction::SDiv: + NeedsExplicitCast = Ty->isUnsigned(); break; + case Instruction::ZExt: + case Instruction::SExt: + 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 = I.getType(); + NeedsExplicitCast = true; + break; + default: break; + } + if (NeedsExplicitCast) { + Out << "(("; + printType(Out, Ty); + Out << ")("; + } + return NeedsExplicitCast; +} + +// 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::writeOperandWithCast(Value* Operand, unsigned Opcode) { + + // Extract the operand's type, we'll need it. + const Type* OpTy = Operand->getType(); + + // Indicate whether to do the cast or not. + bool shouldCast = false; + + // Based on the Opcode for which this Operand is being written, determine + // 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 + break; + case Instruction::LShr: + case Instruction::UDiv: + case Instruction::URem: + // For UDiv to have unsigned operands + if (OpTy->isSigned()) { + OpTy = OpTy->getUnsignedVersion(); + shouldCast = true; + } + break; + case Instruction::AShr: + case Instruction::SDiv: + case Instruction::SRem: + if (OpTy->isUnsigned()) { + OpTy = OpTy->getSignedVersion(); + shouldCast = true; + } + break; + } + + // Write out the casted operand if we should, otherwise just write the + // operand. + if (shouldCast) { + Out << "(("; + printType(Out, OpTy); + Out << ")"; + writeOperand(Operand); + Out << ")"; + } else + writeOperand(Operand); + +} + // generateCompilerSpecificCode - This is where we add conditional compilation // directives to cater to specific compilers as need be. // static void generateCompilerSpecificCode(std::ostream& Out) { - // Alloca is hard to get, and we don't want to include stdlib.h here... + // 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__)\n" + << "#if defined(__CYGWIN__) || defined(__MINGW32__)\n" << "extern void *_alloca(unsigned long);\n" << "#define alloca(x) _alloca(x)\n" << "#elif defined(__APPLE__)\n" @@ -731,7 +1143,7 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "extern void *__builtin_alloca(unsigned int);\n" << "#endif\n" << "#define alloca(x) __builtin_alloca(x)\n" - << "#elif defined(__FreeBSD__)\n" + << "#elif defined(__FreeBSD__) || defined(__OpenBSD__)\n" << "#define alloca(x) __builtin_alloca(x)\n" << "#elif !defined(_MSC_VER)\n" << "#include \n" @@ -743,8 +1155,6 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "#define __attribute__(X)\n" << "#endif\n\n"; -#if 0 - // At some point, we should support "external weak" vs. "weak" linkages. // 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" @@ -753,7 +1163,6 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "#else\n" << "#define __EXTERNAL_WEAK__\n" << "#endif\n\n"; -#endif // For now, turn off the weak linkage attribute on Mac OS X. (See above.) Out << "#if defined(__GNUC__) && defined(__APPLE_CC__)\n" @@ -802,7 +1211,11 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "#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 LLVM_PREFETCH(addr,rw,locality) " + "__builtin_prefetch(addr,rw,locality)\n" + << "#define __ATTRIBUTE_CTOR__ __attribute__((constructor))\n" + << "#define __ATTRIBUTE_DTOR__ __attribute__((destructor))\n" + << "#define LLVM_ASM __asm__\n" << "#else\n" << "#define LLVM_NAN(NanStr) ((double)0.0) /* Double */\n" << "#define LLVM_NANF(NanStr) 0.0F /* Float */\n" @@ -811,13 +1224,17 @@ static void generateCompilerSpecificCode(std::ostream& Out) { << "#define LLVM_INF ((double)0.0) /* Double */\n" << "#define LLVM_INFF 0.0F /* Float */\n" << "#define LLVM_PREFETCH(addr,rw,locality) /* PREFETCH */\n" + << "#define __ATTRIBUTE_CTOR__\n" + << "#define __ATTRIBUTE_DTOR__\n" + << "#define LLVM_ASM(X)\n" << "#endif\n\n"; // Output target-specific code that should be inserted into main. Out << "#define CODE_FOR_MAIN() /* Any target-specific code for main()*/\n"; // On X86, set the FP control word to 64-bits of precision instead of 80 bits. Out << "#if defined(__GNUC__) && !defined(__llvm__)\n" - << "#if defined(i386) || defined(__i386__) || defined(__i386)\n" + << "#if defined(i386) || defined(__i386__) || defined(__i386) || " + << "defined(__x86_64__)\n" << "#undef CODE_FOR_MAIN\n" << "#define CODE_FOR_MAIN() \\\n" << " {short F;__asm__ (\"fnstcw %0\" : \"=m\" (*&F)); \\\n" @@ -826,6 +1243,53 @@ static void generateCompilerSpecificCode(std::ostream& Out) { } +/// FindStaticTors - Given a static ctor/dtor list, unpack its contents into +/// the StaticTors set. +static void FindStaticTors(GlobalVariable *GV, std::set &StaticTors){ + ConstantArray *InitList = dyn_cast(GV->getInitializer()); + if (!InitList) return; + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) + if (ConstantStruct *CS = dyn_cast(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. + Constant *FP = CS->getOperand(1); + if (ConstantExpr *CE = dyn_cast(FP)) + if (CE->isCast()) + FP = CE->getOperand(0); + if (Function *F = dyn_cast(FP)) + StaticTors.insert(F); + } +} + +enum SpecialGlobalClass { + NotSpecial = 0, + GlobalCtors, GlobalDtors, + NotPrinted +}; + +/// getGlobalVariableClass - If this is a global that is specially recognized +/// by LLVM, return a code that indicates how we should handle it. +static SpecialGlobalClass getGlobalVariableClass(const GlobalVariable *GV) { + // If this is a global ctors/dtors list, handle it now. + if (GV->hasAppendingLinkage() && GV->use_empty()) { + if (GV->getName() == "llvm.global_ctors") + return GlobalCtors; + else if (GV->getName() == "llvm.global_dtors") + return GlobalDtors; + } + + // Otherwise, it it is other metadata, don't print it. This catches things + // like debug information. + if (GV->getSection() == "llvm.metadata") + return NotPrinted; + + return NotSpecial; +} + + bool CWriter::doInitialization(Module &M) { // Initialize TheModule = &M; @@ -834,7 +1298,24 @@ bool CWriter::doInitialization(Module &M) { // Ensure that all structure types have names... Mang = new Mangler(M); - + Mang->markCharUnacceptable('.'); + + // Keep track of which functions are static ctors/dtors so they can have + // an attribute added to their prototypes. + std::set 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; + } + } + // get declaration for alloca Out << "/* Provide Declarations */\n"; Out << "#include \n"; // Varargs support @@ -861,38 +1342,62 @@ bool CWriter::doInitialization(Module &M) { // Global variable declarations... 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) { + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) { if (I->hasExternalLinkage()) { Out << "extern "; printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); Out << ";\n"; + } else if (I->hasDLLImportLinkage()) { + Out << "__declspec(dllimport) "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); + Out << ";\n"; + } else if (I->hasExternalWeakLinkage()) { + Out << "extern "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); + Out << " __EXTERNAL_WEAK__ ;\n"; } } } // Function declarations + Out << "\n/* Function Declarations */\n"; Out << "double fmod(double, double);\n"; // Support for FP rem Out << "float fmodf(float, float);\n"; - if (!M.empty()) { - Out << "\n/* Function Declarations */\n"; - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { - // Don't print declarations for intrinsic functions. - if (!I->getIntrinsicID() && - I->getName() != "setjmp" && I->getName() != "longjmp") { - printFunctionSignature(I, true); - if (I->hasWeakLinkage()) Out << " __ATTRIBUTE_WEAK__"; - if (I->hasLinkOnceLinkage()) Out << " __ATTRIBUTE_WEAK__"; - Out << ";\n"; - } + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { + // Don't print declarations for intrinsic functions. + if (!I->getIntrinsicID() && I->getName() != "setjmp" && + I->getName() != "longjmp" && I->getName() != "_setjmp") { + if (I->hasExternalWeakLinkage()) + Out << "extern "; + printFunctionSignature(I, true); + if (I->hasWeakLinkage() || I->hasLinkOnceLinkage()) + Out << " __ATTRIBUTE_WEAK__"; + if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; + if (StaticCtors.count(I)) + Out << " __ATTRIBUTE_CTOR__"; + if (StaticDtors.count(I)) + Out << " __ATTRIBUTE_DTOR__"; + + if (I->hasName() && I->getName()[0] == 1) + Out << " LLVM_ASM(\"" << I->getName().c_str()+1 << "\")"; + + Out << ";\n"; } } // Output the global variable declarations if (!M.global_empty()) { Out << "\n\n/* Global Variable Declarations */\n"; - 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) if (!I->isExternal()) { + // Ignore special globals, such as debug info. + if (getGlobalVariableClass(I)) + continue; + if (I->hasInternalLinkage()) Out << "static "; else @@ -903,6 +1408,8 @@ bool CWriter::doInitialization(Module &M) { Out << " __attribute__((common))"; else if (I->hasWeakLinkage()) Out << " __ATTRIBUTE_WEAK__"; + else if (I->hasExternalWeakLinkage()) + Out << " __EXTERNAL_WEAK__"; Out << ";\n"; } } @@ -910,10 +1417,20 @@ bool CWriter::doInitialization(Module &M) { // Output the global variable definitions and contents... 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) + for (Module::global_iterator I = M.global_begin(), E = M.global_end(); + I != E; ++I) if (!I->isExternal()) { + // Ignore special globals, such as debug info. + if (getGlobalVariableClass(I)) + continue; + if (I->hasInternalLinkage()) Out << "static "; + else if (I->hasDLLImportLinkage()) + Out << "__declspec(dllimport) "; + else if (I->hasDLLExportLinkage()) + Out << "__declspec(dllexport) "; + printType(Out, I->getType()->getElementType(), Mang->getValueName(I)); if (I->hasLinkOnceLinkage()) Out << " __attribute__((common))"; @@ -934,7 +1451,8 @@ bool CWriter::doInitialization(Module &M) { // the compiler figure out the rest of the zeros. Out << " = " ; if (isa(I->getInitializer()->getType()) || - isa(I->getInitializer()->getType())) { + isa(I->getInitializer()->getType()) || + isa(I->getInitializer()->getType())) { Out << "{ 0 }"; } else { // Just print it out normally. @@ -985,7 +1503,7 @@ void CWriter::printFloatingPointConstants(Function &F) { /// printSymbolTable - Run through symbol table looking for type names. If a -/// type name is found, emit it's declaration... +/// type name is found, emit its declaration... /// void CWriter::printModuleTypes(const SymbolTable &ST) { // We are only interested in the type plane of the symbol table. @@ -1033,38 +1551,46 @@ void CWriter::printModuleTypes(const SymbolTable &ST) { // Push the struct onto the stack and recursively push all structs // this one depends on. +// +// TODO: Make this work properly with packed types +// void CWriter::printContainedStructs(const Type *Ty, std::set &StructPrinted){ + // Don't walk through pointers. + if (isa(Ty) || Ty->isPrimitiveType()) return; + + // Print all contained types first. + for (Type::subtype_iterator I = Ty->subtype_begin(), + E = Ty->subtype_end(); I != E; ++I) + printContainedStructs(*I, StructPrinted); + if (const StructType *STy = dyn_cast(Ty)) { - //Check to see if we have already printed this struct - if (StructPrinted.count(STy) == 0) { - // Print all contained types first... - for (StructType::element_iterator I = STy->element_begin(), - E = STy->element_end(); I != E; ++I) { - const Type *Ty1 = I->get(); - if (isa(Ty1) || isa(Ty1)) - printContainedStructs(*I, StructPrinted); - } - - //Print structure type out.. - StructPrinted.insert(STy); + // Check to see if we have already printed this struct. + if (StructPrinted.insert(STy).second) { + // Print structure type out. std::string Name = TypeNames[STy]; printType(Out, STy, Name, true); Out << ";\n\n"; } - - // If it is an array, check contained types and continue - } else if (const ArrayType *ATy = dyn_cast(Ty)){ - const Type *Ty1 = ATy->getElementType(); - if (isa(Ty1) || isa(Ty1)) - printContainedStructs(Ty1, StructPrinted); } } - void CWriter::printFunctionSignature(const Function *F, bool Prototype) { + /// isCStructReturn - Should this function actually return a struct by-value? + bool isCStructReturn = F->getCallingConv() == CallingConv::CSRet; + if (F->hasInternalLinkage()) Out << "static "; - + if (F->hasDLLImportLinkage()) Out << "__declspec(dllimport) "; + if (F->hasDLLExportLinkage()) Out << "__declspec(dllexport) "; + switch (F->getCallingConv()) { + case CallingConv::X86_StdCall: + Out << "__stdcall "; + break; + case CallingConv::X86_FastCall: + Out << "__fastcall "; + break; + } + // Loop over the arguments, printing them... const FunctionType *FT = cast(F->getFunctionType()); @@ -1073,55 +1599,97 @@ void CWriter::printFunctionSignature(const Function *F, bool Prototype) { // Print out the name... FunctionInnards << Mang->getValueName(F) << '('; + bool PrintedArg = false; if (!F->isExternal()) { if (!F->arg_empty()) { + Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end(); + + // If this is a struct-return function, don't print the hidden + // struct-return argument. + if (isCStructReturn) { + assert(I != E && "Invalid struct return function!"); + ++I; + } + std::string ArgName; - if (F->arg_begin()->hasName() || !Prototype) - ArgName = Mang->getValueName(F->arg_begin()); - printType(FunctionInnards, F->arg_begin()->getType(), ArgName); - for (Function::const_arg_iterator I = ++F->arg_begin(), E = F->arg_end(); - I != E; ++I) { - FunctionInnards << ", "; + for (; I != E; ++I) { + if (PrintedArg) FunctionInnards << ", "; if (I->hasName() || !Prototype) ArgName = Mang->getValueName(I); else ArgName = ""; printType(FunctionInnards, I->getType(), ArgName); + PrintedArg = true; } } } else { - // Loop over the arguments, printing them... - for (FunctionType::param_iterator I = FT->param_begin(), - E = FT->param_end(); I != E; ++I) { - if (I != FT->param_begin()) FunctionInnards << ", "; + // Loop over the arguments, printing them. + FunctionType::param_iterator I = FT->param_begin(), E = FT->param_end(); + + // If this is a struct-return function, don't print the hidden + // struct-return argument. + if (isCStructReturn) { + assert(I != E && "Invalid struct return function!"); + ++I; + } + + for (; I != E; ++I) { + if (PrintedArg) FunctionInnards << ", "; printType(FunctionInnards, *I); + PrintedArg = true; } } // Finish printing arguments... if this is a vararg function, print the ..., // unless there are no known types, in which case, we just emit (). // - if (FT->isVarArg() && FT->getNumParams()) { - if (FT->getNumParams()) FunctionInnards << ", "; + if (FT->isVarArg() && PrintedArg) { + if (PrintedArg) FunctionInnards << ", "; FunctionInnards << "..."; // Output varargs portion of signature! - } else if (!FT->isVarArg() && FT->getNumParams() == 0) { + } else if (!FT->isVarArg() && !PrintedArg) { FunctionInnards << "void"; // ret() -> ret(void) in C. } FunctionInnards << ')'; - // Print out the return type and the entire signature for that matter - printType(Out, F->getReturnType(), FunctionInnards.str()); + + // Get the return tpe for the function. + const Type *RetTy; + if (!isCStructReturn) + RetTy = F->getReturnType(); + else { + // If this is a struct-return function, print the struct-return type. + RetTy = cast(FT->getParamType(0))->getElementType(); + } + + // Print out the return type and the signature built above. + printType(Out, RetTy, FunctionInnards.str()); } void CWriter::printFunction(Function &F) { printFunctionSignature(&F, false); Out << " {\n"; + + // If this is a struct return function, handle the result with magic. + if (F.getCallingConv() == CallingConv::CSRet) { + const Type *StructTy = + cast(F.arg_begin()->getType())->getElementType(); + Out << " "; + printType(Out, StructTy, "StructReturn"); + Out << "; /* Struct return temporary */\n"; + + Out << " "; + printType(Out, F.arg_begin()->getType(), Mang->getValueName(F.arg_begin())); + Out << " = &StructReturn;\n"; + } + 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 (const AllocaInst *AI = isDirectAlloca(&*I)) { Out << " "; printType(Out, AI->getAllocatedType(), Mang->getValueName(AI)); Out << "; /* Address-exposed local */\n"; + PrintedVar = true; } else if (I->getType() != Type::VoidTy && !isInlinableInst(*I)) { Out << " "; printType(Out, I->getType(), Mang->getValueName(&*I)); @@ -1133,9 +1701,11 @@ void CWriter::printFunction(Function &F) { Mang->getValueName(&*I)+"__PHI_TEMPORARY"); Out << ";\n"; } + PrintedVar = true; } - Out << '\n'; + if (PrintedVar) + Out << '\n'; if (F.hasExternalLinkage() && F.getName() == "main") Out << " CODE_FOR_MAIN();\n"; @@ -1188,7 +1758,7 @@ void CWriter::printBasicBlock(BasicBlock *BB) { for (BasicBlock::iterator II = BB->begin(), E = --BB->end(); II != E; ++II) { if (!isInlinableInst(*II) && !isDirectAlloca(II)) { - if (II->getType() != Type::VoidTy) + if (II->getType() != Type::VoidTy && !isInlineAsm(*II)) outputLValue(II); else Out << " "; @@ -1206,6 +1776,12 @@ void CWriter::printBasicBlock(BasicBlock *BB) { // 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. + if (I.getParent()->getParent()->getCallingConv() == CallingConv::CSRet) { + Out << " return StructReturn;\n"; + return; + } + // Don't output a void return if this is the last basic block in the function if (I.getNumOperands() == 0 && &*--I.getParent()->getParent()->end() == I.getParent() && @@ -1352,8 +1928,7 @@ void CWriter::visitBinaryOperator(Instruction &I) { Out << "-("; writeOperand(BinaryOperator::getNegArgument(cast(&I))); Out << ")"; - } else if (I.getOpcode() == Instruction::Rem && - I.getType()->isFloatingPoint()) { + } else if (I.getOpcode() == Instruction::FRem) { // Output a call to fmod/fmodf instead of emitting a%b if (I.getType() == Type::FloatTy) Out << "fmodf("; @@ -1364,14 +1939,26 @@ void CWriter::visitBinaryOperator(Instruction &I) { writeOperand(I.getOperand(1)); Out << ")"; } else { - writeOperand(I.getOperand(0)); + + // 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: Out << " + "; break; case Instruction::Sub: Out << " - "; break; case Instruction::Mul: Out << '*'; break; - case Instruction::Div: Out << '/'; break; - case Instruction::Rem: 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; @@ -1382,11 +1969,14 @@ void CWriter::visitBinaryOperator(Instruction &I) { case Instruction::SetLT: Out << " < "; break; case Instruction::SetGT: Out << " > "; break; case Instruction::Shl : Out << " << "; break; - case Instruction::Shr : Out << " >> "; break; - default: std::cerr << "Invalid operator type!" << I; abort(); + case Instruction::LShr: + case Instruction::AShr: Out << " >> "; break; + default: cerr << "Invalid operator type!" << I; abort(); } - writeOperand(I.getOperand(1)); + writeOperandWithCast(I.getOperand(1), I.getOpcode()); + if (NeedsClosingParens) + Out << "))"; } if (needsCast) { @@ -1395,22 +1985,24 @@ void CWriter::visitBinaryOperator(Instruction &I) { } void CWriter::visitCastInst(CastInst &I) { - if (I.getType() == Type::BoolTy) { - Out << '('; - writeOperand(I.getOperand(0)); - Out << " != 0)"; - return; - } + const Type *DstTy = I.getType(); + const Type *SrcTy = I.getOperand(0)->getType(); Out << '('; - printType(Out, I.getType()); - Out << ')'; - if (isa(I.getType())&&I.getOperand(0)->getType()->isIntegral() || - isa(I.getOperand(0)->getType())&&I.getType()->isIntegral()) { - // Avoid "cast to pointer from integer of different size" warnings - Out << "(long)"; + printCast(I.getOpcode(), SrcTy, DstTy); + if (I.getOpcode() == Instruction::SExt && SrcTy == Type::BoolTy) { + // Make sure we really get a sext from bool by subtracing the bool from 0 + Out << "0-"; } - writeOperand(I.getOperand(0)); + if (DstTy == Type::BoolTy && + (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) { @@ -1439,9 +2031,21 @@ void CWriter::lowerIntrinsics(Function &F) { case Intrinsic::setjmp: case Intrinsic::longjmp: case Intrinsic::prefetch: + case Intrinsic::dbg_stoppoint: + case Intrinsic::powi_f32: + case Intrinsic::powi_f64: // We directly implement these intrinsics break; default: + // If this is an intrinsic that directly corresponds to a GCC + // builtin, we handle it. + const char *BuiltinName = ""; +#define GET_GCC_BUILTIN_NAME +#include "llvm/Intrinsics.gen" +#undef GET_GCC_BUILTIN_NAME + // If we handle it, don't lower it. + if (BuiltinName[0]) break; + // All other intrinsic calls we must lower. Instruction *Before = 0; if (CI != &BB->front()) @@ -1453,29 +2057,49 @@ void CWriter::lowerIntrinsics(Function &F) { } else { I = BB->begin(); } + break; } } void CWriter::visitCallInst(CallInst &I) { + //check if we have inline asm + if (isInlineAsm(I)) { + visitInlineAsm(I); + return; + } + + bool WroteCallee = false; + // Handle intrinsic function calls first... if (Function *F = I.getCalledFunction()) if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID()) { switch (ID) { - default: assert(0 && "Unknown LLVM intrinsic!"); + default: { + // If this is an intrinsic that directly corresponds to a GCC + // builtin, we emit it here. + const char *BuiltinName = ""; +#define GET_GCC_BUILTIN_NAME +#include "llvm/Intrinsics.gen" +#undef GET_GCC_BUILTIN_NAME + assert(BuiltinName[0] && "Unknown LLVM intrinsic!"); + + Out << BuiltinName; + WroteCallee = true; + break; + } case Intrinsic::vastart: Out << "0; "; - // Out << "va_start(*(va_list*)&" << Mang->getValueName(&I) << ", "; Out << "va_start(*(va_list*)"; writeOperand(I.getOperand(1)); Out << ", "; // Output the last argument to the enclosing function... if (I.getParent()->getParent()->arg_empty()) { - std::cerr << "The C backend does not currently support zero " - << "argument varargs functions, such as '" - << I.getParent()->getParent()->getName() << "'!\n"; + cerr << "The C backend does not currently support zero " + << "argument varargs functions, such as '" + << I.getParent()->getParent()->getName() << "'!\n"; abort(); } writeOperand(--I.getParent()->getParent()->arg_end()); @@ -1508,12 +2132,26 @@ void CWriter::visitCallInst(CallInst &I) { writeOperand(I.getOperand(1)); Out << ')'; return; + case Intrinsic::powi_f32: + case Intrinsic::powi_f64: + Out << "__builtin_powi("; + writeOperand(I.getOperand(1)); + Out << ", "; + writeOperand(I.getOperand(2)); + Out << ')'; + return; case Intrinsic::setjmp: +#if defined(HAVE__SETJMP) && defined(HAVE__LONGJMP) + Out << "_"; // Use _setjmp on systems that support it! +#endif Out << "setjmp(*(jmp_buf*)"; writeOperand(I.getOperand(1)); Out << ')'; return; case Intrinsic::longjmp: +#if defined(HAVE__SETJMP) && defined(HAVE__LONGJMP) + Out << "_"; // Use _longjmp on systems that support it! +#endif Out << "longjmp(*(jmp_buf*)"; writeOperand(I.getOperand(1)); Out << ", "; @@ -1529,78 +2167,226 @@ void CWriter::visitCallInst(CallInst &I) { writeOperand(I.getOperand(3)); Out << ")"; return; + case Intrinsic::dbg_stoppoint: { + // If we use writeOperand directly we get a "u" suffix which is rejected + // by gcc. + DbgStopPointInst &SPI = cast(I); + + Out << "\n#line " + << SPI.getLine() + << " \"" << SPI.getDirectory() + << SPI.getFileName() << "\"\n"; + return; + } } } Value *Callee = I.getCalledValue(); - // GCC is really a 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. - // - bool WroteCallee = false; + // If this is a call to a struct-return function, assign to the first + // parameter instead of passing it to the call. + bool isStructRet = I.getCallingConv() == CallingConv::CSRet; + if (isStructRet) { + Out << "*("; + writeOperand(I.getOperand(1)); + Out << ") = "; + } + if (I.isTailCall()) Out << " /*tail*/ "; - if (ConstantExpr *CE = dyn_cast(Callee)) - if (CE->getOpcode() == Instruction::Cast) - if (Function *RF = dyn_cast(CE->getOperand(0))) { - const FunctionType *RFTy = RF->getFunctionType(); - if (RFTy->getNumParams() == I.getNumOperands()-1) { - // If the call site expects a value, and the actual callee doesn't - // provide one, return 0. - if (I.getType() != Type::VoidTy && - RFTy->getReturnType() == Type::VoidTy) - Out << "0 /*actual callee doesn't return value*/; "; - Callee = RF; - } else { - // Ok, just cast the pointer type. - Out << "(("; - printType(Out, CE->getType()); - Out << ")(void*)"; - printConstant(RF); - Out << ')'; - WroteCallee = true; - } - } const PointerType *PTy = cast(Callee->getType()); const FunctionType *FTy = cast(PTy->getElementType()); - const Type *RetTy = FTy->getReturnType(); + + if (!WroteCallee) { + // If this is an indirect call to a struct return function, we need to cast + // the pointer. + bool NeedsCast = isStructRet && !isa(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(Callee)) + if (CE->isCast()) + if (Function *RF = dyn_cast(CE->getOperand(0))) { + NeedsCast = true; + Callee = RF; + } + + if (NeedsCast) { + // Ok, just cast the pointer type. + Out << "(("; + if (!isStructRet) + printType(Out, I.getCalledValue()->getType()); + else + printStructReturnPointerFunctionType(Out, + cast(I.getCalledValue()->getType())); + Out << ")(void*)"; + } + writeOperand(Callee); + if (NeedsCast) Out << ')'; + } - if (!WroteCallee) writeOperand(Callee); Out << '('; unsigned NumDeclaredParams = FTy->getNumParams(); - if (I.getNumOperands() != 1) { - CallSite::arg_iterator AI = I.op_begin()+1, AE = I.op_end(); - if (NumDeclaredParams && (*AI)->getType() != FTy->getParamType(0)) { + CallSite::arg_iterator AI = I.op_begin()+1, AE = I.op_end(); + unsigned ArgNo = 0; + if (isStructRet) { // Skip struct return argument. + ++AI; + ++ArgNo; + } + + bool PrintedArg = false; + for (; AI != AE; ++AI, ++ArgNo) { + if (PrintedArg) Out << ", "; + if (ArgNo < NumDeclaredParams && + (*AI)->getType() != FTy->getParamType(ArgNo)) { Out << '('; - printType(Out, FTy->getParamType(0)); + printType(Out, FTy->getParamType(ArgNo)); Out << ')'; } - writeOperand(*AI); + PrintedArg = true; + } + Out << ')'; +} - unsigned ArgNo; - for (ArgNo = 1, ++AI; AI != AE; ++AI, ++ArgNo) { - Out << ", "; - if (ArgNo < NumDeclaredParams && - (*AI)->getType() != FTy->getParamType(ArgNo)) { - Out << '('; - printType(Out, FTy->getParamType(ArgNo)); - 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) { + + assert(c.Codes.size() == 1 && "Too many asm constraint codes to handle"); + + const char** table = 0; + + //Grab the translation table from TargetAsmInfo if it exists + if (!TAsm) { + std::string E; + const TargetMachineRegistry::Entry* Match = + TargetMachineRegistry::getClosestStaticTargetForModule(*TheModule, E); + if (Match) { + //Per platform Target Machines don't exist, so create it + // this must be done only once + const TargetMachine* TM = Match->CtorFn(*TheModule, ""); + TAsm = TM->getTargetAsmInfo(); + } + } + if (TAsm) + table = TAsm->getAsmCBE(); + + //Search the translation table if it exists + for (int i = 0; table && table[i]; i += 2) + if (c.Codes[0] == table[i]) + return table[i+1]; + + //default is identity + return c.Codes[0]; +} + +//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; +} + +//TODO: assumptions about what consume arguments from the call are likely wrong +// handle communitivity +void CWriter::visitInlineAsm(CallInst &CI) { + InlineAsm* as = cast(CI.getOperand(0)); + std::vector Constraints = as->ParseConstraints(); + std::vector > Input; + std::vector > Output; + std::string Clobber; + int count = CI.getType() == Type::VoidTy ? 1 : 0; + for (std::vector::iterator I = Constraints.begin(), + E = Constraints.end(); I != E; ++I) { + assert(I->Codes.size() == 1 && "Too many asm constraint codes to handle"); + std::string c = + InterpretASMConstraint(*I); + switch(I->Type) { + default: + assert(0 && "Unknown asm constraint"); + break; + case InlineAsm::isInput: { + if (c.size()) { + Input.push_back(std::make_pair(c, count ? CI.getOperand(count) : &CI)); + ++count; //consume arg + } + break; + } + case InlineAsm::isOutput: { + if (c.size()) { + Output.push_back(std::make_pair("="+((I->isEarlyClobber ? "&" : "")+c), + count ? CI.getOperand(count) : &CI)); + ++count; //consume arg } - writeOperand(*AI); + break; + } + case InlineAsm::isClobber: { + if (c.size()) + Clobber += ",\"" + c + "\""; + break; + } } } - Out << ')'; + + //fix up the asm string for gcc + std::string asmstr = gccifyAsm(as->getAsmString()); + + Out << "__asm__ volatile (\"" << asmstr << "\"\n"; + Out << " :"; + for (std::vector >::iterator I = Output.begin(), + E = Output.end(); I != E; ++I) { + Out << "\"" << I->first << "\"("; + writeOperandRaw(I->second); + Out << ")"; + if (I + 1 != E) + Out << ","; + } + Out << "\n :"; + for (std::vector >::iterator I = Input.begin(), + E = Input.end(); I != E; ++I) { + Out << "\"" << I->first << "\"("; + writeOperandRaw(I->second); + Out << ")"; + if (I + 1 != E) + Out << ","; + } + if (Clobber.size()) + Out << "\n :" << Clobber.substr(1); + Out << ")"; } void CWriter::visitMallocInst(MallocInst &I) { @@ -1628,7 +2414,7 @@ void CWriter::printIndexingExpression(Value *Ptr, gep_type_iterator I, gep_type_iterator E) { bool HasImplicitAddress = false; // If accessing a global value with no indexing, avoid *(&GV) syndrome - if (GlobalValue *V = dyn_cast(Ptr)) { + if (isa(Ptr)) { HasImplicitAddress = true; } else if (isDirectAlloca(Ptr)) { HasImplicitAddress = true; @@ -1664,14 +2450,14 @@ void CWriter::printIndexingExpression(Value *Ptr, gep_type_iterator I, // Print out the -> operator if possible... if (TmpI != E && isa(*TmpI)) { Out << (HasImplicitAddress ? "." : "->"); - Out << "field" << cast(TmpI.getOperand())->getValue(); + Out << "field" << cast(TmpI.getOperand())->getZExtValue(); I = ++TmpI; } } for (; I != E; ++I) if (isa(*I)) { - Out << ".field" << cast(I.getOperand())->getValue(); + Out << ".field" << cast(I.getOperand())->getZExtValue(); } else { Out << '['; writeOperand(I.getOperand()); @@ -1724,15 +2510,17 @@ void CWriter::visitVAArgInst(VAArgInst &I) { // External Interface declaration //===----------------------------------------------------------------------===// -bool CTargetMachine::addPassesToEmitFile(PassManager &PM, std::ostream &o, - CodeGenFileType FileType, bool Fast) { +bool CTargetMachine::addPassesToEmitWholeFile(PassManager &PM, + std::ostream &o, + CodeGenFileType FileType, + bool Fast) { if (FileType != TargetMachine::AssemblyFile) return true; PM.add(createLowerGCPass()); PM.add(createLowerAllocationsPass(true)); PM.add(createLowerInvokePass()); PM.add(createCFGSimplificationPass()); // clean up after lower invoke. - PM.add(new CBackendNameAllUsedStructs()); - PM.add(new CWriter(o, getIntrinsicLowering())); + PM.add(new CBackendNameAllUsedStructsAndMergeFunctions()); + PM.add(new CWriter(o)); return false; }