summaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorReid Spencer <rspencer@reidspencer.com>2007-04-12 21:00:45 +0000
committerReid Spencer <rspencer@reidspencer.com>2007-04-12 21:00:45 +0000
commit69f80a63a2a82fd24b3936f3297854727676f867 (patch)
tree1cbc6731e119095efe7a712d4eb956f3d31aa19e /lib/Target
parenta4563364d052d078724655bb01e6298f12ed2733 (diff)
downloadllvm-69f80a63a2a82fd24b3936f3297854727676f867.tar.gz
llvm-69f80a63a2a82fd24b3936f3297854727676f867.tar.bz2
llvm-69f80a63a2a82fd24b3936f3297854727676f867.tar.xz
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@35954 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/CBackend/CBackend.cpp34
1 files changed, 32 insertions, 2 deletions
diff --git a/lib/Target/CBackend/CBackend.cpp b/lib/Target/CBackend/CBackend.cpp
index 9f64bd17bc..8f053a6da3 100644
--- a/lib/Target/CBackend/CBackend.cpp
+++ b/lib/Target/CBackend/CBackend.cpp
@@ -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) {