Fixed instruction corruption bug for multiple returns.

BUG=https://bugs.chromium.org/p/nativeclient/issues/detail?id=4374
R=kschimpf@google.com

Review URL: https://codereview.chromium.org/2128643002 .
diff --git a/pydir/szbuild.py b/pydir/szbuild.py
index 7333729..3e1722b 100755
--- a/pydir/szbuild.py
+++ b/pydir/szbuild.py
@@ -266,11 +266,6 @@
     args = argparser.parse_args()
     pexe = args.pexe
     exe = args.output
-    if args.asan:
-        if args.sandbox or args.nonsfi:
-            print 'Can only use AddressSanitizer with a native build'
-            exit(1)
-        args.sz_args.append('-fsanitize-address')
     ProcessPexe(args, pexe, exe)
 
 def ProcessPexe(args, pexe, exe):
@@ -307,6 +302,12 @@
     opt_level_map = { 'm1':'0', '-1':'0', '0':'0', '1':'1', '2':'2' }
     hybrid = args.include or args.exclude
     native = not args.sandbox and not args.nonsfi
+    if args.asan:
+        if args.sandbox or args.nonsfi:
+            print 'Can only use AddressSanitizer with a native build'
+            exit(1)
+        if '-fsanitize-address' not in args.sz_args:
+          args.sz_args.append('-fsanitize-address')
 
     if hybrid and (args.force or
                    NewerThanOrNotThere(pexe, obj_llc) or
diff --git a/src/IceASanInstrumentation.cpp b/src/IceASanInstrumentation.cpp
index bc519bf..a7551a8 100644
--- a/src/IceASanInstrumentation.cpp
+++ b/src/IceASanInstrumentation.cpp
@@ -64,7 +64,6 @@
 void ASanInstrumentation::instrumentGlobals(VariableDeclarationList &Globals) {
   if (DidProcessGlobals)
     return;
-
   VariableDeclarationList NewGlobals;
   // Global holding pointers to all redzones
   auto *RzArray = VariableDeclaration::create(&NewGlobals);
@@ -147,7 +146,6 @@
 void ASanInstrumentation::instrumentFuncStart(LoweringContext &Context) {
   if (ICE_TLS_GET_FIELD(LocalDtors) == nullptr)
     ICE_TLS_SET_FIELD(LocalDtors, new std::vector<InstCall *>());
-
   Cfg *Func = Context.getNode()->getCfg();
   bool HasLocals = false;
   LoweringContext C;
@@ -294,10 +292,21 @@
 }
 
 void ASanInstrumentation::instrumentRet(LoweringContext &Context, InstRet *) {
+  Cfg *Func = Context.getNode()->getCfg();
   InstList::iterator Next = Context.getNext();
   Context.setInsertPoint(Context.getCur());
   for (InstCall *RzUnpoison : *ICE_TLS_GET_FIELD(LocalDtors)) {
-    Context.insert(RzUnpoison);
+    SizeT NumArgs = RzUnpoison->getNumArgs();
+    Variable *Dest = RzUnpoison->getDest();
+    Operand *CallTarget = RzUnpoison->getCallTarget();
+    bool HasTailCall = RzUnpoison->isTailcall();
+    bool IsTargetHelperCall = RzUnpoison->isTargetHelperCall();
+    auto *RzUnpoisonCpy = InstCall::create(Func, NumArgs, Dest, CallTarget,
+                                           HasTailCall, IsTargetHelperCall);
+    for (int I = 0, Args = RzUnpoison->getNumArgs(); I < Args; ++I) {
+      RzUnpoisonCpy->addArg(RzUnpoison->getArg(I));
+    }
+    Context.insert(RzUnpoisonCpy);
   }
   Context.setNext(Next);
 }
diff --git a/tests_lit/asan_tests/multiple_returns.ll b/tests_lit/asan_tests/multiple_returns.ll
new file mode 100644
index 0000000..5575c4b
--- /dev/null
+++ b/tests_lit/asan_tests/multiple_returns.ll
@@ -0,0 +1,42 @@
+; Check that functions with multiple returns are correctly instrumented
+
+; REQUIRES: allow_dump
+
+; RUN: %p2i -i %s --args -verbose=inst -threads=0 -fsanitize-address \
+; RUN:     | FileCheck --check-prefix=DUMP %s
+
+define internal void @ret_twice(i32 %condarg) {
+  %local1 = alloca i8, i32 4, align 4
+  %local2 = alloca i8, i32 4, align 4
+  %cond = icmp ne i32 %condarg, 0
+  br i1 %cond, label %yes, label %no
+yes:
+  ret void
+no:
+  ret void
+}
+
+; DUMP-LABEL: ================ Instrumented CFG ================
+; DUMP-NEXT: define internal void @ret_twice(i32 %condarg) {
+; DUMP-NEXT: __0:
+; DUMP-NEXT:   %local1 = alloca i8, i32 64, align 8
+; DUMP-NEXT:   %local2 = alloca i8, i32 64, align 8
+; DUMP-NEXT:   %__$rz2 = alloca i8, i32 32, align 8
+; DUMP-NEXT:   call void @__asan_poison(i32 %__$rz2, i32 32)
+; DUMP-NEXT:   %__$rz0 = add i32 %local1, 4
+; DUMP-NEXT:   call void @__asan_poison(i32 %__$rz0, i32 60)
+; DUMP-NEXT:   %__$rz1 = add i32 %local2, 4
+; DUMP-NEXT:   call void @__asan_poison(i32 %__$rz1, i32 60)
+; DUMP-NEXT:   %cond = icmp ne i32 %condarg, 0
+; DUMP-NEXT:   br i1 %cond, label %yes, label %no
+; DUMP-NEXT: yes:
+; DUMP-NEXT:   call void @__asan_unpoison(i32 %__$rz0, i32 60)
+; DUMP-NEXT:   call void @__asan_unpoison(i32 %__$rz1, i32 60)
+; DUMP-NEXT:   call void @__asan_unpoison(i32 %__$rz2, i32 32)
+; DUMP-NEXT:   ret void
+; DUMP-NEXT: no:
+; DUMP-NEXT:   call void @__asan_unpoison(i32 %__$rz0, i32 60)
+; DUMP-NEXT:   call void @__asan_unpoison(i32 %__$rz1, i32 60)
+; DUMP-NEXT:   call void @__asan_unpoison(i32 %__$rz2, i32 32)
+; DUMP-NEXT:   ret void
+; DUMP-NEXT: }
\ No newline at end of file
diff --git a/tests_lit/asan_tests/wideloads.ll b/tests_lit/asan_tests/wideloads.ll
index 626a757..50a9975 100644
--- a/tests_lit/asan_tests/wideloads.ll
+++ b/tests_lit/asan_tests/wideloads.ll
@@ -5,7 +5,7 @@
 ; check for wide load exception
 ; RUN: llvm-as %s -o - | pnacl-freeze > %t.pexe && %S/../../pydir/szbuild.py \
 ; RUN:     --fsanitize-address --sz="-allow-externally-defined-symbols" \
-; RUN:     %t.pexe -o %t && %t | FileCheck %s --check-prefix=WIDE
+; RUN:     %t.pexe -o %t && %t | FileCheck %s --check-prefix=WIDE --allow-empty
 
 ; check for error reporting
 ; RUN: llvm-as %s -o - | pnacl-freeze > %t.pexe && %S/../../pydir/szbuild.py \