[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