[sac-user] English Documentation for Calling C from SAC

Scholz, Sven-Bodo s.scholz at herts.ac.uk
Sat Aug 7 10:38:54 CEST 2010

On 07/08/2010 01:56, "Salem Reyen" <salemreyen at yahoo.com> wrote:

> Thank you so much for clear things up Stephan.  Since I may need to pass large
> (GB) size matrices, how can I pass the parameters entirely by reference (for
> saving memory) to a BLAS function?

Yes, you can ! (tm)

Per default, i.e. when you do NOT use a refcounting pragma, you do pass
arrays per reference into a C function and out as well. For this to be safe
the following conventions need to be observed by the C function:

1) arguments (arrays that are passed into the C function) are not modified
in any form (no overwriting behind pointers and no memory ops such as
2) return values (arrays that are returned from your C function) are freshly
allocated (no reuse of argument arrays [no aliasing])!

HOWEVER, there is ONE important exception to this:

IFF you use a linksign pragma to map a return position onto the SAME
argument position you map an argument to

eg   external int[4] foo( int[4] x);
     #pragma linksign [1,1]

(YES you can do this!)

then this expects a function

void foo( int *x);

AND the runtime system of SaC allows you to modify the array behind x in

The caveat of this is that the runtime system of SaC now ensures that by the
time foo is called no other part of the program will ever inspect the
argument again. This may(!) come at the expense of creating a copy!

Example 1:

int main()
  x = [1, 2, 3, 4];
  val = foo( x);
  return( val[0] );

Here, no copy of x will be generated.

Example 2:

int main()
  x = [1, 2, 3, 4];
  val = foo( x);
  return( val[0] + bar(x) );

Here, x is copied prior to the call to foo!

So, you only should use this mapping trick if you want to modify only a
small portion of data!

> Thanks again for the big help,
> Salem
> P.S.  My understanding (and I could be wrong) is that SAC does not support
> call by reference for calling a SAC function.  Then in actual C translation,
> can SAC compiler clever enough to pass a read-only parameter by reference?

Yes, all arguments are passed by reference. Copies are delayed to the moment
when existing arrays are to be modified and further references exist
elsewhere; very much in the same way as described for external functions


PS: if you create a SaC-binding for BLAS we'd be very interested in adding
that to the stdlib! :-)

> --- On Fri, 8/6/10, Herhut, Stephan <s.a.herhut at herts.ac.uk> wrote:
>> From: Herhut, Stephan <s.a.herhut at herts.ac.uk>
>> Subject: Re: [sac-user] English Documentation for Calling C from SAC
>> To: "Salem Reyen" <salemreyen at yahoo.com>, "sac-user at sac-home.org"
>> <sac-user at sac-home.org>
>> Date: Friday, August 6, 2010, 10:23 AM
>> Dear Salem,
>> unfortunately no such documentation exists at the moment. There is a German
>> master¹s thesis but that is outdated, too.
>> We have not tried to use a BLAS C implementation in SAC. However, we have
>> implemented some of the BLAS routines in SAC itself. It would be great to see
>> how the two approaches compare. From our experience, if one compares single
>> primitives, BLAS C implementations will almost always win as they have been
>> tuned to the extreme. The power of an optimising compiler like sac2c only
>> plays out as soon as multiple primitives are called in sequence. Only then
>> additional optimisation potential arises.
>> You can find our BLAS implementation in the standard library
>> (modules/numerical/blas).
>> Let my try to give you a brief intro into the C interface. This should
>> suffice
>> to integrate BLAS. As an example, consider the string module in the standard
>> library (modules/structures/String.sac). In that file, the SAC function
>> strtoi
>> is defined as follows:
>> external int, string strtoi(string S, int BASE);
>> As the keyword external gives away, the function is not implemented in SAC
>> but
>> some other language. The compiler does not actually care what language that
>> is, as long as it uses C calling conventions. To declare an external
>> functions, one simply provides its signature prefixed with the keyword
>> external.
>> By just using the line above, the SAC compiler will make some assumptions on
>> how to map the function to an actual C function. Firstly, it will map return
>> values and arguments from the SAC side to arguments only on the C side. This
>> is done to map the multiple return values of SAC to the C word. So, for the
>> above example, the resulting C prototype would be
>> void strtoi( int *res1, char **res2, char *S, int BASE);
>> As you can see, the return values have been mapped into reference arguments.
>> Often, this is not desired, like in the example of BLAS where the signatures
>> are fixed. For those cases, we provide a means to remap SAC results/arguments
>> to C results/arguments. For the above example, the following pragma is used
>> in
>> the standard library:
>>     #pragma linksign [0,1,2,3]
>> Pragmas in general directly follow an external function declaration. In this
>> case, we use the linksign pragma. It maps each result/argument in SAC to the
>> corresponding C result/arguments by means of a permutation vector. So, to
>> achieve the desired C signature of strtoi, we want to have the first SAC
>> result to be mapped to the C result and the arguments to be mapped in the
>> same
>> order. This is done using the permutation vector [0,1,2,3].  Position zero
>> thereby represents the C function return value and numbers from one onwards
>> are the function arguments. Using that vector, we get
>> int strtoi( char **res1, char *S, int BASE)
>> which is the standard C signature for that function. As you might guess, SAC
>> by default uses the permutation vector [1,2,...].
>> There are some more tuneable settings:
>>     #pragma linkname " SACstrtoi"
>> The linkname pragma allows to use a different C function name. Using the
>> above
>> pragma, we would get
>> int SACstrtoi( char **res1, char *S, int BASE);
>> Further two pragmas handle linking:
>>     #pragma linkobj "src/String/strtoi.o"
>> would instruct the compiler to link the given file whenever the function is
>> required in a program. Similarly
>>     #pragma linkobj "mylib"
>> would make the compiler link the final executable against the specified
>> library. The library is looked for in the search path configured in the
>> sac2crc resource file. The default paths for system wide libraries are
>> preconfigured. By editing or creating a .sac2crc file in your home directory
>> and adding the following lines
>> target default:
>> EXTLIBPATH       := ³path1:path2:pathn²
>> you can add additional paths to the search. A description of all valid field
>> in that file can be found in its master copy in the setup subdirectory of the
>> sac2c compiler.
>> Lastly, there is a the
>> #pragma refcounting [0,1,2]
>> pragma. This configures whether parameters are passed by value or reference.
>> Per default, all parameters are passed by value and thus are immutable. If
>> you
>> want to modify a parameter, you have to use a slightly more complex calling
>> convention. I will cover that subject as demand arises.
>> I hope this suffices to get you started. If you have any further questions,
>> please feel free to reply to this list. Please use the list instead of
>> contacting me directly as this will increase the audience and ensure a timely
>> reply
>> Regards
>>   Stephan
>> On 05/08/2010 04:24, "Salem Reyen" <salemreyen at yahoo.com> wrote:
>>> Hi,
>>>   Is there any documentation (in English) about how to call C functions from
>>> a SAC Module?  More importantly, has anyone successfully tried to call
>>> BLAS/LAPACK (eg, Intel MKL or AMD AML) from SAC?  Any help will be greatly
>>> appreciated.
>>> Salem
>> --
>> Stephan Herhut
>> Centre for Computer Science and Informatics Research
>> Science and Technology Research Institute
>> University of Hertfordshire

More information about the sac-user mailing list