Provide support for intrinsics that lower themselves to a function body.

This can happen for intrinsics that are overloaded.  In such cases it is
necessary to emit a function prototype before the body of the function
that calls the intrinsic and to ensure we don't emit it multiple times.

llvm-svn: 35954
This commit is contained in:
Reid Spencer 2007-04-12 21:00:45 +00:00
parent c451ec635f
commit 0ef2ca8da7
1 changed files with 32 additions and 2 deletions

View File

@ -45,6 +45,7 @@
#include "llvm/Config/config.h"
#include <algorithm>
#include <sstream>
// #include <set>
using namespace llvm;
namespace {
@ -78,8 +79,9 @@ namespace {
const TargetAsmInfo* TAsm;
const TargetData* TD;
std::map<const Type *, std::string> TypeNames;
std::map<const ConstantFP *, unsigned> FPConstantMap;
std::set<Function*> 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<Function*> 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<CallInst>(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<CallInst>(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<Function*>::iterator I = prototypesToGen.begin();
std::vector<Function*>::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) {