How Do I Write Bitness Agnostic ^VAL Code?
Keywords: ^VAL, return value
Topics: 64bit, 32bit
Consider the following toy program:
main record workVars kernel32Handle, D_ADDR processHeap, i8 endrecord proc kernel32Handle = %dll_open( "Kernel32" ) processHeap = GetProcessHeap(kernel32Handle) xcall dll_close(kernel32Handle) nop endmain function GetProcessHeap ,^val kernel32Handle, D_ADDR endparams proc freturn %dll_call(kernel32Handle, DLL_TYPE_WINAPI, "GetProcessHeap") end
This particular function works in both 64bit and 32bit Synergy. However in 32bit Synergy it is wasteful that processHeap is defined as an i8.
^VAL functions (https://www.synergex.com/docs/versions/v111/index.htm#lrm/lrmChap7Writingsubroutinesandfunctions.htm#%5EVAL%20functions) are defined as returning "...an integer value that is the natural integer size of the machine. That is, for a 32-bit machine, it returns an i4; for a 64-bit machine, it returns an i8."
We are looking for something similar to D_ADDR for ^VAL functions to allow us to write bit-agnostic code.
At the end of the day, D_ADDR is defined as being aligned to the bitness of the machin, so, IMHO, the ^VAL is agnositic unless you want to be specific and return an I4.
@Mark Vinten
> unless you are holding onto those values in a large array for an extended period of time.
*grin*
"If a feature was available to us, it was used and abused, in all sorts of unique and interesting ways" - Ace Olszowka Synergex DevPartner 2018 "Computers Unlimited's Journey to Continuous Integration"
Also consider storage into long lived structures, inserted into a repository, or even better into a database.
> At the end of the day, D_ADDR is defined as being aligned to the bitness of the machin, so, IMHO, the ^VAL is agnositic unless you want to be specific and return an I4.
We need an equivalent of D_ADDR to serve as the return type for ^VAL functions.
In the above example D_ADDR could be (ab)used to serve as the return value of ^VAL functions but that would not be inline with how it is documented to behave.
There is a newly created tracker, for release in the next developer build after 11.1.1a, which adds a -W4 truncation warning to inform when a function/routine, whose return type is ^VAL, could potentially truncate the value to a d2/d4/i1/i2/i4 variable. However, this warning will also appear on lines where the developer correctly used ^VAL as intended and the implicit truncation was expected. An (int) cast or (d) cast can be added in the code to remove this warning for those valid cases. There are similar truncation warnings that can be enabled in C++ compilers e.g. the int=strlen(string) returning a 64-bit size_t on 64-bit platforms. We do turn them on to find outliers on occasion and then disable them again. Like those warnings in C++, this warning should help identify areas in code where truncation is happening. You can then identify if it is a valid case of truncation and add a cast (int) or (d) or fix the code. This should help resolve the problem you are trying to fix.
To try and follow up on this; in .NET we'd use INTPTR as you mentioned; when using ^VAL what are we supposed to use? D_ADDR does not seem like the correct structure to use.