diff -uNr gdc-0.21/d/ChangeLog gdc-0.22/d/ChangeLog --- gdc-0.21/d/ChangeLog 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/ChangeLog 2007-02-06 05:30:00.000000000 +0100 @@ -1,3 +1,188 @@ +2007-02-05 David Friedman + + Release GDC 0.22 + + * d-codegen.cc (twoFieldType): Fix back end -> front end type + mapping. + + * Make-lang.in: Enable ELFOBJ to put some RTTI in the read-only + data section. + + * GDC.html: Update + +2007-02-04 David Friedman + + * phobos/gcc/cbridge_time.c (_d_gnu_cbridge_tza), + phobos/std/date.d: Fix timezone adjust sign + +2007-02-03 David Friedman + + * phobos/config/unix-mid: Correctly initialize sockaddr* + (Bugzilla 818) + + * dmd-script: Fix -H* options (Bugzilla 896). + Support -framework. Fix error message. + + * d-lang.cc (d_write_global_declarations), patch-gcc-4.1.x: + Fixes for dwarf2out ICEs + + * d-objfile.cc (check_static_sym): Fix setting TREE_CONSTANT. + + Rest of DMD 1.004 merge: + + * gcc-mars.cc, gdc-version: Update + + * phobos/std/regexp.d: update + + * phobos/internal/gc/gcold.d (_d_newarrayip): + + * phobos/internal/gc/gc.d: Fix argument and result types. + + * phobos/config/unix-head, phobos/config/unix-mid: Update + + * phobos/Makefile.in: Update for files removed in DMD 1.004 + + * d-decls.cc (TypedefDeclaration::toInitializer): Copy + from dmd/tocsym.c. Create the Sdt here. + + * dmd/toobj.c (TypedefDeclaration::toObjFile): Update + for toInitializer change + + * dmd/mtype.c (TypeArray::dotExp): Fix library call decls + + * d-lang.cc: Update + + * d-codegen.[ch], d-glue.cc: Update memory allocation library + calls. + + * d-lang.cc (d_write_global_declarations): call + emit_debug_global_declarations only for GCC 4.0 + + * dmd/mtype.c (TypeArray::dotExp): update + + * phobos/config/unix-head, phobos/config/unix-mid: update + + * phobos/internal/gc/gcold.d: Use old GDC modifications. + +2007-02-02 David Friedman + + Initial merge DMD 1.004: + + * dmd/aggregate.h, dmd/attrib.c, dmd/attrib.h, dmd/declaration.c, + dmd/declaration.h, dmd/dsymbol.c, dmd/dsymbol.h, dmd/expression.c, + dmd/import.c, dmd/import.h, dmd/inline.c, dmd/mars.c, dmd/mars.h, + dmd/module.c, dmd/module.h, dmd/mtype.c, dmd/mtype.h, + dmd/struct.c, dmd/template.c, dmd/template.h, dmd/tocsym.c, + dmd/todt.c, dmd/toobj.c, dmd/typinf.c: Merge DMD 1.004 + + * phobos/internal/aaA.d, phobos/internal/adi.d, + phobos/internal/arraycast.d, phobos/internal/arraycat.d, + phobos/internal/gc/gc.d, phobos/internal/gc/gcx.d, + phobos/internal/gc/linux.mak, phobos/internal/gc/win32.mak, + phobos/internal/object.d, phobos/linux.mak, phobos/object.d, + phobos/std/c/linux/linux.d, phobos/std/compiler.d, + phobos/std/file.d, phobos/std/gc.d, phobos/std/outbuffer.d, + phobos/std/random.d, phobos/std/regexp.d, + phobos/std/typeinfo/ti_AC.d, phobos/std/typeinfo/ti_Acdouble.d, + phobos/std/typeinfo/ti_Acfloat.d, phobos/std/typeinfo/ti_Acreal.d, + phobos/std/typeinfo/ti_Adouble.d, phobos/std/typeinfo/ti_Afloat.d, + phobos/std/typeinfo/ti_Ag.d, phobos/std/typeinfo/ti_Aint.d, + phobos/std/typeinfo/ti_Along.d, phobos/std/typeinfo/ti_Areal.d, + phobos/std/typeinfo/ti_Ashort.d, phobos/std/typeinfo/ti_C.d, + phobos/std/typeinfo/ti_cdouble.d, phobos/std/typeinfo/ti_cfloat.d, + phobos/std/typeinfo/ti_char.d, phobos/std/typeinfo/ti_creal.d, + phobos/std/typeinfo/ti_dchar.d, phobos/std/typeinfo/ti_delegate.d, + phobos/std/typeinfo/ti_double.d, phobos/std/typeinfo/ti_float.d, + phobos/std/typeinfo/ti_ptr.d, phobos/std/typeinfo/ti_real.d, + phobos/std/typeinfo/ti_void.d, phobos/std/typeinfo/ti_wchar.d, + phobos/win32.mak: Merge DMD 1.004 + + * phobos/std/typeinfo/ti_Aa.d, phobos/std/typeinfo/ti_Adchar.d, + phobos/std/typeinfo/ti_Aubyte.d, phobos/std/typeinfo/ti_Auint.d, + phobos/std/typeinfo/ti_Aulong.d, phobos/std/typeinfo/ti_Aushort.d, + phobos/std/typeinfo/ti_Awchar.d: Removed in DMD 1.004 + + * phobos/internal/gc/gcold.d: New in DMD 1.004 + +2007-02-01 David Friedman + + * d-lang.cc (d_write_global_declarations): Emit debug info. + + * d-codegen.cc (twoFieldType): Fix debugging information. + * d-objfile.cc (initTypeDecl): Ditto. + + * d-glue.cc (PtrExp::toElem): Don't wrap the result in + a NOP_EXPR. + + * Make-lang.in: Add d-tree.def to dependencies + +2007-01-30 David Friedman + + GCC 4.1.x changes: + + * GDC.html, INSTALL, INSTALL.html, README: update + + * dmd/idgen.c, dmd/impcnvgen.c, dmd/mtype.h: Change to allow + compilation as C. + + * patch-gcc-4.1.x, patch-toplev-4.1.x: New files + + * Make-lang.in: Use $(version) instead of $(gcc_version). + Add d-bi-attrs-41.h. Use C for generator programs instead of C++. + + * d-bi-attrs-41.h: New file. + + * d-builtins.c: update + + * d-builtins2.cc: Do not associate d_gcc_builtin_va_list_d_type with + va_list_type_node. Do this for GCC 4.0 and 4.1. + + * d-codegen.cc: Use CtorEltMaker. + (maybeExpandSpecialCall): Cast d_gcc_builtin_va_list_d_type to + va_list_type_node. + (hostToTargetString): Update. + + * d-codegen.h: Add CtorEltMaker class for before/after 4.1.x + compatibility. + + * d-convert.cc: Add special case for pointer/int comparison + + * d-decls.cc: Do not use SET_DECL_ASSEMBLER_NAME for CONST_DECLs + + * d-gcc-includes.h: Include vec.h + + * d-glue.cc: Use CtorEltMaker. + (gcc_d_backend_init): Call default_init_unwind_resume_libfunc + + * d-lang.cc: Add d_types_compatible_p hook for va_list conversion + + * d-lang.h: Update + + * d-objfile.cc: CtorEltMaker. + + * phobos/std/conv.d: Do not assume signed integer wraparound. + +2007-01-28 David Friedman + + * d-asm-i386.h, d-codegen.cc, d-gcc-real.cc, + d-decls.cc, d-glue.cc, d-lanc.cc: various fixes + + * d-codegen.cc, d-codegen.h, d-glue.cc, d-lang.h: + Remove bit array code + +2007-01-27 David Friedman + + * d-asm-i386.h: fix fistp, lmsw, lldt, mov[sz]x, setCC, smsw, and + sldt instructions (Bugzilla 836, 837, 838, 839, 841, 843, 844). + Also r[co][lr]. + + * d-glue.cc (StringExp::toElem): Correct termination of wchar + and dchar (Bugzilla 889) + +2007-01-11 David Friedman + + * INSTALL.html: fix corruption + 2007-01-03 David Friedman Release GDC 0.21 diff -uNr gdc-0.21/d/d-asm-i386.h gdc-0.22/d/d-asm-i386.h --- gdc-0.21/d/d-asm-i386.h 2007-01-03 06:19:29.000000000 +0100 +++ gdc-0.22/d/d-asm-i386.h 2007-01-28 20:17:23.000000000 +0100 @@ -116,7 +116,8 @@ Int_Types, Word_Types, // same as Int_Types, but byte is not allowed FP_Types, - FPInt_Types + FPInt_Types, + Byte_NoType, // byte only, but no type suffix } TypeNeeded; typedef enum { @@ -161,9 +162,12 @@ Op_DstSrcNT, Op_UpdSrcNT, Op_DstMemNT, + Op_DstRMBNT, + Op_DstRMWNT, Op_UpdUpd, Op_UpdUpdF, Op_Src, + Op_SrcRMWNT, Op_SrcW, Op_SrcImm, Op_Src_DXAXF, @@ -390,9 +394,12 @@ /* Op_DstSrcNT */ { D|mr, mr, 0, 0 }, // used for movd .. operands can be rm32,sse,mmx /* Op_UpdSrcNT */ { U|mr, mr, 0, 0 }, // used for movd .. operands can be rm32,sse,mmx /* Op_DstMemNT */ { D|mem, 0, 0 }, + /* Op_DstRMBNT */ { D|mr, 0, 0, Byte_NoType }, + /* Op_DstRMWNT */ { D|mr, 0, 0 }, /* Op_UpdUpd */ { U|mr,U|mr, 0,/**/1 }, /* Op_UpdUpdF */ { U|mr,U|mr, 0,/**/1, Clb_Flags }, /* Op_Src */ { mri, 0, 0, 1 }, + /* Op_SrcRMWNT */ { mr, 0, 0, 0 }, /* Op_SrcW */ { mri, 0, 0, Word_Types }, /* Op_SrcImm */ { imm }, /* Op_Src_DXAXF */ { mr, 0, 0, 1, Clb_SizeDXAX|Clb_Flags }, @@ -466,8 +473,8 @@ /* Op_movs */ { mem, mem, 0, 1, Clb_DI|Clb_SI }, // only src/DS can be overridden /* Op_movsd */ { 0, 0, 0, 0, Clb_DI|Clb_SI, Next_Form, Op_DstSrcSSE }, // %% gas doesn't accept movsd .. has to movsl /* Op_movsX */ { 0, 0, 0, 0, Clb_DI|Clb_SI }, - /* Op_movsx */ { reg, mr, 0, 1 }, // type suffix is special case - /* Op_movzx */ { reg, mr, 0, 1 }, // type suffix is special case + /* Op_movsx */ { D|reg, mr, 0, 1 }, // type suffix is special case + /* Op_movzx */ { D|reg, mr, 0, 1 }, // type suffix is special case /* Op_mul */ { U|ax, mr, 0, 1, Clb_SizeDXAX|Clb_Flags, Next_Form, Op_Src_DXAXF }, /* Op_out */ { N|port,ax, 0, 1 }, /* Op_outs */ { N|dx, mem, 0, 1, Clb_SI }, @@ -688,8 +695,8 @@ { "fincstp",Op_F0_P }, { "finit", Op_F0_P }, { "fist", Op_Fid }, // only 16,32bit - { "fisttp", Op_Fid_P }, { "fistp", Op_Fid_P }, + { "fisttp", Op_Fid_P }, { "fisub", Op_Fis_ST }, { "fisubr", Op_Fis_ST }, { "fld", Op_fld }, @@ -813,8 +820,8 @@ { "lgdt", Op_SrcMemNT }, { "lgs", Op_DstSrc }, { "lidt", Op_SrcMemNT }, - { "lldt", Op_SrcMemNT }, - { "lmsw", Op_SrcMemNT }, + { "lldt", Op_SrcRMWNT }, + { "lmsw", Op_SrcRMWNT }, { "lock", Op_0 }, { "lods", Op_lods }, { "lodsb", Op_lodsX }, @@ -972,10 +979,10 @@ { "pushf", Op_SizedStack }, { "pushfd", Op_SizedStack }, { "pxor", Op_DstSrcMMX }, - { "rcl", Op_UpdSrcF }, // limited src operands -- change to shift + { "rcl", Op_Shift }, // limited src operands -- change to shift { "rcpps", Op_DstSrcSSE }, { "rcpss", Op_DstSrcSSE }, - { "rcr", Op_UpdSrcF }, + { "rcr", Op_Shift }, { "rdmsr", Op_0_DXAX }, { "rdpmc", Op_0_DXAX }, { "rdtsc", Op_0_DXAX }, @@ -986,8 +993,8 @@ { "repz", Op_0 }, { "ret", Op_ret }, { "retf", Op_retf }, - { "rol", Op_UpdSrcF }, - { "ror", Op_UpdSrcF }, + { "rol", Op_Shift }, + { "ror", Op_Shift }, { "rsm", Op_0 }, { "rsqrtps", Op_DstSrcSSE }, { "rsqrtss", Op_DstSrcSSE }, @@ -999,36 +1006,36 @@ { "scasb", Op_scasX }, { "scasd", Op_scasX }, { "scasw", Op_scasX }, - { "seta", Op_DstMemNT }, // also gpr8 - { "setae", Op_DstMemNT }, - { "setb", Op_DstMemNT }, - { "setbe", Op_DstMemNT }, - { "setc", Op_DstMemNT }, - { "sete", Op_DstMemNT }, - { "setg", Op_DstMemNT }, - { "setge", Op_DstMemNT }, - { "setl", Op_DstMemNT }, - { "setle", Op_DstMemNT }, - { "setna", Op_DstMemNT }, - { "setnae", Op_DstMemNT }, - { "setnb", Op_DstMemNT }, - { "setnbe", Op_DstMemNT }, - { "setnc", Op_DstMemNT }, - { "setne", Op_DstMemNT }, - { "setng", Op_DstMemNT }, - { "setnge", Op_DstMemNT }, - { "setnl", Op_DstMemNT }, - { "setnle", Op_DstMemNT }, - { "setno", Op_DstMemNT }, - { "setnp", Op_DstMemNT }, - { "setns", Op_DstMemNT }, - { "setnz", Op_DstMemNT }, - { "seto", Op_DstMemNT }, - { "setp", Op_DstMemNT }, - { "setpe", Op_DstMemNT }, - { "setpo", Op_DstMemNT }, - { "sets", Op_DstMemNT }, - { "setz", Op_DstMemNT }, + { "seta", Op_DstRMBNT }, // also gpr8 + { "setae", Op_DstRMBNT }, + { "setb", Op_DstRMBNT }, + { "setbe", Op_DstRMBNT }, + { "setc", Op_DstRMBNT }, + { "sete", Op_DstRMBNT }, + { "setg", Op_DstRMBNT }, + { "setge", Op_DstRMBNT }, + { "setl", Op_DstRMBNT }, + { "setle", Op_DstRMBNT }, + { "setna", Op_DstRMBNT }, + { "setnae", Op_DstRMBNT }, + { "setnb", Op_DstRMBNT }, + { "setnbe", Op_DstRMBNT }, + { "setnc", Op_DstRMBNT }, + { "setne", Op_DstRMBNT }, + { "setng", Op_DstRMBNT }, + { "setnge", Op_DstRMBNT }, + { "setnl", Op_DstRMBNT }, + { "setnle", Op_DstRMBNT }, + { "setno", Op_DstRMBNT }, + { "setnp", Op_DstRMBNT }, + { "setns", Op_DstRMBNT }, + { "setnz", Op_DstRMBNT }, + { "seto", Op_DstRMBNT }, + { "setp", Op_DstRMBNT }, + { "setpe", Op_DstRMBNT }, + { "setpo", Op_DstRMBNT }, + { "sets", Op_DstRMBNT }, + { "setz", Op_DstRMBNT }, { "sfence", Op_0 }, { "sgdt", Op_DstMemNT }, { "shl", Op_Shift }, @@ -1038,8 +1045,8 @@ { "shufpd", Op_DstSrcImmS }, { "shufps", Op_DstSrcImmS }, { "sidt", Op_DstMemNT }, - { "sldt", Op_DstMemNT }, - { "smsw", Op_DstMemNT }, + { "sldt", Op_DstRMWNT }, + { "smsw", Op_DstRMWNT }, { "sqrtpd", Op_DstSrcSSE }, { "sqrtps", Op_DstSrcSSE }, { "sqrtsd", Op_DstSrcSSE }, @@ -1495,6 +1502,8 @@ bool getTypeChar(TypeNeeded needed, PtrType ptrtype, char & type_char) { switch (needed) { + case Byte_NoType: + return ptrtype == Byte_Ptr; case Word_Types: if (ptrtype == Byte_Ptr) return false; @@ -1644,8 +1653,11 @@ { char tc_1; int mlen = strlen(mnemonic); + PtrType op1_size = operands[1].dataSize; + if (op1_size == Default_Ptr) + op1_size = operands[1].dataSizeHint; // Need type char for source arg - switch (operands[1].dataSize) { + switch (op1_size) { case Byte_Ptr: case Default_Ptr: tc_1 = 'b'; @@ -2488,7 +2500,7 @@ // parse primary: DMD allows 'MyAlign' (const int) but not '2+2' // GAS is padding with NOPs last time I checked. Expression * e = parseAsmExp()->constFold(); - uinteger_t align = e->toUInteger(); + integer_t align = e->toInteger(); if (align >= 0) { // %% is this printf portable? diff -uNr gdc-0.21/d/d-bi-attrs-41.h gdc-0.22/d/d-bi-attrs-41.h --- gdc-0.21/d/d-bi-attrs-41.h 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/d-bi-attrs-41.h 2007-01-31 01:52:39.000000000 +0100 @@ -0,0 +1,1799 @@ +static tree handle_packed_attribute (tree *, tree, tree, int, bool *); +static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *); +static tree handle_common_attribute (tree *, tree, tree, int, bool *); +static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *); +static tree handle_noinline_attribute (tree *, tree, tree, int, bool *); +static tree handle_always_inline_attribute (tree *, tree, tree, int, + bool *); +static tree handle_flatten_attribute (tree *, tree, tree, int, bool *); +static tree handle_used_attribute (tree *, tree, tree, int, bool *); +static tree handle_unused_attribute (tree *, tree, tree, int, bool *); +static tree handle_externally_visible_attribute (tree *, tree, tree, int, + bool *); +static tree handle_const_attribute (tree *, tree, tree, int, bool *); +static tree handle_transparent_union_attribute (tree *, tree, tree, + int, bool *); +static tree handle_constructor_attribute (tree *, tree, tree, int, bool *); +static tree handle_destructor_attribute (tree *, tree, tree, int, bool *); +static tree handle_mode_attribute (tree *, tree, tree, int, bool *); +static tree handle_section_attribute (tree *, tree, tree, int, bool *); +static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); +static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; +static tree handle_alias_attribute (tree *, tree, tree, int, bool *); +static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ; +static tree handle_visibility_attribute (tree *, tree, tree, int, + bool *); +static tree handle_tls_model_attribute (tree *, tree, tree, int, + bool *); +static tree handle_no_instrument_function_attribute (tree *, tree, + tree, int, bool *); +static tree handle_malloc_attribute (tree *, tree, tree, int, bool *); +static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *); +static tree handle_no_limit_stack_attribute (tree *, tree, tree, int, + bool *); +static tree handle_pure_attribute (tree *, tree, tree, int, bool *); +static tree handle_novops_attribute (tree *, tree, tree, int, bool *); +static tree handle_deprecated_attribute (tree *, tree, tree, int, + bool *); +static tree handle_vector_size_attribute (tree *, tree, tree, int, + bool *); +static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *); +static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *); +//static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *); +static tree handle_warn_unused_result_attribute (tree *, tree, tree, int, + bool *); +static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *); + +//static void check_function_nonnull (tree, tree); +static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); +static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); +static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *); +//static int resort_field_decl_cmp (const void *, const void *); + +/* extra for gdc copy: */ +static void check_function_arguments_recurse (void (*) + (void *, tree, + unsigned HOST_WIDE_INT), + void *, tree, + unsigned HOST_WIDE_INT); + +static tree +handle_format_arg_attribute (tree *node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED, + tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} +static tree +handle_format_attribute (tree *node ATTRIBUTE_UNUSED, tree name ATTRIBUTE_UNUSED, tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + return NULL_TREE; +} +/* -- end extra */ + +/* more copied... */ + +/* Warn about using __null (as NULL in C++) as sentinel. For code compiled + with GCC this doesn't matter as __null is guaranteed to have the right + size. */ + +int warn_strict_null_sentinel; + +/* Warn about format/argument anomalies in calls to formatted I/O functions + (*printf, *scanf, strftime, strfmon, etc.). */ + +int warn_format; + +/* end more copied-- */ + +/* Table of machine-independent attributes common to all C-like languages. */ +const struct attribute_spec d_common_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "packed", 0, 0, false, false, false, + handle_packed_attribute }, + { "nocommon", 0, 0, true, false, false, + handle_nocommon_attribute }, + { "common", 0, 0, true, false, false, + handle_common_attribute }, + /* FIXME: logically, noreturn attributes should be listed as + "false, true, true" and apply to function types. But implementing this + would require all the places in the compiler that use TREE_THIS_VOLATILE + on a decl to identify non-returning functions to be located and fixed + to check the function type instead. */ + { "noreturn", 0, 0, true, false, false, + handle_noreturn_attribute }, + { "volatile", 0, 0, true, false, false, + handle_noreturn_attribute }, + { "noinline", 0, 0, true, false, false, + handle_noinline_attribute }, + { "always_inline", 0, 0, true, false, false, + handle_always_inline_attribute }, + { "flatten", 0, 0, true, false, false, + handle_flatten_attribute }, + { "used", 0, 0, true, false, false, + handle_used_attribute }, + { "unused", 0, 0, false, false, false, + handle_unused_attribute }, + { "externally_visible", 0, 0, true, false, false, + handle_externally_visible_attribute }, + /* The same comments as for noreturn attributes apply to const ones. */ + { "const", 0, 0, true, false, false, + handle_const_attribute }, + { "transparent_union", 0, 0, false, false, false, + handle_transparent_union_attribute }, + { "constructor", 0, 0, true, false, false, + handle_constructor_attribute }, + { "destructor", 0, 0, true, false, false, + handle_destructor_attribute }, + { "mode", 1, 1, false, true, false, + handle_mode_attribute }, + { "section", 1, 1, true, false, false, + handle_section_attribute }, + { "aligned", 0, 1, false, false, false, + handle_aligned_attribute }, + { "weak", 0, 0, true, false, false, + handle_weak_attribute }, + { "alias", 1, 1, true, false, false, + handle_alias_attribute }, + { "weakref", 0, 1, true, false, false, + handle_weakref_attribute }, + { "no_instrument_function", 0, 0, true, false, false, + handle_no_instrument_function_attribute }, + { "malloc", 0, 0, true, false, false, + handle_malloc_attribute }, + { "returns_twice", 0, 0, true, false, false, + handle_returns_twice_attribute }, + { "no_stack_limit", 0, 0, true, false, false, + handle_no_limit_stack_attribute }, + { "pure", 0, 0, true, false, false, + handle_pure_attribute }, + /* For internal use (marking of builtins) only. The name contains space + to prevent its usage in source code. */ + { "no vops", 0, 0, true, false, false, + handle_novops_attribute }, + { "deprecated", 0, 0, false, false, false, + handle_deprecated_attribute }, + { "vector_size", 1, 1, false, true, false, + handle_vector_size_attribute }, + { "visibility", 1, 1, false, false, false, + handle_visibility_attribute }, + { "tls_model", 1, 1, true, false, false, + handle_tls_model_attribute }, + { "nonnull", 0, -1, false, true, true, + handle_nonnull_attribute }, + { "nothrow", 0, 0, true, false, false, + handle_nothrow_attribute }, + { "may_alias", 0, 0, false, true, false, NULL }, + /* not in gdc + { "cleanup", 1, 1, true, false, false, + handle_cleanup_attribute }, + */ + { "warn_unused_result", 0, 0, false, true, true, + handle_warn_unused_result_attribute }, + { "sentinel", 0, 1, false, true, true, + handle_sentinel_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + +/* Give the specifications for the format attributes, used by C and all + descendants. */ + +const struct attribute_spec d_common_format_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "format", 3, 3, false, true, true, + handle_format_attribute }, + { "format_arg", 1, 1, false, true, true, + handle_format_arg_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + +/* Attribute handlers common to C front ends. */ + +/* Handle a "packed" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int flags, bool *no_add_attrs) +{ + if (TYPE_P (*node)) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_variant_type_copy (*node); + TYPE_PACKED (*node) = 1; + if (TYPE_MAIN_VARIANT (*node) == *node) + { + /* If it is the main variant, then pack the other variants + too. This happens in, + + struct Foo { + struct Foo const *ptr; // creates a variant w/o packed flag + } __ attribute__((packed)); // packs it now. + */ + tree probe; + + for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe)) + TYPE_PACKED (probe) = 1; + } + } + else if (TREE_CODE (*node) == FIELD_DECL) + { + if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT) + warning (OPT_Wattributes, + "%qE attribute ignored for field of type %qT", + name, TREE_TYPE (*node)); + else + DECL_PACKED (*node) = 1; + } + /* We can't set DECL_PACKED for a VAR_DECL, because the bit is + used for DECL_REGISTER. It wouldn't mean anything anyway. + We can't set DECL_PACKED on the type of a TYPE_DECL, because + that changes what the typedef is typing. */ + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "nocommon" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_nocommon_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == VAR_DECL) + DECL_COMMON (*node) = 0; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "common" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == VAR_DECL) + DECL_COMMON (*node) = 1; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "noreturn" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree type = TREE_TYPE (*node); + + /* See FIXME comment in c_common_attribute_table. */ + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_THIS_VOLATILE (*node) = 1; + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) + = build_pointer_type + (build_type_variant (TREE_TYPE (type), + TYPE_READONLY (TREE_TYPE (type)), 1)); + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "noinline" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noinline_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + DECL_UNINLINABLE (*node) = 1; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "always_inline" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_always_inline_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + { + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "flatten" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_flatten_attribute (tree *node, tree name, + tree args ATTRIBUTE_UNUSED, + int flags ATTRIBUTE_UNUSED, bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + ; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + + +/* Handle a "used" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree node = *pnode; + + if (TREE_CODE (node) == FUNCTION_DECL + || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node))) + { + TREE_USED (node) = 1; + DECL_PRESERVE_P (node) = 1; + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "unused" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int flags, bool *no_add_attrs) +{ + if (DECL_P (*node)) + { + tree decl = *node; + + if (TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == LABEL_DECL + || TREE_CODE (decl) == TYPE_DECL) + TREE_USED (decl) = 1; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + } + else + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_variant_type_copy (*node); + TREE_USED (*node) = 1; + } + + return NULL_TREE; +} + +/* Handle a "externally_visible" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_externally_visible_attribute (tree *pnode, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree node = *pnode; + + if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL) + || !TREE_PUBLIC (node)) + { + warning (OPT_Wattributes, + "%qE attribute have effect only on public objects", name); + *no_add_attrs = true; + } + else if (TREE_CODE (node) == FUNCTION_DECL) + { + struct cgraph_node *n = cgraph_node (node); + n->local.externally_visible = true; + if (n->local.finalized) + cgraph_mark_needed_node (n); + } + else if (TREE_CODE (node) == VAR_DECL) + { + struct cgraph_varpool_node *n = cgraph_varpool_node (node); + n->externally_visible = true; + if (n->finalized) + cgraph_varpool_mark_needed_node (n); + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "const" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree type = TREE_TYPE (*node); + + /* See FIXME comment on noreturn in c_common_attribute_table. */ + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_READONLY (*node) = 1; + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE) + TREE_TYPE (*node) + = build_pointer_type + (build_type_variant (TREE_TYPE (type), 1, + TREE_THIS_VOLATILE (TREE_TYPE (type)))); + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "transparent_union" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_transparent_union_attribute (tree *node, tree name, + tree ARG_UNUSED (args), int flags, + bool *no_add_attrs) +{ + tree type = NULL; + + *no_add_attrs = true; + + if (DECL_P (*node)) + { + if (TREE_CODE (*node) != TYPE_DECL) + goto ignored; + node = &TREE_TYPE (*node); + type = *node; + } + else if (TYPE_P (*node)) + type = *node; + else + goto ignored; + + if (TREE_CODE (type) == UNION_TYPE) + { + /* When IN_PLACE is set, leave the check for FIELDS and MODE to + the code in finish_struct. */ + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + { + if (TYPE_FIELDS (type) == NULL_TREE + || TYPE_MODE (type) != DECL_MODE (TYPE_FIELDS (type))) + goto ignored; + + /* A type variant isn't good enough, since we don't a cast + to such a type removed as a no-op. */ + *node = type = build_duplicate_type (type); + } + + TYPE_TRANSPARENT_UNION (type) = 1; + return NULL_TREE; + } + + ignored: + warning (OPT_Wattributes, "%qE attribute ignored", name); + return NULL_TREE; +} + +/* Handle a "constructor" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_constructor_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + tree type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == FUNCTION_DECL + && TREE_CODE (type) == FUNCTION_TYPE + && decl_function_context (decl) == 0) + { + DECL_STATIC_CONSTRUCTOR (decl) = 1; + TREE_USED (decl) = 1; + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "destructor" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_destructor_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + tree type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == FUNCTION_DECL + && TREE_CODE (type) == FUNCTION_TYPE + && decl_function_context (decl) == 0) + { + DECL_STATIC_DESTRUCTOR (decl) = 1; + TREE_USED (decl) = 1; + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "mode" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_mode_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree type = *node; + + *no_add_attrs = true; + + if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE) + warning (OPT_Wattributes, "%qE attribute ignored", name); + else + { + int j; + const char *p = IDENTIFIER_POINTER (TREE_VALUE (args)); + int len = strlen (p); + enum machine_mode mode = VOIDmode; + tree typefm; + bool valid_mode; + + if (len > 4 && p[0] == '_' && p[1] == '_' + && p[len - 1] == '_' && p[len - 2] == '_') + { + char *newp = (char *) alloca (len - 1); + + strcpy (newp, &p[2]); + newp[len - 4] = '\0'; + p = newp; + } + + /* Change this type to have a type with the specified mode. + First check for the special modes. */ + if (!strcmp (p, "byte")) + mode = byte_mode; + else if (!strcmp (p, "word")) + mode = word_mode; + else if (!strcmp (p, "pointer")) + mode = ptr_mode; + else + for (j = 0; j < NUM_MACHINE_MODES; j++) + if (!strcmp (p, GET_MODE_NAME (j))) + { + mode = (enum machine_mode) j; + break; + } + + if (mode == VOIDmode) + { + error ("unknown machine mode %qs", p); + return NULL_TREE; + } + + valid_mode = false; + switch (GET_MODE_CLASS (mode)) + { + case MODE_INT: + case MODE_PARTIAL_INT: + case MODE_FLOAT: + valid_mode = targetm.scalar_mode_supported_p (mode); + break; + + case MODE_COMPLEX_INT: + case MODE_COMPLEX_FLOAT: + valid_mode = targetm.scalar_mode_supported_p (GET_MODE_INNER (mode)); + break; + + case MODE_VECTOR_INT: + case MODE_VECTOR_FLOAT: + warning (OPT_Wattributes, "specifying vector types with " + "__attribute__ ((mode)) is deprecated"); + warning (OPT_Wattributes, + "use __attribute__ ((vector_size)) instead"); + valid_mode = vector_mode_valid_p (mode); + break; + + default: + break; + } + if (!valid_mode) + { + error ("unable to emulate %qs", p); + return NULL_TREE; + } + + if (POINTER_TYPE_P (type)) + { + tree (*fn)(tree, enum machine_mode, bool); + + if (!targetm.valid_pointer_mode (mode)) + { + error ("invalid pointer mode %qs", p); + return NULL_TREE; + } + + if (TREE_CODE (type) == POINTER_TYPE) + fn = build_pointer_type_for_mode; + else + fn = build_reference_type_for_mode; + typefm = fn (TREE_TYPE (type), mode, false); + } + else + typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type)); + + if (typefm == NULL_TREE) + { + error ("no data type for mode %qs", p); + return NULL_TREE; + } + else if (TREE_CODE (type) == ENUMERAL_TYPE) + { + /* For enumeral types, copy the precision from the integer + type returned above. If not an INTEGER_TYPE, we can't use + this mode for this type. */ + if (TREE_CODE (typefm) != INTEGER_TYPE) + { + error ("cannot use mode %qs for enumeral types", p); + return NULL_TREE; + } + + if (flags & ATTR_FLAG_TYPE_IN_PLACE) + { + TYPE_PRECISION (type) = TYPE_PRECISION (typefm); + typefm = type; + } + else + { + /* We cannot build a type variant, as there's code that assumes + that TYPE_MAIN_VARIANT has the same mode. This includes the + debug generators. Instead, create a subrange type. This + results in all of the enumeral values being emitted only once + in the original, and the subtype gets them by reference. */ + if (TYPE_UNSIGNED (type)) + typefm = make_unsigned_type (TYPE_PRECISION (typefm)); + else + typefm = make_signed_type (TYPE_PRECISION (typefm)); + TREE_TYPE (typefm) = type; + } + } + else if (VECTOR_MODE_P (mode) + ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm)) + : TREE_CODE (type) != TREE_CODE (typefm)) + { + error ("mode %qs applied to inappropriate type", p); + return NULL_TREE; + } + + *node = typefm; + } + + return NULL_TREE; +} + +/* Handle a "section" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree decl = *node; + + if (targetm.have_named_sections) + { + user_defined_section_attribute = true; + + if ((TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == VAR_DECL) + && TREE_CODE (TREE_VALUE (args)) == STRING_CST) + { + if (TREE_CODE (decl) == VAR_DECL + && current_function_decl != NULL_TREE + && !TREE_STATIC (decl)) + { + error ("%Jsection attribute cannot be specified for " + "local variables", decl); + *no_add_attrs = true; + } + + /* The decl may have already been given a section attribute + from a previous declaration. Ensure they match. */ + else if (DECL_SECTION_NAME (decl) != NULL_TREE + && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), + TREE_STRING_POINTER (TREE_VALUE (args))) != 0) + { + error ("section of %q+D conflicts with previous declaration", + *node); + *no_add_attrs = true; + } + else + DECL_SECTION_NAME (decl) = TREE_VALUE (args); + } + else + { + error ("section attribute not allowed for %q+D", *node); + *no_add_attrs = true; + } + } + else + { + error ("%Jsection attributes are not supported for this target", *node); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "aligned" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int flags, bool *no_add_attrs) +{ + tree decl = NULL_TREE; + tree *type = NULL; + int is_type = 0; + tree align_expr = (args ? TREE_VALUE (args) + : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); + int i; + + if (DECL_P (*node)) + { + decl = *node; + type = &TREE_TYPE (decl); + is_type = TREE_CODE (*node) == TYPE_DECL; + } + else if (TYPE_P (*node)) + type = node, is_type = 1; + + if (TREE_CODE (align_expr) != INTEGER_CST) + { + error ("requested alignment is not a constant"); + *no_add_attrs = true; + } + else if ((i = tree_log2 (align_expr)) == -1) + { + error ("requested alignment is not a power of 2"); + *no_add_attrs = true; + } + else if (i > HOST_BITS_PER_INT - 2) + { + error ("requested alignment is too large"); + *no_add_attrs = true; + } + else if (is_type) + { + /* If we have a TYPE_DECL, then copy the type, so that we + don't accidentally modify a builtin type. See pushdecl. */ + if (decl && TREE_TYPE (decl) != error_mark_node + && DECL_ORIGINAL_TYPE (decl) == NULL_TREE) + { + tree tt = TREE_TYPE (decl); + *type = build_variant_type_copy (*type); + DECL_ORIGINAL_TYPE (decl) = tt; + TYPE_NAME (*type) = decl; + TREE_USED (*type) = TREE_USED (decl); + TREE_TYPE (decl) = *type; + } + else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *type = build_variant_type_copy (*type); + + TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT; + TYPE_USER_ALIGN (*type) = 1; + } + else if (TREE_CODE (decl) != VAR_DECL + && TREE_CODE (decl) != FIELD_DECL) + { + error ("alignment may not be specified for %q+D", decl); + *no_add_attrs = true; + } + else + { + DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT; + DECL_USER_ALIGN (decl) = 1; + } + + return NULL_TREE; +} + +/* Handle a "weak" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_weak_attribute (tree *node, tree ARG_UNUSED (name), + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool * ARG_UNUSED (no_add_attrs)) +{ + declare_weak (*node); + + return NULL_TREE; +} + +/* Handle an "alias" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_alias_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree decl = *node; + + if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl)) + || (TREE_CODE (decl) != FUNCTION_DECL && !DECL_EXTERNAL (decl))) + { + error ("%q+D defined both normally and as an alias", decl); + *no_add_attrs = true; + } + + /* Note that the very first time we process a nested declaration, + decl_function_context will not be set. Indeed, *would* never + be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that + we do below. After such frobbery, pushdecl would set the context. + In any case, this is never what we want. */ + else if (decl_function_context (decl) == 0 && current_function_decl == NULL) + { + tree id; + + id = TREE_VALUE (args); + if (TREE_CODE (id) != STRING_CST) + { + error ("alias argument not a string"); + *no_add_attrs = true; + return NULL_TREE; + } + id = get_identifier (TREE_STRING_POINTER (id)); + /* This counts as a use of the object pointed to. */ + TREE_USED (id) = 1; + + if (TREE_CODE (decl) == FUNCTION_DECL) + DECL_INITIAL (decl) = error_mark_node; + else + { + if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))) + DECL_EXTERNAL (decl) = 1; + else + DECL_EXTERNAL (decl) = 0; + TREE_STATIC (decl) = 1; + } + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "weakref" attribute; arguments as in struct + attribute_spec.handler. */ + +static tree +handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int flags, bool *no_add_attrs) +{ + tree attr = NULL_TREE; + + /* The idea here is that `weakref("name")' mutates into `weakref, + alias("name")', and weakref without arguments, in turn, + implicitly adds weak. */ + + if (args) + { + attr = tree_cons (get_identifier ("alias"), args, attr); + attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr); + + *no_add_attrs = true; + } + else + { + if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node))) + error ("%Jweakref attribute must appear before alias attribute", + *node); + + attr = tree_cons (get_identifier ("weak"), NULL_TREE, attr); + } + + decl_attributes (node, attr, flags); + + return NULL_TREE; +} + +/* Handle an "visibility" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_visibility_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + tree id = TREE_VALUE (args); + + *no_add_attrs = true; + + if (TYPE_P (*node)) + { + if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE) + { + warning (OPT_Wattributes, "%qE attribute ignored on non-class types", + name); + return NULL_TREE; + } + } + else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl)) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + return NULL_TREE; + } + + if (TREE_CODE (id) != STRING_CST) + { + error ("visibility argument not a string"); + return NULL_TREE; + } + + /* If this is a type, set the visibility on the type decl. */ + if (TYPE_P (decl)) + { + decl = TYPE_NAME (decl); + if (!decl) + return NULL_TREE; + if (TREE_CODE (decl) == IDENTIFIER_NODE) + { + warning (OPT_Wattributes, "%qE attribute ignored on types", + name); + return NULL_TREE; + } + } + + if (strcmp (TREE_STRING_POINTER (id), "default") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; + else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL; + else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN; + else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0) + DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED; + else + error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\""); + DECL_VISIBILITY_SPECIFIED (decl) = 1; + + /* For decls only, go ahead and attach the attribute to the node as well. + This is needed so we can determine whether we have VISIBILITY_DEFAULT + because the visibility was not specified, or because it was explicitly + overridden from the class visibility. */ + if (DECL_P (*node)) + *no_add_attrs = false; + + return NULL_TREE; +} + +/* Determine the ELF symbol visibility for DECL, which is either a + variable or a function. It is an error to use this function if a + definition of DECL is not available in this translation unit. + Returns true if the final visibility has been determined by this + function; false if the caller is free to make additional + modifications. */ + +bool +c_determine_visibility (tree decl) +{ + gcc_assert (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL); + + /* If the user explicitly specified the visibility with an + attribute, honor that. DECL_VISIBILITY will have been set during + the processing of the attribute. We check for an explicit + attribute, rather than just checking DECL_VISIBILITY_SPECIFIED, + to distinguish the use of an attribute from the use of a "#pragma + GCC visibility push(...)"; in the latter case we still want other + considerations to be able to overrule the #pragma. */ + if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))) + return true; + + /* Anything that is exported must have default visibility. */ + if (TARGET_DLLIMPORT_DECL_ATTRIBUTES + && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) + { + DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; + DECL_VISIBILITY_SPECIFIED (decl) = 1; + return true; + } + + return false; +} + +/* Handle an "tls_model" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_tls_model_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree id; + tree decl = *node; + enum tls_model kind; + + *no_add_attrs = true; + + if (!DECL_THREAD_LOCAL_P (decl)) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + return NULL_TREE; + } + + kind = DECL_TLS_MODEL (decl); + id = TREE_VALUE (args); + if (TREE_CODE (id) != STRING_CST) + { + error ("tls_model argument not a string"); + return NULL_TREE; + } + + if (!strcmp (TREE_STRING_POINTER (id), "local-exec")) + kind = TLS_MODEL_LOCAL_EXEC; + else if (!strcmp (TREE_STRING_POINTER (id), "initial-exec")) + kind = TLS_MODEL_INITIAL_EXEC; + else if (!strcmp (TREE_STRING_POINTER (id), "local-dynamic")) + kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC; + else if (!strcmp (TREE_STRING_POINTER (id), "global-dynamic")) + kind = TLS_MODEL_GLOBAL_DYNAMIC; + else + error ("tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\""); + + DECL_TLS_MODEL (decl) = kind; + return NULL_TREE; +} + +/* Handle a "no_instrument_function" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_instrument_function_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error ("%J%qE attribute applies only to functions", decl, name); + *no_add_attrs = true; + } + else if (DECL_INITIAL (decl)) + { + error ("%Jcan%'t set %qE attribute after definition", decl, name); + *no_add_attrs = true; + } + else + DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1; + + return NULL_TREE; +} + +/* Handle a "malloc" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL + && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node)))) + DECL_IS_MALLOC (*node) = 1; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "returns_twice" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + DECL_IS_RETURNS_TWICE (*node) = 1; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "no_limit_stack" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_no_limit_stack_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree decl = *node; + + if (TREE_CODE (decl) != FUNCTION_DECL) + { + error ("%J%qE attribute applies only to functions", decl, name); + *no_add_attrs = true; + } + else if (DECL_INITIAL (decl)) + { + error ("%Jcan%'t set %qE attribute after definition", decl, name); + *no_add_attrs = true; + } + else + DECL_NO_LIMIT_STACK (decl) = 1; + + return NULL_TREE; +} + +/* Handle a "pure" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + DECL_IS_PURE (*node) = 1; + /* ??? TODO: Support types. */ + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "no vops" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_novops_attribute (tree *node, tree ARG_UNUSED (name), + tree ARG_UNUSED (args), int ARG_UNUSED (flags), + bool *ARG_UNUSED (no_add_attrs)) +{ + gcc_assert (TREE_CODE (*node) == FUNCTION_DECL); + DECL_IS_NOVOPS (*node) = 1; + return NULL_TREE; +} + +/* Handle a "deprecated" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_deprecated_attribute (tree *node, tree name, + tree ARG_UNUSED (args), int flags, + bool *no_add_attrs) +{ + tree type = NULL_TREE; + int warn = 0; + tree what = NULL_TREE; + + if (DECL_P (*node)) + { + tree decl = *node; + type = TREE_TYPE (decl); + + if (TREE_CODE (decl) == TYPE_DECL + || TREE_CODE (decl) == PARM_DECL + || TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == FUNCTION_DECL + || TREE_CODE (decl) == FIELD_DECL) + TREE_DEPRECATED (decl) = 1; + else + warn = 1; + } + else if (TYPE_P (*node)) + { + if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + *node = build_variant_type_copy (*node); + TREE_DEPRECATED (*node) = 1; + type = *node; + } + else + warn = 1; + + if (warn) + { + *no_add_attrs = true; + if (type && TYPE_NAME (type)) + { + if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) + what = TYPE_NAME (*node); + else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL + && DECL_NAME (TYPE_NAME (type))) + what = DECL_NAME (TYPE_NAME (type)); + } + if (what) + warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what); + else + warning (OPT_Wattributes, "%qE attribute ignored", name); + } + + return NULL_TREE; +} + +/* Handle a "vector_size" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_vector_size_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + unsigned HOST_WIDE_INT vecsize, nunits; + enum machine_mode orig_mode; + tree type = *node, new_type, size; + + *no_add_attrs = true; + + size = TREE_VALUE (args); + + if (!host_integerp (size, 1)) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + return NULL_TREE; + } + + /* Get the vector size (in bytes). */ + vecsize = tree_low_cst (size, 1); + + /* We need to provide for vector pointers, vector arrays, and + functions returning vectors. For example: + + __attribute__((vector_size(16))) short *foo; + + In this case, the mode is SI, but the type being modified is + HI, so we need to look further. */ + + while (POINTER_TYPE_P (type) + || TREE_CODE (type) == FUNCTION_TYPE + || TREE_CODE (type) == METHOD_TYPE + || TREE_CODE (type) == ARRAY_TYPE) + type = TREE_TYPE (type); + + /* Get the mode of the type being modified. */ + orig_mode = TYPE_MODE (type); + + if (TREE_CODE (type) == RECORD_TYPE + || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT + && GET_MODE_CLASS (orig_mode) != MODE_INT) + || !host_integerp (TYPE_SIZE_UNIT (type), 1)) + { + error ("invalid vector type for attribute %qE", name); + return NULL_TREE; + } + + if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1)) + { + error ("vector size not an integral multiple of component size"); + return NULL; + } + + if (vecsize == 0) + { + error ("zero vector size"); + return NULL; + } + + /* Calculate how many units fit in the vector. */ + nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1); + if (nunits & (nunits - 1)) + { + error ("number of components of the vector not a power of two"); + return NULL_TREE; + } + + new_type = build_vector_type (type, nunits); + + /* Build back pointers if needed. */ + *node = reconstruct_complex_type (*node, new_type); + + return NULL_TREE; +} + +/* Handle the "nonnull" attribute. */ +static tree +handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), + tree args, int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + tree type = *node; + unsigned HOST_WIDE_INT attr_arg_num; + + /* If no arguments are specified, all pointer arguments should be + non-null. Verify a full prototype is given so that the arguments + will have the correct types when we actually check them later. */ + if (!args) + { + if (!TYPE_ARG_TYPES (type)) + { + error ("nonnull attribute without arguments on a non-prototype"); + *no_add_attrs = true; + } + return NULL_TREE; + } + + /* Argument list specified. Verify that each argument number references + a pointer argument. */ + for (attr_arg_num = 1; args; args = TREE_CHAIN (args)) + { + tree argument; + unsigned HOST_WIDE_INT arg_num = 0, ck_num; + + if (!get_nonnull_operand (TREE_VALUE (args), &arg_num)) + { + error ("nonnull argument has invalid operand number (argument %lu)", + (unsigned long) attr_arg_num); + *no_add_attrs = true; + return NULL_TREE; + } + + argument = TYPE_ARG_TYPES (type); + if (argument) + { + for (ck_num = 1; ; ck_num++) + { + if (!argument || ck_num == arg_num) + break; + argument = TREE_CHAIN (argument); + } + + if (!argument + || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE) + { + error ("nonnull argument with out-of-range operand number (argument %lu, operand %lu)", + (unsigned long) attr_arg_num, (unsigned long) arg_num); + *no_add_attrs = true; + return NULL_TREE; + } + + if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE) + { + error ("nonnull argument references non-pointer operand (argument %lu, operand %lu)", + (unsigned long) attr_arg_num, (unsigned long) arg_num); + *no_add_attrs = true; + return NULL_TREE; + } + } + } + + return NULL_TREE; +} + +/* Check the argument list of a function call for null in argument slots + that are marked as requiring a non-null pointer argument. */ + +static void +check_function_nonnull (tree attrs, tree params) +{ + tree a, args, param; + int param_num; + + for (a = attrs; a; a = TREE_CHAIN (a)) + { + if (is_attribute_p ("nonnull", TREE_PURPOSE (a))) + { + args = TREE_VALUE (a); + + /* Walk the argument list. If we encounter an argument number we + should check for non-null, do it. If the attribute has no args, + then every pointer argument is checked (in which case the check + for pointer type is done in check_nonnull_arg). */ + for (param = params, param_num = 1; ; + param_num++, param = TREE_CHAIN (param)) + { + if (!param) + break; + if (!args || nonnull_check_p (args, param_num)) + check_function_arguments_recurse (check_nonnull_arg, NULL, + TREE_VALUE (param), + param_num); + } + } + } +} + +/* Check that the Nth argument of a function call (counting backwards + from the end) is a (pointer)0. */ + +static void +check_function_sentinel (tree attrs, tree params, tree typelist) +{ + tree attr = lookup_attribute ("sentinel", attrs); + + if (attr) + { + /* Skip over the named arguments. */ + while (typelist && params) + { + typelist = TREE_CHAIN (typelist); + params = TREE_CHAIN (params); + } + + if (typelist || !params) + warning (OPT_Wformat, + "not enough variable arguments to fit a sentinel"); + else + { + tree sentinel, end; + unsigned pos = 0; + + if (TREE_VALUE (attr)) + { + tree p = TREE_VALUE (TREE_VALUE (attr)); + pos = TREE_INT_CST_LOW (p); + } + + sentinel = end = params; + + /* Advance `end' ahead of `sentinel' by `pos' positions. */ + while (pos > 0 && TREE_CHAIN (end)) + { + pos--; + end = TREE_CHAIN (end); + } + if (pos > 0) + { + warning (OPT_Wformat, + "not enough variable arguments to fit a sentinel"); + return; + } + + /* Now advance both until we find the last parameter. */ + while (TREE_CHAIN (end)) + { + end = TREE_CHAIN (end); + sentinel = TREE_CHAIN (sentinel); + } + + /* Validate the sentinel. */ + if ((!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel))) + || !integer_zerop (TREE_VALUE (sentinel))) + /* Although __null (in C++) is only an integer we allow it + nevertheless, as we are guaranteed that it's exactly + as wide as a pointer, and we don't want to force + users to cast the NULL they have written there. + We warn with -Wstrict-null-sentinel, though. */ + && (warn_strict_null_sentinel + || null_node != TREE_VALUE (sentinel))) + warning (OPT_Wformat, "missing sentinel in function call"); + } + } +} + +/* Helper for check_function_nonnull; given a list of operands which + must be non-null in ARGS, determine if operand PARAM_NUM should be + checked. */ + +static bool +nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num) +{ + unsigned HOST_WIDE_INT arg_num = 0; + + for (; args; args = TREE_CHAIN (args)) + { + bool found = get_nonnull_operand (TREE_VALUE (args), &arg_num); + + gcc_assert (found); + + if (arg_num == param_num) + return true; + } + return false; +} + +/* Check that the function argument PARAM (which is operand number + PARAM_NUM) is non-null. This is called by check_function_nonnull + via check_function_arguments_recurse. */ + +static void +check_nonnull_arg (void * ARG_UNUSED (ctx), tree param, + unsigned HOST_WIDE_INT param_num) +{ + /* Just skip checking the argument if it's not a pointer. This can + happen if the "nonnull" attribute was given without an operand + list (which means to check every pointer argument). */ + + if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE) + return; + + if (integer_zerop (param)) + warning (OPT_Wnonnull, "null argument where non-null required " + "(argument %lu)", (unsigned long) param_num); +} + +/* Helper for nonnull attribute handling; fetch the operand number + from the attribute argument list. */ + +static bool +get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp) +{ + /* Verify the arg number is a constant. */ + if (TREE_CODE (arg_num_expr) != INTEGER_CST + || TREE_INT_CST_HIGH (arg_num_expr) != 0) + return false; + + *valp = TREE_INT_CST_LOW (arg_num_expr); + return true; +} + +/* Handle a "nothrow" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + TREE_NOTHROW (*node) = 1; + /* ??? TODO: Support types. */ + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "warn_unused_result" attribute. No special handling. */ + +static tree +handle_warn_unused_result_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + /* Ignore the attribute for functions not returning any value. */ + if (VOID_TYPE_P (TREE_TYPE (*node))) + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + +/* Handle a "sentinel" attribute. */ + +static tree +handle_sentinel_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree params = TYPE_ARG_TYPES (*node); + + if (!params) + { + warning (OPT_Wattributes, + "%qE attribute requires prototypes with named arguments", name); + *no_add_attrs = true; + } + else + { + while (TREE_CHAIN (params)) + params = TREE_CHAIN (params); + + if (VOID_TYPE_P (TREE_VALUE (params))) + { + warning (OPT_Wattributes, + "%qE attribute only applies to variadic functions", name); + *no_add_attrs = true; + } + } + + if (args) + { + tree position = TREE_VALUE (args); + + if (TREE_CODE (position) != INTEGER_CST) + { + warning (0, "requested position is not an integer constant"); + *no_add_attrs = true; + } + else + { + if (tree_int_cst_lt (position, integer_zero_node)) + { + warning (0, "requested position is less than zero"); + *no_add_attrs = true; + } + } + } + + return NULL_TREE; +} + +/* Check for valid arguments being passed to a function. */ +void +check_function_arguments (tree attrs, tree params, tree typelist) +{ + /* Check for null being passed in a pointer argument that must be + non-null. We also need to do this if format checking is enabled. */ + + if (warn_nonnull) + check_function_nonnull (attrs, params); + + /* Check for errors in format strings. */ + + /* disabled in gdc + if (warn_format || warn_missing_format_attribute) + check_function_format (attrs, params); + */ + + if (warn_format) + check_function_sentinel (attrs, params, typelist); +} + +/* Generic argument checking recursion routine. PARAM is the argument to + be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked + once the argument is resolved. CTX is context for the callback. */ +void +check_function_arguments_recurse (void (*callback) + (void *, tree, unsigned HOST_WIDE_INT), + void *ctx, tree param, + unsigned HOST_WIDE_INT param_num) +{ + if (TREE_CODE (param) == NOP_EXPR) + { + /* Strip coercion. */ + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 0), param_num); + return; + } + + if (TREE_CODE (param) == CALL_EXPR) + { + tree type = TREE_TYPE (TREE_TYPE (TREE_OPERAND (param, 0))); + tree attrs; + bool found_format_arg = false; + + /* See if this is a call to a known internationalization function + that modifies a format arg. Such a function may have multiple + format_arg attributes (for example, ngettext). */ + + for (attrs = TYPE_ATTRIBUTES (type); + attrs; + attrs = TREE_CHAIN (attrs)) + if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs))) + { + tree inner_args; + tree format_num_expr; + int format_num; + int i; + + /* Extract the argument number, which was previously checked + to be valid. */ + format_num_expr = TREE_VALUE (TREE_VALUE (attrs)); + + gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST + && !TREE_INT_CST_HIGH (format_num_expr)); + + format_num = TREE_INT_CST_LOW (format_num_expr); + + for (inner_args = TREE_OPERAND (param, 1), i = 1; + inner_args != 0; + inner_args = TREE_CHAIN (inner_args), i++) + if (i == format_num) + { + check_function_arguments_recurse (callback, ctx, + TREE_VALUE (inner_args), + param_num); + found_format_arg = true; + break; + } + } + + /* If we found a format_arg attribute and did a recursive check, + we are done with checking this argument. Otherwise, we continue + and this will be considered a non-literal. */ + if (found_format_arg) + return; + } + + if (TREE_CODE (param) == COND_EXPR) + { + /* Check both halves of the conditional expression. */ + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 1), param_num); + check_function_arguments_recurse (callback, ctx, + TREE_OPERAND (param, 2), param_num); + return; + } + + (*callback) (ctx, param, param_num); +} diff -uNr gdc-0.21/d/d-builtins2.cc gdc-0.22/d/d-builtins2.cc --- gdc-0.21/d/d-builtins2.cc 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/d-builtins2.cc 2007-01-31 01:52:39.000000000 +0100 @@ -46,8 +46,11 @@ error("cannot represent built in va_list type in D"); abort(); } - TYPE_MAIN_VARIANT( d_gcc_builtin_va_list_d_type->toCtype() ) = - TYPE_MAIN_VARIANT( va_list_type_node ); + if (POINTER_TYPE_P(va_list_type_node) || + INTEGRAL_TYPE_P(va_list_type_node)) + d_gcc_builtin_va_list_d_type->toCtype(); + else + d_gcc_builtin_va_list_d_type->ctype = va_list_type_node; } /* diff -uNr gdc-0.21/d/d-builtins.c gdc-0.22/d/d-builtins.c --- gdc-0.21/d/d-builtins.c 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/d-builtins.c 2007-01-31 01:52:39.000000000 +0100 @@ -38,6 +38,10 @@ #include "langhooks.h" #include "tree-inline.h" #include "toplev.h" +#if D_GCC_VER >= 40 +/* Only used in >= 4.1.x */ +#include "cgraph.h" +#endif #include "d-lang.h" @@ -47,6 +51,12 @@ tree string_type_node; tree const_string_type_node; +#if D_GCC_VER >= 41 +tree null_node; +extern void dkeep(tree t); +#endif + + #if D_GCC_VER < 34 #include "d-bi-attrs-33.h" #elif D_GCC_VER < 40 @@ -55,10 +65,34 @@ # else # include "d-bi-attrs-34.h" # endif -#else +#elif D_GCC_VER < 41 #include "d-bi-attrs-40.h" +#else +#include "d-bi-attrs-41.h" #endif +#if D_GCC_VER >= 41 +/* Nonzero means enable C89 Amendment 1 features. */ + +/*extern*/ int flag_isoc94; + +/* Nonzero means use the ISO C99 dialect of C. */ + +/*extern*/ int flag_isoc99; +#endif + +/* Used to help initialize the builtin-types.def table. When a type of + the correct size doesn't exist, use error_mark_node instead of NULL. + The later results in segfaults even when a decl using the type doesn't + get invoked. */ + +tree +builtin_type_for_size (int size, bool unsignedp) +{ + tree type = lang_hooks.types.type_for_size (size, unsignedp); + return type ? type : error_mark_node; +} + enum built_in_attribute { #define DEF_ATTR_NULL_TREE(ENUM) ENUM, @@ -133,6 +167,38 @@ } #endif +#if D_GCC_VER >= 41 +tree do_build_builtin_fn(enum built_in_function fncode, + const char *name, + enum built_in_class fnclass, + int fntype_index, tree fntype, int libtype_index, + bool both_p, bool fallback_p, bool nonansi_p, + tree fnattrs, bool implicit_p) +{ + tree decl; + + const char *libname; + + gcc_assert ((!(both_p) && !(fallback_p)) + || !strncmp (name, "__builtin_", + strlen ("__builtin_"))); + libname = name + strlen ("__builtin_"); + + + /*if (!BOTH_P)*/ + decl = lang_hooks.builtin_function (name, fntype, + fncode, + fnclass, + fallback_p ?libname : NULL, + fnattrs); + + built_in_decls[(int) fncode] = decl; + d_bi_builtin_func((int) fncode, name, (int) fntype_index, decl); + if (implicit_p) + implicit_built_in_decls[(int) fncode] = decl; +} +#endif + void d_init_builtins(void) { enum builtin_type @@ -454,7 +520,7 @@ if (IMPLICIT) \ implicit_built_in_decls[(int) ENUM] = decl; \ } -#elif D_GCC_VER >= 40 +#elif D_GCC_VER == 40 #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \ NONANSI_P, ATTRS, IMPLICIT, COND) \ if (NAME && COND) \ @@ -488,6 +554,12 @@ if (IMPLICIT) \ implicit_built_in_decls[(int) ENUM] = decl; \ } +#elif D_GCC_VER >= 41 +#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \ + NONANSI_P, ATTRS, IMPLICIT, COND) \ + if (NAME && COND) \ + do_build_builtin_fn(ENUM, NAME, CLASS, TYPE, builtin_types[TYPE], LIBTYPE, BOTH_P, \ + FALLBACK_P, NONANSI_P, built_in_attributes[(int) ATTRS], IMPLICIT); #endif #include "builtins.def" @@ -500,6 +572,14 @@ (*targetm.init_builtins) (); main_identifier_node = get_identifier ("main"); + +#if D_GCC_VER >= 41 + /* Create the built-in __null node. It is important that this is + not shared. */ + null_node = make_node (INTEGER_CST); + TREE_TYPE (null_node) = d_type_for_size (POINTER_SIZE, 0); + dkeep(null_node); +#endif } /* Return a definition for a builtin function named NAME and whose data type diff -uNr gdc-0.21/d/d-codegen.cc gdc-0.22/d/d-codegen.cc --- gdc-0.21/d/d-codegen.cc 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/d-codegen.cc 2007-02-06 05:30:00.000000000 +0100 @@ -105,7 +105,7 @@ g.ofile->doLineNote(v->loc); expand_decl_init(var_decl); // %%new: merge with above, irs->expandDecl } else { - warning("uninitialized variable '%s'", v->ident ? v->ident->string : "(no name)"); + d_warning(OPT_Wuninitialized, "uninitialized variable '%s'", v->ident ? v->ident->string : "(no name)"); } #else // pushdecl will allow the VAR_DECL to be placed in a BIND_EXPR when @@ -122,7 +122,7 @@ //g.ofile->doLineNote(v->loc); //expand_decl_init(var_decl); // %%new: merge with above, irs->expandDecl } else { - warning("uninitialized variable '%s'", v->ident ? v->ident->string : "(no name)"); + d_warning(OPT_Wuninitialized, "uninitialized variable '%s'", v->ident ? v->ident->string : "(no name)"); } if (init_exp) @@ -292,7 +292,7 @@ return libCall(obj_class_decl->isInterfaceDeclaration() ? LIBCALL_INTERFACE_CAST : LIBCALL_DYNAMIC_CAST, 2, args); } else { - warning("cast to %s will yield null result", target_type->toChars()); + warning(0, "cast to %s will yield null result", target_type->toChars()); result = convert(target_type->toCtype(), d_null_pointer); if (TREE_SIDE_EFFECTS( exp )) { // make sure the expression is still evaluated if necessary result = compound(exp, result); @@ -317,15 +317,11 @@ // conversions to different sizes // Assumes tvoid->size() == 1 // %% TODO: handle misalign like _d_arraycast_xxx ? - if (a_type->next->isbit() != target_type->next->isbit()) { - if (a_type->next->isbit()) { - array_len /= 8 * sz_b; - } else { - array_len *= 8 * sz_a; - } - } else if (sz_a != sz_b) { + gcc_assert(a_type->next->isbit() == target_type->next->isbit()); + + if (sz_a != sz_b) array_len = array_len * sz_a / sz_b; - } + tree pointer_value = nop( addressOf( exp ), target_type->next->pointerTo()->toCtype() ); @@ -348,27 +344,19 @@ Type * dst_elem_type = target_type->next->toBasetype(); d_uns64 sz_a = src_elem_type->size(); d_uns64 sz_b = dst_elem_type->size(); + + gcc_assert((src_elem_type->ty == Tbit) == + (dst_elem_type->ty == Tbit)); - if ((sz_a != sz_b) || - src_elem_type->isbit() != dst_elem_type->isbit()) { - - //TY exp_elem_ty = exp_type->next->toBasetype()->ty; - if (! src_elem_type->isbit()) { - tree args[3] = { - // assumes Type::tbit->size() == 1 - integerConstant(sz_b, Type::tuns32), - integerConstant(sz_a * (dst_elem_type->isbit() ? 8 : 1), - Type::tuns32), - exp - }; - return libCall(LIBCALL_ARRAYCAST, 3, args, target_type->toCtype()); - } else { - tree args[2] = { - integerConstant(sz_b, Type::tuns32), - exp - }; - return libCall(LIBCALL_ARRAYCAST_FROMBIT, 2, args, target_type->toCtype()); - } + if (sz_a != sz_b) { + tree args[3] = { + // assumes Type::tbit->size() == 1 + integerConstant(sz_b, Type::tuns32), + integerConstant(sz_a * (dst_elem_type->isbit() ? 8 : 1), + Type::tuns32), + exp + }; + return libCall(LIBCALL_ARRAYCAST, 3, args, target_type->toCtype()); } else { // %% VIEW_CONVERT_EXPR or NOP_EXPR ? (and the two cases below) // Convert to/from void[] or elements are the same size -- don't change length @@ -511,9 +499,11 @@ tree ctor = make_node( CONSTRUCTOR ); TREE_TYPE( ctor ) = target_type->toCtype(); if (count) { - CONSTRUCTOR_ELTS( ctor ) = tree_cons( build(RANGE_EXPR, Type::tsize_t->toCtype(), - integer_zero_node, integerConstant( count - 1 )), - g.ofile->stripVarDecl(convertForAssignment(exp, sa_type->next)), NULL_TREE ); + CtorEltMaker ce; + ce.cons( build(RANGE_EXPR, Type::tsize_t->toCtype(), + integer_zero_node, integerConstant( count - 1 )), + g.ofile->stripVarDecl(convertForAssignment(exp, sa_type->next))); + CONSTRUCTOR_ELTS( ctor ) = ce.head; } TREE_READONLY( ctor ) = 1; TREE_CONSTANT( ctor ) = 1; @@ -524,9 +514,10 @@ // internal init code -- this also includes default init for _d_newarrayi... if (exp->toInteger() == 0) { + CtorEltMaker ce; tree empty = make_node( CONSTRUCTOR ); TREE_TYPE( empty ) = target_type->toCtype(); - CONSTRUCTOR_ELTS( empty ) = NULL_TREE; // %% will this zero-init? + CONSTRUCTOR_ELTS( empty ) = ce.head; // %% will this zero-init? TREE_CONSTANT( empty ) = 1; // static? return empty; @@ -687,22 +678,6 @@ } tree -IRState::bitAlignCheck(Loc loc, tree index) -{ - tree cond; - - index = maybeMakeTemp(index); - - cond = build(BIT_AND_EXPR, TREE_TYPE(index), - index, integerConstant(7, TREE_TYPE(index))); - cond = build(EQ_EXPR, boolean_type_node, cond, integer_zero_node); - - return build(COND_EXPR, TREE_TYPE(index), cond, index, - assertCall(loc, LIBCALL_ARRAY_BOUNDS)); -} - - -tree IRState::assertCall(Loc loc, LibCall libcall) { tree args[2] = { darrayString(loc.filename ? loc.filename : ""), @@ -940,24 +915,21 @@ static const char * libcall_ids[LIBCALL_count] = { "_d_assert", "_d_assert_msg", "_d_array_bounds", "_d_switch_error", "_D9invariant12_d_invariantFC6ObjectZv", - "_d_newclass", "_d_new", - /*"_d_newarrayi", */"_d_newarrayip", - "_d_newmp", "_d_newarraymip", - "_d_newbitarray", + "_d_newclass", "_d_newarrayT", + "_d_newarrayiT", + "_d_newarraymTp", "_d_newarraymiTp", "_d_delclass", "_d_delarray", "_d_delmemory", "_d_callfinalizer", - "_d_arraysetlength", /*"_d_arraysetlength3",*/ "_d_arraysetlength3p", - "_d_arraysetlengthb", + "_d_arraysetlengthT", "_d_arraysetlengthiT", "_d_dynamic_cast", "_d_interface_cast", - "_adEq", "_adEqBit", "_adCmp", "_adCmpChar", "_adCmpBit", + "_adEq", "_adCmp", "_adCmpChar", "_aaLen", //"_aaIn", "_aaGet", "_aaGetRvalue", "_aaDel", "_aaInp", "_aaGetp", "_aaGetRvaluep", "_aaDelp", - "_d_arraycast", "_d_arraycast_frombit", - "_d_arraycopy", "_d_arraycopybit", - "_d_arraycat", "_d_arraycatb", "_d_arraycatn", - "_d_arrayappend", "_d_arrayappendb", - /*"_d_arrayappendc", */"_d_arrayappendcp", "_d_arrayappendcb", - "_d_arraysetbit", "_d_arraysetbit2", + "_d_arraycast", + "_d_arraycopy", + "_d_arraycatT", "_d_arraycatnT", + "_d_arrayappendT", + /*"_d_arrayappendc", */"_d_arrayappendcTp", "_d_monitorenter", "_d_monitorexit", "_d_criticalenter", "_d_criticalexit", "_d_throw", @@ -1027,33 +999,19 @@ arg_types.push( ClassDeclaration::classinfo->type ); return_type = getObjectType(); break; - case LIBCALL_NEW: - arg_types.push( Type::tsize_t ); - arg_types.push( Type::tsize_t ); - return_type = Type::tvoid->arrayOf(); - break; - //case LIBCALL_NEWARRAYI: - case LIBCALL_NEWARRAYIP: - arg_types.push( Type::tsize_t ); + case LIBCALL_NEWARRAYT: + case LIBCALL_NEWARRAYIT: + arg_types.push( Type::typeinfo->type ); arg_types.push( Type::tsize_t ); - arg_types.push( Type::tvoid->pointerTo() ); //varargs = true; return_type = Type::tvoid->arrayOf(); break; - case LIBCALL_NEWMP: - case LIBCALL_NEWARRAYMIP: + case LIBCALL_NEWARRAYMTP: + case LIBCALL_NEWARRAYMITP: arg_types.push( Type::tsize_t ); arg_types.push( Type::tint32 ); // currently 'int' - arg_types.push( Type::tsize_t->pointerTo() ); - if (lib_call == LIBCALL_NEWARRAYMIP) - { + arg_types.push( Type::typeinfo->type ); + if (lib_call == LIBCALL_NEWARRAYMITP) arg_types.push( Type::tsize_t ); - arg_types.push( Type::tvoidptr ); - } - break; - case LIBCALL_NEWBITARRAY: - arg_types.push( Type::tsize_t ); - arg_types.push( Type::tbit ); - return_type = Type::tbit->arrayOf(); break; case LIBCALL_DELCLASS: arg_types.push(getObjectType()->pointerTo()); @@ -1067,18 +1025,11 @@ case LIBCALL_CALLFINALIZER: arg_types.push(Type::tvoid->pointerTo()); // declared void*; could be Object.... break; - case LIBCALL_ARRAYSETLENGTH: - case LIBCALL_ARRAYSETLENGTH_3P: - case LIBCALL_ARRAYSETLENGTH_B: + case LIBCALL_ARRAYSETLENGTHT: + case LIBCALL_ARRAYSETLENGTHIT: + arg_types.push( Type::typeinfo->type ); arg_types.push( Type::tsize_t ); - if (lib_call != LIBCALL_ARRAYSETLENGTH_B) - arg_types.push( Type::tsize_t ); arg_types.push( Type::tvoid->arrayOf()->pointerTo() ); - if (lib_call == LIBCALL_ARRAYSETLENGTH_3P) - { - arg_types.push( Type::tsize_t ); - arg_types.push( Type::tvoidptr ); - } return_type = Type::tvoid->arrayOf(); break; case LIBCALL_DYNAMIC_CAST: @@ -1101,13 +1052,6 @@ arg_types.push(Type::tchar->arrayOf()); return_type = Type::tint32; break; - case LIBCALL_ADEQBIT: - case LIBCALL_ADCMPBIT: - arg_types.reserve(2); - arg_types.push(Type::tbit->arrayOf()); - arg_types.push(Type::tbit->arrayOf()); - return_type = Type::tint32; - break; // case LIBCALL_AAIN: // case LIBCALL_AAGET: // case LIBCALL_AAGETRVALUE: @@ -1162,12 +1106,6 @@ arg_types.push(t); return_type = t; break; - case LIBCALL_ARRAYCAST_FROMBIT: - t = Type::tvoid->arrayOf(); - arg_types.push(Type::tuns32); - arg_types.push(t); - return_type = t; - break; case LIBCALL_ARRAYCOPY: t = Type::tvoid->arrayOf(); arg_types.push(Type::tuns32); @@ -1175,67 +1113,34 @@ arg_types.push(t); return_type = t; break; - case LIBCALL_ARRAYCOPYBIT: - case LIBCALL_ARRAYCATB: - t = Type::tbit->arrayOf(); - arg_types.push(t); - arg_types.push(t); - return_type = t; - break; - case LIBCALL_ARRAYCAT: + case LIBCALL_ARRAYCATT: + arg_types.push(Type::typeinfo->type); t = Type::tvoid->arrayOf(); arg_types.push(t); arg_types.push(t); - arg_types.push(Type::tsize_t); return_type = t; break; - case LIBCALL_ARRAYCATN: - arg_types.push(Type::tuns32); - arg_types.push(Type::tuns32); + case LIBCALL_ARRAYCATNT: + arg_types.push(Type::typeinfo->type); + arg_types.push(Type::tuns32); // defined to be uint varargs = true; return_type = Type::tvoid->arrayOf(); break; - case LIBCALL_ARRAYAPPEND: + case LIBCALL_ARRAYAPPENDT: + arg_types.push(Type::typeinfo->type); t = Type::tuns8->arrayOf(); arg_types.push(t->pointerTo()); arg_types.push(t); - arg_types.push(Type::tsize_t); return_type = Type::tvoid->arrayOf(); break; - case LIBCALL_ARRAYAPPENDB: - t = Type::tbit->arrayOf(); - arg_types.push(t->pointerTo()); +// case LIBCALL_ARRAYAPPENDCT: + case LIBCALL_ARRAYAPPENDCTP: + arg_types.push(Type::typeinfo->type); + t = Type::tuns8->arrayOf(); arg_types.push(t); - return_type = t; - break; -// case LIBCALL_ARRAYAPPENDC: - case LIBCALL_ARRAYAPPENDCP: - t = Type::tuns8->arrayOf()->pointerTo(); - arg_types.push(t->pointerTo()); - arg_types.push(Type::tsize_t); arg_types.push(Type::tvoid->pointerTo()); // varargs = true; return_type = Type::tvoid->arrayOf(); break; - case LIBCALL_ARRAYAPPENDCB: - t = Type::tbit->arrayOf(); - arg_types.push(t->pointerTo()); // declared inout - arg_types.push(Type::tbit); - return_type = t; - break; - case LIBCALL_ARRAYSETBIT: - t = Type::tbit->arrayOf(); - arg_types.push(t); - arg_types.push(Type::tuns32); - arg_types.push(Type::tuns32); - arg_types.push(Type::tbit); - return_type = t; - break; - case LIBCALL_ARRAYSETBIT2: - t = Type::tbit->arrayOf(); - arg_types.push(t); - arg_types.push(Type::tbit); - return_type = t; - break; case LIBCALL_MONITORENTER: case LIBCALL_MONITOREXIT: case LIBCALL_THROW: @@ -1279,6 +1184,16 @@ return decl; } +static tree +fix_d_va_list_type(tree val) +{ + if (POINTER_TYPE_P(va_list_type_node) || + INTEGRAL_TYPE_P(va_list_type_node)) + return build1(NOP_EXPR, va_list_type_node, val); + else + return val; +} + tree IRState::maybeExpandSpecialCall(tree call_exp) { // More code duplication from C @@ -1333,6 +1248,7 @@ t = build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE(t)), t); } } + t = fix_d_va_list_type(t); type = TREE_TYPE(TREE_TYPE(callee)); if (splitDynArrayVarArgs && (d_type = getDType(type)) && d_type->toBasetype()->ty == Tarray) @@ -1375,15 +1291,28 @@ // The va_list argument should already have its // address taken. The second argument, however, is // inout and that needs to be fixed to prevent a warning. - t = TREE_VALUE(TREE_CHAIN(TREE_OPERAND(call_exp, 1))); - if ( TREE_CODE( t ) == ADDR_EXPR ) { - t = TREE_OPERAND(t, 0); - } - - return buildCall(void_type_node, // assuming nobody tries to change the return type - addressOf( built_in_decls[BUILT_IN_VA_START] ), - tree_cons(NULL_TREE, TREE_VALUE(TREE_OPERAND(call_exp, 1)), - tree_cons( NULL_TREE, t, NULL_TREE))); + { + tree val_arg = TREE_VALUE(TREE_OPERAND(call_exp, 1)); + // kinda wrong... could be casting.. so need to check type too? + while ( TREE_CODE( val_arg ) == NOP_EXPR ) + val_arg = TREE_OPERAND(val_arg, 0); + if ( TREE_CODE( val_arg ) == ADDR_EXPR ) { + val_arg = TREE_OPERAND(val_arg, 0); + val_arg = fix_d_va_list_type(val_arg); + val_arg = addressOf( val_arg ); + } else + val_arg = fix_d_va_list_type(val_arg); + + t = TREE_VALUE(TREE_CHAIN(TREE_OPERAND(call_exp, 1))); + if ( TREE_CODE( t ) == ADDR_EXPR ) { + t = TREE_OPERAND(t, 0); + } + + return buildCall( void_type_node, // assuming nobody tries to change the return type + addressOf( built_in_decls[BUILT_IN_VA_START] ), + tree_cons( NULL_TREE, val_arg, + tree_cons( NULL_TREE, t, NULL_TREE ))); + } default: abort(); break; @@ -1440,33 +1369,21 @@ return call_exp; } -/* Type of return value may be different from aer_exp->exp. - Case 1: For array of bit, type is bitConfig.elemType -*/ - tree -IRState::arrayElemRef(IndexExp * aer_exp, ArrayScope * aryscp, - tree * and_mask_out, tree * or_mask_out, tree * shift_count_out) -{ - if (and_mask_out) - *and_mask_out = NULL_TREE; - if (or_mask_out) - *or_mask_out = NULL_TREE; - if (shift_count_out) - *shift_count_out = NULL_TREE; - +IRState::arrayElemRef(IndexExp * aer_exp, ArrayScope * aryscp) +{ Expression * e1 = aer_exp->e1; Expression * e2 = aer_exp->e2; Type * base_type = e1->type->toBasetype(); TY base_type_ty = base_type->ty; - bool is_bit = base_type->next->isbit(); + gcc_assert(! base_type->next->isbit()); tree index_expr; // logical index - tree subscript_expr; // expr that indexes the array data; different from index_expr for bit for bounds check + tree subscript_expr; // expr that indexes the array data tree ptr_exp; // base pointer to the elements - tree elem_ref; // reference the the element. built in two steps for bit + tree elem_ref; // reference the the element index_expr = e2->toElem( this ); subscript_expr = index_expr; @@ -1510,26 +1427,6 @@ oob_cond, index_expr, throw_expr ); } - if (is_bit) { - // %% dup'd below for Tpointer case - // %% do we want the orig index_expr or the subscript_expr saved? - - index_expr = maybeMakeTemp( index_expr ); - - tree shift_node = bitConfig.shift_tree; - // Type::tindex is signed, subscript_expr must be unsigned to generatate unsigned - // right shift %% - //if ( ! TYPE_UNSIGNED( TREE_TYPE( subscript_expr )) ).. - // %% YOW! calling 'convert' breaks stuff - subscript_expr = d_convert_basic( TREE_TYPE( shift_node ), subscript_expr ); // folding? - subscript_expr = build( RSHIFT_EXPR, TREE_TYPE(shift_node), - subscript_expr, shift_node ); - - subscript_expr = fold( subscript_expr ); // %% won't work for bound check.. - // would need COMPOUND_EXPR( bounds_check_expr, folded_index_expr ) - - } - // %% TODO: make this an ARRAY_REF? if (base_type_ty == Tarray) ptr_exp = darrayPtrRef( e1_tree ); // %% do convert in darrayPtrRef? @@ -1542,77 +1439,20 @@ break; case Tpointer: // Ignores aryscp - if (is_bit) { - // %% dup'd above - if ( TREE_CODE( index_expr ) != SAVE_EXPR) - index_expr = save_expr( index_expr ); - subscript_expr = index_expr; - if ( ! TREE_UNSIGNED(TREE_TYPE(subscript_expr))) - subscript_expr = d_convert_basic( d_unsigned_type(TREE_TYPE(subscript_expr)), - subscript_expr); - subscript_expr = build(RSHIFT_EXPR, TREE_TYPE(subscript_expr), - subscript_expr, - bitConfig.shift_tree/*integerConstant(bitarray_elem_shift, unsigned_type_node)*/); - subscript_expr = fold( subscript_expr ); - } ptr_exp = e1->toElem( this ); break; default: abort(); } - if (! is_bit) - ptr_exp = pvoidOkay( ptr_exp ); - else - ptr_exp = d_convert_basic(bitConfig.elemType->pointerTo()->toCtype(), ptr_exp); + ptr_exp = pvoidOkay( ptr_exp ); elem_ref = indirect(pointerIntSum( ptr_exp, subscript_expr), TREE_TYPE(TREE_TYPE(ptr_exp))); - if (is_bit) { - tree t; - - // (index & ) - tree bit_index_expr = build(BIT_AND_EXPR, TREE_TYPE(index_expr), - index_expr, bitConfig.mask_tree/*integerConstant(bitarray_elem_mask, bitArrayElemType)*/); - bit_index_expr = fold( bit_index_expr ); - - if (or_mask_out || shift_count_out) - bit_index_expr = save_expr( bit_index_expr ); - // 1 << (index & ) - t = build(LSHIFT_EXPR, bitConfig.elemType->toCtype()/*bitArrayElemType->toCtype()*/, - integer_one_node, bit_index_expr); - if (and_mask_out) - * and_mask_out = fold(t); - - if (shift_count_out) - * shift_count_out = bit_index_expr; - } - return elem_ref; } tree -IRState::arrayElemRef(IndexExp * aer_exp, ArrayScope * aryscp) -{ - tree elem_ref, and_mask; - elem_ref = arrayElemRef(aer_exp, aryscp, & and_mask, (tree*) 0, (tree*) 0); - if (and_mask) { // i.e., is the element type bit. - /* - // %% d_truthvalue_conversion will convert something that is already truthval cvt'd? .. would - // be nice to optimize this out... - // %% also assumptions about boolean_type_node == Type::tboolean - if (TREE_CODE(and_mask) == BIT_NOT_EXPR) - and_mask = TREE_OPERAND( and_mask, 0 ); - else - and_mask = fold( build1(BIT_NOT_EXPR, TREE_TYPE(and_mask), and_mask) ); - */ - return d_truthvalue_conversion( build(BIT_AND_EXPR, - TREE_TYPE(elem_ref), elem_ref, and_mask )); - } else - return elem_ref; -} - -tree IRState::darrayPtrRef(tree exp) { // Get the backend type for the array and pick out the array data @@ -1638,7 +1478,7 @@ // %% assert type is a darray tree ctor = make_node( CONSTRUCTOR ); tree len_field, ptr_field; - tree elts; + CtorEltMaker ce; TREE_TYPE( ctor ) = type; TREE_READONLY( ctor ) = 1; @@ -1647,9 +1487,9 @@ len_field = TYPE_FIELDS( TREE_TYPE( ctor )); ptr_field = TREE_CHAIN( len_field ); - elts = tree_cons( ptr_field, data, NULL_TREE ); // shouldn't need to convert the pointer... - elts = tree_cons( len_field, len, elts ); - CONSTRUCTOR_ELTS( ctor ) = elts; + ce.cons(len_field, len); + ce.cons(ptr_field, data); // shouldn't need to convert the pointer... + CONSTRUCTOR_ELTS( ctor ) = ce.head; return ctor; } @@ -1660,7 +1500,7 @@ // %% assert type is a darray tree ctor = make_node( CONSTRUCTOR ); tree len_value, ptr_value, len_field, ptr_field; - tree elts; + CtorEltMaker ce; TREE_TYPE( ctor ) = type; TREE_READONLY( ctor ) = 1; @@ -1673,14 +1513,15 @@ assert( POINTER_TYPE_P( TREE_TYPE( data ))); ptr_value = data; } else { - ptr_value = convert( TREE_TYPE( ptr_field ), integer_zero_node); + ptr_value = d_null_pointer; } - elts = tree_cons( ptr_field, ptr_value, NULL_TREE ); // shouldn't need to convert the pointer... - len_value = integerConstant(len, TREE_TYPE(len_field)); - elts = tree_cons( len_field, len_value, elts ); - CONSTRUCTOR_ELTS( ctor ) = elts; + + ce.cons(len_field, len_value); + ce.cons(ptr_field, ptr_value ); // shouldn't need to convert the pointer... + + CONSTRUCTOR_ELTS( ctor ) = ce.head; return ctor; } @@ -1704,10 +1545,18 @@ assert(unit_size == 2 || unit_size == 4); bool flip; -#ifdef HOST_WORDS_BIG_ENDIAN +#if D_GCC_VER < 41 +# ifdef HOST_WORDS_BIG_ENDIAN flip = (bool) ! BYTES_BIG_ENDIAN; +# else + flip = (bool) BYTES_BIG_ENDIAN; +# endif #else +# if WORDS_BIG_ENDIAN + flip = (bool) ! BYTES_BIG_ENDIAN; +# else flip = (bool) BYTES_BIG_ENDIAN; +# endif #endif if (flip) { @@ -1889,6 +1738,7 @@ tree ctor = make_node( CONSTRUCTOR ); tree obj_field = NULL_TREE; tree func_field = NULL_TREE; + CtorEltMaker ce; TREE_READONLY( ctor ) = 1; if (type) { @@ -1896,9 +1746,9 @@ obj_field = TYPE_FIELDS( type ); func_field = TREE_CHAIN( obj_field ); } - CONSTRUCTOR_ELTS( ctor ) = - tree_cons( obj_field, object_exp, - tree_cons( func_field, method_exp, NULL)); + ce.cons(obj_field, object_exp); + ce.cons(func_field, method_exp); + CONSTRUCTOR_ELTS( ctor ) = ce.head; return ctor; } @@ -1906,9 +1756,15 @@ void IRState::extractMethodCallExpr(tree mcr, tree & callee_out, tree & object_out) { assert( D_IS_METHOD_CALL_EXPR( mcr )); +#if D_GCC_VER < 41 tree elts = CONSTRUCTOR_ELTS( mcr ); object_out = TREE_VALUE( elts ); callee_out = TREE_VALUE( TREE_CHAIN( elts )); +#else + VEC(constructor_elt,gc) *elts = CONSTRUCTOR_ELTS( mcr ); + object_out = VEC_index(constructor_elt, elts, 0)->value; + callee_out = VEC_index(constructor_elt, elts, 1)->value; +#endif } tree @@ -2002,8 +1858,17 @@ TYPE_FIELDS(rec_type) = chainon(f0, f1); layout_type(rec_type); if (d_type) { - g.ofile->declareType(rec_type, d_type); - TYPE_LANG_SPECIFIC(rec_type) = build_d_type_lang_specific(d_type); + /* This is needed so that maybeExpandSpecialCall knows to + split dynamic array varargs. */ + TYPE_LANG_SPECIFIC( rec_type ) = build_d_type_lang_specific(d_type); + + /* ObjectFile::declareType will try to declare it as top-level type + which can break debugging info for element types. */ + tree stub_decl = build_decl(TYPE_DECL, get_identifier(d_type->toChars()), rec_type); + TYPE_STUB_DECL(rec_type) = stub_decl; + TYPE_NAME(rec_type) = stub_decl; + DECL_ARTIFICIAL(stub_decl) = 1; + g.ofile->rodc(stub_decl, 0); } return rec_type; } @@ -2020,6 +1885,7 @@ { tree ctor = make_node( CONSTRUCTOR ); tree ft1, ft2; + CtorEltMaker ce; TREE_TYPE( ctor ) = rec_type; TREE_READONLY( ctor ) = 1; @@ -2028,8 +1894,9 @@ ft1 = TYPE_FIELDS( rec_type ); ft2 = TREE_CHAIN( ft1 ); - CONSTRUCTOR_ELTS( ctor ) = tree_cons( ft1, f1, - tree_cons( ft2, f2, NULL_TREE )); + ce.cons(ft1, f1); + ce.cons(ft2, f2); + CONSTRUCTOR_ELTS( ctor ) = ce.head; return ctor; } @@ -2308,7 +2175,7 @@ for (unsigned i = 0; i < in_attrs->dim; i++) { Expression * e = (Expression *) in_attrs->data[i]; - IdentifierExp * ident_e; + IdentifierExp * ident_e = NULL; ListMaker args; @@ -2327,6 +2194,11 @@ } } } + else + { + gcc_unreachable(); + continue; + } out_attrs.cons(get_identifier(ident_e->ident->string), args.head); } @@ -2931,20 +2803,6 @@ #endif } -BitConfig bitConfig; - -void -BitConfig::setType(Type * type) -{ - elemType = type; - shift = exact_log2( elemType->size() * 8 ); - mask = elemType->size() * 8 - 1; - shift_tree = IRState::integerConstant(shift, unsigned_type_node); // %% 32/64? - mask_tree = IRState::integerConstant(mask, elemType->toCtype()); - dkeep(shift_tree); - dkeep(mask_tree); -} - WrappedExp::WrappedExp(Loc loc, enum TOK op, tree exp_node, Type * type) : Expression(loc, op, sizeof(WrappedExp)) { diff -uNr gdc-0.21/d/d-codegen.h gdc-0.22/d/d-codegen.h --- gdc-0.21/d/d-codegen.h 2007-01-03 06:19:29.000000000 +0100 +++ gdc-0.22/d/d-codegen.h 2007-02-03 18:35:36.000000000 +0100 @@ -32,29 +32,23 @@ LIBCALL_SWITCH_ERROR, LIBCALL_INVARIANT, LIBCALL_NEWCLASS, - LIBCALL_NEW, - //LIBCALL_NEWARRAYI, - LIBCALL_NEWARRAYIP, - //LIBCALL_NEWM, - LIBCALL_NEWMP, - //LIBCALL_NEWARRAYMI, - LIBCALL_NEWARRAYMIP, - LIBCALL_NEWBITARRAY, + LIBCALL_NEWARRAYT, + LIBCALL_NEWARRAYIT, + //LIBCALL_NEWARRAYMT, + LIBCALL_NEWARRAYMTP, + //LIBCALL_NEWARRAYMIT, + LIBCALL_NEWARRAYMITP, LIBCALL_DELCLASS, LIBCALL_DELARRAY, LIBCALL_DELMEMORY, LIBCALL_CALLFINALIZER, - LIBCALL_ARRAYSETLENGTH, - //LIBCALL_ARRAYSETLENGTH_3, - LIBCALL_ARRAYSETLENGTH_3P, - LIBCALL_ARRAYSETLENGTH_B, + LIBCALL_ARRAYSETLENGTHT, + LIBCALL_ARRAYSETLENGTHIT, LIBCALL_DYNAMIC_CAST, LIBCALL_INTERFACE_CAST, LIBCALL_ADEQ, - LIBCALL_ADEQBIT, LIBCALL_ADCMP, LIBCALL_ADCMPCHAR, - LIBCALL_ADCMPBIT, LIBCALL_AALEN, /*LIBCALL_AAIN, LIBCALL_AAGET, @@ -65,19 +59,12 @@ LIBCALL_AAGETRVALUEP, LIBCALL_AADELP, LIBCALL_ARRAYCAST, - LIBCALL_ARRAYCAST_FROMBIT, LIBCALL_ARRAYCOPY, - LIBCALL_ARRAYCOPYBIT, - LIBCALL_ARRAYCAT, - LIBCALL_ARRAYCATB, - LIBCALL_ARRAYCATN, - LIBCALL_ARRAYAPPEND, - LIBCALL_ARRAYAPPENDB, - //LIBCALL_ARRAYAPPENDC, - LIBCALL_ARRAYAPPENDCP, - LIBCALL_ARRAYAPPENDCB, - LIBCALL_ARRAYSETBIT, - LIBCALL_ARRAYSETBIT2, + LIBCALL_ARRAYCATT, + LIBCALL_ARRAYCATNT, + LIBCALL_ARRAYAPPENDT, + //LIBCALL_ARRAYAPPENDCT, + LIBCALL_ARRAYAPPENDCTP, LIBCALL_MONITORENTER, LIBCALL_MONITOREXIT, LIBCALL_CRITICALENTER, @@ -297,30 +284,9 @@ tree checkedIndex(Loc loc, tree index, tree upper_bound, bool inclusive); tree boundsCond(tree index, tree upper_bound, bool inclusive); - tree bitAlignCheck(Loc loc, tree index); - // Returns something that can be used as an l-value or an r-value unless - // the array is of type bit in which case it can only be used as an r-value tree arrayElemRef(IndexExp * aer_exp, ArrayScope * aryscp); - // Returns something that can be used as an l-value. For bit arrays, also - // creates expressions needed to modify or select bits - - // Only one of or_mask_out or shift_count_out is needed .. not - // sure which is better to use... - tree arrayElemRef(IndexExp * aer_exp, ArrayScope * aryscp, - tree * and_mask_out, tree * or_mask_out, tree * shift_count_out); - - bool isBitArrayAccess(Expression * e) { - if (e->op == TOKindex) { - Type * e1_basetype = ((IndexExp *) e)->e1->type->toBasetype(); - // assuming != Taarray is good enough for == Tarray,Tsarray,Tpointer - return e1_basetype->ty != Taarray && e1_basetype->next->isbit(); - } else { - return false; - } - } - #if D_GCC_VER < 40 static tree binding(tree var_chain, tree body) { @@ -463,23 +429,6 @@ static void doLineNote(const Loc & loc) { ObjectFile::doLineNote(loc); } }; -struct BitConfig { - Type * elemType; - unsigned shift; - unsigned mask; - tree mask_tree; - tree shift_tree; - unsigned bitCountToBytes(unsigned bc) { - return ((bc + mask) >> shift) * elemType->size(); - } - unsigned bitCountToWords(unsigned bc) { - return (bc + mask) >> shift; - } - void setType(Type * type); -}; - -extern BitConfig bitConfig; - struct GlobalValues { ObjectFile * ofile; IRState * irs; @@ -506,6 +455,7 @@ tree * ptail; ListMaker() : head(NULL_TREE), ptail( & head ) { } ListMaker(tree * alt_head) : head(NULL_TREE), ptail( alt_head ) { } + void reserve(int i) { } void chain(tree t) { *ptail = t; ptail = & TREE_CHAIN(t); } void cons(tree p, tree v) { *ptail = tree_cons(p,v,NULL_TREE); @@ -514,6 +464,25 @@ void cons(tree v) { cons(NULL_TREE, v); } }; +#if D_GCC_VER < 41 +typedef ListMaker CtorEltMaker; +#else + +struct CtorEltMaker { + VEC(constructor_elt,gc) *head; + CtorEltMaker() : head(NULL) { } + void reserve(int i) { VEC_reserve(constructor_elt,gc,head,i); } + void cons(tree p, tree v) { + constructor_elt * ce; + ce = VEC_safe_push(constructor_elt,gc,head,NULL); + ce->index = p; + ce->value = v; + } + void cons(tree v) { cons(NULL_TREE, v); } +}; + +#endif + class FieldVisitor { public: AggregateDeclaration * aggDecl; diff -uNr gdc-0.21/d/d-convert.cc gdc-0.22/d/d-convert.cc --- gdc-0.21/d/d-convert.cc 2006-07-03 00:54:24.000000000 +0200 +++ gdc-0.22/d/d-convert.cc 2007-01-31 01:52:39.000000000 +0100 @@ -110,17 +110,41 @@ build_buul_binary_op(tree_code code, tree orig_op0, tree orig_op1, int convert_p) { tree op0, op1; - if (convert_p) + tree result_type = NULL_TREE; + if (convert_p) { op0 = default_conversion (orig_op0); op1 = default_conversion (orig_op1); } - else + else { op0 = orig_op0; op1 = orig_op1; } - return build(code, boolean_type_node, op0, op1); + + /* Also need to convert pointer/int comparison for GCC >= 4.1 */ + tree type0 = TREE_TYPE (op0); + tree type1 = TREE_TYPE (op1); + if (POINTER_TYPE_P(type0) && TREE_CODE(op1) == INTEGER_CST + && integer_zerop (op1)) + { + result_type = type0; + } + else if (POINTER_TYPE_P(type1) && TREE_CODE(op0) == INTEGER_CST + && integer_zerop (op0)) + { + result_type = type1; + } + + if (result_type) + { + if (TREE_TYPE (op0) != result_type) + op0 = convert (result_type, op0); + if (TREE_TYPE (op1) != result_type) + op1 = convert (result_type, op1); + } + + return build(code, boolean_type_node, op0, op1); } // These functions support calls from the backend. This happens diff -uNr gdc-0.21/d/d-decls.cc gdc-0.22/d/d-decls.cc --- gdc-0.21/d/d-decls.cc 2006-12-27 01:43:34.000000000 +0100 +++ gdc-0.22/d/d-decls.cc 2007-02-03 18:35:36.000000000 +0100 @@ -83,7 +83,7 @@ n = mangle(); id = (char *) alloca(2 + strlen(n) + sizeof(size_t) * 3 + strlen(prefix) + strlen(suffix) + 1); - sprintf(id,"_D%s%d%s%s", n, strlen(prefix), prefix, suffix); + sprintf(id,"_D%s%"PRIuSIZE"%s%s", n, strlen(prefix), prefix, suffix); s = symbol_name(id, sclass, t); return s; } @@ -202,10 +202,12 @@ var_decl = build_decl(decl_kind, get_identifier(ident_to_use), gen.trueDeclarationType( this )); - if (isDataseg()) - uniqueName(this, var_decl, ident_to_use); - if (c_ident) - SET_DECL_ASSEMBLER_NAME(var_decl, get_identifier(c_ident->string)); + if (decl_kind != CONST_DECL) { + if (isDataseg()) + uniqueName(this, var_decl, ident_to_use); + if (c_ident) + SET_DECL_ASSEMBLER_NAME(var_decl, get_identifier(c_ident->string)); + } dkeep(var_decl); g.ofile->setDeclLoc(var_decl, this); if ( decl_kind == VAR_DECL ) { @@ -427,7 +429,7 @@ functions are finished, but this will only work for GCC >= 3.4. */ Dsymbol * p = this->parent; - FuncDeclaration * outer_func; + FuncDeclaration * outer_func = NULL; bool is_template_member = false; while (p) { @@ -821,6 +823,23 @@ return sinit; } +Symbol *TypedefDeclaration::toInitializer() +{ + Symbol *s; + Classsym *stag; + + if (!sinit) + { + s = toSymbolX("__init", SCextern, 0, "Z"); + s->Sfl = FLextern; + s->Sflags |= SFLnodebug; + slist_add(s); + sinit = s; + sinit->Sdt = ((TypeTypedef *)type)->sym->init->toDt(); + } + return sinit; +} + /****************************************** */ diff -uNr gdc-0.21/d/d-gcc-includes.h gdc-0.22/d/d-gcc-includes.h --- gdc-0.21/d/d-gcc-includes.h 2006-07-03 00:54:24.000000000 +0200 +++ gdc-0.22/d/d-gcc-includes.h 2007-01-31 01:52:39.000000000 +0100 @@ -79,6 +79,9 @@ #include "tree-inline.h" #endif +#if D_GCC_VER >= 41 +#include "vec.h" +#endif } // Undefine things that give us problems diff -uNr gdc-0.21/d/d-gcc-real.cc gdc-0.22/d/d-gcc-real.cc --- gdc-0.21/d/d-gcc-real.cc 2006-07-03 00:54:24.000000000 +0200 +++ gdc-0.22/d/d-gcc-real.cc 2007-01-28 20:17:23.000000000 +0100 @@ -225,10 +225,7 @@ real_t & real_t::operator=(int v) { - REAL_VALUE_FROM_UNSIGNED_INT(rv(), - v & ((1LL << HOST_BITS_PER_WIDE_INT)-1), - v >> HOST_BITS_PER_WIDE_INT, // %% maybe just zero.. - max_float_mode()); + REAL_VALUE_FROM_UNSIGNED_INT(rv(), v, 0, max_float_mode()); return *this; } diff -uNr gdc-0.21/d/d-glue.cc gdc-0.22/d/d-glue.cc --- gdc-0.21/d/d-glue.cc 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/d-glue.cc 2007-02-03 18:35:36.000000000 +0100 @@ -30,7 +30,7 @@ convert (tree type, tree expr) { Type * target_type = g.irs->getDType(type); - Type * expr_type = g.irs->getDType(type); + Type * expr_type = g.irs->getDType(TREE_TYPE(expr)); if (target_type && expr_type) return g.irs->convertTo(expr, expr_type, target_type); else @@ -65,7 +65,7 @@ if (u1 ^ u2) { if (gen.warnSignCompare) { - warning ("unsigned comparison with signed operand"); + d_warning (0, "unsigned comparison with signed operand"); } if (! u1) * e1 = convert( d_unsigned_type( t1 ), * e1 ); @@ -334,11 +334,12 @@ // assuming sizes are equal // shouldn't need to check for Tbit return make_bool_binop(this, irs); - } else if (elem_type->ty != Tbit) { - Type * elem_type = e1->type->toBasetype()->next->toBasetype(); + } else { tree len_expr[2]; tree data_expr[2]; + gcc_assert(elem_type->ty != Tbit); + for (int i = 0; i < 2; i++) { Expression * e = i == 0 ? e1 : e2; TY e_base_ty = i == 0 ? base_ty_1 : base_ty_2; @@ -374,18 +375,6 @@ irs->boolOp(op == TOKequal ? EQ_EXPR : NE_EXPR, result, integer_zero_node)); return convert(type->toCtype(), result); - } else { - error("bit arrays no longer implemented"); - return irs->integerConstant(0, type); - /* - tree args[2]; - args[0] = e1->implicitCastTo(Type::tbit->arrayOf())->toElem(irs); - args[1] = e2->implicitCastTo(Type::tbit->arrayOf())->toElem(irs); - tree result = irs->libCall(LIBCALL_ADEQBIT, 2, args); - if (op == TOKnotequal) - result = build1(TRUTH_NOT_EXPR, boolean_type_node, result); - return convert(type->toCtype(), result); - */ } } else { // Taarray case not defined in spec, probably should be a library call @@ -431,10 +420,9 @@ case Tvoid: lib_call = LIBCALL_ADCMPCHAR; break; - case Tbit: - lib_call = LIBCALL_ADCMPBIT; - break; default: + gcc_assert(elem_type->ty != Tbit); + // Tuns8, Tchar, Tbool if (elem_type->size() == 1 && elem_type->isscalar() && elem_type->isunsigned()) @@ -629,8 +617,6 @@ tree elem_var = NULL_TREE; tree result; - // %% flatten nested CatExp and use arraycatn? - // One of the operands may be an element instead of an array. // Logic copied from CatExp::semantic if ((tb1->ty == Tsarray || tb1->ty == Tarray) && @@ -653,35 +639,34 @@ array_exp[0] = irs->rawArray(e1); if (! array_exp[1]) array_exp[1] = irs->rawArray(e2); - - if (elem_type->ty != Tbit) { - unsigned n_args; - args[0] = irs->integerConstant(elem_type->size(), Type::tsize_t); - args[1] = irs->integerConstant(2, Type::tsize_t); - if (irs->splitDynArrayVarArgs) - { - n_args = 6; - array_exp[0] = irs->maybeMakeTemp(array_exp[0]); - array_exp[1] = irs->maybeMakeTemp(array_exp[1]); - args[2] = irs->darrayLenRef(array_exp[0]); - args[3] = irs->darrayPtrRef(array_exp[0]); - args[4] = irs->darrayLenRef(array_exp[1]); - args[5] = irs->darrayPtrRef(array_exp[1]); - } - else - { - n_args = 4; - args[2] = array_exp[0]; - args[3] = array_exp[1]; - } - result = irs->libCall(LIBCALL_ARRAYCATN, n_args, args, type->toCtype()); - } else { - args[0] = array_exp[0]; - args[1] = array_exp[1]; - result = irs->libCall(LIBCALL_ARRAYCATB, 2, args, type->toCtype()); + + gcc_assert(elem_type->ty != Tbit); + + unsigned n_args; + args[0] = irs->typeinfoReference(type); + args[1] = irs->integerConstant(2, Type::tuns32); + if (irs->splitDynArrayVarArgs) + { + n_args = 6; + array_exp[0] = irs->maybeMakeTemp(array_exp[0]); + array_exp[1] = irs->maybeMakeTemp(array_exp[1]); + args[2] = irs->darrayLenRef(array_exp[0]); + args[3] = irs->darrayPtrRef(array_exp[0]); + args[4] = irs->darrayLenRef(array_exp[1]); + args[5] = irs->darrayPtrRef(array_exp[1]); + } + else + { + n_args = 4; + args[2] = array_exp[0]; + args[3] = array_exp[1]; } + + result = irs->libCall(LIBCALL_ARRAYCATNT, n_args, args, type->toCtype()); + if (elem_var) result = irs->binding(elem_var, result); + return result; } @@ -707,68 +692,6 @@ return make_math_op(this, irs); } -class BitArrayAssign -{ - IRState * irs; - ArrayScope aryscp; - - tree word_ref; // reference to something of type bitConfig.elemType - tree select_mask; - tree left_shift; - tree lhs; - tree src_exp; -public: - BitArrayAssign(IndexExp * exp, IRState * irs) : - aryscp(irs, exp->lengthVar, exp->loc) - { - this->irs = irs; - - word_ref = irs->arrayElemRef(exp, & aryscp, - & select_mask, (tree *) 0, & left_shift); - - } - // Return the left-hand side for b[x] ?= v - // Call only once. - tree getLhs() { - word_ref = stabilize_reference(word_ref); - select_mask = irs->maybeMakeTemp( select_mask ); - lhs = d_truthvalue_conversion( build(BIT_AND_EXPR, - TREE_TYPE(word_ref), word_ref, select_mask )); - return lhs; - } - void setSrc(tree src_exp) { - this->src_exp = src_exp; - } - tree finish() { - tree truth_src = src_exp; - // %% (need this or crash at varasm.c:3172; not sure why) - // the test may not be broad enough - if ( ! INTEGRAL_TYPE_P(TREE_TYPE(truth_src)) ) - truth_src = convert(integer_type_node, truth_src); - truth_src = d_truthvalue_conversion(truth_src); - -#if D_GCC_VER >= 40 - // result LSHIFT_EXPR of seems to be limited to TYPE_PRECISION - // of the (left?) operand(s?). - truth_src = convert(bitConfig.elemType->toCtype(), truth_src); -#endif - - truth_src = irs->maybeMakeTemp( truth_src ); - - tree word_src = build(LSHIFT_EXPR, bitConfig.elemType->toCtype(), - truth_src, left_shift); - - tree tgt_masked = word_ref; - tgt_masked = build(BIT_AND_EXPR, TREE_TYPE(tgt_masked), - tgt_masked, fold(build1(BIT_NOT_EXPR,TREE_TYPE(select_mask),select_mask))); - - tree a = build(MODIFY_EXPR, void_type_node, word_ref, - build(BIT_IOR_EXPR, TREE_TYPE(tgt_masked), tgt_masked, word_src)); - //return build(COMPOUND_EXPR, TREE_TYPE(truth_src), a, truth_src); - return aryscp.finish( build(COMPOUND_EXPR, TREE_TYPE(truth_src), a, truth_src) ); - } -}; - tree chain_cvt(tree t, Type * typ, Array & casts, IRState * irs) { for (int i = casts.dim - 1; i >= 0; i--) { @@ -811,47 +734,32 @@ e1_to_use = cast_exp->e1; } - if ( irs->isBitArrayAccess( e1_to_use )) { - BitArrayAssign bas( (IndexExp *) e1_to_use, irs ); - - tree lhs = chain_cvt(bas.getLhs(), Type::tbit, lhs_casts, irs); - - Type * src_type = lhs_type; - tree src = make_math_op(out_code, lhs, lhs_type, - exp->e2->toElem(irs), exp->e2->type, - src_type, irs); - - bas.setSrc( src ); - - result = bas.finish(); - - } else { - tree tgt = stabilize_reference( irs->toElemLvalue(e1_to_use) ); - tree lhs = chain_cvt(tgt, e1_to_use->type, lhs_casts, irs); + tree tgt = stabilize_reference( irs->toElemLvalue(e1_to_use) ); + tree lhs = chain_cvt(tgt, e1_to_use->type, lhs_casts, irs); - Type * src_type = lhs_type; + Type * src_type = lhs_type; + { + /* Determine the correct combined type from BinExp::typeCombine. */ + TY ty = (TY) Type::impcnvResult[lhs_type->toBasetype()->ty][exp->e2->type->toBasetype()->ty]; + if (ty != Terror) + src_type = Type::basic[ty]; + } + if (out_code == TOKmul && exp->e1->type->isimaginary()) + { + assert( exp->e2->type->isfloating() ); + if ( ! exp->e2->type->isimaginary() && ! exp->e2->type->iscomplex() ) { - /* Determined the correct combined type from BinExp::typeCombine. */ - TY ty = (TY) Type::impcnvResult[lhs_type->toBasetype()->ty][exp->e2->type->toBasetype()->ty]; - if (ty != Terror) - src_type = Type::basic[ty]; - } - if (out_code == TOKmul && exp->e1->type->isimaginary()) - { - assert( exp->e2->type->isfloating() ); - if ( ! exp->e2->type->isimaginary() && ! exp->e2->type->iscomplex() ) - { - assert( exp->e1->type->size() == exp->e2->type->size() ); - src_type = exp->e1->type; - } + assert( exp->e1->type->size() == exp->e2->type->size() ); + src_type = exp->e1->type; } - tree src = make_math_op(out_code, lhs, lhs_type, - exp->e2->toElem(irs), exp->e2->type, - src_type, irs); - result = build(MODIFY_EXPR, exp->type->toCtype(), - tgt, irs->convertForAssignment(src, src_type, e1_to_use->type)); } + tree src = make_math_op(out_code, lhs, lhs_type, + exp->e2->toElem(irs), exp->e2->type, + src_type, irs); + result = build(MODIFY_EXPR, exp->type->toCtype(), + tgt, irs->convertForAssignment(src, src_type, e1_to_use->type)); + return result; } @@ -884,31 +792,21 @@ int n_args; AddrOfExpr aoe; - args[0] = irs->addressOf( irs->toElemLvalue(e1) ); - if (elem_type->ty != Tbit) { - n_args = 3; - if (elem_type->equals(e2->type->toBasetype())) { - // append an element - args[1] = size_exp; - args[2] = aoe.set(irs, e2->toElem(irs) ); - lib_call = LIBCALL_ARRAYAPPENDCP; - } else { - // append an array - args[1] = irs->rawArray(e2); - args[2] = size_exp; - lib_call = LIBCALL_ARRAYAPPEND; - } + args[0] = irs->typeinfoReference( type ); + args[1] = irs->addressOf( irs->toElemLvalue(e1) ); + + gcc_assert(elem_type->ty != Tbit); + + if (elem_type->equals(e2->type->toBasetype())) { + // append an element + args[2] = aoe.set(irs, e2->toElem(irs) ); + lib_call = LIBCALL_ARRAYAPPENDCTP; } else { - n_args = 2; - if (elem_type->equals(e2->type->toBasetype())) { - args[1] = irs->convertForAssignment(e2, Type::tbit); - lib_call = LIBCALL_ARRAYAPPENDCB; - } else { - args[1] = irs->rawArray(e2); - lib_call = LIBCALL_ARRAYAPPENDB; - } + // append an array + args[2] = irs->rawArray(e2); + lib_call = LIBCALL_ARRAYAPPENDT; } - return aoe.finish(irs, irs->libCall(lib_call, n_args, args, type->toCtype())); + return aoe.finish(irs, irs->libCall(lib_call, 3, args, type->toCtype())); } elem * @@ -994,143 +892,69 @@ array_exp = irs->addressOf( ae->toElem( irs )); } - if (! elem_type->isbit()) { - args[0] = irs->convertTo(e2, Type::tsize_t); - args[1] = irs->integerConstant(elem_type->size(), Type::tsize_t); - args[2] = array_exp; + gcc_assert(! elem_type->isbit()); - if (elem_type->isZeroInit()) - result = irs->libCall(LIBCALL_ARRAYSETLENGTH, 3, args); - else - { - AddrOfExpr aoe; - Type * elem_init_type = elem_type; - elem_type = elem_type->toBasetype(); - while (elem_type->ty == Tsarray) { - elem_init_type = elem_type->next; - elem_type = elem_init_type->toBasetype(); - } + args[0] = irs->typeinfoReference(array_type); + args[1] = irs->convertTo(e2, Type::tsize_t); + args[2] = array_exp; - args[3] = irs->integerConstant(elem_init_type->defaultInit()->type->size(), - Type::tsize_t); - args[4] = aoe.set(irs, - irs->convertForAssignment(elem_init_type->defaultInit(), elem_type)); - result = irs->libCall(LIBCALL_ARRAYSETLENGTH_3P, 5, args); - result = aoe.finish(irs, result); - } - } else { - args[0] = irs->convertTo(e2, Type::tsize_t); - args[1] = array_exp; - result = irs->libCall(LIBCALL_ARRAYSETLENGTH_B, 2, args); - } - // the libcall actually returns a whole new dynamic array.., but also - // modifies the array.. - // result = build(MODIFY_EXPR, e1->type->toCtype(), e1, result); - // the result of the expression, is still the length... + LibCall lib_call = elem_type->isZeroInit() ? + LIBCALL_ARRAYSETLENGTHT : LIBCALL_ARRAYSETLENGTHIT; + + result = irs->libCall(lib_call, 3, args); result = irs->darrayLenRef( result ); return result; - } else if (irs->isBitArrayAccess( e1 )) { - // Assignment to a single element of a bit array. - - BitArrayAssign bas( (IndexExp *) e1, irs); - bas.setSrc(e2->toElem( irs )); - return bas.finish(); } else if (e1->op == TOKslice) { Type * elem_type = e1->type->toBasetype()->next->toBasetype(); + + gcc_assert(elem_type->ty != Tbit); + if (elem_type->equals( e2->type->toBasetype() )) { // Set a range of elements to one value. // %% This is used for initing on-stack static arrays.. // should optimize with memset if possible // %% vararg issues - if (elem_type->ty != Tbit) { - tree dyn_array_exp = irs->maybeMakeTemp( e1->toElem(irs) ); - tree set_exp = array_set_expr( irs, irs->darrayPtrRef(dyn_array_exp), - e2->toElem(irs), irs->darrayLenRef(dyn_array_exp)); - return irs->compound(set_exp, dyn_array_exp); - } else { - tree args[4]; - SliceExp * e1_slice = (SliceExp *) e1; - - if (e1_slice->lwr || e1_slice->upr) { - ArrayScope aryscp(irs, e1_slice->lengthVar, loc); - tree ary_t; - - args[1] = e1_slice->lwr ? - e1_slice->lwr->toElem(irs) : size_int(0); - args[2] = e1_slice->upr ? - e1_slice->upr->toElem(irs) : NULL_TREE; - - if (e1_slice->e1->type->toBasetype()->ty == Tpointer) { - ary_t = irs->darrayVal(Type::tbit->arrayOf()->toCtype(), - TYPE_MAX_VALUE(Type::tsize_t->toCtype()), - e1_slice->e1->toElem(irs)); - assert(args[2]); - } else { - ary_t = irs->rawArray(e1_slice->e1); - if ( ! args[2] ) { - ary_t = irs->maybeMakeTemp(ary_t); - args[2] = irs->arrayLength(ary_t, e1_slice->e1->type); - } - } - - ary_t = aryscp.setArrayExp(ary_t, e1_slice->e1->type); - - args[0] = ary_t; - args[3] = irs->convertForAssignment(e2, Type::tbit); - return aryscp.finish( irs->libCall(LIBCALL_ARRAYSETBIT, 4, args) ); - } else { - // Assuming there can be no array scope without a lower or upper bound - assert(! e1_slice->lengthVar); - args[0] = irs->rawArray(e1); - args[1] = irs->convertForAssignment(e2, Type::tbit); - return irs->libCall(LIBCALL_ARRAYSETBIT2, 2, args, type->toCtype()); - } - } + + tree dyn_array_exp = irs->maybeMakeTemp( e1->toElem(irs) ); + tree set_exp = array_set_expr( irs, irs->darrayPtrRef(dyn_array_exp), + e2->toElem(irs), irs->darrayLenRef(dyn_array_exp)); + return irs->compound(set_exp, dyn_array_exp); } else { - // Copy a range. - if (elem_type->ty != Tbit) { - if (global.params.useArrayBounds) { - tree args[3] = { - irs->integerConstant(elem_type->size(), Type::tuns32), - irs->rawArray(e2), - irs->rawArray(e1) }; - return irs->libCall(LIBCALL_ARRAYCOPY, 3, args, type->toCtype()); - } else { - tree array[2] = { - irs->maybeMakeTemp( irs->rawArray(e1) ), - irs->rawArray(e2) }; - tree t_memcpy = built_in_decls[BUILT_IN_MEMCPY]; - tree result; - tree size; - - size = build(MULT_EXPR, size_type_node, - convert(size_type_node, irs->darrayLenRef(array[0])), - size_int(elem_type->size())); - size = fold( size ); - - result = irs->buildCall( TREE_TYPE(TREE_TYPE( t_memcpy )), - irs->addressOf( t_memcpy ), - tree_cons( NULL_TREE, irs->darrayPtrRef(array[0]), - tree_cons( NULL_TREE, irs->darrayPtrRef(array[1]), - tree_cons( NULL_TREE, size, NULL_TREE)))); - - return irs->compound( result, array[0], type->toCtype() ); - /* - result = irs->buildCall( TREE_TYPE(TREE_TYPE( t_memcpy )), - irs->addressOf( t_memcpy ), - List( irs->darrayPtrRef(array[0]) ). - ( irs->darrayPtrRef(array[1]) ). - ( size ).head()); - */ - } - - } else { - tree args[2] = { + if (global.params.useArrayBounds) { + tree args[3] = { + irs->integerConstant(elem_type->size(), Type::tuns32), irs->rawArray(e2), irs->rawArray(e1) }; - return irs->libCall(LIBCALL_ARRAYCOPYBIT, 2, args); + return irs->libCall(LIBCALL_ARRAYCOPY, 3, args, type->toCtype()); + } else { + tree array[2] = { + irs->maybeMakeTemp( irs->rawArray(e1) ), + irs->rawArray(e2) }; + tree t_memcpy = built_in_decls[BUILT_IN_MEMCPY]; + tree result; + tree size; + + size = build(MULT_EXPR, size_type_node, + convert(size_type_node, irs->darrayLenRef(array[0])), + size_int(elem_type->size())); + size = fold( size ); + + result = irs->buildCall( TREE_TYPE(TREE_TYPE( t_memcpy )), + irs->addressOf( t_memcpy ), + tree_cons( NULL_TREE, irs->darrayPtrRef(array[0]), + tree_cons( NULL_TREE, irs->darrayPtrRef(array[1]), + tree_cons( NULL_TREE, size, NULL_TREE)))); + + return irs->compound( result, array[0], type->toCtype() ); + /* + result = irs->buildCall( TREE_TYPE(TREE_TYPE( t_memcpy )), + irs->addressOf( t_memcpy ), + List( irs->darrayPtrRef(array[0]) ). + ( irs->darrayPtrRef(array[1]) ). + ( size ).head()); + */ } } } else { @@ -1303,17 +1127,7 @@ lwr_tree = irs->checkedIndex(loc, lwr_tree, array_len_expr, true); // lower bound can equal length } - if (orig_array_type->next->isbit()) { - assert( tree_low_cst( TYPE_SIZE_UNIT( TREE_TYPE( TREE_TYPE( final_ptr_expr ))), 1) == 1 ); - lwr_tree = irs->bitAlignCheck(loc, lwr_tree); - // Need to convert to unsigned for an unsigned shift. - if ( ! TREE_UNSIGNED( TREE_TYPE( lwr_tree ))) { - lwr_tree = convert( d_unsigned_type( TREE_TYPE( lwr_tree )), lwr_tree ); - } - // !! note: lwr_tree can't be used as the logical index after this point - lwr_tree = build(RSHIFT_EXPR, TREE_TYPE(lwr_tree), lwr_tree, - irs->integerConstant(3, Type::tuns32)); - } + gcc_assert(! orig_array_type->next->isbit()); final_ptr_expr = irs->pointerIntSum(irs->pvoidOkay(final_ptr_expr), lwr_tree); final_ptr_expr = irs->nop(final_ptr_expr, TREE_TYPE( orig_pointer_expr )); @@ -1475,8 +1289,7 @@ field->type->equals(this->type)) { if (rec_tree == error_mark_node) return error_mark_node; // backend will ICE otherwise - return irs->nop(irs->component(rec_tree, field->toSymbol()->Stree), - type->toCtype()); + return irs->component(rec_tree, field->toSymbol()->Stree); } else if (field->offset > the_offset) { break; } @@ -1997,87 +1810,34 @@ Type * elem_init_type = type; - // First, skip past dynamic array types + /* First, skip past dynamic array dimensions/types that will be + allocated by this call. */ for (unsigned i = 0; i < arguments->dim; i++) elem_init_type = elem_init_type->toBasetype()->next; // assert ty == Tarray - /* The element type may be a typedef with a custom ini. Keep track - of that and the actual element type. */ - Type * elem_type = elem_init_type->toBasetype(); - - tree final_size = NULL_TREE; - tree final_init = NULL_TREE; - AddrOfExpr aoe; - uhwint multiple = 1; - - if (elem_type->ty != Tbit) { - if (elem_init_type->isZeroInit()) { - lib_call = LIBCALL_NEW; - } else { - - while (elem_type->ty == Tsarray) { - multiple = ((TypeSArray *) elem_type)->dim->toUInteger() * multiple; - elem_init_type = elem_type->next; - elem_type = elem_init_type->toBasetype(); - } - - final_init = irs->convertForAssignment(elem_init_type->defaultInit(), elem_type); - final_init = aoe.set(irs, final_init); - - lib_call = LIBCALL_NEWARRAYIP; - } - - final_size = size_int(elem_type->size()); - } else { - final_init = irs->integerConstant(0, Type::tbit->toCtype()); - lib_call = LIBCALL_NEWBITARRAY; - } + gcc_assert(! elem_init_type->isbit()); if (arguments->dim == 1) { - tree orig_length = - ((Expression *) arguments->data[0])->toElem(irs); // not new_args.. - tree final_length = orig_length; - - // %%TODO: convert to correct argument types... (for 64-bit) - if (multiple != 1) { - orig_length = irs->maybeMakeTemp(orig_length); - - // %%TODO: type conversions... - final_length = build(MULT_EXPR, size_type_node, - orig_length, - size_int(multiple)); - final_length = fold( final_length ); - } + lib_call = elem_init_type->isZeroInit() ? + LIBCALL_NEWARRAYT : LIBCALL_NEWARRAYIT; - tree args[3]; - tree * p_arg = args; - - *p_arg++ = final_length; - if (final_size) - *p_arg++ = final_size; - if (final_init) - *p_arg++ = final_init; - result = irs->libCall(lib_call, p_arg - args, args, type->toCtype()); // %% forced result type ok? - - if (multiple != 1) { - // need to set the length the original length value - result = irs->darrayVal(base_type->toCtype(), orig_length, - irs->darrayPtrRef(result)); - } + tree args[2]; + args[0] = irs->typeinfoReference(type); + args[1] = ((Expression *) arguments->data[0])->toElem(irs); + result = irs->libCall(lib_call, 2, args, type->toCtype()); } else { - if (elem_init_type->isZeroInit()) - lib_call = LIBCALL_NEWMP; - else - lib_call = LIBCALL_NEWARRAYMIP; - + lib_call = elem_init_type->isZeroInit() ? + LIBCALL_NEWARRAYMTP : LIBCALL_NEWARRAYMITP; + tree dims_var = irs->exprVar(irs->arrayType(size_type_node, arguments->dim)); { tree dims_init; - ListMaker elms; - + CtorEltMaker elms; + + elms.reserve( arguments->dim ); for (unsigned i = 0; i < arguments->dim/* - 1*/; i++) elms.cons( irs->integerConstant(i, size_type_node), ((Expression*) arguments->data[i])->toElem(irs) ); @@ -2089,33 +1849,24 @@ DECL_INITIAL(dims_var) = dims_init; } - tree args[5]; - unsigned n_args; - - args[0] = final_size; + tree args[3]; + args[0] = irs->typeinfoReference(type); args[1] = irs->integerConstant(arguments->dim, Type::tint32); // The ndims arg is declared as 'int' args[2] = irs->addressOf(dims_var); - if (final_init) - { - args[3] = irs->integerConstant(multiple, size_type_node); - args[4] = final_init; - n_args = 5; - } - else - n_args = 3; - result = irs->libCall(lib_call, n_args, args, type->toCtype()); + result = irs->libCall(lib_call, 3, args, type->toCtype()); result = irs->binding(dims_var, result); } - return aoe.finish(irs, result); + return result; } break; case Tpointer: { - Type * object_type = base_type->next->toBasetype(); + Type * object_type = base_type->next; tree new_call; tree t; + bool need_init = true; if (onstack) { tree stack_var = irs->localVar( object_type ); @@ -2125,13 +1876,16 @@ new_call = irs->call(allocator, newargs); } else { tree args[2]; - args[0] = irs->integerConstant(1, Type::tsize_t); - args[1] = irs->integerConstant(object_type->size(), Type::tsize_t); - new_call = irs->libCall(LIBCALL_NEW, 2, args); + LibCall lib_call = object_type->isZeroInit() ? + LIBCALL_NEWARRAYT : LIBCALL_NEWARRAYIT; + args[0] = irs->typeinfoReference( object_type->arrayOf() ); + args[1] = irs->integerConstant(1, Type::tsize_t); + new_call = irs->libCall(lib_call, 2, args); new_call = irs->darrayPtrRef(new_call); + need_init = false; } new_call = irs->nop(new_call, base_type->toCtype()); - if ( ! object_type->isZeroInit() ) { + if ( need_init ) { // Save the result allocation call. new_call = save_expr( new_call ); t = irs->indirect(new_call); @@ -2174,7 +1928,7 @@ case Tpointer: // Assuming this->string is null terminated // .. need to terminate with more nulls for wchar and dchar? - value = build_string(len * sz + 1, + value = build_string((len + 1) * sz, gen.hostToTargetString((char *) string, len + 1, sz)); break; case Tsarray: @@ -2246,9 +2000,13 @@ tree elem_type = array_type->next->toCtype(); tree d_array_type = array_type->next->arrayOf()->toCtype(); - tree args[2] = { irs->integerConstant(elements->dim, size_type_node), - irs->integerConstant(array_type->next->size(), size_type_node) }; - tree d_array = irs->libCall(LIBCALL_NEW, 2, args, d_array_type); + tree args[2] = { irs->typeinfoReference(array_type->next->arrayOf()), + irs->integerConstant(elements->dim, size_type_node) }; + // Unfortunately, this does a useles initialization + LibCall lib_call = array_type->next->isZeroInit() ? + LIBCALL_NEWARRAYT : LIBCALL_NEWARRAYIT; + tree d_array = irs->libCall(lib_call, 2, args, d_array_type); + tree mem = irs->maybeMakeTemp( irs->darrayPtrRef( d_array )); tree result = irs->maybeCompound( array_literal_assign(irs, mem, this), mem ); @@ -2276,11 +2034,13 @@ { tree ctor = make_node(CONSTRUCTOR); tree fa; + CtorEltMaker ce; + TREE_TYPE(ctor) = type->toCtype(); TREE_READONLY(ctor)=1; fa = TYPE_FIELDS(TREE_TYPE(ctor)); - CONSTRUCTOR_ELTS(ctor) = tree_cons(fa, convert(TREE_TYPE(fa), integer_zero_node), - NULL_TREE); + ce.cons(fa, convert(TREE_TYPE(fa), integer_zero_node)); + CONSTRUCTOR_ELTS(ctor) = ce.head; return ctor; } break; @@ -3108,10 +2868,9 @@ if (dim->isConst() && dim->type->isintegral()) { uinteger_t size = dim->toUInteger(); - if (next->isbit()) - ctype = gen.arrayType(bitConfig.elemType, - bitConfig.bitCountToWords(size)); - else if (next->toBasetype()->ty == Tvoid) + gcc_assert(! next->isbit()); + + if (next->toBasetype()->ty == Tvoid) ctype = gen.arrayType(Type::tuns8, size); else ctype = gen.arrayType(next, size); @@ -3803,6 +3562,8 @@ assert(value); + gcc_assert(elem_type->ty != Tbit); + irs->startScope(); irs->startBindings(); /* Variables created by the function will probably end up in a contour created by emitLocalVar. This @@ -3832,76 +3593,73 @@ irs->emitLocalVar(key); // %% getExpInitializer causes uneeded initialization } + + if (value->isOut()) { + iter_decl = value->toSymbol()->Stree; + } else { + iter_decl = irs->localVar(elem_type->pointerTo()); + irs->expandDecl(iter_decl); + } - if (elem_type->ty != Tbit) { - if (value->isOut()) { - iter_decl = value->toSymbol()->Stree; - } else { - iter_decl = irs->localVar(elem_type->pointerTo()); - irs->expandDecl(iter_decl); - } + if ( agg_type->ty == Tsarray) { + bound_expr = ((TypeSArray *) agg_type)->dim->toElem(irs); + iter_init_expr = irs->addressOf( aggr_expr ); + // Type needs to be pointer-to-element to get pointerIntSum + // to work + iter_init_expr = irs->nop(iter_init_expr, + agg_type->next->pointerTo()->toCtype()); + } else { + bound_expr = irs->darrayLenRef( aggr_expr ); + iter_init_expr = irs->darrayPtrRef( aggr_expr ); + } + iter_init_expr = save_expr( iter_init_expr ); + bound_expr = irs->pointerIntSum(iter_init_expr, bound_expr); + // aggr. isn't supposed to be modified, so... + bound_expr = save_expr( bound_expr ); - if ( agg_type->ty == Tsarray) { - bound_expr = ((TypeSArray *) agg_type)->dim->toElem(irs); - iter_init_expr = irs->addressOf( aggr_expr ); - // Type needs to be pointer-to-element to get pointerIntSum - // to work - iter_init_expr = irs->nop(iter_init_expr, - agg_type->next->pointerTo()->toCtype()); - } else { - bound_expr = irs->darrayLenRef( aggr_expr ); - iter_init_expr = irs->darrayPtrRef( aggr_expr ); - } - iter_init_expr = save_expr( iter_init_expr ); - bound_expr = irs->pointerIntSum(iter_init_expr, bound_expr); - // aggr. isn't supposed to be modified, so... - bound_expr = save_expr( bound_expr ); + enum tree_code iter_op = PLUS_EXPR; - enum tree_code iter_op = PLUS_EXPR; + if (op == TOKforeach_reverse) + { + tree t = iter_init_expr; + iter_init_expr = bound_expr; + bound_expr = t; + + iter_op = MINUS_EXPR; + } - if (op == TOKforeach_reverse) - { - tree t = iter_init_expr; - iter_init_expr = bound_expr; - bound_expr = t; - - iter_op = MINUS_EXPR; - } - - tree condition = build(NE_EXPR, boolean_type_node, iter_decl, bound_expr); - tree incr_expr = - build(MODIFY_EXPR, void_type_node, iter_decl, - build(iter_op, TREE_TYPE(iter_decl), iter_decl, - size_int(elem_type->size()))); - if (key) { - tree key_decl = key->toSymbol()->Stree; - tree key_incr_expr = - build(MODIFY_EXPR, void_type_node, key_decl, - build(iter_op, TREE_TYPE(iter_decl), key_decl, - irs->integerConstant(1, TREE_TYPE(key_decl)))); - incr_expr = irs->compound(incr_expr, key_incr_expr); - } + tree condition = build(NE_EXPR, boolean_type_node, iter_decl, bound_expr); + tree incr_expr = + build(MODIFY_EXPR, void_type_node, iter_decl, + build(iter_op, TREE_TYPE(iter_decl), iter_decl, + size_int(elem_type->size()))); + if (key) { + tree key_decl = key->toSymbol()->Stree; + tree key_incr_expr = + build(MODIFY_EXPR, void_type_node, key_decl, + build(iter_op, TREE_TYPE(iter_decl), key_decl, + irs->integerConstant(1, TREE_TYPE(key_decl)))); + incr_expr = irs->compound(incr_expr, key_incr_expr); + } - irs->doExp( build(MODIFY_EXPR, void_type_node, iter_decl, iter_init_expr) ); + irs->doExp( build(MODIFY_EXPR, void_type_node, iter_decl, iter_init_expr) ); - irs->startLoop(this); - irs->exitIfFalse(condition); - if ( op == TOKforeach_reverse ) - irs->doExp( incr_expr ); - if ( iter_decl != value->toSymbol()->Stree ) { - // %% check.. - irs->doExp( build(MODIFY_EXPR, void_type_node, value->toSymbol()->Stree, - irs->indirect(iter_decl)) ); - } - if (body) - body->toIR( irs ); - irs->continueHere(); - - if ( op == TOKforeach ) - irs->doExp( incr_expr ); - } else { - error("bit arrays no longer implemented"); + irs->startLoop(this); + irs->exitIfFalse(condition); + if ( op == TOKforeach_reverse ) + irs->doExp( incr_expr ); + if ( iter_decl != value->toSymbol()->Stree ) { + // %% check.. + irs->doExp( build(MODIFY_EXPR, void_type_node, value->toSymbol()->Stree, + irs->indirect(iter_decl)) ); } + if (body) + body->toIR( irs ); + irs->continueHere(); + + if ( op == TOKforeach ) + irs->doExp( incr_expr ); + irs->endLoop(); irs->endBindings(); // not really needed @@ -4215,6 +3973,9 @@ if (flag_exceptions) { eh_personality_libfunc = init_one_libfunc(d_using_sjlj_exceptions() ? "__gdc_personality_sj0" : "__gdc_personality_v0"); +#if D_GCC_VER >= 41 + default_init_unwind_resume_libfunc (); +#endif lang_eh_runtime_type = d_build_eh_type_type; using_eh_for_cleanups (); // lang_proctect_cleanup_actions = ...; // no need? ... probably needed for autos @@ -4241,8 +4002,6 @@ // This is the C main, not the D main main_identifier_node = get_identifier ("main"); - - bitConfig.setType(Type::tuns8); } void diff -uNr gdc-0.21/d/d-lang.cc gdc-0.22/d/d-lang.cc --- gdc-0.21/d/d-lang.cc 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/d-lang.cc 2007-02-06 05:30:00.000000000 +0100 @@ -61,8 +61,10 @@ #undef LANG_HOOKS_PARSE_FILE #define LANG_HOOKS_PARSE_FILE d_parse_file +#if D_GCC_VER < 41 #undef LANG_HOOKS_TRUTHVALUE_CONVERSION #define LANG_HOOKS_TRUTHVALUE_CONVERSION d_truthvalue_conversion +#endif #undef LANG_HOOKS_MARK_ADDRESSABLE #define LANG_HOOKS_MARK_ADDRESSABLE d_mark_addressable @@ -113,6 +115,11 @@ #define LANG_HOOKS_CALLGRAPH_EXPAND_FUNCTION d_expand_function #endif +#if D_GCC_VER >= 40 +#define LANG_HOOKS_TYPES_COMPATIBLE_P d_types_compatible_p +#endif + + static tree d_type_for_mode(enum machine_mode, int); ////static tree d_type_for_size PARAMS ((unsigned, int)); @@ -718,10 +725,13 @@ static void d_write_global_declarations() { - wrapup_global_declarations( (tree *) globalFunctions.data, globalFunctions.dim ); - check_global_declarations( (tree *) globalFunctions.data, globalFunctions.dim ); + tree * vec = (tree *) globalFunctions.data; + wrapup_global_declarations(vec, globalFunctions.dim); + check_global_declarations(vec, globalFunctions.dim); #if D_GCC_VER >= 40 cgraph_optimize (); + for (int i = 0; i < globalFunctions.dim; i++) + debug_hooks->global_decl(vec[i]); #endif } @@ -916,6 +926,9 @@ m = (Module *)modules.data[i]; if (global.params.verbose) fprintf(stderr, "parse %s\n", m->toChars()); + if (!Module::rootModule) + Module::rootModule = m; + m->importedFrom = m; //m->deleteObjFile(); // %% driver does this m->read(0); m->parse(global.params.dump_source); @@ -1686,6 +1699,27 @@ #endif +#if D_GCC_VER >= 40 +static int +d_types_compatible_p (tree x, tree y) +{ + if (lhd_types_compatible_p(x, y)) + return 1; + else if (d_gcc_builtin_va_list_d_type && + ( + ( x == d_gcc_builtin_va_list_d_type->ctype && + y == va_list_type_node ) || + ( y == d_gcc_builtin_va_list_d_type->ctype && + x == va_list_type_node ) )) + return 1; + else + return 0; + + return TYPE_MAIN_VARIANT (x) == TYPE_MAIN_VARIANT (y); +} +#endif + + struct lang_type * build_d_type_lang_specific(Type * t) { diff -uNr gdc-0.21/d/d-lang.h gdc-0.22/d/d-lang.h --- gdc-0.21/d/d-lang.h 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/d-lang.h 2007-01-31 01:52:39.000000000 +0100 @@ -133,6 +133,11 @@ extern GTY(()) tree d_void_zero_node; extern GTY(()) tree d_vtbl_ptr_type_node; +#if D_GCC_VER >= 41 +/* not GTY'd because gtype does not actually understand #if */ +extern tree null_node; +#endif + #ifdef __cplusplus /* In d-lang.cc. These are called through function pointers and do not need to be "extern C". */ @@ -145,7 +150,6 @@ extern void d_add_global_function PARAMS(( tree )); -extern tree d_type_for_size(unsigned bits , int unsignedp); extern tree d_unsigned_type(tree); extern tree d_signed_type(tree); @@ -178,6 +182,8 @@ tree pushdecl PARAMS ((tree)); void pushlevel PARAMS ((int)); tree poplevel PARAMS ((int, int, int)); +tree d_type_for_size(unsigned bits , int unsignedp); +void dkeep(tree t); /* In d-builtins.c */ extern void d_init_builtins PARAMS ((void)); @@ -201,9 +207,6 @@ /* protect from garbage collection */ extern GTY(()) tree d_keep_list; -#ifdef __cplusplus -extern void dkeep(tree t); -#endif #include "d-dmd-gcc.h" @@ -217,6 +220,16 @@ #if D_GCC_VER < 40 static inline tree build2(enum tree_code c, tree t, tree a, tree b) { return build(c, t, a, b); } +#define gcc_assert(x) (assert(x)) +#define gcc_unreachable(x) (assert(0)) +#endif + +#if D_GCC_VER < 41 +//#define d_warning(option, xformat, ...) warning(format, __VA_ARGS__) +#define d_warning(option, ...) warning(__VA_ARGS__) +#else +//#define d_warning(option, format, ...) warning(option, format, __VA_ARGS__) +#define d_warning(option, ...) warning(option, __VA_ARGS__) #endif #endif diff -uNr gdc-0.21/d/dmd/aggregate.h gdc-0.22/d/dmd/aggregate.h --- gdc-0.21/d/dmd/aggregate.h 2006-12-26 00:35:46.000000000 +0100 +++ gdc-0.22/d/dmd/aggregate.h 2007-02-03 17:34:12.000000000 +0100 @@ -157,7 +157,7 @@ void copyBaseInterfaces(BaseClasses *); }; -#define CLASSINFO_SIZE 0x3C // value of ClassInfo.size +#define CLASSINFO_SIZE (0x3C+8) // value of ClassInfo.size struct ClassDeclaration : AggregateDeclaration { diff -uNr gdc-0.21/d/dmd/attrib.c gdc-0.22/d/dmd/attrib.c --- gdc-0.21/d/dmd/attrib.c 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/dmd/attrib.c 2007-02-03 17:34:12.000000000 +0100 @@ -217,6 +217,22 @@ return nwritten; } +int AttribDeclaration::hasPointers() +{ + Array *d = include(NULL, NULL); + + if (d) + { + for (size_t i = 0; i < d->dim; i++) + { + Dsymbol *s = (Dsymbol *)d->data[i]; + if (s->hasPointers()) + return 1; + } + } + return 0; +} + char *AttribDeclaration::kind() { return "attribute"; diff -uNr gdc-0.21/d/dmd/attrib.h gdc-0.22/d/dmd/attrib.h --- gdc-0.21/d/dmd/attrib.h 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/dmd/attrib.h 2007-02-03 17:34:12.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -44,6 +44,7 @@ void emitComment(Scope *sc); char *kind(); int oneMember(Dsymbol **ps); + int hasPointers(); void checkCtorConstInit(); void addLocalClass(ClassDeclarations *); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff -uNr gdc-0.21/d/dmd/declaration.c gdc-0.22/d/dmd/declaration.c --- gdc-0.21/d/dmd/declaration.c 2006-12-26 22:37:35.000000000 +0100 +++ gdc-0.22/d/dmd/declaration.c 2007-02-03 17:34:12.000000000 +0100 @@ -171,6 +171,7 @@ this->sem = 0; this->inuse = 0; this->loc = loc; + this->sinit = NULL; } Dsymbol *TypedefDeclaration::syntaxCopy(Dsymbol *s) @@ -1039,6 +1040,11 @@ parent->isTemplateInstance()); } +int VarDeclaration::hasPointers() +{ + return (!isDataseg() && type->hasPointers()); +} + /****************************************** * If a variable has an auto destructor call, return call for it. * Otherwise, return NULL. diff -uNr gdc-0.21/d/dmd/declaration.h gdc-0.22/d/dmd/declaration.h --- gdc-0.21/d/dmd/declaration.h 2006-12-26 22:37:35.000000000 +0100 +++ gdc-0.22/d/dmd/declaration.h 2007-02-03 17:34:12.000000000 +0100 @@ -172,6 +172,9 @@ int cvMember(unsigned char *p); TypedefDeclaration *isTypedefDeclaration() { return this; } + + Symbol *sinit; + Symbol *toInitializer(); }; /**************************************************************/ @@ -228,6 +231,7 @@ int needThis(); int isImportedSymbol(); int isDataseg(); + int hasPointers(); Expression *callAutoDtor(); ExpInitializer *getExpInitializer(); void checkCtorConstInit(); diff -uNr gdc-0.21/d/dmd/dsymbol.c gdc-0.22/d/dmd/dsymbol.c --- gdc-0.21/d/dmd/dsymbol.c 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/dmd/dsymbol.c 2007-02-03 17:34:12.000000000 +0100 @@ -132,6 +132,16 @@ return TRUE; } +/***************************************** + * Is Dsymbol a variable that contains pointers? + */ + +int Dsymbol::hasPointers() +{ + //printf("Dsymbol::hasPointers() %s\n", toChars()); + return 0; +} + char *Dsymbol::toChars() { return ident ? ident->toChars() : (char *)"__anonymous"; diff -uNr gdc-0.21/d/dmd/dsymbol.h gdc-0.22/d/dmd/dsymbol.h --- gdc-0.21/d/dmd/dsymbol.h 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/dmd/dsymbol.h 2007-02-03 17:34:12.000000000 +0100 @@ -147,6 +147,7 @@ virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees virtual int oneMember(Dsymbol **ps); static int oneMembers(Array *members, Dsymbol **ps); + virtual int hasPointers(); virtual void addLocalClass(ClassDeclarations *) { } virtual void checkCtorConstInit() { } diff -uNr gdc-0.21/d/dmd/expression.c gdc-0.22/d/dmd/expression.c --- gdc-0.21/d/dmd/expression.c 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/dmd/expression.c 2007-02-03 17:34:12.000000000 +0100 @@ -1290,7 +1290,10 @@ { #ifndef IN_GCC return (isnan(x1) && isnan(x2)) || - memcmp(&x1, &x2, sizeof(real_t)) == 0; + /* In some cases, the REALPAD bytes get garbage in them, + * so be sure and ignore them. + */ + memcmp(&x1, &x2, REALSIZE - REALPAD) == 0; #else return (x1.isNan() && x2.isNan()) || x1.isIdenticalTo(x2); #endif diff -uNr gdc-0.21/d/dmd/idgen.c gdc-0.22/d/dmd/idgen.c --- gdc-0.21/d/dmd/idgen.c 2006-12-26 00:35:46.000000000 +0100 +++ gdc-0.22/d/dmd/idgen.c 2007-01-31 01:52:39.000000000 +0100 @@ -11,7 +11,7 @@ /* NOTE: This file has been patched from the original DMD distribution to work with the GDC compiler. - Modified by David Friedman, December 2006 + Modified by David Friedman, January 2007 */ // Program to generate string files in d data structures. @@ -32,7 +32,7 @@ char *name; // name in D executable }; -Msgtable msgtable[] = +struct Msgtable msgtable[] = { { "IUnknown" }, { "Object" }, diff -uNr gdc-0.21/d/dmd/impcnvgen.c gdc-0.22/d/dmd/impcnvgen.c --- gdc-0.21/d/dmd/impcnvgen.c 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/dmd/impcnvgen.c 2007-01-31 01:52:39.000000000 +0100 @@ -7,9 +7,16 @@ // in artistic.txt, or the GNU General Public License in gnu.txt. // See the included readme.txt for details. +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, January 2007 +*/ + #include #include +#define ENUM_TY_ONLY #include "mtype.h" enum TY impcnvResult[TMAX][TMAX]; diff -uNr gdc-0.21/d/dmd/import.c gdc-0.22/d/dmd/import.c --- gdc-0.21/d/dmd/import.c 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/dmd/import.c 2007-02-03 17:34:12.000000000 +0100 @@ -77,7 +77,7 @@ return si; } -void Import::load() +void Import::load(Scope *sc) { DsymbolTable *dst; Dsymbol *s; @@ -102,6 +102,8 @@ mod = Module::load(loc, packages, id); dst->insert(id, mod); // id may be different from mod->ident, // if so then insert alias + if (!mod->importedFrom) + mod->importedFrom = sc ? sc->module->importedFrom : Module::rootModule; } if (!pkg) pkg = mod; @@ -115,16 +117,19 @@ { //printf("Import::semantic('%s')\n", toChars()); - load(); + load(sc); if (mod) { +#if 0 if (mod->loc.linnum != 0) { /* If the line number is not 0, then this is not * a 'root' module, i.e. it was not specified on the command line. */ mod->importedFrom = sc->module->importedFrom; + assert(mod->importedFrom); } +#endif if (!isstatic && !aliasId && !names.dim) { @@ -225,7 +230,7 @@ //printf("%s.Import::search(ident = '%s', flags = x%x)\n", toChars(), ident->toChars(), flags); if (!pkg) - load(); + load(NULL); // Forward it to the package/module return pkg->search(loc, ident, flags); diff -uNr gdc-0.21/d/dmd/import.h gdc-0.22/d/dmd/import.h --- gdc-0.21/d/dmd/import.h 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/dmd/import.h 2007-02-03 17:34:12.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -50,7 +50,7 @@ char *kind(); Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees - void load(); + void load(Scope *sc); void semantic(Scope *sc); void semantic2(Scope *sc); Dsymbol *toAlias(); diff -uNr gdc-0.21/d/dmd/inline.c gdc-0.22/d/dmd/inline.c --- gdc-0.21/d/dmd/inline.c 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/dmd/inline.c 2007-02-03 17:34:12.000000000 +0100 @@ -233,6 +233,7 @@ if (declaration->isStructDeclaration() || declaration->isClassDeclaration() || declaration->isFuncDeclaration() || + declaration->isTypedefDeclaration() || declaration->isTemplateMixin()) return COST_MAX; diff -uNr gdc-0.21/d/dmd/mars.c gdc-0.22/d/dmd/mars.c --- gdc-0.21/d/dmd/mars.c 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/dmd/mars.c 2007-02-03 17:34:12.000000000 +0100 @@ -60,7 +60,7 @@ copyright = "Copyright (c) 1999-2007 by Digital Mars"; written = "written by Walter Bright"; - version = "v1.0"; + version = "v1.004"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); @@ -126,7 +126,7 @@ void fatal() { #if 0 - *(char *)0 = 0; + halt(); #endif exit(EXIT_FAILURE); } @@ -154,7 +154,7 @@ Usage:\n\ dmd files.d ... { -switch }\n\ \n\ - files.d D source files\n\ + files.d D source files\n%s\ -c do not link\n\ -cov do code coverage analysis\n\ -D generate documentation\n\ @@ -189,7 +189,13 @@ -version=level compile in version code >= level\n\ -version=ident compile in version code identified by ident\n\ -w enable warnings\n\ -"); +", +#if WIN32 +" @cmdfile read arguments from cmdfile\n" +#else +"" +#endif +); } int main(int argc, char *argv[]) @@ -692,6 +698,9 @@ m = (Module *)modules.data[i]; if (global.params.verbose) printf("parse %s\n", m->toChars()); + if (!Module::rootModule) + Module::rootModule = m; + m->importedFrom = m; m->deleteObjFile(); m->read(0); m->parse(); diff -uNr gdc-0.21/d/dmd/mars.h gdc-0.22/d/dmd/mars.h --- gdc-0.21/d/dmd/mars.h 2006-12-26 22:37:35.000000000 +0100 +++ gdc-0.22/d/dmd/mars.h 2007-02-03 17:34:12.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -25,6 +25,7 @@ #include #define __STDC_FORMAT_MACROS 1 #include +#include #ifdef IN_GCC /* Changes for the GDC compiler by David Friedman */ diff -uNr gdc-0.21/d/dmd/module.c gdc-0.22/d/dmd/module.c --- gdc-0.21/d/dmd/module.c 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/dmd/module.c 2007-02-03 17:34:12.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -42,6 +42,7 @@ ClassDeclaration *Module::moduleinfo; +Module *Module::rootModule; DsymbolTable *Module::modules; Array Module::amodules; @@ -88,7 +89,8 @@ sdtor = NULL; stest = NULL; sfilename = NULL; - importedFrom = this; + root = 0; + importedFrom = NULL; srcfile = NULL; docfile = NULL; @@ -874,6 +876,7 @@ Dsymbol *s = todo[i]; s->semantic(NULL); + //printf("deferred: %s, parent = %s\n", s->toChars(), s->parent->toChars()); } //printf("\tdeferred.dim = %d, len = %d, dprogress = %d\n", deferred.dim, len, dprogress); } while (deferred.dim < len || dprogress); // while making progress diff -uNr gdc-0.21/d/dmd/module.h gdc-0.22/d/dmd/module.h --- gdc-0.21/d/dmd/module.h 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/dmd/module.h 2007-02-03 17:34:12.000000000 +0100 @@ -46,6 +46,7 @@ struct Module : Package { + static Module *rootModule; static DsymbolTable *modules; // symbol table of all modules static Array amodules; // array of all modules static Array deferred; // deferred Dsymbol's needing semantic() run on them @@ -78,6 +79,9 @@ int semanticstarted; // has semantic() been started? int semanticdone; // has semantic() been done? + int root; // != 0 if this is a 'root' module, + // i.e. a module that will be taken all the + // way to an object file Module *importedFrom; // module from command line we're imported from, // i.e. a module that will be taken all the // way to an object file diff -uNr gdc-0.21/d/dmd/mtype.c gdc-0.22/d/dmd/mtype.c --- gdc-0.21/d/dmd/mtype.c 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/dmd/mtype.c 2007-02-03 18:35:36.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -740,6 +740,16 @@ return NULL; } +/*************************************** + * Return !=0 if type has pointers that need to + * be scanned by the GC during a collection cycle. + */ + +int Type::hasPointers() +{ + return FALSE; +} + /* ============================= TypeBasic =========================== */ TypeBasic::TypeBasic(TY ty) @@ -1540,19 +1550,26 @@ FuncDeclaration *fd; Expressions *arguments; int size = next->size(e->loc); + int dup; char *nm; - static char *name[2][2] = { { "_adReverse", "_adDup" }, - { "_adReverseBit", "_adDupBit" } }; + static char *name[2] = { "_adReverse", "_adDupT" }; assert(size); - nm = name[n->ty == Tbit][ident == Id::dup]; - fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), nm, - Type::tvoid->arrayOf(), next->ty != Tbit ? Type::tint32 : NULL); + dup = (ident == Id::dup); + nm = name[dup]; + if (dup) + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), nm, + Type::typeinfo->type, Type::tvoid->arrayOf()); + else + fd = FuncDeclaration::genCfunc(Type::tvoid->arrayOf(), nm, + Type::tvoid->arrayOf(), Type::tint32); ec = new VarExp(0, fd); e = e->castTo(sc, n->arrayOf()); // convert to dynamic array arguments = new Expressions(); + if (dup) + arguments->push(getTypeInfo(sc)); arguments->push(e); - if (next->ty != Tbit) + if (!dup) arguments->push(new IntegerExp(0, size, Type::tint32)); e = new CallExp(e->loc, ec, arguments); e->type = next->arrayOf(); @@ -1637,6 +1654,7 @@ #endif } + /***************************** TypeSArray *****************************/ TypeSArray::TypeSArray(Type *t, Expression *dim) @@ -1904,6 +1922,11 @@ return e; } +int TypeSArray::hasPointers() +{ + return next->hasPointers(); +} + /***************************** TypeDArray *****************************/ TypeDArray::TypeDArray(Type *t) @@ -2042,11 +2065,21 @@ return e; } +int TypeDArray::isZeroInit() +{ + return 1; +} + int TypeDArray::checkBoolean() { return TRUE; } +int TypeDArray::hasPointers() +{ + return TRUE; +} + /***************************** TypeAArray *****************************/ TypeAArray::TypeAArray(Type *t, Type *index) @@ -2264,6 +2297,11 @@ return TRUE; } +int TypeAArray::hasPointers() +{ + return TRUE; +} + /***************************** TypePointer *****************************/ TypePointer::TypePointer(Type *t) @@ -2360,6 +2398,11 @@ return 1; } +int TypePointer::hasPointers() +{ + return TRUE; +} + /***************************** TypeReference *****************************/ @@ -2944,6 +2987,11 @@ return e; } +int TypeDelegate::hasPointers() +{ + return TRUE; +} + /***************************** TypeQualified *****************************/ @@ -3775,6 +3823,10 @@ return (sym->defaultval == 0); } +int TypeEnum::hasPointers() +{ + return toBasetype()->hasPointers(); +} /***************************** TypeTypedef *****************************/ @@ -3972,13 +4024,19 @@ { if (sym->init->isVoidInitializer()) return 1; // initialize voids to 0 - if (sym->init->toExpression()->isBool(FALSE)) + Expression *e = sym->init->toExpression(); + if (e && e->isBool(FALSE)) return 1; return 0; // assume not } return sym->basetype->isZeroInit(); } +int TypeTypedef::hasPointers() +{ + return toBasetype()->hasPointers(); +} + /***************************** TypeStruct *****************************/ TypeStruct::TypeStruct(StructDeclaration *sym) @@ -4238,6 +4296,22 @@ return FALSE; } +int TypeStruct::hasPointers() +{ + StructDeclaration *s = sym; + + sym->size(0); // give error for forward references + if (s->members) + { + for (size_t i = 0; i < s->members->dim; i++) + { + Dsymbol *sm = (Dsymbol *)s->members->data[i]; + if (sm->hasPointers()) + return TRUE; + } + } + return FALSE; +} /***************************** TypeClass *****************************/ @@ -4581,6 +4655,11 @@ return TRUE; } +int TypeClass::hasPointers() +{ + return TRUE; +} + /***************************** TypeTuple *****************************/ TypeTuple::TypeTuple(Arguments *arguments) diff -uNr gdc-0.21/d/dmd/mtype.h gdc-0.22/d/dmd/mtype.h --- gdc-0.21/d/dmd/mtype.h 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/dmd/mtype.h 2007-02-03 17:34:12.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -11,12 +11,14 @@ /* NOTE: This file has been patched from the original DMD distribution to work with the GDC compiler. - Modified by David Friedman, September 2004 + Modified by David Friedman, January 2007 */ #ifndef DMD_MTYPE_H #define DMD_MTYPE_H +#ifndef ENUM_TY_ONLY + #ifdef __DMC__ #pragma once #endif /* __DMC__ */ @@ -52,6 +54,8 @@ #endif struct Symbol; +#endif + enum TY { Tarray, // dynamic array @@ -103,6 +107,8 @@ TMAX }; +#ifndef ENUM_TY_ONLY + #define Tascii Tchar extern int Tsize_t; @@ -246,6 +252,7 @@ virtual int builtinTypeInfo(); virtual Type *reliesOnTident(); virtual Expression *toExpression(); + virtual int hasPointers(); static void error(Loc loc, const char *format, ...); @@ -323,6 +330,7 @@ MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Array *atypes); TypeInfoDeclaration *getTypeInfoDeclaration(); Expression *toExpression(); + int hasPointers(); type *toCtype(); type *toCParamtype(); @@ -341,11 +349,13 @@ void toPrettyBracket(OutBuffer *buf, HdrGenState *hgs); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); int isString(); + int isZeroInit(); int checkBoolean(); int implicitConvTo(Type *to); Expression *defaultInit(); int builtinTypeInfo(); TypeInfoDeclaration *getTypeInfoDeclaration(); + int hasPointers(); type *toCtype(); }; @@ -366,6 +376,7 @@ MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Array *atypes); int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); + int hasPointers(); // Back end Symbol *aaGetSymbol(char *func, int flags); @@ -385,6 +396,7 @@ Expression *defaultInit(); int isZeroInit(); TypeInfoDeclaration *getTypeInfoDeclaration(); + int hasPointers(); type *toCtype(); }; @@ -443,6 +455,7 @@ int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); Expression *dotExp(Scope *sc, Expression *e, Identifier *ident); + int hasPointers(); type *toCtype(); }; @@ -528,6 +541,7 @@ dt_t **toDt(dt_t **pdt); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Array *atypes); TypeInfoDeclaration *getTypeInfoDeclaration(); + int hasPointers(); type *toCtype(); }; @@ -557,6 +571,7 @@ int isZeroInit(); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Array *atypes); TypeInfoDeclaration *getTypeInfoDeclaration(); + int hasPointers(); type *toCtype(); }; @@ -592,6 +607,7 @@ dt_t **toDt(dt_t **pdt); MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Array *atypes); TypeInfoDeclaration *getTypeInfoDeclaration(); + int hasPointers(); type *toCtype(); type *toCParamtype(); @@ -619,6 +635,7 @@ int isauto(); int checkBoolean(); TypeInfoDeclaration *getTypeInfoDeclaration(); + int hasPointers(); type *toCtype(); @@ -682,4 +699,6 @@ extern int Tsize_t; extern int Tptrdiff_t; +#endif + #endif /* DMD_MTYPE_H */ diff -uNr gdc-0.21/d/dmd/struct.c gdc-0.22/d/dmd/struct.c --- gdc-0.21/d/dmd/struct.c 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/dmd/struct.c 2007-02-03 17:34:12.000000000 +0100 @@ -406,7 +406,7 @@ { Dsymbol *s = (Dsymbol *)fields.data[i]; VarDeclaration *vd = s->isVarDeclaration(); - if (vd) + if (vd && !vd->isDataseg()) { if (vd->init) { diff -uNr gdc-0.21/d/dmd/template.c gdc-0.22/d/dmd/template.c --- gdc-0.21/d/dmd/template.c 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/dmd/template.c 2007-02-03 17:34:12.000000000 +0100 @@ -2254,6 +2254,7 @@ #endif this->havetempdecl = 0; this->isnested = 0; + this->errors = 0; } @@ -2278,6 +2279,7 @@ #endif this->havetempdecl = 1; this->isnested = 0; + this->errors = 0; assert((size_t)tempdecl->scope > 0x10000); } @@ -2497,8 +2499,6 @@ } else { Module *m = sc->module->importedFrom; - while (m->loc.linnum != 0 && m != m->importedFrom) - m = m->importedFrom; //printf("\t2: adding to module %s\n", m->toChars()); a = m->members; if (m->semanticdone >= 3) @@ -2617,6 +2617,17 @@ #endif #endif + /* If any of the instantiation members didn't get semantic() run + * on them due to forward references, we cannot run semantic2() + * or semantic3() yet. + */ + for (size_t i = 0; i < Module::deferred.dim; i++) + { Dsymbol *sd = (Dsymbol *)Module::deferred.data[i]; + + if (sd->parent == this) + goto Laftersemantic; + } + /* The problem is when to parse the initializer for a variable. * Perhaps VarDeclaration::semantic() should do it like it does * for initializers inside a function. @@ -2634,6 +2645,7 @@ semantic3(sc2); } + Laftersemantic: sc2->pop(); scope->pop(); @@ -2642,6 +2654,7 @@ if (global.errors != errorsave) { error("error instantiating"); + errors = 1; if (global.gag) tempdecl->instances.remove(tempdecl_instance_idx); } @@ -3157,7 +3170,7 @@ #if LOG printf("+TemplateInstance::semantic2('%s')\n", toChars()); #endif - if (members) + if (!errors && members) { sc = tempdecl->scope; assert(sc); @@ -3189,7 +3202,7 @@ if (semanticdone >= 3) return; semanticdone = 3; - if (members) + if (!errors && members) { sc = tempdecl->scope; sc = sc->push(argsym); @@ -3210,7 +3223,7 @@ #if LOG printf("TemplateInstance::toObjFile('%s', this = %p)\n", toChars(), this); #endif - if (members) + if (!errors && members) { for (i = 0; i < members->dim; i++) { @@ -3226,7 +3239,7 @@ #if LOG printf("TemplateInstance::inlineScan('%s')\n", toChars()); #endif - if (members) + if (!errors && members) { for (i = 0; i < members->dim; i++) { @@ -3719,6 +3732,21 @@ return Dsymbol::oneMember(ps); } +int TemplateMixin::hasPointers() +{ + //printf("TemplateMixin::hasPointers() %s\n", toChars()); + for (size_t i = 0; i < members->dim; i++) + { + Dsymbol *s = (Dsymbol *)members->data[i]; + //printf(" s = %s %s\n", s->kind(), s->toChars()); + if (s->hasPointers()) + { + return 1; + } + } + return 0; +} + char *TemplateMixin::toChars() { OutBuffer buf; diff -uNr gdc-0.21/d/dmd/template.h gdc-0.22/d/dmd/template.h --- gdc-0.21/d/dmd/template.h 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/dmd/template.h 2007-02-03 17:34:12.000000000 +0100 @@ -240,6 +240,7 @@ int nest; // for recursion detection int havetempdecl; // 1 if used second constructor int isnested; // if referencing local symbols + int errors; // 1 if compiled with errors #ifdef IN_GCC /* On some targets, it is necessary to know whether a symbol will be emitted in the output or not before the symbol @@ -290,6 +291,7 @@ void inlineScan(); char *kind(); int oneMember(Dsymbol **ps); + int hasPointers(); char *toChars(); void toCBuffer(OutBuffer *buf, HdrGenState *hgs); diff -uNr gdc-0.21/d/dmd/tocsym.c gdc-0.22/d/dmd/tocsym.c --- gdc-0.21/d/dmd/tocsym.c 2006-12-26 22:37:35.000000000 +0100 +++ gdc-0.22/d/dmd/tocsym.c 2007-02-03 17:34:12.000000000 +0100 @@ -552,6 +552,23 @@ return sinit; } +Symbol *TypedefDeclaration::toInitializer() +{ + Symbol *s; + Classsym *stag; + + if (!sinit) + { + stag = fake_classsym(NULL); + s = toSymbolX("__init", SCextern, stag->Stype, "Z"); + s->Sfl = FLextern; + s->Sflags |= SFLnodebug; + slist_add(s); + sinit = s; + } + return sinit; +} + /****************************************** */ diff -uNr gdc-0.21/d/dmd/todt.c gdc-0.22/d/dmd/todt.c --- gdc-0.21/d/dmd/todt.c 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/dmd/todt.c 2007-02-03 17:34:12.000000000 +0100 @@ -569,7 +569,7 @@ integer_t dim; #ifndef IN_GCC - pdt = dtnbytes(pdt, len * sz, (char *)string); + pdt = dtnbytes(pdt, len * sz, (const char *)string); #else pdt = dtnwords(pdt, len, string, sz); #endif diff -uNr gdc-0.21/d/dmd/toobj.c gdc-0.22/d/dmd/toobj.c --- gdc-0.21/d/dmd/toobj.c 2006-12-26 22:37:35.000000000 +0100 +++ gdc-0.22/d/dmd/toobj.c 2007-02-03 18:35:36.000000000 +0100 @@ -407,6 +407,7 @@ void *invariant; // class invariant uint flags; void *deallocator; + OffsetTypeInfo[] offTi; } */ dt_t *dt = NULL; @@ -467,7 +468,23 @@ dtdword(&dt, 0); // flags - dtdword(&dt, com); + int flags = 4 | com; + for (ClassDeclaration *cd = this; cd; cd = cd->baseClass) + { + if (cd->members) + { + for (size_t i = 0; i < cd->members->dim; i++) + { + Dsymbol *sm = (Dsymbol *)cd->members->data[i]; + //printf("sm = %s %s\n", sm->kind(), sm->toChars()); + if (sm->hasPointers()) + goto L2; + } + } + } + flags |= 2; // no pointers + L2: + dtdword(&dt, flags); // deallocator @@ -476,6 +493,10 @@ else dtdword(&dt, 0); + // offTi[] + dtdword(&dt, 0); + dtdword(&dt, 0); // null for now, fix later + ////////////////////////////////////////////// // Put out vtblInterfaces->data[]. Must immediately follow csym, because @@ -857,11 +878,15 @@ dtdword(&dt, 0); // flags - dtdword(&dt, com); + dtdword(&dt, 4 | com); // deallocator dtdword(&dt, 0); + // offTi[] + dtdword(&dt, 0); + dtdword(&dt, 0); // null for now, fix later + ////////////////////////////////////////////// // Put out vtblInterfaces->data[]. Must immediately follow csym, because @@ -912,14 +937,20 @@ { // Generate static initializer toInitializer(); +#if 0 + sinit->Sclass = SCcomdat; +#else if (parent && parent->isTemplateInstance()) sinit->Sclass = SCcomdat; else sinit->Sclass = SCglobal; +#endif sinit->Sfl = FLdata; toDt(&sinit->Sdt); #if !ELFOBJ + /* For OMF, common blocks aren't pulled in from the library. + */ /* ELF comdef's generate multiple * definition errors for them from the gnu linker. * Need to figure out how to generate proper comdef's for ELF. @@ -1125,6 +1156,33 @@ toDebug(); type->getTypeInfo(NULL); // generate TypeInfo + + TypeTypedef *tc = (TypeTypedef *)type; + if (type->isZeroInit() || !tc->sym->init) + ; + else + { + enum_SC scclass = SCglobal; + for (Dsymbol *parent = this->parent; parent; parent = parent->parent) + { + if (parent->isTemplateInstance()) + { + scclass = SCcomdat; + break; + } + } + + // Generate static initializer + toInitializer(); + sinit->Sclass = scclass; + sinit->Sfl = FLdata; +#if ELFOBJ // Burton + sinit->Sseg = CDATA; +#endif /* ELFOBJ */ + if (! sinit->Sdt) + sinit->Sdt = tc->sym->init->toDt(); + outdata(sinit); + } } /* ================================================================== */ diff -uNr gdc-0.21/d/dmd/typinf.c gdc-0.22/d/dmd/typinf.c --- gdc-0.21/d/dmd/typinf.c 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/dmd/typinf.c 2007-02-03 17:34:12.000000000 +0100 @@ -1,6 +1,6 @@ // Compiler implementation of the D programming language -// Copyright (c) 1999-2006 by Digital Mars +// Copyright (c) 1999-2007 by Digital Mars // All Rights Reserved // written by Walter Bright // www.digitalmars.com @@ -128,12 +128,12 @@ if (sc) // if in semantic() pass { // Find module that will go all the way to an object file Module *m = sc->module->importedFrom; - while (m != m->importedFrom) - m = m->importedFrom; m->members->push(t->vtinfo); } else // if in obj generation pass + { t->vtinfo->toObjFile(); + } } } e = new VarExp(0, t->vtinfo); @@ -233,6 +233,7 @@ /* Put out: * TypeInfo base; * char[] name; + * void[] m_init; */ sd->basetype->getTypeInfo(NULL); @@ -242,6 +243,18 @@ size_t namelen = strlen(name); dtdword(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); + + // void[] init; + if (tinfo->isZeroInit() || !sd->init) + { // 0 initializer, or the same as the base type + dtdword(pdt, 0); // init.length + dtdword(pdt, 0); // init.ptr + } + else + { + dtdword(pdt, sd->type->size()); // init.length + dtxoff(pdt, sd->toInitializer(), 0, TYnptr); // init.ptr + } } void TypeInfoEnumDeclaration::toDt(dt_t **pdt) @@ -372,11 +385,12 @@ /* Put out: * char[] name; - * byte[] init; + * void[] init; * hash_t function(void*) xtoHash; * int function(void*,void*) xopEquals; * int function(void*,void*) xopCmp; * char[] function(void*) xtoString; + * uint m_flags; */ char *name = sd->toPrettyChars(); @@ -384,7 +398,7 @@ dtdword(pdt, namelen); dtabytes(pdt, TYnptr, 0, namelen + 1, name); - // byte[] init; + // void[] init; dtdword(pdt, sd->structsize); // init.length if (sd->zeroInit) dtdword(pdt, 0); // NULL for 0 initialization @@ -479,6 +493,9 @@ } else dtdword(pdt, 0); + + // uint m_flags; + dtdword(pdt, tc->hasPointers()); } void TypeInfoClassDeclaration::toDt(dt_t **pdt) diff -uNr gdc-0.21/d/dmd-script gdc-0.22/d/dmd-script --- gdc-0.21/d/dmd-script 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/dmd-script 2007-02-03 20:56:13.000000000 +0100 @@ -87,6 +87,7 @@ -Dffilename write documentation file to filename -d allow deprecated features -f... pass an -f... option to gdc + -framework ... pass a -framework ... option to gdc -debug compile in debug code -debug=level compile in debug code <= level -debug=ident compile in debug code identified by ident @@ -144,7 +145,7 @@ sub argCheck($$) { my ($name,$arg) = @_; - errorExit "argument expected for switch '$'" unless defined $arg; + errorExit "argument expected for switch '$name'" unless defined $arg; } my $arg_i = 0; @@ -180,12 +181,14 @@ } elsif ( $arg =~ m/^-H$/ ) { push @out, '-fintfc'; } elsif ( $arg =~ m/^-Hd(.*)$/ ) { - push @out, '-fintfc-dir=$1'; + push @out, "-fintfc-dir=$1"; } elsif ( $arg =~ m/^-Hf(.*)$/ ) { - push @out, '-fintfc-file=$1'; + push @out, "-fintfc-file=$1"; } elsif ( $arg eq '--help' ) { printUsage; exit 0; + } elsif ($arg eq '-framework' ) { + push @link_out, '-framework', $ARGV[$arg_i++]; } elsif ( $arg =~ m/^-inline$/ ) { push @out, '-finline-functions'; } elsif ( $arg =~ m/^-I(.*)$/ ) { diff -uNr gdc-0.21/d/d-objfile.cc gdc-0.22/d/d-objfile.cc --- gdc-0.21/d/d-objfile.cc 2006-12-26 00:35:46.000000000 +0100 +++ gdc-0.22/d/d-objfile.cc 2007-02-03 20:56:13.000000000 +0100 @@ -213,7 +213,7 @@ static bool warned = false; if (! warned) { warned = true; - ::warning("system does not support one-only linkage"); + ::warning(0, "system does not support one-only linkage"); } } } @@ -475,34 +475,22 @@ assert( ! POINTER_TYPE_P( t ) ); TYPE_CONTEXT( t ) = DECL_CONTEXT( decl ); - -#if D_GCC_VER < 40 - // In 4.0, causes errors in dwarf2out.c:splice_child_die... - - /* The following dance is needed to make typedefs work for DWARF 2. - C and C++ do this different ways. The C version crashes for dbx (when - member functions are involved) and I can't get the C++ way to work. - So here's a third way. */ - if (1) { - tree t_clone = build_type_copy( t ); - TYPE_MAIN_VARIANT(t_clone) = t_clone; - TYPE_NEXT_VARIANT(t_clone) = NULL_TREE; - TYPE_NEXT_VARIANT( t ) = NULL_TREE; - - tree clone_stub = build_decl(TYPE_DECL, NULL_TREE, t_clone); - - DECL_CONTEXT( clone_stub ) = DECL_CONTEXT( decl ); - // TREE_CHAIN( clone_stub ) = decl; // not needed? - - TYPE_STUB_DECL( t_clone ) = clone_stub; - - // rest_of_type_compilation(t_clone, 1); // not needed? - DECL_ORIGINAL_TYPE( decl ) = t_clone; - } -#endif - TYPE_NAME( t ) = decl; - TYPE_STUB_DECL( t ) = decl; + switch (TREE_CODE(t)) + { + case ENUMERAL_TYPE: + case RECORD_TYPE: + case UNION_TYPE: + /* Not sure if there is a need for separate TYPE_DECLs in + TYPE_NAME and TYPE_STUB_DECL. */ + TYPE_STUB_DECL( t ) = build_decl(TYPE_DECL, DECL_NAME(decl), t); + // g++ does this and the debugging code assumes it: + DECL_ARTIFICIAL( TYPE_STUB_DECL( t ) ) = 1; + break; + default: + // nothing + break; + } } } @@ -511,7 +499,7 @@ { bool top_level = DECL_CONTEXT(decl) == fileContext || ! DECL_CONTEXT(decl); - if (top_level) + //EXPER//always nyan//if (top_level) rodc(decl, top_level); } @@ -809,7 +797,7 @@ TREE_STATIC( t_var ) = 1; if (sym->Sseg == CDATA) { TREE_CONSTANT( t_var ) = TREE_CONSTANT( t_ini ) = 1; - TREE_READONLY( t_var ) = TREE_CONSTANT( t_var ) = 1; + TREE_READONLY( t_var ) = TREE_READONLY( t_ini ) = 1; } // %% need to check SCcomdat? @@ -820,7 +808,7 @@ } return sym->Stree; } - + static tree dt2node(dt_t * dt) @@ -863,7 +851,7 @@ static tree dt2tree(dt_t * dt) { - ListMaker elts; + CtorEltMaker elts; ListMaker fields; tree offset = size_zero_node; @@ -943,7 +931,7 @@ void obj_includelib(char *name) { - ::warning("pragma(lib) not implemented"); + d_warning(OPT_Wunknown_pragmas, "pragma(lib) not implemented"); } void @@ -973,9 +961,11 @@ dkeep(our_mod_ref); tree init = make_node(CONSTRUCTOR); + CtorEltMaker ce; TREE_TYPE( init ) = mod_ref_type; - CONSTRUCTOR_ELTS( init ) = tree_cons(f0, d_null_pointer, - tree_cons(f1, gen.addressOf(sym->Stree), NULL_TREE)); + ce.cons(f0, d_null_pointer); + ce.cons(f1, gen.addressOf(sym->Stree)); + CONSTRUCTOR_ELTS( init ) = ce.head; TREE_STATIC( init ) = 1; DECL_ARTIFICIAL( our_mod_ref ) = 1; TREE_PRIVATE( our_mod_ref ) = 1; diff -uNr gdc-0.21/d/gcc-mars.cc gdc-0.22/d/gcc-mars.cc --- gdc-0.21/d/gcc-mars.cc 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/gcc-mars.cc 2007-02-03 18:35:36.000000000 +0100 @@ -35,7 +35,7 @@ copyright = "Copyright (c) 1999-2007 by Digital Mars"; written = "written by Walter Bright"; - version = "v0.100"; + version = "v0.104"; global.structalign = 8; memset(¶ms, 0, sizeof(Param)); diff -uNr gdc-0.21/d/GDC.html gdc-0.22/d/GDC.html --- gdc-0.21/d/GDC.html 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/GDC.html 2007-02-06 05:30:00.000000000 +0100 @@ -2,47 +2,87 @@ + + + + - D Front End for GCC + + + D Front End for GCC -

D Front End for GCC - Release 0.21
+ + +

D Front End for GCC - Release 0.22
+ +

-Last update: January 2, 2007
+ + +Last update: February 5, 2007
+ +

Supported Systems

+ +
    -
  • GCC 3.3.x, 3.4.x, 4.0.x
    + + +
  • GCC 3.4.x, 4.0.x, 4.1.x
    + +
  • + +
  • Linux (tested on Fedora Core 5 x86 and PowerPC)
    + +
  • + +
  • Mac OS X 10.3.9, 10.4.x
    + +
  • + +
  • FreeBSD 6.x
  • + +
  • Cygwin
  • + +
  • MinGW
  • + +
  • AIX (tested on 5.1)
  • + +
+ + Similar versions of the above systems should work and other Unix platforms may work.  @@ -50,83 +90,147 @@ probably work on most 32-bit architectures, the D runtime library will still need to be updated to support them.
+ +

Requirements

+ + The MacOS X universal binary package requires XCode 2.4.1 or the equivalent version of cctools.

Downloads

+ + + +

Links

+ + + +

Contact

+ + David Friedman
+ + e-mail: dvdfrdmn <at> users.sf.net
+ +

Status
+ +

+ +

Known Issues

+ +
    + +
  • See the DStress page for known failing cases.
    + +
  • + +
  • Debugging information may have a few problems. To enable D name mangling in gdb, apply this patch.
    + +
  • + +
  • Some targets do not support once-only linking. A workaround is to manually control template emission. See the -femit-templates @@ -135,38 +239,70 @@ no problems with the stock GCC 4.x on Darwin.
    + +
  • + + + +
      + + + +
    + +
  • Complex floating point operations may not work the same as DMD.
  • + +
  • Some math functions behave differently due to different implementations of the extended floating-point type.
  • + +
  • Volatile statements may not always do the right thing.
  • + +
  • Because of a problem on AIX, the linker will pull in more modules than needed.
    + +
  • + +
  • Some C libraries (Cygwin, MinGW, AIX) don't handle floating-point formatting and parsing in a standard way.
    + +
  • + +
+ +

Known Differences from DMD

+ +
    + +
  • The type of _argptr in variadic functions is the target-specific va_list type.  The only @@ -177,425 +313,799 @@ pointer to data an expect it to work.
    + +
  • + +
  • In assembler code, direct access to parameters in naked functions works differently.  Frame relative addressing through [ESP+4] does work the same way.
    + +
  • + +
  • Currently, GDC uses the C calling convention for all functions except those declared extern (Windows).
  • -
  • GDC allows catches in try + + +
  • GDC allows catch statements in finally blocks.
  • + +
  • pragma(lib) is not supported.
  • + +
  • Some targets do not have a distinct extended floating-point type.  On these targets, real and double are the same size.
  • + +
  • On Win32, GDC allocates 12 bytes for the real type, while DMD allocates 10 bytes. This also applies to the components of the creal type.
    + +
  • + +
+ +

Inline Assembler Notes

+ +
    + +
  • Getting GCC to respect the "naked" attribute is difficult.  It is recommended that you use only assembler statements in a naked function.
  • + +
  • Jumps from assembler statements will not run cleanups (auto and finally)
  • + +
+ +

Usage

+ +

Invoking gdc and gdmd

+ + The compiler driver is named 'gdc' and accepts the standard GCC options.  There is also a script named 'gdmd' which has the same interface as the Digital Mars dmd.
+ +
+ + The mapping from DMD options to GCC is as follows:
+ + + + + + - - - - - + + + + - - - - - - + + + + - - - + - - - + - - - - + - - + - - - + - - - - + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-c
-
-c
+ +
-D
+
-c
-
-fdoc
-Dd<docdir>
-
-fdoc-dir=<docdir>
+
-D
+ +
-Df<filename>
+
-fdoc
-
-fdoc-file=<filename>
-d-fdeprecated
-Dd<docdir>
-
-debug[=<arg>]
-fdebug[=<arg>]
-
-fdoc-dir=<docdir>
-
-g
-g
-
-inline
-
-finline-functions
-
-Df<filename>
-
-I<path>
-I -<path>
-
-fdoc-file=<filename>
-
-L<arg>
-Wl,<arg>
-
-O
-
-O3 without -inlining (may not be -equivalent)
-
-d
-o-
-
-fdeprecated-fsyntax-only
-
-debug[=<arg>]
+ + + +
-fdebug[=<arg>]
+ + + +
-g
+ + + +
-g
+ + + +
-inline
+ + + +
-finline-functions
+ + + +
-I<path>
+ + + +
-I +<path>
+ + + +
-L<arg>
+ + + +
-Wl,<arg>
+ + + +
-O
+ + + +
-O3 without +inlining (may not be +equivalent)
+ + + +
-o-
+ + + +
-fsyntax-only
+ + + +
-od<dir>
+ +
no equivalent; use the wrapper script
+ +
-of<file>-o <file>
+ +
-op<dir>
+ +
no equivalent; use the wrapper script
+ +
-profile
+ +
(see the GCC manual for profiling options)
-quiet
+ +
no equivalent
+ +
-release
+ +
-frelease
+ +
-run
+ +
no equivalent; use the wrapper script
-unittest
+ +
-funittest
+ +
-version=<arg>
+ +
-fversion=<arg>
+ +
-w
+ +
-Wall
+ +
<.ddoc file>
+ +
-fdoc-inc=<.ddoc file>
+ +
+ +
+ + Other options:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
-f[no-]bounds-check
+ +
Controls array bounds checking
+ +
-femit-templates[=normal|private|all|none|auto]
+ + -f[no-]emit-templates
+ +
Controls whether or not template code is emitted.
+ +
+ + "normal" -- Emit templates, expecting multiple copies to be merged by the linker.
+ + "private" -- Emit templates, but make them private to the translation unit.  The executable will have multiple copies of code and data.
+ + "all" -- Emit all template instances with public visibility.  Do this even if they would not normally be emitted.
+ + "none" -- Do not emit templates at all.
+ + "auto" -- For targets that support templates, the "full" mode is used.  Otherwise, the "private" mode is used.
+ +
+ + "none" and -fno-emit-templates are synonyms.
+ + "auto" and -femit-templates are synonyms.
+ +
-fall-sources
+ +
For each source file on the command line, semantically process each file preceding it.  @@ -604,68 +1114,158 @@ compilation errors occur due to complicated circular module references.  This will slow compilation noticeably.
+ +
-fdump-source
+ +
Dump decoded UTF-8 text and source from HTML to <source>.utf-8 and <source>.d.utf-8.
+ +
+ +

Extensions

+ +
Extended Assembler
+ + GDC implements a GCC extension that allows inline assembler with D expression operands.  It is available on nearly all targets, not just i386.  The syntax differs from the C language extension in the follow ways.
    + +
  • Statements start with 'asm { ...', just like the regular DMD inline assembler.
  • + +
  • It is not necesary to put parentheses around operands.
  • + +
  • Instruction templates can be compile-time string constants, not just string literals.  If the template is not a string literal, use parenthesis to indicate that it is not an opcode.
  • + +
+ + Unlike i386 inline assembler statements, extended assembler statements do not prevent a function from being inlined.
+ +
+ + See the GCC manual for more information about this extension.
+ +
+ + Example:
+ +
+ +
uint invert(uint v)
+ + {
+ +     uint result;
+ +     version(X86)
+ +        asm{ "notl %[iov]" : [iov] "=r" result : "0" v; }
+ +     else version(PPC)
+ +        asm{ "nor %[oresult],%[iv],%[iv]" : [oresult] "=r" result : [iv] "r" v; }
+ +     return result;
+ + }
+ +
+ +
Declaration and Type Attributes
+ + (This extension is a work in progress.)
+ +
+ + GDC implements the GCC __attribute__ extension with two pragmas:
+ +
+ + pragma(GNU_attribute, name1(arg1, arg2, ...), ...) declarations...
+ +
+ + pragma(GNU_set_attribute, symbol, name1(arg1, arg2...), ...);
+ +
+ + If an attribute has no arguments, the argument list may be omitted.
+ +
+ + The first form applies to declarations directly contained in the pragma.  The second form affects the given symbol.  See the GCC manual for a list of attributes that can be set.  Not all @@ -674,401 +1274,880 @@ for example) is not well defined.

Changes

+ + +0.22: +
    +
  • Added support for GCC 4.1.x
  • +
  • Support for GCC 3.3.x is deprecated
  • +
  • Updated to DMD 1.004
  • +
  • Fixed Bugzilla 836, 837, 838, 839, 841, 843, 844, 889, 896
  • +
  • Fixed problems with missing debug information
  • +
  • Added Rick Mann's -frameowrk patch for gdmd
  • +
0.21:
    + +
  • Updated to DMD 1.00
  • + +
  • Fixed Bugzilla 695, 696, 737, 738, 739, 742, 743, 745
  • + +
  • Implemented GCC extended assembler
  • + +
  • Implemented basic support for GCC attributes
  • + +
+ + 0.20:
    + +
  • Updated to DMD 0.177
  • + +
  • Fixes for synchronized code generation
  • + +
  • Better support for cross-hosted builds
  • + +
  • Fixed Bugzilla 307, 375, 403, 575, 578
  • + +
  • Applied Anders Björklund's MacOS X build patches
  • + +
+ + 0.19:
    + +
  • Fixed D Bugzilla bugs 141(gdc), 157, 162, 164, 171, 174, 175, 192, 229
  • + +
  • Applied Dave Fladebo's suggestion for -O3 in gdmd
  • + +
  • Updated to DMD 0.162
  • + +
  • The version symbol for FreeBSD is now "freebsd"
  • + +
  • Enabled std.loader for FreeBSD
  • + +
  • Implement offsetof in assembler
  • + +
  • Support building with Apple's GCC (4.0 only)
  • + +
  • Fix parallel builds
  • + +
+ + 0.18:
+ +
    + +
  • Fixes
  • + + + +
      + +
    • ICE on assignment arithmetic
    • + +
    • Problems mixing D and assembler floating point operations
    • + +
    • Mac OS X 10.2 build problems
    • + +
    • The gdc driver no longer compiles C source as C++.
      + +
    • + +
    • Many others...
    • + + + +
    + +
  • Improvements
  • + + + +
      + +
    • Updated to DMD 0.157.
    • + +
    • Added support for PowerPC Linux.
      + +
    • + +
    • Added partial support for SkyOS.
    • + +
    • Compiler can be relocated to another directory.
      + +
    • + + + +
    + +
+ + 0.17:
+ +
    + +
  • Fixes
  • + + + +
      + +
    • Mixed complex/float operations on GCC 4.0 (D.gnu/1485)
    • + +
    • Applied Thomas Kuhne's HTML line number fix
    • + +
    • Foreach/nested functions in templates (D.gnu/1514)
    • + +
    • Use correct default initializer when allocating arrays of typedef'd types
    • + +
    • Recursive calls to nested functions (D.gnu/1525)
    • + + + +
    + +
  • Improvements
  • + + + +
      + +
    • Updated to DMD 0.140
      + +
    • + + + +
    + +
+ + 0.16:
+ +
    + +
  • Fixes
  • + + + +
      + +
    • Concatenating a array and single element
    • + +
    • "__arrayArg already defined"
    • + +
    • ICE on nested foreach statements (D.gnu/1393)
    • + +
    • Inline assembler
    • + + + +
        + +
      • Functions returning floating point types
      • + + + +
      + + + +
        + +
      • Spurious error on scaled register without a base register
      • + +
      • Access to locals by var+ofs[EBP] now works with optimization.
      • + +
      • Can now guess operand size from referenced variables.
      • + + + +
      + +
    • Thunks errors with reimplemented interfaces (e.g., Mango)
      + +
    • + + + +
    + +
  • Improvements
  • + + + +
      + +
    • Support GCC 4.0.x
    • + +
    • Updated to DMD 0.137
    • + +
    • Support DW_LANG_D for DWARF debugging
    • + +
    • Support compiling multiple sources to a single object with GCC 3.4.x.
      + +
    • + + + +
    + +
+ +
+ + 0.15:
+ +
    Updated to DMD 0.128
+ +
+ +
+ + 0.14:
+ +
    + +
  • Fixes
  • + + + +
      + +
    • Classes nested in functions actually work now.
    • + +
    • Fix for newest versions of the GNU assembler.
      + +
    • + + + +
    + +
  • Improvements
  • + + + +
      + +
    • Updated to DMD 0.127
      + +
    • + + + +
    + +
+ +
+ + 0.13:
+ +
    + +
  • Fixes
  • + + + +
      + +
    • Cygwin/MinGW assembler problem
    • + + + +
    + +
  • Improvements
  • + + + +
      + +
    • Updated to DMD 0.126.
    • + +
    • Calling nested functions with delegates is faster.
    • + +
    • The "check-target-libphobos" uses unit tests and runtime checks.
      + +
    • + + + +
    + +
+ + 0.12.1:
+ +
    + +
  • Fixes
  • + + + +
      + +
    • Compilation errors and crashes with -fpic
    • + +
    • Crashes with interfaces on Cygwin/MinGW
    • + +
    • Support the -mno-cygwin option
      + +
    • + + + +
    + +
+ + 0.12:
+ +
    + +
  • Fixes
  • + + + +
      + +
    • Various problems building MinGW in MSYS
    • + +
    • Mango "endless output"
    • + +
    • Build problems with gcc 3.4.1
    • + +
    • Various problems revealed by dmdscript
      + +
    • + +
    • Error message now go to standard error
    • + +
    • DStress catch_01, catch_02, new_04, switch_19, throw_02, and others.
    • + + + +
    + +
  • Improvements
  • + + + +
      + +
    • Updated to DMD 0.125
    • + +
    • New target: AIX
    • + +
    • GDC and DMD versions are reported with "gcc --version"
    • + +
    • Take advantage of DMD template improvements on
      + +
    • + + + +
    + +
  • Changes
  • + + + +
      + +
    • std.c.unix is now std.c.unix.unix
    • + +
    • The runtime library is now "libgphobos" to avoid conflicts with DMD.
    • + +
    • The dmd wrapper script...
    • + + + +
        + +
      • Is now named "gdmd".
      • + +
      • Looks for gdc in its own directory instead of searching the path
      • + +
      • Requires a comma after the "-q" option.
        + +
      • + + + +
      + + + +
    + +
+ + 0.11:
+ +
    + +
  • Fixes
  • + + + +
      + +
    • Reversed structure compare
    • + +
    • Correct meaning of '-L' option in wrapper script
    • + +
    • Static data GC bug on Linux
    • + + + +
    + +
  • Improvements
  • + + + +
      + +
    • Updated to DMD 0.121
    • + +
    • New target: MingGW
    • + +
    • Included Anders F Björklund's man pages.
      + +
    • + +
    • It is now possible to build a cross-compiler.  Only MingGW is supported out-of-the-box, however.
    • + + + +
    + +
+ +

License

+ +     This program is free software; you can redistribute it and/or modify
+ +     it under the terms of the GNU General Public License as published by
+ +     the Free Software Foundation; either version 2 of the License, or
+ +     (at your option) any later version.
+ +
+ +     This program is distributed in the hope that it will be useful,
+ +     but WITHOUT ANY WARRANTY; without even the implied warranty of
+ +     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ +     GNU General Public License for more details.
+ +
+ +     You should have received a copy of the GNU General Public License
+ +     along with this program; if not, write to the Free Software
+ +     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ + diff -uNr gdc-0.21/d/gdc-version gdc-0.22/d/gdc-version --- gdc-0.21/d/gdc-version 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/gdc-version 2007-02-06 05:30:00.000000000 +0100 @@ -1 +1 @@ -gdc 0.21, using dmd 1.00 +gdc 0.22, using dmd 1.004 diff -uNr gdc-0.21/d/History gdc-0.22/d/History --- gdc-0.21/d/History 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/History 2007-02-06 05:30:00.000000000 +0100 @@ -1,3 +1,11 @@ +0.22: + * Added support for GCC 4.1.x + * Support for GCC 3.3.x is deprecated + * Updated to DMD 1.004 + * Fixed Bugzilla 836, 837, 838, 839, 841, 843, 844, 889, 896 + * Fixed problems with missing debug information + * Added Rick Mann's -frameowrk patch for gdmd + 0.21: * Updated to DMD 1.00 * Fixed Bugzilla 695, 696, 737, 738, 739, 742, 743, 745 diff -uNr gdc-0.21/d/INSTALL gdc-0.22/d/INSTALL --- gdc-0.21/d/INSTALL 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/INSTALL 2007-01-31 01:52:39.000000000 +0100 @@ -2,7 +2,7 @@ Required source packages - * The "core" package of a recent GCC 3.3.x, 3.4.x, or 4.0.x release. + * The "core" package of a recent GCC 3.4.x, 4.0.x, or 4.1.x release. * The GDC source package. Required software diff -uNr gdc-0.21/d/INSTALL.html gdc-0.22/d/INSTALL.html --- gdc-0.21/d/INSTALL.html 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/INSTALL.html 2007-01-31 01:52:39.000000000 +0100 @@ -18,7 +18,7 @@
    -
  • The "core" package of a recent GCC 3.3.x, 3.4.x, or 4.0.x +
  • The "core" package of a recent GCC 3.4.x, 4.0.x, or 4.1.x release.
  • @@ -73,22 +73,7 @@
  • Unpack the gdc archive.  This will create a subdirectory named "d".
  • -
  • CUpdated to DMD 0.177
    -Fixes for synchronized code generation
    -Better support for cross-hosted builds
    -Fixed Bugzilla 307, 375, 403, 575, 578
    -Applied Anders Björklund's MacOS X build patches
    -Updated to DMD 0.177
    -Fixes for synchronized code generation
    -Better support for cross-hosted builds
    -Fixed Bugzilla 307, 375, 403, 575, 578
    -Applied Anders Björklund's MacOS X build Updated to DMD 0.177
    -Fixes for synchronized code generation
    -Better support for cross-hosted builds
    -Fixed Bugzilla 307, 375, 403, 575, 578
    -Applied Anders Björklund's MacOS X build patches
    -patches
    -hange back to <srcdir> and run the setup script:
    +
  • Change back to <srcdir> and run the setup script:

    diff -uNr gdc-0.21/d/Make-lang.in gdc-0.22/d/Make-lang.in --- gdc-0.21/d/Make-lang.in 2006-12-25 18:59:42.000000000 +0100 +++ gdc-0.22/d/Make-lang.in 2007-02-06 05:30:00.000000000 +0100 @@ -29,9 +29,13 @@ # Enables correct implementation of delegates. This requires patching GCC. D_EXTRA_DEFINES += -DD_NO_TRAMPOLINES=1 +# Enables placing some RTTI in the read-only data section. Does not +# have to be an ELF target. +D_EXTRA_DEFINES += -DELFOBJ=1 + # Enable the asm(...) style syntax for extended asm. Deviates from the D # specification syntax. Can still use extended asm if disabled. -D_EXTRA_DEFINES += -DGDC_EXTENDED_ASM_SYNTAX=1 +# D_EXTRA_DEFINES += -DGDC_EXTENDED_ASM_SYNTAX=1 # As with C++: (quote) OTOH, I think this means the g++ driver... # Note that it would be nice to move the dependency on g++ @@ -49,7 +53,7 @@ GDMD_TARGET_INSTALL_NAME = $(target_alias)-$(shell echo gdmd|sed '$(program_transform_name)') # This should be configured -gcc_d_include_dir = $(libsubdir)/$(unlibsubdir)/..`echo $(exec_prefix) | sed -e 's|^$(prefix)||' -e 's|/[^/]*|/..|g'`/include/d/$(gcc_version) +gcc_d_include_dir = $(libsubdir)/$(unlibsubdir)/..`echo $(exec_prefix) | sed -e 's|^$(prefix)||' -e 's|/[^/]*|/..|g'`/include/d/$(version) D_DMD_H = d/dmd/aggregate.h d/dmd/arraytypes.h d/dmd/attrib.h \ d/dmd/complex_t.h d/dmd/cond.h d/dmd/dchar.h d/dmd/declaration.h \ @@ -62,9 +66,10 @@ d/dmd/template.h d/dmd/total.h d/dmd/utf.h d/dmd/version.h \ d/id.h d/d-dmd-gcc.h -D_TREE_H = $(TREE_H) d/d-lang.h d/d-codegen.h d/d-objfile.h d/d-irstate.h \ - d/d-dmd-gcc.h d/d-gcc-includes.h d/d-gcc-real.h d/symbol.h d/dt.h \ - function.h varray.h $(SYSTEM_H) $(CONFIG_H) $(TARGET_H) \ +D_TREE_H = $(TREE_H) d/d-tree.def d/d-lang.h d/d-codegen.h d/d-objfile.h \ + d/d-irstate.h d/d-dmd-gcc.h d/d-gcc-includes.h d/d-gcc-real.h \ + d/symbol.h d/dt.h function.h varray.h \ + $(SYSTEM_H) $(CONFIG_H) $(TARGET_H) \ $(GGC_H) \ $(srcdir)/../include/hashtab.h $(srcdir)/../include/splay-tree.h \ $(D_DMD_H) @@ -75,7 +80,9 @@ # Would be better to configure these rather than running shell script again and again, # but would require a patch to gcc/configure.ac D_gcc_main_ver:=$(shell echo $(version) | sed -e 's/\([0-9]*\.[0-9]*\).*/\1/') -D_is_apple_ver:=$(shell grep version_string $(gcc_version_trigger) | grep 'Apple') +ifeq ($(D_gcc_main_ver),4.0) + D_is_apple_ver:=$(shell grep version_string $(gcc_version_trigger) | grep 'Apple') +endif D_versyms=$(shell $(srcdir)/d/target-ver-syms.sh $(target)) D_EXTRA_DEFINES += $(D_versyms) @@ -96,7 +103,11 @@ ifeq ($(D_gcc_main_ver),3.4) D_EXTRA_DEFINES += -DD_GCC_VER=34 else - D_EXTRA_DEFINES += -DD_GCC_VER=40 + ifeq ($(D_gcc_main_ver),4.0) + D_EXTRA_DEFINES += -DD_GCC_VER=40 + else + D_EXTRA_DEFINES += -DD_GCC_VER=41 + endif endif D_TREE_H += coretypes.h @@ -105,15 +116,15 @@ DMD_CROSS_NAME = $(DMD_INSTALL_NAME) GDMD_CROSS_NAME = $(GDMD_INSTALL_NAME) endif -ifeq ($(gcc_version),3.3-fast) +ifeq ($(version),3.3-fast) D_EXTRA_DEFINES += -DD_GCC_VER330=1 endif -ifeq ($(gcc_version),3.4.1) +ifeq ($(version),3.4.1) # need for Cygwin which does not have 3.4.x, x>1 yet... D_EXTRA_DEFINES += -DD_GCC_VER341=1 endif -ifeq ($(gcc_version),3.4.0) +ifeq ($(version),3.4.0) # similar: needed for SkyOS which uses 3.4.0 D_EXTRA_DEFINES += -DD_GCC_VER341=1 endif @@ -181,7 +192,7 @@ # For generator programs, can't implicitly include "total.h" which includes "id.h" d/%.dmdgen.o: $(srcdir)/d/dmd/%.c - $(CXX_FOR_BUILD) $(ALL_DMD_COMPILER_FLAGS) -o d/$*.dmdgen.o -c $< + $(CC_FOR_BUILD) $(ALL_DMD_COMPILER_FLAGS) -o d/$*.dmdgen.o -c $< d/%.gen.o: d/%.c $(CXX) $(ALL_DMD_COMPILER_FLAGS) -o d/$*.gen.o -c $< @@ -193,10 +204,10 @@ $(CC) $(ALL_D_COMPILER_FLAGS) -o d/$*.cglue.o -c $< d/impcvgen: d/impcnvgen.dmdgen.o - $(CXX_FOR_BUILD) $(ALL_D_COMPILER_FLAGS) $(BUILD_LDFLAGS) -o $@ $^ + $(CC_FOR_BUILD) $(ALL_D_COMPILER_FLAGS) $(BUILD_LDFLAGS) -o $@ $^ d/idgen: d/idgen.dmdgen.o - $(CXX_FOR_BUILD) $(ALL_D_COMPILER_FLAGS) $(BUILD_LDFLAGS) -o $@ $^ + $(CC_FOR_BUILD) $(ALL_D_COMPILER_FLAGS) $(BUILD_LDFLAGS) -o $@ $^ d/impcnvtab.c: d/impcvgen cd d && ./impcvgen @@ -225,7 +236,7 @@ d/symbol.glue.o: d/symbol.cc $(D_TREE_H) d/dt.glue.o: d/symbol.cc $(D_TREE_H) d/d-gt.cglue.o: d/d-gt.c $(D_TREE_H) -d/d-builtins.cglue.o: d/d-builtins.c $(D_TREE_H) d/d-bi-attrs-33.h d/d-bi-attrs-34.h d/d-bi-attrs-40.h +d/d-builtins.cglue.o: d/d-builtins.c $(D_TREE_H) d/d-bi-attrs-33.h d/d-bi-attrs-34.h d/d-bi-attrs-40.h d/d-bi-attrs-41.h d/d-builtins2.glue.o: d/d-builtins.c $(D_TREE_H) d/d-misc.cglue.o: d/d-misc.c $(D_TREE_H) @@ -356,7 +367,7 @@ @echo "host=$(host)" >> $@ @echo "target=$(target)" >> $@ @echo "target_alias=$(D_target_alias)" >> $@ - @echo "gcc_version=$(gcc_version)" >> $@ + @echo "gcc_version=$(version)" >> $@ @echo "srcdir=$(srcdir)" >> $@ @echo "prefix=$(prefix)" >> $@ @echo "exeext=$(exeext)" >> $@ diff -uNr gdc-0.21/d/package/simple.sh gdc-0.22/d/package/simple.sh --- gdc-0.21/d/package/simple.sh 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/package/simple.sh 2007-01-31 01:52:39.000000000 +0100 @@ -169,6 +169,7 @@ $host_strip $target_alias/bin/* > /dev/null # TODO: these options are specific to binutils? $target_strip -S -X lib/lib*.* +$target_strip -S -X lib/gcc/$target_alias/$gcc_version/* > /dev/null if test "$build" != "$host"; then echo "note: removing specs as it is mostly like wrong" diff -uNr gdc-0.21/d/patch-gcc-4.1.x gdc-0.22/d/patch-gcc-4.1.x --- gdc-0.21/d/patch-gcc-4.1.x 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/patch-gcc-4.1.x 2007-02-03 20:56:13.000000000 +0100 @@ -0,0 +1,582 @@ +diff -cr gcc-orig/cgraph.c gcc/cgraph.c +*** gcc-orig/cgraph.c Mon Oct 31 16:07:29 2005 +--- gcc/cgraph.c Tue Jan 23 19:39:14 2007 +*************** +*** 182,187 **** +--- 182,188 ---- + cgraph_node (tree decl) + { + struct cgraph_node key, *node, **slot; ++ tree context; + + gcc_assert (TREE_CODE (decl) == FUNCTION_DECL); + +*************** +*** 203,214 **** + node = cgraph_create_node (); + node->decl = decl; + *slot = node; +! if (DECL_CONTEXT (decl) && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL) + { +! node->origin = cgraph_node (DECL_CONTEXT (decl)); +! node->next_nested = node->origin->nested; +! node->origin->nested = node; +! node->master_clone = node; + } + return node; + } +--- 204,219 ---- + node = cgraph_create_node (); + node->decl = decl; + *slot = node; +! if (!DECL_NO_STATIC_CHAIN (decl)) + { +! context = decl_function_context (decl); +! if (context) +! { +! node->origin = cgraph_node (context); +! node->next_nested = node->origin->nested; +! node->origin->nested = node; +! node->master_clone = node; +! } + } + return node; + } +diff -cr gcc-orig/config/darwin.h gcc/config/darwin.h +*** gcc-orig/config/darwin.h Mon Nov 14 23:55:12 2005 +--- gcc/config/darwin.h Tue Jan 23 19:39:14 2007 +*************** +*** 926,933 **** + + #define MACHO_DYNAMIC_NO_PIC_P (TARGET_DYNAMIC_NO_PIC) + #define MACHOPIC_INDIRECT (flag_pic || MACHO_DYNAMIC_NO_PIC_P) +! #define MACHOPIC_JUST_INDIRECT (flag_pic == 1 || MACHO_DYNAMIC_NO_PIC_P) +! #define MACHOPIC_PURE (flag_pic == 2 && ! MACHO_DYNAMIC_NO_PIC_P) + + #undef TARGET_ENCODE_SECTION_INFO + #define TARGET_ENCODE_SECTION_INFO darwin_encode_section_info +--- 926,933 ---- + + #define MACHO_DYNAMIC_NO_PIC_P (TARGET_DYNAMIC_NO_PIC) + #define MACHOPIC_INDIRECT (flag_pic || MACHO_DYNAMIC_NO_PIC_P) +! #define MACHOPIC_JUST_INDIRECT (MACHO_DYNAMIC_NO_PIC_P) +! #define MACHOPIC_PURE (flag_pic && ! MACHO_DYNAMIC_NO_PIC_P) + + #undef TARGET_ENCODE_SECTION_INFO + #define TARGET_ENCODE_SECTION_INFO darwin_encode_section_info +Only in gcc/config: darwin.h.orig +diff -cr gcc-orig/config/i386/i386.c gcc/config/i386/i386.c +*** gcc-orig/config/i386/i386.c Tue May 16 21:11:59 2006 +--- gcc/config/i386/i386.c Tue Jan 23 19:39:14 2007 +*************** +*** 16950,16956 **** + output_set_got (tmp); + + xops[1] = tmp; +! output_asm_insn ("mov{l}\t{%0@GOT(%1), %1|%1, %0@GOT[%1]}", xops); + output_asm_insn ("jmp\t{*}%1", xops); + } + } +--- 16950,16956 ---- + output_set_got (tmp); + + xops[1] = tmp; +! output_asm_insn ("mov{l}\t{%a0@GOT(%1), %1|%1, %a0@GOT[%1]}", xops); + output_asm_insn ("jmp\t{*}%1", xops); + } + } +diff -cr gcc-orig/config/rs6000/rs6000.c gcc/config/rs6000/rs6000.c +*** gcc-orig/config/rs6000/rs6000.c Thu Apr 13 01:46:01 2006 +--- gcc/config/rs6000/rs6000.c Tue Jan 23 19:39:14 2007 +*************** +*** 15236,15242 **** + use language_string. + C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9. + Java is 13. Objective-C is 14. */ +! if (! strcmp (language_string, "GNU C")) + i = 0; + else if (! strcmp (language_string, "GNU F77") + || ! strcmp (language_string, "GNU F95")) +--- 15236,15243 ---- + use language_string. + C is 0. Fortran is 1. Pascal is 2. Ada is 3. C++ is 9. + Java is 13. Objective-C is 14. */ +! if (! strcmp (language_string, "GNU C") || +! ! strcmp (language_string, "GNU D")) + i = 0; + else if (! strcmp (language_string, "GNU F77") + || ! strcmp (language_string, "GNU F95")) +Only in gcc: d +diff -cr gcc-orig/dwarf2.h gcc/dwarf2.h +*** gcc-orig/dwarf2.h Fri Jun 24 22:02:01 2005 +--- gcc/dwarf2.h Tue Jan 23 19:39:14 2007 +*************** +*** 731,736 **** +--- 731,737 ---- + DW_LANG_C99 = 0x000c, + DW_LANG_Ada95 = 0x000d, + DW_LANG_Fortran95 = 0x000e, ++ DW_LANG_D = 0x0013, + /* MIPS. */ + DW_LANG_Mips_Assembler = 0x8001, + /* UPC. */ +diff -cr gcc-orig/dwarf2out.c gcc/dwarf2out.c +*** gcc-orig/dwarf2out.c Mon Apr 10 09:21:13 2006 +--- gcc/dwarf2out.c Tue Jan 23 19:39:14 2007 +*************** +*** 5311,5317 **** + unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); + + return (lang == DW_LANG_C || lang == DW_LANG_C89 +! || lang == DW_LANG_C_plus_plus); + } + + /* Return TRUE if the language is C++. */ +--- 5311,5318 ---- + unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); + + return (lang == DW_LANG_C || lang == DW_LANG_C89 +! || lang == DW_LANG_C_plus_plus +! || lang == DW_LANG_D); + } + + /* Return TRUE if the language is C++. */ +*************** +*** 12187,12192 **** +--- 12188,12195 ---- + language = DW_LANG_Pascal83; + else if (strcmp (language_string, "GNU Java") == 0) + language = DW_LANG_Java; ++ else if (strcmp (language_string, "GNU D") == 0) ++ language = DW_LANG_D; + else + language = DW_LANG_C89; + +*************** +*** 13318,13324 **** + + /* For local statics lookup proper context die. */ + if (TREE_STATIC (decl) && decl_function_context (decl)) +! context_die = lookup_decl_die (DECL_CONTEXT (decl)); + + /* If we are in terse mode, don't generate any DIEs to represent any + variable declarations or definitions. */ +--- 13321,13327 ---- + + /* For local statics lookup proper context die. */ + if (TREE_STATIC (decl) && decl_function_context (decl)) +! context_die = lookup_decl_die (decl_function_context (decl)); + + /* If we are in terse mode, don't generate any DIEs to represent any + variable declarations or definitions. */ +diff -cr gcc-orig/expr.c gcc/expr.c +*** gcc-orig/expr.c Wed May 17 12:03:25 2006 +--- gcc/expr.c Tue Jan 23 19:39:14 2007 +*************** +*** 8476,8481 **** +--- 8476,8486 ---- + /* Lowered by gimplify.c. */ + gcc_unreachable (); + ++ case STATIC_CHAIN_EXPR: ++ case STATIC_CHAIN_DECL: ++ /* Lowered by tree-nested.c */ ++ gcc_unreachable (); ++ + case EXC_PTR_EXPR: + return get_exception_pointer (cfun); + +diff -cr gcc-orig/function.c gcc/function.c +*** gcc-orig/function.c Wed Jan 4 04:13:56 2006 +--- gcc/function.c Tue Jan 23 19:39:14 2007 +*************** +*** 4169,4179 **** + tree parm = cfun->static_chain_decl; + rtx local = gen_reg_rtx (Pmode); + +- set_decl_incoming_rtl (parm, static_chain_incoming_rtx); + SET_DECL_RTL (parm, local); + mark_reg_pointer (local, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm)))); + +! emit_move_insn (local, static_chain_incoming_rtx); + } + + /* If the function receives a non-local goto, then store the +--- 4169,4183 ---- + tree parm = cfun->static_chain_decl; + rtx local = gen_reg_rtx (Pmode); + + SET_DECL_RTL (parm, local); + mark_reg_pointer (local, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (parm)))); + +! if (! cfun->custom_static_chain) +! { +! set_decl_incoming_rtl (parm, static_chain_incoming_rtx); +! emit_move_insn (local, static_chain_incoming_rtx); +! } +! /* else, the static chain will be set in the main body */ + } + + /* If the function receives a non-local goto, then store the +diff -cr gcc-orig/function.h gcc/function.h +*** gcc-orig/function.h Fri Aug 19 17:16:20 2005 +--- gcc/function.h Tue Jan 23 19:39:14 2007 +*************** +*** 461,466 **** +--- 461,470 ---- + /* Number of units of floating point registers that need saving in stdarg + function. */ + unsigned int va_list_fpr_size : 8; ++ ++ /* Nonzero if static chain is initialized by something other than ++ static_chain_incoming_rtx. */ ++ unsigned int custom_static_chain : 1; + }; + + /* If va_list_[gf]pr_size is set to this, it means we don't know how +diff -cr gcc-orig/gcc.c gcc/gcc.c +*** gcc-orig/gcc.c Wed May 17 14:38:58 2006 +--- gcc/gcc.c Tue Jan 23 19:39:14 2007 +*************** +*** 876,881 **** +--- 876,883 ---- + #endif + #endif + ++ #define GCC_SPEC_FORMAT_4 1 ++ + /* Record the mapping from file suffixes for compilation specs. */ + + struct compiler +diff -cr gcc-orig/gimplify.c gcc/gimplify.c +*** gcc-orig/gimplify.c Wed Apr 5 09:41:27 2006 +--- gcc/gimplify.c Tue Jan 23 19:39:14 2007 +*************** +*** 4181,4186 **** +--- 4181,4192 ---- + } + break; + ++ case STATIC_CHAIN_EXPR: ++ /* The argument is used as information only. No need to gimplify */ ++ case STATIC_CHAIN_DECL: ++ ret = GS_ALL_DONE; ++ break; ++ + case TREE_LIST: + gcc_unreachable (); + +diff -cr gcc-orig/real.c gcc/real.c +*** gcc-orig/real.c Mon Sep 19 13:01:40 2005 +--- gcc/real.c Tue Jan 23 19:39:14 2007 +*************** +*** 2212,2217 **** +--- 2212,2219 ---- + np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b; + memset (r->sig, -1, SIGSZ * sizeof (unsigned long)); + clear_significand_below (r, np2); ++ if (REAL_MODE_FORMAT_COMPOSITE_P (mode)) ++ clear_significand_bit (r, SIGNIFICAND_BITS - fmt->pnan - 1); + } + + /* Fills R with 2**N. */ +diff -cr gcc-orig/tree-dump.c gcc/tree-dump.c +*** gcc-orig/tree-dump.c Sat Aug 20 12:03:58 2005 +--- gcc/tree-dump.c Tue Jan 23 19:39:14 2007 +*************** +*** 582,587 **** +--- 582,591 ---- + dump_child ("args", TREE_OPERAND (t, 1)); + break; + ++ case STATIC_CHAIN_EXPR: ++ dump_child ("func", TREE_OPERAND (t, 0)); ++ break; ++ + case CONSTRUCTOR: + { + unsigned HOST_WIDE_INT cnt; +diff -cr gcc-orig/tree-gimple.c gcc/tree-gimple.c +*** gcc-orig/tree-gimple.c Sun Nov 20 14:05:43 2005 +--- gcc/tree-gimple.c Tue Jan 23 19:39:14 2007 +*************** +*** 72,77 **** +--- 72,79 ---- + case VECTOR_CST: + case OBJ_TYPE_REF: + case ASSERT_EXPR: ++ case STATIC_CHAIN_EXPR: /* not sure if this is right...*/ ++ case STATIC_CHAIN_DECL: + return true; + + default: +*************** +*** 143,149 **** + || TREE_CODE (t) == WITH_SIZE_EXPR + /* These are complex lvalues, but don't have addresses, so they + go here. */ +! || TREE_CODE (t) == BIT_FIELD_REF); + } + + /* Return true if T is a GIMPLE condition. */ +--- 145,154 ---- + || TREE_CODE (t) == WITH_SIZE_EXPR + /* These are complex lvalues, but don't have addresses, so they + go here. */ +! || TREE_CODE (t) == BIT_FIELD_REF +! /* This is an lvalue because it will be replaced with the real +! static chain decl. */ +! || TREE_CODE (t) == STATIC_CHAIN_DECL); + } + + /* Return true if T is a GIMPLE condition. */ +diff -cr gcc-orig/tree-inline.c gcc/tree-inline.c +*** gcc-orig/tree-inline.c Fri Apr 28 07:43:43 2006 +--- gcc/tree-inline.c Tue Jan 23 19:39:14 2007 +*************** +*** 602,611 **** + knows not to copy VAR_DECLs, etc., so this is safe. */ + else + { + /* Here we handle trees that are not completely rewritten. + First we detect some inlining-induced bogosities for + discarding. */ +! if (TREE_CODE (*tp) == MODIFY_EXPR + && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) + && (lang_hooks.tree_inlining.auto_var_in_fn_p + (TREE_OPERAND (*tp, 0), fn))) +--- 602,622 ---- + knows not to copy VAR_DECLs, etc., so this is safe. */ + else + { ++ if (! id->cloning_p && ! id->saving_p && ++ TREE_CODE (*tp) == MODIFY_EXPR && ++ TREE_OPERAND (*tp, 0) == ++ DECL_STRUCT_FUNCTION (fn)->static_chain_decl) ++ { ++ /* Don't use special methods to initialize the static chain ++ if expanding inline. If this code could somehow be ++ expanded in expand_start_function, it would not be ++ necessary to deal with it here. */ ++ *tp = build_empty_stmt (); ++ } + /* Here we handle trees that are not completely rewritten. + First we detect some inlining-induced bogosities for + discarding. */ +! else if (TREE_CODE (*tp) == MODIFY_EXPR + && TREE_OPERAND (*tp, 0) == TREE_OPERAND (*tp, 1) + && (lang_hooks.tree_inlining.auto_var_in_fn_p + (TREE_OPERAND (*tp, 0), fn))) +diff -cr gcc-orig/tree-nested.c gcc/tree-nested.c +*** gcc-orig/tree-nested.c Mon Oct 3 16:57:45 2005 +--- gcc/tree-nested.c Tue Jan 23 19:39:14 2007 +*************** +*** 320,325 **** +--- 320,326 ---- + if (!decl) + { + tree type; ++ enum tree_code code; + + type = get_frame_type (info->outer); + type = build_pointer_type (type); +*************** +*** 330,341 **** + Note also that it's represented as a parameter. This is more + close to the truth, since the initial value does come from + the caller. */ +! decl = build_decl (PARM_DECL, create_tmp_var_name ("CHAIN"), type); + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_USED (decl) = 1; + DECL_CONTEXT (decl) = info->context; +! DECL_ARG_TYPE (decl) = type; + + /* Tell tree-inline.c that we never write to this variable, so + it can copy-prop the replacement value immediately. */ +--- 331,347 ---- + Note also that it's represented as a parameter. This is more + close to the truth, since the initial value does come from + the caller. */ +! /* If the function has a custom static chain, a VAR_DECL is more +! appropriate. */ +! code = DECL_STRUCT_FUNCTION (info->context)->custom_static_chain ? +! VAR_DECL : PARM_DECL; +! decl = build_decl (code, create_tmp_var_name ("CHAIN"), type); + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_USED (decl) = 1; + DECL_CONTEXT (decl) = info->context; +! if (TREE_CODE (decl) == PARM_DECL) +! DECL_ARG_TYPE (decl) = type; + + /* Tell tree-inline.c that we never write to this variable, so + it can copy-prop the replacement value immediately. */ +*************** +*** 738,743 **** +--- 744,751 ---- + + if (info->context == target_context) + { ++ /* might be doing something wrong to need the following line.. */ ++ get_frame_type (info); + x = build_addr (info->frame_decl, target_context); + } + else +*************** +*** 1221,1226 **** +--- 1229,1238 ---- + if (DECL_NO_STATIC_CHAIN (decl)) + break; + ++ /* Don't use a trampoline for a static reference. */ ++ if (TREE_STATIC (t)) ++ break; ++ + /* Lookup the immediate parent of the callee, as that's where + we need to insert the trampoline. */ + for (i = info; i->context != target_context; i = i->outer) +*************** +*** 1285,1290 **** +--- 1297,1310 ---- + = get_static_chain (info, target_context, &wi->tsi); + break; + ++ case STATIC_CHAIN_EXPR: ++ *tp = get_static_chain (info, TREE_OPERAND (t, 0), &wi->tsi); ++ break; ++ ++ case STATIC_CHAIN_DECL: ++ *tp = get_chain_decl (info); ++ break; ++ + case RETURN_EXPR: + case MODIFY_EXPR: + case WITH_SIZE_EXPR: +*************** +*** 1384,1390 **** + tree x = build (COMPONENT_REF, TREE_TYPE (root->chain_field), + root->frame_decl, root->chain_field, NULL_TREE); + x = build (MODIFY_EXPR, TREE_TYPE (x), x, get_chain_decl (root)); +! append_to_statement_list (x, &stmt_list); + } + + /* If trampolines were created, then we need to initialize them. */ +--- 1404,1431 ---- + tree x = build (COMPONENT_REF, TREE_TYPE (root->chain_field), + root->frame_decl, root->chain_field, NULL_TREE); + x = build (MODIFY_EXPR, TREE_TYPE (x), x, get_chain_decl (root)); +! /* If the function has a custom static chain, chain_field must +! be set after the static chain. */ +! if (DECL_STRUCT_FUNCTION (root->context)->custom_static_chain) +! { +! /* Should use walk_function instead. */ +! tree_stmt_iterator i = +! tsi_start ( BIND_EXPR_BODY (DECL_SAVED_TREE (context))); +! while (!tsi_end_p (i)) +! { +! tree t = tsi_stmt (i); +! if (TREE_CODE (t) == MODIFY_EXPR && +! TREE_OPERAND (t, 0) == root->chain_decl) +! { +! tsi_link_after(& i, x, TSI_SAME_STMT); +! x = NULL_TREE; +! break; +! } +! } +! gcc_assert(x == NULL_TREE); +! } +! else +! append_to_statement_list (x, &stmt_list); + } + + /* If trampolines were created, then we need to initialize them. */ +diff -cr gcc-orig/tree-pretty-print.c gcc/tree-pretty-print.c +*** gcc-orig/tree-pretty-print.c Sun Jul 31 16:55:41 2005 +--- gcc/tree-pretty-print.c Tue Jan 23 19:39:14 2007 +*************** +*** 1004,1009 **** +--- 1004,1019 ---- + pp_string (buffer, " [tail call]"); + break; + ++ case STATIC_CHAIN_EXPR: ++ pp_string (buffer, "<>"); ++ break; ++ ++ case STATIC_CHAIN_DECL: ++ pp_string (buffer, "<>"); ++ break; ++ + case WITH_CLEANUP_EXPR: + NIY; + break; +diff -cr gcc-orig/tree.def gcc/tree.def +*** gcc-orig/tree.def Fri Feb 10 12:32:10 2006 +--- gcc/tree.def Tue Jan 23 19:39:14 2007 +*************** +*** 526,531 **** +--- 526,538 ---- + Operand 2 is the static chain argument, or NULL. */ + DEFTREECODE (CALL_EXPR, "call_expr", tcc_expression, 3) + ++ /* Operand 0 is the FUNC_DECL of the outer function for ++ which the static chain is to be computed. */ ++ DEFTREECODE (STATIC_CHAIN_EXPR, "static_chain_expr", tcc_expression, 1) ++ ++ /* Represents a function's static chain. It can be used as an lvalue. */ ++ DEFTREECODE (STATIC_CHAIN_DECL, "static_chain_decl", tcc_expression, 0) ++ + /* Specify a value to compute along with its corresponding cleanup. + Operand 0 is the cleanup expression. + The cleanup is executed by the first enclosing CLEANUP_POINT_EXPR, +diff -cr gcc-orig/varray.h gcc/varray.h +*** gcc-orig/varray.h Fri Jun 24 22:02:01 2005 +--- gcc/varray.h Tue Jan 23 19:39:14 2007 +*************** +*** 62,67 **** +--- 62,78 ---- + NUM_VARRAY_DATA + }; + ++ #ifndef __cplusplus ++ # define VARRAY_STRANGE_1 rtx ++ # define VARRAY_STRANGE_2 rtvec ++ # define VARRAY_STRANGE_3 tree ++ #else ++ # define VARRAY_STRANGE_1 rtx_ ++ # define VARRAY_STRANGE_2 rtvec_ ++ # define VARRAY_STRANGE_3 tree_ ++ #endif ++ ++ + /* Union of various array types that are used. */ + typedef union varray_data_tag GTY (()) { + char GTY ((length ("%0.num_elements"), +*************** +*** 91,101 **** + char *GTY ((length ("%0.num_elements"), + tag ("VARRAY_DATA_CPTR"))) cptr[1]; + rtx GTY ((length ("%0.num_elements"), +! tag ("VARRAY_DATA_RTX"))) rtx[1]; + rtvec GTY ((length ("%0.num_elements"), +! tag ("VARRAY_DATA_RTVEC"))) rtvec[1]; + tree GTY ((length ("%0.num_elements"), +! tag ("VARRAY_DATA_TREE"))) tree[1]; + struct bitmap_head_def *GTY ((length ("%0.num_elements"), + tag ("VARRAY_DATA_BITMAP"))) bitmap[1]; + struct reg_info_def *GTY ((length ("%0.num_elements"), skip, +--- 102,112 ---- + char *GTY ((length ("%0.num_elements"), + tag ("VARRAY_DATA_CPTR"))) cptr[1]; + rtx GTY ((length ("%0.num_elements"), +! tag ("VARRAY_DATA_RTX"))) VARRAY_STRANGE_1[1]; + rtvec GTY ((length ("%0.num_elements"), +! tag ("VARRAY_DATA_RTVEC"))) VARRAY_STRANGE_2[1]; + tree GTY ((length ("%0.num_elements"), +! tag ("VARRAY_DATA_TREE"))) VARRAY_STRANGE_3[1]; + struct bitmap_head_def *GTY ((length ("%0.num_elements"), + tag ("VARRAY_DATA_BITMAP"))) bitmap[1]; + struct reg_info_def *GTY ((length ("%0.num_elements"), skip, diff -uNr gdc-0.21/d/patch-toplev-4.1.x gdc-0.22/d/patch-toplev-4.1.x --- gdc-0.21/d/patch-toplev-4.1.x 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/patch-toplev-4.1.x 2007-01-31 01:52:39.000000000 +0100 @@ -0,0 +1,724 @@ + diff -c gcc-4.1.1-orig/Makefile.def gcc-4.1.1/Makefile.def +*** gcc-4.1.1-orig/Makefile.def Fri Nov 11 16:47:07 2005 +--- gcc-4.1.1/Makefile.def Tue Jan 23 19:39:14 2007 +*************** +*** 136,141 **** +--- 136,142 ---- + target_modules = { module= qthreads; }; + target_modules = { module= rda; }; + target_modules = { module= libada; }; ++ target_modules = { module= libphobos; }; + + // These are (some of) the make targets to be done in each subdirectory. + // Not all; these are the ones which don't have special options. +diff -c gcc-4.1.1-orig/Makefile.in gcc-4.1.1/Makefile.in +*** gcc-4.1.1-orig/Makefile.in Tue Apr 4 17:03:05 2006 +--- gcc-4.1.1/Makefile.in Tue Jan 23 19:39:14 2007 +*************** +*** 626,632 **** + maybe-configure-target-boehm-gc \ + maybe-configure-target-qthreads \ + maybe-configure-target-rda \ +! maybe-configure-target-libada + + # The target built for a native non-bootstrap build. + .PHONY: all +--- 626,633 ---- + maybe-configure-target-boehm-gc \ + maybe-configure-target-qthreads \ + maybe-configure-target-rda \ +! maybe-configure-target-libada \ +! maybe-configure-target-libphobos + + # The target built for a native non-bootstrap build. + .PHONY: all +*************** +*** 745,751 **** + maybe-all-target-boehm-gc \ + maybe-all-target-qthreads \ + maybe-all-target-rda \ +! maybe-all-target-libada + + # Do a target for all the subdirectories. A ``make do-X'' will do a + # ``make X'' in all subdirectories (because, in general, there is a +--- 746,753 ---- + maybe-all-target-boehm-gc \ + maybe-all-target-qthreads \ + maybe-all-target-rda \ +! maybe-all-target-libada \ +! maybe-all-target-libphobos + + # Do a target for all the subdirectories. A ``make do-X'' will do a + # ``make X'' in all subdirectories (because, in general, there is a +*************** +*** 852,858 **** + maybe-info-target-boehm-gc \ + maybe-info-target-qthreads \ + maybe-info-target-rda \ +! maybe-info-target-libada + + .PHONY: do-dvi + do-dvi: +--- 854,861 ---- + maybe-info-target-boehm-gc \ + maybe-info-target-qthreads \ + maybe-info-target-rda \ +! maybe-info-target-libada \ +! maybe-info-target-libphobos + + .PHONY: do-dvi + do-dvi: +*************** +*** 954,960 **** + maybe-dvi-target-boehm-gc \ + maybe-dvi-target-qthreads \ + maybe-dvi-target-rda \ +! maybe-dvi-target-libada + + .PHONY: do-html + do-html: +--- 957,964 ---- + maybe-dvi-target-boehm-gc \ + maybe-dvi-target-qthreads \ + maybe-dvi-target-rda \ +! maybe-dvi-target-libada \ +! maybe-dvi-target-libphobos + + .PHONY: do-html + do-html: +*************** +*** 1056,1062 **** + maybe-html-target-boehm-gc \ + maybe-html-target-qthreads \ + maybe-html-target-rda \ +! maybe-html-target-libada + + .PHONY: do-TAGS + do-TAGS: +--- 1060,1067 ---- + maybe-html-target-boehm-gc \ + maybe-html-target-qthreads \ + maybe-html-target-rda \ +! maybe-html-target-libada \ +! maybe-html-target-libphobos + + .PHONY: do-TAGS + do-TAGS: +*************** +*** 1158,1164 **** + maybe-TAGS-target-boehm-gc \ + maybe-TAGS-target-qthreads \ + maybe-TAGS-target-rda \ +! maybe-TAGS-target-libada + + .PHONY: do-install-info + do-install-info: +--- 1163,1170 ---- + maybe-TAGS-target-boehm-gc \ + maybe-TAGS-target-qthreads \ + maybe-TAGS-target-rda \ +! maybe-TAGS-target-libada \ +! maybe-TAGS-target-libphobos + + .PHONY: do-install-info + do-install-info: +*************** +*** 1260,1266 **** + maybe-install-info-target-boehm-gc \ + maybe-install-info-target-qthreads \ + maybe-install-info-target-rda \ +! maybe-install-info-target-libada + + .PHONY: do-installcheck + do-installcheck: +--- 1266,1273 ---- + maybe-install-info-target-boehm-gc \ + maybe-install-info-target-qthreads \ + maybe-install-info-target-rda \ +! maybe-install-info-target-libada \ +! maybe-install-info-target-libphobos + + .PHONY: do-installcheck + do-installcheck: +*************** +*** 1362,1368 **** + maybe-installcheck-target-boehm-gc \ + maybe-installcheck-target-qthreads \ + maybe-installcheck-target-rda \ +! maybe-installcheck-target-libada + + .PHONY: do-mostlyclean + do-mostlyclean: +--- 1369,1376 ---- + maybe-installcheck-target-boehm-gc \ + maybe-installcheck-target-qthreads \ + maybe-installcheck-target-rda \ +! maybe-installcheck-target-libada \ +! maybe-installcheck-target-libphobos + + .PHONY: do-mostlyclean + do-mostlyclean: +*************** +*** 1464,1470 **** + maybe-mostlyclean-target-boehm-gc \ + maybe-mostlyclean-target-qthreads \ + maybe-mostlyclean-target-rda \ +! maybe-mostlyclean-target-libada + + .PHONY: do-clean + do-clean: +--- 1472,1479 ---- + maybe-mostlyclean-target-boehm-gc \ + maybe-mostlyclean-target-qthreads \ + maybe-mostlyclean-target-rda \ +! maybe-mostlyclean-target-libada \ +! maybe-mostlyclean-target-libphobos + + .PHONY: do-clean + do-clean: +*************** +*** 1566,1572 **** + maybe-clean-target-boehm-gc \ + maybe-clean-target-qthreads \ + maybe-clean-target-rda \ +! maybe-clean-target-libada + + .PHONY: do-distclean + do-distclean: +--- 1575,1582 ---- + maybe-clean-target-boehm-gc \ + maybe-clean-target-qthreads \ + maybe-clean-target-rda \ +! maybe-clean-target-libada \ +! maybe-clean-target-libphobos + + .PHONY: do-distclean + do-distclean: +*************** +*** 1668,1674 **** + maybe-distclean-target-boehm-gc \ + maybe-distclean-target-qthreads \ + maybe-distclean-target-rda \ +! maybe-distclean-target-libada + + .PHONY: do-maintainer-clean + do-maintainer-clean: +--- 1678,1685 ---- + maybe-distclean-target-boehm-gc \ + maybe-distclean-target-qthreads \ + maybe-distclean-target-rda \ +! maybe-distclean-target-libada \ +! maybe-distclean-target-libphobos + + .PHONY: do-maintainer-clean + do-maintainer-clean: +*************** +*** 1770,1776 **** + maybe-maintainer-clean-target-boehm-gc \ + maybe-maintainer-clean-target-qthreads \ + maybe-maintainer-clean-target-rda \ +! maybe-maintainer-clean-target-libada + + + # Here are the targets which correspond to the do-X targets. +--- 1781,1788 ---- + maybe-maintainer-clean-target-boehm-gc \ + maybe-maintainer-clean-target-qthreads \ + maybe-maintainer-clean-target-rda \ +! maybe-maintainer-clean-target-libada \ +! maybe-maintainer-clean-target-libphobos + + + # Here are the targets which correspond to the do-X targets. +*************** +*** 1928,1934 **** + maybe-check-target-boehm-gc \ + maybe-check-target-qthreads \ + maybe-check-target-rda \ +! maybe-check-target-libada + + do-check: + @: $(MAKE); $(unstage) +--- 1940,1947 ---- + maybe-check-target-boehm-gc \ + maybe-check-target-qthreads \ + maybe-check-target-rda \ +! maybe-check-target-libada \ +! maybe-check-target-libphobos + + do-check: + @: $(MAKE); $(unstage) +*************** +*** 2127,2133 **** + maybe-install-target-boehm-gc \ + maybe-install-target-qthreads \ + maybe-install-target-rda \ +! maybe-install-target-libada + + uninstall: + @echo "the uninstall target is not supported in this tree" +--- 2140,2147 ---- + maybe-install-target-boehm-gc \ + maybe-install-target-qthreads \ + maybe-install-target-rda \ +! maybe-install-target-libada \ +! maybe-install-target-libphobos + + uninstall: + @echo "the uninstall target is not supported in this tree" +*************** +*** 34743,34748 **** +--- 34757,35111 ---- + + + ++ # There's only one multilib.out. Cleverer subdirs shouldn't need it copied. ++ @if target-libphobos ++ $(TARGET_SUBDIR)/libphobos/multilib.out: multilib.out ++ $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libphobos ; \ ++ rm -f $(TARGET_SUBDIR)/libphobos/Makefile || : ; \ ++ cp multilib.out $(TARGET_SUBDIR)/libphobos/multilib.out ++ @endif target-libphobos ++ ++ ++ ++ .PHONY: configure-target-libphobos maybe-configure-target-libphobos ++ maybe-configure-target-libphobos: ++ @if target-libphobos ++ maybe-configure-target-libphobos: configure-target-libphobos ++ configure-target-libphobos: $(TARGET_SUBDIR)/libphobos/multilib.out ++ @$(unstage) ++ @test ! -f $(TARGET_SUBDIR)/libphobos/Makefile || exit 0; \ ++ $(SHELL) $(srcdir)/mkinstalldirs $(TARGET_SUBDIR)/libphobos ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo Configuring in $(TARGET_SUBDIR)/libphobos; \ ++ cd "$(TARGET_SUBDIR)/libphobos" || exit 1; \ ++ case $(srcdir) in \ ++ /* | [A-Za-z]:[\\/]*) topdir=$(srcdir) ;; \ ++ *) topdir=`echo $(TARGET_SUBDIR)/libphobos/ | \ ++ sed -e 's,\./,,g' -e 's,[^/]*/,../,g' `$(srcdir) ;; \ ++ esac; \ ++ srcdiroption="--srcdir=$${topdir}/libphobos"; \ ++ libsrcdir="$$s/libphobos"; \ ++ rm -f no-such-file || : ; \ ++ CONFIG_SITE=no-such-file $(SHELL) $${libsrcdir}/configure \ ++ $(TARGET_CONFIGARGS) $${srcdiroption} \ ++ || exit 1 ++ @endif target-libphobos ++ ++ ++ ++ ++ ++ .PHONY: all-target-libphobos maybe-all-target-libphobos ++ maybe-all-target-libphobos: ++ @if target-libphobos ++ TARGET-target-libphobos=all ++ maybe-all-target-libphobos: all-target-libphobos ++ all-target-libphobos: configure-target-libphobos ++ @$(unstage) ++ @r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(TARGET_FLAGS_TO_PASS) $(TARGET-target-libphobos)) ++ @endif target-libphobos ++ ++ ++ ++ ++ ++ .PHONY: check-target-libphobos maybe-check-target-libphobos ++ maybe-check-target-libphobos: ++ @if target-libphobos ++ maybe-check-target-libphobos: check-target-libphobos ++ ++ check-target-libphobos: ++ @: $(MAKE); $(unstage) ++ @r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(TARGET_FLAGS_TO_PASS) check) ++ ++ @endif target-libphobos ++ ++ .PHONY: install-target-libphobos maybe-install-target-libphobos ++ maybe-install-target-libphobos: ++ @if target-libphobos ++ maybe-install-target-libphobos: install-target-libphobos ++ ++ install-target-libphobos: installdirs ++ @: $(MAKE); $(unstage) ++ @r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(TARGET_FLAGS_TO_PASS) install) ++ ++ @endif target-libphobos ++ ++ # Other targets (info, dvi, etc.) ++ ++ .PHONY: maybe-info-target-libphobos info-target-libphobos ++ maybe-info-target-libphobos: ++ @if target-libphobos ++ maybe-info-target-libphobos: info-target-libphobos ++ ++ info-target-libphobos: \ ++ configure-target-libphobos ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing info in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ info) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-dvi-target-libphobos dvi-target-libphobos ++ maybe-dvi-target-libphobos: ++ @if target-libphobos ++ maybe-dvi-target-libphobos: dvi-target-libphobos ++ ++ dvi-target-libphobos: \ ++ configure-target-libphobos ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing dvi in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ dvi) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-html-target-libphobos html-target-libphobos ++ maybe-html-target-libphobos: ++ @if target-libphobos ++ maybe-html-target-libphobos: html-target-libphobos ++ ++ html-target-libphobos: \ ++ configure-target-libphobos ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing html in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ html) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-TAGS-target-libphobos TAGS-target-libphobos ++ maybe-TAGS-target-libphobos: ++ @if target-libphobos ++ maybe-TAGS-target-libphobos: TAGS-target-libphobos ++ ++ TAGS-target-libphobos: \ ++ configure-target-libphobos ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing TAGS in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ TAGS) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-install-info-target-libphobos install-info-target-libphobos ++ maybe-install-info-target-libphobos: ++ @if target-libphobos ++ maybe-install-info-target-libphobos: install-info-target-libphobos ++ ++ install-info-target-libphobos: \ ++ configure-target-libphobos \ ++ info-target-libphobos ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing install-info in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ install-info) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-installcheck-target-libphobos installcheck-target-libphobos ++ maybe-installcheck-target-libphobos: ++ @if target-libphobos ++ maybe-installcheck-target-libphobos: installcheck-target-libphobos ++ ++ installcheck-target-libphobos: \ ++ configure-target-libphobos ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing installcheck in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ installcheck) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-mostlyclean-target-libphobos mostlyclean-target-libphobos ++ maybe-mostlyclean-target-libphobos: ++ @if target-libphobos ++ maybe-mostlyclean-target-libphobos: mostlyclean-target-libphobos ++ ++ mostlyclean-target-libphobos: ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing mostlyclean in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ mostlyclean) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-clean-target-libphobos clean-target-libphobos ++ maybe-clean-target-libphobos: ++ @if target-libphobos ++ maybe-clean-target-libphobos: clean-target-libphobos ++ ++ clean-target-libphobos: ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing clean in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ clean) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-distclean-target-libphobos distclean-target-libphobos ++ maybe-distclean-target-libphobos: ++ @if target-libphobos ++ maybe-distclean-target-libphobos: distclean-target-libphobos ++ ++ distclean-target-libphobos: ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing distclean in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ distclean) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ .PHONY: maybe-maintainer-clean-target-libphobos maintainer-clean-target-libphobos ++ maybe-maintainer-clean-target-libphobos: ++ @if target-libphobos ++ maybe-maintainer-clean-target-libphobos: maintainer-clean-target-libphobos ++ ++ maintainer-clean-target-libphobos: ++ @: $(MAKE); $(unstage) ++ @[ -f $(TARGET_SUBDIR)/libphobos/Makefile ] || exit 0 ; \ ++ r=`${PWD_COMMAND}`; export r; \ ++ s=`cd $(srcdir); ${PWD_COMMAND}`; export s; \ ++ $(NORMAL_TARGET_EXPORTS) \ ++ echo "Doing maintainer-clean in $(TARGET_SUBDIR)/libphobos" ; \ ++ for flag in $(EXTRA_TARGET_FLAGS); do \ ++ eval `echo "$$flag" | sed -e "s|^\([^=]*\)=\(.*\)|\1='\2'; export \1|"`; \ ++ done; \ ++ (cd $(TARGET_SUBDIR)/libphobos && \ ++ $(MAKE) $(BASE_FLAGS_TO_PASS) "AR=$${AR}" "AS=$${AS}" \ ++ "CC=$${CC}" "CXX=$${CXX}" "LD=$${LD}" "NM=$${NM}" \ ++ "RANLIB=$${RANLIB}" \ ++ "DLLTOOL=$${DLLTOOL}" "WINDRES=$${WINDRES}" \ ++ maintainer-clean) \ ++ || exit 1 ++ ++ @endif target-libphobos ++ ++ ++ + # ---------- + # GCC module + # ---------- +*************** +*** 36182,36187 **** +--- 36545,36552 ---- + + configure-target-libada: maybe-all-gcc + ++ configure-target-libphobos: maybe-all-gcc ++ + + + configure-target-boehm-gc: maybe-all-target-newlib maybe-all-target-libgloss +Common subdirectories: gcc-4.1.1-orig/config and gcc-4.1.1/config +diff -c gcc-4.1.1-orig/configure gcc-4.1.1/configure +*** gcc-4.1.1-orig/configure Fri Dec 16 07:57:40 2005 +--- gcc-4.1.1/configure Tue Jan 23 19:39:14 2007 +*************** +*** 909,914 **** +--- 909,915 ---- + target-libgfortran \ + ${libgcj} \ + target-libobjc \ ++ target-libphobos \ + target-libada" + + # these tools are built using the target libraries, and are intended to +*************** +*** 1802,1807 **** +--- 1803,1809 ---- + CXX=${CXX-${host_alias}-c++} + CXXFLAGS=${CXXFLAGS-"-g -O2"} + CC_FOR_BUILD=${CC_FOR_BUILD-gcc} ++ CXX_FOR_BUILD=${CXX_FOR_BUILD-c++} + BUILD_PREFIX=${build_alias}- + BUILD_PREFIX_1=${build_alias}- + +*************** +*** 1815,1820 **** +--- 1817,1823 ---- + # This is all going to change when we autoconfiscate... + + CC_FOR_BUILD="\$(CC)" ++ CXX_FOR_BUILD="\$(CXX)" + BUILD_PREFIX= + BUILD_PREFIX_1=loser- + +*************** +*** 6311,6316 **** +--- 6314,6320 ---- + s%@target_configargs@%$target_configargs%g + s%@target_configdirs@%$target_configdirs%g + s%@CC_FOR_BUILD@%$CC_FOR_BUILD%g ++ s%@CXX_FOR_BUILD@%$CXX_FOR_BUILD%g + s%@config_shell@%$config_shell%g + s%@YACC@%$YACC%g + s%@BISON@%$BISON%g +diff -c gcc-4.1.1-orig/configure.in gcc-4.1.1/configure.in +*** gcc-4.1.1-orig/configure.in Fri Dec 16 07:57:40 2005 +--- gcc-4.1.1/configure.in Tue Jan 23 19:39:14 2007 +*************** +*** 151,156 **** +--- 151,157 ---- + target-libgfortran \ + ${libgcj} \ + target-libobjc \ ++ target-libphobos \ + target-libada" + + # these tools are built using the target libraries, and are intended to +*************** +*** 1010,1015 **** +--- 1011,1017 ---- + CXX=${CXX-${host_alias}-c++} + CXXFLAGS=${CXXFLAGS-"-g -O2"} + CC_FOR_BUILD=${CC_FOR_BUILD-gcc} ++ CXX_FOR_BUILD=${CXX_FOR_BUILD-c++} + BUILD_PREFIX=${build_alias}- + BUILD_PREFIX_1=${build_alias}- + +*************** +*** 1023,1028 **** +--- 1025,1031 ---- + # This is all going to change when we autoconfiscate... + + CC_FOR_BUILD="\$(CC)" ++ CXX_FOR_BUILD="\$(CXX)" + BUILD_PREFIX= + BUILD_PREFIX_1=loser- + +*************** +*** 2086,2091 **** +--- 2089,2095 ---- + + # Build tools. + AC_SUBST(CC_FOR_BUILD) ++ AC_SUBST(CXX_FOR_BUILD) + AC_SUBST(config_shell) + + # Generate default definitions for YACC, M4, LEX and other programs that run diff -uNr gdc-0.21/d/phobos/internal/aaA.d gdc-0.22/d/phobos/internal/aaA.d --- gdc-0.21/d/phobos/internal/aaA.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/internal/aaA.d 2007-02-03 17:34:12.000000000 +0100 @@ -6,7 +6,7 @@ */ /* - * Copyright (C) 2000-2006 by Digital Mars, www.digitalmars.com + * Copyright (C) 2000-2007 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -281,7 +281,7 @@ // Not found, create new elem //printf("create new one\n"); - e = cast(aaA *) cast(void*) new byte[aaA.sizeof + keysize + valuesize]; + e = cast(aaA *) cast(void*) new void[aaA.sizeof + keysize + valuesize]; memcpy(e + 1, pkey, keysize); e.hash = key_hash; *pe = e; @@ -480,7 +480,7 @@ if (aa.a) { a.length = _aaLen(aa); - a.ptr = (new byte[a.length * valuesize]).ptr; + a.ptr = (new void[a.length * valuesize]).ptr; resi = 0; foreach (e; aa.a.b) { @@ -616,7 +616,7 @@ auto len = _aaLen(aa); if (!len) return a; - res = new byte[len * keysize]; + res = cast(byte[])new void[len * keysize]; resi = 0; foreach (e; aa.a.b) { diff -uNr gdc-0.21/d/phobos/internal/adi.d gdc-0.22/d/phobos/internal/adi.d --- gdc-0.21/d/phobos/internal/adi.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/internal/adi.d 2007-02-03 17:34:12.000000000 +0100 @@ -469,6 +469,8 @@ * Support for array.reverse property for bit[]. */ +version (none) +{ extern (C) bit[] _adReverseBit(bit[] a) out (result) { @@ -509,7 +511,7 @@ assert(b[i] == data[4 - i]); } } - +} /********************************************** * Sort array of chars. @@ -610,92 +612,16 @@ } -/********************************** - * Support for array.dup property. - */ - -extern (C) Array _adDup(Array a, int szelem) - out (result) - { - assert(memcmp(result.ptr, a.ptr, a.length * szelem) == 0); - } - body - { - Array r; - - auto size = a.length * szelem; - r.ptr = cast(void *) new byte[size]; - r.length = a.length; - memcpy(r.ptr, a.ptr, size); - return r; - } - -unittest -{ - int[] a; - int[] b; - int i; - - debug(adi) printf("array.dup.unittest\n"); - - a = new int[3]; - a[0] = 1; a[1] = 2; a[2] = 3; - b = a.dup; - assert(b.length == 3); - for (i = 0; i < 3; i++) - assert(b[i] == i + 1); -} - -/********************************** - * Support for array.dup property for bit[]. - */ - -extern (C) Array _adDupBit(Array a) - out (result) - { - assert(memcmp(result.ptr, a.ptr, (a.length + 7) / 8) == 0); - } - body - { - Array r; - - auto size = (a.length + 31) / 32; - r.ptr = cast(void *) new uint[size]; - r.length = a.length; - memcpy(r.ptr, a.ptr, size * uint.sizeof); - return r; - } - -unittest -{ - bit[] a; - bit[] b; - int i; - - debug(adi) printf("array.dupBit[].unittest\n"); - - a = new bit[3]; - a[0] = 1; a[1] = 0; a[2] = 1; - b = a.dup; - assert(b.length == 3); - for (i = 0; i < 3; i++) - { debug(adi) printf("b[%d] = %d\n", i, b[i]); - assert(b[i] == (((i ^ 1) & 1) ? true : false)); - } -} - - /*************************************** * Support for array equality test. */ extern (C) int _adEq(Array a1, Array a2, TypeInfo ti) { - //printf("a1.length = %d, a2.length = %d\n", a1.length, a2.length); + //printf("_adEq(a1.length = %d, a2.length = %d)\n", a1.length, a2.length); if (a1.length != a2.length) return 0; // not equal auto sz = ti.tsize(); - //printf("sz = %d\n", sz); auto p1 = a1.ptr; auto p2 = a2.ptr; @@ -735,6 +661,8 @@ * Support for array equality test for bit arrays. */ +version (none) +{ extern (C) int _adEqBit(Array a1, Array a2) { int i; @@ -772,6 +700,7 @@ assert(a != d); assert(a == e); } +} /*************************************** * Support for array compare test. @@ -829,6 +758,8 @@ * Support for array compare test. */ +version (none) +{ extern (C) int _adCmpBit(Array a1, Array a2) { int len; @@ -876,5 +807,5 @@ assert(a <= e); assert(a >= e); } - +} diff -uNr gdc-0.21/d/phobos/internal/arraycast.d gdc-0.22/d/phobos/internal/arraycast.d --- gdc-0.21/d/phobos/internal/arraycast.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/internal/arraycast.d 2007-02-03 17:34:12.000000000 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -32,18 +32,17 @@ extern (C) -void[] _d_arraycast(uint tsize, uint fsize, void[] a) +void[] _d_arraycast(size_t tsize, size_t fsize, void[] a) { - uint length = a.length; - uint nbytes; + auto length = a.length; - nbytes = length * fsize; + auto nbytes = length * fsize; if (nbytes % tsize != 0) { throw new Error("array cast misalignment"); } length = nbytes / tsize; - *cast(uint *)&a = length; // jam new length + *cast(size_t *)&a = length; // jam new length return a; } @@ -70,6 +69,8 @@ * Throws exception if new length is not aligned. */ +version (none) +{ extern (C) void[] _d_arraycast_frombit(uint tsize, void[] a) @@ -81,7 +82,7 @@ throw new Error("bit[] array cast misalignment"); } length /= 8 * tsize; - *cast(uint *)&a = length; // jam new length + *cast(size_t *)&a = length; // jam new length return a; } @@ -101,4 +102,4 @@ } } - +} diff -uNr gdc-0.21/d/phobos/internal/arraycat.d gdc-0.22/d/phobos/internal/arraycat.d --- gdc-0.21/d/phobos/internal/arraycat.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/internal/arraycat.d 2007-02-03 17:34:12.000000000 +0100 @@ -3,7 +3,7 @@ */ /* - * Copyright (C) 2004-2006 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -39,70 +39,7 @@ import std.c.stdio; import std.c.stdarg; -extern (C): - -byte[] _d_arraycatn(uint size, uint n, ...) -{ byte[] a; - uint length; - uint i; - byte[] b; - va_list va; - - va_start!(typeof(n))(va, n); - - for (i = 0; i < n; i++) - { - b = va_arg!(typeof(b))(va); - length += b.length; - } - if (!length) - return null; - - a = new byte[length * size]; - va_start!(typeof(n))(va, n); - - uint j = 0; - for (i = 0; i < n; i++) - { - b = va_arg!(typeof(b))(va); - if (b.length) - { - memcpy(&a[j], b.ptr, b.length * size); - j += b.length * size; - } - } - - *cast(int *)&a = length; // jam length - //a.length = length; - return a; -} - -bit[] _d_arraycatb(bit[] x, bit[] y) -{ bit[] a; - uint a_length; - uint x_bytes; - - //printf("_d_arraycatb(x.ptr = %p, x.length = %d, y.ptr = %p, y.length = %d)\n", x.ptr, x.length, y.ptr, y.length); - if (!x.length) - return y; - if (!y.length) - return x; - - a_length = x.length + y.length; - a = new bit[a_length]; - x_bytes = (x.length + 7) >> 3; - memcpy(a.ptr, x.ptr, x_bytes); - if ((x.length & 7) == 0) - memcpy(cast(void*)a.ptr + x_bytes, y.ptr, (y.length + 7) >> 3); - else - { uint x_length = x.length; - uint y_length = y.length; - for (uint i = 0; i < y_length; i++) - a[x_length + i] = y[i]; - } - return a; -} - +extern (C) byte[] _d_arraycopy(uint size, byte[] from, byte[] to) { //printf("f = %p,%d, t = %p,%d, size = %d\n", (void*)from, from.length, (void*)to, to.length, size); @@ -125,104 +62,3 @@ return to; } -bit[] _d_arraycopybit(bit[] from, bit[] to) -{ - //printf("f = %p,%d, t = %p,%d\n", (void*)from, from.length, (void*)to, to.length); - uint nbytes; - - if (to.length != from.length) - { - throw new Error("lengths don't match for array copy"); - } - else - { - nbytes = (to.length + 7) / 8; - if (cast(void *)to + nbytes <= cast(void *)from || - cast(void *)from + nbytes <= cast(void *)to) - { - nbytes = to.length / 8; - if (nbytes) - memcpy(cast(void *)to, cast(void *)from, nbytes); - - if (to.length & 7) - { - /* Copy trailing bits. - */ - static ubyte[8] masks = [0,1,3,7,0x0F,0x1F,0x3F,0x7F]; - ubyte mask = masks[to.length & 7]; - (cast(ubyte*)to)[nbytes] &= ~mask; - (cast(ubyte*)to)[nbytes] |= (cast(ubyte*)from)[nbytes] & mask; - } - } - else - { - throw new Error("overlapping array copy"); - } - } - return to; -} - -bit[] _d_arraysetbit(bit[] ba, uint lwr, uint upr, bit value) -in -{ - //printf("_d_arraysetbit(ba.length = %d, lwr = %u, upr = %u, value = %d)\n", ba.length, lwr, upr, value); - assert(lwr <= upr); - assert(upr <= ba.length); -} -body -{ - // Inefficient; lots of room for improvement here - for (uint i = lwr; i < upr; i++) - ba[i] = value; - - return ba; -} - -bit[] _d_arraysetbit2(bit[] ba, bit value) -{ - //printf("_d_arraysetbit2(ba.ptr = %p, ba.length = %d, value = %d)\n", ba.ptr, ba.length, value); - size_t len = ba.length; - uint val = -cast(int)value; - memset(ba.ptr, val, len >> 3); - for (uint i = len & ~7; i < len; i++) - ba[i] = value; - //printf("-_d_arraysetbit2(ba.ptr = %p, ba.length = %d, value = %d)\n", ba.ptr, ba.length, ba[0]); - return ba; -} - -version (GNU) { /* _d_arrayliteral not used; can't always be compiled */ } -else -void* _d_arrayliteral(size_t size, size_t length, ...) -{ - byte[] result; - - //printf("_d_arrayliteral(size = %d, length = %d)\n", size, length); - if (length == 0 || size == 0) - result = null; - else - { - result = new byte[length * size]; - *cast(size_t *)&result = length; // jam length - - va_list q; - va_start!(size_t)(q, length); - - size_t stacksize = (size + int.sizeof - 1) & ~(int.sizeof - 1); - - if (stacksize == size) - { - memcpy(result.ptr, q, length * size); - } - else - { - for (size_t i = 0; i < length; i++) - { - memcpy(result.ptr + i * size, q, size); - q += stacksize; - } - } - - va_end(q); - } - return result.ptr; -} diff -uNr gdc-0.21/d/phobos/internal/gc/gc.d gdc-0.22/d/phobos/internal/gc/gc.d --- gdc-0.21/d/phobos/internal/gc/gc.d 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gc.d 2007-02-03 18:35:36.000000000 +0100 @@ -1,6 +1,9 @@ +/** + * Part of the D programming language runtime library. + */ /* - * Copyright (C) 2004-2005 by Digital Mars, www.digitalmars.com + * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com * Written by Walter Bright * * This software is provided 'as-is', without any express or implied @@ -19,16 +22,12 @@ * be misrepresented as being the original software. * o This notice may not be removed or altered from any source * distribution. - * - * Modifications from original software: - * - * 2004-09-24 David Friedman -- Modified to work with the D GCC compiler */ /* NOTE: This file has been patched from the original DMD distribution to work with the GDC compiler. - Modified by David Friedman, September 2004 + Modified by David Friedman, February 2007 */ @@ -38,13 +37,13 @@ //debug = PRINTF; -import std.c.stdarg; -import std.c.stdlib; -import std.c.string; -import gcx; -import std.outofmemory; -import gcstats; -import std.thread; +public import std.c.stdarg; +public import std.c.stdlib; +public import std.c.string; +public import gcx; +public import std.outofmemory; +public import gcstats; +public import std.thread; version=GCCLASS; @@ -66,6 +65,17 @@ void disable() { _gc.disable(); } void enable() { _gc.enable(); } void getStats(out GCStats stats) { _gc.getStats(stats); } +void hasPointers(void* p) { _gc.hasPointers(p); } +void hasNoPointers(void* p) { _gc.hasNoPointers(p); } +void setV1_0() { _gc.setV1_0(); } + +void setTypeInfo(TypeInfo ti, void* p) +{ + if (ti.flags() & 1) + hasNoPointers(p); + else + hasPointers(p); +} void* getGCHandle() { @@ -125,7 +135,7 @@ { void *p; - debug(PRINTF) printf("_d_newclass(ci = %p)\n", ci); + debug(PRINTF) printf("_d_newclass(ci = %p, %s)\n", ci, cast(char *)ci.name); if (ci.flags & 1) // if COM object { p = cast(Object)std.c.stdlib.malloc(ci.init.length); @@ -137,6 +147,8 @@ p = _gc.malloc(ci.init.length); debug(PRINTF) printf(" p = %p\n", p); _gc.setFinalizer(p, &new_finalizer); + if (ci.flags & 2) + _gc.hasNoPointers(p); } debug (PRINTF) @@ -203,149 +215,108 @@ } } -Array _d_new(size_t length, size_t size) -{ - void *p; - Array result; - - debug(PRINTF) printf("_d_new(length = %d, size = %d)\n", length, size); - /* - if (length == 0 || size == 0) - result = 0; - else - */ - if (length && size) - { - p = _gc.malloc(length * size + 1); - debug(PRINTF) printf(" p = %p\n", p); - memset(p, 0, length * size); - result.length = length; - result.data = cast(byte*)p; - return result; - } - return result; -} -/+ -byte[] _d_new(uint length, uint size) -{ - void *p; - - debug(PRINTF) printf("_d_newarray(length = %d, size = %d)\n", length, size); - if (length && size) - { - p = _gc.malloc(length * size); - debug(PRINTF) printf(" p = %p\n", p); - memset(p, 0, length * size); - return (cast(byte*)p)[0..length]; - } else - return null; -} -+/ +/****************************************** + * Allocate a new array of length elements. + * ti is the type of the resulting array, or pointer to element. + */ -Array _d_newarrayip(size_t length, size_t size, void * init) +/* For when the array is initialized to 0 */ +Array _d_newarrayT(TypeInfo ti, size_t length) { Array result; + auto size = ti.next.tsize(); // array element size + debug(PRINTF) printf("_d_newT(length = %d, size = %d)\n", length, size); if (length && size) { result.length = length; - result.data = cast(byte*) _gc.malloc(length * size + 1); - if (size == 1) - memset(result.data, * cast(ubyte*) init, length); - else if (size == int.sizeof) - { - int init_val = *cast(int*)init; - void * p = result.data; - for (uint u = 0; u < length; u++) - { - (cast(int*)p)[u] = init_val; - } - } - else - { - void * p = result.data; - for (uint u = 0; u < length; u++) - { - memcpy(p, init, size); - p += size; - } - } + size *= length; + result.data = cast(byte*) _gc.malloc(size + 1); + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(result.data); + memset(result.data, 0, size); } return result; } -version (GNU) { } else -ulong _d_newarrayii(size_t length, size_t size, size_t isize ...) +/* For when the array has a non-zero initializer. + */ +Array _d_newarrayiT(TypeInfo ti, size_t length) { - void *p; - ulong result; + Array result; + auto size = ti.next.tsize(); // array element size - //debug(PRINTF) printf("_d_newarrayii(length = %d, size = %d, isize = %d)\n", length, size, isize); + //debug(PRINTF) printf("_d_newarrayiT(length = %d, size = %d, isize = %d)\n", length, size, isize); if (length == 0 || size == 0) - result = 0; + { } else { - //void* q = cast(void*)(&size + 1); // pointer to initializer - va_list q; - va_start!(size_t)(q, isize); // q is pointer to ... initializer + auto initializer = ti.next.init(); + auto isize = initializer.length; + auto q = initializer.ptr; size *= length; - p = _gc.malloc(size * isize + 1); + auto p = _gc.malloc(size + 1); debug(PRINTF) printf(" p = %p\n", p); + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(p); if (isize == 1) memset(p, *cast(ubyte*)q, size); else if (isize == int.sizeof) { int init = *cast(int*)q; - for (uint u = 0; u < size; u++) + size /= int.sizeof; + for (size_t u = 0; u < size; u++) { (cast(int*)p)[u] = init; } } else { - for (uint u = 0; u < size; u++) + for (size_t u = 0; u < size; u += isize) { - memcpy(p + u * isize, q, isize); + memcpy(p + u, q, isize); } } - va_end(q); - result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); + result.length = length; + result.data = cast(byte*) p ; } return result; } -void[] _d_newmp(size_t size, int ndims, size_t* pdim) +void[] _d_newarraymTp(TypeInfo ti, int ndims, size_t* pdim) { void[] result = void; //debug(PRINTF) - //printf("_d_newm(size = %d, ndims = %d)\n", size, ndims); - if (size == 0 || ndims == 0) + //printf("_d_newarraymT(ndims = %d)\n", ndims); + if (ndims == 0) result = null; else { - void[] foo(size_t* pdim, int ndims) + void[] foo(TypeInfo ti, size_t* pdim, int ndims) { size_t dim = *pdim; void[] p; + //printf("foo(ti = %p, ti.next = %p, dim = %d, ndims = %d\n", ti, ti.next, dim, ndims); if (ndims == 1) - { p = _gc.malloc(dim * size + 1)[0 .. dim]; - memset(p.ptr, 0, dim * size + 1); + { + auto r = _d_newarrayT(ti, dim); + p = *cast(void[]*)(&r); } else { p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim]; for (int i = 0; i < dim; i++) { - (cast(void[]*)p.ptr)[i] = foo(pdim + 1, ndims - 1); + (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); } } return p; } - result = foo(pdim, ndims); + result = foo(ti, pdim, ndims); //printf("result = %llx\n", result); version (none) @@ -359,47 +330,39 @@ return result; } -void[] _d_newarraymip(size_t size, int ndims, size_t* pdim, size_t mult, void* pinit) +void[] _d_newarraymiTp(TypeInfo ti, int ndims, size_t* pdim) { void[] result = void; //debug(PRINTF) //printf("_d_newarraymi(size = %d, ndims = %d)\n", size, ndims); - if (size == 0 || ndims == 0) + if (ndims == 0) result = null; else { - void[] foo(size_t* pdim, int ndims) + void[] foo(TypeInfo ti, size_t* pdim, int ndims) { size_t dim = *pdim; void[] p; if (ndims == 1) - { p = _gc.malloc(dim * mult * size + 1)[0 .. dim]; - if (size == 1) - memset(p.ptr, *cast(ubyte*)pinit, dim); - else - { - size_t n = dim * mult; - for (size_t u = 0; u < n; u++) - { - memcpy(p.ptr + u * size, pinit, size); - } - } + { + auto r = _d_newarrayiT(ti, dim); + p = *cast(void[]*)(&r); } else { p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim]; for (int i = 0; i < dim; i++) { - (cast(void[]*)p.ptr)[i] = foo(pdim + 1, ndims - 1); + (cast(void[]*)p.ptr)[i] = foo(ti.next, pdim + 1, ndims - 1); } } return p; } - result = foo(pdim, ndims); + result = foo(ti, pdim, ndims); //printf("result = %llx\n", result); version (none) @@ -414,31 +377,6 @@ return result; } -Array _d_newbitarray(size_t length, bit value) -{ - void *p; - Array result; - - debug(PRINTF) printf("_d_newbitarray(length = %d, value = %d)\n", length, value); - /* - if (length == 0) - result = 0; - else - */ - if (length) - { size_t size = ((length + 31) >> 5) * 4 + 1; // number of bytes - // (not sure what the extra byte is for...) - ubyte fill = value ? 0xFF : 0; - - p = _gc.malloc(size); - debug(PRINTF) printf(" p = %p\n", p); - memset(p, fill, size); - result.length = length; - result.data = cast(byte*)p; - } - return result; -} - struct Array { size_t length; @@ -520,19 +458,20 @@ */ extern (C) -byte[] _d_arraysetlength(size_t newlength, size_t sizeelem, Array *p) +byte[] _d_arraysetlengthT(TypeInfo ti, size_t newlength, Array *p) in { - assert(sizeelem); + assert(ti); assert(!p.length || p.data); } body { byte* newdata; + size_t sizeelem = ti.next.tsize(); debug(PRINTF) { - printf("_d_arraysetlength(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); + printf("_d_arraysetlengthT(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); if (p) printf("\tp.data = %p, p.length = %d\n", p.data, p.length); } @@ -580,6 +519,8 @@ { newdata = cast(byte *)_gc.malloc(newsize + 1); newdata[0 .. size] = p.data[0 .. size]; + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(newdata); } newdata[size .. newsize] = 0; } @@ -587,108 +528,8 @@ else { newdata = cast(byte *)_gc.calloc(newsize + 1, 1); - } - } - else - { - newdata = p.data; - } - - p.data = newdata; - p.length = newlength; - return newdata[0 .. newlength]; - -Loverflow: - _d_OutOfMemory(); -} - -/** - * Resize arrays for non-zero initializers. - * (obsolete, replaced by _d_arraysetlength3) - */ -extern (C) -byte[] _d_arraysetlength2p(size_t newlength, size_t sizeelem, Array *p, void * init) -in -{ - assert(sizeelem); - assert(!p.length || p.data); -} -body -{ - byte* newdata; - - debug(PRINTF) - { - printf("_d_arraysetlength2(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); - if (p) - printf("\tp.data = %p, p.length = %d\n", p.data, p.length); - } - - if (newlength) - { - version (GNU) - { - // required to output the label; - static char x = 0; - if (x) - goto Loverflow; - } - - version (D_InlineAsm_X86) - { - size_t newsize = void; - - asm - { - mov EAX,newlength ; - mul EAX,sizeelem ; - mov newsize,EAX ; - jc Loverflow ; - } - } - else - { - size_t newsize = sizeelem * newlength; - - if (newsize / newlength != sizeelem) - goto Loverflow; - } - //printf("newsize = %x, newlength = %x\n", newsize, newlength); - - size_t size = p.length * sizeelem; - if (p.data) - { - newdata = p.data; - if (newlength > p.length) - { - size_t cap = _gc.capacity(p.data); - - if (cap <= newsize) - { - newdata = cast(byte *)_gc.malloc(newsize + 1); - newdata[0 .. size] = p.data[0 .. size]; - } - } - } - else - { - newdata = cast(byte *)_gc.malloc(newsize + 1); - } - - if (newsize > size) - { - if (sizeelem == 1) - { - //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); - newdata[size .. newsize] = *(cast(byte*)init); - } - else - { - for (size_t u = size; u < newsize; u += sizeelem) - { - memcpy(newdata + u, init, sizeelem); - } - } + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(newdata); } } else @@ -713,23 +554,26 @@ * ... initializer */ extern (C) -byte[] _d_arraysetlength3p(size_t newlength, size_t sizeelem, Array *p, - size_t initsize, void *init) +byte[] _d_arraysetlengthiT(TypeInfo ti, size_t newlength, Array *p) in { - assert(sizeelem); - assert(initsize); - assert(initsize <= sizeelem); - assert((sizeelem / initsize) * initsize == sizeelem); assert(!p.length || p.data); } body { byte* newdata; + size_t sizeelem = ti.next.tsize(); + void[] initializer = ti.next.init(); + size_t initsize = initializer.length; + + assert(sizeelem); + assert(initsize); + assert(initsize <= sizeelem); + assert((sizeelem / initsize) * initsize == sizeelem); debug(PRINTF) { - printf("_d_arraysetlength3(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize); + printf("_d_arraysetlengthiT(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize); if (p) printf("\tp.data = %p, p.length = %d\n", p.data, p.length); } @@ -783,20 +627,24 @@ else { newdata = cast(byte *)_gc.malloc(newsize + 1); + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(newdata); } + auto q = initializer.ptr; // pointer to initializer + if (newsize > size) { if (initsize == 1) { //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); - newdata[size .. newsize] = *(cast(byte*)init); + newdata[size .. newsize] = *(cast(byte*)q); } else { for (size_t u = size; u < newsize; u += initsize) { - memcpy(newdata + u, init, initsize); + memcpy(newdata + u, q, initsize); } } } @@ -814,65 +662,15 @@ _d_OutOfMemory(); } -/*************************** - * Resize bit[] arrays. - */ - -version (none) -{ -extern (C) -bit[] _d_arraysetlengthb(size_t newlength, Array *p) -{ - byte* newdata; - size_t newsize; - - debug (PRINTF) - printf("p = %p, newlength = %d\n", p, newlength); - - assert(!p.length || p.data); - if (newlength) - { - newsize = ((newlength + 31) >> 5) * 4; // # bytes rounded up to uint - if (p.length) - { size_t size = ((p.length + 31) >> 5) * 4; - - newdata = p.data; - if (newsize > size) - { - size_t cap = _gc.capacity(p.data); - if (cap <= newsize) - { - newdata = cast(byte *)_gc.malloc(newsize + 1); - newdata[0 .. size] = p.data[0 .. size]; - } - newdata[size .. newsize] = 0; - } - } - else - { - newdata = cast(byte *)_gc.calloc(newsize + 1, 1); - } - } - else - { - newdata = null; - } - - p.data = newdata; - p.length = newlength; - return (cast(bit *)newdata)[0 .. newlength]; -} -} - /**************************************** * Append y[] to array x[]. * size is size of each array element. */ extern (C) -Array _d_arrayappend(Array *px, byte[] y, size_t size) +Array _d_arrayappendT(TypeInfo ti, Array *px, byte[] y) { - + auto size = ti.next.tsize(); // array element size size_t cap = _gc.capacity(px.data); size_t length = px.length; size_t newlength = length + y.length; @@ -880,6 +678,8 @@ { byte* newdata; newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size) + 1); + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(newdata); memcpy(newdata, px.data, length * size); px.data = newdata; } @@ -888,40 +688,6 @@ return *px; } -version (none) -{ -extern (C) -Array _d_arrayappendb(Array *px, bit[] y) -{ - - size_t cap = _gc.capacity(px.data); - size_t length = px.length; - size_t newlength = length + y.length; - size_t newsize = (newlength + 7) / 8; - if (newsize > cap) - { void* newdata; - - //newdata = _gc.malloc(newlength * size); - newdata = _gc.malloc(newCapacity(newsize, 1) + 1); - memcpy(newdata, px.data, (length + 7) / 8); - px.data = cast(byte*)newdata; - } - px.length = newlength; - if ((length & 7) == 0) - // byte aligned, straightforward copy - memcpy(px.data + length / 8, y, (y.length + 7) / 8); - else - { bit* x = cast(bit*)px.data; - - for (size_t u = 0; u < y.length; u++) - { - x[length + u] = y[u]; - } - } - return *px; -} -} - size_t newCapacity(size_t newlength, size_t size) { version(none) @@ -990,8 +756,9 @@ } extern (C) -byte[] _d_arrayappendcp(inout byte[] x, in size_t size, void *argp) +byte[] _d_arrayappendcTp(TypeInfo ti, inout byte[] x, void *argp) { + auto size = ti.next.tsize(); // array element size size_t cap = _gc.capacity(x.ptr); size_t length = x.length; size_t newlength = length + 1; @@ -1007,6 +774,8 @@ cap = newCapacity(newlength, size); assert(cap >= newlength * size); newdata = cast(byte *)_gc.malloc(cap + 1); + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(newdata); memcpy(newdata, x.ptr, length * size); (cast(void **)(&x))[1] = newdata; } @@ -1019,10 +788,11 @@ } extern (C) -byte[] _d_arraycat(byte[] x, byte[] y, size_t size) +byte[] _d_arraycatT(TypeInfo ti, byte[] x, byte[] y) out (result) { - //printf("_d_arraycat(%d,%p ~ %d,%p size = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, size, result.length, result.ptr); + auto size = ti.next.tsize(); // array element size + //printf("_d_arraycatT(%d,%p ~ %d,%p size = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, size, result.length, result.ptr); assert(result.length == x.length + y.length); for (size_t i = 0; i < x.length * size; i++) assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); @@ -1049,6 +819,9 @@ return y; } + //printf("_d_arraycatT(%d,%p ~ %d,%p)\n", x.length, x.ptr, y.length, y.ptr); + auto size = ti.next.tsize(); // array element size + //printf("_d_arraycatT(%d,%p ~ %d,%p size = %d)\n", x.length, x.ptr, y.length, y.ptr, size); size_t xlen = x.length * size; size_t ylen = y.length * size; size_t len = xlen + ylen; @@ -1056,6 +829,8 @@ return null; byte* p = cast(byte*)_gc.malloc(len + 1); + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(p); memcpy(p, x.ptr, xlen); memcpy(p + xlen, y.ptr, ylen); p[len] = 0; @@ -1064,20 +839,135 @@ } -version (none) -{ extern (C) -bit[] _d_arrayappendcb(inout bit[] x, bit b) -{ - if (x.length & 7) +byte[] _d_arraycatnT(TypeInfo ti, uint n, ...) +{ byte[] a; + size_t length; + byte[]* p; + uint i; + byte[] b; + va_list va; + auto size = ti.next.tsize(); // array element size + + va_start!(typeof(n))(va, n); + + for (i = 0; i < n; i++) { - *cast(size_t *)&x = x.length + 1; + b = va_arg!(typeof(b))(va); + length += b.length; + } + if (!length) + return null; + + a = new byte[length * size]; + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(a.ptr); + va_start!(typeof(n))(va, n); + + uint j = 0; + for (i = 0; i < n; i++) + { + b = va_arg!(typeof(b))(va); + if (b.length) + { + memcpy(&a[j], b.ptr, b.length * size); + j += b.length * size; + } } + + *cast(int *)&a = length; // jam length + //a.length = length; + return a; +} + +version (GNU) { } else +extern (C) +void* _d_arrayliteralT(TypeInfo ti, size_t length, ...) +{ + auto size = ti.next.tsize(); // array element size + byte[] result; + + //printf("_d_arrayliteralT(size = %d, length = %d)\n", size, length); + if (length == 0 || size == 0) + result = null; else { - x.length = x.length + 1; + result = new byte[length * size]; + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(result.ptr); + *cast(size_t *)&result = length; // jam length + + va_list q; + va_start!(size_t)(q, length); + + size_t stacksize = (size + int.sizeof - 1) & ~(int.sizeof - 1); + + if (stacksize == size) + { + memcpy(result.ptr, q, length * size); + } + else + { + for (size_t i = 0; i < length; i++) + { + memcpy(result.ptr + i * size, q, size); + q += stacksize; + } + } + + va_end(q); } - x[x.length - 1] = b; - return x; + return result.ptr; } + +/********************************** + * Support for array.dup property. + */ + +struct Array2 +{ + size_t length; + void* ptr; } + +extern (C) +Array2 _adDupT(TypeInfo ti, Array2 a) + out (result) + { + auto szelem = ti.next.tsize(); // array element size + assert(memcmp((*cast(Array2*)&result).ptr, a.ptr, a.length * szelem) == 0); + } + body + { + Array2 r; + + if (a.length) + { + auto szelem = ti.next.tsize(); // array element size + auto size = a.length * szelem; + r.ptr = cast(void *) new void[size]; + if (!(ti.next.flags() & 1)) + _gc.hasNoPointers(r.ptr); + r.length = a.length; + memcpy(r.ptr, a.ptr, size); + } + return r; + } + +unittest +{ + int[] a; + int[] b; + int i; + + debug(adi) printf("array.dup.unittest\n"); + + a = new int[3]; + a[0] = 1; a[1] = 2; a[2] = 3; + b = a.dup; + assert(b.length == 3); + for (i = 0; i < 3; i++) + assert(b[i] == i + 1); +} + + diff -uNr gdc-0.21/d/phobos/internal/gc/gcold.d gdc-0.22/d/phobos/internal/gc/gcold.d --- gdc-0.21/d/phobos/internal/gc/gcold.d 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.22/d/phobos/internal/gc/gcold.d 2007-02-03 18:35:36.000000000 +0100 @@ -0,0 +1,1015 @@ +/** + * Part of the D programming language runtime library. + */ + +/* + * Copyright (C) 2004-2007 by Digital Mars, www.digitalmars.com + * Written by Walter Bright + * + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * + * o The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * o Altered source versions must be plainly marked as such, and must not + * be misrepresented as being the original software. + * o This notice may not be removed or altered from any source + * distribution. + */ + + +/* Obsolete storage allocation functions, kept for link compatibility with + * older library binaries. + */ + +module std.gcold; + +//debug = PRINTF; + +import gc; + +extern (C) +Array _d_newarrayip(size_t length, size_t size, void * init) +{ + Array result; + + if (length && size) + { + result.length = length; + result.data = cast(byte*) _gc.malloc(length * size + 1); + if (size == 1) + memset(result.data, * cast(ubyte*) init, length); + else if (size == int.sizeof) + { + int init_val = *cast(int*)init; + void * p = result.data; + for (uint u = 0; u < length; u++) + { + (cast(int*)p)[u] = init_val; + } + } + else + { + void * p = result.data; + for (uint u = 0; u < length; u++) + { + memcpy(p, init, size); + p += size; + } + } + } + return result; +} + +version (GNU) { } else +extern (C) +ulong _d_newarrayii(size_t length, size_t size, size_t isize ...) +{ + void *p; + ulong result; + + //debug(PRINTF) printf("_d_newarrayii(length = %d, size = %d, isize = %d)\n", length, size, isize); + if (length == 0 || size == 0) + result = 0; + else + { + //void* q = cast(void*)(&size + 1); // pointer to initializer + va_list q; + va_start!(size_t)(q, isize); // q is pointer to ... initializer + size *= length; + p = _gc.malloc(size * isize + 1); + debug(PRINTF) printf(" p = %p\n", p); + if (isize == 1) + memset(p, *cast(ubyte*)q, size); + else if (isize == int.sizeof) + { + int init = *cast(int*)q; + for (uint u = 0; u < size; u++) + { + (cast(int*)p)[u] = init; + } + } + else + { + for (uint u = 0; u < size; u++) + { + memcpy(p + u * isize, q, isize); + } + } + va_end(q); + result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); + } + return result; +} + +extern (C) +void[] _d_newmp(size_t size, int ndims, size_t* pdim) +{ + void[] result = void; + + //debug(PRINTF) + //printf("_d_newm(size = %d, ndims = %d)\n", size, ndims); + if (size == 0 || ndims == 0) + result = null; + else + { + + void[] foo(size_t* pdim, int ndims) + { + size_t dim = *pdim; + void[] p; + + if (ndims == 1) + { p = _gc.malloc(dim * size + 1)[0 .. dim]; + memset(p.ptr, 0, dim * size + 1); + } + else + { + p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim]; + for (int i = 0; i < dim; i++) + { + (cast(void[]*)p.ptr)[i] = foo(pdim + 1, ndims - 1); + } + } + return p; + } + + result = foo(pdim, ndims); + //printf("result = %llx\n", result); + + version (none) + { + for (int i = 0; i < ndims; i++) + { + printf("index %d: %d\n", i, pdim[i]); + } + } + } + return result; +} + +extern (C) +void[] _d_newarraymip(size_t size, int ndims, size_t* pdim, size_t mult, void* pinit) +{ + void[] result = void; + + //debug(PRINTF) + //printf("_d_newarraymi(size = %d, ndims = %d)\n", size, ndims); + if (size == 0 || ndims == 0) + result = null; + else + { + + void[] foo(size_t* pdim, int ndims) + { + size_t dim = *pdim; + void[] p; + + if (ndims == 1) + { p = _gc.malloc(dim * mult * size + 1)[0 .. dim]; + if (size == 1) + memset(p.ptr, *cast(ubyte*)pinit, dim); + else + { + size_t n = dim * mult; + for (size_t u = 0; u < n; u++) + { + memcpy(p.ptr + u * size, pinit, size); + } + } + } + else + { + p = _gc.malloc(dim * (void[]).sizeof + 1)[0 .. dim]; + for (int i = 0; i < dim; i++) + { + (cast(void[]*)p.ptr)[i] = foo(pdim + 1, ndims - 1); + } + } + return p; + } + + result = foo(pdim, ndims); + //printf("result = %llx\n", result); + + version (none) + { + for (int i = 0; i < ndims; i++) + { + printf("index %d: %d\n", i, pdim[i]); + printf("init = %d\n", *cast(int*)pinit); + } + } + } + return result; +} + +/****************************************** + * Allocate a new array of length elements, each of size size. + * Initialize to 0. + */ + +extern (C) +Array _d_new(size_t length, size_t size) +{ + void *p; + Array result; + + debug(PRINTF) printf("_d_new(length = %d, size = %d)\n", length, size); + /* + if (length == 0 || size == 0) + result = 0; + else + */ + if (length && size) + { + p = _gc.malloc(length * size + 1); + debug(PRINTF) printf(" p = %p\n", p); + memset(p, 0, length * size); + result.length = length; + result.data = cast(byte*)p; + return result; + } + return result; +} + +extern (C) +byte[] _d_arraysetlength(size_t newlength, size_t sizeelem, Array *p) +in +{ + assert(sizeelem); + assert(!p.length || p.data); +} +body +{ + byte* newdata; + + debug(PRINTF) + { + printf("_d_arraysetlength(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); + if (p) + printf("\tp.data = %p, p.length = %d\n", p.data, p.length); + } + + if (newlength) + { + version (GNU) + { + // required to output the label; + static char x = 0; + if (x) + goto Loverflow; + } + + version (D_InlineAsm_X86) + { + size_t newsize = void; + + asm + { + mov EAX,newlength ; + mul EAX,sizeelem ; + mov newsize,EAX ; + jc Loverflow ; + } + } + else + { + size_t newsize = sizeelem * newlength; + + if (newsize / newlength != sizeelem) + goto Loverflow; + } + //printf("newsize = %x, newlength = %x\n", newsize, newlength); + + if (p.data) + { + newdata = p.data; + if (newlength > p.length) + { + size_t size = p.length * sizeelem; + size_t cap = _gc.capacity(p.data); + + if (cap <= newsize) + { + newdata = cast(byte *)_gc.malloc(newsize + 1); + newdata[0 .. size] = p.data[0 .. size]; + } + newdata[size .. newsize] = 0; + } + } + else + { + newdata = cast(byte *)_gc.calloc(newsize + 1, 1); + } + } + else + { + newdata = p.data; + } + + p.data = newdata; + p.length = newlength; + return newdata[0 .. newlength]; + +Loverflow: + _d_OutOfMemory(); +} + +/** + * Resize arrays for non-zero initializers. + * (obsolete, replaced by _d_arraysetlength3) + */ +extern (C) +byte[] _d_arraysetlength2p(size_t newlength, size_t sizeelem, Array *p, void * init) +in +{ + assert(sizeelem); + assert(!p.length || p.data); +} +body +{ + byte* newdata; + + debug(PRINTF) + { + printf("_d_arraysetlength2(p = %p, sizeelem = %d, newlength = %d)\n", p, sizeelem, newlength); + if (p) + printf("\tp.data = %p, p.length = %d\n", p.data, p.length); + } + + if (newlength) + { + version (GNU) + { + // required to output the label; + static char x = 0; + if (x) + goto Loverflow; + } + + version (D_InlineAsm_X86) + { + size_t newsize = void; + + asm + { + mov EAX,newlength ; + mul EAX,sizeelem ; + mov newsize,EAX ; + jc Loverflow ; + } + } + else + { + size_t newsize = sizeelem * newlength; + + if (newsize / newlength != sizeelem) + goto Loverflow; + } + //printf("newsize = %x, newlength = %x\n", newsize, newlength); + + size_t size = p.length * sizeelem; + if (p.data) + { + newdata = p.data; + if (newlength > p.length) + { + size_t cap = _gc.capacity(p.data); + + if (cap <= newsize) + { + newdata = cast(byte *)_gc.malloc(newsize + 1); + newdata[0 .. size] = p.data[0 .. size]; + } + } + } + else + { + newdata = cast(byte *)_gc.malloc(newsize + 1); + } + + if (newsize > size) + { + if (sizeelem == 1) + { + //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); + newdata[size .. newsize] = *(cast(byte*)init); + } + else + { + for (size_t u = size; u < newsize; u += sizeelem) + { + memcpy(newdata + u, init, sizeelem); + } + } + } + } + else + { + newdata = p.data; + } + + p.data = newdata; + p.length = newlength; + return newdata[0 .. newlength]; + +Loverflow: + _d_OutOfMemory(); +} + + +version (none) +{ +ulong _d_newbitarray(size_t length, bit value) +{ + void *p; + ulong result; + + debug(PRINTF) printf("_d_newbitarray(length = %d, value = %d)\n", length, value); + if (length == 0) + result = 0; + else + { size_t size = (length + 8) >> 3; // number of bytes + ubyte fill = value ? 0xFF : 0; + + p = _gc.malloc(size); + debug(PRINTF) printf(" p = %p\n", p); + memset(p, fill, size); + result = cast(ulong)length + (cast(ulong)cast(uint)p << 32); + } + return result; +} +} + +/*************************** + * Resize bit[] arrays. + */ + +version (none) +{ +extern (C) +bit[] _d_arraysetlengthb(size_t newlength, Array *p) +{ + byte* newdata; + size_t newsize; + + debug (PRINTF) + printf("p = %p, newlength = %d\n", p, newlength); + + assert(!p.length || p.data); + if (newlength) + { + newsize = ((newlength + 31) >> 5) * 4; // # bytes rounded up to uint + if (p.length) + { size_t size = ((p.length + 31) >> 5) * 4; + + newdata = p.data; + if (newsize > size) + { + size_t cap = _gc.capacity(p.data); + if (cap <= newsize) + { + newdata = cast(byte *)_gc.malloc(newsize + 1); + newdata[0 .. size] = p.data[0 .. size]; + } + newdata[size .. newsize] = 0; + } + } + else + { + newdata = cast(byte *)_gc.calloc(newsize + 1, 1); + } + } + else + { + newdata = null; + } + + p.data = newdata; + p.length = newlength; + return (cast(bit *)newdata)[0 .. newlength]; +} +} + +version (none) +{ +extern (C) +long _d_arrayappendb(Array *px, bit[] y) +{ + + size_t cap = _gc.capacity(px.data); + size_t length = px.length; + size_t newlength = length + y.length; + size_t newsize = (newlength + 7) / 8; + if (newsize > cap) + { void* newdata; + + //newdata = _gc.malloc(newlength * size); + newdata = _gc.malloc(newCapacity(newsize, 1) + 1); + memcpy(newdata, px.data, (length + 7) / 8); + px.data = cast(byte*)newdata; + } + px.length = newlength; + if ((length & 7) == 0) + // byte aligned, straightforward copy + memcpy(px.data + length / 8, y, (y.length + 7) / 8); + else + { bit* x = cast(bit*)px.data; + + for (size_t u = 0; u < y.length; u++) + { + x[length + u] = y[u]; + } + } + return *cast(long*)px; +} +} + +version (none) +{ +extern (C) +bit[] _d_arrayappendcb(inout bit[] x, bit b) +{ + if (x.length & 7) + { + *cast(size_t *)&x = x.length + 1; + } + else + { + x.length = x.length + 1; + } + x[x.length - 1] = b; + return x; +} +} + +/** + * Resize arrays for non-zero initializers. + * p pointer to array lvalue to be updated + * newlength new .length property of array + * sizeelem size of each element of array + * initsize size of initializer + * ... initializer + */ +extern (C) +byte[] _d_arraysetlength3p(size_t newlength, size_t sizeelem, Array *p, + size_t initsize, void *init) +in +{ + assert(sizeelem); + assert(initsize); + assert(initsize <= sizeelem); + assert((sizeelem / initsize) * initsize == sizeelem); + assert(!p.length || p.data); +} +body +{ + byte* newdata; + + debug(PRINTF) + { + printf("_d_arraysetlength3(p = %p, sizeelem = %d, newlength = %d, initsize = %d)\n", p, sizeelem, newlength, initsize); + if (p) + printf("\tp.data = %p, p.length = %d\n", p.data, p.length); + } + + if (newlength) + { + version (GNU) + { + // required to output the label; + static char x = 0; + if (x) + goto Loverflow; + } + + version (D_InlineAsm_X86) + { + size_t newsize = void; + + asm + { + mov EAX,newlength ; + mul EAX,sizeelem ; + mov newsize,EAX ; + jc Loverflow ; + } + } + else + { + size_t newsize = sizeelem * newlength; + + if (newsize / newlength != sizeelem) + goto Loverflow; + } + //printf("newsize = %x, newlength = %x\n", newsize, newlength); + + size_t size = p.length * sizeelem; + if (p.data) + { + newdata = p.data; + if (newlength > p.length) + { + size_t cap = _gc.capacity(p.data); + + if (cap <= newsize) + { + newdata = cast(byte *)_gc.malloc(newsize + 1); + newdata[0 .. size] = p.data[0 .. size]; + } + } + } + else + { + newdata = cast(byte *)_gc.malloc(newsize + 1); + } + + if (newsize > size) + { + if (initsize == 1) + { + //printf("newdata = %p, size = %d, newsize = %d, *q = %d\n", newdata, size, newsize, *cast(byte*)q); + newdata[size .. newsize] = *(cast(byte*)init); + } + else + { + for (size_t u = size; u < newsize; u += initsize) + { + memcpy(newdata + u, init, initsize); + } + } + } + } + else + { + newdata = p.data; + } + + p.data = newdata; + p.length = newlength; + return newdata[0 .. newlength]; + +Loverflow: + _d_OutOfMemory(); +} + + +extern (C) +Array _d_arrayappend(Array *px, byte[] y, size_t size) +{ + + size_t cap = _gc.capacity(px.data); + size_t length = px.length; + size_t newlength = length + y.length; + if (newlength * size > cap) + { byte* newdata; + + newdata = cast(byte *)_gc.malloc(newCapacity(newlength, size) + 1); + memcpy(newdata, px.data, length * size); + px.data = newdata; + } + px.length = newlength; + memcpy(px.data + length * size, y.ptr, y.length * size); + return *px; +} + + +extern (C) +byte[] _d_arrayappendcp(inout byte[] x, in size_t size, void *argp) +{ + size_t cap = _gc.capacity(x.ptr); + size_t length = x.length; + size_t newlength = length + 1; + + assert(cap == 0 || length * size <= cap); + + //printf("_d_arrayappendc(size = %d, ptr = %p, length = %d, cap = %d)\n", size, x.ptr, x.length, cap); + + if (newlength * size >= cap) + { byte* newdata; + + //printf("_d_arrayappendc(size = %d, newlength = %d, cap = %d)\n", size, newlength, cap); + cap = newCapacity(newlength, size); + assert(cap >= newlength * size); + newdata = cast(byte *)_gc.malloc(cap + 1); + memcpy(newdata, x.ptr, length * size); + (cast(void **)(&x))[1] = newdata; + } + + *cast(size_t *)&x = newlength; + (cast(byte *)x)[length * size .. newlength * size] = (cast(byte*)argp)[0 .. size]; + assert((cast(size_t)x.ptr & 15) == 0); + assert(_gc.capacity(x.ptr) > x.length * size); + return x; +} + + +extern (C) +byte[] _d_arraycat(byte[] x, byte[] y, size_t size) +out (result) +{ + //printf("_d_arraycat(%d,%p ~ %d,%p size = %d => %d,%p)\n", x.length, x.ptr, y.length, y.ptr, size, result.length, result.ptr); + assert(result.length == x.length + y.length); + for (size_t i = 0; i < x.length * size; i++) + assert((cast(byte*)result)[i] == (cast(byte*)x)[i]); + for (size_t i = 0; i < y.length * size; i++) + assert((cast(byte*)result)[x.length * size + i] == (cast(byte*)y)[i]); + + size_t cap = _gc.capacity(result.ptr); + assert(!cap || cap > result.length * size); +} +body +{ + version (none) + { + /* Cannot use this optimization because: + * char[] a, b; + * char c = 'a'; + * b = a ~ c; + * c = 'b'; + * will change the contents of b. + */ + if (!y.length) + return x; + if (!x.length) + return y; + } + + size_t xlen = x.length * size; + size_t ylen = y.length * size; + size_t len = xlen + ylen; + if (!len) + return null; + + byte* p = cast(byte*)_gc.malloc(len + 1); + memcpy(p, x.ptr, xlen); + memcpy(p + xlen, y.ptr, ylen); + p[len] = 0; + + return p[0 .. x.length + y.length]; +} + + +extern (C) +byte[] _d_arraycatn(uint size, uint n, ...) +{ byte[] a; + uint length; + uint i; + byte[] b; + va_list va; + + va_start!(typeof(n))(va, n); + + for (i = 0; i < n; i++) + { + b = va_arg!(typeof(b))(va); + length += b.length; + } + if (!length) + return null; + + a = new byte[length * size]; + va_start!(typeof(n))(va, n); + + uint j = 0; + for (i = 0; i < n; i++) + { + b = va_arg!(typeof(b))(va); + if (b.length) + { + memcpy(&a[j], b.ptr, b.length * size); + j += b.length * size; + } + } + + *cast(int *)&a = length; // jam length + //a.length = length; + return a; +} + +version (none) +{ +extern (C) +bit[] _d_arraycatb(bit[] x, bit[] y) +{ bit[] a; + uint a_length; + uint x_bytes; + + //printf("_d_arraycatb(x.ptr = %p, x.length = %d, y.ptr = %p, y.length = %d)\n", x.ptr, x.length, y.ptr, y.length); + if (!x.length) + return y; + if (!y.length) + return x; + + a_length = x.length + y.length; + a = new bit[a_length]; + x_bytes = (x.length + 7) >> 3; + memcpy(a.ptr, x.ptr, x_bytes); + if ((x.length & 7) == 0) + memcpy(cast(void*)a.ptr + x_bytes, y.ptr, (y.length + 7) >> 3); + else + { uint x_length = x.length; + uint y_length = y.length; + for (uint i = 0; i < y_length; i++) + a[x_length + i] = y[i]; + } + return a; +} +} + +version (none) +{ +extern (C) +bit[] _d_arraycopybit(bit[] from, bit[] to) +{ + //printf("f = %p,%d, t = %p,%d\n", (void*)from, from.length, (void*)to, to.length); + uint nbytes; + + if (to.length != from.length) + { + throw new Error("lengths don't match for array copy"); + } + else + { + nbytes = (to.length + 7) / 8; + if (cast(void *)to + nbytes <= cast(void *)from || + cast(void *)from + nbytes <= cast(void *)to) + { + nbytes = to.length / 8; + if (nbytes) + memcpy(cast(void *)to, cast(void *)from, nbytes); + + if (to.length & 7) + { + /* Copy trailing bits. + */ + static ubyte[8] masks = [0,1,3,7,0x0F,0x1F,0x3F,0x7F]; + ubyte mask = masks[to.length & 7]; + (cast(ubyte*)to)[nbytes] &= ~mask; + (cast(ubyte*)to)[nbytes] |= (cast(ubyte*)from)[nbytes] & mask; + } + } + else + { + throw new Error("overlapping array copy"); + } + } + return to; +} + +extern (C) +bit[] _d_arraysetbit(bit[] ba, uint lwr, uint upr, bit value) +in +{ + //printf("_d_arraysetbit(ba.length = %d, lwr = %u, upr = %u, value = %d)\n", ba.length, lwr, upr, value); + assert(lwr <= upr); + assert(upr <= ba.length); +} +body +{ + // Inefficient; lots of room for improvement here + for (uint i = lwr; i < upr; i++) + ba[i] = value; + + return ba; +} + +extern (C) +bit[] _d_arraysetbit2(bit[] ba, bit value) +{ + //printf("_d_arraysetbit2(ba.ptr = %p, ba.length = %d, value = %d)\n", ba.ptr, ba.length, value); + size_t len = ba.length; + uint val = -cast(int)value; + memset(ba.ptr, val, len >> 3); + for (uint i = len & ~7; i < len; i++) + ba[i] = value; + //printf("-_d_arraysetbit2(ba.ptr = %p, ba.length = %d, value = %d)\n", ba.ptr, ba.length, ba[0]); + return ba; +} +} + +version (GNU) { /* _d_arrayliteral not used; can't always be compiled */ } +else +extern (C) +void* _d_arrayliteral(size_t size, size_t length, ...) +{ + byte[] result; + + //printf("_d_arrayliteral(size = %d, length = %d)\n", size, length); + if (length == 0 || size == 0) + result = null; + else + { + result = new byte[length * size]; + *cast(size_t *)&result = length; // jam length + + va_list q; + va_start!(size_t)(q, length); + + size_t stacksize = (size + int.sizeof - 1) & ~(int.sizeof - 1); + + if (stacksize == size) + { + memcpy(result.ptr, q, length * size); + } + else + { + for (size_t i = 0; i < length; i++) + { + memcpy(result.ptr + i * size, q, size); + q += stacksize; + } + } + + va_end(q); + } + return result.ptr; +} + +/********************************** + * Support for array.dup property. + */ + +extern (C) Array _adDup(Array a, int szelem) + out (result) + { + assert(memcmp(result.ptr, a.ptr, a.length * szelem) == 0); + } + body + { + Array r; + + auto size = a.length * szelem; + r.ptr = cast(void *) new byte[size]; + r.length = a.length; + memcpy(r.ptr, a.ptr, size); + return r; + } + +unittest +{ + int[] a; + int[] b; + int i; + + debug(adi) printf("array.dup.unittest\n"); + + a = new int[3]; + a[0] = 1; a[1] = 2; a[2] = 3; + b = a.dup; + assert(b.length == 3); + for (i = 0; i < 3; i++) + assert(b[i] == i + 1); +} + +/********************************** + * Support for array.dup property for bit[]. + */ + +version (none) +{ +extern (C) Array _adDupBit(Array a) + out (result) + { + assert(memcmp(result.ptr, a.ptr, (a.length + 7) / 8) == 0); + } + body + { + Array r; + + auto size = (a.length + 31) / 32; + r.ptr = cast(void *) new uint[size]; + r.length = a.length; + memcpy(r.ptr, a.ptr, size * uint.sizeof); + return r; + } + +unittest +{ + bit[] a; + bit[] b; + int i; + + debug(adi) printf("array.dupBit[].unittest\n"); + + a = new bit[3]; + a[0] = 1; a[1] = 0; a[2] = 1; + b = a.dup; + assert(b.length == 3); + for (i = 0; i < 3; i++) + { debug(adi) printf("b[%d] = %d\n", i, b[i]); + assert(b[i] == (((i ^ 1) & 1) ? true : false)); + } +} +} + + + diff -uNr gdc-0.21/d/phobos/internal/gc/gcx.d gdc-0.22/d/phobos/internal/gc/gcx.d --- gdc-0.21/d/phobos/internal/gc/gcx.d 2006-09-04 18:43:38.000000000 +0200 +++ gdc-0.22/d/phobos/internal/gc/gcx.d 2007-02-03 17:34:12.000000000 +0100 @@ -423,9 +423,10 @@ synchronized (gcLock) { + biti = cast(uint)(p - pool.baseAddr) / 16; + pool.noptrs.clear(biti); if (pool.finals.nbits && gcx.finalizer) { - biti = cast(uint)(p - pool.baseAddr) / 16; if (pool.finals.testClear(biti)) { (*gcx.finalizer)(sentinel_add(p), null); @@ -693,6 +694,29 @@ } } + void hasPointers(void *p) + { + synchronized (gcLock) + { + gcx.HasPointers(p); + } + } + + void hasNoPointers(void *p) + { + if (!gcx.conservative) + { synchronized (gcLock) + { + gcx.HasNoPointers(p); + } + } + } + + void setV1_0() + { + gcx.conservative = 1; + } + void enable() { synchronized (gcLock) @@ -840,6 +864,7 @@ uint rangedim; Range *ranges; + uint conservative; // !=0 means conservative behavior uint noStack; // !=0 means don't scan stack uint log; // turn on logging uint anychanges; @@ -1397,8 +1422,10 @@ { //if (log) debug(PRINTF) printf("\t\tmarking %x\n", p); pool.mark.set(biti); - pool.scan.set(biti); - changes = 1; + if (!pool.noptrs.test(biti)) + { pool.scan.set(biti); + changes = 1; + } log_parent(sentinel_add(pool.baseAddr + biti * 16), sentinel_add(pbot)); } } @@ -1689,6 +1716,7 @@ sentinel_Invariant(sentinel_add(p)); pool.freebits.set(biti); + pool.noptrs.clear(biti); if (finalizer && pool.finals.nbits && pool.finals.testClear(biti)) { @@ -1712,6 +1740,7 @@ { byte *p = pool.baseAddr + pn * PAGESIZE; sentinel_Invariant(sentinel_add(p)); + pool.noptrs.clear(biti); if (finalizer && pool.finals.nbits && pool.finals.testClear(biti)) { @@ -1817,6 +1846,34 @@ } + /********************************* + * Indicate that block pointed to by p has possible pointers + * to GC allocated memory in it. + */ + + void HasPointers(void *p) + { + Pool *pool = findPool(p); + assert(pool); + + pool.noptrs.clear((p - pool.baseAddr) / 16); + } + + + /********************************* + * Indicate that block pointed to by p has no possible pointers + * to GC allocated memory in it. + */ + + void HasNoPointers(void *p) + { + //printf("HasNoPointers(%p)\n", p); + Pool *pool = findPool(p); + assert(pool); + + pool.noptrs.set((p - pool.baseAddr) / 16); + } + /***** Leak Detector ******/ debug (LOGGING) @@ -1950,10 +2007,11 @@ { byte* baseAddr; byte* topAddr; - GCBits mark; - GCBits scan; - GCBits finals; - GCBits freebits; + GCBits mark; // entries already scanned, or should not be scanned + GCBits scan; // entries that need to be scanned + GCBits finals; // entries that need finalizer run on them + GCBits freebits; // entries that are on the free list + GCBits noptrs; // entries that do not contain pointers uint npages; uint ncommitted; // ncommitted <= npages @@ -1985,6 +2043,7 @@ mark.alloc(poolsize / 16); scan.alloc(poolsize / 16); freebits.alloc(poolsize / 16); + noptrs.alloc(poolsize / 16); pagetable = cast(ubyte*)std.c.stdlib.malloc(npages); memset(pagetable, B_UNCOMMITTED, npages); diff -uNr gdc-0.21/d/phobos/internal/gc/linux.mak gdc-0.22/d/phobos/internal/gc/linux.mak --- gdc-0.21/d/phobos/internal/gc/linux.mak 2006-09-05 01:50:43.000000000 +0200 +++ gdc-0.22/d/phobos/internal/gc/linux.mak 2007-02-03 17:34:12.000000000 +0100 @@ -9,9 +9,9 @@ #DFLAGS=-release -inline -O CC=gcc -OBJS= gc.o gcx.o gcbits.o gclinux.o +OBJS= gc.o gcx.o gcbits.o gclinux.o gcold.o -SRC= gc.d gcx.d gcbits.d win32.d gclinux.d testgc.d win32.mak linux.mak +SRC= gc.d gcx.d gcbits.d win32.d gclinux.d gcold.d testgc.d win32.mak linux.mak .c.o: $(CC) -c $(CFLAGS) $* @@ -33,6 +33,9 @@ gc.o : gc.d $(DMD) -c $(DFLAGS) gc.d +gcold.o : gcold.d + $(DMD) -c $(DFLAGS) gcold.d + gcx.o : gcx.d $(DMD) -c $(DFLAGS) gcx.d gcbits.d diff -uNr gdc-0.21/d/phobos/internal/gc/win32.mak gdc-0.22/d/phobos/internal/gc/win32.mak --- gdc-0.21/d/phobos/internal/gc/win32.mak 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/internal/gc/win32.mak 2007-02-03 17:34:12.000000000 +0100 @@ -31,19 +31,22 @@ testgc.obj : testgc.d -OBJS= gc.obj gcx.obj gcbits.obj win32.obj +OBJS= gc.obj gcold.obj gcx.obj gcbits.obj win32.obj -SRC= gc.d gcx.d gcbits.d win32.d gclinux.d testgc.d win32.mak linux.mak +SRC= gc.d gcold.d gcx.d gcbits.d win32.d gclinux.d testgc.d win32.mak linux.mak dmgc.lib : $(OBJS) win32.mak del dmgc.lib - lib dmgc /c/noi +gc+gcx+gcbits+win32; + lib dmgc /c/noi +gc+gcold+gcx+gcbits+win32; gc.obj : gc.d - $(DMD) -c -release -inline -O $* + $(DMD) -c $(DFLAGS) $* + +gcold.obj : gcold.d + $(DMD) -c $(DFLAGS) $* gcx.obj : gcx.d gcbits.d - $(DMD) -c -release -inline -O gcx gcbits + $(DMD) -c $(DFLAGS) gcx gcbits #gcbits.obj : gcbits.d diff -uNr gdc-0.21/d/phobos/internal/object.d gdc-0.22/d/phobos/internal/object.d --- gdc-0.21/d/phobos/internal/object.d 2006-12-26 22:37:35.000000000 +0100 +++ gdc-0.22/d/phobos/internal/object.d 2007-02-03 17:34:12.000000000 +0100 @@ -267,12 +267,26 @@ void (*classInvariant)(Object); uint flags; // 1: // IUnknown + // 2: // has no possible pointers into GC memory + // 4: // has offTi[] member void *deallocator; + OffsetTypeInfo[] offTi; } private import std.string; /** + * Array of pairs giving the offset and type information for each + * member in an aggregate. + */ +struct OffsetTypeInfo +{ + size_t offset; /// Offset of member from start of object + TypeInfo ti; /// TypeInfo for this member +} + + +/** * Runtime type information about a type. * Can be retrieved for any type using a * TypeidExpression. @@ -325,6 +339,19 @@ (cast(byte *)p2)[i] = t; } } + + /// Get TypeInfo for 'next' type, as defined by what kind of type this is, + /// null if none. + TypeInfo next() { return null; } + + /// Return default initializer, null if default initialize to 0 + void[] init() { return null; } + + /// Get flags for type: 1 means GC should scan for pointers + uint flags() { return 0; } + + /// Get type information on the contents of the type; null if not available + OffsetTypeInfo[] offTi() { return null; } } class TypeInfo_Typedef : TypeInfo @@ -346,8 +373,13 @@ size_t tsize() { return base.tsize(); } void swap(void *p1, void *p2) { return base.swap(p1, p2); } + TypeInfo next() { return base.next(); } + uint flags() { return base.flags(); } + void[] init() { return m_init.length ? m_init : base.init(); } + TypeInfo base; char[] name; + void[] m_init; } class TypeInfo_Enum : TypeInfo_Typedef @@ -356,14 +388,14 @@ class TypeInfo_Pointer : TypeInfo { - char[] toString() { return next.toString() ~ "*"; } + char[] toString() { return m_next.toString() ~ "*"; } int opEquals(Object o) { TypeInfo_Pointer c; return this is o || ((c = cast(TypeInfo_Pointer)o) !is null && - this.next == c.next); + this.m_next == c.m_next); } hash_t getHash(void *p) @@ -393,27 +425,30 @@ *cast(void**)p2 = tmp; } - TypeInfo next; + TypeInfo next() { return m_next; } + uint flags() { return 1; } + + TypeInfo m_next; } class TypeInfo_Array : TypeInfo { - char[] toString() { return next.toString() ~ "[]"; } + char[] toString() { return value.toString() ~ "[]"; } int opEquals(Object o) { TypeInfo_Array c; return this is o || ((c = cast(TypeInfo_Array)o) !is null && - this.next == c.next); + this.value == c.value); } hash_t getHash(void *p) - { size_t sz = next.tsize(); + { size_t sz = value.tsize(); hash_t hash = 0; void[] a = *cast(void[]*)p; for (size_t i = 0; i < a.length; i++) - hash += next.getHash(a.ptr + i * sz); + hash += value.getHash(a.ptr + i * sz); return hash; } @@ -423,10 +458,10 @@ void[] a2 = *cast(void[]*)p2; if (a1.length != a2.length) return 0; - size_t sz = next.tsize(); + size_t sz = value.tsize(); for (size_t i = 0; i < a1.length; i++) { - if (!next.equals(a1.ptr + i * sz, a2.ptr + i * sz)) + if (!value.equals(a1.ptr + i * sz, a2.ptr + i * sz)) return 0; } return 1; @@ -436,14 +471,14 @@ { void[] a1 = *cast(void[]*)p1; void[] a2 = *cast(void[]*)p2; - size_t sz = next.tsize(); + size_t sz = value.tsize(); size_t len = a1.length; if (a2.length < len) len = a2.length; for (size_t u = 0; u < len; u++) { - int result = next.compare(a1.ptr + u * sz, a2.ptr + u * sz); + int result = value.compare(a1.ptr + u * sz, a2.ptr + u * sz); if (result) return result; } @@ -462,14 +497,21 @@ *cast(void[]*)p2 = tmp; } - TypeInfo next; + TypeInfo value; + + TypeInfo next() + { + return value; + } + + uint flags() { return 1; } } class TypeInfo_StaticArray : TypeInfo { char[] toString() { - return next.toString() ~ "[" ~ std.string.toString(len) ~ "]"; + return value.toString() ~ "[" ~ std.string.toString(len) ~ "]"; } int opEquals(Object o) @@ -478,24 +520,24 @@ return this is o || ((c = cast(TypeInfo_StaticArray)o) !is null && this.len == c.len && - this.next == c.next); + this.value == c.value); } hash_t getHash(void *p) - { size_t sz = next.tsize(); + { size_t sz = value.tsize(); hash_t hash = 0; for (size_t i = 0; i < len; i++) - hash += next.getHash(p + i * sz); + hash += value.getHash(p + i * sz); return hash; } int equals(void *p1, void *p2) { - size_t sz = next.tsize(); + size_t sz = value.tsize(); for (size_t u = 0; u < len; u++) { - if (!next.equals(p1 + u * sz, p2 + u * sz)) + if (!value.equals(p1 + u * sz, p2 + u * sz)) return 0; } return 1; @@ -503,11 +545,11 @@ int compare(void *p1, void *p2) { - size_t sz = next.tsize(); + size_t sz = value.tsize(); for (size_t u = 0; u < len; u++) { - int result = next.compare(p1 + u * sz, p2 + u * sz); + int result = value.compare(p1 + u * sz, p2 + u * sz); if (result) return result; } @@ -516,19 +558,19 @@ size_t tsize() { - return len * next.tsize(); + return len * value.tsize(); } void swap(void *p1, void *p2) - { ubyte* tmp; - size_t sz = next.tsize(); + { void* tmp; + size_t sz = value.tsize(); ubyte[16] buffer; - ubyte* pbuffer; + void* pbuffer; if (sz < buffer.sizeof) tmp = buffer.ptr; else - tmp = pbuffer = (new ubyte[sz]).ptr; + tmp = pbuffer = (new void[sz]).ptr; for (size_t u = 0; u < len; u += sz) { size_t o = u * sz; @@ -540,7 +582,11 @@ delete pbuffer; } - TypeInfo next; + void[] init() { return value.init(); } + TypeInfo next() { return value; } + uint flags() { return value.flags(); } + + TypeInfo value; size_t len; } @@ -548,7 +594,7 @@ { char[] toString() { - return next.toString() ~ "[" ~ key.toString() ~ "]"; + return value.toString() ~ "[" ~ key.toString() ~ "]"; } int opEquals(Object o) @@ -557,7 +603,7 @@ return this is o || ((c = cast(TypeInfo_AssociativeArray)o) !is null && this.key == c.key && - this.next == c.next); + this.value == c.value); } // BUG: need to add the rest of the functions @@ -567,7 +613,10 @@ return (char[int]).sizeof; } - TypeInfo next; + TypeInfo next() { return value; } + uint flags() { return 1; } + + TypeInfo value; TypeInfo key; } @@ -618,6 +667,8 @@ return dg.sizeof; } + uint flags() { return 1; } + TypeInfo next; } @@ -674,6 +725,13 @@ return Object.sizeof; } + uint flags() { return 1; } + + OffsetTypeInfo[] offTi() + { + return (info.flags & 4) ? info.offTi : null; + } + ClassInfo info; } @@ -735,6 +793,8 @@ return Object.sizeof; } + uint flags() { return 1; } + ClassInfo info; } @@ -827,13 +887,19 @@ return init.length; } + void[] init() { return m_init; } + + uint flags() { return m_flags; } + char[] name; - byte[] init; // initializer; init.ptr == null if 0 initialize + void[] m_init; // initializer; init.ptr == null if 0 initialize hash_t function(void*) xtoHash; int function(void*,void*) xopEquals; int function(void*,void*) xopCmp; char[] function(void*) xtoString; + + uint m_flags; } class TypeInfo_Tuple : TypeInfo diff -uNr gdc-0.21/d/phobos/linux.mak gdc-0.22/d/phobos/linux.mak --- gdc-0.21/d/phobos/linux.mak 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/phobos/linux.mak 2007-02-03 17:34:12.000000000 +0100 @@ -64,9 +64,9 @@ ti_float.o ti_double.o ti_real.o ti_delegate.o \ ti_creal.o ti_ireal.o ti_cfloat.o ti_ifloat.o \ ti_cdouble.o ti_idouble.o \ - ti_Aa.o ti_AC.o ti_Ag.o ti_Aubyte.o ti_Aushort.o ti_Ashort.o \ - ti_C.o ti_int.o ti_char.o ti_dchar.o ti_Adchar.o \ - ti_Aint.o ti_Auint.o ti_Along.o ti_Aulong.o ti_Awchar.o \ + ti_AC.o ti_Ag.o ti_Ashort.o \ + ti_C.o ti_int.o ti_char.o ti_dchar.o \ + ti_Aint.o ti_Along.o \ ti_Afloat.o ti_Adouble.o ti_Areal.o \ ti_Acfloat.o ti_Acdouble.o ti_Acreal.o \ ti_void.o \ @@ -79,7 +79,7 @@ etc/c/zlib/inflate.o etc/c/zlib/infback.o \ etc/c/zlib/inftrees.o etc/c/zlib/inffast.o -GC_OBJS= internal/gc/gc.o internal/gc/gcx.o \ +GC_OBJS= internal/gc/gc.o internal/gc/gcold.o internal/gc/gcx.o \ internal/gc/gcbits.o internal/gc/gclinux.o SRC= errno.c object.d unittest.d crc32.d gcstats.d @@ -111,19 +111,18 @@ std/typeinfo/ti_creal.d std/typeinfo/ti_ireal.d \ std/typeinfo/ti_cfloat.d std/typeinfo/ti_ifloat.d \ std/typeinfo/ti_cdouble.d std/typeinfo/ti_idouble.d \ - std/typeinfo/ti_Adchar.d std/typeinfo/ti_Aubyte.d \ - std/typeinfo/ti_Aushort.d std/typeinfo/ti_Ashort.d \ - std/typeinfo/ti_Aa.d std/typeinfo/ti_Ag.d \ + std/typeinfo/ti_Adchar.d \ + std/typeinfo/ti_Ashort.d \ + std/typeinfo/ti_Ag.d \ std/typeinfo/ti_AC.d std/typeinfo/ti_C.d \ std/typeinfo/ti_int.d std/typeinfo/ti_char.d \ - std/typeinfo/ti_Aint.d std/typeinfo/ti_Auint.d \ - std/typeinfo/ti_Along.d std/typeinfo/ti_Aulong.d \ + std/typeinfo/ti_Aint.d \ + std/typeinfo/ti_Along.d \ std/typeinfo/ti_Afloat.d std/typeinfo/ti_Adouble.d \ std/typeinfo/ti_Areal.d \ std/typeinfo/ti_Acfloat.d std/typeinfo/ti_Acdouble.d \ std/typeinfo/ti_Acreal.d \ - std/typeinfo/ti_void.d \ - std/typeinfo/ti_Awchar.d std/typeinfo/ti_dchar.d + std/typeinfo/ti_void.d SRC_INT= \ internal/switch.d internal/complex.c internal/critical.c \ @@ -180,6 +179,7 @@ etc/c/zlib\linux.mak SRC_GC= internal/gc/gc.d \ + internal/gc/gcold.d \ internal/gc/gcx.d \ internal/gc/gcstub.d \ internal/gc/gcbits.d \ @@ -196,6 +196,7 @@ #libphobos.a : $(OBJS) internal/gc/dmgc.a linux.mak libphobos.a : $(OBJS) internal/gc/dmgc.a $(ZLIB_OBJS) linux.mak + rm -f libphobos.a ar -r $@ $(OBJS) $(ZLIB_OBJS) $(GC_OBJS) ########################################################### @@ -527,9 +528,6 @@ ti_idouble.o : std/typeinfo/ti_idouble.d $(DMD) -c $(DFLAGS) std/typeinfo/ti_idouble.d -ti_Aa.o : std/typeinfo/ti_Aa.d - $(DMD) -c $(DFLAGS) std/typeinfo/ti_Aa.d - ti_AC.o : std/typeinfo/ti_AC.d $(DMD) -c $(DFLAGS) std/typeinfo/ti_AC.d @@ -539,24 +537,12 @@ ti_Abit.o : std/typeinfo/ti_Abit.d $(DMD) -c $(DFLAGS) std/typeinfo/ti_Abit.d -ti_Aubyte.o : std/typeinfo/ti_Aubyte.d - $(DMD) -c $(DFLAGS) std/typeinfo/ti_Aubyte.d - -ti_Aushort.o : std/typeinfo/ti_Aushort.d - $(DMD) -c $(DFLAGS) std/typeinfo/ti_Aushort.d - ti_Ashort.o : std/typeinfo/ti_Ashort.d $(DMD) -c $(DFLAGS) std/typeinfo/ti_Ashort.d -ti_Auint.o : std/typeinfo/ti_Auint.d - $(DMD) -c $(DFLAGS) std/typeinfo/ti_Auint.d - ti_Aint.o : std/typeinfo/ti_Aint.d $(DMD) -c $(DFLAGS) std/typeinfo/ti_Aint.d -ti_Aulong.o : std/typeinfo/ti_Aulong.d - $(DMD) -c $(DFLAGS) std/typeinfo/ti_Aulong.d - ti_Along.o : std/typeinfo/ti_Along.d $(DMD) -c $(DFLAGS) std/typeinfo/ti_Along.d @@ -578,12 +564,6 @@ ti_Acreal.o : std/typeinfo/ti_Acreal.d $(DMD) -c $(DFLAGS) std/typeinfo/ti_Acreal.d -ti_Awchar.o : std/typeinfo/ti_Awchar.d - $(DMD) -c $(DFLAGS) std/typeinfo/ti_Awchar.d - -ti_Adchar.o : std/typeinfo/ti_Adchar.d - $(DMD) -c $(DFLAGS) std/typeinfo/ti_Adchar.d - ti_C.o : std/typeinfo/ti_C.d $(DMD) -c $(DFLAGS) std/typeinfo/ti_C.d diff -uNr gdc-0.21/d/phobos/Makefile.in gdc-0.22/d/phobos/Makefile.in --- gdc-0.21/d/phobos/Makefile.in 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/Makefile.in 2007-02-03 18:35:36.000000000 +0100 @@ -105,8 +105,8 @@ testgc: internal/gc/testgc.o libgphobos_t.a libgphobos.a $(GDC) -o $@ $(CFLAGS) internal/gc/testgc.o -L./ -lgphobos_t $(LIBS) -TI=ti_AC.o ti_Aa.o ti_Adchar.o ti_Ag.o ti_Aint.o ti_Along.o ti_Ashort.o \ - ti_Aubyte.o ti_Auint.o ti_Aulong.o ti_Aushort.o ti_Awchar.o ti_C.o \ +TI=ti_AC.o ti_Ag.o ti_Aint.o ti_Along.o ti_Ashort.o \ + ti_C.o \ ti_byte.o ti_cdouble.o ti_cfloat.o ti_char.o ti_creal.o \ ti_dchar.o ti_delegate.o ti_double.o ti_float.o ti_idouble.o ti_ifloat.o \ ti_int.o ti_ireal.o ti_long.o ti_ptr.o ti_real.o ti_short.o ti_ubyte.o \ diff -uNr gdc-0.21/d/phobos/object.d gdc-0.22/d/phobos/object.d --- gdc-0.21/d/phobos/object.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/object.d 2007-02-03 17:34:12.000000000 +0100 @@ -44,7 +44,16 @@ void (*classInvariant)(Object); uint flags; // 1: // IUnknown + // 2: // has no possible pointers into GC memory + // 4: // has offTi[] member void *deallocator; + OffsetTypeInfo[] offTi; +} + +struct OffsetTypeInfo +{ + size_t offset; + TypeInfo ti; } class TypeInfo @@ -54,12 +63,18 @@ int compare(void *p1, void *p2); size_t tsize(); void swap(void *p1, void *p2); + TypeInfo next(); + void[] init(); + uint flags(); + // 1: // has possible pointers into GC memory + OffsetTypeInfo[] offTi(); } class TypeInfo_Typedef : TypeInfo { TypeInfo base; char[] name; + void[] m_init; } class TypeInfo_Enum : TypeInfo_Typedef @@ -68,23 +83,23 @@ class TypeInfo_Pointer : TypeInfo { - TypeInfo next; + TypeInfo m_next; } class TypeInfo_Array : TypeInfo { - TypeInfo next; + TypeInfo value; } class TypeInfo_StaticArray : TypeInfo { - TypeInfo next; + TypeInfo value; size_t len; } class TypeInfo_AssociativeArray : TypeInfo { - TypeInfo next; + TypeInfo value; TypeInfo key; } @@ -111,12 +126,14 @@ class TypeInfo_Struct : TypeInfo { char[] name; - byte[] init; + void[] m_init; uint function(void*) xtoHash; int function(void*,void*) xopEquals; int function(void*,void*) xopCmp; char[] function(void*) xtoString; + + uint m_flags; } class TypeInfo_Tuple : TypeInfo diff -uNr gdc-0.21/d/phobos/std/c/linux/linux.d.orig-dmd gdc-0.22/d/phobos/std/c/linux/linux.d.orig-dmd --- gdc-0.21/d/phobos/std/c/linux/linux.d.orig-dmd 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/phobos/std/c/linux/linux.d.orig-dmd 2007-02-03 17:34:12.000000000 +0100 @@ -11,6 +11,8 @@ public import std.c.linux.linuxextern; public import std.c.linux.pthread; +private import std.c.stdio; + alias int pid_t; alias int off_t; alias uint mode_t; @@ -136,6 +138,27 @@ int pipe(int[2]); pid_t wait(int*); int waitpid(pid_t, int*, int); + + uint alarm(uint); + char* basename(char*); + //wint_t btowc(int); + int chown(char*, uid_t, gid_t); + int chroot(char*); + size_t confstr(int, char*, size_t); + int creat(char*, mode_t); + char* ctermid(char*); + int dirfd(DIR*); + char* dirname(char*); + int fattach(int, char*); + int fchmod(int, mode_t); + int fdatasync(int); + int ffs(int); + int fmtmsg(int, char*, int, char*, char*, char*); + int fpathconf(int, int); + int fseeko(FILE*, off_t, int); + off_t ftello(FILE*); + + extern char** environ; } struct timeval diff -uNr gdc-0.21/d/phobos/std/compiler.d gdc-0.22/d/phobos/std/compiler.d --- gdc-0.21/d/phobos/std/compiler.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/compiler.d 2007-02-03 17:34:12.000000000 +0100 @@ -32,8 +32,8 @@ * The vendor specific version number, as in * version_major.version_minor */ - uint version_major = 0; - uint version_minor = 176; /// ditto + uint version_major = 1; + uint version_minor = 002; /// ditto /** diff -uNr gdc-0.21/d/phobos/std/conv.d gdc-0.22/d/phobos/std/conv.d --- gdc-0.21/d/phobos/std/conv.d 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/phobos/std/conv.d 2007-01-31 01:52:39.000000000 +0100 @@ -105,7 +105,7 @@ goto Lerr; int sign = 0; - int v = 0; + uint v = 0; for (int i = 0; i < length; i++) { @@ -133,13 +133,13 @@ } if (sign == -1) { - if (cast(uint)v > 0x80000000) + if (v > 0x80000000) goto Loverflow; v = -v; } else { - if (cast(uint)v > 0x7FFFFFFF) + if (v > 0x7FFFFFFF) goto Loverflow; } return v; @@ -324,7 +324,7 @@ goto Lerr; int sign = 0; - long v = 0; + ulong v = 0; for (int i = 0; i < length; i++) { @@ -352,13 +352,13 @@ } if (sign == -1) { - if (cast(ulong)v > 0x8000000000000000) + if (v > 0x8000000000000000) goto Loverflow; v = -v; } else { - if (cast(ulong)v > 0x7FFFFFFFFFFFFFFF) + if (v > 0x7FFFFFFFFFFFFFFF) goto Loverflow; } return v; diff -uNr gdc-0.21/d/phobos/std/date.d gdc-0.22/d/phobos/std/date.d --- gdc-0.21/d/phobos/std/date.d 2006-12-26 22:37:35.000000000 +0100 +++ gdc-0.22/d/phobos/std/date.d 2007-02-06 05:30:00.000000000 +0100 @@ -849,7 +849,7 @@ d_time getLocalTZA() { - return - ( _d_gnu_cbridge_tza() * TicksPerSecond ); + return _d_gnu_cbridge_tza() * TicksPerSecond; /+ int t; tm * t_tm; @@ -859,9 +859,9 @@ // %%TODO: handle systems without tm_gmtoff // %%TODO: configurate on _timezone instead of this.. version (cygwin) { - return _timzone * TicksPerSecond; + return -_timzone * TicksPerSecond; } else { - return -(t_tm.tm_gmtoff * TicksPerSecond); + return t_tm.tm_gmtoff * TicksPerSecond; } +/ } diff -uNr gdc-0.21/d/phobos/std/file.d gdc-0.22/d/phobos/std/file.d --- gdc-0.21/d/phobos/std/file.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/file.d 2007-02-03 17:34:12.000000000 +0100 @@ -1,3 +1,5 @@ +// Written in the D programming language. + /** * Macros: * WIKI = Phobos/StdFile @@ -39,6 +41,7 @@ private import std.path; private import std.string; private import std.regexp; +private import std.gc; /* =========================== Win32 ======================= */ @@ -97,10 +100,8 @@ void[] read(char[] name) { - DWORD size; DWORD numread; HANDLE h; - byte[] buf; if (useWfuncs) { @@ -118,11 +119,13 @@ if (h == INVALID_HANDLE_VALUE) goto err1; - size = GetFileSize(h, null); + auto size = GetFileSize(h, null); if (size == INVALID_FILE_SIZE) goto err2; - buf = new byte[size]; + auto buf = new void[size]; + if (buf.ptr) + std.gc.hasNoPointers(buf.ptr); if (ReadFile(h,buf.ptr,size,&numread,null) != 1) goto err2; @@ -461,14 +464,12 @@ { if (useWfuncs) { - wchar[] dir; - int len; wchar c; - len = GetCurrentDirectoryW(0, &c); + auto len = GetCurrentDirectoryW(0, &c); if (!len) goto Lerr; - dir = new wchar[len]; + auto dir = new wchar[len]; len = GetCurrentDirectoryW(len, dir.ptr); if (!len) goto Lerr; @@ -476,14 +477,12 @@ } else { - char[] dir; - int len; char c; - len = GetCurrentDirectoryA(0, &c); + auto len = GetCurrentDirectoryA(0, &c); if (!len) goto Lerr; - dir = new char[len]; + auto dir = new char[len]; len = GetCurrentDirectoryA(len, dir.ptr); if (!len) goto Lerr; @@ -891,16 +890,12 @@ void[] read(char[] name) { - uint size; uint numread; - int fd; struct_stat statbuf; - byte[] buf; - char *namez; - namez = toStringz(name); + auto namez = toStringz(name); //printf("file.read('%s')\n",namez); - fd = unix.open(namez, O_RDONLY); + auto fd = unix.open(namez, O_RDONLY); if (fd == -1) { //printf("\topen error, errno = %d\n",getErrno()); @@ -913,8 +908,10 @@ //printf("\tfstat error, errno = %d\n",getErrno()); goto err2; } - size = statbuf.st_size; - buf = new byte[size]; + auto size = statbuf.st_size; + auto buf = new void[size]; + if (buf.ptr) + std.gc.hasNoPointers(buf.ptr); numread = unix.read(fd, cast(char*)buf, size); if (numread != size) @@ -1213,14 +1210,13 @@ } else { - char* p; - p = unix.getcwd(null, 0); + auto p = unix.getcwd(null, 0); if (!p) { throw new FileException("cannot get cwd", getErrno()); } - size_t len = std.string.strlen(p); - char[] buf = new char[len]; + auto len = std.string.strlen(p); + auto buf = new char[len]; buf[] = p[0 .. len]; std.c.stdlib.free(p); return buf; diff -uNr gdc-0.21/d/phobos/std/gc.d gdc-0.22/d/phobos/std/gc.d --- gdc-0.21/d/phobos/std/gc.d 2006-12-26 22:37:35.000000000 +0100 +++ gdc-0.22/d/phobos/std/gc.d 2007-02-03 17:34:12.000000000 +0100 @@ -59,6 +59,27 @@ */ void removeRange(void *pbot); // remove range +/** + * Mark a gc allocated block of memory as possibly containing pointers. + */ +void hasPointers(void* p); + +/** + * Mark a gc allocated block of memory as definitely NOT containing pointers. + */ +void hasNoPointers(void* p); + +/** + * Mark a gc allocated block of memory pointed to by p as being populated with + * an array of TypeInfo ti (as many as will fit). + */ +void setTypeInfo(TypeInfo ti, void* p); + +/** + * Set gc behavior to match that of 1.0. + */ +void setV1_0(); + /*********************************** * Run a full garbage collection cycle. * diff -uNr gdc-0.21/d/phobos/std/outbuffer.d gdc-0.22/d/phobos/std/outbuffer.d --- gdc-0.21/d/phobos/std/outbuffer.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/outbuffer.d 2007-02-03 17:34:12.000000000 +0100 @@ -25,6 +25,7 @@ private { import std.string; + import std.gc; import std.c.stdio; import std.c.stdlib; import std.c.stdarg; @@ -85,6 +86,7 @@ if (data.length < offset + nbytes) { data.length = (offset + nbytes) * 2; + std.gc.hasPointers(data.ptr); } } diff -uNr gdc-0.21/d/phobos/std/random.d gdc-0.22/d/phobos/std/random.d --- gdc-0.21/d/phobos/std/random.d 2006-06-21 05:12:11.000000000 +0200 +++ gdc-0.22/d/phobos/std/random.d 2007-02-03 17:34:12.000000000 +0100 @@ -46,6 +46,9 @@ This means that the $(I n)th random number of the sequence can be directly generated by passing index + $(I n) to rand_seed(). + + Note: This is more random, but slower, than C's rand() function. + To use C's rand() instead, import std.c.stdlib. */ void rand_seed(uint seed, uint index) diff -uNr gdc-0.21/d/phobos/std/regexp.d gdc-0.22/d/phobos/std/regexp.d --- gdc-0.21/d/phobos/std/regexp.d 2006-12-27 01:43:34.000000000 +0100 +++ gdc-0.22/d/phobos/std/regexp.d 2007-02-03 18:35:36.000000000 +0100 @@ -204,8 +204,8 @@ char[] sub(char[] string, char[] pattern, char[] format, char[] attributes = null) { - RegExp r = new RegExp(pattern, attributes); - char[] result = r.replace(string, format); + auto r = new RegExp(pattern, attributes); + auto result = r.replace(string, format); delete r; return result; } @@ -244,7 +244,7 @@ char[] sub(char[] string, char[] pattern, char[] delegate(RegExp) dg, char[] attributes = null) { - RegExp r = new RegExp(pattern, attributes); + auto r = new RegExp(pattern, attributes); rchar[] result; int lastindex; int offset; @@ -334,7 +334,7 @@ { int i = -1; - RegExp r = new RegExp(pattern, attributes); + auto r = new RegExp(pattern, attributes); if (r.test(string)) { i = r.pmatch[0].rm_so; @@ -377,7 +377,7 @@ int i = -1; int lastindex = 0; - RegExp r = new RegExp(pattern, attributes); + auto r = new RegExp(pattern, attributes); while (r.test(string, lastindex)) { int eo = r.pmatch[0].rm_eo; i = r.pmatch[0].rm_so; @@ -432,8 +432,8 @@ char[][] split(char[] string, char[] pattern, char[] attributes = null) { - RegExp r = new RegExp(pattern, attributes); - char[][] result = r.split(string); + auto r = new RegExp(pattern, attributes); + auto result = r.split(string); delete r; return result; } @@ -485,7 +485,7 @@ RegExp search(char[] string, char[] pattern, char[] attributes = null) { - RegExp r = new RegExp(pattern, attributes); + auto r = new RegExp(pattern, attributes); if (r.test(string)) { @@ -885,7 +885,7 @@ { debug(regexp) printf("regexp.split.unittest()\n"); - RegExp r = new RegExp("a*?", null); + auto r = new RegExp("a*?", null); rchar[][] result; rchar[] j; int i; @@ -1125,9 +1125,7 @@ if (!test()) return null; - rchar[][] result; - - result = new rchar[][pmatch.length]; + auto result = new rchar[][pmatch.length]; for (int i = 0; i < pmatch.length; i++) { if (pmatch[i].rm_so == pmatch[i].rm_eo) @@ -2408,7 +2406,7 @@ offset = buf.offset; buf.write(cast(uint)0); // reserve space for length buf.reserve(128 / 8); - Range r = new Range(buf); + auto r = new Range(buf); if (op == REnotbit) r.setbit2(0); switch (pattern[p]) @@ -2757,8 +2755,8 @@ case REparen: case REgoto: { - OutBuffer bitbuf = new OutBuffer; - Range r = new Range(bitbuf); + auto bitbuf = new OutBuffer; + auto r = new Range(bitbuf); uint offset; offset = i; @@ -3138,24 +3136,23 @@ unittest { // Created and placed in public domain by Don Clugston - alias std.regexp regexp; - auto m = regexp.search("aBC r s", `bc\x20r[\40]s`, "i"); + auto m = search("aBC r s", `bc\x20r[\40]s`, "i"); assert(m.pre=="a"); assert(m.match(0)=="BC r s"); - auto m2 = regexp.search("7xxyxxx", `^\d([a-z]{2})\D\1`); + auto m2 = search("7xxyxxx", `^\d([a-z]{2})\D\1`); assert(m2.match(0)=="7xxyxx"); // Just check the parsing. - auto m3 = regexp.search("dcbxx", `ca|b[\d\]\D\s\S\w-\W]`); - auto m4 = regexp.search("xy", `[^\ca-\xFa\r\n\b\f\t\v\0123]{2,485}$`); - auto m5 = regexp.search("xxx", `^^\r\n\b{13,}\f{4}\t\v\u02aF3a\w\W`); - auto m6 = regexp.search("xxy", `.*y`); + auto m3 = search("dcbxx", `ca|b[\d\]\D\s\S\w-\W]`); + auto m4 = search("xy", `[^\ca-\xFa\r\n\b\f\t\v\0123]{2,485}$`); + auto m5 = search("xxx", `^^\r\n\b{13,}\f{4}\t\v\u02aF3a\w\W`); + auto m6 = search("xxy", `.*y`); assert(m6.match(0)=="xxy"); - auto m7 = regexp.search("QWDEfGH", "(ca|b|defg)+", "i"); + auto m7 = search("QWDEfGH", "(ca|b|defg)+", "i"); assert(m7.match(0)=="DEfG"); - auto m8 = regexp.search("dcbxx", `a?\B\s\S`); - auto m9 = regexp.search("dcbxx", `[-w]`); - auto m10 = regexp.search("dcbsfd", `aB[c-fW]dB|\d|\D|\u012356|\w|\W|\s|\S`, "i"); - auto m11 = regexp.search("dcbsfd", `[]a-]`); + auto m8 = search("dcbxx", `a?\B\s\S`); + auto m9 = search("dcbxx", `[-w]`); + auto m10 = search("dcbsfd", `aB[c-fW]dB|\d|\D|\u012356|\w|\W|\s|\S`, "i"); + auto m11 = search("dcbsfd", `[]a-]`); m.replaceOld(`a&b\1c`); m.replace(`a$&b$'$1c`); } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Aa.d gdc-0.22/d/phobos/std/typeinfo/ti_Aa.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Aa.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Aa.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,84 +0,0 @@ - -module std.typeinfo.Aa; - -private import std.string; -private import std.c.string; - -// char[] - -class TypeInfo_Aa : TypeInfo -{ - char[] toString() { return "char[]"; } - - hash_t getHash(void *p) - { char[] s = *cast(char[]*)p; - hash_t hash = 0; - -version (all) -{ - foreach (char c; s) - hash = hash * 11 + c; -} -else -{ - size_t len = s.length; - char *str = s; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(ubyte *)str; - return hash; - - case 2: - hash *= 9; - hash += *cast(ushort *)str; - return hash; - - case 3: - hash *= 9; - hash += (*cast(ushort *)str << 8) + - (cast(ubyte *)str)[2]; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 4; - len -= 4; - break; - } - } -} - return hash; - } - - int equals(void *p1, void *p2) - { - char[] s1 = *cast(char[]*)p1; - char[] s2 = *cast(char[]*)p2; - - return s1.length == s2.length && - memcmp(cast(char *)s1, cast(char *)s2, s1.length) == 0; - } - - int compare(void *p1, void *p2) - { - char[] s1 = *cast(char[]*)p1; - char[] s2 = *cast(char[]*)p2; - - return std.string.cmp(s1, s2); - } - - size_t tsize() - { - return (char[]).sizeof; - } -} - diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_AC.d gdc-0.22/d/phobos/std/typeinfo/ti_AC.d --- gdc-0.21/d/phobos/std/typeinfo/ti_AC.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_AC.d 2007-02-03 17:34:12.000000000 +0100 @@ -78,5 +78,15 @@ { return (Object[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(Object); + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Acdouble.d gdc-0.22/d/phobos/std/typeinfo/ti_Acdouble.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Acdouble.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Acdouble.d 2007-02-03 17:34:12.000000000 +0100 @@ -89,5 +89,15 @@ { return (cdouble[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(cdouble); + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Acfloat.d gdc-0.22/d/phobos/std/typeinfo/ti_Acfloat.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Acfloat.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Acfloat.d 2007-02-03 17:34:12.000000000 +0100 @@ -87,5 +87,15 @@ { return (cfloat[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(cfloat); + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Acreal.d gdc-0.22/d/phobos/std/typeinfo/ti_Acreal.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Acreal.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Acreal.d 2007-02-03 17:34:12.000000000 +0100 @@ -90,5 +90,15 @@ { return (creal[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(creal); + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Adchar.d gdc-0.22/d/phobos/std/typeinfo/ti_Adchar.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Adchar.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Adchar.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,60 +0,0 @@ - -module std.typeinfo.ti_Adchar; - -private import std.c.string; - -// dchar[] - -class TypeInfo_Aw : TypeInfo -{ - char[] toString() { return "dchar[]"; } - - hash_t getHash(void *p) - { dchar[] s = *cast(dchar[]*)p; - size_t len = s.length; - dchar *str = s.ptr; - hash_t hash = 0; - - while (len) - { - hash *= 9; - hash += *cast(uint *)str; - str++; - len--; - } - - return hash; - } - - int equals(void *p1, void *p2) - { - dchar[] s1 = *cast(dchar[]*)p1; - dchar[] s2 = *cast(dchar[]*)p2; - - return s1.length == s2.length && - memcmp(cast(void *)s1, cast(void *)s2, s1.length * dchar.sizeof) == 0; - } - - int compare(void *p1, void *p2) - { - dchar[] s1 = *cast(dchar[]*)p1; - dchar[] s2 = *cast(dchar[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (dchar[]).sizeof; - } -} - diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Adouble.d gdc-0.22/d/phobos/std/typeinfo/ti_Adouble.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Adouble.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Adouble.d 2007-02-03 17:34:12.000000000 +0100 @@ -87,6 +87,16 @@ { return (double[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(double); + } } // idouble[] @@ -94,4 +104,9 @@ class TypeInfo_Ap : TypeInfo_Ad { char[] toString() { return "idouble[]"; } + + TypeInfo next() + { + return typeid(idouble); + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Afloat.d gdc-0.22/d/phobos/std/typeinfo/ti_Afloat.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Afloat.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Afloat.d 2007-02-03 17:34:12.000000000 +0100 @@ -86,6 +86,16 @@ { return (float[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(float); + } } // ifloat[] @@ -93,4 +103,9 @@ class TypeInfo_Ao : TypeInfo_Af { char[] toString() { return "ifloat[]"; } + + TypeInfo next() + { + return typeid(ifloat); + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Ag.d gdc-0.22/d/phobos/std/typeinfo/ti_Ag.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Ag.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Ag.d 2007-02-03 17:34:12.000000000 +0100 @@ -1,6 +1,7 @@ module std.typeinfo.ti_Ag; +private import std.string; private import std.c.string; // byte[] @@ -80,5 +81,122 @@ { return (byte[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(byte); + } +} + + +// ubyte[] + +class TypeInfo_Ah : TypeInfo_Ag +{ + char[] toString() { return "ubyte[]"; } + + int compare(void *p1, void *p2) + { + char[] s1 = *cast(char[]*)p1; + char[] s2 = *cast(char[]*)p2; + + return std.string.cmp(s1, s2); + } + + TypeInfo next() + { + return typeid(ubyte); + } +} + +// void[] + +class TypeInfo_Av : TypeInfo_Ah +{ + char[] toString() { return "void[]"; } + + TypeInfo next() + { + return typeid(void); + } +} + +// bool[] + +class TypeInfo_Ab : TypeInfo_Ah +{ + char[] toString() { return "bool[]"; } + + TypeInfo next() + { + return typeid(bool); + } +} + +// char[] + +class TypeInfo_Aa : TypeInfo_Ag +{ + char[] toString() { return "char[]"; } + + hash_t getHash(void *p) + { char[] s = *cast(char[]*)p; + hash_t hash = 0; + +version (all) +{ + foreach (char c; s) + hash = hash * 11 + c; } +else +{ + size_t len = s.length; + char *str = s; + + while (1) + { + switch (len) + { + case 0: + return hash; + + case 1: + hash *= 9; + hash += *cast(ubyte *)str; + return hash; + + case 2: + hash *= 9; + hash += *cast(ushort *)str; + return hash; + + case 3: + hash *= 9; + hash += (*cast(ushort *)str << 8) + + (cast(ubyte *)str)[2]; + return hash; + + default: + hash *= 9; + hash += *cast(uint *)str; + str += 4; + len -= 4; + break; + } + } +} + return hash; + } + + TypeInfo next() + { + return typeid(char); + } +} + diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Aint.d gdc-0.22/d/phobos/std/typeinfo/ti_Aint.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Aint.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Aint.d 2007-02-03 17:34:12.000000000 +0100 @@ -56,5 +56,56 @@ { return (int[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(int); + } +} + +// uint[] + +class TypeInfo_Ak : TypeInfo_Ai +{ + char[] toString() { return "uint[]"; } + + int compare(void *p1, void *p2) + { + uint[] s1 = *cast(uint[]*)p1; + uint[] s2 = *cast(uint[]*)p2; + size_t len = s1.length; + + if (s2.length < len) + len = s2.length; + for (size_t u = 0; u < len; u++) + { + int result = s1[u] - s2[u]; + if (result) + return result; + } + return cast(int)s1.length - cast(int)s2.length; + } + + TypeInfo next() + { + return typeid(uint); + } +} + +// dchar[] + +class TypeInfo_Aw : TypeInfo_Ak +{ + char[] toString() { return "dchar[]"; } + + TypeInfo next() + { + return typeid(dchar); + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Along.d gdc-0.22/d/phobos/std/typeinfo/ti_Along.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Along.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Along.d 2007-02-03 17:34:12.000000000 +0100 @@ -18,7 +18,7 @@ while (len) { hash *= 9; - hash += *str; + hash += *cast(uint *)str + *(cast(uint *)str + 1); str++; len--; } @@ -57,5 +57,47 @@ { return (long[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(long); + } +} + + +// ulong[] + +class TypeInfo_Am : TypeInfo_Al +{ + char[] toString() { return "ulong[]"; } + + int compare(void *p1, void *p2) + { + ulong[] s1 = *cast(ulong[]*)p1; + ulong[] s2 = *cast(ulong[]*)p2; + size_t len = s1.length; + + if (s2.length < len) + len = s2.length; + for (size_t u = 0; u < len; u++) + { + if (s1[u] < s2[u]) + return -1; + else if (s1[u] > s2[u]) + return 1; + } + return cast(int)s1.length - cast(int)s2.length; + } + + TypeInfo next() + { + return typeid(ulong); + } } + diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Areal.d gdc-0.22/d/phobos/std/typeinfo/ti_Areal.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Areal.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Areal.d 2007-02-03 17:34:12.000000000 +0100 @@ -88,6 +88,16 @@ { return (real[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(real); + } } // ireal[] @@ -95,4 +105,9 @@ class TypeInfo_Aj : TypeInfo_Ae { char[] toString() { return "ireal[]"; } + + TypeInfo next() + { + return typeid(ireal); + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Ashort.d gdc-0.22/d/phobos/std/typeinfo/ti_Ashort.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Ashort.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Ashort.d 2007-02-03 17:34:12.000000000 +0100 @@ -24,7 +24,7 @@ case 1: hash *= 9; - hash += *cast(short *)str; + hash += *cast(ushort *)str; return hash; default: @@ -69,5 +69,58 @@ { return (short[]).sizeof; } + + uint flags() + { + return 1; + } + + TypeInfo next() + { + return typeid(short); + } } + +// ushort[] + +class TypeInfo_At : TypeInfo_As +{ + char[] toString() { return "ushort[]"; } + + int compare(void *p1, void *p2) + { + ushort[] s1 = *cast(ushort[]*)p1; + ushort[] s2 = *cast(ushort[]*)p2; + size_t len = s1.length; + + if (s2.length < len) + len = s2.length; + for (size_t u = 0; u < len; u++) + { + int result = s1[u] - s2[u]; + if (result) + return result; + } + return cast(int)s1.length - cast(int)s2.length; + } + + TypeInfo next() + { + return typeid(ushort); + } +} + +// wchar[] + +class TypeInfo_Au : TypeInfo_At +{ + char[] toString() { return "wchar[]"; } + + TypeInfo next() + { + return typeid(wchar); + } +} + + diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Aubyte.d gdc-0.22/d/phobos/std/typeinfo/ti_Aubyte.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Aubyte.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Aubyte.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,89 +0,0 @@ - -module std.typeinfo.ti_Aubyte; - -private import std.string; -private import std.c.string; - -// ubyte[] - -class TypeInfo_Ah : TypeInfo -{ - char[] toString() { return "ubyte[]"; } - - hash_t getHash(void *p) - { ubyte[] s = *cast(ubyte[]*)p; - size_t len = s.length; - ubyte *str = s.ptr; - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(ubyte *)str; - return hash; - - case 2: - hash *= 9; - hash += *cast(ushort *)str; - return hash; - - case 3: - hash *= 9; - hash += (*cast(ushort *)str << 8) + - (cast(ubyte *)str)[2]; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 4; - len -= 4; - break; - } - } - - return hash; - } - - int equals(void *p1, void *p2) - { - ubyte[] s1 = *cast(ubyte[]*)p1; - ubyte[] s2 = *cast(ubyte[]*)p2; - - return s1.length == s2.length && - memcmp(cast(ubyte *)s1, cast(ubyte *)s2, s1.length) == 0; - } - - int compare(void *p1, void *p2) - { - char[] s1 = *cast(char[]*)p1; - char[] s2 = *cast(char[]*)p2; - - return std.string.cmp(s1, s2); - } - - size_t tsize() - { - return (ubyte[]).sizeof; - } -} - -// void[] - -class TypeInfo_Av : TypeInfo_Ah -{ - char[] toString() { return "void[]"; } -} - -// bool[] - -class TypeInfo_Ab : TypeInfo_Ah -{ - char[] toString() { return "bool[]"; } -} diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Auint.d gdc-0.22/d/phobos/std/typeinfo/ti_Auint.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Auint.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Auint.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,60 +0,0 @@ - -module std.typeinfo.ti_Auint; - -private import std.c.string; - -// uint[] - -class TypeInfo_Ak : TypeInfo -{ - char[] toString() { return "uint[]"; } - - hash_t getHash(void *p) - { uint[] s = *cast(uint[]*)p; - size_t len = s.length; - auto str = s.ptr; - hash_t hash = 0; - - while (len) - { - hash *= 9; - hash += *cast(uint *)str; - str++; - len--; - } - - return hash; - } - - int equals(void *p1, void *p2) - { - uint[] s1 = *cast(uint[]*)p1; - uint[] s2 = *cast(uint[]*)p2; - - return s1.length == s2.length && - memcmp(cast(void *)s1, cast(void *)s2, s1.length * uint.sizeof) == 0; - } - - int compare(void *p1, void *p2) - { - uint[] s1 = *cast(uint[]*)p1; - uint[] s2 = *cast(uint[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (uint[]).sizeof; - } -} - diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Aulong.d gdc-0.22/d/phobos/std/typeinfo/ti_Aulong.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Aulong.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Aulong.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,61 +0,0 @@ - -module std.typeinfo.ti_Aulong; - -private import std.c.string; - -// ulong[] - -class TypeInfo_Am : TypeInfo -{ - char[] toString() { return "ulong[]"; } - - hash_t getHash(void *p) - { ulong[] s = *cast(ulong[]*)p; - size_t len = s.length; - auto str = s.ptr; - hash_t hash = 0; - - while (len) - { - hash *= 9; - hash += *cast(uint *)str; - str += 1; - len -= 1; - } - - return hash; - } - - int equals(void *p1, void *p2) - { - ulong[] s1 = *cast(ulong[]*)p1; - ulong[] s2 = *cast(ulong[]*)p2; - - return s1.length == s2.length && - memcmp(cast(void *)s1, cast(void *)s2, s1.length * ulong.sizeof) == 0; - } - - int compare(void *p1, void *p2) - { - ulong[] s1 = *cast(ulong[]*)p1; - ulong[] s2 = *cast(ulong[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - if (s1[u] < s2[u]) - return -1; - else if (s1[u] > s2[u]) - return 1; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (ulong[]).sizeof; - } -} - diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Aushort.d gdc-0.22/d/phobos/std/typeinfo/ti_Aushort.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Aushort.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Aushort.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,73 +0,0 @@ - -module std.typeinfo.ti_Aushort; - -private import std.c.string; - -// ushort[] - -class TypeInfo_At : TypeInfo -{ - char[] toString() { return "ushort[]"; } - - hash_t getHash(void *p) - { ushort[] s = *cast(ushort[]*)p; - size_t len = s.length; - ushort *str = s.ptr; - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(ushort *)str; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 2; - len -= 2; - break; - } - } - - return hash; - } - - int equals(void *p1, void *p2) - { - ushort[] s1 = *cast(ushort[]*)p1; - ushort[] s2 = *cast(ushort[]*)p2; - - return s1.length == s2.length && - memcmp(cast(void *)s1, cast(void *)s2, s1.length * ushort.sizeof) == 0; - } - - int compare(void *p1, void *p2) - { - ushort[] s1 = *cast(ushort[]*)p1; - ushort[] s2 = *cast(ushort[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (ushort[]).sizeof; - } -} - diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_Awchar.d gdc-0.22/d/phobos/std/typeinfo/ti_Awchar.d --- gdc-0.21/d/phobos/std/typeinfo/ti_Awchar.d 2006-12-17 06:03:04.000000000 +0100 +++ gdc-0.22/d/phobos/std/typeinfo/ti_Awchar.d 1970-01-01 01:00:00.000000000 +0100 @@ -1,73 +0,0 @@ - -module std.typeinfo.ti_Awchar; - -private import std.c.string; - -// wchar[] - -class TypeInfo_Au : TypeInfo -{ - char[] toString() { return "wchar[]"; } - - hash_t getHash(void *p) - { wchar[] s = *cast(wchar[]*)p; - size_t len = s.length; - auto str = s.ptr; - hash_t hash = 0; - - while (1) - { - switch (len) - { - case 0: - return hash; - - case 1: - hash *= 9; - hash += *cast(wchar *)str; - return hash; - - default: - hash *= 9; - hash += *cast(uint *)str; - str += 2; - len -= 2; - break; - } - } - - return hash; - } - - int equals(void *p1, void *p2) - { - wchar[] s1 = *cast(wchar[]*)p1; - wchar[] s2 = *cast(wchar[]*)p2; - - return s1.length == s2.length && - memcmp(cast(void *)s1, cast(void *)s2, s1.length * wchar.sizeof) == 0; - } - - int compare(void *p1, void *p2) - { - wchar[] s1 = *cast(wchar[]*)p1; - wchar[] s2 = *cast(wchar[]*)p2; - size_t len = s1.length; - - if (s2.length < len) - len = s2.length; - for (size_t u = 0; u < len; u++) - { - int result = s1[u] - s2[u]; - if (result) - return result; - } - return cast(int)s1.length - cast(int)s2.length; - } - - size_t tsize() - { - return (wchar[]).sizeof; - } -} - diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_C.d gdc-0.22/d/phobos/std/typeinfo/ti_C.d --- gdc-0.21/d/phobos/std/typeinfo/ti_C.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_C.d 2007-02-03 17:34:12.000000000 +0100 @@ -67,5 +67,10 @@ { return Object.sizeof; } + + uint flags() + { + return 1; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_cdouble.d gdc-0.22/d/phobos/std/typeinfo/ti_cdouble.d --- gdc-0.21/d/phobos/std/typeinfo/ti_cdouble.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_cdouble.d 2007-02-03 17:34:12.000000000 +0100 @@ -57,5 +57,11 @@ *cast(cdouble *)p1 = *cast(cdouble *)p2; *cast(cdouble *)p2 = t; } + + void[] init() + { static cdouble r; + + return (cast(cdouble *)&r)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_cfloat.d gdc-0.22/d/phobos/std/typeinfo/ti_cfloat.d --- gdc-0.21/d/phobos/std/typeinfo/ti_cfloat.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_cfloat.d 2007-02-03 17:34:12.000000000 +0100 @@ -56,5 +56,11 @@ *cast(cfloat *)p1 = *cast(cfloat *)p2; *cast(cfloat *)p2 = t; } + + void[] init() + { static cfloat r; + + return (cast(cfloat *)&r)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_char.d gdc-0.22/d/phobos/std/typeinfo/ti_char.d --- gdc-0.21/d/phobos/std/typeinfo/ti_char.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_char.d 2007-02-03 17:34:12.000000000 +0100 @@ -33,5 +33,11 @@ *cast(char *)p1 = *cast(char *)p2; *cast(char *)p2 = t; } + + void[] init() + { static char c; + + return (cast(char *)&c)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_creal.d gdc-0.22/d/phobos/std/typeinfo/ti_creal.d --- gdc-0.21/d/phobos/std/typeinfo/ti_creal.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_creal.d 2007-02-03 17:34:12.000000000 +0100 @@ -58,5 +58,11 @@ *cast(creal *)p1 = *cast(creal *)p2; *cast(creal *)p2 = t; } + + void[] init() + { static creal r; + + return (cast(creal *)&r)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_dchar.d gdc-0.22/d/phobos/std/typeinfo/ti_dchar.d --- gdc-0.21/d/phobos/std/typeinfo/ti_dchar.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_dchar.d 2007-02-03 17:34:12.000000000 +0100 @@ -35,5 +35,11 @@ *cast(dchar *)p1 = *cast(dchar *)p2; *cast(dchar *)p2 = t; } + + void[] init() + { static dchar c; + + return (cast(dchar *)&c)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_delegate.d gdc-0.22/d/phobos/std/typeinfo/ti_delegate.d --- gdc-0.21/d/phobos/std/typeinfo/ti_delegate.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_delegate.d 2007-02-03 17:34:12.000000000 +0100 @@ -31,5 +31,10 @@ *cast(dg *)p1 = *cast(dg *)p2; *cast(dg *)p2 = t; } + + uint flags() + { + return 1; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_double.d gdc-0.22/d/phobos/std/typeinfo/ti_double.d --- gdc-0.21/d/phobos/std/typeinfo/ti_double.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_double.d 2007-02-03 17:34:12.000000000 +0100 @@ -57,5 +57,11 @@ *cast(double *)p1 = *cast(double *)p2; *cast(double *)p2 = t; } + + void[] init() + { static double r; + + return (cast(double *)&r)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_float.d gdc-0.22/d/phobos/std/typeinfo/ti_float.d --- gdc-0.21/d/phobos/std/typeinfo/ti_float.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_float.d 2007-02-03 17:34:12.000000000 +0100 @@ -57,5 +57,11 @@ *cast(float *)p1 = *cast(float *)p2; *cast(float *)p2 = t; } + + void[] init() + { static float r; + + return (cast(float *)&r)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_ptr.d gdc-0.22/d/phobos/std/typeinfo/ti_ptr.d --- gdc-0.21/d/phobos/std/typeinfo/ti_ptr.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_ptr.d 2007-02-03 17:34:12.000000000 +0100 @@ -33,5 +33,10 @@ *cast(void* *)p1 = *cast(void* *)p2; *cast(void* *)p2 = t; } + + uint flags() + { + return 1; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_real.d gdc-0.22/d/phobos/std/typeinfo/ti_real.d --- gdc-0.21/d/phobos/std/typeinfo/ti_real.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_real.d 2007-02-03 17:34:12.000000000 +0100 @@ -57,5 +57,11 @@ *cast(real *)p1 = *cast(real *)p2; *cast(real *)p2 = t; } + + void[] init() + { static real r; + + return (cast(real *)&r)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_void.d gdc-0.22/d/phobos/std/typeinfo/ti_void.d --- gdc-0.21/d/phobos/std/typeinfo/ti_void.d 2006-06-21 05:12:11.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_void.d 2007-02-03 17:34:12.000000000 +0100 @@ -35,5 +35,10 @@ *cast(byte *)p1 = *cast(byte *)p2; *cast(byte *)p2 = t; } + + uint flags() + { + return 1; + } } diff -uNr gdc-0.21/d/phobos/std/typeinfo/ti_wchar.d gdc-0.22/d/phobos/std/typeinfo/ti_wchar.d --- gdc-0.21/d/phobos/std/typeinfo/ti_wchar.d 2006-06-02 05:31:29.000000000 +0200 +++ gdc-0.22/d/phobos/std/typeinfo/ti_wchar.d 2007-02-03 17:34:12.000000000 +0100 @@ -34,5 +34,11 @@ *cast(wchar *)p1 = *cast(wchar *)p2; *cast(wchar *)p2 = t; } + + void[] init() + { static wchar c; + + return (cast(wchar *)&c)[0 .. 1]; + } } diff -uNr gdc-0.21/d/phobos/win32.mak gdc-0.22/d/phobos/win32.mak --- gdc-0.21/d/phobos/win32.mak 2007-01-03 07:23:08.000000000 +0100 +++ gdc-0.22/d/phobos/win32.mak 2007-02-03 17:34:12.000000000 +0100 @@ -75,18 +75,18 @@ errno.obj boxer.obj cstream.obj charset.obj \ gamma.obj demangle.obj cover.obj bitarray.obj aApplyR.obj \ signals.obj cpuid.obj typetuple.obj traits.obj bind.obj \ - ti_Aa.obj ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \ + ti_Ag.obj ti_C.obj ti_int.obj ti_char.obj \ ti_wchar.obj ti_uint.obj ti_short.obj ti_ushort.obj \ ti_byte.obj ti_ubyte.obj ti_long.obj ti_ulong.obj ti_ptr.obj \ ti_float.obj ti_double.obj ti_real.obj ti_delegate.obj \ ti_creal.obj ti_ireal.obj \ ti_cfloat.obj ti_ifloat.obj \ ti_cdouble.obj ti_idouble.obj \ - ti_AC.obj ti_Aubyte.obj ti_Aushort.obj ti_Ashort.obj \ - ti_Aint.obj ti_Auint.obj ti_Along.obj ti_Aulong.obj ti_Awchar.obj \ + ti_AC.obj ti_Ashort.obj \ + ti_Aint.obj ti_Along.obj \ ti_Afloat.obj ti_Adouble.obj ti_Areal.obj \ ti_Acfloat.obj ti_Acdouble.obj ti_Acreal.obj \ - ti_dchar.obj ti_Adchar.obj ti_void.obj + ti_dchar.obj ti_void.obj # ti_bit.obj ti_Abit.obj @@ -160,28 +160,24 @@ std\typeinfo\ti_short.d std\typeinfo\ti_ushort.d \ std\typeinfo\ti_byte.d std\typeinfo\ti_ubyte.d \ std\typeinfo\ti_long.d std\typeinfo\ti_ulong.d \ - std\typeinfo\ti_ptr.d \ + std\typeinfo\ti_ptr.d std\typeinfo\ti_dchar.d \ std\typeinfo\ti_float.d std\typeinfo\ti_double.d \ std\typeinfo\ti_real.d std\typeinfo\ti_delegate.d \ std\typeinfo\ti_creal.d std\typeinfo\ti_ireal.d \ std\typeinfo\ti_cfloat.d std\typeinfo\ti_ifloat.d \ std\typeinfo\ti_cdouble.d std\typeinfo\ti_idouble.d \ - std\typeinfo\ti_Adchar.d std\typeinfo\ti_Aubyte.d \ - std\typeinfo\ti_Aushort.d std\typeinfo\ti_Ashort.d \ - std\typeinfo\ti_Aa.d std\typeinfo\ti_Ag.d \ + std\typeinfo\ti_Ashort.d \ + std\typeinfo\ti_Ag.d \ std\typeinfo\ti_AC.d std\typeinfo\ti_C.d \ std\typeinfo\ti_int.d std\typeinfo\ti_char.d \ - std\typeinfo\ti_Aint.d std\typeinfo\ti_Auint.d \ - std\typeinfo\ti_Along.d std\typeinfo\ti_Aulong.d \ + std\typeinfo\ti_Aint.d \ + std\typeinfo\ti_Along.d \ std\typeinfo\ti_Afloat.d std\typeinfo\ti_Adouble.d \ std\typeinfo\ti_Areal.d \ std\typeinfo\ti_Acfloat.d std\typeinfo\ti_Acdouble.d \ std\typeinfo\ti_Acreal.d \ - std\typeinfo\ti_Awchar.d std\typeinfo\ti_dchar.d \ std\typeinfo\ti_void.d -# std\typeinfo\ti_bit.d std\typeinfo\ti_Abit.d - SRC_INT= \ internal\switch.d internal\complex.c internal\critical.c \ internal\minit.asm internal\alloca.d internal\llmath.d internal\deh.c \ @@ -237,6 +233,7 @@ etc\c\zlib\linux.mak SRC_GC= internal\gc\gc.d \ + internal\gc\gcold.d \ internal\gc\gcx.d \ internal\gc\gcstub.d \ internal\gc\gcbits.d \ @@ -592,9 +589,6 @@ ti_idouble.obj : std\typeinfo\ti_idouble.d $(DMD) -c $(DFLAGS) std\typeinfo\ti_idouble.d -ti_Aa.obj : std\typeinfo\ti_Aa.d - $(DMD) -c $(DFLAGS) std\typeinfo\ti_Aa.d - ti_AC.obj : std\typeinfo\ti_AC.d $(DMD) -c $(DFLAGS) std\typeinfo\ti_AC.d @@ -604,24 +598,12 @@ ti_Abit.obj : std\typeinfo\ti_Abit.d $(DMD) -c $(DFLAGS) std\typeinfo\ti_Abit.d -ti_Aubyte.obj : std\typeinfo\ti_Aubyte.d - $(DMD) -c $(DFLAGS) std\typeinfo\ti_Aubyte.d - -ti_Aushort.obj : std\typeinfo\ti_Aushort.d - $(DMD) -c $(DFLAGS) std\typeinfo\ti_Aushort.d - ti_Ashort.obj : std\typeinfo\ti_Ashort.d $(DMD) -c $(DFLAGS) std\typeinfo\ti_Ashort.d -ti_Auint.obj : std\typeinfo\ti_Auint.d - $(DMD) -c $(DFLAGS) std\typeinfo\ti_Auint.d - ti_Aint.obj : std\typeinfo\ti_Aint.d $(DMD) -c $(DFLAGS) std\typeinfo\ti_Aint.d -ti_Aulong.obj : std\typeinfo\ti_Aulong.d - $(DMD) -c $(DFLAGS) std\typeinfo\ti_Aulong.d - ti_Along.obj : std\typeinfo\ti_Along.d $(DMD) -c $(DFLAGS) std\typeinfo\ti_Along.d @@ -643,12 +625,6 @@ ti_Acreal.obj : std\typeinfo\ti_Acreal.d $(DMD) -c $(DFLAGS) std\typeinfo\ti_Acreal.d -ti_Awchar.obj : std\typeinfo\ti_Awchar.d - $(DMD) -c $(DFLAGS) std\typeinfo\ti_Awchar.d - -ti_Adchar.obj : std\typeinfo\ti_Adchar.d - $(DMD) -c $(DFLAGS) std\typeinfo\ti_Adchar.d - ti_C.obj : std\typeinfo\ti_C.d $(DMD) -c $(DFLAGS) std\typeinfo\ti_C.d diff -uNr gdc-0.21/d/README gdc-0.22/d/README --- gdc-0.21/d/README 2007-01-03 11:30:29.000000000 +0100 +++ gdc-0.22/d/README 2007-02-06 05:30:00.000000000 +0100 @@ -1,16 +1,18 @@ D Front End for GCC - Release 0.21 -Last update: January 2, 2007 +Last update: February 5, 2007 -Release Notes for 0.21 - * Updated to DMD 1.00 - * Fixed Bugzilla 695, 696, 737, 738, 739, 742, 743, 745 - * Implemented GCC extended assembler - * Implemented basic support for GCC attributes +Release Notes for 0.22 + * Added support for GCC 4.1.x + * Support for GCC 3.3.x is deprecated + * Updated to DMD 1.004 + * Fixed Bugzilla 836, 837, 838, 839, 841, 843, 844, 889, 896 + * Fixed problems with missing debug information + * Added Rick Mann's -frameowrk patch for gdmd Supported Systems - * GCC 3.4.x and 4.0.x + * GCC 3.4.x, 4.0.x, 4.1.x * Linux (tested on Fedora Core 5 x86 and PowerPC) * Mac OS X 10.3.9 and 10.4.x * FreeBSD 6.x @@ -88,7 +90,7 @@ [ESP+4] does work the same way. * Currently, GDC uses the C calling convention for all functions except those declared extern (Windows). - * GDC allows catches in try blocks. + * GDC allows catch statements in finally blocks. * pragma(lib) is not supported. * Some targets do not have a distinct extended floating-point type. On these targets, real and double are the same size. diff -uNr gdc-0.21/d/setup-gcc.sh gdc-0.22/d/setup-gcc.sh --- gdc-0.21/d/setup-gcc.sh 2006-12-21 04:33:35.000000000 +0100 +++ gdc-0.22/d/setup-gcc.sh 2007-01-31 01:52:39.000000000 +0100 @@ -16,6 +16,8 @@ gcc_ver=3.4 elif grep version_string gcc/version.c | grep -q '"4.0'; then gcc_ver=4.0 +elif grep -q '^4\.1\.' gcc/BASE-VER; then + gcc_ver=4.1 fi # 0.1. Find out if this is Apple's GCC @@ -52,11 +54,15 @@ # 3. Patch the gcc subdirectory cd gcc || exit 1 patch -p1 < "$gcc_patch_fn" || exit 1 -# -e 's/ *(gdc [^)]*)//' \ -sed -e 's/ *(gdc.*using dmd [0-9\.]*)//' \ - -e 's/\(, *\)gdc.*using dmd [0-9\.]*/\1/' \ - -e 's/\(version_string[^"]*"[^"]*\)"/\1 ('"$gdc_ver"')"/' \ - version.c > version.c.tmp && mv -f version.c.tmp version.c + +if test "$gcc_ver" = 4.1; then + echo `cat DEV-PHASE` ' ' "($gdc_ver)" > DEV-PHASE +else + sed -e 's/ *(gdc.*using dmd [0-9\.]*)//' \ + -e 's/\(, *\)gdc.*using dmd [0-9\.]*/\1/' \ + -e 's/\(version_string[^"]*"[^"]*\)"/\1 ('"$gdc_ver"')"/' \ + version.c > version.c.tmp && mv -f version.c.tmp version.c +fi # 4. Maybe apply Darwin patches if test -z "$gcc_apple" && test "`uname`" = Darwin; then