Index: osprey/wgen/wgen_spin_symbol.cxx
===================================================================
--- osprey/wgen/wgen_spin_symbol.cxx	(revision 3856)
+++ osprey/wgen/wgen_spin_symbol.cxx	(working copy)
@@ -437,19 +437,15 @@
 			if (gs_tree_code(type_tree) == GS_ARRAY_TYPE)
 				DevWarn ("Encountered VLA at line %d", lineno);
 			else
-#ifndef KEY
-				Fail_FmtAssertion ("VLA at line %d not currently implemented", lineno);
-#else
 			// bugs 943, 11277, 10506
 #if defined(TARG_SL)
 				ErrMsg(EC_Unimplemented_Feature, "variable-length structure",
 				  Orig_Src_File_Name?Orig_Src_File_Name:Src_File_Name, lineno);
 #else
-				ErrMsg(EC_Unimplemented_Feature, "variable-length structure");
+				DevWarn ("Encountered variable-length structure at line %d", lineno);
 #endif
-#endif
 			variable_size = TRUE;
-			tsize = 0;
+			tsize = -1;
 		}
 		else
 #ifdef KEY		// bug 3045
@@ -633,6 +629,7 @@
                     Set_TY_anonymous(ty);
 		Set_TY_etype (ty, Get_TY (gs_tree_type(type_tree)));
 		Set_TY_align (idx, TY_align(TY_etype(ty)));
+	        TYPE_TY_IDX(type_tree) = idx;
 		// assumes 1 dimension
 		// nested arrays are treated as arrays of arrays
 		ARB_HANDLE arb = New_ARB ();
Index: osprey/wgen/wgen_expr.cxx
===================================================================
--- osprey/wgen/wgen_expr.cxx	(revision 3856)
+++ osprey/wgen/wgen_expr.cxx	(working copy)
@@ -637,7 +637,7 @@
 
 static WN *WGEN_Expand_Ptr_To_Member_Func_Call_Expr (gs_t exp,
 	     TY_IDX nop_ty_idx, TYPE_ID rtype, TYPE_ID desc,
-	     WN_OFFSET offset = 0, UINT field_id = 0);
+	     WN* offset = NULL, UINT field_id = 0);
 
 // The words in 'buf' are in target order. Convert them to host order
 // in place. 'buf' is a two word array.
@@ -887,6 +887,153 @@
 } /* WGEN_Set_ST_Addr_Saved */
 
 
+/* to support VLA in structure in which the field offset isn't
+ * constant, a WN is generated to represent the offset.
+ * for normal structs, the WN is INTCONST and value if the offset.
+ * for VLA in structs, the WN is an INT expression.
+ */
+static WN*
+WGEN_Expand_Field_Offset(gs_t arg1) {
+  Is_True(gs_tree_code(arg1) == GS_FIELD_DECL,
+          ("WGEN_Expand_Field_Offset: arg1 is not field decl"));
+  WN* ofst = WGEN_Expand_Expr(gs_decl_field_offset(arg1));
+  WN* bit_ofst = WGEN_Expand_Expr(gs_decl_field_bit_offset(arg1));
+  TYPE_ID rtype = WN_rtype(ofst);
+  if (WN_operator(ofst) == OPR_INTCONST &&
+      WN_operator(bit_ofst) == OPR_INTCONST) {
+    INT64 ofst_value = (BITSPERBYTE * WN_const_val(ofst) + WN_const_val(bit_ofst))
+                       / BITSPERBYTE;
+    ofst = (ofst_value == 0) ? NULL : WN_Intconst(rtype, ofst_value);
+  }
+  else {
+    ofst = WN_Div(rtype,
+                  WN_Add(rtype,
+                         WN_Mpy(rtype, 
+                                ofst,
+                                WN_Intconst(rtype, BITSPERBYTE)),
+                         bit_ofst),
+                  WN_Intconst(rtype, BITSPERBYTE));
+  }
+  return ofst;
+}
+
+/* create a new address expression for given ST and offset
+ * if ofst is NULL or intconst, return LDA.
+ * otherwise, generate a add expression for the address.
+ */
+static WN*
+WGEN_Compose_Address(ST* st, WN* ofst, TY_IDX hl_ty, UINT32 field_id) {
+  if (ofst == NULL) {
+    return WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
+                        ST_ofst(st), Make_Pointer_Type(hl_ty), st, field_id);
+  }
+  else if (WN_operator(ofst) == OPR_INTCONST) {
+    return WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
+                        ST_ofst(st) + WN_const_val(ofst), Make_Pointer_Type(hl_ty), st, field_id);
+  }
+  else {
+    WN* lda = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
+                           ST_ofst(st), Make_Pointer_Type(hl_ty), st, field_id);
+    return WN_Binary(OPR_ADD, Pointer_Mtype, lda, ofst);  // TODO: use ILDA instrad
+  }
+}
+
+/* compose a new offset expression
+ * if given ofst1 and ofst2 are constants, generate a new INTCONST WN
+ * otherwise, generate a ADD expression
+ */
+static WN*
+WGEN_Compose_Offset(WN* ofst1, WN* ofst2) {
+  if (ofst1 == NULL)
+    return ofst2;
+  if (ofst2 == NULL)
+    return ofst1;
+  TYPE_ID rtype = WN_rtype(ofst1);
+  if (WN_operator(ofst1) == OPR_INTCONST && WN_operator(ofst2) == OPR_INTCONST)
+    return WN_Intconst(rtype, WN_const_val(ofst1) + WN_const_val(ofst2));
+  else
+    return WN_Add(rtype, ofst1, ofst2);
+}
+
+/* crate a Iload/Istore with constant or variable offset
+ * if given offset is constant, the value is on the Iload/Istore node.
+ * other, a new address is generated using OPR_ADD and used in Iload/Istore.
+ */
+static WN*
+WGEN_CreateIload(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc,
+                   WN* offset, TY_IDX ty,
+                   TY_IDX load_addr_ty, WN *addr, UINT field_id) {
+  if (offset == NULL || WN_operator(offset) == OPR_INTCONST) {
+    INT64 ofst_value = (offset == NULL) ? 0 : WN_const_val(offset);
+    return WN_CreateIload(opr, rtype, desc,
+                          ofst_value, ty,
+                          load_addr_ty, addr, field_id);
+  }
+  else {
+    WN* new_addr = WN_Binary(OPR_ADD, Pointer_Mtype, addr, offset);  // TODO: use ILDA instrad
+    return WN_CreateIload(opr, rtype, desc,
+                          0, ty,
+                          load_addr_ty, new_addr, field_id);
+  }
+}
+
+static WN*
+WGEN_CreateIstore(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc,
+                    WN* offset, TY_IDX ty, WN *value, WN *addr,
+                    UINT field_id) {
+  if (offset == NULL || WN_operator(offset) == OPR_INTCONST) {
+    INT64 ofst_value = (offset == NULL) ? 0 : WN_const_val(offset);
+    FmtAssert(desc != MTYPE_M || TY_size(TY_pointed(ty)) != -1,
+              ("WGEN_CreateIstore: TODO: store variable length object"));
+    return WN_CreateIstore(opr, rtype, desc,
+                           ofst_value, ty, value, addr,
+                           field_id);
+  }
+  else {
+    WN* new_addr = WN_Binary(OPR_ADD, Pointer_Mtype, addr, offset);  // TODO: use ILDA instrad
+    return WN_CreateIstore(opr, rtype, desc,
+                           0, ty, value, new_addr,
+                           field_id);
+  }
+}
+
+/* create a LDID/STID with constant or variable offset
+ * if given offset is constant, the LDID/STID with constant offset is generated
+ * other, a new address is generated using OPR_LDA and OPR_ADD and the final returned
+ * WN is Iload/Istore
+ */
+static WN*
+WGEN_CreateLdid(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc,
+                  WN* offset, ST* st, TY_IDX ty, UINT field_id) {
+  if (offset == NULL || WN_operator(offset) == OPR_INTCONST) {
+    INT64 ofst_value = (offset == NULL) ? 0 : WN_const_val(offset);
+    return WN_CreateLdid(opr, rtype, desc,
+                         ST_ofst(st) + ofst_value, st, ty, field_id);
+  }
+  else {
+    // variable offset should only appear in VLA/VLS but we never generate
+    // LDID for VLA/VLS
+    Is_True(FALSE, ("WGEN_CreateLdid: offset is not constant for LDID."));
+    return NULL;
+  }
+}
+
+static WN*
+WGEN_CreateStid(OPERATOR opr, TYPE_ID rtype, TYPE_ID desc,
+                  WN* offset, ST* st, TY_IDX ty, WN *value, UINT field_id) {
+  if (offset == NULL || WN_operator(offset) == OPR_INTCONST) {
+    INT64 ofst_value = (offset == NULL) ? 0 : WN_const_val(offset);
+    return WN_CreateStid(opr, rtype, desc,
+                         ST_ofst(st) + ofst_value, st, ty, value, field_id);
+  }
+  else {
+    // variable offset should only appear in VLA/VLS but we never generate
+    // STID for VLA/VLS
+    Is_True(FALSE, ("WGEN_CreateStid: offset is not constant for STID."));
+    return NULL;
+  }
+}
+
 typedef struct wgen_save_expr_t {
   gs_t  exp;
   ST   *st;
@@ -909,7 +1056,7 @@
                bool need_result,
                TY_IDX nop_ty_idx,
                TY_IDX component_ty_idx,
-               INT64 component_offset,
+               WN* component_offset,
                UINT16 field_id)
 {
   INT32     i;
@@ -987,7 +1134,7 @@
   else {
     TYPE_ID desc  = TY_mtype(component_ty_idx);
     TYPE_ID rtype = Widen_Mtype(desc);
-    wn = WN_CreateLdid(OPR_LDID, rtype, desc, component_offset, st,
+    wn = WGEN_CreateLdid(OPR_LDID, rtype, desc, component_offset, st,
 		     field_id? ty_idx : component_ty_idx, field_id);  
   }
   return wn;
@@ -1049,7 +1196,6 @@
   return WN_Ldid(ret_mtype, 0, res_st, ty_idx);
 }
 
-
 /* process the tree doing array indicing and return the WN that performs
  * the address computation; ty_idx returns the high-level array type if it
  * is a DECL node, and the element type if it is an ARRAY_REF node.
@@ -1058,7 +1204,7 @@
 WGEN_Array_Expr(gs_t exp, 
 	       TY_IDX *ty_idx, 
 	       TY_IDX component_ty_idx,
-	       INT64 component_offset,
+	       WN* component_offset,
 	       UINT32 field_id)
 {
   WN *wn;
@@ -1076,9 +1222,7 @@
 #endif
     Is_True(! gs_decl_bit_field(arg1),
 	    ("WGEN_Array_Expr: address arithmetic cannot use bitfield addresses"));
-    INT64 ofst = (BITSPERBYTE * gs_get_integer_value(gs_decl_field_offset(arg1)) +
-				gs_get_integer_value(gs_decl_field_bit_offset(arg1)))
-			      / BITSPERBYTE;
+    WN* ofst = WGEN_Expand_Field_Offset(arg1);
 #ifdef KEY
     // Refer GCC 4.0.2: gcc.c-torture/compile/struct-non-lval-3.c
     // We only handle this case so far:
@@ -1092,13 +1236,15 @@
       arg0 = lhs;
     }
 #endif
-    
+
+    ofst = WGEN_Compose_Offset(ofst, component_offset);    
+
 #ifdef KEY // bug 9725: If the field is an array of struct, it is considered
            // a single field.
-    return WGEN_Array_Expr(arg0, ty_idx, ty_idx0, ofst + component_offset,
+    return WGEN_Array_Expr(arg0, ty_idx, ty_idx0, ofst,
 			  DECL_FIELD_ID(arg1));
 #else
-    return WGEN_Array_Expr(arg0, ty_idx, ty_idx0, ofst + component_offset,
+    return WGEN_Array_Expr(arg0, ty_idx, ty_idx0, ofst,
 			  field_id + DECL_FIELD_ID(arg1));
 #endif
   }
@@ -1116,15 +1262,6 @@
           ) {
     ST *st = Get_ST (exp);
     ST *base_st = ST_base (st);
-    // for VLAs the instead of using the ST use its base st
-    // also for the time being do not support VLAs within structs
-    if (st != base_st) {
-      FmtAssert (component_ty_idx == 0,
-                 ("Variable Length Arrays within struct not currently implemented"));
-      wn = WN_Ldid (Pointer_Mtype, 0, base_st, ST_type (base_st));
-    }
-    else
-      wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
     if (component_ty_idx == 0)
       *ty_idx = ST_type(st);
     else {
@@ -1134,16 +1271,29 @@
     }
     Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
 	    ("WGEN_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
+    // for VLAs the instead of using the ST use its base st
+    // also for the time being do not support VLAs within structs
+    if (st != base_st) {
+      DevWarn ("Encountered VLA at line %d", lineno);
+      Is_True(ST_ofst(st) == 0, ("TODO: ST_ofst is not 0"));
+      wn = WN_Ldid (Pointer_Mtype, 0, base_st, Make_Pointer_Type(*ty_idx));
+      if (component_offset != NULL) { // TODO: use ILDA instead
+        wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn, component_offset);
+      }
+    }
+    else {
+      wn = WGEN_Compose_Address(st, component_offset, *ty_idx, field_id);
+    }
     return wn;
   }
   else if (code == GS_CONSTRUCTOR) {
     ST *st = WGEN_Generate_Temp_For_Initialized_Aggregate (exp, "");
-    wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
     if (component_ty_idx == 0)
       *ty_idx = ST_type(st);
     else *ty_idx = component_ty_idx;
     Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
 	    ("WGEN_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
+    wn = WGEN_Compose_Address(st, component_offset, *ty_idx, field_id);
     return wn;
   }
   else if (code == GS_STRING_CST) {
@@ -1161,9 +1311,8 @@
       if (node_align < TY_align(component_ty_idx))
 	Set_TY_align(*ty_idx, node_align);//pick more stringent align
     }
-    if (component_offset != 0) { // TODO: use ILDA instead
-      WN *wn0 = WN_Intconst(MTYPE_I4, component_offset);
-      wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn, wn0);
+    if (component_offset != NULL) { // TODO: use ILDA instead
+      wn = WN_Binary(OPR_ADD, Pointer_Mtype, wn, component_offset);
     }
     return wn;
   }
@@ -1175,7 +1324,6 @@
     ST *st = WN_st (WN_kid1 (wn));
     WN_Delete (WN_kid1 (wn));
     WN_Delete (wn);
-    wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
     if (component_ty_idx == 0)
       *ty_idx = ST_type(st);
     else {
@@ -1185,6 +1333,7 @@
     }
     Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
 	    ("WGEN_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
+    wn = WGEN_Compose_Address(st, component_offset, *ty_idx, field_id);
     return wn;
   }
   else if (code == GS_ARRAY_REF) { // recursive call
@@ -1276,7 +1425,6 @@
     Is_True(WN_operator(wn) == OPR_LDID,
 	    ("WGEN_Array_Expr: OPR_LDID not found"));
     ST *st = WN_st(wn);
-    wn = WN_Lda (Pointer_Mtype, ST_ofst(st)+component_offset, st, field_id);
     if (component_ty_idx == 0)
       *ty_idx = ST_type(st);
     else {
@@ -1286,6 +1434,7 @@
     }
     Is_True(TY_kind(*ty_idx) == KIND_ARRAY,
 	    ("WGEN_Array_Expr: ARRAY_REF base not of type KIND_ARRAY"));
+    wn = WGEN_Compose_Address(st, component_offset, *ty_idx, field_id);
     return wn;
   }
 #endif /* KEY */
@@ -1374,7 +1523,7 @@
 		       WN* lhs_retval,
 		       bool need_result,
 		       TY_IDX component_ty_idx, 
-		       INT64 component_offset,
+		       WN* component_offset,
 		       UINT32 field_id,
 		       bool is_bit_field,
 		       WN *rhs_wn,
@@ -1405,7 +1554,6 @@
   switch (code) {
   case GS_COMPONENT_REF:
     {
-      INT64 ofst;
       TY_IDX ty_idx0;
 
       gs_t arg0 = gs_tree_operand(lhs, 0);
@@ -1420,11 +1568,14 @@
       else ty_idx0 = component_ty_idx;
       if (gs_decl_bit_field(arg1)) 
         is_bit_field = TRUE;
-      if (! is_bit_field)
-        ofst = (BITSPERBYTE * gs_get_integer_value(gs_decl_field_offset(arg1)) +
-			      gs_get_integer_value(gs_decl_field_bit_offset(arg1)))
-			    / BITSPERBYTE;
-      else ofst = 0;
+      WN* ofst;
+      if (! is_bit_field) {
+        ofst = WGEN_Expand_Field_Offset(arg1);
+        ofst = WGEN_Compose_Offset(ofst, component_offset);
+      }
+      else {
+        ofst = component_offset;
+      }
 #ifdef KEY    // bug 10422: check if the field is volatile, arg1 is FIELD_DECL
       if (gs_tree_this_volatile(arg1)) {
 	Set_TY_is_volatile(ty_idx0);
@@ -1440,7 +1591,7 @@
                  ("WGEN_Lhs_Of_Modify_Expr: DECL_FIELD_ID used but not set"));
 #endif
       wn = WGEN_Lhs_Of_Modify_Expr(assign_code, arg0, NULL, need_result, ty_idx0, 
-				  ofst+component_offset,
+				  ofst,
 			          field_id + DECL_FIELD_ID(arg1), is_bit_field, 
 				  rhs_wn, rhs_preg_num, is_realpart,
 				  is_imagpart);
@@ -1568,16 +1719,16 @@
 			       rhs_wn,
 			       WN_Unary(OPR_IMAGPART,
 				        Mtype_complex_to_real (rtype),
-				        WN_CreateLdid(OPR_LDID, rtype, desc,
-						      ST_ofst(st) + component_offset,
+				        WGEN_CreateLdid(OPR_LDID, rtype, desc,
+						      component_offset,
 						      st, hi_ty_idx, field_id)));
 	  else
 	  if (is_imagpart)
 	    rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
 			       WN_Unary(OPR_REALPART,
 				        Mtype_complex_to_real (rtype),
-				        WN_CreateLdid(OPR_LDID, rtype, desc,
-						      ST_ofst(st) + component_offset,
+				        WGEN_CreateLdid(OPR_LDID, rtype, desc,
+						      component_offset,
 						      st, hi_ty_idx, field_id)),
 			       rhs_wn);
         }
@@ -1595,8 +1746,8 @@
 
         if (assign_code == GS_PREINCREMENT_EXPR ||
 	    assign_code == GS_PREDECREMENT_EXPR) {
-          wn = WN_CreateLdid (OPR_LDID, rtype, desc, 
-			      ST_ofst(st) + component_offset,
+          wn = WGEN_CreateLdid (OPR_LDID, rtype, desc, 
+			      component_offset,
 			      st, hi_ty_idx, field_id);
           rhs_wn = WN_Binary(Operator_From_Tree [assign_code].opr,
 		             rtype, wn, rhs_wn);
@@ -1604,8 +1755,8 @@
         }
         else if (assign_code == GS_POSTINCREMENT_EXPR ||
 	         assign_code == GS_POSTDECREMENT_EXPR) {
-          result_wn = WN_CreateLdid (OPR_LDID, rtype, desc, 
-				     ST_ofst(st) + component_offset,
+          result_wn = WGEN_CreateLdid (OPR_LDID, rtype, desc, 
+				     component_offset,
 				     st, hi_ty_idx, field_id);
         }
         else result_wn = rhs_wn;
@@ -1646,15 +1797,24 @@
 	if (volt) 
 	  Set_TY_is_volatile(hi_ty_idx);
 #endif
-        wn = WN_Stid (desc, ST_ofst(st) + component_offset + lhs_preg_num, st,
-		      hi_ty_idx, rhs_wn, field_id);
+        if (ST_base(st) != st) {
+          ST* base_st = ST_base(st);
+          Is_True(ST_ofst(st) == 0, ("TODO: ST_ofst is not 0"));
+          WN* addr = WN_Ldid(Pointer_Mtype, 0, base_st, ST_type(base_st));
+          wn = WGEN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset,
+                                   ST_type(base_st), rhs_wn, addr, field_id);
+        }
+        else {
+          wn = WGEN_CreateStid (OPR_STID, MTYPE_V, desc, component_offset, st,
+		        hi_ty_idx, rhs_wn, field_id);
+        }
         WGEN_Stmt_Append(wn, Get_Srcpos());
 #if defined(TARG_SL)
         if (need_append) {
           WN *ldid_wn;
           if (! result_in_temp)
-            ldid_wn =  WN_CreateLdid(OPR_LDID, rtype, desc,
-                                     ST_ofst(st) + component_offset, st, hi_ty_idx,
+            ldid_wn =  WGEN_CreateLdid(OPR_LDID, rtype, desc,
+                                     component_offset, st, hi_ty_idx,
                                      field_id);
           else
             ldid_wn =  WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
@@ -1665,8 +1825,8 @@
       }
       if (need_result) {
         if (! result_in_temp)
-          wn = WN_CreateLdid(OPR_LDID, rtype, desc, 
-			     ST_ofst(st) + component_offset, st, hi_ty_idx,
+          wn = WGEN_CreateLdid(OPR_LDID, rtype, desc, 
+			     component_offset, st, hi_ty_idx,
 			     field_id);
         else wn = WN_Ldid(rtype, result_preg, result_preg_st, desc_ty_idx, 0);
         if (is_realpart)
@@ -1781,7 +1941,7 @@
 			       rhs_wn,
 			       WN_Unary(OPR_IMAGPART,
 				        Mtype_complex_to_real (rtype),
-				        WN_CreateIload(OPR_ILOAD, rtype, desc,
+				        WGEN_CreateIload(OPR_ILOAD, rtype, desc,
 						       component_offset,
 						       field_id != 0 ? hi_ty_idx : desc_ty_idx,
 						       Make_Pointer_Type(hi_ty_idx, FALSE),
@@ -1792,7 +1952,7 @@
 	    rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
 			       WN_Unary(OPR_REALPART,
 				        Mtype_complex_to_real (rtype),
-				        WN_CreateIload(OPR_ILOAD, rtype, desc,
+				        WGEN_CreateIload(OPR_ILOAD, rtype, desc,
 						       component_offset,
 						       field_id != 0 ? hi_ty_idx : desc_ty_idx,
 						       Make_Pointer_Type(hi_ty_idx, FALSE),
@@ -1814,7 +1974,7 @@
 
         if (assign_code == GS_PREINCREMENT_EXPR ||
 	    assign_code == GS_PREDECREMENT_EXPR) {
-          wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
+          wn = WGEN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
 			       field_id != 0 ? hi_ty_idx : desc_ty_idx,
 			       Make_Pointer_Type(hi_ty_idx, FALSE),
 			       WN_COPY_Tree (addr_wn),
@@ -1825,7 +1985,7 @@
         }
         else if (assign_code == GS_POSTINCREMENT_EXPR ||
 	         assign_code == GS_POSTDECREMENT_EXPR) {
-	  result_wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
+	  result_wn = WGEN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
 				      field_id != 0 ? hi_ty_idx : desc_ty_idx,
 				      Make_Pointer_Type(hi_ty_idx, FALSE),
 				      WN_COPY_Tree (addr_wn),
@@ -1903,14 +2063,16 @@
 	  gs_t type = gs_tree_type(ptr_type);
 	  FmtAssert(gs_tree_code(ptr_type) == GS_POINTER_TYPE,
 	    ("WGEN_Lhs_Of_Modify_Expr: INDIRECT_REF opnd0 is not POINTER_TYPE"));
-	  FmtAssert(component_offset == 0,
+	  FmtAssert(component_offset == NULL ||
+                    (WN_operator(component_offset) == OPR_INTCONST && 
+                     WN_const_val(component_offset) == 0),
 		    ("WGEN_Lhs_Of_Modify_Expr: component_offset nonzero"));
 	  TY_IDX tidx = Get_TY(ptr_type);
 	  // Check object has no copy constructor.
 	  FmtAssert(!WGEN_has_copy_constructor(type),
 	      ("WGEN_Lhs_Of_Modify_Expr: object needs copy constructor"));
         }
-        wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset, 
+        wn = WGEN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset, 
 			     Make_Pointer_Type (hi_ty_idx, FALSE),
 			     rhs_wn, addr_wn, field_id);
 #ifdef TARG_SL
@@ -1931,7 +2093,7 @@
         if (need_append) {
           WN *ldid_wn;
           if (! result_in_temp)
-            ldid_wn = WN_CreateIload(OPR_ILOAD, rtype, desc, component_offset,
+            ldid_wn = WGEN_CreateIload(OPR_ILOAD, rtype, desc, component_offset,
                                      field_id != 0 ? hi_ty_idx : desc_ty_idx,
                                      Make_Pointer_Type (hi_ty_idx, FALSE),
                                      WN_COPY_Tree (addr_wn),
@@ -1944,7 +2106,7 @@
 #endif
         if (need_result) {
 	  if (! result_in_temp)
-            wn = WN_CreateIload(OPR_ILOAD, rtype, desc, component_offset,
+            wn = WGEN_CreateIload(OPR_ILOAD, rtype, desc, component_offset,
 			        field_id != 0 ? hi_ty_idx : desc_ty_idx,
 			        Make_Pointer_Type (hi_ty_idx, FALSE),
 			        WN_COPY_Tree (addr_wn),
@@ -1965,7 +2127,7 @@
     {
       TY_IDX elem_ty_idx;
       // generate the WHIRL array node
-      WN *addr_wn = WGEN_Array_Expr(lhs, &elem_ty_idx, 0, 0, 0);
+      WN *addr_wn = WGEN_Array_Expr(lhs, &elem_ty_idx, 0, NULL, 0);
       if (TY_is_volatile(elem_ty_idx))
         volt = TRUE;
       TY_IDX desc_ty_idx = component_ty_idx;
@@ -2017,7 +2179,7 @@
 			       rhs_wn,
 			       WN_Unary(OPR_IMAGPART,
 				        Mtype_complex_to_real (rtype),
-				        WN_CreateIload(OPR_ILOAD, rtype, desc,
+				        WGEN_CreateIload(OPR_ILOAD, rtype, desc,
 						       component_offset,
 						       field_id != 0 ? elem_ty_idx : desc_ty_idx,
 						       Make_Pointer_Type(elem_ty_idx, FALSE),
@@ -2028,7 +2190,7 @@
 	    rhs_wn = WN_Binary(OPR_COMPLEX, rtype,
 			       WN_Unary(OPR_REALPART,
 				        Mtype_complex_to_real (rtype),
-				        WN_CreateIload(OPR_ILOAD, rtype, desc,
+				        WGEN_CreateIload(OPR_ILOAD, rtype, desc,
 						       component_offset,
 						       field_id != 0 ? elem_ty_idx : desc_ty_idx,
 						       Make_Pointer_Type(elem_ty_idx, FALSE),
@@ -2050,7 +2212,7 @@
 
         if (assign_code == GS_PREINCREMENT_EXPR ||
             assign_code == GS_PREDECREMENT_EXPR) {
-          wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
+          wn = WGEN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
                                field_id != 0 ? elem_ty_idx : desc_ty_idx,
                                Make_Pointer_Type(elem_ty_idx, FALSE),
                                WN_COPY_Tree (addr_wn),
@@ -2061,7 +2223,7 @@
         }
         else if (assign_code == GS_POSTINCREMENT_EXPR ||
 	         assign_code == GS_POSTDECREMENT_EXPR) {
-          result_wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
+          result_wn = WGEN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
 				      field_id != 0 ? elem_ty_idx : desc_ty_idx,
 				      Make_Pointer_Type(elem_ty_idx, FALSE),
 				      WN_COPY_Tree (addr_wn),
@@ -2106,7 +2268,7 @@
         wn = NULL;
       }
       else {
-        wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset, 
+        wn = WGEN_CreateIstore(OPR_ISTORE, MTYPE_V, desc, component_offset, 
 			     Make_Pointer_Type(elem_ty_idx, FALSE), rhs_wn,
 			     addr_wn, field_id);
         WGEN_Stmt_Append(wn, Get_Srcpos());
@@ -2114,7 +2276,7 @@
         if (need_append) {
           WN *iload;
           if (!result_in_temp)
-            iload = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
+            iload = WGEN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
                                       field_id != 0 ? elem_ty_idx : desc_ty_idx,
                                       Make_Pointer_Type (elem_ty_idx, FALSE),
                                       WN_COPY_Tree (addr_wn),
@@ -2126,7 +2288,7 @@
 #endif
         if (need_result) {
           if (! result_in_temp)
-	    wn = WN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
+	    wn = WGEN_CreateIload (OPR_ILOAD, rtype, desc, component_offset,
 			         field_id != 0 ? elem_ty_idx : desc_ty_idx,
                                  Make_Pointer_Type (elem_ty_idx, FALSE),
 			         WN_COPY_Tree (addr_wn),
@@ -2202,20 +2364,25 @@
       TYPE_ID desc = is_bit_field ? MTYPE_BS : TY_mtype(desc_ty_idx);
       if (desc == MTYPE_UNKNOWN)
 	desc = WN_rtype(rhs_wn); // is a scalar
+
+      Is_True(component_offset == NULL || WN_operator(component_offset) == OPR_INTCONST,
+              ("WGEN_Lhs_Of_Modify_Expr: GS_COMPOUND_LITERAL_EXPR: offset is not constant"));
+      INT64 ofst_value = (component_offset == NULL) ? 0 : WN_const_val(component_offset);
+
 #ifdef KEY // bug 14372
-      wn = WN_Stid (desc, ST_ofst(copy) + component_offset, copy,
+      wn = WN_Stid (desc, ST_ofst(copy) + ofst_value, copy,
 		    hi_ty_idx, rhs_wn, field_id);
 #else
       if (desc_ty_idx == 0)
         desc_ty_idx = MTYPE_TO_TY_array[desc];
 
-      wn = WN_Stid (desc, ST_ofst(copy) + component_offset, copy,
+      wn = WN_Stid (desc, ST_ofst(copy) + ofst_value, copy,
 		    desc_ty_idx, rhs_wn, field_id);
 #endif
       WGEN_Stmt_Append(wn, Get_Srcpos());
       if (need_result) // bug 10548
         wn = WN_CreateLdid(OPR_LDID, desc, desc,
-                           ST_ofst(copy) + component_offset, copy,
+                           ST_ofst(copy) + ofst_value, copy,
                            ST_type(copy));
       else
         wn = NULL;
@@ -5767,7 +5934,7 @@
 		  bool need_result,
 		  TY_IDX nop_ty_idx,
 		  TY_IDX component_ty_idx,
-		  INT64 component_offset,
+		  WN* component_offset,
 		  UINT32 field_id ,
 		  bool is_bit_field,
 		  bool is_aggr_init_via_ctor,
@@ -6241,10 +6408,31 @@
 
 	Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
 		("WGEN_Expand_Expr: field id for bit-field exceeds limit"));
-	wn = WN_CreateLdid (OPR_LDID, rtype,
-			    is_bit_field ? MTYPE_BS : desc,
-			    ST_ofst(st)+component_offset+xtra_BE_ofst+preg_num, st,
-			    field_id != 0 ? hi_ty_idx : ty_idx, field_id);
+        WN* load_ofst = NULL;
+        if (xtra_BE_ofst + preg_num != 0)
+          load_ofst = WGEN_Compose_Offset(component_offset,
+                                          WN_Intconst(Pointer_Mtype, xtra_BE_ofst));
+        else
+          load_ofst = component_offset;
+        if (ST_base(st) != st) {
+          ST* base_st = ST_base(st);
+          Is_True(ST_ofst(st) == 0, ("TODO: ST_ofst is not 0"));
+          WN* load_addr = WN_Ldid(Pointer_Mtype, 0, base_st, ST_type(base_st));
+          TY_IDX load_ty = field_id != 0 ? hi_ty_idx : ty_idx;
+          wn = WGEN_CreateIload(OPR_ILOAD, rtype,
+                              is_bit_field ? MTYPE_BS : desc,
+                              load_ofst,
+                              load_ty,
+                              ST_type(base_st),
+                              load_addr,
+                              field_id);
+        }
+        else {
+	  wn = WGEN_CreateLdid (OPR_LDID, rtype,
+			      is_bit_field ? MTYPE_BS : desc,
+			      load_ofst, st,
+			      field_id != 0 ? hi_ty_idx : ty_idx, field_id);
+        }
 	if (cvtl_size != 0)
 	  wn = WN_CreateCvtl(OPR_CVTL, rtype, MTYPE_V, cvtl_size, wn);
       }
@@ -6305,9 +6493,9 @@
 	  if (ST_assigned_to_dedicated_preg (st))
 	    Set_TY_is_volatile (ty_idx);
 	}
-	wn = WN_CreateLdid (OPR_LDID, rtype,
+	wn = WGEN_CreateLdid (OPR_LDID, rtype,
 			    is_bit_field ? MTYPE_BS : desc, 
-			    ST_ofst(st)+component_offset, st,
+			    component_offset, st,
 			    field_id != 0 ? hi_ty_idx : ty_idx, field_id);
 	if (cvtl_size != 0)
 	  wn = WN_CreateCvtl(OPR_CVTL, rtype, MTYPE_V, cvtl_size, wn);
@@ -6582,7 +6770,6 @@
 
     case GS_COMPONENT_REF:
       {
-	INT64 ofst;
 	arg0 = gs_tree_operand (exp, 0);
 	arg1 = gs_tree_operand (exp, 1);
 	// If this is an indirect of a nop_expr, we may need to fix the
@@ -6615,11 +6802,14 @@
 	  }
         }
 
-	if (! is_bit_field)
-	  ofst = (BITSPERBYTE * gs_get_integer_value(gs_decl_field_offset(arg1)) +
-			        gs_get_integer_value(gs_decl_field_bit_offset(arg1)))
-			      / BITSPERBYTE;
-	else ofst = 0;
+        WN* ofst = NULL;
+	if (! is_bit_field) {
+          ofst = WGEN_Expand_Field_Offset(arg1);
+          ofst = WGEN_Compose_Offset(ofst, component_offset);
+        }
+	else {
+          ofst = component_offset;
+        }
 #ifdef KEY
 	FmtAssert (DECL_FIELD_ID(arg1) != 0,
                    ("WGEN_Expand_Expr: DECL_FIELD_ID used but not set"));
@@ -6634,11 +6824,11 @@
 	  // WGEN_Call_Returns_Ptr_To_Member_Func(arg0)) is TRUE.  Bug 6022.
 	  TYPE_ID desc = TY_mtype(Get_TY(gs_tree_type(field0)));
 	  wn = WGEN_Expand_Ptr_To_Member_Func_Call_Expr (arg0, nop_ty_idx,
-		  Pointer_Mtype, desc, component_offset,
+		  Pointer_Mtype, desc, ofst,
 		  field_id + DECL_FIELD_ID(arg1));
 	} else
 #endif
-        wn = WGEN_Expand_Expr (arg0, TRUE, nop_ty_idx, ty_idx, ofst+component_offset,
+        wn = WGEN_Expand_Expr (arg0, TRUE, nop_ty_idx, ty_idx, ofst,
 			      field_id + DECL_FIELD_ID(arg1), is_bit_field);
 
 #ifdef KEY
@@ -6655,15 +6845,26 @@
 	  TYPE_ID rtype = Widen_Mtype(TY_mtype(ty_idx));
 	  TYPE_ID desc = TY_mtype(ty_idx);
 	  if (WN_operator(wn) == OPR_ILOAD) {
-            wn = WN_CreateIload(OPR_ILOAD, rtype, desc,
-			        WN_offset(wn) + ofst + component_offset, ty_idx,
+            WN* iload_ofst = NULL;
+            if (WN_offset(wn) != 0) {
+              iload_ofst = WGEN_Compose_Offset(ofst,
+                                               WN_Intconst(Pointer_Mtype, WN_offset(wn)));
+            }
+            else {
+              iload_ofst = ofst;
+            }
+            wn = WGEN_CreateIload(OPR_ILOAD, rtype, desc,
+			        iload_ofst, ty_idx,
 			        WN_load_addr_ty(wn), WN_kid0(wn),
 			        WN_field_id(wn)+field_id + DECL_FIELD_ID(arg1));
 	  } 
 	  else if (WN_operator(wn) == OPR_LDID) {
 	    WN_set_rtype(wn, rtype);
 	    WN_set_desc(wn, desc);
-	    WN_offset(wn) = WN_offset(wn)+ofst+component_offset;
+            Is_True(ofst == NULL || WN_operator(ofst) == OPR_INTCONST,
+                    ("WGEN_Expand_Expr: ofst is not constant for LDID"));
+            INT64 ofst_value = (ofst == NULL) ? 0 : WN_const_val(ofst);
+	    WN_offset(wn) = WN_offset(wn) + ofst_value;
 	    WN_set_field_id(wn, WN_field_id(wn)+field_id + DECL_FIELD_ID(arg1));
 	  } 
 	} 
@@ -6686,7 +6887,8 @@
 	  wn = WN_Stid (MTYPE_M, 0, temp, temp_ty_idx, wn);
 	  WGEN_Stmt_Append (wn, Get_Srcpos());
 	  // Load correct field from temp symbol
-	  wn = WN_Ldid (TY_mtype (ty_idx), ofst + component_offset,
+          TYPE_ID rtype= Mtype_comparison(TY_mtype (ty_idx));
+	  wn = WGEN_CreateLdid (OPR_LDID, rtype, TY_mtype (ty_idx), ofst,
 	                temp, temp_ty_idx, field_id + DECL_FIELD_ID(arg1));
 	}
 #endif
@@ -6769,7 +6971,10 @@
 	    if (TCON_ty (tcon) == MTYPE_STRING &&
                 TY_size (Be_Type_Tbl (desc)) == 1) {
 	      mUINT32 len = Targ_String_Length (tcon);
-	      mUINT64 offset = component_offset + xtra_BE_ofst + WN_offset (wn0);
+              Is_True(component_offset == NULL || WN_operator(component_offset) == OPR_INTCONST,
+                      ("WGEN_Expand_Expr: component_offset is not constant"));
+              INT64 offset_value = (component_offset == NULL) ? 0 : WN_const_val(component_offset);
+	      mUINT64 offset = offset_value + xtra_BE_ofst + WN_offset (wn0);
 	      if (offset <= len    &&
 		  desc == MTYPE_U1 &&
 		  (rtype == MTYPE_U4 || rtype == MTYPE_U8)) {
@@ -6790,13 +6995,20 @@
 	    }
 	  }
 	  // NOTE: In GNU4, this may be a REFERENCE_REF_P.
-	  if (need_result)
-	    wn = WN_CreateIload(OPR_ILOAD, rtype,
+	  if (need_result) {
+            WN* iload_ofst = NULL;
+            if (xtra_BE_ofst != 0)
+              iload_ofst = WGEN_Compose_Offset(component_offset,
+                                               WN_Intconst(Pointer_Mtype, xtra_BE_ofst));
+            else
+              iload_ofst = component_offset;
+	    wn = WGEN_CreateIload(OPR_ILOAD, rtype,
 				is_bit_field ? MTYPE_BS : desc, 
-				component_offset+xtra_BE_ofst,
+				iload_ofst,
 				field_id != 0 ? hi_ty_idx : ty_idx, 
 				Make_Pointer_Type (hi_ty_idx, FALSE),
 				wn0, field_id);
+          }
 	  else
 	  if (WN_has_side_effects (wn0))
 	    wn = wn0;
@@ -7740,7 +7952,7 @@
 	  break;
 #endif
 	wn  = WGEN_Lhs_Of_Modify_Expr(code, gs_tree_operand (exp, 0), call_return_val, need_result, 
-				     0, 0, 0, FALSE, wn1, 0, FALSE, FALSE);
+				     0, NULL, 0, FALSE, wn1, 0, FALSE, FALSE);
       }
       break;
 
@@ -7839,7 +8051,7 @@
 	UINT xtra_BE_ofst = 0; 	// only needed for big-endian target
 	TY_IDX elem_ty_idx;
 	// generate the WHIRL array node
-        wn0 = WGEN_Array_Expr(exp, &elem_ty_idx, 0, 0, 0);
+        wn0 = WGEN_Array_Expr(exp, &elem_ty_idx, 0, NULL, 0);
 
 	// generate the iload node
 	TY_IDX hi_ty_idx = Get_TY (gs_tree_type(exp));
@@ -7883,9 +8095,15 @@
 
 	Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
 		("WGEN_Expand_Expr: field id for bit-field exceeds limit"));
-	wn = WN_CreateIload(OPR_ILOAD, rtype,
+        WN* iload_ofst = NULL;
+        if (xtra_BE_ofst != 0)
+          iload_ofst = WGEN_Compose_Offset(component_offset,
+                                           WN_Intconst(Pointer_Mtype, xtra_BE_ofst));
+        else
+          iload_ofst = component_offset;
+	wn = WGEN_CreateIload(OPR_ILOAD, rtype,
 			    is_bit_field ? MTYPE_BS : desc, 
-			    component_offset+xtra_BE_ofst,
+			    iload_ofst,
 			    field_id != 0 ? hi_ty_idx : ty_idx,
 			    Make_Pointer_Type(elem_ty_idx, FALSE),
 			    wn0, field_id);
@@ -9786,6 +10004,8 @@
 	  if (arg_mtype == MTYPE_M) {
 	    arg_mtype = WN_rtype(arg_wn);
 	  }
+          FmtAssert(arg_mtype != MTYPE_M || TY_size(WN_ty(arg_wn)) != -1,
+                    ("WGEN_Expand_Expr: TODO: pass variable length object"));
           arg_wn = WN_CreateParm (Mtype_comparison (arg_mtype), arg_wn,
 		    		  arg_ty_idx, WN_PARM_BY_VALUE);
           WN_kid (call_wn, i++) = arg_wn;
@@ -9950,9 +10170,15 @@
             Is_True(! is_bit_field || field_id <= MAX_FIELD_ID,
                     ("WGEN_Expand_Expr: field id for bit-field exceeds limit"));
  
-	    wn1 = WN_CreateLdid(OPR_LDID, rtype,
+            WN* ldid_ofst = NULL;
+            if (xtra_BE_ofst != 0)
+              ldid_ofst = WGEN_Compose_Offset(component_offset,
+                                               WN_Intconst(Pointer_Mtype, xtra_BE_ofst));
+            else
+              ldid_ofst = component_offset;
+	    wn1 = WGEN_CreateLdid(OPR_LDID, rtype,
 			        is_bit_field ? MTYPE_BS : desc,
-			        ST_ofst(ret_st)+component_offset+xtra_BE_ofst, 
+			        ldid_ofst, 
 				ret_st,
 				(field_id != 0 && component_ty_idx != 0) ?
 				Get_TY (gs_tree_type(exp)) : ty_idx,
@@ -10666,7 +10892,7 @@
 static WN*
 WGEN_Expand_Ptr_To_Member_Func_Call_Expr (gs_t exp, TY_IDX nop_ty_idx,
 					 TYPE_ID rtype, TYPE_ID desc,
-					 WN_OFFSET offset, UINT field_id)
+					 WN* offset, UINT field_id)
 {
   TY_IDX exp_ty_idx = Get_TY(gs_tree_type(exp));
   WN *wn;
@@ -10677,7 +10903,7 @@
   WN *target_wn = WN_Lda(Pointer_Mtype, ST_ofst(st), st);
   WGEN_Expand_Expr(exp, TRUE, nop_ty_idx, exp_ty_idx, 0, 0, FALSE, FALSE,
 		  target_wn);
-  wn = WN_CreateLdid(OPR_LDID, rtype, desc, ST_ofst(st) + offset,
+  wn = WGEN_CreateLdid(OPR_LDID, rtype, desc, offset,
 		     st, exp_ty_idx, field_id);
   return wn;
 }
Index: osprey/wgen/wgen_dst.cxx
===================================================================
--- osprey/wgen/wgen_dst.cxx	(revision 3856)
+++ osprey/wgen/wgen_dst.cxx	(working copy)
@@ -836,12 +836,7 @@
     }
     else {
           if (gs_tree_code(type_size) != GS_INTEGER_CST) {
-            if (gs_tree_code(type_size) == GS_ARRAY_TYPE)
-              Fail_FmtAssertion ("Encountered VLA at line %d", lineno);
-            else
-              Fail_FmtAssertion ("VLA at line %d not currently implemented", 
-		lineno);
-            tsize = 0;
+            tsize = -1;
           }
           else
             tsize = gs_get_integer_value(type_size) / BITSPERBYTE;
@@ -1737,12 +1732,8 @@
    }
    else {
 		if (gs_tree_code(type_size) != GS_INTEGER_CST) {
-			if (gs_tree_code(type_tree) == GS_ARRAY_TYPE)
-				DevWarn ("Encountered VLA at line %d", lineno);
-			else
-				Fail_FmtAssertion ("VLA at line %d not currently implemented", lineno);
 			variable_size = TRUE;
-			tsize = 0;
+			tsize = -1;
 		}
 		else
 			tsize = gs_get_integer_value(type_size) / BITSPERBYTE;
Index: osprey/wgen/wgen_expr.h
===================================================================
--- osprey/wgen/wgen_expr.h	(revision 3856)
+++ osprey/wgen/wgen_expr.h	(working copy)
@@ -68,7 +68,7 @@
 			     bool need_result = TRUE,
 			     TY_IDX nop_ty_idx = 0,
 			     TY_IDX component_ty_idx = 0,
-			     INT64 component_offset = 0,
+			     WN* component_offset = NULL,
 			     UINT32 field_id = 0,
 			     bool is_bit_field = FALSE,
 			     bool is_aggr_init_via_ctor = FALSE
@@ -90,7 +90,7 @@
 				    WN* lhs_retval,
 				    bool need_result,
 				    TY_IDX component_ty_idx,
-				    INT64 component_offset,
+				    WN* component_offset,
 				    UINT32 field_id,
 				    bool is_bit_field,
 				    WN *rhs_wn,
