diff --git a/llvm/lib/Target/CBackend/CBackend.cpp b/llvm/lib/Target/CBackend/CBackend.cpp index 9f64bd17bc55..8f053a6da3a9 100644 --- a/llvm/lib/Target/CBackend/CBackend.cpp +++ b/llvm/lib/Target/CBackend/CBackend.cpp @@ -45,6 +45,7 @@ #include "llvm/Config/config.h" #include #include +// #include using namespace llvm; namespace { @@ -78,8 +79,9 @@ namespace { const TargetAsmInfo* TAsm; const TargetData* TD; std::map TypeNames; - std::map FPConstantMap; + std::set intrinsicPrototypesAlreadyGenerated; + public: CWriter(std::ostream &o) : Out(o), IL(0), Mang(0), LI(0), TheModule(0), TAsm(0), TD(0) {} @@ -2364,6 +2366,13 @@ void CWriter::visitSelectInst(SelectInst &I) { void CWriter::lowerIntrinsics(Function &F) { + // This is used to keep track of intrinsics that get generated to a lowered + // function. We must generate the prototypes before the function body which + // will only be expanded on first use (by the loop below). + std::vector prototypesToGen; + + // Examine all the instructions in this function to find the intrinsics that + // need to be lowered. for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) if (CallInst *CI = dyn_cast(I++)) @@ -2404,10 +2413,31 @@ void CWriter::lowerIntrinsics(Function &F) { } 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(I)) + if (Function *NewF = Call->getCalledFunction()) + if (!NewF->isDeclaration()) + prototypesToGen.push_back(NewF); + break; } -} + // We may have collected some prototypes to emit in the loop above. + // Emit them now, before the function that uses them is emitted. But, + // be careful not to emit them twice. + std::vector::iterator I = prototypesToGen.begin(); + std::vector::iterator E = prototypesToGen.end(); + for ( ; I != E; ++I) { + if (intrinsicPrototypesAlreadyGenerated.count(*I) == 0) { + Out << '\n'; + printFunctionSignature(*I, true); + Out << ";\n"; + intrinsicPrototypesAlreadyGenerated.insert(*I); + } + } +} void CWriter::visitCallInst(CallInst &I) {