diff --git a/src/liboslexec/llvm_headers.h b/src/liboslexec/llvm_headers.h
index c324634..4024e8c 100644
--- a/src/liboslexec/llvm_headers.h
+++ b/src/liboslexec/llvm_headers.h
@@ -48,7 +48,11 @@ namespace llvm = LLVM_NAMESPACE;
 # include <llvm/ExecutionEngine/JIT.h>
 # include <llvm/ExecutionEngine/JITMemoryManager.h>
 # include <llvm/Linker.h>
-# include <llvm/PassManager.h>
+# if OSL_LLVM_VERSION >= 34
+#   include <llvm/IR/LegacyPassManager.h>
+# else
+#   include <llvm/PassManager.h>
+# endif
 # include <llvm/Support/ManagedStatic.h>
 # include <llvm/Support/MemoryBuffer.h>
 # include <llvm/Support/raw_ostream.h>
diff --git a/src/liboslexec/llvm_instance.cpp b/src/liboslexec/llvm_instance.cpp
index 90ffa0e..20c4205 100644
--- a/src/liboslexec/llvm_instance.cpp
+++ b/src/liboslexec/llvm_instance.cpp
@@ -1119,6 +1119,7 @@ public:
     virtual void deallocateFunctionBody(void *Body) {
         // DON'T DEALLOCATE mm->deallocateFunctionBody (Body);
     }
+#if OSL_LLVM_VERSION <= 33
     virtual uint8_t* startExceptionTable(const llvm::Function* F,
                                          uintptr_t &ActualSize) {
         return mm->startExceptionTable (F, ActualSize);
@@ -1130,6 +1131,7 @@ public:
     virtual void deallocateExceptionTable(void *ET) {
         // DON'T DEALLOCATE mm->deallocateExceptionTable(ET);
     }
+#endif
     virtual bool CheckInvariants(std::string &s) {
         return mm->CheckInvariants(s);
     }
@@ -1145,7 +1147,41 @@ public:
     virtual unsigned GetNumCodeSlabs() { return mm->GetNumCodeSlabs(); }
     virtual unsigned GetNumDataSlabs() { return mm->GetNumDataSlabs(); }
     virtual unsigned GetNumStubSlabs() { return mm->GetNumStubSlabs(); }
-#if OSL_LLVM_VERSION >= 31
+
+#if OSL_LLVM_VERSION >= 34
+
+    virtual void *getPointerToNamedFunction(const std::string &Name,
+                                            bool AbortOnFailure = true) {
+        return mm->getPointerToNamedFunction (Name, AbortOnFailure);
+    }
+    virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+                             unsigned SectionID, llvm::StringRef SectionName) {
+        return mm->allocateCodeSection(Size, Alignment, SectionID, SectionName);
+    }
+    virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
+                             unsigned SectionID, llvm::StringRef SectionName,
+                             bool IsReadOnly) {
+        return mm->allocateDataSection(Size, Alignment, SectionID,
+                                       SectionName, IsReadOnly);
+    }
+    virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
+        mm->registerEHFrames (Addr, LoadAddr, Size);
+    }
+    virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) {
+        mm->deregisterEHFrames(Addr, LoadAddr, Size);
+    }
+    virtual uint64_t getSymbolAddress(const std::string &Name) {
+        return mm->getSymbolAddress (Name);
+    }
+    virtual void notifyObjectLoaded(llvm::ExecutionEngine *EE, const llvm::ObjectImage *oi) {
+        mm->notifyObjectLoaded (EE, oi);
+    }
+    virtual bool finalizeMemory(std::string *ErrMsg = 0) {
+        return mm->finalizeMemory (ErrMsg);
+    }
+
+#elif OSL_LLVM_VERSION == 33
+
     virtual void *getPointerToNamedFunction(const std::string &Name,
                                             bool AbortOnFailure = true) {
         return mm->getPointerToNamedFunction (Name, AbortOnFailure);
@@ -1154,7 +1190,6 @@ public:
                                          unsigned SectionID) {
         return mm->allocateCodeSection(Size, Alignment, SectionID);
     }
-#if OSL_LLVM_VERSION >= 33
     virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
                                          unsigned SectionID, bool IsReadOnly) {
         return mm->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
@@ -1162,12 +1197,22 @@ public:
     virtual bool applyPermissions(std::string *ErrMsg = 0) {
         return mm->applyPermissions(ErrMsg);
     }
-#else
+
+#elif OSL_LLVM_VERSION == 32 || OSL_LLVM_VERSION == 31
+
+    virtual void *getPointerToNamedFunction(const std::string &Name,
+                                            bool AbortOnFailure = true) {
+        return mm->getPointerToNamedFunction (Name, AbortOnFailure);
+    }
+    virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
+                                         unsigned SectionID) {
+        return mm->allocateCodeSection(Size, Alignment, SectionID);
+    }
     virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
                                          unsigned SectionID) {
         return mm->allocateDataSection(Size, Alignment, SectionID);
     }
-#endif
+
 #endif
 };
 
@@ -1417,7 +1462,12 @@ ShadingSystemImpl::SetupLLVM ()
     // Some global LLVM initialization for the first thread that
     // gets here.
     info ("Setting up LLVM");
+
+#if OSL_LLVM_VERSION <= 33
+    // Starting with LLVM 3.4, the pretty stack trace was opt-in rather
+    // than opt-out, and the following variable was removed.
     llvm::DisablePrettyStackTrace = true;
+#endif
     llvm::llvm_start_multithreaded ();  // enable it to be thread-safe
     llvm::InitializeNativeTarget();
     done = true;
@@ -1432,8 +1482,14 @@ RuntimeOptimizer::llvm_setup_optimization_passes ()
 
     // Specify per-function passes
     //
+#if OSL_LLVM_VERSION >= 34
+    m_llvm_func_passes = new llvm::legacy::FunctionPassManager(llvm_module());
+    llvm::legacy::FunctionPassManager &fpm (*m_llvm_func_passes);
+    fpm.add (new llvm::DataLayout(llvm_module()));
+#else
     m_llvm_func_passes = new llvm::FunctionPassManager(llvm_module());
     llvm::FunctionPassManager &fpm (*m_llvm_func_passes);
+#endif
 #if OSL_LLVM_VERSION >= 32
     fpm.add (new llvm::DataLayout(llvm_module()));
 #else
@@ -1442,8 +1498,14 @@ RuntimeOptimizer::llvm_setup_optimization_passes ()
 
     // Specify module-wide (interprocedural optimization) passes
     //
+#if OSL_LLVM_VERSION >= 34
+    m_llvm_passes = new llvm::legacy::PassManager;
+    llvm::legacy::PassManager &passes (*m_llvm_passes);
+    passes.add (new llvm::DataLayout(llvm_module()));
+#else
     m_llvm_passes = new llvm::PassManager;
     llvm::PassManager &passes (*m_llvm_passes);
+#endif
 #if OSL_LLVM_VERSION >= 32
     passes.add (new llvm::DataLayout(llvm_module()));
 #else
diff --git a/src/liboslexec/oslexec_pvt.h b/src/liboslexec/oslexec_pvt.h
index 2ca2800..000d9f5 100644
--- a/src/liboslexec/oslexec_pvt.h
+++ b/src/liboslexec/oslexec_pvt.h
@@ -57,12 +57,19 @@ using namespace OSL::pvt;
 namespace llvm {
   class ExecutionEngine;
   class Function;
-  class FunctionPassManager;
   class LLVMContext;
   class Linker;
   class Module;
-  class PassManager;
   class JITMemoryManager;
+#if OSL_LLVM_VERSION >= 34
+  namespace legacy {
+    class FunctionPassManager;
+    class PassManager;
+  }
+#else
+  class FunctionPassManager;
+  class PassManager;
+#endif
 }
 
 using OIIO::atomic_int;
diff --git a/src/liboslexec/runtimeoptimize.h b/src/liboslexec/runtimeoptimize.h
index d25cf46..fb10cf6 100644
--- a/src/liboslexec/runtimeoptimize.h
+++ b/src/liboslexec/runtimeoptimize.h
@@ -968,8 +968,13 @@ private:
     llvm::Type *m_llvm_type_closure_component_attr; // LLVM type for ClosureMeta::Attr
     llvm::PointerType *m_llvm_type_prepare_closure_func;
     llvm::PointerType *m_llvm_type_setup_closure_func;
+#if OSL_LLVM_VERSION >= 34
+    llvm::legacy::PassManager *m_llvm_passes;
+    llvm::legacy::FunctionPassManager *m_llvm_func_passes;
+#else
     llvm::PassManager *m_llvm_passes;
     llvm::FunctionPassManager *m_llvm_func_passes;
+#endif
     int m_llvm_local_mem;             // Amount of memory we use for locals
 
     // Persistant data shared between layers
