aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/InitializePasses.h2
-rw-r--r--include/llvm/Transforms/NaCl.h2
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp7
-rw-r--r--lib/Transforms/NaCl/AddPNaClExternalDecls.cpp71
-rw-r--r--lib/Transforms/NaCl/CMakeLists.txt4
-rw-r--r--lib/Transforms/NaCl/ResolvePNaClIntrinsics.cpp100
-rw-r--r--test/NaCl/ARM/nacl-setlongjmp-intrinsics.ll2
-rw-r--r--test/NaCl/X86/nacl-setlongjmp-intrinsics.ll2
-rw-r--r--test/Transforms/NaCl/add-pnacl-external-decls.ll6
-rw-r--r--test/Transforms/NaCl/resolve-pnacl-intrinsics.ll25
-rw-r--r--tools/llc/llc.cpp23
-rw-r--r--tools/opt/opt.cpp2
-rw-r--r--tools/pnacl-llc/pnacl-llc.cpp13
13 files changed, 249 insertions, 10 deletions
diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h
index b55970ad84..a55ea5ce1e 100644
--- a/include/llvm/InitializePasses.h
+++ b/include/llvm/InitializePasses.h
@@ -277,6 +277,7 @@ void initializeLoopVectorizePass(PassRegistry&);
void initializeBBVectorizePass(PassRegistry&);
void initializeMachineFunctionPrinterPassPass(PassRegistry&);
// @LOCALMOD-BEGIN
+void initializeAddPNaClExternalDeclsPass(PassRegistry&);
void initializeExpandByValPass(PassRegistry&);
void initializeExpandConstantExprPass(PassRegistry&);
void initializeExpandCtorsPass(PassRegistry&);
@@ -294,6 +295,7 @@ void initializePNaClABIVerifyFunctionsPass(PassRegistry&);
void initializePromoteIntegersPass(PassRegistry&);
void initializeReplacePtrsWithIntsPass(PassRegistry&);
void initializeResolveAliasesPass(PassRegistry&);
+void initializeResolvePNaClIntrinsicsPass(PassRegistry&);
void initializeRewritePNaClLibraryCallsPass(PassRegistry&);
void initializeStripMetadataPass(PassRegistry&);
// @LOCALMOD-END
diff --git a/include/llvm/Transforms/NaCl.h b/include/llvm/Transforms/NaCl.h
index 3b9ce35dc8..f42336fc67 100644
--- a/include/llvm/Transforms/NaCl.h
+++ b/include/llvm/Transforms/NaCl.h
@@ -20,6 +20,7 @@ class PassManager;
class Use;
class Value;
+ModulePass *createAddPNaClExternalDeclsPass();
ModulePass *createExpandByValPass();
FunctionPass *createExpandConstantExprPass();
ModulePass *createExpandCtorsPass();
@@ -33,6 +34,7 @@ ModulePass *createGlobalCleanupPass();
FunctionPass *createPromoteIntegersPass();
ModulePass *createReplacePtrsWithIntsPass();
ModulePass *createResolveAliasesPass();
+FunctionPass *createResolvePNaClIntrinsicsPass();
ModulePass *createRewritePNaClLibraryCallsPass();
ModulePass *createStripMetadataPass();
FunctionPass *createInsertDivideCheckPass();
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 9113fb1b6f..b7a7e2e133 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -5215,13 +5215,6 @@ SelectionDAGBuilder::visitIntrinsicCall(const CallInst &I, unsigned Intrinsic) {
setValue(&I, DAG.getNode(ISD::NACL_TARGET_ARCH, dl, DestVT));
return 0;
}
- // Native Client Intrinsics for setjmp/longjmp
- case Intrinsic::nacl_setjmp: {
- return "setjmp";
- }
- case Intrinsic::nacl_longjmp: {
- return "longjmp";
- }
// @LOCALMOD-END
}
}
diff --git a/lib/Transforms/NaCl/AddPNaClExternalDecls.cpp b/lib/Transforms/NaCl/AddPNaClExternalDecls.cpp
new file mode 100644
index 0000000000..f96db09b2f
--- /dev/null
+++ b/lib/Transforms/NaCl/AddPNaClExternalDecls.cpp
@@ -0,0 +1,71 @@
+//===- AddPNaClExternalDecls.cpp - Add decls for PNaCl external functions -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass adds function declarations for external functions used by PNaCl.
+// These externals are implemented in native libraries and calls to them are
+// created as part of the translation process.
+//
+// Running this pass is a precondition for running ResolvePNaClIntrinsics. They
+// are separate because one is a ModulePass and the other is a FunctionPass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Type.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/NaCl.h"
+
+using namespace llvm;
+
+namespace {
+ // This is a module pass because it adds declarations to the module.
+ class AddPNaClExternalDecls : public ModulePass {
+ public:
+ static char ID;
+ AddPNaClExternalDecls() : ModulePass(ID) {
+ initializeAddPNaClExternalDeclsPass(*PassRegistry::getPassRegistry());
+ }
+
+ virtual bool runOnModule(Module &M);
+ };
+}
+
+bool AddPNaClExternalDecls::runOnModule(Module &M) {
+ // Add declarations for a pre-defined set of external functions to the module.
+ // The function names must match the functions implemented in native code (in
+ // pnacl/support). The function types must match the types of the LLVM
+ // intrinsics.
+ // We expect these declarations not to exist in the module before this pass
+ // runs, but don't assert it; it will be handled by the ABI verifier.
+ LLVMContext &C = M.getContext();
+ M.getOrInsertFunction("setjmp",
+ // return type
+ Type::getInt32Ty(C),
+ // arguments
+ Type::getInt8Ty(C)->getPointerTo(),
+ NULL);
+ M.getOrInsertFunction("longjmp",
+ // return type
+ Type::getVoidTy(C),
+ // arguments
+ Type::getInt8Ty(C)->getPointerTo(),
+ Type::getInt32Ty(C),
+ NULL);
+ return true;
+}
+
+char AddPNaClExternalDecls::ID = 0;
+INITIALIZE_PASS(AddPNaClExternalDecls, "add-pnacl-external-decls",
+ "Add declarations of external functions used by PNaCl",
+ false, false)
+
+ModulePass *llvm::createAddPNaClExternalDeclsPass() {
+ return new AddPNaClExternalDecls();
+}
diff --git a/lib/Transforms/NaCl/CMakeLists.txt b/lib/Transforms/NaCl/CMakeLists.txt
index a98d929f83..14225d79b8 100644
--- a/lib/Transforms/NaCl/CMakeLists.txt
+++ b/lib/Transforms/NaCl/CMakeLists.txt
@@ -1,4 +1,7 @@
+set(LLVM_LINK_COMPONENTS ipo)
+
add_llvm_library(LLVMNaClTransforms
+ AddPNaClExternalDecls.cpp
ExpandByVal.cpp
ExpandConstantExpr.cpp
ExpandCtors.cpp
@@ -14,6 +17,7 @@ add_llvm_library(LLVMNaClTransforms
PNaClABISimplify.cpp
PromoteIntegers.cpp
ReplacePtrsWithInts.cpp
+ ResolvePNaClIntrinsics.cpp
RewritePNaClLibraryCalls.cpp
StripMetadata.cpp
)
diff --git a/lib/Transforms/NaCl/ResolvePNaClIntrinsics.cpp b/lib/Transforms/NaCl/ResolvePNaClIntrinsics.cpp
new file mode 100644
index 0000000000..e4efeb67c3
--- /dev/null
+++ b/lib/Transforms/NaCl/ResolvePNaClIntrinsics.cpp
@@ -0,0 +1,100 @@
+//===- ResolvePNaClIntrinsics.cpp - Resolve calls to PNaCl intrinsics ----====//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This pass resolves calls to PNaCl stable bitcode intrinsics. It is
+// normally run in the PNaCl translator.
+//
+// Running AddPNaClExternalDeclsPass is a precondition for running this pass.
+// They are separate because one is a ModulePass and the other is a
+// FunctionPass.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/NaCl.h"
+
+using namespace llvm;
+
+namespace {
+ class ResolvePNaClIntrinsics : public FunctionPass {
+ public:
+ ResolvePNaClIntrinsics() : FunctionPass(ID) {
+ initializeResolvePNaClIntrinsicsPass(*PassRegistry::getPassRegistry());
+ }
+
+ static char ID;
+ virtual bool runOnFunction(Function &F);
+ private:
+ // Some intrinsic calls are resolved simply by replacing the call with a
+ // call to an alternative function with exactly the same type.
+ bool resolveSimpleCall(Function &F, Intrinsic::ID IntrinsicID,
+ const char *TargetFunctionName);
+ };
+}
+
+bool ResolvePNaClIntrinsics::resolveSimpleCall(Function &F,
+ Intrinsic::ID IntrinsicID,
+ const char *TargetFunctionName) {
+ Module *M = F.getParent();
+ bool Changed = false;
+ Function *IntrinsicFunction = Intrinsic::getDeclaration(M, IntrinsicID);
+
+ if (!IntrinsicFunction) {
+ return false;
+ }
+
+ // Expect to find the target function for this intrinsic already declared
+ Function *TargetFunction = M->getFunction(TargetFunctionName);
+ if (!TargetFunction) {
+ report_fatal_error(
+ std::string("Expected to find external declaration of ") +
+ TargetFunctionName);
+ }
+
+ for (Value::use_iterator UI = IntrinsicFunction->use_begin(),
+ UE = IntrinsicFunction->use_end(); UI != UE;) {
+ // At this point, the only uses of the intrinsic can be calls, since
+ // we assume this pass runs on bitcode that passed ABI verification.
+ CallInst *Call = dyn_cast<CallInst>(*UI++);
+
+ if (!Call) {
+ report_fatal_error(
+ std::string("Expected use of intrinsic to be a call: ") +
+ Intrinsic::getName(IntrinsicID));
+ }
+
+ // To be a well-behaving FunctionPass, don't touch uses in other
+ // functions. These will be handled when the pass manager gets to those
+ // functions.
+ if (Call->getParent()->getParent() == &F) {
+ Call->setCalledFunction(TargetFunction);
+ Changed = true;
+ }
+ }
+
+ return Changed;
+}
+
+bool ResolvePNaClIntrinsics::runOnFunction(Function &F) {
+ bool Changed = resolveSimpleCall(F, Intrinsic::nacl_setjmp, "setjmp");
+ Changed |= resolveSimpleCall(F, Intrinsic::nacl_longjmp, "longjmp");
+ return Changed;
+}
+
+char ResolvePNaClIntrinsics::ID = 0;
+INITIALIZE_PASS(ResolvePNaClIntrinsics, "resolve-pnacl-intrinsics",
+ "Resolve PNaCl intrinsic calls", false, false)
+
+FunctionPass *llvm::createResolvePNaClIntrinsicsPass() {
+ return new ResolvePNaClIntrinsics();
+}
diff --git a/test/NaCl/ARM/nacl-setlongjmp-intrinsics.ll b/test/NaCl/ARM/nacl-setlongjmp-intrinsics.ll
index 73251d10f3..e0854db4ff 100644
--- a/test/NaCl/ARM/nacl-setlongjmp-intrinsics.ll
+++ b/test/NaCl/ARM/nacl-setlongjmp-intrinsics.ll
@@ -10,7 +10,7 @@ define void @foo(i8* %arg) {
%num = call i32 @llvm.nacl.setjmp(i8* %arg)
; ARM: bl setjmp
- call void @llvm.nacl.longjmp(i8* %arg, i32 %num)
+ call void @llvm.nacl.longjmp(i8* %arg, i32 %num)
; ARM: bl longjmp
ret void
diff --git a/test/NaCl/X86/nacl-setlongjmp-intrinsics.ll b/test/NaCl/X86/nacl-setlongjmp-intrinsics.ll
index fa827a2758..ac595d613a 100644
--- a/test/NaCl/X86/nacl-setlongjmp-intrinsics.ll
+++ b/test/NaCl/X86/nacl-setlongjmp-intrinsics.ll
@@ -10,7 +10,7 @@ define void @foo(i8* %arg) {
%num = call i32 @llvm.nacl.setjmp(i8* %arg)
; X86: naclcall setjmp
- call void @llvm.nacl.longjmp(i8* %arg, i32 %num)
+ call void @llvm.nacl.longjmp(i8* %arg, i32 %num)
; X86: naclcall longjmp
ret void
diff --git a/test/Transforms/NaCl/add-pnacl-external-decls.ll b/test/Transforms/NaCl/add-pnacl-external-decls.ll
new file mode 100644
index 0000000000..1f525a9268
--- /dev/null
+++ b/test/Transforms/NaCl/add-pnacl-external-decls.ll
@@ -0,0 +1,6 @@
+; RUN: opt < %s -add-pnacl-external-decls -S | FileCheck %s
+
+declare void @foobar(i32)
+
+; CHECK: declare i32 @setjmp(i8*)
+; CHECK: declare void @longjmp(i8*, i32)
diff --git a/test/Transforms/NaCl/resolve-pnacl-intrinsics.ll b/test/Transforms/NaCl/resolve-pnacl-intrinsics.ll
new file mode 100644
index 0000000000..3aa263fa9a
--- /dev/null
+++ b/test/Transforms/NaCl/resolve-pnacl-intrinsics.ll
@@ -0,0 +1,25 @@
+; RUN: opt < %s -resolve-pnacl-intrinsics -S | FileCheck %s
+
+declare i32 @llvm.nacl.setjmp(i8*)
+declare void @llvm.nacl.longjmp(i8*, i32)
+
+; These declarations must be here because the function pass expects
+; to find them. In real life they're inserted by the translator
+; before the function pass runs.
+declare i32 @setjmp(i8*)
+declare void @longjmp(i8*, i32)
+
+; CHECK-NOT: call i32 @llvm.nacl.setjmp
+; CHECK-NOT: call void @llvm.nacl.longjmp
+
+define i32 @call_setjmp(i8* %arg) {
+ %val = call i32 @llvm.nacl.setjmp(i8* %arg)
+; CHECK: %val = call i32 @setjmp(i8* %arg)
+ ret i32 %val
+}
+
+define void @call_longjmp(i8* %arg, i32 %num) {
+ call void @llvm.nacl.longjmp(i8* %arg, i32 %num)
+; CHECK: call void @longjmp(i8* %arg, i32 %num)
+ ret void
+}
diff --git a/tools/llc/llc.cpp b/tools/llc/llc.cpp
index 64bb6991d8..0fcd1f3c06 100644
--- a/tools/llc/llc.cpp
+++ b/tools/llc/llc.cpp
@@ -15,7 +15,7 @@
#include "llvm/IR/LLVMContext.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Analysis/NaCl.h"
+#include "llvm/Analysis/NaCl.h" // @LOCALMOD
#include "llvm/Assembly/PrintModulePass.h"
#include "llvm/Support/DataStream.h" // @LOCALMOD
#include "llvm/CodeGen/CommandFlags.h"
@@ -33,6 +33,7 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/IRReader.h"
#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Transforms/NaCl.h" // @LOCALMOD
#if !defined(__native_client__)
#include "llvm/Support/PluginLoader.h"
#endif
@@ -392,6 +393,7 @@ static int compileModule(char **argv, LLVMContext &Context) {
VerifyPass->runOnModule(*mod);
CheckABIVerifyErrors(ABIErrorReporter, "Module");
}
+
#if defined(__native_client__) && defined(NACL_SRPC)
RecordMetadataForSrpc(*mod);
@@ -413,6 +415,19 @@ static int compileModule(char **argv, LLVMContext &Context) {
if (!TargetTriple.empty())
mod->setTargetTriple(Triple::normalize(TargetTriple));
TheTriple = Triple(mod->getTargetTriple());
+
+ // @LOCALMOD-BEGIN
+ // Add declarations for external functions required by PNaCl. The
+ // ResolvePNaClIntrinsics function pass running during streaming
+ // depends on these declarations being in the module.
+ if (TheTriple.isOSNaCl()) {
+ // TODO(eliben): pnacl-llc presumably won't need the isOSNaCl
+ // test.
+ OwningPtr<ModulePass> AddPNaClExternalDeclsPass(
+ createAddPNaClExternalDeclsPass());
+ AddPNaClExternalDeclsPass->runOnModule(*mod);
+ }
+ // @LOCALMOD-END
} else {
TheTriple = Triple(Triple::normalize(TargetTriple));
}
@@ -525,6 +540,12 @@ static int compileModule(char **argv, LLVMContext &Context) {
FunctionVerifyPass = createPNaClABIVerifyFunctionsPass(&ABIErrorReporter);
PM->add(FunctionVerifyPass);
}
+
+ if (TheTriple.isOSNaCl()) {
+ // Add the intrinsic resolution pass. It assumes ABI-conformant code.
+ PM->add(createResolvePNaClIntrinsicsPass());
+ }
+
// @LOCALMOD-END
// Add an appropriate TargetLibraryInfo pass for the module's triple.
diff --git a/tools/opt/opt.cpp b/tools/opt/opt.cpp
index 35e18d02ad..f12c36a7c7 100644
--- a/tools/opt/opt.cpp
+++ b/tools/opt/opt.cpp
@@ -598,6 +598,7 @@ int main(int argc, char **argv) {
initializeInstrumentation(Registry);
initializeTarget(Registry);
// @LOCALMOD-BEGIN
+ initializeAddPNaClExternalDeclsPass(Registry);
initializeExpandByValPass(Registry);
initializeExpandConstantExprPass(Registry);
initializeExpandCtorsPass(Registry);
@@ -614,6 +615,7 @@ int main(int argc, char **argv) {
initializePromoteIntegersPass(Registry);
initializeReplacePtrsWithIntsPass(Registry);
initializeResolveAliasesPass(Registry);
+ initializeResolvePNaClIntrinsicsPass(Registry);
initializeRewritePNaClLibraryCallsPass(Registry);
initializeStripMetadataPass(Registry);
// @LOCALMOD-END
diff --git a/tools/pnacl-llc/pnacl-llc.cpp b/tools/pnacl-llc/pnacl-llc.cpp
index f75bada099..060c1b6c94 100644
--- a/tools/pnacl-llc/pnacl-llc.cpp
+++ b/tools/pnacl-llc/pnacl-llc.cpp
@@ -38,6 +38,7 @@
#include "llvm/Support/ToolOutputFile.h"
#include "llvm/Target/TargetLibraryInfo.h"
#include "llvm/Target/TargetMachine.h"
+#include "llvm/Transforms/NaCl.h"
#include <memory>
@@ -326,6 +327,14 @@ static int compileModule(char **argv, LLVMContext &Context) {
VerifyPass->runOnModule(*mod);
CheckABIVerifyErrors(ABIErrorReporter, "Module");
}
+
+ // Add declarations for external functions required by PNaCl. The
+ // ResolvePNaClIntrinsics function pass running during streaming
+ // depends on these declarations being in the module.
+ OwningPtr<ModulePass> AddPNaClExternalDeclsPass(
+ createAddPNaClExternalDeclsPass());
+ AddPNaClExternalDeclsPass->runOnModule(*mod);
+
#if defined(__native_client__) && defined(NACL_SRPC)
// Record that this isn't a shared library.
// TODO(eliben): clean this up more once the pnacl-llc switch-over is
@@ -462,6 +471,10 @@ static int compileModule(char **argv, LLVMContext &Context) {
FunctionVerifyPass = createPNaClABIVerifyFunctionsPass(&ABIErrorReporter);
PM->add(FunctionVerifyPass);
}
+
+ // Add the intrinsic resolution pass. It assumes ABI-conformant code.
+ PM->add(createResolvePNaClIntrinsicsPass());
+
// @LOCALMOD-END
// Add an appropriate TargetLibraryInfo pass for the module's triple.