📄 init.c
字号:
/* * C compiler * ========== * * Copyright 1989, 1990, 1991 Christoph van Wuellen. * Credits to Matthew Brandt. * All commercial rights reserved. * * This compiler may be redistributed as long there is no * commercial interest. The compiler must not be redistributed * without its full sources. This notice must stay intact. * * History: * * 1989 starting an 68000 C compiler, starting with material * originally by M. Brandt * 1990 68000 C compiler further bug fixes * started i386 port (December) * 1991 i386 port finished (January) * further corrections in the front end and in the 68000 * code generator. * The next port will be a SPARC port *//*****************************************************************************/#include "chdr.h"#include "expr.h"#include "cglbdec.h"#include "proto.h"#include "outproto.h"/********************************************************** Static Variables */#ifdef CPU_DEFINEDstatic BOOL was_bitfield = FALSE;#endif /* CPU_DEFINED */static UVAL bit_value = (UVAL) 0;static int level = 0;/*********************************************** Static Function Definitions */static EXPR *constexpr P_ ((TYP *));static SIZE initarray P_ ((TYP *, BOOL));static SIZE initbitfield P_ ((TYP *));static SIZE initbool P_ ((TYP *));static SIZE initchar P_ ((TYP *));static SIZE initlong P_ ((TYP *));static SIZE initpointer P_ ((TYP *));static SIZE initshort P_ ((TYP *));static SIZE initstruct P_ ((const TYP *, BOOL));static SIZE inittype P_ ((TYP *));static SIZE initunion P_ ((const TYP *, BOOL));static void check_brace P_ ((BOOL));static EXPR *initializer P_ ((TYP *, SIZE, STORAGE));
#ifdef CPU_DEFINEDstatic SIZE alignfield P_ ((SIZE, SIZE));#endif /* CPU_DEFINED */#ifdef TOPSPEEDstatic SIZE initfunc P_ ((BOOL));#endif /* TOPSPEED */#ifdef LONGLONG_SUPPORTstatic SIZE initlonglong P_ ((TYP *));#endif /* LONGLONG_SUPPORT */ #ifdef FLOAT_SUPPORT#ifndef FLOAT_BOOTSTRAPstatic SIZE initfloat P_ ((TYP *));static SIZE initdouble P_ ((TYP *));static SIZE initlongdouble P_ ((TYP *));#endif /* FLOAT_BOOTSTRAP */#endif /* FLOAT_SUPPORT *//*****************************************************************************/static void check_brace P1 (BOOL, brace_seen){#ifndef SYNTAX_CORRECT if (!brace_seen) { if (level == 1) { message (ERR_BRACE); } else { message (WARN_BRACE); } }#endif /* SYNTAX_CORRECT */}SIZE align P2 (const TYP *, tp, SIZE, offset){ SIZE size = 0L;#ifdef CPU_DEFINED SIZE al = alignment_of_type (tp);#else SIZE al = tp->size;#endif if (al) { while ((offset + size) % al) size++; } return size;}#ifdef CPU_DEFINED/* * cast an argument back which has been widened on the caller's side. * append the resulting assignment expression to init_node */static void castback P3 (SIZE, offset, TYP *, tp1, TYP *, tp2){ EXPR *ep1, *ep2; if (is_same_type (tp1, tp2)) { return; } ep2 = mk_autocon (offset); ep1 = copynode (ep2); ep2 = mk_ref (ep2, tp1); ep2 = mk_node (en_cast, ep2, NIL_EXPR, tp2); ep1 = mk_ref (ep1, tp2); ep1 = mk_node (en_assign, ep1, ep2, tp2); if (init_node == NIL_EXPR) { init_node = ep1; } else { init_node = mk_node (en_comma, init_node, ep1, tp2); }}/* * Round 'size' up to a multiple of 'algn' */static SIZE roundup P2 (SIZE, size, SIZE, algn){ if (size % algn) { size = ((size / algn) + 1) * algn; } return size;}SIZE allocate_storage P4 (SYM *, sp, SIZE, offset, STORAGE, def_sc, BOOL, promoted){ TYP *tp = typeof (sp); SIZE size; switch (storageof (sp)) { case sc_register: if (def_sc == sc_parms) { goto parms; /*lint !e801*/ /* use of goto is deprecated */ } /*lint -fallthrough */ case sc_auto: size = tp->size; switch (tp->type) { case bt_struct: case bt_union: size = roundup (size, alignment_of_type (tp)); break; default: break; } if (g_is_ascending_stack ()) { sp->value.i = (IVAL) (offset + align (tp, offset) + 1L); } else { sp->value.i = (IVAL) (-(offset + align (tp, offset) + size)); } offset += align (tp, offset) + size; break; case sc_static: if (sp->value.l == UNDEF_LABEL) { sp->value.l = nextlabel++; } break; case sc_parms: parms: /* * If we don't have a prototype in scope (ie. promoted is true) * then parameters may have been widened when passed. By knowing * whether this is a BIGendian or LOWendian machine we can adjust * the stack offset in order to perform the implicit narrowing cast. */ switch (tp->type) { case bt_char: case bt_charu: case bt_uchar: case bt_schar: if (g_is_ascending_stack ()) { sp->value.i = (IVAL) (-(offset + tp->size) + 1L); } else { if (g_is_bigendian ()) { tp = promoted ? promote_type (tp) : tp_short; sp->value.i = (IVAL) (offset + tp->size - 1L); } else { tp = tp_int; sp->value.i = (IVAL) offset; } } break; case bt_short: case bt_ushort: case bt_int16: case bt_uint16: if (g_is_ascending_stack ()) { sp->value.i = (IVAL) (-(offset + tp->size) + 1); } else { if (g_is_bigendian ()) { tp = promoted ? promote_type (tp) : tp_short; sp->value.i = (IVAL) (offset + tp->size - 2L); } else { tp = tp_int; sp->value.i = (IVAL) offset; } } break; case bt_float: if (g_is_ascending_stack ()) { sp->value.i = (IVAL) (-(offset + tp->size) + 1L); } else { if (promoted) { castback (offset, tp_double, tp); tp = tp_double; } sp->value.i = (IVAL) offset; } break; case bt_pointer16: case bt_pointer32: tp = tp_pointer; goto lab; /* common code with function */ /*lint !e801*/ /* use of goto is deprecated */ case bt_func: tp = tp_func; /* * arrays and functions are never passed. They are really * Pointers */ lab:if (is_derived_type (typeof (sp))) { global_flag++; set_type (sp, copy_type (typeof (sp))); global_flag--; typeof (sp)->state &= (STATE) ~(unsigned) STATE_DERIVED; typeof (sp)->size = tp->size; } /*lint -fallthrough */ default: if (g_is_ascending_stack ()) { sp->value.i = (IVAL) (-(offset + tp->size) + 1L); } else { sp->value.i = (IVAL) offset; } break; } offset += tp->size; break; default: break; } return offset;}#endif /* CPU_DEFINED */SIZE doinit P2 (SYM *, sp, SIZE, offset){ TYP *tp = typeof (sp);#ifdef CPU_DEFINED LABEL label; EXPR *ep1;#endif /* CPU_DEFINED */ EXPR *ep2; int brace_level = 0; switch (lastst) { case tk_assign: /* Initializer */ getsym (); symbol_set (sp); switch (storageof (sp)) { case sc_auto: case sc_register: /* AUTO Initialisation */ switch (tp->type) { case bt_pointer16: case bt_pointer32: if (!is_array_type (tp)) { goto common; /*lint !e801*/ /* use of goto is deprecated */ } /* This must be an array. However it is possible that the * size of the array isn't known until we have parsed the * initializer. We must therefore delay calculating the * offset of the item on the stack until we know it's actual * size. */ /*lint -fallthrough */ case bt_struct: case bt_union:#ifndef SYNTAX_CORRECT if (lang_option == LANG_KANDR) { message (ERR_ILLINIT); }#endif /* SYNTAX_CORRECT */ if (lastst == tk_id || lastst == tk_star || lastst == tk_openpa) { goto common; /*lint !e801*/ /* use of goto is deprecated */ }#ifdef CPU_DEFINED label = nextlabel++; put_kseg (alignment_of_type (tp)); put_label (label);#endif /* CPU_DEFINED */ VOIDCAST inittype (tp); if (is_array_type (tp)) { tp = copy_type (tp); set_array_assignment (tp); }#ifdef CPU_DEFINED ep2 = mk_lcon (label); ep2 = mk_ref (ep2, tp); uses_structassign = TRUE;#endif /* CPU_DEFINED */ break; default: common: while (lastst == tk_begin) { brace_level++; getsym (); } ep2 = exprnc ();#ifndef SYNTAX_CORRECT if (ep2 == NIL_EXPR) { message (ERR_ILLINIT); break; }#endif /* SYNTAX_CORRECT */ ep2 = implicit_castop (ep2, tp); }#ifdef CPU_DEFINED offset = allocate_storage (sp, offset, sc_auto, FALSE); ep1 = mk_symnode (sp); ep1 = mk_ref (ep1, tp); ep1 = mk_node (en_assign, ep1, ep2, tp); if (init_node == NIL_EXPR) { init_node = ep1; } else { init_node = mk_node (en_comma, init_node, ep1, tp); }#endif /* CPU_DEFINED */ while (brace_level--) needpunc (tk_end); break; /* Normal initializers */ case sc_static:#ifdef CPU_DEFINED offset = allocate_storage (sp, offset, sc_auto, FALSE); put_dseg (alignment_of_type (tp)); put_label (sp->value.l);#endif /* CPU_DEFINED */ VOIDCAST inittype (tp); break; case sc_external:#ifndef SYNTAX_CORRECT if (!is_global_scope (sp)) { message (ERR_ILLINIT); }#endif /* SYNTAX_CORRECT */ set_storage (sp, sc_global); /*lint -fallthrough */ case sc_global:#ifdef CPU_DEFINED put_dseg (alignment_of_type (tp)); put_name (sp);#endif /* CPU_DEFINED */ VOIDCAST inittype (tp); break;#ifndef SYNTAX_CORRECT case sc_parms: message (ERR_ILLINIT); break;#endif /* SYNTAX_CORRECT */ default: CANNOT_REACH_HERE (); break; }#ifndef SYNTAX_CORRECT if (is_symbol_defined (sp)) { message (ERR_REDECL, nameof (sp)); }#endif /* SYNTAX_CORRECT */ symbol_defined (sp); break; default:#ifndef SYNTAX_CORRECT switch (storageof (sp)) { case sc_auto: case sc_global: case sc_static: if (is_const_qualified (typeof (sp))) { message (WARN_CONSTINIT, nameof (sp)); } break; default: break; }#endif /* SYNTAX_CORRECT */#ifdef CPU_DEFINED offset = allocate_storage (sp, offset, sc_auto, FALSE);#endif /* CPU_DEFINED */ break; } sequence_point (); return offset;}static SIZE inittype P1 (TYP *, tp){ BOOL brace_seen = FALSE; SIZE nbytes; level++; if (lastst == tk_begin) { brace_seen = TRUE; getsym (); } switch (tp->type) { case bt_bool: nbytes = initbool (tp); break; case bt_char: case bt_charu: case bt_uchar: case bt_schar: nbytes = initchar (tp); break; case bt_short: case bt_ushort: case bt_int16: case bt_uint16: nbytes = initshort (tp); break; case bt_pointer16: case bt_pointer32: if (is_array_type (tp)) { nbytes = initarray (tp, brace_seen); } else { nbytes = initpointer (tp); } break; case bt_bitfield: case bt_ubitfield: case bt_bbitfield: nbytes = initbitfield (tp); break; case bt_int32: case bt_uint32: case bt_ulong: case bt_long: nbytes = initlong (tp); break; #ifdef LONGLONG_SUPPORT case bt_longlong: case bt_ulonglong: nbytes = initlonglong (tp); break; #endif /* LONGLONG_SUPPORT */ case bt_struct: nbytes = initstruct (tp, brace_seen); break; case bt_union: nbytes = initunion (tp, brace_seen); break;#ifdef FLOAT_SUPPORT#ifndef FLOAT_BOOTSTRAP case bt_float: nbytes = initfloat (tp); break; case bt_double: nbytes = initdouble (tp); break; case bt_longdouble: nbytes = initlongdouble (tp); break;#endif /* FLOAT_BOOTSTRAP */#endif /* FLOAT_SUPPORT */#ifdef TOPSPEED case bt_func: if (topspeed_option) { nbytes = initfunc (brace_seen); break; } /*lint -fallthrough */#endif /* TOPSPEED */ default:#ifndef SYNTAX_CORRECT message (ERR_NOINIT); nbytes = 0L;#endif /* SYNTAX_CORRECT */ break; } if (brace_seen) { if (lastst == tk_comma) { getsym (); } needpunc (tk_end); } level--; return nbytes;}#ifdef TOPSPEED/* * The TopSpeed C Compiler allows function to be "inlined" as * a series of initialized bytes. */static SIZE initfunc P1 (BOOL, brace_seen){ SIZE nbytes; check_brace (brace_seen); for (nbytes = 0L;;) { VOIDCAST arithexpr (tp_uchar); nbytes += tp_uchar->size; if (lastst != tk_comma) { break; } getsym (); /* comma */ if (lastst == tk_end) { break; } } return nbytes;}#endif /* TOPSPEED */static SIZE initarray P2 (TYP *, tp, BOOL, brace_seen){ SIZE nbytes; TYP *rtp = referenced_type (tp); if (((lastst == tk_sconst) && (is_char (rtp) || rtp->type == bt_uchar || rtp->type == bt_schar)) || ((lastst == tk_wsconst && is_same_type (rtp, tp_wchar)))) {#ifdef CPU_DEFINED SIZE len; const CHAR *p;#endif /* CPU_DEFINED */ nbytes = (SIZE) lastsymlen;#ifdef CPU_DEFINED for (len = nbytes, p = lastsym; len--;) put_byte ((UVAL) *p++);#endif /* CPU_DEFINED */ if (is_unknown_size (tp)) { tp->size = nbytes + 1L; } getsym (); /* skip sconst/wsconst */ } else { check_brace (brace_seen); for (nbytes = 0L;;) { nbytes += inittype (rtp); if (lastst != tk_comma || nbytes == tp->size) { break; } getsym (); /* comma */ if (lastst == tk_end) { break; } }#ifndef SYNTAX_CORRECT if (tp->size > nbytes) { message (WARN_INCOMPLETE); }#endif /* SYNTAX_CORRECT */ }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -