[M3devel] m3_load/m3_store/bit_field_ref lose offset??

Tony Hosking hosking at cs.purdue.edu
Wed Nov 12 21:46:53 CET 2008


Jay, do you have access to an AMD64_DARWIN box?   I did get things  
working on that 64-bit platform.   Or is it an endianness issue you  
are dealing with.  In any case, I will not have a lot of bandwidth for  
doing much in the way of tackling this unless it becomes critical path  
for me soon.

Antony Hosking | Associate Professor | Computer Science | Purdue  
University
305 N. University Street | West Lafayette | IN 47907 | USA
Office +1 765 494 6001 | Mobile +1 765 427 5484



On 12 Nov 2008, at 07:57, Jay wrote:

> Target.Little_endian is used to drive some target-specificity in the  
> IR.
>    I guess, after all, that is why you have to specify it.
>
> The IR for RTLinker.m3 is identical for MIPS64_OPENBSD and  
> SPARC64_SOLARIS, once I set them both to unaligned_procedures, which  
> they both need. (Tangent, I ran m3cgcat on the .ms file a few times  
> instead of the .mc file; that makes it crash.)
>
> I can't claim SPARC64_SOLARIS is any paragon of working and correct  
> though, by far.
> I should also be able to compare with SPARC64_OPENBSD, I forgot  
> about that, and didn't have an m3cg.
> I only ran SPARC64_SOLARIS far enough to discover it needed  
> unaligned procedures.
> I think I should fork linux-common and solaris-common off of the  
> minimal 29k openbsd-common, rather than worry about all the stuff in  
> solaris-2-x and linux-libc, over 100k each. Then SPARC64_SOLARIS  
> could/would be in better shape probably.
>
> MIPS64_OPENBSD cm3 gets further with unaligned_procedures, along  
> with the parse.c fix -- it gets to a bus error in RunMainBody.
> Again an alignment problem, though I think maybe memory memory  
> trashing.
> The fault occurs here:
>
>     desc_offset := init_depth * ADRSIZE (InitDesc);
>
>       desc := init_stack + desc_offset;
>       init_depth := desc.low_link; <<
>
>   InitDesc = RECORD
>     module   : RT0.ModulePtr;
>     low_link : INTEGER;
>   END;
>
> desc_offset appears to not be a multiple of 4.
>
> I will look into that.
>
> Long story short -- consider again the parse.c change?
> I admit I still haven't debugged it (or rather, the code that  
> consumes the data produced by it).
>
>  - Jay
>
>
>
> From: jay.krell at cornell.edu
> To: hosking at cs.purdue.edu
> CC: m3devel at elegosoft.com
> Subject: RE: [M3devel] m3_load/m3_store/bit_field_ref lose offset??
> Date: Sun, 9 Nov 2008 11:10:54 +0000
>
> I agree. I am suspicious too. I will investigate more. Thanks.
>
>  - Jay
>
>
>
>
> From: hosking at cs.purdue.edu
> To: jay.krell at cornell.edu
> Date: Sun, 9 Nov 2008 10:01:58 +0000
> CC: m3devel at elegosoft.com
> Subject: Re: [M3devel] m3_load/m3_store/bit_field_ref lose offset??
>
>
>
> Aren't the integer values supposed to be written endian- 
> independently in the IR?  I am suspicious about these differences.
>
> On 9 Nov 2008, at 01:25, Jay wrote:
>
> Thanks for the tip/direction.
>
> Uncertain -- m3cgcat between AMD64_LINUX and MIPS64_OPENBSD are "the  
> same" but for two systematic diffs:
>
>  - AMD64_LINUX has a bunch of added calls to check_nil.
>    This is a "bug" in it, inoptimal but ok code, because "first  
> readable address" is 0. It should probably be 4k. I should write a  
> program that iterates starting at 0 to find the value.
>   (or better yet, cm3 should have a -configure option that does  
> this? -- for configuration values for which there is a safe default;  
> in general, imho, the targets should be auto configured via C,  
> assuming there is a native development environment available).
>
>  - some integers are different (again, systematically)
>
> AMD64_LINUX:
>  init_int  656 13 Int.64
>  init_chars  664 "    typecode "
>  init_int  680 2 Int.64
>  init_var  688 v.1 0
>  init_int  696 13 Int.64
>  init_chars  704 "    typeid   "
>  init_int  720 2 Int.64
>  init_var  728 v.1 0
>  init_int  736 13 Int.64
>  init_chars  744 "RunMainBody: "
>  init_int  760 2 Int.64
>  init_var  768 v.1 0
>  init_int  776 19 Int.64
>  init_chars  784 "RunMainBody: exec: "
>  init_int  808 2 Int.64
>  init_var  816 v.1 0
>  init_int  824 17 Int.64
>  init_chars  832 "ExpandInitStack: "
>
> MIPS64_OPENBSD:
>
>  init_chars  664 "    typecode "
>  init_int  680 8796093022208 Int.64
>  init_var  688 v.1 0
>  init_int  696 13 Int.64
>  init_chars  704 "    typeid   "
>  init_int  720 8796093022208 Int.64
>  init_var  728 v.1 0
>  init_int  736 13 Int.64
>  init_chars  744 "RunMainBody: "
>  init_int  760 8796093022208 Int.64
>  init_var  768 v.1 0
>  init_int  776 19 Int.64
>  init_chars  784 "RunMainBody: exec: "
>  init_int  808 8796093022208 Int.64
>  init_var  816 v.1 0
>
> This 8796093022208 is 80000000000 aka 0000_0800_0000_0000, where  
> little endian has 2.
>
> I don't know what these numbers represent.
> I should look at other systems -- preferably a working 64 bit big  
> endian system, if there are any.
>
> Could be flags/type with text literals?
>
> (Btw, I always leave the TextLiteral.i3 change on my system,  
> lowering the maximum literal length to around 4gig even on 64 bit  
> targets, so 32 bit can bootstrap 64 bit...need to fix the compiler  
> here to do target arithmetic instead of host arithmetic...)
>
> Thanks,
>  - Jay
>
>
> From: hosking at cs.purdue.edu
> To: jay.krell at cornell.edu
> Date: Sat, 8 Nov 2008 22:55:54 +0000
> CC: m3devel at elegosoft.com
> Subject: Re: [M3devel] m3_load/m3_store/bit_field_ref lose offset??
>
> Have you checked to make sure that the pre-gcc IR makes sense?  Does  
> it see these values as 32-bit or 64-bit?  The reason I ask is that  
> there may be something wrong in your m3middle target specs that  
> cause bad IR.  Once we know the IR looks right then we can try and  
> fix the problem.
>
> Antony Hosking | Associate Professor | Computer Science | Purdue  
> University
> 305 N. University Street | West Lafayette | IN 47907 | USA
> Office +1 765 494 6001 | Mobile +1 765 427 5484
>
>
>
> On 8 Nov 2008, at 15:45, Jay wrote:
>
>
> truncated as usual...along with losing a lot of whitespace..
> Let's see...
>
>
> Tony, how about switching these #if's?
> I explain some of why below.
>
> static void
> m3_store (tree v, int o, tree src_t, m3_type src_T, tree dst_t,  
> m3_type dst_T)
> {
>  tree val;
> #if 0
>  if (o != 0 || TREE_TYPE (v) != dst_t) {
>    v = m3_build3 (BIT_FIELD_REF, dst_t, v, TYPE_SIZE (dst_t),
>     bitsize_int (o));
>  }
> #else
>  /* failsafe, but inefficient */
>  if (o != 0 || TREE_TYPE (v) != dst_t) {
>    v = m3_build1 (ADDR_EXPR, t_addr, v);
>    v = m3_build2 (PLUS_EXPR, t_addr, v, size_int (o / BITS_PER_UNIT));
>    v = m3_build1 (INDIRECT_REF, dst_t,
>     m3_cast (build_pointer_type (dst_t), v));
>  }
> #endif
>  TREE_THIS_VOLATILE (v) = 1; /* force this to avoid aliasing  
> problems */
>  val = m3_cast (src_t, EXPR_REF (-1));
>  if (src_T != dst_T) {
>    val = m3_build1 (CONVERT_EXPR, dst_t, val);
>  }
>  add_stmt (build2 (MODIFY_EXPR, dst_t, v, val));
>  EXPR_POP ();
> }
> m3_load (tree v, int o, tree src_t, m3_type src_T, tree dst_t,  
> m3_type dst_T)
> {
> #if 0
>  if (o != 0 || TREE_TYPE (v) != src_t) {
>    v = m3_build3 (BIT_FIELD_REF, src_t, v, TYPE_SIZE (src_t),
>     bitsize_int (o));
>  }
> #else
>  /* failsafe, but inefficient */
>  if (o != 0 || TREE_TYPE (v) != src_t) {
>    v = m3_build1 (ADDR_EXPR, t_addr, v);
>    v = m3_build2 (PLUS_EXPR, t_addr, v, size_int (o / BITS_PER_UNIT));
>    v = m3_build1 (INDIRECT_REF, src_t,
>     m3_cast (build_pointer_type (src_t), v));
>  }
> #endif
>  TREE_THIS_VOLATILE (v) = 1; /* force this to avoid aliasing  
> problems */
>  if (src_T != dst_T) {
>    v = m3_build1 (CONVERT_EXPR, dst_t, v);
>  }
>  EXPR_PUSH (v);
> }
>
> I'm working on MIPS64_OPENBSD (OpenBSD on an SGI O2).
> In an early version it seems that many loads/stores of global  
> variables is wrong.
> The "first" code affected is RTLinker_ExpandModuleTable.
>
> PROCEDURE ExpandModuleTable () =
>  CONST InitialTableSize = 500;
>  VAR new_mods: ADDRESS;  n_bytes: INTEGER;
>  BEGIN
>    IF (modules = NIL) THEN
>      (* first time... *)
>      max_modules := InitialTableSize;
>      modules := Cstdlib.malloc (InitialTableSize * BYTESIZE  
> (RT0.ModulePtr));
>      IF (modules = NIL) THEN Cstdlib.abort (); END;
>    ELSE
>      n_bytes := max_modules * BYTESIZE (RT0.ModulePtr);
>      new_mods := Cstdlib.malloc (n_bytes + n_bytes);
>      IF (new_mods = NIL) THEN Cstdlib.abort (); END;
>      EVAL Cstring.memcpy (new_mods, modules, n_bytes);
>      Cstdlib.free (modules);
>      modules := new_mods;
>      INC (max_modules, max_modules);
>    END;
>  END ExpandModuleTable;
>
> It should read back modules as NIL.
> What happens is it reads back modules as not NIL,
> and then max_modules should also be zero, but is "large", leading to  
> malloc to fail,
> and abort called.
>
> The output of cm3cg -y is reasonable.
> It indicates offset loads.
>
> What is incorrect is that in many loads and stores, but not all, the
> offsets are lost.
>
> (923) begin_procedure
>  procedure RTLinker__ExpandModuleTable
> RTLinker__ExpandModuleTable(924) set_source_line
>  source line  208
> (925) load_nil
> (926) store
>  store (M3_AJWxb1_new_mods) offset 0x0 src_t 0xb dst_t 0xb
> (927) set_source_line
>  source line  207
> (928) set_source_line
>  source line  210
> (929) load_nil
> (930) load
>  m3cg_load (MM_RTLinker): offset 0x440, convert 0xb -> 0xb
>
> Here is the incorrect code:
>
> .globl RTLinker__ExpandModuleTable
> .stabd 46,0,0
> .stabn 68,0,206,.LM108
> .LM108:
> .LFBB8:
> .set nomips16
> .ent RTLinker__ExpandModuleTable
> RTLinker__ExpandModuleTable:
> .frame $fp,64,$31  # vars= 32, regs= 3/0, args= 0, gp= 0
> .mask 0xd0000000,-8
> .fmask 0x00000000,0
> daddiu $sp,$sp,-64
> sd $31,56($sp)
> sd $fp,48($sp)
> sd $28,40($sp)
> move $fp,$sp
> lui $28,%hi(%neg(%gp_rel(RTLinker__ExpandModuleTable)))
> daddu $28,$28,$25
> daddiu $28,$28,%lo(%neg(%gp_rel(RTLinker__ExpandModuleTable)))
> .LBB9:
> .stabn 68,0,208,.LM109
> .LM109:
> sd $0,16($fp)
> .stabn 68,0,210,.LM110
> .LM110:
> dla $2,MM_RTLinker
> ld $2,0($2)      << WRONG
> bne $2,$0,.L61
> .stabn 68,0,212,.LM111
> .LM111:
> dla $3,MM_RTLinker
> ld $2,128($3)
> andi $2,$2,0x0
> ori $2,$2,0x1f4
> sd $2,128($3)
> .stabn 68,0,213,.LM112
> .LM112:
> li $4,4000   # 0xfa0
> jal malloc
> sd $2,0($fp)
> ld $4,0($fp)
> dla $3,MM_RTLinker
> ld $2,136($3)
> andi $2,$2,0x0
> or $2,$4,$2
> sd $2,136($3)     << OK, offset seems low, but it agrees with  
> elsewhere
> .stabn 68,0,214,.LM113
> .LM113:
> dla $2,MM_RTLinker
> ld $2,0($2)       << WRONG
> bne $2,$0,.L65
> jal abort
> b .L65
> .L61:
> .stabn 68,0,216,.LM114
> .LM114:
> dla $2,MM_RTLinker
> ld $2,0($2)        << WRONG
> dsll $2,$2,3
> sd $2,8($fp)
> .stabn 68,0,217,.LM115
> .LM115:
> ld $3,8($fp)
> ld $2,8($fp)
> daddu $2,$3,$2
> move $4,$2
> jal malloc
> sd $2,0($fp)
> ld $2,0($fp)
> sd $2,16($fp)
> .stabn 68,0,218,.LM116
> .LM116:
> ld $2,16($fp)
> bne $2,$0,.L64
> jal abort
> .L64:
> .stabn 68,0,219,.LM117
> .LM117:
> ld $4,16($fp)
> dla $2,MM_RTLinker
> ld $2,0($2)          << WRONG
> ld $3,8($fp)
> move $5,$2
> move $6,$3
> jal memcpy
> sd $2,0($fp)
> .stabn 68,0,220,.LM118
> .LM118:
> dla $2,MM_RTLinker
> ld $2,0($2)           << WRONG
> move $4,$2
> jal free
> .stabn 68,0,221,.LM119
> .LM119:
> ld $4,16($fp)
> dla $3,MM_RTLinker
> ld $2,136($3)         << OK
> andi $2,$2,0x0
> or $2,$4,$2
> sd $2,136($3)         << OK
> .stabn 68,0,222,.LM120
> .LM120:
> dla $2,MM_RTLinker
> ld $3,0($2)           << WRONG
> dla $2,MM_RTLinker
> ld $2,0($2)           << WRONG
> daddu $4,$3,$2
> dla $3,MM_RTLinker
> ld $2,128($3)         << OK
> andi $2,$2,0x0
> or $2,$2,$4
> sd $2,128($3)         << OK
> .L65:
> .LBE9:
> .stabn 68,0,224,.LM121
> .LM121:
> move $sp,$fp
> ld $31,56($sp)
> ld $fp,48($sp)
> ld $28,40($sp)
> daddiu $sp,$sp,64
> j $31
> .end RTLinker__ExpandModuleTable
>
> Here is corrected code:
>
> RTLinker__ExpandModuleTable:
> .frame $fp,64,$31  # vars= 32, regs= 3/0, args= 0, gp= 0
> .mask 0xd0000000,-8
> .fmask 0x00000000,0
> daddiu $sp,$sp,-64
> sd $31,56($sp)
> sd $fp,48($sp)
> sd $28,40($sp)
> move $fp,$sp
> lui $28,%hi(%neg(%gp_rel(RTLinker__ExpandModuleTable)))
> daddu $28,$28,$25
> daddiu $28,$28,%lo(%neg(%gp_rel(RTLinker__ExpandModuleTable)))
> .LBB9:
> .stabn 68,0,208,.LM109
> .LM109:
> sd $0,16($fp)
> .stabn 68,0,210,.LM110
> .LM110:
> dla $2,MM_RTLinker
> daddiu $2,$2,136     << CORRECT (offset seems low, but at least it  
> isn't zero)
> ld $2,0($2)
> bne $2,$0,.L61
> .stabn 68,0,212,.LM111
> .LM111:
> dla $2,MM_RTLinker
> daddiu $3,$2,128     << CORRECT
> li $2,500   # 0x1f4
> sd $2,0($3)
> .stabn 68,0,213,.LM112
> .LM112:
> li $4,4000   # 0xfa0
> jal malloc
> sd $2,0($fp)
> dla $2,MM_RTLinker
> daddiu $3,$2,136      << CORRECT
> ld $2,0($fp)
> sd $2,0($3)
> .stabn 68,0,214,.LM113
> .LM113:
> dla $2,MM_RTLinker
> daddiu $2,$2,136      << CORRECT
> ld $2,0($2)
> bne $2,$0,.L65
> jal abort
> b .L65
> .L61:
>
> I still dump core with this change, but I get much further.
> I have not tested this change at all otherwise -- i.e. on working  
> platforms.
>
> I have not debugged through the gcc/m3cg code to see why
> the offsets are only sometimes lost, or why other platforms
> have no problem. Is MIPS's "global pointer" unusual these days?
> I know SPARC has similar, and all the non-x86, non-AMD64 NT platforms
> had similar, but that's essentially nothing now (I'm not counting  
> IA64).
> I know Linux has PLT (procedure linkage table) and GOT (global  
> offset table).
> Same thing?
> I haven't looked much at other MIPS ports yet.
>
> http://modula3.elegosoft.com/cgi-bin/cvsweb.cgi/cm3/m3-sys/m3cc/gcc/gcc/m3cg/parse.c.diff?r1=1.7;r2=1.8
>
> is what made it look about like it does -- in particularing using  
> BIT_FIELD_REF.
>
> 1.7:
>
> static void m3_load (v, o, src_t, src_T, dest_t, dest_T) /* GCC32OK */
>     tree v;
>     int o;
>     tree src_t, dest_t;
>     m3_type src_T, dest_T;
> {
>  if (o == 0 && TREE_TYPE (v) == src_t) {
>    EXPR_PUSH (v);
>  } else {
>    tree adr = m3_build1 (ADDR_EXPR, t_addr, v);
>    if (o != 0) {
>      adr = m3_build2 (PLUS_EXPR, t_addr, adr, size_int (o /  
> BITS_PER_UNIT));
>    }
>    EXPR_PUSH (m3_build1 (INDIRECT_REF, src_t,
>                          m3_cast (build_pointer_type (src_t), adr)));
>  }
> #if 1
>  if (src_T != dest_T) {
>    EXPR_REF (-1) = m3_build1 (CONVERT_EXPR, dest_t, EXPR_REF (-1));
>  }
>  if (debug_vars) {
>    const char *name = "noname";
>    if (v != 0 && DECL_NAME(v) != 0) {
>      name = IDENTIFIER_POINTER(DECL_NAME(v));
>    }
>    fprintf(stderr, "  m3_load (%s): offset %d, convert %d -> %d\n",  
> name,
>            o, src_T, dest_T);
>  }
> #else
>  if (src_T != dest_T) {
>    if (IS_INTEGER_TYPE(dest_T) && dest_t != t_int) {
>      EXPR_REF (-1) = m3_build1 (CONVERT_EXPR, t_int, EXPR_REF (-1));
>    } else if (IS_WORD_TYPE(dest_T) && dest_t != t_word) {
>      EXPR_REF (-1) = m3_build1 (CONVERT_EXPR, t_word, EXPR_REF (-1));
>    } else if (IS_INTEGER_TYPE(dest_T) || IS_WORD_TYPE(dest_T)) {
>      /* okay */
>    } else {
>      fatal_error("m3load: cannot convert types: src_t %d dest_t %d\n",
>                  src_T, dest_T);
>    }
>  }
> #endif
> }
> static void
> m3_store (v, o, src_t, dest_t)  /* GCC32OK */
>     tree v;
>     int o;
>     tree src_t, dest_t;
> {
>  tree lhs, rhs;
>  if (TREE_TYPE (EXPR_REF (-1)) == src_t) {
>    rhs = EXPR_REF (-1);
>  } else {
>    rhs = m3_cast (src_t, EXPR_REF (-1));
>  }
>  if (o == 0 && TREE_TYPE (v) == dest_t) {
>    lhs = v;
>  } else {
>    tree f = make_node (FIELD_DECL);
>    TREE_TYPE (f) = dest_t;
>    DECL_ALIGN (f) = TYPE_ALIGN (dest_t);
>    DECL_SIZE (f) = TYPE_SIZE (dest_t);
>    DECL_MODE (f) = TYPE_MODE (dest_t);
>    DECL_FIELD_OFFSET (f) = size_int (o / BITS_PER_UNIT);
>    DECL_FIELD_BIT_OFFSET (f) = bitsize_int (o % BITS_PER_UNIT);
>    DECL_FIELD_CONTEXT (f) = TREE_TYPE (v);
>    lhs = m3_build2 (COMPONENT_REF, dest_t, v, f);
>  }
> #if 1
>    expand_assignment (lhs, m3_build1 (CONVERT_EXPR, dest_t, rhs), 0,  
> 0);
> #else
>  if (dest_t ==  NULL) {
>    expand_assignment (lhs, rhs, 0, 0);
>  } else {
>    expand_assignment (lhs, m3_build1 (CONVERT_EXPR, dest_t, rhs), 0,  
> 0);
>  }
> #endif
>  EXPR_POP ();
> }
>
> 1.8:
> static void
> m3_load (tree v, int o,
>  tree src_t, m3_type src_T,
>  tree dst_t, m3_type dst_T) /* GCC32OK */
> {
>  if (o == 0 && TREE_TYPE (v) == src_t) {
>    EXPR_PUSH (v);
>  } else {
>    EXPR_PUSH (m3_build3 (BIT_FIELD_REF, src_t, v, TYPE_SIZE (src_t),
>     bitsize_int (o)));
>  }
>  if (src_T != dst_T) {
>    EXPR_REF (-1) = m3_build1 (CONVERT_EXPR, dst_t, EXPR_REF (-1));
>  }
>  if (option_vars_trace) {
>    const char *name = "noname";
>    if (v != 0 && DECL_NAME(v) != 0) {
>      name = IDENTIFIER_POINTER(DECL_NAME(v));
>    }
>    fprintf(stderr, "  m3_load (%s): offset %d, convert %d -> %d\n",  
> name,
>     o, src_T, dst_T);
>  }
> }
> static void
> m3_store (tree v, int o, tree src_t, tree dst_t)  /* GCC32OK */
> {
>  tree lhs, rhs;
>  if (TREE_TYPE (EXPR_REF (-1)) == src_t) {
>    rhs = EXPR_REF (-1);
>  } else {
>    rhs = m3_cast (src_t, EXPR_REF (-1));
>  }
>  if (o == 0 && TREE_TYPE (v) == dst_t) {
>    lhs = v;
>  } else {
>    lhs = m3_build3 (BIT_FIELD_REF, dst_t, v, TYPE_SIZE (dst_t),
>       bitsize_int (o));
>  }
>  if (src_t != dst_t) {
>    rhs = m3_build1 (CONVERT_EXPR, dst_t, rhs);
>  }
>  expand_assignment (lhs, rhs, 0, 0);
>  EXPR_POP ();
> }
>
> - Jay
>
> <AMD64_LINUX_RTLinker.mc><MIPS64_OPENBSD_RTLinker.mc>
>
>

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://m3lists.elegosoft.com/pipermail/m3devel/attachments/20081112/6950a8b4/attachment-0002.html>


More information about the M3devel mailing list