\input texinfo
@c %**start of header
@setfilename ksi.info
@settitle Ksi Language and Compiler Manual
@c %**end of header

@titlepage
@title Ksi Language and Compiler Manual

@page
@vskip 0pt plus 1filll
Copyright @copyright{} 2001, 2002 Michal Moskal @email{malekith@@pld-linux.org}
@end titlepage

@contents

@ifnottex
@dircategory Programming tools:
@direntry
* ksi: (ksi).				Ksi Language and Compiler Manual
@end direntry
@node Top
@top Ksi

This is complete manual for Ksi. It also includes information
for using GCC front end for it.

Copyright (C) 2001, 2002 Michal Moskal @email{malekith@@pld-linux.org}

Version: $Id: ksi.texi,v 1.13 2002/07/20 20:48:08 malekith Exp $
@end ifnottex

@menu
* Overview::                       General introduction
* Installation::                   How to install Ksi

Language description:

General topics:

* Hello world::		First example
* fact::		More complex example
* Lex::			Lexical layer
* type::		Type expressions
* kpp::			Preprocessor
* System macros::	Predefined preprocessor symbols
* builtins::		List of built in functions
* attr::		Attributes

Top-level terms:

* func::		(func ...) term
* structdef::		Defining structures and unions
* enumdef::		Defining enumeral types
* global::		Defining global variables
* input_file::		Defining debugger input file
* alias_subset::	Aliasing control
* tyalias::		Defining type aliases and new types

Expressions:

* const::		(const ...) term
* enumref::		(enumref ...) term
* var::			(var ...) and (static_var ...) terms
* bind::		(bind ...) term
* ref::			(ref ...) term
* func_ref::		(func_ref ...) term
* modify::		(modify ...) term
* compound::		(compound ...) term
* goto::		(goto ...) and (label ...) terms
* return::		(return ...) and (result) terms
* loop::		(loop ...) and (exit_loop ...) terms
* nop::			(nop) term
* indirect::		(indirect ...) term
* cond::		(cond ...) term
* call::		(call ...) family of terms
* convert::		(convert ...), (fix ...) and (float ...) terms
* block::		(block ...) and (exit ...) terms
* size_of::		(size_of ...) term
* bin::			Regular binary expressions
* unary::		Regular unary expressions
* wfl::                 (wfl ...) term
* try_finally::         (try_finally ...) term

And finally:

* Using ksi driver::               How to use languages that have Ksi 
                                   as a target
* Remarks::                        Remarks on Ksi code generation
* Adding languages to ksi driver:: How to add languages that have Ksi as a 
				   target to ksi driver
* Author::                         Who's responsible for this?!!
* TODO::                           Things to do
* BUGS::                           Known bugs, and how to report unknown
* Term index::	  		   Index of defined (term ...)s
@end menu

@c ================================================================
@node Overview
@chapter Overview

Ksi language is ASCII representation of GCC syntax trees.
It's roughly 1:1, i.e. for one tree node, there is one term in Ksi.
It's thought as machine-independent assembler, suitable as a target
for high level languages. It's not meant to be written by human
beings.

Why should you or should you not use Ksi?

Disadvantages vs using trees to access GCC back end:

@itemize @bullet

@item
It's slower, however speed difference, especially when using
optimization shouldn't be significant. As Ksi is quite simple
with respect to lexical and grammatical structure, parser is
rather fast. Also generation of code shouldn't be slow.
If you really want high speed consider using pipes instead
of temporary disk files.

@item
There are few tree nodes that cannot be at present expressed
using Ksi, there might be in future (they are not implemented,
as *I* think they aren't very needed for target assembler).

@item
There is no way to define new tree nodes with custom way
of creating RTL. While this is IMHO the most important
disadvantage, it is still not so harmful, as most ppl doesn't
even know what RTL means... :)

@end itemize

and advantages:

@itemize @bullet

@item
Trees aren't very good documented, there are several callbacks
you have to define, creating tree nodes is sometimes tricky.

@item
You can easily write compiler in language other then C
(especially using functional languages (or possibly
scripting, but who would use perl to write a compiler?), 
which are hard (if at all possible) to link with complex
C code, such as GCC back end)

@item
It should be easier to debug, you can easily examine generated
Ksi source code, also GCC back-end won't segfault (at least
it shouldn't :^)

@item
Ksi includes <insert-number-here> Kb sources, this is
code you don't have to write and debug :^) You just need to debug
Ksi :))

@end itemize

Advantages of using GCC back-end in general are obvious: several 
targets, good optimizations and so on.

There is also another alternative. Use C as portable assembler.
Comparison of this approach vs using Ksi:

@itemize

@item
C is far more portable and well tested. Even if Ksi would run on every
platform GCC is ported to, there would be still more platforms that has
any C compiler.

@item
Ksi compiler should run faster then C compiler, having the same back end.
This is because Ksi is several times easier to parse.

@item
Switching from Ksi code generation to interfacing trees directly
shouldn't be as painful as switching from C code generation.

@item
Ksi provides better control over debug info generation. You can suppress
debug information for any symbol, use different names in debug info then
in Ksi, annotate output with line number information more freely, use
references in addition to pointers (some debugging formats understand
it) and so on.

@item
Ksi is also better in getting aliasing information from you. I don't 
know if it works however...

@item
There are no reserved words in Ksi. You can use any valid identifiers to
name your symbols.

@end itemize


@c ================================================================
@node Installation
@chapter Installation

Let's say you have gcc-3.1 release (earlier will not work),
and you have unpacked ksi-preXX.tar.gz (this will result in
ksi/ directory):

@example
cp -a ksi gcc-3.1/gcc
mkdir obj
cd obj
../gcc-3.1/configure --enable-languages=c,ksi
make
@end example

I have tested Ksi against i[56]86-pld-linux, alpha-pld-linux and
sparc-pld-linux targets (at some point in past).

GCC versions before 3.0 are not supported anymore. 3.1 has already
been released.

@c ================================================================
@node Hello world
@chapter First example: Hello world!

@example
!version 1

[
  (func .extern (int 32) printf 
    (parm (var (ptr (uint 8) str) (ellipsis)) 
    (nil))
  (func .public (int 32) main (nil)
    (bind (compound [
      (call printf [(const (ptr (uint 8)) "Hello world!\n")])
      (return (modify (result) 
      (const (int 32) 0)))])))]
@end example

If you have gcc capable of compiling Ksi, you can save this down
to hello.ksi file and execute the following:

@example
gcc hello.ksi
./a.out
@end example

Hello world! should get printed.

@c ================================================================
@node fact
@chapter More complex example

@example
!version 1

[
// int fact(int x)
// @{
//         if (x == 0)
//               return 1;
//         else
//               return x * fact(x - 1);
// @}
  (func .public (int 32) fact
    [(var (int 32) x)]
    (bind (cond (eq (ref x) (const (int 32) 0))
      (return (modify (result) (const (int 32) 1)))
      (return (modify (result) 
        (mult (ref x) (call fact [
          (minus (ref x) (const (int 32) 1))])))))))

// extern int printf(void *, ...);
  (func .extern (int 32) printf 
    [(var (ptr (uint 8)) str) (ellipsis)] (nil))

// int main(void)
// @{
//         printf("%d\n", fact(5));
//         return 0;
// @}
  (func .public (int 32) main []
    (bind (compound [
      (call printf [
        (const (ptr (uint 8)) "5! = %d\n") 
	(call fact [(const (int 32) 5) (nil)])])
      (return (modify (result) (const (int 32) 0)))])))
]
@end example

@c ================================================================
@node Lex
@chapter Lexical layer

File has to start with !version tag followed by at least one white space
and version number (always 1 at the moment). There was version 0 in
the past, the most notable difference was that function arguments
was written [parm (...) (...)], while now they are written [(...) (...)].
Similarly other lists (like toplevel [unit ...]). Version 0 is not supported
anymore.

Comments are donated by `//' and `#', they exceed until newline.

Lexical layer is very C-like, while term notation is Lisp-like.

White space is space, tab or new line.

Identifiers has to match following regular expression:
[a-zA-Z_@@$][a-zA-Z0-9_@@$]*

As you see Ksi allows @@ and $ in identifiers. However certain
linkers and/or assemblers may have different opinion about it...
For example on linux with binutils 2.12.90.0.7 gas accepts '$',
'.' but not '@' (Ksi doesn't accept '.' in identifiers, however
it can be generated with (export_name "foo.bar") attribute).

Integers (up to 64 (for 32 bit targets) or 128 bits (for 64 bit targets))
are accepted in following forms: 10 (decimal), 010 (octal), 0x10 (hex),
'a' (character, ASCII code is used).

Floating point numbers are written the same as in C.

Strings look similar to C. They are enclosed in double quotes (""),
few C escapes are allowed. There can be no newlines inside strings,
i.e. the following is not legal:

@example
"line
second"
@end example

use \n escape, like this "line\nsecond". If you want to concatenate few
strings write a dot (.) after closing quote (but without any spaces
between), any number of whitespace, and then the second string, like
this:

@example
"s1\n".    "s2".
"s3"
@end example

Following escape sequences are supported:

@itemize @bullet
@item
\n - newline (ASCII 10)
@item
\r - cr (ASCII 13)
@item
\t - tab (ASCII 9)
@item
\e - escape (ASCII 27)
@item
\" - "
@item
\' - '
@item
\\ - \
@item
\0 - nul (ASCII 0) - note, that this is unlink C. Octal escapes
are not supported.
@item
\x - hex character, next two characters (not less, and not more) are
treated as a hex code for character.
@end itemize

They are supported both in strings, and integers (e.g. '\n').

For people unfamiliar with math and/or programming languages theory
basics, term in this document is meant as an abstract object representing
tree. 

Terms are written as:

@example
  (term-name arguments...)
@end example

Arguments are separated by one or more white space. Term-name has
to be identifier (see above for definition). Arguments can be,
depending on given term, integers, floats, strings, identifiers
and other terms.

Few examples:

Argument less term:
@example
  (nil)
@end example

Term ref with single argument named x:
@example
  (ref x)
@end example

Lists of terms are introduced with in [], like this:
@example
  [(ref x) (ref y)]
@end example

Rule of thumb is: if term requires variable number of arguments
(like function call), list is used.

@c ================================================================
@node builtins
@chapter List of built in functions

In `prototypes' below, we assume, following symbols are defined as
system macros, in addition to standard:

@example
!define str (ptr (uint 8))
// `const'
!define cstr .str
!define cptr .ptr
@end example

Now list of builtins, here it goes:

@example
.c_int constant_p [(ellipsis)]
@end example

Return 1 if expression passed in constant, 0 otherwise.

@example
.ptr alloca [.sizetype]
@end example

Allocate given number bytes of memory on the stack. Memory can be
used until end of current (bind ...).

@example
.ptr return_address [.c_uint]
.ptr frame_address [.c_uint]
.ptr saveregs [(ellipsis)]
.c_int classify_type [(ellipsis)]
.ptr next_arg [(ellipsis)]
.c_int args_info [.c_int]
.void trap [parm]
.ptr apply_args [(ellipsis)]
.ptr apply [(func_ptr .void [(ellipsis)]) .ptr .sizetype]
.void return [.ptr]
.void varargs_start [.va_list_ref]
.void stdarg_start [.va_list_ref (ellipsis)]
.void va_end [.va_list_ref]
.void va_copy [.va_list_ref .va_list_ref]
@c #ifdef EH_RETURN_DATA_REGNO
@c .c_int eh_return_data_regno [.c_int]
@c #endif
@end example

[[TODO: describe this]]]

@example
.c_int setjmp [.ptr]
.void longjmp [.ptr .c_int]
@end example

Similar to functions in C library, but more efficient. They should be
passed pointer to 5 words (it is best to pass pointer to 5 pointers,
as array of 5 .c_ints won't work on 64 bit archs), @code{longjmp} should
be passed @code{(const .c_int 1)} as second argument.

Example:
@example
  (structdef jmpbuf 
    [field
      (var .ptr w1)
      (var .ptr w2)
      (var .ptr w3)
      (var .ptr w4)
      (var .ptr w5)])
  // ...
    (var (struct jmpbuf) buf)
    (cond 
      (eq (builtin setjmp [(addr (ref buf))]) (const .c_int 0))
      (nop)  // regular return
      (nop)) // return from longjmp
  // ...
     (builtin longjmp [(addr (ref buf)) (const .c_int 1)])
@end example

However note, that __builtin_@{set,long@}jmp are not documented in
gcc.info, and comments in sources states, that they should not be used
in other way then sjlj exception handling and Ada exceptions does.
I'm not quite sure what it's supposed to mean, though :^). There is
also bug related to it in GCC back end, in conjunction with inlining, 
workaround is enabled (functions that call (builtin longjmp ...) cannot
be inlined).

@example
.ptr memcpy [.ptr .cptr .sizetype]
.c_int memcmp [.cptr .cptr .sizetype]
.ptr memset [.ptr .c_int .sizetype]
.c_int strcmp [.cstr .cstr]
.c_int strncmp [.cstr .cstr .sizetype]
.str strstr [.cstr .cstr]
.str strpbrk [.cstr .cstr]
.str strchr [.cstr .c_int]
.str strrchr [.cstr .c_int]
.str strcpy [.str .cstr]
.str strncpy [.str .cstr .sizetype]
.str strcat [.str .cstr]
.str strncat [.str .cstr .sizetype]
.sizetype strspn [.cstr .cstr]
.sizetype strcspn [.cstr .cstr]
.sizetype strlen [.cstr]
.str index [.cstr .c_int]
.str rindex [.cstr .c_int]
.void bzero [.ptr .sizetype]
.c_int bcmp [.cptr .cptr .sizetype]
@end example

String/memory handling function. They work the same way, as equivalents
in C library. If -O is not given they are not substituted, but called
from C library. (maybe also with -O on some targets).

@example
.c_float sqrtf [.c_float]
.c_double sqrt [.c_double]
.c_long_double sqrtl [.c_long_double]
.c_float sinf [.c_float]
.c_double sin [.c_double]
.c_long_double sinl [.c_long_double]
.c_float cosf [.c_float]
.c_double cos [.c_double]
.c_long_double cosl [.c_long_double]
@end example

Floating point arithmetics (often supported directly by FPU).


@c ================================================================
@node attr
@chapter Attributes

Types, variables and functions can have attributes. It is given as list
of zero or more following terms. It can be often omitted, it is treated
as @code{[]} then.

Attributes are parsed as they are read, later ones override former,
except (aligned ...), for which maximal value is taken i.e. this:
@code{[(aligned 4) (public) (aligned 1) (local)]} is same as
@code{[(aligned 4) (local)]}.

Following terms are allowed inside:

@findex aligned
@example
(aligned BYTES)
@end example

Align entity to given number of BYTES (integer literal).

Allowed in: functions, types, local and global variables.

@findex packed
@example
(packed)
@end example

Entity should be bit-packed.

Allowed in: types.

@findex local
@example
(local)
@end example

Entity should be local to translation unit, this is the default,
unless overridden with (public).

Allowed in: functions and global variables.

@findex public
@example
(public)
@end example

Entity should be public, exported from translation unit.

Allowed in: functions and global variables.

@findex extern
@example
(extern)
@end example

Entity is not defined in translation unit, it should be imported from
outside.

Allowed in: functions and global variables.


@findex suppress_debug
@example
(suppress_debug)
@end example

Don't emit debugging information for entity.

Allowed in: functions, types, local and global variables.

Following are allowed only for functions:

@findex const_func
@example
(const_func)
@end example

Function does not examine any values beside arguments, and has no
side effects.

@findex pure_func
@example
(pure_func)
@end example

Like @code{const_func}, except can read global data.

@findex static_ctor
@example
(static_ctor)
@end example

Function should be run before main().

@findex static_dtor
@example
(static_dtor)
@end example

Function should be run before exit().

@findex malloc_like
@example
(malloc_like)
@end example

Function returns pointer that is not an alias.

@findex no_return
@example
(no_return)
@end example

Function does not return.

@findex alias_set
@example
(alias_set NAME)
@end example

Make entity reside in named alias set. Entities in different alias
sets cannot alias each other (unless (alias_subset ...) is used).

This is allowed in (tyalias ...) and (abstract_type ...) only for 
now. This functionality has not been tested at all yet, be warned.

See also @xref{alias_subset}.

@findex export_name
@example
(export_name STRING)
@end example

Use given name in assembly in debug info. Name should be string (i.e.
given in ""). Note: most assemblers won't accept non alphanumeric 
characters other then '_', '$' and '.'. At least ia32 linux gas doesn't.
However note, that types are not put into assembly output and DWARF2 seems
to be happy with anything.

Allowed in: types and global symbols.

Other terms:
@example
(no_limit_stack)
(artificial)
(weak)
(one_only)
(comdat)
(section SECTION_NAME)
@end example


@c ================================================================
@node func
@chapter (func ...) term
@findex unit

Translation unit is list of toplevel terms. It is enclosed in [].

@findex func

@example
  (func ATTR RET_TYPE NAME PARMS BODY)
@end example

Toplevel term to define function.

@itemize @bullet
@item
ATTR is list of attributes. @xref{attr}.  Each external function has
to be prototyped before it is used (with [(extern)]).  For extern
function BODY has to be (nil). local and public functions giving (nil)
body serves as way of forward prototyping.
@item
RET_TYPE is type expression (@xref{type}.), designating type that function
returns.
@item
NAME is simple identifier, used as function name.
@item
@findex ellipsis
PARMS is list of parameters. The term (var ...) (@xref{var}.)  is used
here.  Last element can be (ellipsis) to donate vararg function. See
below for an example.
@item
BODY is expression being function body, use (nil) if you just want prototype.
Top-level term for function body has to be (bind ...), that is used to
create function scope.
@end itemize

Few examples:

fprintf(3) function prototype can look like this:
@example
  (func .extern (int 32) fprintf 
    [(var (ptr (void)) f) (var (ptr (uint 8)) str) (ellipsis)] 
    (nil))
@end example

Constant function returning 1.0:
@example
  (func .public (float 64) f []
    (bind (return (modify (result) (const (float 64) 1.0)))))
@end example

Local integer identity function:
@example
  (func .local (int 32) id [(var (int 32) x)]
    (bind (return (modify (result) (ref x)))))
@end example

Function that does nothing:
@example
  (func .public (void) nop [] (bind (nop)))
@end example

Note one neat thing here: function is called `nop', and
later on we use (nop) term. There is no namespace collision,
separate namespaces are maintained for term names, function
names, local variables and parameters, labels, labeled blocks.

(func ...) is not an expression.


@c ================================================================
@node type
@chapter Type expressions

@findex int
@findex uint
@findex float
@example
  (int SIZE)
  (uint SIZE)
  (float SIZE)
@end example

Define signed integer, unsigned integer, or floating point (real) type
of size specified in bits. SIZE is integer literal. 

@findex void
@example
  (void)
@end example

Define one element type, used as function return value. Also
most statement expressions returns (void). (ptr (void)) type is
compatible with all other pointer types.

@findex bool
@example
  (bool)
@end example

Define boolean (true/false) type.

@findex ptr
@example
  (ptr TYPE)
@end example

Define pointer to X type. TYPE is type expression.

@findex reference
@example
  (reference TYPE)
@end example

Define reference to X type. TYPE is type expression. Reference is similar
to pointer (i.e. one need to use @code{(indirect ...)} to get into it
and so on), but only operations allowed beside (indirect ...) is
(eq ...) and (ne ...) (i.e. no (lt ...), (gt ...), (plus ...) and 
(minus ...)). The only reason why one want to use (reference ...) is that
is presented in a different way to the debugger.

@findex func_ptr
@example
  (func_ptr RET_TYPE PARMS)
@end example

Define pointer-to-function type. RET_TYPE is type expression for
return type. PARMS is list of types of arguments.  Last element can be
(ellipsis), to donate vararg function.

@findex struct
@findex union 
@findex enum
@example
  (struct NAME)
  (union NAME)
@end example

Reference previously defined structure or union. Separate
namespace is maintained for each of them (however there might
be some problems with debuggers in case of name clashes).
@xref{structdef}.

@findex poly
@example
  (poly)
@end example

Poor-man's polymorphic type. Type discipline for it is relaxed in the
following way: if function takes (poly) as argument, any type of native
pointer size is allowed. However inside this function you cannot do
much with values of type (poly), just assign and return them.
If function returns (poly) you have to (convert ...) the returned
value to proper type before using it.

In Real World (poly) is unsigned integer of native pointer size.
It might be useful for polymorphism implementation, but I'm not sure 
(I'm going to check that).

@findex tyref
@example
  (tyref NAME)
@end example

Refer to previously defined (tyalias ...) or (abstract_type ...).
See @xref{tyalias}.

Examples:
@example
  (ptr (uint 16))
  (void)
  (int 32)
  (float 32)
  (float 64)
  (struct stat)
  (ptr (struct stat))
  (func_ptr (void) (nil)) // type of void X(void)
  (func_ptr (int 32) [parm (ptr (void)) (int 32) (ellipsis)])
           // type of int f(void*, int, ...)
@end example

Type expression is not an ordinary expression to be used in
function body, so it doesn't have type itself.


@c ================================================================
@node structdef
@chapter (structdef ...) and (uniondef ...) terms

Structures and unions are defined at the top level, they are not 
expressions, thus they cannot be used in function bodies.

@findex structdef
@example
  (structdef ATTR NAME FIELDS)
  (structdef NAME FIELDS)
@end example

NAME is simple identifier, used as structure name. FIELDS is list
of fields: (var ...) (@xref{var}.) arguments are
used here.  

ATTR is attribute list. @xref{attr}. If it is omitted it is taken to
be [].

If FIELDS is empty list (i.e. []), this is only forward
declaration. (struct NAME) can be only used to construct pointers,
until actual definition.

Size of structure is not less then sum of sizes of fields. It can be
more because of alignment. There is currently no way to mark structure
as packed, or to use specified align.

@findex uniondef
@example
  (uniondef ATTR NAME FIELDS)
  (uniondef NAME FIELDS)
@end example

(uniondef ...) is same as (structdef ...) except offset of all fields
inside object is taken to be 0, i.e. only one field can occupy union at 
any given time.

Size of union is size of widest field.

Examples:
@example
  (structdef FILE [])
  (structdef buf [
    (var (ptr (uint 8)) data)
    (var (int 32) ptr)
    (var (int 32) off)
    (var (ptr (struct FILE)) f)])
    
  (union arg [
    (var (ptr (uint 8)) id)
    (var (int 32) number)])

  (structdef node [
    (var (ptr (struct node)) next)
    (var (int 32) data)])
@end example

@c ================================================================
@node enumdef
@chapter (enumdef ...) term

(enumdef ...) is used to define constants, mainly to output symbols 
in debug info. However it can be also used to define integer constants.
Syntax is:

@findex enumdef
@example
  (enumdef [(entry NAME VALUE) (entry NAME VALUE) ...])
@end example

where NAME is identifier and VALUE is integer constant.

Names are output in debug info, and can be later referred with
@xref{enumref}.

@c ================================================================
@node alias_subset
@chapter Controlling aliasing rules

In general variables from different alias sets cannot alias each
other. However after:

@findex alias_subset
@example
  (alias_subset foo bar)
@end example

things in alias set bar can alias things in alias set foo, but not
the other way around.

Things without defined alias set can alias anything.

@c ================================================================
@node tyalias
@chapter Defining new types and names for old

(tyalias ...) term is used to define new names for existing types,
just like typedef in C. Syntax is:

@findex tyalias
@example
  (tyalias (var TYPE NAME))
@end example

On the other hand (abstract_type ...) is used to create brand new types,
incompatible with anything else. Syntax is:

@findex abstract_type
@example
  (abstract_type NAME)
@end example

Real World type used here is unsigned integer of pointer size. Operations
allowed on abstract type are similar to these allowed on (poly) -- pass
to function, return from function and assign.

Both type aliases and abstract types can be referred to with (tyref ...)
term.

@c ================================================================
@node global
@chapter (global ...) term

@findex global
@example
  (global ATTR VAR)
@end example

ATTR is attribute list. @xref{attr}.

VAR is (var ...) term. @xref{var}.

Global variables are defined at the top level, they are not expressions, 
thus they cannot be used in function bodies.

Examples:
@example
  (global .public (var (int 32) x))         // int x;
  (global .local (var (int 8) y))           // static char y;
  (global .extern (var (ptr (void)) ptr))   // extern void *ptr;
@end example


@c ================================================================
@node const
@chapter (const ...) term
@findex const

@example
  (const TYPE VALUE)
@end example

Create constant of given TYPE and VALUE. TYPE is type expression 
(@xref{type}.).  VALUE is literal constant. Type for strings literals
has to (ptr ...). Strings are automagicly NUL terminated.

Examples:

@example
  (const (uint 32) 2818)
  (const (uint 32) 0xdeadf00d)
  (const (float 64) 3.1415926535)
  (const (ptr (uint 8)) "Hello world\n")
  (const (bool) 0) // false
  (const (bool) 1) // true
  (const (ptr (uint 8)) "Demo ".
                    "\tmulti-line string.\n")
@end example

Type of (const ...) term is same as TYPE.


@c ================================================================
@node enumref
@chapter (enumref ...) term
@findex enumref

@example
  (enumref NAME)
@end example

Create constant with value assigned to named enumerator. See 
@xref{enumdef}.

Type of (enumref ...) term is signed integer of native pointer size.

@c ================================================================
@node var
@chapter (var ...) and (static_var ...) terms
@findex var

@example
  (var TYPE NAME)
@end example

Used in function's parameters lists, structures and unions fields,
and for creation of local and global variables. 

In case of expression context it creates local variable. 
TYPE is type expression (@xref{type}.), NAME is identifier. 
Variable remains visible, and can be referenced with (ref ...)
term (@xref{ref}.), until exit from first surrounding (bind ...)
block (@xref{bind}.). Initial value of variable is undefined.

Type of (var ...) term is (void). 

@example
  (var (int 32) x)
  (var (bool) y)
  (var (ptr (uint 8)) s)
@end example

@findex static_var
@example
  (static_var TYPE NAME)
@end example

In function body context same as (var ...) except it creates static 
variable (in C's sense, i.e. it preserves its value between function
calls, and contains at first 0), illegal in other contexts.


@c ================================================================
@node bind
@chapter (bind ...) term
@findex bind

@example
  (bind EXP)
@end example

Creates local scope, variables defined in EXP remains visible only 
inside it. Scoping does not apply to labels.

EXP is expression of any type.

Top-level term in function body has to be (bind ...) term.

Type of (bind ...) term is (void).

This example swaps two integers, `x' and `y':
@example
  (bind [compound
    (var (int 32) tmp)
    (modify (ref tmp) (ref x))
    (modify (ref x) (ref y))
    (modify (ref y) (ref tmp))])
@end example

Note that no scopes are introduced implicitly.


@c ================================================================
@node func_ref
@chapter (func_ref ...) term
@findex func_ref

@example
  (func_ref NAME)
@end example

Reference function. Returns pointer to given function.

NAME is identifier naming function.

Type of (func_ref ...) term is (func_ptr X), where X if type of 
function referenced.


@c ================================================================
@node size_of
@chapter (size_of ...) term
@findex size_of

@example
  (size_of TYPE)
@end example

Return size, in bytes, of specified type. Most useful with
structures.


@c ================================================================
@node ref
@chapter (ref ...) term
@findex ref

@example
  (ref NAME)
@end example

Reference parameter, local or global variable. Scope nesting applies.

NAME is identifier naming variable or parameter.

(ref ...) can be used both as R and L-value, i.e. as any operand of
(modify ...) (@xref{modify}.).

Type of (ref ...) term is type of variable referenced.

This example assigns `x' it's doubled value:
@example
  (modify (ref x) (plus (ref x) (ref x)))
@end example

Note that there is none corresponding GCC tree_code for (ref ...),
in GCC you use variable declaration directly.


@c ================================================================
@node modify
@chapter (modify ...) term
@findex modify

@example
  (modify TARGET_EXP SOURCE_EXP)
@end example

Assign value of SOURCE_EXP to TARGET_EXP.

EXP_TARGET is probably (indirect ...) (@xref{indirect}.), 
(ref ...) (@xref{ref}.) or (result) (@xref{return}.), however
Ksi compiler doesn't check it, so be careful, as back end
might crash if you pass it something strange there, or even
worse you might get strange assembler code.

Types of TARGET_EXP and SOURCE_EXP has to be the same.

Type of (modify ...) term is type of TARGET_EXP.

Examples:
@example
  (modify (ref x) (const (int 32) 0))
  (modify (result) (ref x))
  (modify (indirect (float 64) 
            (plus (ref x) (const (int 32) 16)))
            (const (float 64) 0.0))
@end example


@c ================================================================
@node compound
@chapter (compound ...) term
@findex compound

@example
  (compound EXP_LIST)
@end example

Same as C's "EXP1, EXP2, ..., EXPN", all are computed, value of last is 
used. EXP_LIST is list (in []) of expressions.

It might be sometimes required to cast some value to (void).
This can be done with (compound ...):

@example
  (compound [
    (call printf [parm (.string "Hello world!\n")])
    (nop)])
@end example

or with (convert ...) (@xref{convert}.).

Type of (compound ...) is type of last expression.

Compound expressions are most often used as way of grouping
expressions, similar to @{@} in C. Note, that in order to
additionally introduce scope (second function of @{@} in C),
use (bind ...) term (@xref{bind}.), like this:

@example
  (bind (compound [
    (var (bool) x)
    (call f (parm (unary addr (ref x)) (nil)))]))
@end example


@c ================================================================
@node goto
@chapter (goto ...) and (label ...) terms

@findex label
@example
  (label NAME)
@end example

Define label.

@findex goto
@example
  (goto NAME)
@end example

Jump to label.

NAME is identifier. Separate namespace is maintained just for labels.
(goto ...) cannot be used to jump out the function. However it
can cross scope ((bind ...)) boundaries, jump forward and backward.

Labels might not work well, since no other GCC front end is using
them in functional way as I do, and there might be bugs... (at least
there was one).

Endless loop:
@example
  (compound [(label x) (goto x)])
@end example

There is possibly not much need to use (goto ...). It is not advised,
as there are problems optimizing it. In order to implement break
or continue statements known from C you may use labeled blocks. 
@xref{block}.

Type of both (label ...) and (goto ...) statements is (void).


@c ================================================================
@node return
@chapter (return ...) and (result) terms

@findex return
@example
  (return EXP)
@end example

Evaluate EXP, and leave current function. EXP can have any type,
it will in most cases be (modify (result) ...).

Type of (return ...) statement is (void).

@findex result
@example
  (result)
@end example

Reference result value of function. It's safest to use it just
in (return ...), as first argument of (modify ...).

Type of (result) term is return type of current function.

Note: this, while syntacticly correct, leaves current with *undefined*
value:
@example
  (return (const (int 32) 10)) 
@end example

In order to return 10 from function you need to write:
@example
  (return (modify (result) (const (int 32) 10)))
@end example


@c ================================================================
@node loop
@chapter (loop ...) and (exit_loop ...) terms

@findex loop
@example
  (loop EXP)
@end example

Evaluate EXP in endless loop. EXP can have any type.

Type of (loop ...) is (void).

@findex exit_loop
@example
  (exit_loop COND)
@end example

Leave surrounding (loop ...) if COND is true. COND needs to have
(bool) type.

Type of (exit_loop ...) term is (void).

C's break:
@example
  (exit_loop (const (bool) 1))
@end example


@c ================================================================
@node nop
@chapter (nop) term
@findex nop

(nop)

Do nothing.

Type of (nop) term is (void).


@c ================================================================
@node indirect
@chapter (indirect ...) term
@findex indirect

@example
  (indirect EXP)
@end example

Unary `*' in C. EXP should have (ptr X) type. 

Type of (indirect ...) term is X (when EXP has (ptr X) type).


@c ================================================================
@node cond
@chapter (cond ...) term
@findex cond

@example
  (cond COND TRUE_EXP FALSE_EXP)
@end example

Conditional expression. COND should have (bool) type,
while TRUE_EXP and FALSE_EXP types can be anything, except
that they has to be the same.

If (cond ...) evaluates to (const (bool) 1) TRUE_EXP
is evaluated and returned, otherwise FALSE_EXP is evaluated
and returned.

It is same as ? : operator in C.

Type of (cond ...) expression is type of TRUE_EXP (or FALSE_EXP).

Example:
@example
  (func .extern (int 32) printf 
    [(var (ptr (uint 8)) str) (ellipsis)] 
    (nil))
  // ...
  (cond (lt (ref x) (const (int 32) 0))
    (convert (void) 
      (call printf [parm (.string "x < 0\n")]))
    (nop))
@end example

Note (convert ...). It is required since printf(3) returns (int 32),
and (nop) returns (void).


@c ================================================================
@node bin
@chapter Regular binary operators
@cindex binary operations

@example
  (OP_NAME EXP1 EXP2)
@end example

Binary operator. 

OP_NAME is one of:

@itemize -
@item
@findex bit_and
@findex bit_andtc
@findex bit_ior
@findex bit_xor
`bit_and', `bit_andtc', `bit_ior', `bit_xor' - bitwise operations. A andtc
B is same as A and not B (I'm not sure if andtc will work correctly,
better test it before using... it does not appear in gcc/expr.c).
Operands needs to be of the same (int ...) or (uint ...). The
result is also of the same type.

@item
@findex exact_div
@findex ceil_div
@findex floor_div
@findex trunc_div
@findex round_div
@findex ceil_mod
@findex floor_mod
@findex trunc_mod
@findex round_mod
`exact_div', `ceil_div', `floor_div', `trunc_div', `round_div', `ceil_mod', 
`floor_mod', `trunc_mod', `round_mod' - various integer division and modulo
operations. Use `exact_div' when no modulo is expected (e.g. pointer
operations). Meaning of rest should be clear. Operands needs to be of the same
(int ...) or (uint ...). The result is also of the same type.

@item
@findex rdiv
`rdiv' - real division.  have the same type which is (float ...).
The result is also of the same type.

@item
@findex eq
@findex ne
`eq', `ne' - equality/inequality operators. Operands can be of any type
(but they must be the same). Result has type (bool).

@item
@findex ge
@findex le
@findex lt
@findex gt
`ge', `gt', `le', `lt' - comparison operators, respectively `>=', `>',
`<=', `<'.  Operands need to have the same type which is either (int ...),
(uint ...), (ptr ...) or (float ...). Result has type (bool).

@item
@findex max
@findex min
`max', `min' - return greater/lesser of two values.  Operands need to
have the same type which is either (int ...), (uint ...),
(ptr ...) or (float ...).  The result is also of the same type.

@item
@findex lrotate
@findex rrotate
@findex lshift
@findex rshift
`lrotate', `lshift', `rrotate', `rshift' - shift/rotate operators.
Operands needs to be of the same (int ...) or (uint ...). The
result is also of the same type.

@item
@findex minus
`minus' - subtraction.  Operands need to have the same type which
is either (int ...), (uint ...), (ptr ...) or (float
...). Result has type the same type, except when two (ptr ...) values
are subtracted, then return type is (int X), where X is machine
pointer size. Size of object pointed to is not taken into account,
the difference is always returned in bytes.

@item
@findex plus
`plus' - addition.  Operands need to have the same type which is either
(int ...), (uint ...) or (float ...). Result has type the same type. It
is also possible that one argument is (ptr) and the other is either
(int ...) or (uint ...) (of machine pointer size). In this case result
has type (ptr). Size of object pointed to is not taken into account,
the offset is always specified in bytes.

@item
@findex postinc
@findex preinc
@findex postdec
@findex predec
`postinc', `preinc', `postdec', `predec' - @code{++} and @code{--}
in C.  Operands need to have the same type which is either (int ...),
(uint ...) or (float ...). Result has type the same type. It is also
possible that one argument is (ptr) and the other is either (int ...) or
(uint ...) (of machine pointer size). In this case result has type
(ptr). Size of object pointed to is not taken into account, the offset
is always specified in bytes.

First operand has to be proper lvalue.

Note: don't expect any better performance from this terms (used instead
of (modify X (plus X (const T I)))), especially when running with -O2,
they can be useful for their side-effects semantics, though.

@item
@findex mult
`mult' - multiplication. Operands need to have the same type which is
either (int ...), (uint ...)  or (float ...).  The result
is also of the same type.

@item
@findex truth_and
@findex truth_or
@findex truth_xor
`truth_and', `truth_or', `truth_xor' - logical and, or and xor. Both operands
needs to have (bool) type, so is the return type. They are not lazy.

@item
@findex truth_andif
@findex truth_orif
`truth_andif', `truth_orif' - lazy logical `and' and `or'. Both operands
needs to have (bool) type, so is the return type. Lazy means, that
computation is stop as soon as the value is known, so this:
@example
  (truth_andif 
    (ne (ref x) .null) 
    (ne (indirect (int 32) (ref x)) 0))
@end example
won't ever crash on dereferencing NULL pointer.

@item
@findex ordered
@findex unordered
@findex uneq
@findex unge
@findex unle
@findex unlt
@findex ungt
`ordered', `uneq', `unge', `ungt', `unle', `unlt', `unordered' -
ordered/unordered floating point comparisons. Operands needs to be
of the sane (float ...) type.  [In fact I don't know what they does
:^]. Return type is (bool).
@end itemize

EXP1 and EXP2 are expressions of appropriate types.

Return value of (OP_NAME ...) term depends on OP_NAME and types
of EXP1 and EXP2, see above.

@c See tree.def in GCC sources for details. Khm...


@c ================================================================
@node call
@chapter (call ...) terms family

@findex call
@example
  (call NAME PARMS)
@end example

Call function. NAME is identifier. PARMS is list of expressions
to be passed as arguments.

@findex fcall
@example
  (fcall NAME PARAMS)
@end example

Functional call. Same as (call ...) but claims, that call has no 
side effects. Use with care, as it might get optimized out.

@findex ptr_call
@findex ptr_fcall
@example
  (ptr_call EXP PARAMS)
  (ptr_fcall EXP PARAMS)
@end example

Same as (call ...) and (fcall ...) respectively, except function is 
referenced by pointer, not by name. @xref{func_ref}.

@findex builtin
@findex fbuiltin
@example
  (builtin NAME PARAMS)
  (fbuiltin NAME PARAMS) 
@end example

Same as (call ...) and (fcall ...) respectively, except built in function is 
called. @xref{builtins}, for list of built in functions.

Type of (*call ...) and (*builtin ...) is type of returned value.

Few examples:
@example
  (call printf [ 
    (.string "x = %d\ny = %d\n-z = %d")
    (ref x)
    (ref y)
    (unary negate (ref z))])
    
  (fcall sqrt [(ref x)])

  (call f [])
  (ptr_call (func_ptr f) [])		// same as above

  (ptr_call (ref fnc) [])
@end example


@c ================================================================

@node convert
@chapter (convert ...), (fix* ...) and (float ...) terms

@findex convert
@findex fix_trunc
@findex fix_ceil
@findex fix_floor
@findex fix_round
@findex float
@example
  (convert TYPE EXP)
  (fix_trunc METHOD TYPE EXP)
  (fix_floor METHOD TYPE EXP)
  (fix_ceil METHOD TYPE EXP)
  (fix_round METHOD TYPE EXP)
  (float_expr TYPE EXP)
@end example

Convert/cast EXP to TYPE. TYPE is type expression (@xref{type}.).

For (convert ...) EXP can be of any type, for (fix* ...) it has to
(float ...), for (float_expr ...) it has to be (int ...)  or (uint ...).

(float_expr ...) can be only used to convert integer to floating point number.

Note: (fix* ...) other then (fix_trunc ...) is not implemented in GCC as
of 3.1.

`CONVERT_EXPR' tree node in GCC does not work for int<->float
conversions. I made (convert ...) use `FLOAT_EXPR' and `FIX_TRUNC_EXPR'
as needed, so you don't need to worry about it.

Having this two facts in mind, one may note that other conversion
expressions then (convert ...) are superfluous.

Convert expressions are very often needed in Ksi, as it is very strict
about operands, and if they has to be the same type, no different sign
or size is allowed. Also, even if value of expression is discarded,
if term needs same type expressions, you have to use (convert ...).
This is especially remarkable for (cond ...).

For example consider following:
@example
  (compound
    (cond (lt (ref x) (ref y))
      (convert (void) 
        (call printf [(.string "x < y")])
      (nop)))
     (ref x))
@end example


@c ================================================================
@node unary
@chapter Regular unary operators
@cindex unary operations

@example
  (OP_NAME EXP)
@end example

OP_NAME is one of:

@itemize -

@item
@findex negate
@findex abs
`negate', `abs' - returns expression negated or absolute value of an
expression respectively. Operand needs to have (int ...)  or (float ...).

@item
@findex ffs
`ffs' - returns position of the first bit set. The least significant bit
has position 1. Operand needs to have (int ...) or (uint ...)
type.

@item
@findex bit_not
`bit_not' - bitwise negation. Operand needs to have (int ...) or
(uint ...)  type.

@item
@findex truth_not
`truth_not' - logical negation. Operand needs to have (bool) type.

@item
@findex non_lvalue
`non_lvalue' - change expression to non-lvalue. Operand can have any type.

@item
@findex addr
`addr' - take address of expression. At present only address of variable
or parameter can be taken.  Operand can have any type.  Returned value
has type (ptr X), if type of EXP was X.
@end itemize

Unless otherwise stated returned value of (OP_NAME ...) is the same
as type of EXP.


@c ================================================================
@node block
@chapter (block ...) and (exit ...) terms

@findex block
@example
  (block ID TYPE EXP)
  (block ID EXP)
@end example

Create named block, with name ID (which is an identifier) and body
EXP. If TYPE isn't present it is assumed to be (void).  If TYPE
is not (void), EXP has to have the same type.  Otherwise there are
no restrictions.

Type of (block ...) term is same as TYPE.


@findex exit
@example
  (exit ID EXP)
  (exit ID)
@end example

Exit block with name ID (which is an identifier). If EXP is omitted it's
assumed to be (nop).

Type of (exit ...) term is (void).

It is only possible to (exit ...) from inside block, i.e. you cannot
(exit x) outside EXP of (block x EXP).

Block doesn't introduce scope. (the only way to scope is to use (bind
...) (@xref{bind}.).

There is separate namespace for block names.

Warning: as of GCC 3.1 returning values other then void from block with
(exit ...) is not implemented, and won't work.  I don't know if it is
ever going to work.

For example, one may use labeled blocks to implement break and
continue statements in C, like this:
@example
  (block outer
    (loop (block inner (compound [// for (;;) @{
      // do something ...
      (cond (ref b)
        (exit outer) // break
        (exit inner)) // continue
      // do something more ...
    ]))))
@end example


@c ================================================================
@node wfl
@chapter (wfl ...) term

@findex wfl
@example
  (wfl LINE EXP)
  (wfl LINE COLUMN EXP)
@end example

WFL stands for With File, Line. It is part of Ksi interface to debugger.
It marks expression EXP as result of compilation of line number LINE,
column number COLUMN of source file. 

If COLUMN is omitted it is taken to be 1. (Note: column numbers seems
to be ignored by GCC back end).

You should place (wfl ...) notes for every input line your compiler 
parses, otherwise you won't be able to trace execution using source
level debugger.

Type of (wfl ...) term is same as type of EXP.

If you wonder how to tell name of source file, @xref{input_file}. :P

Example:

module.foo:
@example
extern x, y;

f:
  x = 1;  # this is 4th line
  y = 2;
@end example

module.ksi:
@example
!version 1
[
  (input_file "module.foo")
  (global .extern (var (int 32) x))
  (global .extern (var (int 32) y))
  (func .public (void) f []
  (bind (compound [
      (wfl 4 (modify (ref x) (const (int 32) 1)))
      (wfl 5 (modify (ref y) (const (int 32) 2)))])))]
@end example


@c ================================================================
@node try_finally
@chapter (try_finally ...) term

@findex try_finally
@example
  (try_finally EXP CLEANUP_EXP)
@end example

Evaluate EXP. No matter by what means control leaves EXP, CLEANUP_EXP
is always evaluated (and its value is discarded).

Type of (try_finally ...) term is type of EXP.

This might be useful in translating following snippet of code:

@example
L1: loop @{
  try @{
    do_foo
    if (condition) break L1
    do_bar
  @} finally @{
    do_baz
  @}
@}
@end example

into:

@example
  (block L1
    (loop
      (try_finally
        [compound
          .do_foo
          (cond .condition (exit L1) (nop))
          .do_bar]
        .do_baz)))
@end example


@c ================================================================
@node input_file
@chapter (input_file ...) term

@findex input_file
@example
  (input_file FILENAME)
@end example

Set input filename passed to debugger. It defaults to Ksi source file,
which is processed (it's probably not what you want). It can be only
changed at the top level (i.e.  as part of (unit ...), @xref{func}.).

FILENAME is string literal, standing for name of file, that is taken
as the source file from now on. Note that it has nothing to do with
diagnostic messages produced by Ksi compiler, it is only relevant
with respect to debug info.

(wfl ...) term is used to set line number information, @xref{wfl},
for discussion and example.


@c ================================================================
@node kpp 
@chapter Ksi PreProcessor

Ksi GCC front end includes simple internal preprocessor. It is
responsible for striping off comments and macro expansion.
Conditional compilation will be supported soon.

Comments are strings matching following eregexp: (//|#).*$,
outside (double and single) quoted strings.

Macros are identifiers, with `.' or `^' in front of them.

@example
!define int (int 32)
  (const ^int 10)
@end example

Macros starting with `.' are system macros, while macros starting 
with `^' are user macros. User macros can be created with !define
directive, at first there are no user macros defined. System macros
cannot be redefined from source code. They can be defined with -D
option, however it shouldn't be used. There is huge set of predefined
system macros. @xref{System macros}.

!define directive is followed by one or more white space, identifier
name to define, one or more white space, and string to be defined.
!define directives are preprocessed, i.e. following input:

@example
!define foo bar
!define baz .foo
!define foo biz
.baz
@end example

produces `bar'.

There is also stringize operator defined. It can be used only
to stringize macros. It can be used by adding `%' in front of
`.' or `^', like this:

@example
  (call printf [parm (.string "Machine is ". %.machine. "!\n")])
@end example

Note two things, first: there is no white space between `%' and `.',
and also between `.' and `machine', second: there is a `.' after
machine, this is there to concatenate strings, and only because of that.
For example:

@example
  (call printf [parm (.string "Machine is %s!\n") (.string %.machine)])
@end example


@c ================================================================
@node System macros 
@chapter Predefined preprocessor symbols

Following symbols are defined:

@example
.ksi_version 1

.kpp 1
	
.c_int_bits
.c_short_bits
.c_long_bits
.c_char_bits
.c_long_long_bits
.c_float_bits
.c_double_bits
.c_long_double_bits
.c_ptr_bits
@end example
size of appropriate C type in bits.

@example
.c_int_bytes
.c_short_bytes
.c_long_bytes
.c_char_bytes
.c_long_long_bytes
.c_float_bytes
.c_double_bytes
.c_long_double_bytes
.c_ptr_bytes
@end example
size of appropriate C type in bytes.

@example
.c_int
.c_short
.c_long
.c_char
.c_long_long
.c_float
.c_double
.c_long_double
.c_ptr
.c_uint
.c_ushort
.c_ulong
.c_uchar
.c_ulong_long
@end example
appropriate C type (defined with (int|float|ptr|uint .c_XXX_bits)).
	
@example
.c_ptr_off (int .c_ptr_bits)
.c_uptr_off (uint .c_ptr_bits)
@end example

.intX (int X), where X is one of 8, 16, 32, 64 or 128.

.uintX (uint X), where X is one of 8, 16, 32, 64 or 128.

.floatX (float X), where X is one of 32, 64, 96 or 128.

@example
.ptr (ptr (uint 8))
.bool (bool)
.void (void)
.ptr_off .c_ptr_off
.uptr_off .c_uptr_off
.sizetype .c_uptr_off		// size_t
.null (const (ptr (void)) 0)
.true (const (bool) 1)
.false (const (bool) 0)
.string const (ptr)
.local [attr (local)]		// same as (nil)
.public [attr (public)]
.extern [attr (extern)]
@end example

Target endian stuff:

@example
.bytes_big_endian
@end example
Defined to 1 if most significant byte of word is the lowest numbered.
Defined to 0 otherwise.

@example
.words_big_endian
@end example
Defined to 1 if most significant word of multiword number is the 
lowest numbered. Defined to 0 otherwise.

@example
.bytes_big_endian_defined
.words_big_endian_defined
@end example
Likewise, but undefined if not true, defined to `1' if true.
This can be used for conditional compilation, when it is available.

@example
.bytes_big_endian_bool (const (bool) .bytes_big_endian)
.words_big_endian_bool (const (bool) .words_big_endian)
@end example
With these constants you can write something like this:

@example
  (cond .words_big_endian_bool
    (call printf [parm (.string "Big endian!")])
    (call printf [parm (.string "Little endian!")]))
@end example

Code that is not reachable (for different endianess), will be
eliminated by GCC.

Several macros are passed by gcc driver program to Ksi compiler.
For example, for an gcc-3.0.1 on i586, without any special options
it include:

@example
.__GNUC__ 3
.__GNUC_MINOR__ 0
.__GNUC_PATHLEVEL__ 1
.cpu i386
.machine i386
.i386 1
.__i386 1
.__i386__ 1
.__tune_i586__ 1
.__tune_pentium__ 1
@end example

Important things might be `.i386', `.cpu' and `.machine' macros.
You probably shouldn't use __ versions, as there is no point to use them
in Ksi (separate namespace is maintained for system macros). You can
examine various flags passed by running `gcc -v test.ksi'.  Also note
`gcc -march=i686 -v test.ksi'.


@c ================================================================
@node Remarks 
@chapter Remarks on Ksi code generation

These are notes for compiler writer, who is going to use Ksi as a
target language.

Don't hardcode for example `(int 32)' in external functions defined
in C with `int' type. Use system macros, like .c_int for this purpose.
@xref{System macros}. This will allow compilation for different targets.

Write target-independent Ksi code whenever possible. It is the best to
write compiler that doesn't depend on target. Don't be afraid of writing
code that does nothing (`if (1) sth; else sth_else;' and similar),
that extensively uses constant expressions (`array[x * (4 + 2 + 1)]')
and so on. This will all get optimized, and user will get possibility
of changing target by just changing Ksi compiler in use.

There is no requirement of using or not using convenience preprocessor
macros like `.int32' or `.true'. I have added them mainly to write tests
more easily.

Don't use (goto ...) if possible. (block ...), (loop ...), (exit ...) and
(exit_loop ...) should be better optimized.

Don't be afraid of temporary variables, think about SSA -- there are
going to be zilons of them introduced by back end anyway.

If you're using tree operands that are not used in C or other front ends
in GCC, double check if they work correctly. Unfortunately not-used-in-C
predicate is also true for LABEL_EXPR and GOTO_EXPR used to implement
(label ...) and (goto ...).


@c ================================================================
@node Using ksi driver
@chapter How to use languages that have Ksi as a target

[[[Ok, maybe it's not as bright idea as it first seemed ;< However
still consider using target configuration files, I did that in Gont,
and it appears to work.]]]

`ksi' shell wrapper is called in style of Unix cc(1) command. It first
calls compiler, that outputs .ksi file, and then ksi compiler to
produce object files and/or executables. Ksi driver can be used to
compile .ksi files, however regular gcc command can be used as well.
The main goal of `ksi' wrapper is to compile other languages, that
use Ksi as target.

`ksi' command accepts following options:

@itemize @bullet
@item
-x LANG - specify language to use.
@item
-t TARGET, -target TARGET - use specified target. Targets use different
compilers.  
@item
-list-targets - print list of available targets.
@item
-o FILENAME - specify output file name. If name matches *.s - file
is not assembled, if it matches *.iksi, it's just preprocessed.
@item
-c - compile, do not link.
@item
-O*, -f*, -g* - passed to ksi_compiler.
@item
-W*, -F*, -w - passed to lang_compiler
@item
-v - passed to ksi_compiler, additionally prints out what is being called.
@item
-ksi-* - pass option to ksi_compiler, with -ksi stripped off.
@item
-lang-* - pass option to lang_compiler, with -lang stripped off.
@item
-mktarget TARGETNAME COMPILER - makes new target, in /etc/ksi or
~/.ksi depending if you're root or not. Making new target involves
preprocessing special config file.
@end itemize

Other options are invalid. Input files are specified by simply passing
them on command line.

Example. Let's say you have following files: f1.foo, f2.foo, runtime.ksi
and clib.c. You need to compile and link them together. f1.foo and f2.foo
are files in Foo language, targeted at Ksi.

@example
ksi -O2 -Wall -c f1.foo f2.foo
ksi -O3 -funroll-loops -c runtime.ksi
gcc -O2 -c clib.c
gcc -o myprog f1.o f2.o runtime.o clib.o
@end example

-Wall option is passed to foo compiler, so you'll probably get some
warnings for *.foo files.

And now, let's say you need to compile it for `mipsel-pld-linux' target:

@example
ksi -t mipsel-pld-linux -O2 -Wall -c f1.foo f2.foo
ksi -t mipsel-pld-linux -O3 -funroll-loops -c runtime.ksi
mipsel-pld-linux-gcc -O2 -c clib.c
mipsel-pld-linux-gcc -o myprog f1.o f2.o runtime.o clib.o
@end example


@c ================================================================
@node Adding languages to ksi driver
@chapter How to add languages that have Ksi as a target to ksi driver

If you are writing compiler targeted at ksi, you can simply write program
in style of cc1, that takes just few simple options, plus optionally
some flags that controls generated code.  Then add compiler spec file to
`/etc/ksi/lang.d'. For example to add compiler for language called foo,
that handles files matching *.foo and *.fooh, you need to write the
following to `/etc/ksi/lang.d/foo':

@example
suffixes="foo fooh"
lang_compiler=/usr/local/lib/foo/foo1
add_ksi_options=
@end example

Then doing simply:

@example
ksi -O3 -fomit-frame-pointer -c test.foo
@end example

will produce `test.o', and

@example
ksi test.foo
@end example

will produce `a.out'.

You can also use `~/.ksi/lang.d'.

However the entire idea behind `ksi' wrapper is being multitarget.
Ksi code generated by your compiler will be probably more or less
machine independent, and it is possible to cross-compile with the same
binary, only with different Ksi compilers connected. However you might
need to know few characteristics of target machine, thus special config
file is passed with each call to your compiler. It looks like this
(this is from i586-pld-linux host):

@example

ksi_version 1
c_int_bits 32
c_short_bits 16
c_long_bits 32
c_char_bits 1
c_long_long_bits 64
c_float_bits 32
c_double_bits 64
c_long_double_bits 96
c_ptr_bits 32
c_int_bytes 4
c_short_bytes 2
c_long_bytes 4
c_char_bytes 0
c_long_long_bytes 8
c_float_bytes 4
c_double_bytes 8
c_long_double_bytes 12
c_ptr_bytes 4
bytes_big_endian 0
words_big_endian 0
cpu i386
machine i386
@end example

You should not depend on order of lines in this file, however it
can be easily parsed using scanf(3) family of functions (note that
there are just name-value pairs, each being two words).

This is list of options that needs to be accepted by your compiler:

@itemize @bullet
@item
-target - which target are we compiling for.
@item
-target-conf FILENAME - name of file with configuration.
@item
-output FILENAME - which file to write .ksi output to, `-' for stdout.
@item
-input FILENAME - which file to read input from, `-' for stdin.
@end itemize

User can however pass more options. @xref{Using ksi driver},
for more information about how this options could be passed, and
therefore what will be the best way to choose them.

Note, that there is no requirement of using `ksi' driver program.
You might as well call ksi compiler directly. However, if you
lack something in `ksi' driver, tell me it, I'll be happy to add it.
If you're not using `ksi' driver remember about allowing users
cross-compilation, it is sometimes very handy.


@c ================================================================
@node TODO
@chapter Things to do

Add (in order of importance):

@enumerate
@item
passing sequence points and alias information, (AST optimizer, LI trees)
@item
do some testing with attributes, allow them everywhere
@item
(alignof ...)
@item
enums
@item
provide some way of passing binary data (array initializers?)
@item
const decl?
@item
arrays?
@item
initializers?
@item
methods?
@item
va_arg? (partially done, see builtins)
@item
exceptions? try/catch/finally, cleanups
@item
switch??? front end implementation parts required :<
@item
complex numbers
@item
bit fields?
@item
save/unsave, what's that?
@item
do some error recovery. Now there are plenty of fatal_error()s out there.
However, as ksi1 will in 99% of cases get right code (output of compiler)
this isn't very important.
@end enumerate

Any feedback (what else is needed, maybe other order?) is appreciated.


@c ================================================================
@node BUGS
@chapter Known bugs, how to report unknown

This chapter includes bugs that are known. Check it first to reporting
bugs, also look at the TODO section, @xref{TODO}. If you didn't found it 
here nor there, report it directly to author.

Known bugs:

@enumerate
@item
Value cannot be returned from (block ...). It's not implemented in GCC.
@item
(fix ...) other then trunc are not supported by GCC.
@end enumerate

Generally anything that will result in `Internal error' message
is bug. Other bugs include miscompilation of code (i.e. inconsistency
of generated code behavior with this manual and/or common sense).

Compiler hasn't been heavily tested against illegal input, therefore
it is highly possible to find bugs there.

In case you're submitting bug report, don't forget to mention
Ksi and GCC version used. Also in case of miscompilation check
with other targets if you can.


@c ================================================================
@node Author
@chapter Author

The person to blame for Ksi (language and front end) is 
Michal Moskal @email{malekith@@pld-linux.org}

Front end is available at 
@c aleph-0 is tmp(?) dead :<
@c @uref{ftp://aleph-0.dhs.org/pub/ksi/} and alternatively at 
@uref{ftp://ftp.pld.org.pl/people/malekith/ksi/}.
It was tested against gcc-3.1 release.
You might also want to have a look at Gont compiler that should be
somewhere around @uref{ftp://ftp.pld.org.pl/people/malekith/ksi/}
and also at @uref{ftp://ftp.kernel.pl/pub/People/malekith/gont/}.
It is written in OCaml and compiles high level language (called Gont) 
with ML-like types and C-like syntax to Ksi. It is work in progress
though.

@c general bookkeeping info... possibly should go elsewhere...
Front end is distributed under GNU General Public License, version 2.

I tried to write the front end readably, functions are short and simple,
indentation is huge to make things better visible.  See CodingStyle in
Linux kernel tarball for motivation, and discussion about -kr -i8 :)
Code is not well commented :< I hope to fix this some day. It is also
meant as a reference for writing front ends (as Ksi isn't very complex
language, and there is *very* little more in front end, then interface to
GCC back end).

Code requires ANSI C compiler. GCC shouldn't be required, but I'm
not sure (it is not important, as front ends are compiled by GCC
during bootstrap). glue.c file, that mainly (well, now maybe in 
50%...) comes from toy compiler, is written using K&R C (but I don't
mind...).

@c maybe insert few links here?
I would like to thank Fergus Henderson, Jonathan Bartlett,
Brian Young and Michael Meeks for the toy compiler, Cobol For GCC
authors, for Chapter 14 of documentation (Writing a Compiler Front 
End). Also Trees entry in GCC 3 .info files was very helpful.


@c ================================================================
@node Term index
@unnumbered Term index

@printindex fn

@bye
