gollvm: fix crash on non-trivial switch case with fallthrough

The code in GenBlocks::genSwitch that handled switch case fallthrough
branches was not properly handling case statements that have internal
control flow (as opposed to being a single basic block).

Change-Id: Id0cecea2422d43cddf5e8f972a5a6786ff4ce62f
Reviewed-on: https://go-review.googlesource.com/48451
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/llvm-gofrontend/go-llvm.cpp b/llvm-gofrontend/go-llvm.cpp
index 9b0766a..e5e804c 100644
--- a/llvm-gofrontend/go-llvm.cpp
+++ b/llvm-gofrontend/go-llvm.cpp
@@ -2561,13 +2561,13 @@
   // Walk statement/block
   for (unsigned idx = 0; idx < ncases; ++idx) {
     Bstatement *st = swst->getSwitchStmtNthStmt(idx);
-    walk(st, blocks[idx]);
-    if (! blocks[idx]->getTerminator()) {
+    llvm::BasicBlock *newblock = walk(st, blocks[idx]);
+    if (newblock && newblock->getTerminator() == nullptr) {
       // The front end inserts a goto statement at the end for
       // non-fallthrough cases. Fall through to the next case
       // otherwise.
       assert(idx < ncases-1);
-      builder.SetInsertPoint(blocks[idx]);
+      builder.SetInsertPoint(newblock);
       builder.CreateBr(blocks[idx+1]);
     }
   }
diff --git a/unittests/BackendCore/BackendStmtTests.cpp b/unittests/BackendCore/BackendStmtTests.cpp
index 1e54203..f127c81 100644
--- a/unittests/BackendCore/BackendStmtTests.cpp
+++ b/unittests/BackendCore/BackendStmtTests.cpp
@@ -340,12 +340,16 @@
   Bstatement *cs1 = be->compound_statement(as1, goto1);
 
   // second case
-  // loc1 = 987 * loc1
+  // loc1 = loc1 < 987 ? loc1 : 987 * loc1
   Bexpression *ve2 = be->var_expression(loc1, VE_lvalue, loc);
   Bexpression *ve2r = be->var_expression(loc1, VE_rvalue, loc);
+  Bexpression *ve2r2 = be->var_expression(loc1, VE_rvalue, loc);
+  Bexpression *ve2r3 = be->var_expression(loc1, VE_rvalue, loc);
   Bexpression *c987 = mkInt64Const(be, 987);
   Bexpression *mul = be->binary_expression(OPERATOR_MULT, c987, ve2r, loc);
-  Bstatement *as2 = be->assignment_statement(func, ve2, mul, loc);
+  Bexpression *cmp = be->binary_expression(OPERATOR_LE, ve2r2, c987, loc);
+  Bexpression *condex = be->conditional_expression(func, bi64t, cmp, ve2r3, mul, loc);
+  Bstatement *as2 = be->assignment_statement(func, ve2, condex, loc);
   // implicit fallthrough
 
   // third case
@@ -385,34 +389,57 @@
      %param2.addr = alloca i32
      %param3.addr = alloca i64*
      %loc1 = alloca i64
+     %tmpv.0 = alloca i64
      store i32 %param1, i32* %param1.addr
      store i32 %param2, i32* %param2.addr
      store i64* %param3, i64** %param3.addr
      store i64 0, i64* %loc1
-     %loc1.ld.2 = load i64, i64* %loc1
-     switch i64 %loc1.ld.2, label %default.0 [
+     %loc1.ld.4 = load i64, i64* %loc1
+     switch i64 %loc1.ld.4, label %default.0 [
        i64 1, label %case.0
        i64 2, label %case.0
        i64 3, label %case.1
        i64 4, label %case.1
      ]
-   case.0:                               ; preds = %entry, %entry
+
+   case.0:                                           ; preds = %entry, %entry
      %loc1.ld.0 = load i64, i64* %loc1
      %div.0 = sdiv i64 %loc1.ld.0, 123
      store i64 %div.0, i64* %loc1
      br label %label.0
-   case.1:                               ; preds = %entry, %entry
+
+   case.1:                                           ; preds = %entry, %entry
      %loc1.ld.1 = load i64, i64* %loc1
-     %mul.0 = mul i64 987, %loc1.ld.1
-     store i64 %mul.0, i64* %loc1
-     br label %default.0
-   default.0:                            ; preds = %entry, %case.1
+     %icmp.0 = icmp sle i64 %loc1.ld.1, 987
+     %zext.0 = zext i1 %icmp.0 to i8
+     %trunc.0 = trunc i8 %zext.0 to i1
+     br i1 %trunc.0, label %then.0, label %else.0
+
+   default.0:                                        ; preds = %entry, %fallthrough.0
      store i64 456, i64* %loc1
      br label %label.0
-   epilog.0:                             ; No predecessors!
+
+   epilog.0:                                         ; No predecessors!
      br label %label.0
-   label.0:                              ; preds = %epilog.0, %default.0, %case.0
+
+   label.0:                                          ; preds = %epilog.0, %default.0, %case.0
      ret i64 10101
+
+   then.0:                                           ; preds = %case.1
+     %loc1.ld.3 = load i64, i64* %loc1
+     store i64 %loc1.ld.3, i64* %tmpv.0
+     br label %fallthrough.0
+
+   fallthrough.0:                                    ; preds = %else.0, %then.0
+     %tmpv.0.ld.0 = load i64, i64* %tmpv.0
+     store i64 %tmpv.0.ld.0, i64* %loc1
+     br label %default.0
+
+   else.0:                                           ; preds = %case.1
+     %loc1.ld.2 = load i64, i64* %loc1
+     %mul.0 = mul i64 987, %loc1.ld.2
+     store i64 %mul.0, i64* %tmpv.0
+     br label %fallthrough.0
    }
   )RAW_RESULT";