Add MC-based code generation support (experimental)

This feature is disabled by default.  To enable it, please
open Config.h and change USE_MCJIT from 0 to 1.
diff --git a/lib/ExecutionEngine/Compiler.cpp b/lib/ExecutionEngine/Compiler.cpp
index 2ca2f36..b89c0ce 100644
--- a/lib/ExecutionEngine/Compiler.cpp
+++ b/lib/ExecutionEngine/Compiler.cpp
@@ -21,9 +21,12 @@
 #include "ContextManager.h"
 #include "DebugHelper.h"
 #include "FileHandle.h"
+#include "Runtime.h"
 #include "ScriptCompiled.h"
 #include "Sha1Helper.h"
 
+#include "librsloader.h"
+
 #include "llvm/ADT/StringRef.h"
 
 #include "llvm/Analysis/Passes.h"
@@ -219,20 +222,27 @@
 }
 
 
+#if USE_OLD_JIT
 CodeMemoryManager *Compiler::createCodeMemoryManager() {
   mCodeMemMgr.reset(new CodeMemoryManager());
   return mCodeMemMgr.get();
 }
+#endif
 
 
+#if USE_OLD_JIT
 CodeEmitter *Compiler::createCodeEmitter() {
   mCodeEmitter.reset(new CodeEmitter(mpResult, mCodeMemMgr.get()));
   return mCodeEmitter.get();
 }
+#endif
 
 
 Compiler::Compiler(ScriptCompiled *result)
   : mpResult(result),
+#if USE_MCJIT
+    mRSExecutable(NULL),
+#endif
     mpSymbolLookupFn(NULL),
     mpSymbolLookupContext(NULL),
     mContext(NULL),
@@ -245,6 +255,7 @@
 }
 
 
+#if USE_MCJIT
 // input objPath: For example,
 //                 /data/user/0/com.example.android.rs.fountain/cache/
 //                     @com.example.android.rs.fountain:raw@fountain.oBCC
@@ -269,6 +280,7 @@
   LOGV("objPath = %s", objPath.c_str());
   return true;
 }
+#endif
 
 
 llvm::Module *Compiler::parseBitcodeFile(llvm::MemoryBuffer *MEM) {
@@ -295,40 +307,16 @@
 
 
 int Compiler::compile() {
+  llvm::Target const *Target = NULL;
   llvm::TargetData *TD = NULL;
-
   llvm::TargetMachine *TM = NULL;
-  const llvm::Target *Target;
+
   std::string FeaturesStr;
 
-#if USE_OLD_JIT
-  llvm::FunctionPassManager *CodeGenPasses = NULL;
-#endif
-
-#if USE_MCJIT
-  bool RelaxAll = true;
-  llvm::PassManager MCCodeGenPasses;
-
-  std::string objPath(mCachePath);
-
-  if (!getObjPath(objPath)) {
-    LOGE("Fail to create objPath");
-    return 1;
-  }
-
-  int Fd = -1;
-  FileHandle file;
-
-  Fd = file.open(objPath.c_str(), OpenMode::Write);
-  if (Fd < 0) {
-    LOGE("Fail to open file '%s'", objPath.c_str());
-    return 1;
-  }
-
-  llvm::raw_fd_ostream OutFdOS(Fd, /* shouldClose= */ false);
-  OutFdOS.seek(0);
-  llvm::formatted_raw_ostream OutFOS(OutFdOS);
-#endif
+  llvm::NamedMDNode const *PragmaMetadata;
+  llvm::NamedMDNode const *ExportVarMetadata;
+  llvm::NamedMDNode const *ExportFuncMetadata;
+  llvm::NamedMDNode const *ObjectSlotMetadata;
 
   if (mModule == NULL)  // No module was loaded
     return 0;
@@ -357,10 +345,114 @@
     goto on_bcc_compile_error;
   }
 
+  // Get target data from Module
+  TD = new llvm::TargetData(mModule);
+
+  // Load named metadata
+  ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
+  ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
+  PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
+  ObjectSlotMetadata = mModule->getNamedMetadata(ObjectSlotMetadataName);
+
+  // Perform link-time optimization if we have multiple modules
+  if (mHasLinked) {
+    runLTO(new llvm::TargetData(*TD), ExportVarMetadata, ExportFuncMetadata);
+  }
+
+  // Perform code generation
+#if USE_OLD_JIT
+  if (runCodeGen(new llvm::TargetData(*TD), TM,
+                 ExportVarMetadata, ExportFuncMetadata) != 0) {
+    goto on_bcc_compile_error;
+  }
+#endif
+
+#if USE_MCJIT
+  if (runMCCodeGen(new llvm::TargetData(*TD), TM,
+                   ExportVarMetadata, ExportFuncMetadata) != 0) {
+    goto on_bcc_compile_error;
+  }
+#endif
+
+  // Read pragma information from the metadata node of the module.
+  if (PragmaMetadata) {
+    ScriptCompiled::PragmaList &pragmaList = mpResult->mPragmas;
+
+    for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
+      llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
+      if (Pragma != NULL &&
+          Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
+        llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
+        llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
+
+        if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
+            (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
+          llvm::StringRef PragmaName =
+            static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
+          llvm::StringRef PragmaValue =
+            static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
+
+          pragmaList.push_back(
+            std::make_pair(std::string(PragmaName.data(),
+                                       PragmaName.size()),
+                           std::string(PragmaValue.data(),
+                                       PragmaValue.size())));
+        }
+      }
+    }
+    LOGD("Found %d pragma\n", pragmaList.size());
+  }
+
+  if (ObjectSlotMetadata) {
+    ScriptCompiled::ObjectSlotList &objectSlotList = mpResult->mObjectSlots;
+
+    for (int i = 0, e = ObjectSlotMetadata->getNumOperands(); i != e; i++) {
+      llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
+      if (ObjectSlot != NULL &&
+          ObjectSlot->getNumOperands() == 1) {
+        llvm::Value *SlotMDS = ObjectSlot->getOperand(0);
+        if (SlotMDS->getValueID() == llvm::Value::MDStringVal) {
+          llvm::StringRef Slot =
+              static_cast<llvm::MDString*>(SlotMDS)->getString();
+          uint32_t USlot = 0;
+          if (Slot.getAsInteger(10, USlot)) {
+            setError("Non-integer object slot value '" + Slot.str() + "'");
+            goto on_bcc_compile_error;
+          }
+          objectSlotList.push_back(USlot);
+        }
+      }
+    }
+    LOGD("Found %d object slot\n", objectSlotList.size());
+  }
+
+on_bcc_compile_error:
+  // LOGE("on_bcc_compiler_error");
+  if (TD) {
+    delete TD;
+  }
+
+  if (TM) {
+    delete TM;
+  }
+
+  if (mError.empty()) {
+    return 0;
+  }
+
+  // LOGE(getErrorMessage());
+  return 1;
+}
+
+
+#if USE_OLD_JIT
+int Compiler::runCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
+                         llvm::NamedMDNode const *ExportVarMetadata,
+                         llvm::NamedMDNode const *ExportFuncMetadata) {
   // Create memory manager for creation of code emitter later.
   if (!mCodeMemMgr.get() && !createCodeMemoryManager()) {
     setError("Failed to startup memory management for further compilation");
-    goto on_bcc_compile_error;
+    return 1;
   }
 
   mpResult->mContext = (char *) (mCodeMemMgr.get()->getCodeMemBase());
@@ -368,9 +460,8 @@
   // Create code emitter
   if (!mCodeEmitter.get()) {
     if (!createCodeEmitter()) {
-      setError("Failed to create machine code emitter to complete"
-               " the compilation");
-      goto on_bcc_compile_error;
+      setError("Failed to create machine code emitter for compilation");
+      return 1;
     }
   } else {
     // Reuse the code emitter
@@ -381,65 +472,31 @@
   mCodeEmitter->registerSymbolCallback(mpSymbolLookupFn,
                                        mpSymbolLookupContext);
 
-  // Get target data from Module
-  TD = new llvm::TargetData(mModule);
-
-  // Load named metadata
-  const llvm::NamedMDNode *PragmaMetadata;
-  const llvm::NamedMDNode *ExportVarMetadata;
-  const llvm::NamedMDNode *ExportFuncMetadata;
-  const llvm::NamedMDNode *ObjectSlotMetadata;
-
-  ExportVarMetadata = mModule->getNamedMetadata(ExportVarMetadataName);
-  ExportFuncMetadata = mModule->getNamedMetadata(ExportFuncMetadataName);
-  PragmaMetadata = mModule->getNamedMetadata(PragmaMetadataName);
-  ObjectSlotMetadata = mModule->getNamedMetadata(ObjectSlotMetadataName);
-
-  // Perform Link-time Optimization if we have multiple modules
-  if (mHasLinked) {
-    runLTO(new llvm::TargetData(*TD), ExportVarMetadata, ExportFuncMetadata);
-  }
-
-#if USE_OLD_JIT
   // Create code-gen pass to run the code emitter
-  CodeGenPasses = new llvm::FunctionPassManager(mModule);
-  CodeGenPasses->add(new llvm::TargetData(*TD));
+  llvm::OwningPtr<llvm::FunctionPassManager> CodeGenPasses(
+    new llvm::FunctionPassManager(mModule));
 
+  // Add TargetData to code generation pass manager
+  CodeGenPasses->add(TD);
+
+  // Add code emit passes
   if (TM->addPassesToEmitMachineCode(*CodeGenPasses,
                                      *mCodeEmitter,
                                      CodeGenOptLevel)) {
-    setError("The machine code emission is not supported by BCC on target '"
-             + Triple + "'");
-    goto on_bcc_compile_error;
+    setError("The machine code emission is not supported on '" + Triple + "'");
+    return 1;
   }
 
-  // Run the pass (the code emitter) on every non-declaration function in the
-  // module
+  // Run the code emitter on every non-declaration function in the module
   CodeGenPasses->doInitialization();
-  for (llvm::Module::iterator I = mModule->begin(), E = mModule->end();
-       I != E; I++) {
+  for (llvm::Module::iterator
+       I = mModule->begin(), E = mModule->end(); I != E; I++) {
     if (!I->isDeclaration()) {
       CodeGenPasses->run(*I);
     }
   }
 
   CodeGenPasses->doFinalization();
-#endif
-
-#if USE_MCJIT
-  TM->setMCRelaxAll(RelaxAll);
-
-  MCCodeGenPasses.add(new llvm::TargetData(*TD));
-
-  if (TM->addPassesToEmitFile(MCCodeGenPasses, OutFOS,
-                              llvm::TargetMachine::CGFT_ObjectFile,
-                              CodeGenOptLevel)) {
-    setError("Fail to add passes to emit file");
-    goto on_bcc_compile_error;
-  }
-
-  MCCodeGenPasses.run(*mModule);
-#endif
 
   // Copy the global address mapping from code emitter and remapping
   if (ExportVarMetadata) {
@@ -461,6 +518,7 @@
               continue;
             if (ExportVarName == I->first->getName()) {
               varList.push_back(I->second);
+              LOGD("Exported VAR: %s\n", ExportVarName.str().c_str());
               break;
             }
           }
@@ -488,6 +546,7 @@
           llvm::StringRef ExportFuncName =
             static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
           funcList.push_back(mpResult->lookup(ExportFuncName.str().c_str()));
+          LOGD("Exported Func: %s\n", ExportFuncName.str().c_str());
         }
       }
     }
@@ -497,83 +556,110 @@
   // we have done the code emission
   mCodeEmitter->releaseUnnecessary();
 
-  // Finally, read pragma information from the metadata node of the @Module if
-  // any.
-  if (PragmaMetadata) {
-    ScriptCompiled::PragmaList &pragmaList = mpResult->mPragmas;
-
-    for (int i = 0, e = PragmaMetadata->getNumOperands(); i != e; i++) {
-      llvm::MDNode *Pragma = PragmaMetadata->getOperand(i);
-      if (Pragma != NULL &&
-          Pragma->getNumOperands() == 2 /* should have exactly 2 operands */) {
-        llvm::Value *PragmaNameMDS = Pragma->getOperand(0);
-        llvm::Value *PragmaValueMDS = Pragma->getOperand(1);
-
-        if ((PragmaNameMDS->getValueID() == llvm::Value::MDStringVal) &&
-            (PragmaValueMDS->getValueID() == llvm::Value::MDStringVal)) {
-          llvm::StringRef PragmaName =
-            static_cast<llvm::MDString*>(PragmaNameMDS)->getString();
-          llvm::StringRef PragmaValue =
-            static_cast<llvm::MDString*>(PragmaValueMDS)->getString();
-
-          pragmaList.push_back(
-            std::make_pair(std::string(PragmaName.data(),
-                                       PragmaName.size()),
-                           std::string(PragmaValue.data(),
-                                       PragmaValue.size())));
-        }
-      }
-    }
-  }
-
-  if (ObjectSlotMetadata) {
-    ScriptCompiled::ObjectSlotList &objectSlotList = mpResult->mObjectSlots;
-
-    for (int i = 0, e = ObjectSlotMetadata->getNumOperands(); i != e; i++) {
-      llvm::MDNode *ObjectSlot = ObjectSlotMetadata->getOperand(i);
-      if (ObjectSlot != NULL &&
-          ObjectSlot->getNumOperands() == 1) {
-        llvm::Value *SlotMDS = ObjectSlot->getOperand(0);
-        if (SlotMDS->getValueID() == llvm::Value::MDStringVal) {
-          llvm::StringRef Slot =
-              static_cast<llvm::MDString*>(SlotMDS)->getString();
-          uint32_t USlot = 0;
-          if (Slot.getAsInteger(10, USlot)) {
-            setError("Non-integer object slot value '" + Slot.str() + "'");
-            goto on_bcc_compile_error;
-          }
-          objectSlotList.push_back(USlot);
-        }
-      }
-    }
-  }
-
-on_bcc_compile_error:
-  // LOGE("on_bcc_compiler_error");
-  if (CodeGenPasses) {
-    delete CodeGenPasses;
-  }
-
-  if (TD) {
-    delete TD;
-  }
-
-  if (TM) {
-    delete TM;
-  }
-
-  if (mError.empty()) {
-    return 0;
-  }
-
-  // LOGE(getErrorMessage());
-  return 1;
+  return 0;
 }
+#endif // USE_OLD_JIT
 
 
-void Compiler::runLTO(llvm::TargetData *TD,
-                      llvm::NamedMDNode const *ExportVarMetadata,
-                      llvm::NamedMDNode const *ExportFuncMetadata) {
+#if USE_MCJIT
+int Compiler::runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
+                           llvm::NamedMDNode const *ExportVarMetadata,
+                           llvm::NamedMDNode const *ExportFuncMetadata) {
+  // Decorate mEmittedELFExecutable with formatted ostream
+  llvm::raw_svector_ostream OutSVOS(mEmittedELFExecutable);
+
+  // Relax all machine instructions
+  TM->setMCRelaxAll(/* RelaxAll= */ true);
+
+  // Create MC code generation pass manager
+  llvm::PassManager MCCodeGenPasses;
+
+  // Add TargetData to MC code generation pass manager
+  MCCodeGenPasses.add(TD);
+
+  // Add MC code generation passes to pass manager
+  llvm::MCContext *Ctx;
+  if (TM->addPassesToEmitMC(MCCodeGenPasses, Ctx, OutSVOS,
+                            CodeGenOptLevel, false)) {
+    setError("Fail to add passes to emit file");
+    return 1;
+  }
+
+  MCCodeGenPasses.run(*mModule);
+  OutSVOS.flush();
+
+  // Load the ELF Object
+  mRSExecutable =
+    rsloaderCreateExec((unsigned char *)&*mEmittedELFExecutable.begin(),
+                       mEmittedELFExecutable.size(),
+                       &resolveSymbolAdapter, this);
+
+  if (!mRSExecutable) {
+    setError("Fail to load emitted ELF relocatable file");
+    return 1;
+  }
+
+#if !USE_OLD_JIT
+  // Note: If old JIT is compiled then we prefer the old version instead of the
+  // new version.
+
+  if (ExportVarMetadata) {
+    ScriptCompiled::ExportVarList &varList = mpResult->mExportVars;
+
+    for (int i = 0, e = ExportVarMetadata->getNumOperands(); i != e; i++) {
+      llvm::MDNode *ExportVar = ExportVarMetadata->getOperand(i);
+      if (ExportVar == NULL || ExportVar->getNumOperands() <= 1) {
+        continue;
+      }
+
+      llvm::Value *ExportVarNameMDS = ExportVar->getOperand(0);
+      if (ExportVarNameMDS->getValueID() == llvm::Value::MDStringVal) {
+        llvm::StringRef ExportVarName =
+          static_cast<llvm::MDString*>(ExportVarNameMDS)->getString();
+
+        varList.push_back(
+          rsloaderGetSymbolAddress(mRSExecutable,
+                                   ExportVarName.str().c_str()));
+      }
+    }
+  }
+
+  if (ExportFuncMetadata) {
+    ScriptCompiled::ExportFuncList &funcList = mpResult->mExportFuncs;
+
+    for (int i = 0, e = ExportFuncMetadata->getNumOperands(); i != e; i++) {
+      llvm::MDNode *ExportFunc = ExportFuncMetadata->getOperand(i);
+      if (ExportFunc != NULL && ExportFunc->getNumOperands() > 0) {
+        llvm::Value *ExportFuncNameMDS = ExportFunc->getOperand(0);
+        if (ExportFuncNameMDS->getValueID() == llvm::Value::MDStringVal) {
+          llvm::StringRef ExportFuncName =
+            static_cast<llvm::MDString*>(ExportFuncNameMDS)->getString();
+
+          funcList.push_back(
+            rsloaderGetSymbolAddress(mRSExecutable,
+                                     ExportFuncName.str().c_str()));
+        }
+      }
+    }
+  }
+#endif // !USE_OLD_JIT
+
+#if USE_CACHE
+  // Write generated executable to file.
+  if (writeELFExecToFile() != 0) {
+    setError("Fail to write mcjit-ed executable to file");
+    return 1;
+  }
+#endif
+
+  return 0;
+}
+#endif // USE_MCJIT
+
+
+int Compiler::runLTO(llvm::TargetData *TD,
+                     llvm::NamedMDNode const *ExportVarMetadata,
+                     llvm::NamedMDNode const *ExportFuncMetadata) {
   llvm::PassManager LTOPasses;
 
   // Add TargetData to LTO passes
@@ -694,13 +780,69 @@
   LTOPasses.add(llvm::createGlobalDCEPass());
 
   LTOPasses.run(*mModule);
+
+  return 0;
 }
 
 
+#if USE_MCJIT
+int Compiler::writeELFExecToFile() {
+  std::string objPath(mCachePath);
+  if (!getObjPath(objPath)) {
+    LOGE("Fail to create objPath");
+    return 1;
+  }
+
+  FileHandle file;
+
+  int Fd = file.open(objPath.c_str(), OpenMode::Write);
+  if (Fd < 0) {
+    LOGE("Fail to open file '%s'", objPath.c_str());
+    return 1;
+  }
+
+  file.write(&*mEmittedELFExecutable.begin(), mEmittedELFExecutable.size());
+
+  return 0;
+}
+#endif
+
+
+#if USE_MCJIT
+void *Compiler::getSymbolAddress(char const *name) {
+  return rsloaderGetSymbolAddress(mRSExecutable, name);
+}
+#endif
+
+
+#if USE_MCJIT
+void *Compiler::resolveSymbolAdapter(void *context, char const *name) {
+  Compiler *self = reinterpret_cast<Compiler *>(context);
+
+  if (void *Addr = FindRuntimeFunction(name)) {
+    return Addr;
+  }
+
+  if (self->mpSymbolLookupFn) {
+    if (void *Addr = self->mpSymbolLookupFn(self->mpSymbolLookupContext, name)) {
+      return Addr;
+    }
+  }
+
+  LOGE("Unable to resolve symbol: %s\n", name);
+  return NULL;
+}
+#endif
+
+
 Compiler::~Compiler() {
   delete mModule;
   delete mContext;
 
+#if USE_MCJIT
+  rsloaderDisposeExec(mRSExecutable);
+#endif
+
   // llvm::llvm_shutdown();
 }
 
diff --git a/lib/ExecutionEngine/Compiler.h b/lib/ExecutionEngine/Compiler.h
index 0766eaf..8e9ce98 100644
--- a/lib/ExecutionEngine/Compiler.h
+++ b/lib/ExecutionEngine/Compiler.h
@@ -22,8 +22,11 @@
 #include "CodeEmitter.h"
 #include "CodeMemoryManager.h"
 
+#include "librsloader.h"
+
 #include "llvm/ADT/OwningPtr.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Target/TargetMachine.h"
 
 #include <stddef.h>
@@ -87,11 +90,21 @@
 
     std::string mError;
 
+#if USE_OLD_JIT
     // The memory manager for code emitter
     llvm::OwningPtr<CodeMemoryManager> mCodeMemMgr;
 
     // The CodeEmitter
     llvm::OwningPtr<CodeEmitter> mCodeEmitter;
+#endif
+
+#if USE_MCJIT
+    // Compilation buffer for MCJIT
+    llvm::SmallVector<char, 1024> mEmittedELFExecutable;
+
+    // Loaded and relocated executable
+    RSExecRef mRSExecutable;
+#endif
 
     BCCSymbolLookupFn mpSymbolLookupFn;
     void *mpSymbolLookupContext;
@@ -116,12 +129,18 @@
       mpSymbolLookupContext = pContext;
     }
 
+#if USE_OLD_JIT
     CodeMemoryManager *createCodeMemoryManager();
 
     CodeEmitter *createCodeEmitter();
+#endif
 
+#if USE_MCJIT
     bool getObjPath(std::string &objPath);
 
+    void *getSymbolAddress(char const *name);
+#endif
+
     llvm::Module *parseBitcodeFile(llvm::MemoryBuffer *MEM);
 
     int readModule(llvm::Module *module) {
@@ -145,9 +164,23 @@
 
   private:
 
-    void runLTO(llvm::TargetData *TD,
-                llvm::NamedMDNode const *ExportVarMetadata,
-                llvm::NamedMDNode const *ExportFuncMetadata);
+    int runCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
+                   llvm::NamedMDNode const *ExportVarMetadata,
+                   llvm::NamedMDNode const *ExportFuncMetadata);
+
+    int runMCCodeGen(llvm::TargetData *TD, llvm::TargetMachine *TM,
+                     llvm::NamedMDNode const *ExportVarMetadata,
+                     llvm::NamedMDNode const *ExportFuncMetadata);
+
+#if USE_MCJIT
+    static void *resolveSymbolAdapter(void *context, char const *name);
+#endif
+
+    int runLTO(llvm::TargetData *TD,
+               llvm::NamedMDNode const *ExportVarMetadata,
+               llvm::NamedMDNode const *ExportFuncMetadata);
+
+    int writeELFExecToFile();
 
     bool hasError() const {
       return !mError.empty();
diff --git a/lib/ExecutionEngine/ScriptCompiled.cpp b/lib/ExecutionEngine/ScriptCompiled.cpp
index d38b447..189f94a 100644
--- a/lib/ExecutionEngine/ScriptCompiled.cpp
+++ b/lib/ExecutionEngine/ScriptCompiled.cpp
@@ -90,8 +90,16 @@
 
 
 void *ScriptCompiled::lookup(const char *name) {
+#if USE_OLD_JIT
   FuncInfoMap::const_iterator I = mEmittedFunctions.find(name);
   return (I == mEmittedFunctions.end()) ? NULL : I->second->addr;
+#endif
+
+#if USE_MCJIT
+  return mCompiler.getSymbolAddress(name);
+#endif
+
+  return NULL;
 }