This FAQ is meant to assist people who intend to or have already downloaded a version of sac2c. It covers basic information on different versions of sac2c as well as solutions to more sophisticated problems that may arise during installation / usage of sac2c.
If you encounter any problems that are not yet covered here, please do not hesitate to contact us directly or to join our mailing list.
| It's first official version sac2c0.7 was released (as pre-alpha 8-) on 16th November 1998. Up to now this is the most recent version. |
sac2c0.7 includes support for the following features:
|
| Features to be included in the next release:
|
| Features to be included in later releases:
|
| There is a binary distribution of the pre-alpha sac2c compiler version 0.7 available. Besides the compiler itself it contains the complete sources of the actual standard library. |
|
The platforms supported right now are
If it happens to be the case that your particular UNIX platform is none of the above, please contact us by email: info@sac-home.org. |
| Try the Download Section of the SAC-Hompage. |
| The up-to-date version of sac2c for Solaris (Sparc) may be found at /home/sacbase/bin/sac2c. Just set your environment variable $SACBASE to /home/sacbase and have fun. |
After downloading the binary distribution you should:
|
| In most cases "install_sac" should work without any problems. However, if something goes wrong, adjusting "install_sac" to your particular system and re-running might help. Don't worry, "install_sac" may well be called repeatedly. |
| These are due to an implicit dependency generation mechanism we installed via make,
so you can ignore them.
Whenever you compile a sac file <name>.sac using one of our GNU-make templates, it will first generate a dependency file named .<name>.d which contains the dependencies of that sac-file. Therefore, if you compile a sac file the very first time, make will complain that it does not yet exist. However, any successive make will find that file and simply re-make it without any "error-messages". |
Some LINUX versions tend to require different defines in order to be ANSI / POSIX
compliant. Therefore, a few symbols sometimes are not available.
However, if your compiler complains about a missing function/symbol "P_tmpdir",
you should proceed as follows:
|
Some LINUX versions tend to require different defines in order to be ANSI / POSIX
compliant. Therefore, a few symbols sometimes are not available.
However, if your compiler complains about a missing prototype for "tempnam",
you should proceed as follows:
|
Some LINUX versions tend to require different defines in order to be ANSI / POSIX
compliant. Therefore, a few symbols sometimes are not available.
However, if your compiler complains about a missing prototype for "putenv",
you should proceed as follows:
|
| If some system call made from sac2c goes wrong, e.g. the sac2c generated
C-compiler call, you have to adjust your sac2c configuration file
in $SACBASE/runtime/sac2crc.
From this, sac2c deduces how to generate the intended system calls.
Anyway, patching the sac2crc file may effect the performance of the generated code. Most entries of sac2crc are self explanatory, e.g. CC, CCFLAGS, or MKDIR. Not so straightforward are the "OPT_*" entries. They "translate" sac2c options into option settings for the C-compiler defined by CC. The CPP_STDIN and CPP_FILE entries are needed for running the C preprocessor on a program from stdin or a file, respectively. STDLIB_DECPATH and STDLIB_LIBPATH are used for implicitly pre-setting the search paths for the declaration and implementation files of modules and classes. Therefore, in most cases, you probably only want to extend them - if you want to modify them at all. The SYSTEM_LIBPATH is more crucial. It is needed for telling the C compiler where to find include files and libraries used by external modules, such as many modules/classes from the standard library. Finally, the CACHE* entries are used for giving the sac2c compiler informations about the cache your particular platform is equipped with. This allows for optimizing the code generated from with-loops with respect to their cache behaviour (blocking, alignment, etc.), and for generating code for multi-threaded execution. In version 0.7 this information is only used for the latter. |
| The file sac2crc allows you to specify more than one target.
For example, the standard sac2crc file that comes with the distribution besides
the default target defines many other targets, e.g. a target "par" or a
target "suncc".
As you can see for "suncc" these can even inherit settings from other targets.
In this case, all unspecified settings are taken from the "ancestors".
When compiling for another target machine you simply call sac2c with the option "-target <name>". |
| No, sac2c will also look for a file called .sac2crc in your home directory. Here, you may define your own private targets including a private default target. Settings in your private configuration file always override those from the public configuration file in $SACBASE/runtime. |
| The only environment variable that is mandatory for running sac2c is $SACBASE.
It should point to the directory, where the standard library and
the sac2c runtime library are placed (cf. install_sac).
Though it is not necessary to specify any other environment variables you may find it useful to set up some other environment variables used by sac2c:
|
| Probably, your environment variable $SACBASE is not set correctly! It should point to a directory, where a file "runtime/sac2crc" exists! |
| The bad news is: Sorry, but there is none available yet.
The good news is: Most syntax you will probably already know: it's simply C! A description of the complete syntax of SAC, as well as some papers that describe the SAC specific features to some more detail can be found on the SAC homepage in the section on Research and in the other Documentation. For any further questions, don't hesitate to ask us directly by sending an email to info@sac-base.org. |
| Simply call "sac2c -h". This will list you all sac2c options available. |
First, you should send an email to
info@sac-base.org.
It should contain:
|
| In most cases this is due to an indexing error!
To verify that you may call "sac2c -dcheck_boundary ..." which will include
some runtime code for checking index validity.
Another problem might be the lack of enough memory in your system. To verify this problem use "sac2c -dcheck_malloc ..." it will make sure that all memory requests will either be satisfied by the operating system or lead to an appropriate error message. |
| Yes! A set of "generic" Makefiles is provided in $(SACBASE)/stdlib/Makefiles/Makefile.*. In most situations the usage of one of the template Makefiles: $(SACBASE)/stdlib/Makefiles/Makefile_template.* will help. For some example usages see the Makefiles that comes with the demo-files, or the Makefiles within the stdlib (e.g. $(SACBASE)/stdlib/Makefile). |
Basically, there are two ways of finding out what is going on:
|
| Yes! You may even choose between a built-in (intrinsic) version and a
library-defined one.
If you call sac2c without any further option, none of the built-in primitives
will be available.
So if you want to use them you have to either
import them by using "import Array:all;" or use the sac2c option "-intrinsic [a+-*/ptdcr]"
which will make the built-in versions available.
Depending on the program context, both decisions may have advantages. Since the library version is defined by With-Loops With-Loop-Folding may apply and thus improve the runtime by avoiding intermediate array structures. In situations where With-Loop-Folding does not apply, on avarage the intrinsic versions are advantageous since their code is optimized to their particular purpose. |
| Yes! A specific makefile template for benchmarking is provided
in $(SACBASE)/stdlib/Makefiles/Makefile_template.bench!
For more info on using the makefile template see |
| Tracing operates on a local scope only! Whenever a library function is called, all memory operations that happen while that function is executed, is traced iff that module/class was compiled with tracing turned on!! If you want to check for a potential memory leak, better use the built-in heap diagnostics ("-check h"). |
| No, not at all. The sac2c compiler will do everything required for you. |
There are two alternative ways: either you specify the exact number of
threads to be used right when compiling your program or you just give an
upper bound and postpone the specification of the exact number until
actually running your application.
These are the corresponding compiler switches for sac2c:
|
| If you have compiled your SAC program with the -mtdynamic option, you must specify the actual number of threads to be used when running the executable. This is done by starting it with the additional option -mt <n>. If you fail to do so, your executable will stop immediately and display an error message. |
| Provided that it is compiled with the -mtdynamic <n> option, you can simply run your program with -mt 1. Just note that you get some administrative overhead due to multi-threading although you definitely won't benefit from it. However, when evaluating benchmarks we discovered that this overhead is usually neglectible. |
| Yes, you can. The mapping between threads and processors is rather loosely and completely managed by the underlying operating system. So, you may well test your multi-threaded application right on your uniprocessor desktop machine. However, wallclock execution times are likely to grow enormously with the number of threads. This is caused by very frequent context switches in the cpu. |
| Yes, of course you can. The problem is just the same as with running a multi-threaded program on a uniprocessor. As soon as the number of threads used exceeds the number of processors actually available, frequent context switches between competing threads will have a very negative impact on the runtime performance of your program. |
| Well, do you have exclusive access to the machine used? If not, check for other processes running in the system. These virtually ``steal'' processors from your system. So, at any given time, the number of processors actually available to you might be less than the number of processors physically existing. Usually, you achieve the utmost performance if the number of threads you use plus the number of other active processes in your system does not exceed the number of existing processors. |
| The SAC module system anables you to do so by writing so-called external modules. Similar to ``pure'' SAC modules their interface is defined by a module declaration file xyz.dec, but the implementation is provided by a C implemented archive file xyz.a. The additional key word external in the module declaration tells the SAC compiler to expect xyz.a rather than the SAC library xyz.lib. |
| The only comprehensive source of information about this topic is
Clemens' Diploma thesis which unfortunately is available in German only
(see SAC homepage).
Apart from this, some aspects are addressed in these FAQs.
Another approach is to write an external module declaration, to write a rudimentary SAC program which imports this module and uses its functions, and compile the whole with the sac2c option '-c' which stops after creating the respective C file. Now you can see what your function declarations have been compiled to and how the use of pragmas effects the compilation. Don't be afraid; this sounds nastier than it actually turns out to be. |
Any implicit type imported from an external module is compiled to
type void* by the SAC compiler.
So, any pointer type is just fine.
However, if you use an implicit type in an external module, sac2c takes
care of the meory management of the respective data structures.
Therefore, sac2c requires means to remove and to copy such data objects.
For this purpose, it expects the external module implicitly to provide
two additional functions not mentioned in the module declaration:
|
| This, of course, is limited to types available in SAC, i.e.,
int, float, double, and char are simply implemented
by their respective C counterparts; bool in SAC is implemented
by the type int in C.
SAC Arrays are implemented as pointers to the respective base type in C.
|
First, you have to introduce all types needed in the signature of the function,
possibly by additional implicit types.
Then, you just need to make sure that the function actually behaves as declared
in the signature, i.e.
|
| Sometimes it is quite useful to use a function name within SAC which is different from the name used in the resulting C code, e.g. you may want to use overloading within SAC also for C-implemented functions or your C function has a given name that is not allowed as identifier within SAC. For these purposes, the linksign pragma allows you to specifify a completely different function name to be used for linking. This feature even enables you to overload operators like + or == by functions implemented in C. |