diff --git a/emscripten-version.txt b/emscripten-version.txt
index 7b4009ac531..3f5f9c3ae64 100644
--- a/emscripten-version.txt
+++ b/emscripten-version.txt
@@ -1,2 +1,2 @@
-1.32.0
+1.32.1
 
diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp
index 1fade5ea929..018f4181387 100644
--- a/lib/Target/JSBackend/JSBackend.cpp
+++ b/lib/Target/JSBackend/JSBackend.cpp
@@ -160,9 +160,11 @@ namespace {
     FunctionTableMap FunctionTables; // sig => list of functions
     std::vector<std::string> GlobalInitializers;
     std::vector<std::string> Exports; // additional exports
+    StringMap Aliases;
     BlockAddressMap BlockAddresses;
     NameIntMap AsmConsts;
     IntSet AsmConstArities;
+    NameSet BlockRelocatableExterns; // which externals are accessed in this block; we load them once at the beginning (avoids a potential call in a heap access, and might be faster)
 
     std::string CantValidate;
     bool UsesSIMD;
@@ -382,6 +384,7 @@ namespace {
             // All postsets are of external values, so they are pointers, hence 32-bit
             std::string Name = getOpName(V);
             Externals.insert(Name);
+            if (Relocatable) Name = "g$" + Name + "() | 0"; // we access linked externs through calls
             PostSets += "\n HEAP32[" + relocateGlobal(utostr(AbsoluteTarget)) + " >> 2] = " + Name + ';';
             return 0; // emit zero in there for now, until the postSet
           } else if (Relocatable) {
@@ -1093,6 +1096,11 @@ std::string JSWriter::getConstant(const Constant* CV, AsmCast sign) {
     if (GV->isDeclaration()) {
       std::string Name = getOpName(GV);
       Externals.insert(Name);
+      if (Relocatable) {
+        // we access linked externs through calls, which we load at the beginning of basic blocks
+        BlockRelocatableExterns.insert(Name);
+        Name = "t$" + Name;
+      }
       return Name;
     }
     if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(CV)) {
@@ -2283,6 +2291,18 @@ void JSWriter::addBlock(const BasicBlock *BB, Relooper& R, LLVMToRelooperMap& LL
     }
   }
   CodeStream.flush();
+  if (Relocatable) {
+    // add code to load externals once at the beginning
+    if (BlockRelocatableExterns.size() > 0) {
+      for (auto& RE : BlockRelocatableExterns) {
+        std::string Temp = "t$" + RE;
+        std::string Call = "g$" + RE;
+        UsedVars[Temp] = Type::getInt32Ty(BB->getContext());
+        Code = Temp + " = " + Call + "() | 0; " + Code;
+      }
+      BlockRelocatableExterns.clear();
+    }
+  }
   const Value* Condition = considerConditionVar(BB->getTerminator());
   Block *Curr = new Block(Code.c_str(), Condition ? getValueAsCastStr(Condition).c_str() : NULL);
   LLVMToRelooper[BB] = Curr;
@@ -2565,6 +2585,16 @@ void JSWriter::printFunction(const Function *F) {
 void JSWriter::printModuleBody() {
   processConstants();
 
+  if (Relocatable) {
+    for (Module::const_alias_iterator I = TheModule->alias_begin(), E = TheModule->alias_end();
+         I != E; ++I) {
+      if (const GlobalAlias *GA = dyn_cast<GlobalAlias>(I)) {
+        const Value* Target = resolveFully(GA);
+        Aliases[getJSName(GA)] = getJSName(Target);
+      }
+    }
+  }
+
   // Emit function bodies.
   nl(Out) << "// EMSCRIPTEN_START_FUNCTIONS"; nl(Out);
   for (Module::const_iterator I = TheModule->begin(), E = TheModule->end();
@@ -2726,6 +2756,19 @@ void JSWriter::printModuleBody() {
   }
   Out << "],";
 
+  Out << "\"aliases\": {";
+  first = true;
+  for (StringMap::const_iterator I = Aliases.begin(), E = Aliases.end();
+       I != E; ++I) {
+    if (first) {
+      first = false;
+    } else {
+      Out << ", ";
+    }
+    Out << "\"" << I->first << "\": \"" << I->second << "\"";
+  }
+  Out << "},";
+
   Out << "\"cantValidate\": \"" << CantValidate << "\",";
 
   Out << "\"simd\": ";