* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
static char sccsid
[] = "@(#)p2put.c 5.3 (Berkeley) 6/21/85";
* functions to help pi put out
* polish postfix binary portable c compiler intermediate code
* thereby becoming the portable pascal compiler
* emits an ftext operator and a string to the pcstream
int length
= str4len( string
);
p2word( PCCM_TRIPLE( PCCF_FTEXT
, length
, 0 ) );
fprintf( stdout
, "PCCF_FTEXT | %3d | 0 " , length
);
return ( ( strlen( string
) + 3 ) / 4 );
* put formatted text into a buffer for printing to the pcstream.
* a call to putpflush actually puts out the text.
* none of arg1 .. arg5 need be present.
* and you can add more if you need them.
putprintf( format
, incomplete
, arg1
, arg2
, arg3
, arg4
, arg5
)
static char ppbuffer
[ BUFSIZ
];
static char *ppbufp
= ppbuffer
;
sprintf( ppbufp
, format
, arg1
, arg2
, arg3
, arg4
, arg5
);
ppbufp
= &( ppbuffer
[ strlen( ppbuffer
) ] );
if ( ppbufp
>= &( ppbuffer
[ BUFSIZ
] ) )
* emit a left bracket operator to pcstream
* with function number, the maximum temp register, and total local bytes
putlbracket(ftnno
, sizesp
)
maxtempreg
= sizesp
->curtmps
.next_avail
[REG_GENERAL
];
* this is how /lib/f1 wants it.
maxtempreg
= (sizesp
->curtmps
.next_avail
[REG_ADDR
] << 4)
| (sizesp
->curtmps
.next_avail
[REG_DATA
]);
alignedframesize
= roundup((int)(BITSPERBYTE
* -sizesp
->curtmps
.om_off
),
(long)(BITSPERBYTE
* A_STACK
));
p2word( PCCM_TRIPLE( PCCF_FLBRAC
, maxtempreg
, ftnno
) );
p2word(alignedframesize
);
fprintf(stdout
, "PCCF_FLBRAC | %3d | %d %d\n",
maxtempreg
, ftnno
, alignedframesize
);
* emit a right bracket operator
* which for the binary interface
* forces the stack allocate and register mask
p2word( PCCM_TRIPLE( PCCF_FRBRAC
, 0 , ftnno
) );
fprintf( stdout
, "PCCF_FRBRAC | 0 | %d\n" , ftnno
);
fprintf( stdout
, "PCCF_FEOF\n" );
* with a source file line number and name
* if line is negative, there was an error on that line, but who cares?
putdot( filename
, line
)
int length
= str4len( filename
);
p2word( PCCM_TRIPLE( PCCF_FEXPR
, length
, line
) );
fprintf( stdout
, "PCCF_FEXPR | %3d | %d " , length
, line
);
putleaf( op
, lval
, rval
, type
, name
)
p2word( PCCM_TRIPLE( PCC_ICON
, name
!= NIL
, type
) );
fprintf( stdout
, "PCC_ICON | %3d | 0x%x "
fprintf( stdout
, "%d\n" , lval
);
p2word( PCCM_TRIPLE( PCC_NAME
, lval
!= 0 , type
) );
fprintf( stdout
, "PCC_NAME | %3d | 0x%x "
fprintf( stdout
, "%d " , lval
);
p2word( PCCM_TRIPLE( PCC_REG
, rval
, type
) );
fprintf( stdout
, "PCC_REG | %3d | 0x%x\n" ,
* rvalues are just lvalues with indirection, except
* special cases for registers and for named globals,
* whose names are their rvalues.
putRV( name
, level
, offset
, other_flags
, type
)
if ( other_flags
& NREGVAR
) {
if ( ( offset
< 0 ) || ( offset
> P2FP
) ) {
putleaf( PCC_REG
, 0 , offset
, type
, (char *) 0 );
if ( whereis( offset
, other_flags
) == GLOBALVAR
) {
sprintf( extname
, EXTFORMAT
, name
);
putleaf( PCC_NAME
, offset
, 0 , type
, printname
);
panic( "putRV no name" );
putLV( name
, level
, offset
, other_flags
, type
);
putop( PCCOM_UNARY PCC_MUL
, type
);
* given a level and offset
* named globals, whose lvalues are just their names as constants.
putLV( name
, level
, offset
, other_flags
, type
)
if ( other_flags
& NREGVAR
) {
switch ( whereis( offset
, other_flags
) ) {
sprintf( extname
, EXTFORMAT
, name
);
putleaf( PCC_ICON
, offset
, 0 , PCCM_ADDTYPE( type
, PCCTM_PTR
)
panic( "putLV no name" );
putleaf( PCC_REG
, 0, P2AP
, PCCM_ADDTYPE( type
, PCCTM_PTR
), (char *) 0 );
putleaf( PCC_NAME
, (level
* sizeof(struct dispsave
)) + AP_OFFSET
, 0 , PCCTM_PTR
| PCCT_CHAR
, DISPLAYNAME
);
parts
[ level
] |= NONLOCALVAR
;
putleaf( PCC_ICON
, offset
, 0 , PCCT_INT
, (char *) 0 );
putop( PCC_PLUS
, PCCTM_PTR
| PCCT_CHAR
);
putleaf( PCC_REG
, 0, P2FP
, PCCM_ADDTYPE( type
, PCCTM_PTR
), (char *) 0 );
putleaf( PCC_NAME
, (level
* sizeof(struct dispsave
)) + FP_OFFSET
, 0 , PCCTM_PTR
| PCCT_CHAR
, DISPLAYNAME
);
parts
[ level
] |= NONLOCALVAR
;
putleaf( PCC_ICON
, -offset
, 0 , PCCT_INT
, (char *) 0 );
putop( PCC_MINUS
, PCCTM_PTR
| PCCT_CHAR
);
putleaf( PCC_REG
, 0, P2FP
, PCCM_ADDTYPE( type
, PCCTM_PTR
), (char *) 0 );
putleaf( PCC_NAME
, (level
* sizeof(struct dispsave
)) + FP_OFFSET
, 0 , PCCTM_PTR
| PCCT_CHAR
, DISPLAYNAME
);
parts
[ level
] |= NONLOCALVAR
;
putleaf( PCC_ICON
, 0 , 0 , PCCT_INT
, name
);
putop( PCC_MINUS
, PCCTM_PTR
| PCCT_CHAR
);
* put out a floating point constant leaf node
* the constant is declared in aligned data space
* and a PCC_NAME leaf put out for it
putprintf( " .data" , 0 );
putprintf( " .double 0d%.20e" , 0 , val
);
putprintf( " .long 0x%x,0x%x", 0, val
);
putprintf( " .text" , 0 );
sprintf( name
, PREFIXFORMAT
, LABELPREFIX
, label
);
putleaf( PCC_NAME
, 0 , 0 , PCCT_DOUBLE
, name
);
* put out either an lvalue or an rvalue for a constant string.
* an lvalue (for assignment rhs's) is the name as a constant,
* an rvalue (for parameters) is just the name.
putCONG( string
, length
, required
)
putprintf( " .data" , 0 );
putprintf( " .byte 0%o" , 1 , *cp
++ );
for ( others
= 2 ; ( others
<= 8 ) && *cp
; others
++ ) {
putprintf( ",0%o" , 1 , *cp
++ );
pad
= length
- strlen( string
);
putprintf( " .byte 0%o" , 1 , ' ' );
for ( others
= 2 ; ( others
<= 8 ) && ( pad
-- > 0 ) ; others
++ ) {
putprintf( ",0%o" , 1 , ' ' );
putprintf( " .byte 0" , 0 );
putprintf( " .text" , 0 );
sprintf( name
, PREFIXFORMAT
, LABELPREFIX
, label
);
if ( required
== RREQ
) {
putleaf( PCC_NAME
, 0 , 0 , PCCTM_ARY
| PCCT_CHAR
, name
);
putleaf( PCC_ICON
, 0 , 0 , PCCTM_PTR
| PCCT_CHAR
, name
);
* map a pascal type to a c type
* this would be tail recursive, but i unfolded it into a for (;;).
* this is sort of like isa and lwidth
* a note on the types used by the portable c compiler:
* they are divided into a basic type (char, short, int, long, etc.)
* and qualifications on those basic types (pointer, function, array).
* the basic type is kept in the low 4 bits of the type descriptor,
* and the qualifications are arranged in two bit chunks, with the
* most significant on the right,
* and the least significant on the left
* (a function returning a pointer to an integer)
* so, we build types recursively
* also, we know that /lib/f1 can only deal with 6 qualifications
* so we stop the recursion there. this stops infinite type recursion
* through mutually recursive pointer types.
return typerecur( np
, 0 );
if ( np
== NIL
|| quals
> MAXQUALS
) {
if ( np
-> type
== ( nl
+ TDOUBLE
) ) {
switch ( bytes( np
-> range
[0] , np
-> range
[1] ) ) {
return ( PCCTM_ARY
| PCCT_CHAR
);
return ( PCCTM_PTR
| PCCT_STRTY
);
return p2type( np
-> type
);
return ( PCCTM_PTR
| PCCT_UNDEF
);
return ( PCCTM_ARY
| PCCT_CHAR
);
return ( p2type( np
-> type
) );
return PCCM_ADDTYPE( typerecur( np
-> type
, quals
+ 1 ) , PCCTM_PTR
);
return PCCM_ADDTYPE( typerecur( np
-> type
, quals
+ 1 ) , PCCTM_ARY
);
* functions are really pointers to functions
* which return their underlying type.
return PCCM_ADDTYPE( PCCM_ADDTYPE( typerecur( np
-> type
, quals
+ 2 ) ,
PCCTM_FTN
) , PCCTM_PTR
);
* procedures are pointers to functions
* which return integers (whether you look at them or not)
return PCCM_ADDTYPE( PCCM_ADDTYPE( PCCT_INT
, PCCTM_FTN
) , PCCTM_PTR
);
* formal procedures and functions are pointers
* to structures which describe their environment.
return ( PCCTM_PTR
| PCCT_STRTY
);
* put a typed operator to the pcstream
p2word( PCCM_TRIPLE( op
, 0 , type
) );
fprintf( stdout
, "%s (%d) | 0 | 0x%x\n"
, p2opname( op
) , op
, type
);
* put out a structure operator (STASG, STARG, STCALL, UNARY STCALL )
* which looks just like a regular operator, only the size and
* alignment go in the next consecutive words
putstrop( op
, type
, size
, alignment
)
p2word( PCCM_TRIPLE( op
, 0 , type
) );
fprintf( stdout
, "%s (%d) | 0 | 0x%x %d %d\n"
, p2opname( op
) , op
, type
, size
, alignment
);
* the string names of p2ops
static struct p2op p2opnames
[] = {
PCC_STRING
, "PCC_STRING",
PCC_UMINUS
, "PCC_UMINUS",
PCC_ADDROF
, "PCC_ADDROF",
PCC_ANDAND
, "PCC_ANDAND",
PCC_ASSIGN
, "PCC_ASSIGN",
PCC_FORTCALL
, "PCC_FORTCALL",
PCC_UFORTCALL
, "PCC_UFORTCALL",
PCC_CCODES
, "PCC_CCODES",
PCC_STCALL
, "PCC_STCALL",
PCC_USTCALL
, "PCC_USTCALL",
PCC_PMCONV
, "PCC_PMCONV",
PCC_PVCONV
, "PCC_PVCONV",
PCC_CBRANCH
, "PCC_CBRANCH",
static char *p2map
[PCC_MAXOP
+1];
static bool mapready
= FALSE
;
register struct p2op
*pp
;
if ( mapready
== FALSE
) {
for ( pp
= p2opnames
; pp
->op
>= 0; pp
++ )
p2map
[ pp
->op
] = pp
->name
;
return ( p2map
[ op
] ? p2map
[ op
] : "unknown" );
* puts a long word on the pcstream
* put a length 0 mod 4 null padded string onto the pcstream
int slen
= strlen( string
);
int wlen
= ( slen
+ 3 ) / 4;
int plen
= ( wlen
* 4 ) - slen
;
for ( cp
= string
; *cp
; cp
++ )
for ( p
= 1 ; p
<= plen
; p
++ )
fprintf( stdout
, "\"%s" , string
);
for ( p
= 1 ; p
<= plen
; p
++ )
fprintf( stdout
, "\\0" );
fprintf( stdout
, "\"\n" );
* puts a name on the pcstream
fprintf( pcstream
, NAMEFORMAT
, name
);
pad
= strlen( name
) % sizeof (long);
for ( ; pad
< sizeof (long) ; pad
++ ) {
fprintf( stdout
, NAMEFORMAT
, name
);
pad
= strlen( name
) % sizeof (long);
for ( ; pad
< sizeof (long) ; pad
++ ) {
fprintf( stdout
, "\\0" );
fprintf( stdout
, "\n" );
* put out a jump to a label
printjbr( LABELPREFIX
, label
);
* put out a jump to any kind of label
printjbr( prefix
, label
)
putprintf( " jbr " , 1 );
putprintf( PREFIXFORMAT
, 0 , prefix
, label
);
putprintf( " jra " , 1 );
putprintf( PREFIXFORMAT
, 0 , prefix
, label
);
* another version of put to catch calls to put