lpwAlign Function

Started by Robert, June 11, 2022, 01:12:10 AM

Previous topic - Next topic

MrBcx

Quote from: Robert on June 12, 2022, 01:54:45 AM
Hi MrBCX:

Very interesting. Here's an lpwAlign snippet that I adapted from the Rufus USB code of Pete 'friggin_microsoft_unicode_amateurs' Batard

   IF Use_Inputbox OR Use_Infobox THEN
      FPRINT FP_WRITE, "LPWORD lpwAlign(LPWORD lpIn)"
      FPRINT FP_WRITE, "{"
      FPRINT FP_WRITE, " return (LPWORD)((((uintptr_t)lpIn) + 3) & (~3));"
      FPRINT FP_WRITE, "}\n\n"
   END IF


Code Elegance!  A clear winner!!

Also, Pete's Github has much to explore!!!


Robert

Hi MrBCX:

Very interesting. Here's an lpwAlign snippet that I adapted from the Rufus USB code of Pete 'friggin_microsoft_unicode_amateurs' Batard

   IF Use_Inputbox OR Use_Infobox THEN
      FPRINT FP_WRITE, "LPWORD lpwAlign(LPWORD lpIn)"
      FPRINT FP_WRITE, "{"
      FPRINT FP_WRITE, " return (LPWORD)((((uintptr_t)lpIn) + 3) & (~3));"
      FPRINT FP_WRITE, "}\n\n"
   END IF

MrBcx

#2
Hi Robert,

First off, here are my settings for my MING batch files,  the 32-bit batch uses -m32.


SET FLAGS=  -m64 -s -ofast -Wall -Wextra -D__USE_MINGW_ANSI_STDIO=1 -D NTDDI_VERSION=0x0A000000 -D_WIN32_WINNT=0x0A000000  -fms-extensions -Wno-write-strings -funroll-loops 
SET LIBS= -lshell32 -lcomctl32 -lcomdlg32 -lmsimg32 -lole32 -loleaut32 -luuid -luser32 -lgdi32 -lkernel32 -ladvapi32  -lurl -limagehlp -lws2_32 -lwinmm -lwininet  -lurlmon


From the Help file, I used this one-liner as a test:


MSGBOX INPUTBOX$("So Tell Me ...", "Do you like BCX?", "Yes!"),"BCX!",0


Using BCX 789, I get a completely silent compile/link with 64-bit and, like you, I get the warnings in 32-bit.

Based on a thread in SO, I came up with this replacement which results in a silent compile/link in 32-bit and 64-bit.


LPWORD lpwAlign (LPWORD lpIn)
{
  char *ul = {0};
  ul=(char*)lpIn;
  while((*((char*)&ul))&3)
  {
    ul++;
  }
  return (LPWORD)ul;
}


Unless there are objections, I will include my changes in the next version of BCX.


References:
https://stackoverflow.com/questions/8824622/fix-for-dereferencing-type-punned-pointer-will-break-strict-aliasing


and this:



C99 6.5 7:

    An object shall have its stored value accessed only by an lvalue expression that has one of the following types:
    — a type compatible with the effective type of the object,
    — a qualified version of a type compatible with the effective type of the object,
    — a type that is the signed or unsigned type corresponding to the effective type of the object,
    — a type that is the signed or unsigned type corresponding to a qualified version of the effective type of the object,
    — an aggregate or union type that includes one of the aforementioned types among its members
           (including, recursively, a member of a subaggregate or contained union), or
    — a character type.



Robert

Hi BCX BASIC Coders:

I am seeking opinions because I am uncertain if it would be wise that the lpwAlign function be changed from

   IF Use_Inputbox OR Use_Infobox THEN
      FPRINT FP_WRITE, "LPWORD lpwAlign (LPWORD lpIn)"
      FPRINT FP_WRITE, "{"
      FPRINT FP_WRITE, "  BYTE *ul = {0};"
      FPRINT FP_WRITE, "  ul=(BYTE*)lpIn;"
      FPRINT FP_WRITE, "  while((*((ULONGLONG*)&ul))&3)"
      FPRINT FP_WRITE, "  {"
      FPRINT FP_WRITE, "    ul++;"
      FPRINT FP_WRITE, "  }"
      FPRINT FP_WRITE, "  return (LPWORD)ul;"
      FPRINT FP_WRITE, "}\n\n"
   END IF


to

   IF Use_Inputbox OR Use_Infobox THEN
      FPRINT FP_WRITE, "LPWORD lpwAlign(LPWORD lpIn)"
      FPRINT FP_WRITE, "{"
      FPRINT FP_WRITE, "  ULONG_PTR ul;"
      FPRINT FP_WRITE, "  ul = (ULONG_PTR)lpIn;"
      FPRINT FP_WRITE, "  ul += 3;"
      FPRINT FP_WRITE, "  ul >>= 2;"
      FPRINT FP_WRITE, "  ul <<= 2;"
      FPRINT FP_WRITE, "  return (LPWORD)ul;"
      FPRINT FP_WRITE, "}\n\n"
   END IF


As is, in BCX 7.8.9, the Equation compiler complains

Quotebc.cpp: In function 'WORD* lpwAlign(LPWORD)':
bc.cpp:4296:12: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
4296 |   while((*((ULONGLONG*)&ul))&3)
      |           ~^~~~~~~~~~~~~~~~

bc.cpp: In function 'WORD* lpwAlign(LPWORD)':
bc.cpp:4296:10: warning: 'ul' is used uninitialized [-Wuninitialized]
4296 |   while((*((ULONGLONG*)&ul))&3)
      |         ~^~~~~~~~~~~~~~~~~~~
bc.cpp:4294:9: note: 'ul' declared here
4294 |   BYTE *ul = {0};
      |         ^~

The History of lpwAlign

In BCX 6.0.8 the lpwAlign function, I.I.R.C., based on Charles Petzold's code
from popedit.c, was

  IF Use_Inputbox OR Use_Infobox THEN
    IF Use_Library THEN FPRINT Outfile,"// BCXRTLIB: lpwAligh"
    FPRINT Outfile,"LPWORD lpwAlign (LPWORD lpIn)"
    FPRINT Outfile,"{"
    FPRINT Outfile,"  ULONG ul;"
    FPRINT Outfile,"  ul=(ULONG)lpIn;"
    FPRINT Outfile,"  ul+=3;"
    FPRINT Outfile,"  ul>>=2;"
    FPRINT Outfile,"  ul<<=2;"
    FPRINT Outfile,"  return (LPWORD)ul;"
    FPRINT Outfile,"}\n\n"
    IF Use_Library THEN FPRINT Outfile,"// ENDBCXRTLIB "
  END IF

 
In BCX 6.1.0, an undocumented change, based I suspect as an attempt at
64 bit compliance, was made to

  IF Use_Inputbox OR Use_Infobox THEN
    IF Use_Library THEN FPRINT Outfile,"// BCXRTLIB: lpwAligh"
    FPRINT Outfile,"LPWORD lpwAlign (LPWORD lpIn)"
    FPRINT Outfile,"{"
    FPRINT Outfile,"  BYTE*  ul;"
    FPRINT Outfile,"  ul=(BYTE*)lpIn;"
    FPRINT Outfile,"  while((ULONGLONG)ul & 3)"
    FPRINT Outfile,"    {"
    FPRINT Outfile,"      ul++;"
    FPRINT Outfile,"    }"
    FPRINT Outfile,"  return (LPWORD)ul;"
    FPRINT Outfile,"}\n\n"
    IF Use_Library THEN FPRINT Outfile,"// ENDBCXRTLIB "
  END IF

 
and again, lpwAlign was slightly modified, undocumented, in BCX 7.4.0.