aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-01-04 18:01:35 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-01-04 18:01:35 -0800
commit887963b047d69e19649749fb426a9f35e5f2eaad (patch)
tree6aa5b29facbe85ea52b1babdfb0733309a860668
parent9e4381bdf422b1ece4084a2584477ca2dfc3acac (diff)
if a function is bitcast to another type, just call the actual function properly, do not go through a bitcast into an unnecessary indirect call that also uses the wrong type
-rw-r--r--lib/Target/JSBackend/CallHandlers.h18
1 files changed, 16 insertions, 2 deletions
diff --git a/lib/Target/JSBackend/CallHandlers.h b/lib/Target/JSBackend/CallHandlers.h
index 36f0acdabf..c6f16e6a78 100644
--- a/lib/Target/JSBackend/CallHandlers.h
+++ b/lib/Target/JSBackend/CallHandlers.h
@@ -8,11 +8,25 @@ CallHandlerMap *CallHandlers;
// Definitions
+const Value *getActuallyCalledValue(const CallInst *CI) {
+ const Value *CV = CI->getCalledValue();
+ if (const BitCastInst *B = dyn_cast<const BitCastInst>(CV)) {
+ // if the called value is a bitcast of a function, then we just call it directly, properly
+ // for example, extern void x() in C will turn into void x(...) in LLVM IR, then the IR bitcasts
+ // it to the proper form right before the call. this both causes an unnecessary indirect
+ // call, and it is done with the wrong type. TODO: don't even put it into the function table
+ if (const Function *F = dyn_cast<const Function>(B->getOperand(0))) {
+ CV = F;
+ }
+ }
+ return CV;
+}
+
#define DEF_CALL_HANDLER(Ident, Code) \
std::string CH_##Ident(const CallInst *CI, std::string Name, int NumArgs=-1) { Code }
DEF_CALL_HANDLER(__default__, {
- const Value *CV = CI->getCalledValue();
+ const Value *CV = getActuallyCalledValue(CI);
bool NeedCasts;
if (const Function *F = dyn_cast<const Function>(CV)) {
NeedCasts = F->isDeclaration(); // if ffi call, need casts
@@ -721,7 +735,7 @@ void setupCallHandlers() {
}
std::string handleCall(const CallInst *CI) {
- const Value *CV = CI->getCalledValue();
+ const Value *CV = getActuallyCalledValue(CI);
assert(!isa<InlineAsm>(CV) && "asm() not supported, use EM_ASM() (see emscripten.h)");
std::string Name = getJSName(CV);
if (strcmp(Name.c_str(), "_llvm_dbg_value") == 0) return ""; // ignore this