Call #pragmas

Top  Previous  Next

 

#pragmas with the class name call affect all aspects of calling conventions, code segments, and code pointers. The current settings of the call #pragmas at the point at which a procedure’s definition is encountered, determines the calling convention that is used to call the procedure. SoftVelocity compilers detect if an inconsistent calling convention is used when a procedure is called. The type-safe linker reports an error if the calling conventions attributed to a given procedure do not match in every object file.

The following call #pragmas are available:

#pragma call(c_conv => on | off)

#pragma call(ds_entry => identifier)

#pragma call(ds_eq_ss => on | off)

#pragma call(inline => on | off)

#pragma call(inline_max => Number)

#pragma call(near_call => on | off)

#pragma call(o_a_copy => on | off)

#pragma call(o_a_size => on | off)

#pragma call(opt_var_arg => on | off)

#pragma call(reg_param => RegList)

#pragma call(reg_return => RegList)

#pragma call(reg_saved => RegList)

#pragma call(result_optional => on | off)

#pragma call(same_ds => on | off)

#pragma call(seg_name => identifier)

#pragma call(set_jmp => on | off)

#pragma call(standard_conv => on | off)

#pragma call(var_arg => on | off)

 

A pragma can be used in the Project language, C++ code, Modula-2 code, or Clarion code. Some only work in certain places. A ‘P’ to the right of the pragma indicates it can be used in the Project language, a ‘C’ indicates it can be used in C++ code, a ‘M’ indicates it can be used in Modula-2 code, and a ‘W’ indicates that it can be used in Clarion code (CLW files).

 

#pragma call(near_call => on | off)    cpm

Specifies whether procedure calls are near or far. When on, the compiler calls procedures with near calls. The compiler can only use near calls if the calling and called procedures are in the same segment. The compiler checks that this is the case.

The default value is off. This example forces near calls:

#pragma call(near_call=>on)

 

#pragma call(same_ds => on | off)    cpm

Specifies whether to load the data segment (DS) register on entry to a procedure. When on, DS will not be loaded as part of the procedure prolog. This will only be correct when the DS setting of the calling procedure matches that of the called procedure. The compiler checks that this is the case.

This option is off by default. For example:

#pragma call(same_ds => on)

This stops DS from being loaded in the procedure prolog.

 

#pragma call(c_conv => on | off)    cpm

When on, this option enables the Microsoft C calling convention. In this convention, the compiler pushes procedure parameters in right to left order on the stack and the caller pops these parameters off the stack.

This is not the default, so you should only use this #pragma when interfacing to Microsoft C code. For example:

#pragma call(c_conv=>on)

You can also use the cdecl keyword in C and C++ to achieve the same effect.

See also the standard_conv #pragma, which has the same effect for C and C++, but is ignored for Modula-2. The standard_conv #pragma is set off by default.

 

#pragma call(inline => on | off)     cm

If this #pragma is set on before a procedure definition, the compiler makes a copy of the procedure in the code rather than using a call instruction. The default value is off.

You can use this convention for any procedure, but this #pragma is mainly used together with the reg_param #pragma for simple machine-code procedures. For example:

 

#pragma save

#pragma call(inline => on, reg_param => (dx,ax))

static void outp(int port, unsigned char byt)=

{

0xEE, /* out dx,al */

};

#pragma restore

makes outp an inline procedure, so a call to it appears as a single 80x86 machine instruction: out dx,al.

 

#pragma call(seg_name => identifier)    cpm

Specifies the code segment name. call(seg_name => nnn) means that the compiler places the code for the procedure in segment nnn_TEXT. The default value depends on the memory model. In the small and compact models, the default is null; in the other models it is the name of the source file. For example, a code segment named _TEXT would be specified as:

#pragma call(seg_name => null)

and a code segment named MYCODE_TEXT, would be specified as:

#pragma call(seg_name => MYCODE)

The default setting is language dependent, and is not defined by the Project System.

 

#pragma call(ds_entry => identifier)    cpm

This #pragma indicates a segment name which the DS register will point to throughout the execution of a procedure. If the identifier is null, the compiler names the segment _DATA. If the identifier is none, the compiler does not assume a fixed DS during procedure execution and uses DS as a general purpose segment register like ES.

#pragma call(ds_entry => MYDATA)

This example indicates that on entry to the procedure, DS will point to the segment named MYDATA_DGROUP.

 

#pragma call(reg_param => RegList)    cm

SoftVelocity languages pass procedure parameters in machine registers rather than using the stack. This generates smaller and faster code. This #pragma allows you to fine-tune individual procedure calls for maximum speed. Other vendors’ languages use a less efficient calling convention; you must, therefore, disable this calling convention when interfacing to precompiled objects written for these compilers (see the Advanced Programmer’s Guide that comes with SoftVelocity C, C++, and Modula-2, Chapter 5: Multi-language Programming). This #pragma has no effect on structure parameters, which are always passed on the stack.

The argument for reg_param is a register list, specifying which registers should be used. Registers for parameters are allocated left to right from the list. The table shows how the compiler allocates registers dependent on parameter types:

1 byte ax, bx, cx, dx

2 bytes ax, bx, cx, dx, si, di

4 bytes ax, bx, cx, dx, si, di for low word.

ax, bx, cx, dx, si, di, es, ds for high word.

floating point st0, st1, st2, st3, st4, st5, st6

Note that the es and ds registers will only be used for the high word of a 4-byte parameter where that parameter is of pointer type. If either the low or high word cannot be allocated, then the whole parameter is passed on the stack.

When the compiler exhausts the list of registers, it passes the parameter on the stack. If you specify an empty list, the compiler uses the stack for all parameters.

The default setting for the SoftVelocity calling convention is:

#pragma call(reg_param=>(ax,bx,cx,dx,st0,st6,st5,st4,st3))

The default setting for the stack calling convention is:

#pragma call(reg_param => ())

 

#pragma call(reg_saved => RegList)    cm

This #pragma specifies which registers a procedure preserves. The argument RegList is a list that specifies the set of registers.

The default set for the SoftVelocity calling convention is:

ccall(reg_saved=>(ax,bx,cx,dx,si,di,ds,st1,st2))

The default set for the stack calling convention is:

#pragma call(reg_saved=>(si,di,ds,st1,st2))

 

#pragma call(o_a_size => on | off)    m

When on, this option passes the size of open array parameters on the stack:

(*# call( o_a_size => on ) *)

This #pragma has no effect for value parameter open arrays, unless the o_a_copy #pragma is set off.

The default setting is on.

 

#pragma call(o_a_copy => on | off)    m

When on, open array parameters are copied onto the stack as part of the procedure prolog. If off, only a reference to the array is passed. Note that the open array parameters size must be passed in order for a copy to be made - see #pragma call(o_a_size). The default setting is on.

 

#pragma call(ds_eq_ss => on | off)    m

It controls whether VAR parameters use 16- or 32-bit pointers. The default setting is on for small and medium models, otherwise off.

 

#pragma call(var_arg => on | off)    m

When on, it implies that the following procedures take a variable number of arguments. This effectively disables the "too many arguments" error that the compiler would normally detect. The consequence however, is that the compiler cannot carry out any type checking on the arguments.

This #pragma should be used when calling C procedures (such as printf) where the number of arguments varies:

 

(*# call(var_arg => on,

reg_param=>(),

c_conv=>on ) *)

The default setting is off.

 

#pragma call(reg_return => RegList)    cm

This #pragma is used to specify the registers to be used for return values of integer, pointer and floating point types. For example:

#pragma call(reg_return => (bx,cx))

The default setting is:

#pragma call(reg_return=>(ax,dx,st0))

 

#pragma call(result_optional => on | off)   m

It can be used to call a procedure as a proper procedure without generating a compiler error. For example:

 

(*# save *)

(*# module( result_optional => on ) *)

PROCEDURE FuncProc(x: CHAR): CARDINAL;

(*# restore *)

With this declaration, you can write both of the following:

 

i := FuncProc(‘a’);

FuncProc(‘a’);

This is only useful when the called procedure has a side effect that is more important than the result. It is particularly useful when calling SoftVelocity C library procedures.

The default setting is off.

 

#pragma call(set_jmp => on | off)    cm

This #pragma should only be used for the library routines which implement non-local jumps. The effect is to inform the compiler of the non-standard register saving properties of these routines.

 

#pragma call(inline_max => Number)    cpm

This #pragma controls the largest procedure which is inlined. The default setting is 12, which corresponds to the minimum code size for most programs. A larger value increases the code size and may accelerate code execution.

The #pragma takes effect for each call, so a procedure may be called in different ways at different places.

 

 Procedures are not inlined if the body has not been compiled before the call.

 

#pragma call(standard_conv => on | off)   c

The effect on C and C++ programs is the same as the call(c_conv) #pragma. For Modula-2 there is no effect. The default is off.

 

#pragma call(opt_var_arg => on | off)    cp

This #pragma controls whether optimized entry sequences are generated for procedures with variable parameter lists. The default is on.