BrowserUk has asked for the wisdom of the Perl Monks concerning the following question:

I use 64-bit Windows and have sufficient physical memory to benefit considerably from doing so. But, when compiling many *nix-developed code(*), for 64-bit, I encounter myriad warnings and some outright errors, because of the difference between the compilation data models used by the two platforms.

Specifically,

Regardless of the wisdom or superiority of one choice over the other, the situation exists and has to be lived with. Currently:

I've been looking into what it would take to try and fix-up the warnings for Perl64. The problem lies in the pervasive assumption that a pointer will fit in a long. Ostensibly, the fix is define any typedef or variable that must accept a pointer as a long long rather than a long, but it is never quite that simple.

So, to the question.

Does anyone know of any good discussion/wisdom/examples of coding for LP64 .v. LLP64 portability?

(*)To give topical reference: Perl and Parrot suffer this.

Replies are listed 'Best First'.
Re: [OT] LLP64 .v. LP64 portability
by ikegami (Patriarch) on Apr 21, 2010 at 05:35 UTC

    The Perl approach is to create a type that's large enough to store an int or a pointer: IV. Apparently, it's not used properly everywhere, or it's misconfigured in your environment.

    I know that there were a number of places where I32 was used where it shouldn't, and IV values were assigned to STRLEN variables, even though the latter can be smaller. I fixed those problems in substr for 5.12.0, but some remain elsewhere.

      I fixed those problems in substr for 5.12.0

      Well done. But--this isn't critism, just a need for understanding--those fixes look very complex in places.

      For example:

      - else { - pos += curlen; - if (num_args < 3) - rem = curlen; - else if (len >= 0) { - rem = pos+len; - if (rem > (I32)curlen) - rem = curlen;

      becomes

      + if (pos1_is_uv || pos1_iv > 0) { + if ((UV)pos1_iv > curlen) + goto BOUND_FAIL; + } + + if (num_args > 2) { + if (!len_is_uv && len_iv < 0) { + pos2_iv = curlen + len_iv; + if (curlen) + pos2_is_uv = curlen-1 > ~(UV)len_iv; + else + pos2_is_uv = 0; + } else { /* len_iv >= 0 */ + if (!pos1_is_uv && pos1_iv < 0) { + pos2_iv = pos1_iv + len_iv; + pos2_is_uv = (UV)len_iv > (UV)IV_MAX; + } else { + if ((UV)len_iv > curlen-(UV)pos1_iv) + pos2_iv = curlen; + else + pos2_iv = pos1_iv+len_iv; + pos2_is_uv = 1; + }

      Is all of that manual tracking whether a integer is signed or unsigned necessary?

      If so, life just got a whole lot tougher for source-divers. That's really nasty!

      but some remain elsewhere.

      I'm currently looking at 1988 (1302 uniq), "possible loss of data" warnings spread across 73 source files in the 5.12.0 release.

      Don't you just wish that C compilers would list the identifier of offending variables!


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        In some C files that I've written, I've suppressed certain warnings with:
        #ifdef _MSC_VER #pragma warning(disable:4700 4715 4716) #endif
        I forget which 3 warnings they equate to - and haven't checked. If it's just a matter of shutting 'em up, without being too particular about the means employed, I think there's a chance that approach could be useful.

        With any luck you'd only need to do it in a few select header files (assuming that many of those 73 source files #include a common header).

        Cheers,
        Rob

        Is all of that manual tracking whether a integer is signed or unsigned necessary?

        The range of numbers substr accepts for its position and length offsets can be greater than the range of signed or unsigned integers.

        Take a system where both IV and STRLEN are 32 bits. The range of the position and length arguments should be -2**32 .. 2**32-1 (33 bits). Even with all that complexity, only -2**31 .. 2**32 (32 bit signed or 32 bit unsigned) is accepted.

        I'm all for simplifying it, but Perl doesn't currently have a type that's twice the size of IV (LONG_IV?) as far as I know. Keep in mind I wrote that under pressure since I took on the task when it was one of the last two or three 5.12 blockers. I took the easiest approach for me ("When all you have is a hammer, every problem looks like a nail.") and the one least likely to cause immediate problems.

        Note that $[ is being removed shortly, so some substr will shrink (but not the bit you posted).