gollvm: don't propagate lvalue-ness down on deref expression

For *expr = val, expr should be evaluated as an rvalue, even
the deref expression (*expr) is an lvalue. For example,

	var p float64 = ...
	*(*int32)(unsafe.Pointer(uintptr(p))) = 5

The expression being dereferenced should be evalueated as a
float64 load of p, a convertion to uint then to *int32,
instead of a pointer bitcast from *float64 to *uint then load.

Change-Id: Ife46a4f6181636e9561c7968891cfac67421743f
Reviewed-on: https://go-review.googlesource.com/55672
Reviewed-by: Than McIntosh <thanm@google.com>
diff --git a/llvm-gofrontend/go-llvm-materialize.cpp b/llvm-gofrontend/go-llvm-materialize.cpp
index 153f2f6..0dbd621 100644
--- a/llvm-gofrontend/go-llvm-materialize.cpp
+++ b/llvm-gofrontend/go-llvm-materialize.cpp
@@ -1553,7 +1553,6 @@
     assert(echild != nullptr);
     if (isLvalue(eparent) && isMem(echild)) {
       Bexpression *cmem = memArg(eparent);
-      assert(cmem != nullptr);
       if (cmem == echild)
         setLvalue(echild);
     }
@@ -1643,7 +1642,6 @@
       case N_StructField:
       case N_ArrayIndex:
       case N_Address:
-      case N_Deref:
       case N_Conversion:
       case N_PointerOffset:
         return kids[0]->castToBexpression();
diff --git a/unittests/BackendCore/BackendExprTests.cpp b/unittests/BackendCore/BackendExprTests.cpp
index 01ccfa6..043ff54 100644
--- a/unittests/BackendCore/BackendExprTests.cpp
+++ b/unittests/BackendCore/BackendExprTests.cpp
@@ -258,19 +258,40 @@
   Bfunction *func = h.func();
   Location loc;
 
-  // *(*uint32)parm3 = 5
   Btype *bi32t = be->integer_type(false, 32);
   Btype *bpi32t = be->pointer_type(bi32t);
-  Bvariable *p3 = func->getNthParamVar(2);
-  Bexpression *ve = be->var_expression(p3, VE_lvalue, loc);
-  Bexpression *conv = be->convert_expression(bpi32t, ve, loc);
-  Bexpression *dex = be->indirect_expression(bi32t, conv, false, loc);
-  h.mkAssign(dex, mkInt32Const(be, 5));
+
+  // *(*int32)parm3 = 5
+  {
+    Bvariable *p3 = func->getNthParamVar(2);
+    Bexpression *ve = be->var_expression(p3, VE_lvalue, loc);
+    Bexpression *conv = be->convert_expression(bpi32t, ve, loc);
+    Bexpression *dex = be->indirect_expression(bi32t, conv, false, loc);
+    h.mkAssign(dex, mkInt32Const(be, 5));
+  }
+
+  // var p float64
+  // *(*int32)(uintptr(p)) = 5
+  {
+    Btype *bf64t = be->float_type(64);
+    Btype *bu64t = be->integer_type(true, 64);
+    Bvariable *p = h.mkLocal("p", bf64t);
+    Bexpression *ve = be->var_expression(p, VE_rvalue, loc);
+    Bexpression *conv = be->convert_expression(bu64t, ve, loc);
+    Bexpression *conv2 = be->convert_expression(bpi32t, conv, loc);
+    Bexpression *dex = be->indirect_expression(bi32t, conv2, false, loc);
+    h.mkAssign(dex, mkInt32Const(be, 5));
+  }
 
   const char *exp = R"RAW_RESULT(
-      %cast.0 = bitcast i64** %param3.addr to i32**
-      %deref.ld.0 = load i32*, i32** %cast.0
-      store i32 5, i32* %deref.ld.0
+      %param3.ld.0 = load i64*, i64** %param3.addr
+      %cast.0 = bitcast i64* %param3.ld.0 to i32*
+      store i32 5, i32* %cast.0
+      store double 0.000000e+00, double* %p
+      %p.ld.0 = load double, double* %p
+      %ftoui.0 = fptoui double %p.ld.0 to i64
+      %itpcast.0 = inttoptr i64 %ftoui.0 to i32*
+      store i32 5, i32* %itpcast.0
     )RAW_RESULT";
 
   bool isOK = h.expectBlock(exp);