diff -uNr gdc-1g/d/asmstmt.cc gdc-0.8/d/asmstmt.cc --- gdc-1g/d/asmstmt.cc 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.8/d/asmstmt.cc 2004-10-11 02:13:55.000000000 +0200 @@ -0,0 +1,40 @@ +// Taken from an earlier version of DMD -- why is it missing from 0.79? + +#include "total.h" +#include "statement.h" + +AsmStatement::AsmStatement(Loc loc, Token *tokens) : + Statement(loc) +{ + this->tokens = tokens; // Do I need to copy these? + asmcode = 0; + asmalign = 0; + refparam = 0; + naked = 0; + regs = 0; +} + +Statement *AsmStatement::syntaxCopy() +{ + // copy tokens? copy 'code'? + AsmStatement * a_s = new AsmStatement(loc,tokens); + a_s->asmcode = asmcode; + a_s->refparam = refparam; + a_s->naked = naked; + a_s->regs = a_s->regs; + return a_s; +} + +Statement *AsmStatement::semantic(Scope *sc) +{ + return Statement::semantic(sc); +} + + +void AsmStatement::toCBuffer(OutBuffer *buf) +{ + buf->printf("AsmStatement::toCBuffer()"); + buf->writenl(); +} + + diff -uNr gdc-1g/d/d-builtins2.cc gdc-0.8/d/d-builtins2.cc --- gdc-1g/d/d-builtins2.cc 2004-10-03 06:03:08.000000000 +0200 +++ gdc-0.8/d/d-builtins2.cc 2004-10-14 02:28:08.000000000 +0200 @@ -239,6 +239,31 @@ IRState::setCStdArg(td); else IRState::setStdArg(td); + if ( TREE_CODE( TREE_TYPE( va_list_type_node )) == ARRAY_TYPE ) { + /* For GCC, a va_list can be an array. D static arrays are + automatically passed by reference, but the 'inout' + modifier is not allowed. */ + assert(td->members); + for (unsigned j = 0; j < td->members->dim; j++) { + FuncDeclaration * fd = + ((Dsymbol *) td->members->data[j])->isFuncDeclaration(); + if (fd && fd->ident == id) { + TypeFunction * tf; + + // Should have nice error message instead of ICE in case some tries + // to tweak the file. + assert( ! fd->parameters ); + tf = (TypeFunction *) fd->type; + assert( tf->ty == Tfunction && + tf->arguments && tf->arguments->dim == 1 ); + ((Argument*) tf->arguments->data[0])->inout = In; + + fd->isFuncDeclaration(); + } + } + // ? -- version(GNU_PtrVaList)/version(GNU_AryVaList) -- less total LOC + } + break; } } } diff -uNr gdc-1g/d/d-codegen.cc gdc-0.8/d/d-codegen.cc --- gdc-1g/d/d-codegen.cc 2004-10-04 01:15:39.000000000 +0200 +++ gdc-0.8/d/d-codegen.cc 2004-10-23 22:44:51.000000000 +0200 @@ -134,7 +134,7 @@ } bool is_static = is_template ? - emitTemplates != TEnone : + emitTemplates != TEnone : // only because of the change in templates.c that emit all instances in this module dsym->getModule() == getCurrentModule(); if ( is_static ) { @@ -147,10 +147,10 @@ if ( ( real_decl ) ) { switch (real_decl->prot()) { + case PROTexport: case PROTpublic: case PROTpackage: case PROTprotected: - case PROTexport: // %% set for specials like init,vtbl ? -- otherwise,special case // for reverse the default TREE_PUBLIC( decl_tree ) = 1; @@ -201,7 +201,9 @@ // until the variable is emitted. So.... if (D_DECL_ONE_ONLY(decl_tree)) { - if (SUPPORTS_ONE_ONLY) { // have to check, otherwise backend will abort + if (SUPPORTS_ONE_ONLY // have to check, otherwise backend will abort + && ! (D_DECL_IS_TEMPLATE( decl_tree ) && emitTemplates == TEprivate) // this check is only to make -femit-templates=private work on targets that it is not actually needed... + ) { // this sets TREE_PUBLIC make_decl_one_only( decl_tree ); #ifdef MAKE_DECL_COALESCED @@ -299,10 +301,15 @@ tree var_decl = v->toSymbol()->Stree; tree init_exp = NULL_TREE; + tree cleanup = NULL_TREE; FuncDeclaration * f = getCurrentFunction(); assert( ! TREE_STATIC(var_decl )); + // If this were enabled, it would cause each local to come into scope on the line it + // is declared, but it is causing crashes... looks like expand_end_bindings is called too many times? + // startBindings(); + DECL_CONTEXT( var_decl ) = getDeclContext(); pushdecl(var_decl); @@ -321,6 +328,9 @@ addressOf( built_in_decls[BUILT_IN_VA_START] ), tree_cons(NULL_TREE, addressOf(var_decl), tree_cons( NULL_TREE, parm, NULL_TREE))); + cleanup = buildCall(void_type_node, + addressOf( built_in_decls[BUILT_IN_VA_END] ), + tree_cons(NULL_TREE, addressOf(var_decl), NULL_TREE)); } else if ( ! DECL_INITIAL( var_decl ) ) { if (v->init) { ExpInitializer * exp_init = v->init->isExpInitializer(); @@ -349,6 +359,8 @@ } expand_decl(var_decl); + if (cleanup) + expand_decl_cleanup(var_decl, cleanup); // special case for _argptr if ( init_exp ) { @@ -363,48 +375,101 @@ } } +tree +IRState::declContext(Dsymbol * d_sym) +{ + AggregateDeclaration * agg_decl; + + while ( (d_sym = d_sym->toParent()) ) { + if (d_sym->isFuncDeclaration()) { + return d_sym->toSymbol()->Stree; + } else if ( (agg_decl = d_sym->isAggregateDeclaration()) ) { + tree type = agg_decl->type->toCtype(); + if (d_sym->isClassDeclaration()) + type = TREE_TYPE(type); + return type; + } else if ( d_sym->isModule() ) { + return d_sym->toSymbol()->ScontextDecl; + } + } + return NULL_TREE; +} + + void -IRState::declareType(tree t, Dsymbol * d_sym) +IRState::addAggMethods(tree rec_type, AggregateDeclaration * agg) +{ + if (write_symbols != NO_DEBUG) { + ListMaker methods; + for (unsigned i = 0; i < agg->methods.dim; i++) { + FuncDeclaration * fd = (FuncDeclaration *) agg->methods.data[i]; + + methods.chain(fd->toSymbol()->Stree); + } + TYPE_METHODS( rec_type ) = methods.head; + } +} + +void IRState::declareType(tree t, Type * d_type) +{ + // Note: not safe to call d_type->toCtype() + Loc l; + tree decl = build_decl(TYPE_DECL, get_identifier(d_type->toChars()), t); + l.filename = ""; + l.linnum = 1; + setDeclLoc(decl, l); + // %% toplevel context + + declareType(t, decl); +} + +void IRState::declareType(tree t, Dsymbol * d_sym) { - //if (d_sym->getModule() != getCurrentModule()) - // return; + assert( ! POINTER_TYPE_P( t ) ); + + const char * name = d_sym->ident ? d_sym->ident->string : "fix"; + tree decl = build_decl(TYPE_DECL, get_identifier(name), t); + DECL_CONTEXT( decl ) = gen.declContext(d_sym); + setDeclLoc(decl, d_sym); - bool top_level = true; + declareType(t, decl); +} - tree ident = d_sym->ident ? get_identifier(d_sym->ident->string) : get_identifier("fix"); - tree decl = build_decl(TYPE_DECL, ident, t); - TYPE_NAME( t ) = decl; +void +IRState::declareType(tree t, tree decl) +{ + assert( ! POINTER_TYPE_P( t ) ); + + bool top_level = true; + TYPE_CONTEXT( t ) = DECL_CONTEXT( decl ); - while (d_sym->parent) { - top_level = false; + /* 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); - d_sym = d_sym->parent; - if (d_sym->isFuncDeclaration() || - d_sym->isAggregateDeclaration() || - ( top_level = d_sym->isModule() )) { - - DECL_CONTEXT( decl ) = d_sym->toSymbol()->ScontextDecl; - break; - } - } + DECL_CONTEXT( clone_stub ) = DECL_CONTEXT( decl ); + // TREE_CHAIN( clone_stub ) = decl; // not needed? - // still resolved -- the the STUB_DECL decls need identifiers or not? - TYPE_STUB_DECL( t ) = build_decl(TYPE_DECL, NULL_TREE, t); - if (POINTER_TYPE_P( t )) { - tree a_t = TREE_TYPE(a_t); - if (AGGREGATE_TYPE_P(a_t)) { - /* Using the same ident as the reference type - doesn't seem to cause a problem. A non-null identifier is required - for the debugging info to work on dbx. */ - //TYPE_NAME(a_t) = ident; - TYPE_STUB_DECL(a_t) = build_decl(TYPE_DECL, NULL_TREE, a_t); - TYPE_NAME(a_t) = ident; - DECL_CONTEXT( TYPE_STUB_DECL(a_t) ) = DECL_CONTEXT( decl ); - } + TYPE_STUB_DECL( t_clone ) = clone_stub; + + // rest_of_type_compilation(t_clone, 1); // not needed? + DECL_ORIGINAL_TYPE( decl ) = t_clone; } - + + TYPE_NAME( t ) = decl; + TYPE_STUB_DECL( t ) = decl; + rest_of_decl_compilation(decl, NULL, top_level, 0); + //pushdecl(decl); } tree @@ -419,12 +484,13 @@ tree result = 0; target_type = target_type->toBasetype(); - if (exp_type->toBasetype()->equals(target_type)) - return exp; + assert(exp_type); + exp_type = exp_type->toBasetype(); - // %%TODO: fix this annoying exception - // %% still needed for scalar types? - switch (exp_type ? exp_type->toBasetype()->ty : -1) { + if (exp_type->equals(target_type)) + return exp; + + switch (exp_type->ty) { case Tdelegate: // %%TODO:NOP/VIEW_CONVERT if (target_type->ty == Tdelegate) { @@ -449,8 +515,12 @@ if (offset == OFFSET_RUNTIME) { use_dynamic = true; } else if (offset) { - return build(PLUS_EXPR, target_type->toCtype(), - exp, size_int(offset)); + tree t = target_type->toCtype(); + exp = maybeMakeTemp(exp); + return build(COND_EXPR, t, + boolOp(NE_EXPR, exp, nullPointer()), + build(PLUS_EXPR, t, exp, size_int(offset)), + nullPointer()); } else { // d_convert will make a NOP cast break; @@ -465,11 +535,10 @@ return libCall(obj_class_decl->isInterfaceDeclaration() ? LIBCALL_INTERFACE_CAST : LIBCALL_DYNAMIC_CAST, 2, args); } else { - warning("class/interface cast will fail"); - // %% warn that this will always fail? + warning("cast to %s will fail", target_type->toChars()); result = convert(target_type->toCtype(), d_null_pointer); - if (TREE_SIDE_EFFECTS( exp )) { // make sure the expression is still used if user expects it - result = build(COMPOUND_EXPR, TREE_TYPE(result), exp, result); + if (TREE_SIDE_EFFECTS( exp )) { // make sure the expression is still evaluated if user expects it + result = compound(exp, result); } return result; } @@ -477,41 +546,31 @@ // nothing; default } break; - strings_are_arrays: case Tsarray: { // %% TODO: stuffing types ok? - tree pointer_value = build1( ADDR_EXPR, - build_pointer_type( TREE_TYPE( exp )), // could use TYPE_POINTER_TO, but probably not for strings - exp ); + tree pointer_value = addressOf( exp ); if (target_type->ty == Tpointer) { result = pointer_value; TREE_TYPE(result) = target_type->toCtype(); } else if (target_type->ty == Tarray) { - unsigned array_len; - - if ( ! exp_type && TREE_CODE( exp ) == STRING_CST ) { - // %% may not be correct with null padding.. - array_len = TREE_STRING_LENGTH( exp ) / target_type->next->size(); - } else { - TypeSArray * a_type = (TypeSArray*) exp_type; - - array_len = a_type->dim->toInteger(); - unsigned sz_a = a_type->next->size(); - unsigned sz_b = target_type->next->size(); - - // conversions to different sizes - // %% assume 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) { - array_len = array_len * sz_a / sz_b; + TypeSArray * a_type = (TypeSArray*) exp_type; + + unsigned array_len = a_type->dim->toInteger(); + unsigned sz_a = a_type->next->size(); + unsigned sz_b = target_type->next->size(); + + // 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) { + array_len = array_len * sz_a / sz_b; } TREE_TYPE(pointer_value) = target_type->next->pointerTo()->toCtype(); @@ -562,25 +621,45 @@ } break; default: - if (exp_type->iscomplex()) { + if (exp_type->isreal() && target_type->isimaginary() || + exp_type->isimaginary() && target_type->isreal()) { + // warn? handle in front end? + + result = build_real_from_int_cst( target_type->toCtype(), integer_zero_node ); + if (TREE_SIDE_EFFECTS( exp )) + result = compound(exp, result); + return result; + } else if (exp_type->iscomplex()) { + Type * part_type; // creal.re, .im implemented by cast to real or ireal // Assumes target type is the same size as the original's components size if (target_type->isreal()) { - return realPart(exp); + // maybe install lang_specific... + switch (exp_type->ty) { + case Tcomplex32: part_type = Type::tfloat32; break; + case Tcomplex64: part_type = Type::tfloat64; break; + case Tcomplex80: part_type = Type::tfloat80; break; + default: + abort(); + } + result = realPart(exp); } else if (target_type->isimaginary()) { - return imagPart(exp); - } - } else { - //if (exp->op == TOKstring) - // goto strings_are_arrays; - switch( TREE_CODE( exp )) { - case STRING_CST: - goto strings_are_arrays; + switch (exp_type->ty) { + case Tcomplex32: part_type = Type::timaginary32; break; + case Tcomplex64: part_type = Type::timaginary64; break; + case Tcomplex80: part_type = Type::timaginary80; break; + default: + abort(); + } + result = imagPart(exp); + } else { + // default conversion break; - default: - // %% convert(value, target_type->toCtype()) ? - ; } + result = convertTo(result, part_type, target_type); + } else { + assert( TREE_CODE( exp ) != STRING_CST ); + // default conversion } } @@ -1016,16 +1095,28 @@ return result; } +static inline bool +function_type_p(tree t) +{ + return TREE_CODE(t) == FUNCTION_TYPE || TREE_CODE(t) == METHOD_TYPE; +} + tree IRState::call(tree callable, tree object, Array * arguments) { tree func_type_node = TREE_TYPE( callable ); + + tree actual_callee; TypeFunction * func_type = 0; if ( POINTER_TYPE_P( func_type_node ) ) { func_type_node = TREE_TYPE( func_type_node ); + actual_callee = callable; + } else { + actual_callee = addressOf( callable ); } - assert( TREE_CODE(func_type_node) == FUNCTION_TYPE ); + + assert( function_type_p( func_type_node ) ); assert( TYPE_LANG_SPECIFIC( func_type_node ) != 0 ); func_type = (TypeFunction *) getDType(func_type_node)->toBasetype(); assert( func_type->ty == Tfunction ); @@ -1033,21 +1124,29 @@ bool is_d_vararg = func_type->varargs && func_type->linkage == LINKd; ListMaker actual_arg_list; - tree actual_callee; tree result; - if ( TREE_CODE(TREE_TYPE( callable )) == FUNCTION_TYPE ) { - // || TREE_CODE(callable) == FUNCTION_DECL // redundant - - // The backend does not accept a FUNCTION_DECL (but it does accept a VAR_DECL - // that is a function pointer.) We also need to handle - // (* pointer_to_function)(arg,arg,...) - actual_callee = addressOf( callable ); - } else { - actual_callee = callable; - } - if ( object != NULL_TREE ) { - func_type_node = build_method_type( TREE_TYPE( object ), func_type_node ); + if ( TREE_CODE( func_type_node ) == FUNCTION_TYPE ) { + if ( object != NULL_TREE ) { + tree method_type = build_method_type( TREE_TYPE( object ), func_type_node ); + TYPE_ATTRIBUTES( method_type ) = TYPE_ATTRIBUTES( func_type_node ); + func_type_node = method_type; + } + } else /* METHOD_TYPE */ { + if ( ! object ) { + FuncDeclaration * cur_func = getCurrentFunction(); + if (cur_func->isMember() && ! cur_func->isThis() && + // Front-end apparently doesn't check this. + + TREE_CODE(callable) == FUNCTION_DECL ) { // not an exact check of the condition + error("need 'this' to access member %s", IDENTIFIER_POINTER( DECL_NAME( callable ))); + return error_mark_node; + } else { + // Probably an internal error + + assert(object != NULL_TREE); + } + } } Array * formal_args = func_type->arguments; // can be NULL for genCfunc decls @@ -1132,7 +1231,7 @@ } static const char * libcall_ids[LIBCALL_count] = - { "_d_assert", "_d_array_bounds", "_d_switch_error", "_d_invariant", + { "_d_assert", "_d_array_bounds", "_d_switch_error", "_D9invariant12_d_invariantFC6ObjectZv", "_d_newclass", "_d_new","_d_newarrayi", "_d_newbitarray", "_d_delclass", "_d_delarray", "_d_delmemory", "_d_callfinalizer", "_d_arraysetlength", "_d_arraysetlengthb", @@ -1530,9 +1629,49 @@ return call_exp; } +// Can't output thunks while a function is being compiled. Called from +// d-decls.cc (no cur_irs) +static Array deferredThunks; + +typedef struct { + tree decl; + tree target; + int offset; +} DeferredThunk; + void IRState::doThunk(tree thunk_decl, tree target_decl, int offset) { + if (current_function_decl) { + DeferredThunk * t = new DeferredThunk; + t->decl = thunk_decl; + t->target = target_decl; + t->offset = offset; + deferredThunks.push(t); + } else { + outputThunk(thunk_decl, target_decl, offset); + } +} + +IRState * +IRState::endFunction() +{ + IRState * irs = IRBase::endFunction(); + + if ( ! current_function_decl ) { // Could just hold off to the end of the module... + for (unsigned i = 0; i < deferredThunks.dim; i++) { + DeferredThunk * t = (DeferredThunk *) deferredThunks.data[i]; + outputThunk(t->decl, t->target, t->offset); + } + deferredThunks.setDim(0); + } + + return irs; +} + +void +IRState::outputThunk(tree thunk_decl, tree target_decl, int offset) +{ int delta = -offset; tree alias = target_decl; @@ -1566,6 +1705,7 @@ if (targetm.asm_out.can_output_mi_thunk(thunk_decl, delta, 0, alias)) { const char *fnname; + current_function_decl = thunk_decl; DECL_RESULT( thunk_decl ) = build_decl(RESULT_DECL, 0, integer_type_node); @@ -1939,7 +2079,7 @@ Type * base_type = exp_type->toBasetype(); switch (base_type->ty) { case Tsarray: - return integerConstant(((TypeSArray *) base_type)->dim->toInteger(), size_type_node); + return size_int( ((TypeSArray *) base_type)->dim->toInteger() ); case Tarray: return darrayLenRef(exp); default: @@ -2166,10 +2306,32 @@ DECL_CONTEXT(f1) = rec_type; TYPE_FIELDS(rec_type) = chainon(f0, f1); layout_type(rec_type); +#ifdef ORIG TYPE_STUB_DECL(rec_type) = build_decl(TYPE_DECL, NULL_TREE, rec_type); rest_of_type_compilation(rec_type, 1); - if (d_type) +#else + /* + if (d_type) { + // EXPER + TYPE_NAME(rec_type) = build_decl(TYPE_DECL, get_identifier(d_type->toChars()), rec_type); // this, and rest_of_decl.. is all that is needed for dbxout + //TYPE_STUB_DECL(rec_type) = copy_node(TYPE_NAME(rec_type)); + //DECL_ARTIFICIAL(TYPE_STUB_DECL(rec_type)) = 1; + //DECL_IGNORED_P(TYPE_STUB_DECL(rec_type)) = 1; + Loc l; + l.filename = ""; + l.linnum = 1; + //setDeclLoc(TYPE_NAME(rec_type), l); + //pushdecl(TYPE_NAME(rec_type)); + // global_binding_level->names + //rest_of_type_compilation(rec_type, 1); + rest_of_decl_compilation(TYPE_NAME(rec_type), NULL, 1, 0); + } + */ +#endif + if (d_type) { + declareType(rec_type, d_type); TYPE_LANG_SPECIFIC(rec_type) = build_d_type_lang_specific(d_type); + } return rec_type; } @@ -2337,6 +2499,34 @@ } tree +IRState::addTypeAttribute(tree type, const char * attrname, tree value) +{ + // use build_type_copy / build_type_attribute_variant + + // types built by functions in tree.c need to be treated as immutable + if ( ! TYPE_ATTRIBUTES( type )) { + type = copy_node( type ); + // TYPE_STUB_DECL( type ) = .. if we need this for structs, etc.. since + // TYPE_STUB_DECL^U14^H TREE_CHAIN is cleared by COPY_NODE + } + if (value) + value = tree_cons(NULL_TREE, value, NULL_TREE); + TYPE_ATTRIBUTES( type ) = tree_cons( get_identifier(attrname), value, + TYPE_ATTRIBUTES( type )); + return type; +} + +void +IRState::addDeclAttribute(tree type, const char * attrname, tree value) +{ + if (value) + value = tree_cons(NULL_TREE, value, NULL_TREE); + DECL_ATTRIBUTES( type ) = tree_cons( get_identifier(attrname), value, + DECL_ATTRIBUTES( type )); +} + + +tree IRState::vtable(Array * vtbl, ClassDeclaration * ci_override) { tree ctor = make_node( CONSTRUCTOR ); @@ -2386,7 +2576,7 @@ { tree index_type_node; if (size > 0) { - index_type_node = integerConstant(size - 1, size_type_node); + index_type_node = size_int( size - 1 ); index_type_node = build_index_type(index_type_node); } else { // See c-decl.c grokdeclarator for zero-length arrays @@ -2466,9 +2656,16 @@ } -void AggLayout::doFields(Array * fields) +void AggLayout::doFields(Array * fields, AggregateDeclaration * agg) { - tree new_field_chain = NULL_TREE; + bool inherited = agg != this->aggDecl; + tree fcontext; + + fcontext = agg->type->toCtype(); + if ( POINTER_TYPE_P( fcontext )) + fcontext = TREE_TYPE(fcontext); + + // tree new_field_chain = NULL_TREE; for (unsigned i = 0; i < fields->dim; i++) { // %% D anonymous unions just put the fields into the outer struct... // does this cause problems? @@ -2480,30 +2677,35 @@ tree ident = var_decl->ident ? get_identifier(var_decl->ident->string) : NULL_TREE; tree field_decl = build_decl(FIELD_DECL, ident, gen.trueDeclarationType( var_decl )); - // %% may want to set var_decl->csym and lang_decl - // %% there are issues with this (inherited members) - gen.setDeclLoc( field_decl, var_decl->loc ); + gen.setDeclLoc( field_decl, var_decl ); var_decl->csym = new Symbol; var_decl->csym->Stree = field_decl; DECL_CONTEXT( field_decl ) = aggType; - DECL_FCONTEXT( field_decl ) = aggType; // %% should point to base class + DECL_FCONTEXT( field_decl ) = fcontext; DECL_FIELD_OFFSET (field_decl) = size_int( var_decl->offset ); DECL_FIELD_BIT_OFFSET (field_decl) = bitsize_zero_node; + + DECL_ARTIFICIAL( field_decl ) = + DECL_IGNORED_P( field_decl ) = inherited; + //SET_DECL_OFFSET_ALIGN (field_decl, BIGGEST_ALIGNMENT); // ? layout_decl( field_decl, 0 ); - new_field_chain = chainon(field_decl, new_field_chain); + fieldList.chain( field_decl ); } - TYPE_FIELDS( aggType ) = chainon(TYPE_FIELDS( aggType ), nreverse( new_field_chain )); } -void AggLayout::doInterfaces(Array * bases) +void AggLayout::doInterfaces(Array * bases, AggregateDeclaration * agg) { + tree fcontext = TREE_TYPE( agg->type->toCtype() ); for (unsigned i = 0; i < bases->dim; i++) { BaseClass * bc = (BaseClass *) bases->data[i]; tree decl = build_decl(FIELD_DECL, NULL_TREE, Type::tvoid->pointerTo()->pointerTo()->toCtype() /* %% better */ ); - DECL_VIRTUAL_P( decl ) = 1; + //DECL_VIRTUAL_P( decl ) = 1; %% nobody cares, boo hoo + DECL_ARTIFICIAL( decl ) = + DECL_IGNORED_P( decl ) = 1; + // DECL_FCONTEXT( decl ) = fcontext; // shouldn't be needed since it's ignored addField(decl, bc->offset); } } @@ -2511,7 +2713,7 @@ void AggLayout::addField(tree field_decl, unsigned offset) { DECL_CONTEXT( field_decl ) = aggType; - DECL_FCONTEXT( field_decl ) = aggType; // %% should point to base class + // DECL_FCONTEXT( field_decl ) = aggType; // caller needs to set this DECL_FIELD_OFFSET (field_decl) = size_int( offset ); DECL_FIELD_BIT_OFFSET (field_decl) = bitsize_int( 0 ); Loc l(aggDecl->getModule(), 1); // Must set this or we crash with DWARF debugging @@ -2519,7 +2721,7 @@ gen.setDeclLoc(field_decl, l); layout_decl( field_decl, 0 ); - TYPE_FIELDS( aggType ) = chainon(TYPE_FIELDS( aggType ), field_decl); + fieldList.chain( field_decl ); } void AggLayout::finish() @@ -2527,6 +2729,12 @@ unsigned size_to_use = aggDecl->structsize; unsigned align_to_use = aggDecl->alignsize; + /* probably doesn't do anything */ + /* + if (aggDecl->structsize == 0 && aggDecl->isInterfaceDeclaration()) + size_to_use = Type::tvoid->pointerTo()->size(); + */ + TYPE_SIZE( aggType ) = bitsize_int( size_to_use * BITS_PER_UNIT ); TYPE_SIZE_UNIT( aggType ) = size_int( size_to_use ); TYPE_ALIGN( aggType ) = align_to_use * BITS_PER_UNIT; // %%doc int, not a tree @@ -2535,7 +2743,6 @@ compute_record_mode ( aggType ); // %% stor-layout.c:finalize_type_size ... it's private to that file - // c-decl.c -- set up variants ? %% for (tree x = TYPE_MAIN_VARIANT( aggType ); x; x = TYPE_NEXT_VARIANT( x )) { TYPE_FIELDS (x) = TYPE_FIELDS (aggType); @@ -2622,10 +2829,10 @@ if (class_decl && class_decl->baseClass) FieldVisitor::visit(class_decl->baseClass); - doFields(& decl->fields); + doFields(& decl->fields, decl); if (class_decl) - doInterfaces(class_decl->vtblInterfaces); + doInterfaces(class_decl->vtblInterfaces, decl); } dt_t** dtnwords(dt_t** pdt, unsigned word_count, void * pwords, unsigned word_size) @@ -2692,7 +2899,7 @@ TREE_STATIC( s ) = 1; return gen.addressOf( s ); } - case DT_word: + case DT_word: // %% make sure this is the target word type return gen.integerConstant(dt->DTint, long_unsigned_type_node); case DT_xoff: diff -uNr gdc-1g/d/d-codegen.h gdc-0.8/d/d-codegen.h --- gdc-1g/d/d-codegen.h 2004-10-04 01:15:39.000000000 +0200 +++ gdc-0.8/d/d-codegen.h 2004-10-23 22:44:51.000000000 +0200 @@ -134,8 +134,17 @@ static void prepareSymbolOutput(Symbol * s); static void outputStaticSymbol(tree t); + static void addAggMethods(tree rec_type, AggregateDeclaration * agg); + + static void declareType(tree t, Type * d_type); static void declareType(tree t, Dsymbol * d_sym); +protected: + static void declareType(tree t, tree decl); +public: + + static tree declContext(Dsymbol * d_sym); + // Hack for systems without linkonce support static TemplateEmission emitTemplates; static bool shouldEmit(Dsymbol * d_sym); @@ -202,6 +211,9 @@ return TYPE_MODE(long_double_type_node) != TYPE_MODE(double_type_node); } + static tree addTypeAttribute(tree type, const char * attrname, tree value = NULL_TREE); + static void addDeclAttribute(tree type, const char * attrname, tree value = NULL_TREE); + // ** Simple constants static tree nullPointer() { return d_null_pointer; } @@ -222,10 +234,6 @@ return integerConstant(value, type->toCtype()); } - static Expression * sizeInt(xdmd_integer_t value) { - Loc loc; - return new IntegerExp(loc, value, Type::tsize_t); - } tree floatConstant( real_t value, TypeBasic * target_type ); // ** Routines for built in structured types @@ -414,9 +422,11 @@ static tree functionPointer(FuncDeclaration * func_decl); - - void doThunk(tree thunk_decl, tree target_decl, int offset); + IRState * endFunction(); +protected: + void outputThunk(tree thunk_decl, tree target_decl, int offset); +public: tree doSimpleFunction(Module * mod, const char * name, tree expr, bool static_ctor); tree doFunctionToCallFunctions(Module * mod, const char * name, Array * functions); @@ -496,6 +506,7 @@ tree head; tree * ptail; ListMaker() : head(NULL_TREE), ptail( & head ) { } + ListMaker(tree * alt_head) : head(NULL_TREE), ptail( alt_head ) { } void chain(tree t) { *ptail = t; ptail = & TREE_CHAIN(t); } void cons(tree p, tree v) { *ptail = tree_cons(p,v,NULL_TREE); @@ -509,8 +520,8 @@ AggregateDeclaration * aggDecl; FieldVisitor(AggregateDeclaration * decl) : aggDecl(decl) { } //virtual doField(VarDeclaration * field) = 0; - virtual void doFields(Array * fields) = 0; - virtual void doInterfaces(Array * bases) = 0; + virtual void doFields(Array * fields, AggregateDeclaration * agg) = 0; + virtual void doInterfaces(Array * bases, AggregateDeclaration * agg) = 0; void go() { visit(aggDecl); } void visit(AggregateDeclaration * decl); }; @@ -518,12 +529,14 @@ class AggLayout : public FieldVisitor { public: tree aggType; + ListMaker fieldList; AggLayout(AggregateDeclaration * ini_agg_decl, tree ini_agg_type) : FieldVisitor(ini_agg_decl), - aggType(ini_agg_type) { } - void doFields(Array * fields); - void doInterfaces(Array * bases); - void addField(tree field_decl, unsigned offset); // FIELD_DECL + aggType(ini_agg_type), + fieldList(& TYPE_FIELDS( aggType )) { } + void doFields(Array * fields, AggregateDeclaration * agg); + void doInterfaces(Array * bases, AggregateDeclaration * agg); + void addField(tree field_decl, unsigned offset); void finish(); }; diff -uNr gdc-1g/d/d-decls.cc gdc-0.8/d/d-decls.cc --- gdc-1g/d/d-decls.cc 2004-10-04 00:43:18.000000000 +0200 +++ gdc-0.8/d/d-decls.cc 2004-10-23 22:44:51.000000000 +0200 @@ -93,20 +93,9 @@ Symbol *Dsymbol::toSymbol() { - // %% could move this out by haveing IRState::symbolContextDecl... - // %% Because call toSymbol for arbitrary symbols now, may need - // to remove the assert below.. - StructDeclaration * struct_decl = (this->isStructDeclaration()); // ClassDeclaration handles itself - if (struct_decl) { - if (! csym) { - csym = new Symbol(); - csym->ScontextDecl = struct_decl->type->toCtype(); - } - return csym; - } else { - assert(0); // BUG: implement - return NULL; - } + printf("Dsymbol::toSymbol() '%s', kind = '%s'\n", toChars(), kind()); + assert(0); // BUG: implement + return NULL; } /********************************* @@ -164,15 +153,12 @@ if ( TREE_CODE( var_decl ) == VAR_DECL ) { gen.setupSymbolStorage(this, var_decl); } else { - Dsymbol * p_parent = toParent(); - // PARM_DECL /* from gcc code: Some languages have different nominal and real types. */ // %% What about DECL_ORIGINAL_TYPE, DECL_ARG_TYPE_AS_WRITTEN, DECL_ARG_TYPE ? - // %% dup of context function.. - DECL_ARG_TYPE (var_decl) = TREE_TYPE (var_decl); - if ( p_parent->isFuncDeclaration() ) { - DECL_CONTEXT (var_decl) = p_parent->toSymbol()->Stree; - } + DECL_ARG_TYPE( var_decl ) = TREE_TYPE (var_decl); + + DECL_CONTEXT( var_decl ) = gen.declContext(this); + assert( TREE_CODE(DECL_CONTEXT( var_decl )) == FUNCTION_DECL ); } // Can't set TREE_STATIC, etc. until we get to toObjFile as this could be @@ -253,12 +239,9 @@ //tree type_node; tree fn_decl; char * mangled_ident_str = 0; + AggregateDeclaration * agg_decl; - //if (getModule() == gen.getBuiltinsModule() && gen.setUpBuiltin(this)) { - // (still needed, just do it later... - if (ident) { - // Obtain be an IDENTIFIER_NODE tree. id = get_identifier(ident->string); } else { // This happens for assoc array foreach bodies @@ -275,7 +258,11 @@ } tree fn_type = type->toCtype(); - tree context; + dkeep(fn_type); /* TODO: fix this. we need to keep the type because + the creation of a method type below leaves this fn_type + unreferenced. maybe lang_specific.based_on */ + + tree vindex = NULL_TREE; if (isNested()) { // Nested functions take an extra argument to be compatible with delegates. // The stack frame will come from a trampoline. @@ -283,10 +270,26 @@ tree_cons(NULL_TREE, ptr_type_node, TYPE_ARG_TYPES(fn_type))); TYPE_LANG_SPECIFIC( fn_type ) = build_d_type_lang_specific(type); TYPE_LANG_SPECIFIC( fn_type )->is_nested_function = 1; - context = toParent()->toSymbol()->Stree; - } else { - context = NULL; } + else if ( ( agg_decl = isMember() ) ) { + // Do this even if there is no debug info. It is needed to maker + // sure member functions are not called statically + if (isThis()) { + tree method_type = build_method_type(TREE_TYPE(agg_decl->handle->toCtype()), fn_type); + TYPE_ATTRIBUTES( method_type ) = TYPE_ATTRIBUTES( fn_type ); + fn_type = method_type; + + /* hopefully, this->type->toCtype()->lang_specific->dtype != this->type + won't be a problem */ + TYPE_LANG_SPECIFIC( fn_type ) = build_d_type_lang_specific(this->type); + + if (isVirtual()) + vindex = size_int(vtblIndex); + } + } + + // %%CHECK: is it okay for static nested functions to have a FUNC_DECL context? + // seems okay so far... fn_decl = build_decl( FUNCTION_DECL, id, fn_type ); dkeep(fn_decl); @@ -296,7 +299,23 @@ } // %% What about DECL_SECTION_NAME ? //DECL_ARGUMENTS(fn_decl) = NULL_TREE; // Probably don't need to do this until toObjFile - DECL_CONTEXT (fn_decl) = context; + DECL_CONTEXT (fn_decl) = gen.declContext(this); //context; + if (vindex) { + DECL_VINDEX (fn_decl) = vindex; + DECL_VIRTUAL_P (fn_decl) = 1; + } + if (! isNested()) { + // Prevent backend from thinking this is a nested function. + DECL_NO_STATIC_CHAIN( fn_decl ) = 1; + } + +#ifdef TARGET_DLLIMPORT_DECL_ATTRIBUTES + // Have to test for import first + if (isImportedSymbol()) + gen.addDeclAttribute( fn_decl, "dllimport" ); + else if (isExport()) + gen.addDeclAttribute( fn_decl, "dllexport" ); +#endif gen.setDeclLoc(fn_decl, this); gen.setupSymbolStorage(this, fn_decl); @@ -310,8 +329,9 @@ switch (linkage) { case LINKwindows: - // %% how to mangle these? - // add attribute stdcall + gen.addDeclAttribute(fn_decl, "stdcall"); + // The stdcall attribute also needs to be set on the function type. + assert( ((TypeFunction *) type)->linkage == LINKwindows ); break; case LINKpascal: // this is just stdcall without mangling, right? @@ -338,7 +358,6 @@ csym = new Symbol(); csym->Sident = mangled_ident_str; // save for making thunks csym->Stree = fn_decl; - csym->ScontextDecl = fn_decl; gen.maybeSetUpBuiltin(this); } @@ -352,9 +371,11 @@ { Symbol *sthunk; Thunk * thunk; - bool is_extern = getModule() != getCurrentModule(); + bool is_extern; toSymbol(); + is_extern = DECL_EXTERNAL( csym->Stree ); // shortcut for shouldEmit, isTemplate, etc. + /* If the thunk is to be static (that is, it is being emitted in this module, there can only be one FUNCTION_DECL for it. Thus, there is a list of all thunks for a given function. */ @@ -406,11 +427,14 @@ #if D_GCC_VER >= 34 DECL_DECLARED_INLINE_P(thunk_decl) = 0; #endif + D_DECL_ONE_ONLY(thunk_decl) = D_DECL_ONE_ONLY(target_func_decl); + D_DECL_IS_TEMPLATE(thunk_decl) = D_DECL_IS_TEMPLATE(target_func_decl); // This does not do anything now. TREE_ADDRESSABLE(thunk_decl) = 1; - TREE_USED (thunk_decl) = 1; // assuming only called if it will be used + TREE_USED (thunk_decl) = 1; // assuming only called if it will be used + + gen.prepareSymbolOutput(sthunk); - //cod3_thunk(sthunk, csym, 0, TYnptr, -offset, -1, 0); if (is_extern) { DECL_EXTERNAL( thunk_decl ) = 1; } else { @@ -458,7 +482,6 @@ decl = build_decl( VAR_DECL, get_identifier( csym->Sident ), TREE_TYPE( ClassDeclaration::classinfo->type->toCtype() )); // want the RECORD_TYPE, not the REFERENCE_TYPE csym->Stree = decl; - csym->ScontextDecl = TREE_TYPE( type->toCtype() ); // want the RECORD_TYPE, not the REFERENCE_TYPE dkeep(decl); gen.setupStaticStorage(this, decl); @@ -498,11 +521,19 @@ if (!csym) { Type * some_type; + + /* PAIN -- causes problems with zomg_t3h_rei .. workaround + is to call moduleinfo->toCtype() before we start processing + decls in genobjfile */ + /* We don't, in general, have moduleinfo anyway, so don't bother */ + /* if (moduleinfo) { some_type = moduleinfo->type; } else { some_type = gen.getObjectType(); } + */ + some_type = gen.getObjectType(); csym = toSymbolX("_ModuleInfo_", SCextern, 0); slist_add(csym); @@ -511,10 +542,13 @@ TREE_TYPE(some_type->toCtype())); // want the RECORD_TYPE, not the REFERENCE_TYPE csym->Stree = decl; #if D_GCC_VER >= 34 + // EXPER, what have you done for me lately? + /* csym->ScontextDecl = build_decl(TRANSLATION_UNIT_DECL, NULL, NULL); + dkeep(csym->ScontextDecl); + */ #endif - dkeep(csym->ScontextDecl); dkeep(decl); gen.setupStaticStorage(this, decl); @@ -551,7 +585,7 @@ TREE_CONSTANT( decl ) = 1; TREE_ADDRESSABLE( decl ) = 1; // from cp/class.c - DECL_CONTEXT (decl) = toSymbol()->ScontextDecl; // %% Does this do anything? + DECL_CONTEXT (decl) = TREE_TYPE( type->toCtype() ); DECL_VIRTUAL_P (decl) = 1; DECL_ALIGN (decl) = TARGET_VTABLE_ENTRY_ALIGN; } diff -uNr gdc-1g/d/d-gcc-real.cc gdc-0.8/d/d-gcc-real.cc --- gdc-1g/d/d-gcc-real.cc 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/d-gcc-real.cc 2004-10-10 18:50:41.000000000 +0200 @@ -131,7 +131,7 @@ p.dig = (int)(rf.p * M_LOG10_2); // %% not always the same as header values.. p.mant_dig = rf.p; p.max_10_exp = (int)(rf.emax * M_LOG10_2); - p.min_10_exp = (int)(rf.emax * M_LOG10_2); + p.min_10_exp = (int)(rf.emin * M_LOG10_2); p.max_exp = rf.emax; p.min_exp = rf.emin; } diff -uNr gdc-1g/d/d-gcc-real.h gdc-0.8/d/d-gcc-real.h --- gdc-1g/d/d-gcc-real.h 2004-08-21 14:38:43.000000000 +0200 +++ gdc-0.8/d/d-gcc-real.h 2004-10-18 05:27:20.000000000 +0200 @@ -63,6 +63,7 @@ // prevent this from being used real_t & operator=(float v) { return *this; } real_t & operator=(double v) { return *this; } + // real_t & operator=(long double v) { return *this; } }; typedef struct { diff -uNr gdc-1g/d/d-glue.cc gdc-0.8/d/d-glue.cc --- gdc-1g/d/d-glue.cc 2004-10-04 02:22:23.000000000 +0200 +++ gdc-0.8/d/d-glue.cc 2004-10-23 22:44:51.000000000 +0200 @@ -217,17 +217,6 @@ } } -static tree -make_varblock_type(tree size_expr, IRState * irs) -{ - tree the_type = irs->arrayType(unsigned_intQI_type_node, 0); - tree the_copy = copy_node(the_type); // don't mess up a cached copy... - struct lang_type * lt = build_d_type_lang_specific(0); - lt->varblock_size = size_expr; - TYPE_LANG_SPECIFIC(the_copy) = lt; - return the_copy; -} - elem * EqualExp::toElem(IRState* irs) { @@ -257,55 +246,44 @@ // shouldn't need to check for Tbit return make_bool_binop(this, irs); } else if (elem_type->ty != Tbit) { - // %% hmm, maybe generating a call to builtin memcmp would be easier... - - // The front end will cast a static array to a dynamic array - // for EqualExp, so some of this code is pointless (static_size_type) - Type * elem_type = e1->type->toBasetype()->next->toBasetype(); - // Assumes for bit that unused bits in last unit are all zero - tree array_expr[3]; - tree len_expr[3]; - tree data_expr[3]; - tree static_size_type = NULL_TREE; - - for (int i = 1; i <= 2; i++) { - Expression * e = i == 1 ? e1 : e2; - TY e_base_ty = i == 1 ? base_ty_1 : base_ty_2; + tree len_expr[2]; + tree data_expr[2]; - array_expr[i] = irs->maybeMakeTemp( e->toElem(irs) ); + 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; if ( e_base_ty == Tarray ) { - data_expr[i] = build1(INDIRECT_REF, void_type_node, - irs->darrayPtrRef( array_expr[i] )); - len_expr[i] = irs->darrayLenRef( array_expr[i] ); + tree array_expr = irs->maybeMakeTemp( e->toElem(irs) ); + + data_expr[i] = irs->darrayPtrRef( array_expr ); + len_expr[i] = irs->darrayLenRef( array_expr ); // may be used twice -- should be okay } else { - data_expr[i] = e->toElem(irs); + data_expr[i] = irs->addressOf( e->toElem(irs) ); len_expr[i] = ((TypeSArray *) e->type->toBasetype())->dim->toElem(irs); - static_size_type = TREE_TYPE( data_expr[i] ); } } - if (static_size_type) { - TREE_TYPE( data_expr[1] ) = static_size_type; - TREE_TYPE( data_expr[2] ) = static_size_type; - } else { - tree byte_size_expr; - - len_expr[1] = irs->maybeMakeTemp( len_expr[1] ); + tree t_memcmp = built_in_decls[BUILT_IN_MEMCMP]; + tree result; + tree size; - byte_size_expr = build(MULT_EXPR, size_type_node, - len_expr[1], irs->integerConstant(elem_type->size(), size_type_node)); - - tree vb_type = make_varblock_type(byte_size_expr, irs); - TREE_TYPE( data_expr[1] ) = vb_type; - TREE_TYPE( data_expr[2] ) = vb_type; - } + size = build(MULT_EXPR, size_type_node, + convert(size_type_node, len_expr[0]), // should be size_type already, though + size_int(elem_type->size())); + size = fold( size ); + + result = irs->buildCall( TREE_TYPE(TREE_TYPE( t_memcmp )), + irs->addressOf( t_memcmp ), + tree_cons( NULL_TREE, data_expr[0], + tree_cons( NULL_TREE, data_expr[1], + tree_cons( NULL_TREE, size, NULL_TREE )))); + + result = irs->boolOp(op == TOKequal ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR, + irs->boolOp(op == TOKequal ? EQ_EXPR : NE_EXPR, len_expr[0], len_expr[1]), + irs->boolOp(op == TOKequal ? EQ_EXPR : NE_EXPR, result, integer_zero_node)); - // %% conversions on sizes.. - tree result = irs->boolOp(op == TOKequal ? TRUTH_ANDIF_EXPR : TRUTH_ORIF_EXPR, - irs->boolOp(op == TOKequal ? EQ_EXPR : NE_EXPR, len_expr[1], len_expr[2]), - irs->boolOp(op == TOKequal ? EQ_EXPR : NE_EXPR, data_expr[1], data_expr[2])); return convert(type->toCtype(), result); } else { Array args; @@ -810,7 +788,7 @@ tree ary_t; args[1] = e1_slice->lwr ? - e1_slice->lwr->toElem(irs) : irs->integerConstant(0, size_type_node); + e1_slice->lwr->toElem(irs) : size_int(0); args[2] = e1_slice->upr ? e1_slice->upr->toElem(irs) : NULL_TREE; @@ -836,12 +814,41 @@ } else { // copy a range if (elem_type->ty != Tbit) { - // %% 1. check both dynamic arrays 2. can use builtin with varblock.. - 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()); + 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] = { irs->rawArray(e2), @@ -1406,7 +1413,7 @@ // %%TODO: type conversions... final_length = build(MULT_EXPR, size_type_node, orig_length, - irs->integerConstant(multiple, size_type_node)); + size_int(multiple)); final_length = fold( final_length ); } @@ -1415,7 +1422,7 @@ lib_call = LIBCALL_NEWARRAYI; } - final_size = irs->integerConstant(elem_type->size(), size_type_node); + final_size = size_int(elem_type->size()); } else { final_init = irs->integerConstant(0, Type::tbit->toCtype()); lib_call = LIBCALL_NEWBITARRAY; @@ -1648,7 +1655,6 @@ announce_function( fn_decl ); current_function_decl = fn_decl; - // DECL_CONTEXT( fn_decl ) is set in toSymbol() TREE_STATIC( fn_decl ) = 1; // set after body is set? result_decl = build_decl( RESULT_DECL, NULL_TREE, type->next->toCtype() ); @@ -1755,11 +1761,10 @@ // Start a binding level for the function body //(*lang_hooks.decls.pushlevel) (0); - cur_irs->startBindings(); + cur_irs->startScope(); gen.doLineNote(loc); - // Initialize 'out' arguments to default values #if D_NO_TRAMPOLINES if (isNested()) { tree sc_expr = make_node(RTL_EXPR); @@ -1773,31 +1778,15 @@ expand_expr_stmt_value(mod_expr, 0, 1); } #endif + // + //if (isMain() /* && also check not nested like the C compiler does */) + // expand_main_function (); - /* Initialization of out arguments is now handled by the front end. - if (parameters) { - // "this" argument is always In; start with first normal arg - for (int i = 0; i < (int) parameters->dim; i++) { - VarDeclaration * param = (VarDeclaration *) parameters->data[i]; - tree parm_decl = param->toSymbol()->Stree; - - if ( param->isOut() && ! param->isIn() ) { - tree init_exp = build(MODIFY_EXPR, void_type_node, - build1(INDIRECT_REF, TREE_TYPE(TREE_TYPE(parm_decl)), parm_decl), - cur_irs->convertForAssignment(param->type->defaultInit(), param->type)); - expand_expr_stmt_value(init_exp, 0, 1); - } - } - } - */ - - if (vresult) { - //vresult->toObjFile(); + if (vresult) cur_irs->emitLocalVar(vresult); - } fbody->toIR(cur_irs); - cur_irs->endBindings(); + cur_irs->endScope(); #ifdef D_GCC_VER330 expand_function_end (input_filename, loc.linnum, 0, fn_decl); @@ -1814,9 +1803,6 @@ expand_end_bindings (NULL_TREE, 0, 1); - // - //if (isMain() /* && also check not nested like the C compiler does */) - // expand_main_function (); //expand_stmt (DECL_SAVED_TREE (fn_decl)); //if (lang_expand_function_end) @@ -1826,6 +1812,8 @@ rest_of_compilation( fn_decl ); if (isNested()) pop_function_context(); + else + current_function_decl = NULL_TREE; // must come before endFunction cur_irs = cur_irs->endFunction(); } else { @@ -1840,7 +1828,7 @@ rest_of_decl_compilation(fn_decl, NULL, 1, 0); } - pushdecl(fn_decl); + pushdecl(fn_decl); // %%EXPERIMENTAL -- don't pushdecl functions! } @@ -1868,6 +1856,11 @@ } } + /* zomg + if (Module::moduleinfo) + Module::moduleinfo->type->toCtype(); + */ + if (needModuleInfo()) { { ModuleInfo & mi = gen.getModuleInfo(); @@ -1950,35 +1943,57 @@ type * Type::toCtype() { - switch (ty) { - case Tvoid: return void_type_node; - case Tint8: return intQI_type_node; - case Tuns8: return unsigned_intQI_type_node; - case Tint16: return intHI_type_node; - case Tuns16: return unsigned_intHI_type_node; - case Tint32: return intSI_type_node; - case Tuns32: return unsigned_intSI_type_node; - case Tint64: return intDI_type_node; - case Tuns64: return unsigned_intDI_type_node; - case Timaginary32: // %% make another type node for this with another name for debugging - case Tfloat32: return float_type_node; - case Timaginary64: - case Tfloat64: return double_type_node; - case Timaginary80: - case Tfloat80: return long_double_type_node; - case Tcomplex32: return complex_float_type_node; - case Tcomplex64: return complex_double_type_node; - case Tcomplex80: return complex_long_double_type_node; - case Tbit: return unsigned_intQI_type_node; // This is what DMD does - case Tchar: return unsigned_intQI_type_node; - case Twchar: return unsigned_intHI_type_node; - case Tdchar: return unsigned_intSI_type_node; - case Terror: return error_mark_node; - default: - ::error("unexpected call to Type::toCtype() for %s\n", this->toChars()); - abort(); - return NULL_TREE; + if (! ctype) { + switch (ty) { + case Tvoid: return void_type_node; + case Tint8: return intQI_type_node; + case Tuns8: return unsigned_intQI_type_node; + case Tint16: return intHI_type_node; + case Tuns16: return unsigned_intHI_type_node; + case Tint32: return intSI_type_node; + case Tuns32: return unsigned_intSI_type_node; + case Tint64: return intDI_type_node; + case Tuns64: return unsigned_intDI_type_node; + case Tfloat32: return float_type_node; + case Tfloat64: return double_type_node; + case Tfloat80: return long_double_type_node; + case Tcomplex32: return complex_float_type_node; + case Tcomplex64: return complex_double_type_node; + case Tcomplex80: return complex_long_double_type_node; + /* The following types copy an existing type so that they can have + unique names. Also need to change TYPE_MAIN_VARIANT so tree.c + functions don't use the original types for arrays, etc. */ + case Tbit: + //ctype = copy_node(unsigned_intQI_type_node); // This is what DMD does + ctype = build_type_copy( unsigned_intQI_type_node ); + return ctype; + case Tchar: + ctype = build_type_copy( unsigned_intQI_type_node ); + return ctype; + case Twchar: + ctype = build_type_copy( unsigned_intHI_type_node ); + return ctype; + case Tdchar: + ctype = build_type_copy( unsigned_intSI_type_node ); + return ctype; + case Timaginary32: + ctype = build_type_copy( float_type_node ); + return ctype; + case Timaginary64: + ctype = build_type_copy( double_type_node ); + return ctype; + case Timaginary80: + ctype = build_type_copy( long_double_type_node ); + return ctype; + + case Terror: return error_mark_node; + default: + ::error("unexpected call to Type::toCtype() for %s\n", this->toChars()); + abort(); + return NULL_TREE; + } } + return ctype; } // This is not used for GCC @@ -2067,6 +2082,7 @@ if (! ctype) { // need to set this right away in case of self-references ctype = make_node( sym->isUnionDeclaration() ? UNION_TYPE : RECORD_TYPE ); + TYPE_LANG_SPECIFIC( ctype ) = build_d_type_lang_specific(this); if (sym->ident) { TYPE_NAME( ctype ) = build_decl(TYPE_DECL, @@ -2077,6 +2093,7 @@ agg_layout.go(); agg_layout.finish(); + gen.addAggMethods(ctype, sym); gen.declareType(ctype, sym); } return ctype; @@ -2093,7 +2110,7 @@ if (! ctype) { ListMaker type_list; tree ret_type; - + if (varargs && linkage == LINKd) { // hidden _arguments parameter type_list.cons( Type::typeinfo->type->arrayOf()->toCtype() ); @@ -2119,6 +2136,24 @@ ctype = build_function_type(ret_type, type_list.head); TYPE_LANG_SPECIFIC( ctype ) = build_d_type_lang_specific(this); + + if (linkage == LINKwindows) + ctype = gen.addTypeAttribute(ctype, "stdcall"); + +#ifdef D_DMD_CALLING_CONVENTIONS + // W.I.P. + /* Setting this on all targets. TARGET_RETURN_IN_MEMORY has precedence + over this attribute. So, only targets on which flag_pcc_struct_return + is considered will be affected. */ + if ( (linkage == LINKd && next->size() <= 8) || + (next && next->toBasetype()->ty == Tarray)) + ctype = gen.addTypeAttribute(ctype, "no_pcc_struct_return"); // EXPER + +#ifdef TARGET_386 + if (linkage == LINKd && ! TARGET_64BIT) + ctype = gen.addTypeAttribute(ctype, "regparm", integer_one_node); +#endif +#endif } return ctype; } @@ -2178,55 +2213,183 @@ return ctype; } +#if D_GCC_VER < 34 +#define BINFO_ELTS 8 +#endif + +/* Create debug information for a ClassDeclaration's inheritance tree. + Interfaces are included because I do not see any benefit. */ +static tree +binfo_for(tree tgt_binfo, ClassDeclaration * cls) +{ + tree binfo = make_tree_vec(BINFO_ELTS); + TREE_TYPE (binfo) = TREE_TYPE( cls->type->toCtype() ); // RECORD_TYPE, not REFERENCE_TYPE + BINFO_INHERITANCE_CHAIN(binfo) = tgt_binfo; + BINFO_OFFSET (binfo) = gen.integerConstant(0, Type::tuns32); // %% type? + + if (cls->baseClass) { + tree prot_tree; + + BINFO_BASETYPES(binfo) = make_tree_vec(1); + BINFO_BASETYPE(binfo, 0) = binfo_for(binfo, cls->baseClass); +#ifdef BINFO_BASEACCESSES + BINFO_BASEACCESSES(binfo) = make_tree_vec(1); + switch ( ((BaseClass *) cls->baseclasses.data[0])->protection ) { + case PROTpublic: + prot_tree = access_public_node; + break; + case PROTprotected: + prot_tree = access_protected_node; + break; + case PROTprivate: + prot_tree = access_private_node; + break; + default: + prot_tree = access_public_node; + break; + } + BINFO_BASEACCESS(binfo,0) = prot_tree; +#endif + } + + return binfo; +} + +/* Create debug information for an InterfaceDeclaration's inheritance + tree. In order to access all inherited methods in the debugger, + the entire tree must be described. + + This function makes assumptions about inherface layout. */ +static tree +intfc_binfo_for(tree tgt_binfo, ClassDeclaration * iface, unsigned & inout_offset) +{ + tree binfo = make_tree_vec(BINFO_ELTS); + tree prot_tree; + TREE_TYPE (binfo) = TREE_TYPE( iface->type->toCtype() ); // RECORD_TYPE, not REFERENCE_TYPE + BINFO_INHERITANCE_CHAIN(binfo) = tgt_binfo; + BINFO_OFFSET (binfo) = gen.integerConstant(inout_offset * + int_size_in_bytes(ptr_type_node), Type::tuns32); // %% type? + + if (iface->baseclasses.dim) { + BINFO_BASETYPES(binfo) = make_tree_vec(iface->baseclasses.dim); +#ifdef BINFO_BASEACCESSES + BINFO_BASEACCESSES(binfo) = make_tree_vec(iface->baseclasses.dim); +#endif + } + for (unsigned i = 0; i < iface->baseclasses.dim; i++) { + BaseClass * bc = (BaseClass *) iface->baseclasses.data[i]; + + if (i) + inout_offset++; + + BINFO_BASETYPE(binfo, i) = intfc_binfo_for(binfo, bc->base, inout_offset); +#ifdef BINFO_BASEACCESSES + switch ( bc->protection ) { + case PROTpublic: + prot_tree = access_public_node; + break; + case PROTprotected: + prot_tree = access_protected_node; + break; + case PROTprivate: + prot_tree = access_private_node; + break; + default: + prot_tree = access_public_node; + break; + } + BINFO_BASEACCESS(binfo, i) = prot_tree; +#endif + } + + return binfo; +} + type * TypeClass::toCtype() { if (! ctype) { - tree vtbl_type = Type::tvoid->pointerTo()->pointerTo()->toCtype(); tree rec_type; Array base_class_decls; + bool inherited = sym->baseClass != 0; + tree obj_rec_type; + tree vfield; + /* Need to set ctype right away in case of self-references to + the type during this call. */ rec_type = make_node( RECORD_TYPE ); - // TypeClass is really a reference type... need to set this right away - // in case of self-references to the type during this call ctype = build_reference_type( rec_type ); - // This (could be) set on both the REFERENCE_TYPE and RECORD_TYPE - TYPE_LANG_SPECIFIC( ctype ) = build_d_type_lang_specific( this ); - - ClassDeclaration * the_class_decl = ((TypeClass*)this)->sym; + // TYPE_STUB_DECL(rec_type) = build_decl(TYPE_DECL, NULL_TREE, ctype);// EXPER -- DOES NOT KILL REI but does not stop second impact either - AggLayout agg_layout(the_class_decl, rec_type); + obj_rec_type = TREE_TYPE( gen.getObjectType()->toCtype() ); + + // Note that this is set on the reference type, not the record type. + TYPE_LANG_SPECIFIC( ctype ) = build_d_type_lang_specific( this ); - // Add the base object fields + AggLayout agg_layout(sym, rec_type); + + // Most of this silly code is just to produce correct debugging information. /* gdb apparently expects the vtable field to be named - "_vptr$...." (stabsread.c) Otherwise, the debugger gives - lots of annoying error messages. C++ appends the class name - after the '$'. */ - tree decl = build_decl(FIELD_DECL, get_identifier("_vptr$"), vtbl_type); - TYPE_VFIELD( rec_type ) = decl; // This only seems to affect debug info - DECL_VIRTUAL_P( decl ) = 1; // I don't think this does anything + "_vptr$...." (stabsread.c) Otherwise, the debugger gives + lots of annoying error messages. C++ appends the class + name of the first base witht that field after the '$'. */ + /* update: annoying messages might not appear anymore after making + other changes */ + // Add the virtual table pointer + tree decl = build_decl(FIELD_DECL, get_identifier("_vptr$"), /*vtbl_type*/d_vtbl_ptr_type_node); agg_layout.addField( decl, 0 ); // %% target stuff.. - // cdh->flattenedFields.push( 0 ); + + if (inherited) { + vfield = copy_node( decl ); + DECL_ARTIFICIAL( decl ) = DECL_IGNORED_P( decl ) = 1; + } else { + vfield = decl; + } + DECL_VIRTUAL_P( vfield ) = 1; + TYPE_VFIELD( rec_type ) = vfield; // This only seems to affect debug info - if (! the_class_decl->isInterfaceDeclaration()) { + if (! sym->isInterfaceDeclaration()) { + DECL_FCONTEXT( vfield ) = obj_rec_type; + + // Add the monitor // %% target type - decl = build_decl(FIELD_DECL, get_identifier("_monitor"), vtbl_type); + decl = build_decl(FIELD_DECL, get_identifier("_monitor"), ptr_type_node); + DECL_FCONTEXT( decl ) = obj_rec_type; + DECL_ARTIFICIAL( decl ) = DECL_IGNORED_P( decl ) = inherited; agg_layout.addField( decl, 4); // %% target stuff... // Add the fields of each base class agg_layout.go(); } else { - // that's it for interfaces + ClassDeclaration * p = sym; + while (p->baseclasses.dim) { + p = ((BaseClass *) sym->baseclasses.data[0])->base; + } + DECL_FCONTEXT( vfield ) = TREE_TYPE( p->type->toCtype() ); } agg_layout.finish(); - gen.declareType(rec_type, ((TypeClass*)this)->sym); + if (write_symbols != NO_DEBUG) { + gen.addAggMethods(rec_type, sym); + + if ( ! sym->isInterfaceDeclaration() ) + TYPE_BINFO( rec_type ) = binfo_for(NULL_TREE, sym); + else { + unsigned offset = 0; + BaseClass bc; + bc.base = sym; + TYPE_BINFO( rec_type ) = intfc_binfo_for(NULL_TREE, sym, offset); + } + } + + gen.declareType(rec_type, sym); } return ctype; } + void LabelStatement::toIR(IRState* irs) { @@ -2315,8 +2478,8 @@ gen.doLineNote(loc); // %% really? expand_eh_region_start(); - body->toIR(irs); - + if (body) + body->toIR(irs); expand_start_all_catch(); if (catches) { for (unsigned i = 0; i < catches->dim; i++) { @@ -2325,7 +2488,7 @@ expand_start_catch( a_catch->type->toCtype() ); gen.doLineNote(a_catch->loc); - irs->startBindings(); + irs->startScope(); if ( a_catch->var ) { tree exc_obj = irs->convertTo(irs->exceptionObject(), @@ -2337,7 +2500,7 @@ } a_catch->handler->toIR(irs); - irs->endBindings(); + irs->endScope(); expand_end_catch(); } } @@ -2348,12 +2511,12 @@ WithStatement::toIR(IRState * irs) { if (wthis) { - irs->startBindings(); + irs->startScope(); irs->emitLocalVar(wthis); } body->toIR(irs); if (wthis) { - irs->endBindings(); + irs->endScope(); } } @@ -2364,8 +2527,10 @@ InterfaceDeclaration * iface; tree decl = build_decl(VAR_DECL, NULL_TREE, IRState::getObjectType()->toCtype()); - pushdecl(decl); /* only doing this for GC purposes, otherwise should start a new + pushdecl(decl); /* Only doing this for GC purposes, otherwise should start a new block and place it there */ + DECL_ARTIFICIAL( decl ) = 1; + DECL_IGNORED_P( decl ) = 1; DECL_CONTEXT( decl ) = irs->getDeclContext(); tree cleanup = irs->libCall(LIBCALL_MONITOREXIT, 1, & decl); // assuming no conversions needed @@ -2393,7 +2558,7 @@ expand_decl(decl); expand_decl_init(decl); expand_expr_stmt_value(irs->libCall(LIBCALL_MONITORENTER, 1, & decl), 0, 1); - expand_decl_cleanup(decl, cleanup); // %% does it matter where this goes? + expand_decl_cleanup(decl, cleanup); if (body) body->toIR( irs ); expand_end_target_temps(); @@ -2587,7 +2752,8 @@ genrtl_do_pushlevel (); //%% gen.doLineNote( loc ); expand_start_cond( irs->convertForCondition( condition ), 0 ); - ifbody->toIR( irs ); + if (ifbody) + ifbody->toIR( irs ); if ( elsebody ) { expand_start_else(); elsebody->toIR ( irs ); @@ -2611,7 +2777,10 @@ assert(value); - irs->startBindings(); + irs->startScope(); + irs->startBindings(); /* Variables created by the function will probably + end up in a contour created by emitLocalVar. This + startBindings call is just to be safe */ gen.doLineNote( loc ); Loc default_loc; @@ -2681,7 +2850,7 @@ expand_expr_stmt_value( build(MODIFY_EXPR, void_type_node, iter_decl, build(PLUS_EXPR, TREE_TYPE(iter_decl), iter_decl, - irs->integerConstant(elem_type->size(), size_type_node))), + size_int(elem_type->size()))), 0, 1); if (key) { tree key_decl = key->toSymbol()->Stree; @@ -2748,7 +2917,8 @@ expand_end_loop(); irs->endLoop(); - irs->endBindings(); + irs->endBindings(); // not really needed + irs->endScope(); } void @@ -2824,23 +2994,22 @@ ScopeStatement::toIR(IRState* irs) { if (statement) { - irs->startBindings(); + irs->startScope(); statement->toIR( irs ); - irs->endBindings(); + irs->endScope(); } } void CompoundStatement::toIR(IRState* irs) { - if (! statements) - return; - for (unsigned i = 0; i < statements->dim; i++) { - Statement * statement = (Statement *) statements->data[i]; - if (! statement) { - continue; + if (statements) { + for (unsigned i = 0; i < statements->dim; i++) { + Statement * statement = (Statement *) statements->data[i]; + + if (statement) + statement->toIR(irs); } - statement->toIR(irs); } } @@ -2952,8 +3121,8 @@ tree count_var = build_decl(VAR_DECL, NULL_TREE, Type::tsize_t->toCtype()); // %% same type as count? tree ptr_var = build_decl(VAR_DECL, NULL_TREE, TREE_TYPE(TREE_OPERAND(exp, 0))); - pushdecl(count_var); - pushdecl(ptr_var); + pushdecl(count_var); // for GC, shouldn't be seen in debugger + pushdecl(ptr_var); // // for GC, shouldn't be seen in debugger DECL_CONTEXT(count_var) = cur_irs->getDeclContext(); // %% should use make/retrieveStmtExpr.. DECL_CONTEXT(ptr_var) = cur_irs->getDeclContext(); DECL_INITIAL(count_var) = TREE_OPERAND(exp, 2); @@ -3019,6 +3188,7 @@ #endif tree d_null_pointer; +tree d_vtbl_ptr_type_node; void gcc_d_backend_init() @@ -3064,6 +3234,7 @@ // (else) %%TODO: we are relying on default boolean_type_node being 8bit / same as Tbit d_null_pointer = convert(ptr_type_node, integer_zero_node); + //%% fix dbxout_init expects integer_type_node and others to have a TYPE_NAME.. // and it must be a TYPE_DECL, not an IDENTIFIER_NODE @@ -3105,6 +3276,25 @@ // lang_proctect_cleanup_actions = ...; // no need? ... probably needed for autos } + /* copied and modified from cp/decl.c; only way for vtable to work in gdb... */ + // or not, I'm feeling very confused... + if (1) { + /* Make sure we get a unique function type, so we can give + its pointer type a name. (This wins for gdb.) */ + tree vfunc_type = make_node (FUNCTION_TYPE); + TREE_TYPE (vfunc_type) = Type::tint32->toCtype(); // integer_type_node; messed up built in types? + TYPE_ARG_TYPES (vfunc_type) = NULL_TREE; + layout_type (vfunc_type); + + tree vtable_entry_type = build_pointer_type (vfunc_type); + d_vtbl_ptr_type_node = build_pointer_type(vtable_entry_type); + layout_type (d_vtbl_ptr_type_node);// %%TODO: check if needed + } + + // This also allows virtual functions to be called, but when vtbl entries, + // are inspected, function symbol names do not appear. + // d_vtbl_ptr_type_node = Type::tvoid->pointerTo()->pointerTo()->toCtype(); + // This is the C main, not the D main main_identifier_node = get_identifier ("main"); diff -uNr gdc-1g/d/d-irstate.cc gdc-0.8/d/d-irstate.cc --- gdc-1g/d/d-irstate.cc 2004-10-04 01:15:39.000000000 +0200 +++ gdc-0.8/d/d-irstate.cc 2004-10-10 18:50:41.000000000 +0200 @@ -75,6 +75,8 @@ IRState * IRBase::endFunction() { + assert(scopes.dim == 0); + thisFunction = 0; // make shouldDeferFunction return false while ( deferedFuncDecls.dim ) { FuncDeclaration * decl = (FuncDeclaration *) deferedFuncDecls.pop(); @@ -176,6 +178,33 @@ extern "C" void set_block PARAMS ((tree)); extern "C" void insert_block PARAMS ((tree)); +void IRBase::startScope() +{ + unsigned * p_count = new unsigned; + *p_count = 0; + scopes.push(p_count); + + //printf("%*sstartScope\n", scopes.dim, ""); + startBindings(); +} + +void IRBase::endScope() +{ + unsigned * p_count; + + assert(scopes.dim); + p_count = (unsigned *) scopes.tos(); + + //endBindings(); + + //printf("%*s ending scope with %d left \n", scopes.dim, "", *p_count); + while ( *p_count ) + endBindings(); + scopes.pop(); + //printf("%*sendScope\n", scopes.dim, ""); +} + + void IRBase::startBindings() { pushlevel(0); @@ -186,6 +215,10 @@ // Simplying having the whole tree of BLOCKs doesn't matter as // reorder_blocks will discard the whole thing. expand_start_bindings_and_block(0, block); + + assert(scopes.dim); + ++( * (unsigned *) scopes.tos() ); + //printf("%*s start -> %d\n", scopes.dim, "", * (unsigned *) scopes.tos() ); } void IRBase::endBindings() @@ -198,6 +231,11 @@ // Because we used set_block, the popped level/block is not automatically recorded insert_block(block); + + assert(scopes.dim); + --( * (unsigned *) scopes.tos() ); + assert( * (int *) scopes.tos() >= 0 ); + //printf("%*s end -> %d\n", scopes.dim, "", * (unsigned *) scopes.tos() ); } diff -uNr gdc-1g/d/d-irstate.h gdc-0.8/d/d-irstate.h --- gdc-1g/d/d-irstate.h 2004-10-03 06:03:08.000000000 +0200 +++ gdc-0.8/d/d-irstate.h 2004-10-11 01:09:17.000000000 +0200 @@ -56,7 +56,9 @@ FuncDeclaration * getCurrentFunction() { return thisFunction; } IRState * startFunction(FuncDeclaration * decl); +protected: IRState * endFunction(); +public: Array deferedFuncDecls; bool shouldDeferFunction(FuncDeclaration * decl); @@ -92,6 +94,21 @@ // ** "Binding contours" + /* Definitions for IRBase scope code: + "Scope": A container for binding contours. Each user-declared + function has a toplevel scope. Every ScopeStatement creates + a new scope. (And for now, until the emitLocalVar crash is + solved, this also creates a default binding contour.) + + "Binding countour": Same as GCC's definition, whatever that is. + Each user-declared variable will have a binding contour that begins + where the variable is declared and ends at it's containing scope. + */ + Array scopes; // of unsigned* + + void startScope(); + void endScope(); + void startBindings(); void endBindings(); diff -uNr gdc-1g/d/d-lang.cc gdc-0.8/d/d-lang.cc --- gdc-1g/d/d-lang.cc 2004-10-04 00:43:18.000000000 +0200 +++ gdc-0.8/d/d-lang.cc 2004-10-23 22:44:51.000000000 +0200 @@ -17,7 +17,7 @@ */ /* - dc-lang.cc: implementation of backend callbacks and data structures + dc-lang.cc: implementation of back-end callbacks and data structures */ #include "root.h" @@ -38,10 +38,13 @@ #undef LANG_HOOKS_NAME #define LANG_HOOKS_NAME "GNU D" + #undef LANG_HOOKS_INIT #define LANG_HOOKS_INIT d_init + #undef LANG_HOOKS_INIT_OPTIONS #define LANG_HOOKS_INIT_OPTIONS d_init_options + #if D_GCC_VER == 33 #undef LANG_HOOKS_DECODE_OPTION #define LANG_HOOKS_DECODE_OPTION d_decode_option @@ -56,7 +59,6 @@ #undef LANG_HOOKS_PARSE_FILE #define LANG_HOOKS_PARSE_FILE d_parse_file -/* these are required (?); not sure if the above are requried */ #undef LANG_HOOKS_TRUTHVALUE_CONVERSION #define LANG_HOOKS_TRUTHVALUE_CONVERSION d_truthvalue_conversion @@ -81,10 +83,6 @@ #undef LANG_HOOKS_TYPE_PROMOTES_TO #define LANG_HOOKS_TYPE_PROMOTES_TO d_type_promotes_to -// for dynarray cmp -#undef LANG_HOOKS_EXPR_SIZE -#define LANG_HOOKS_EXPR_SIZE d_expr_size - #undef LANG_HOOKS_WRITE_GLOBALS #define LANG_HOOKS_WRITE_GLOBALS d_write_global_declarations @@ -100,11 +98,20 @@ #define LANG_HOOKS_UNSAFE_FOR_REEVAL d_unsafe_for_reeval -static tree d_type_for_mode PARAMS ((enum machine_mode, int)); -//static tree d_type_for_size PARAMS ((unsigned, int)); -static tree d_signed_or_unsigned_type PARAMS ((int, tree)); -tree d_unsigned_type PARAMS ((tree)); -tree d_signed_type PARAMS ((tree)); +static tree d_type_for_mode(enum machine_mode, int); +////static tree d_type_for_size PARAMS ((unsigned, int)); +static tree d_signed_or_unsigned_type(int, tree); +////tree d_unsigned_type(tree); +////tree d_signed_type(tree); + +/* +class DGCCMain { + bool stdInc; + + initOptions() { } +}; +*/ + static bool std_inc; // %%FIX: find a place for this @@ -121,19 +128,17 @@ { // Set default values #if D_GCC_VER == 33 - global.params.argv0 = "cc1d"; // %% fix - all_input_files = new Array; -#else - global.params.argv0 = "cc1d"; // %% fix xstrdup(argv[0]); // %% want last path component #endif + + global.params.argv0 = (char *) progname; global.params.link = 1; global.params.useAssert = 1; global.params.useInvariants = 1; global.params.useIn = 1; global.params.useOut = 1; global.params.useArrayBounds = 1; - flag_bounds_check = global.params.useArrayBounds; // use the existing -fbounds-check flag + flag_bounds_check = global.params.useArrayBounds; // keep in synch with existing -fbounds-check flag global.params.useSwitchError = 1; global.params.useInline = 0; @@ -163,22 +168,12 @@ d_init () #endif { - /* -#if D_GCC_VER == 33 - printf("d_init(%s)\n", filename); -#endif - */ - Type::init(); Id::initialize(); Module::init(); gcc_d_backend_init(); real_t::init(); - // Predefine version identifiers - // %% Should this be defined for GCC? -- It's still the DM front-end - VersionCondition::addGlobalIdent("DigitalMars"); - VersionCondition::addGlobalIdent("GNU"); #ifdef D_CPU_VERSYM VersionCondition::addGlobalIdent(D_CPU_VERSYM); @@ -465,9 +460,6 @@ // %% In gcc 3.4 (not sure about 3.3), wrapup_global_declaration needs // to be called or functions will not be emitted. -// would be best to use the binding stuff in d-lang.c, but non top-level -// functions may not end up in that list -- also means we have to override -// the LANG_HOOKS_WRITE_GLOBALS Array globalFunctions; // Array of tree (for easy passing to wrapup_global_declarations) void @@ -476,7 +468,6 @@ globalFunctions.push(decl); } -// %% maint note -- need to keep this sync'd with the default versions static void d_write_global_declarations() { @@ -488,8 +479,7 @@ int d_unsafe_for_reeval (tree exp) { - /* Statement expressions may not be reevaluated, likewise compound - literals. */ + /* Statement expressions may not be reevaluated. */ if (TREE_CODE (exp) == (enum tree_code) D_STMT_EXPR) return 2; @@ -497,8 +487,6 @@ return -1; } - - static Module * current_module = 0; struct Module * getCurrentModule() { @@ -530,10 +518,7 @@ char * name; unsigned i; - // %%TODO: move this to the post-options lang hook - { - global.params.useArrayBounds = flag_bounds_check; - } + global.params.useArrayBounds = flag_bounds_check; if (gen.emitTemplates == TEauto) { gen.emitTemplates = (SUPPORTS_ONE_ONLY) ? TEfull : TEprivate; } @@ -558,6 +543,13 @@ printf("main_input_filename = '%s'\n", main_input_filename); */ + /* hack... + */ + Type::tbit->toCtype(); + Type::tchar->toCtype(); + Type::twchar->toCtype(); + Type::tdchar->toCtype(); + for (TY ty = (TY) 0; ty < TMAX; ty = (TY)(ty + 1)) { if (Type::basic[ty]) nametype(Type::basic[ty]); @@ -752,6 +744,7 @@ */ //printf("d_parse_file: parsed!\n"); + the_one->genobjfile(); // should probably set current_module to itself #if D_GCC_VER == 33 (*debug_hooks->end_source_file) (lineno); @@ -1203,7 +1196,8 @@ // %% Pascal: if not a local external routine decl doesn't consitite nesting // %% probably should be cur_irs->getDeclContext() - if ( DECL_CONTEXT( decl ) != NULL_TREE ) + // %% should only be for variables OR, should also use TRANSLATION_UNIT for toplevel.. + if ( DECL_CONTEXT( decl ) == NULL_TREE ) DECL_CONTEXT( decl ) = current_function_decl; // could be NULL_TREE (top level) .. hmm. // hm.m. /* Put decls on list in reverse order. We will reverse them later if necessary. */ @@ -1222,8 +1216,7 @@ } -// %% this is called by dbxout_init from lang_dependend init when -gstabs is given -// don't need to give it anything? +// Supports dbx and stabs tree getdecls () { @@ -1278,17 +1271,6 @@ return l; } -// hack.. for comparing dynamic arrays -tree -d_expr_size (tree exp) -{ - struct lang_type * l = TYPE_LANG_SPECIFIC( TREE_TYPE( exp )); - if (l && l->varblock_size) - return l->varblock_size; - else - return lhd_expr_size(exp); -} - tree d_keep_list = NULL_TREE; void dkeep(tree t) { diff -uNr gdc-1g/d/d-lang.h gdc-0.8/d/d-lang.h --- gdc-1g/d/d-lang.h 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/d-lang.h 2004-10-14 02:28:08.000000000 +0200 @@ -19,20 +19,20 @@ #ifndef GCC_DCMPLR_DC_LANG_H #define GCC_DCMPLR_DC_LANG_H -// Nothing is added to tree_identifier; +/* Nothing is added to tree_identifier; */ struct lang_identifier GTY(()) { - struct tree_identifier ignore; + struct tree_identifier ignore; }; -// This is required to be defined, but we do not use it. +/* This is required to be defined, but we do not use it. */ struct language_function GTY(()) { - int unused; + int unused; }; -// The DMD front end types have not been integrated into the GCC garbage -// collection system. Handle this by using the "skip" attribute. +/* The DMD front end types have not been integrated into the GCC garbage + collection system. Handle this by using the "skip" attribute. */ struct Declaration; typedef struct Declaration *DeclarationGTYP; struct lang_decl GTY(()) @@ -40,18 +40,17 @@ DeclarationGTYP GTY ((skip(""))) d_decl; }; -// This lang_type field is not set for every GCC type. +/* The lang_type field is not set for every GCC type. */ struct Type; typedef struct Type *TypeGTYP; struct lang_type GTY(()) { TypeGTYP GTY((skip(""))) d_type; - tree varblock_size; bool is_nested_function; }; -// Another required, but unused declaration. This could be simplified, since -// there is no special lang_identifier +/* Another required, but unused declaration. This could be simplified, since + there is no special lang_identifier */ union lang_tree_node GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), chain_next ("(union lang_tree_node *)TREE_CHAIN (&%h.generic)"))) @@ -62,48 +61,6 @@ struct lang_identifier GTY ((tag ("1"))) identifier; }; -extern bool d_mark_addressable PARAMS ((tree)); -extern tree d_truthvalue_conversion PARAMS ((tree)); -extern tree d_convert_basic PARAMS ((tree, tree)); - -#ifdef __cplusplus -extern struct lang_type * build_d_type_lang_specific(Type * t); -#endif - -extern void init_global_binding_level(void); - -extern void set_decl_binding_chain(tree decl_chain); - -extern tree d_type_for_size(unsigned bits , int unsignedp); -extern tree d_unsigned_type(tree); -extern tree d_signed_type(tree); - -#if D_GCC_VER == 33 -extern rtx d_expand_expr(tree, rtx, enum machine_mode, int); -#else -extern rtx d_expand_expr(tree, rtx, enum machine_mode, int, rtx *); -#endif - -/* %% gty ? */ -extern tree d_void_zero_node; /* This is in c-common as a #define */ -#if D_GCC_VER == 33 -/* In GCC 3.3, these are in c-common; in 3.4, they are in tree.h */ -extern tree boolean_type_node; /* %% should be bit_type */ -extern tree boolean_false_node; -extern tree boolean_true_node; -#endif - -struct Module; -struct Module * getCurrentModule(void); - - -extern -#ifdef __cplusplus - "C" -#endif -tree pushdecl PARAMS ((tree)); - -void d_add_global_function PARAMS(( tree )); #undef DEFTREECODE #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) SYM, @@ -117,8 +74,11 @@ /* True if the Tdelegate typed expression is not really a variable, but a literal function / method reference */ #define D_IS_METHOD_CALL_EXPR(NODE) (TREE_LANG_FLAG_0(NODE)) -/* True if the symbol should be made "link one only" */ + +/* True if the symbol should be made "link one only". This is used to + defer calling make_decl_one_only() before the decl has been prepared. */ #define D_DECL_ONE_ONLY(NODE) (TREE_LANG_FLAG_1(NODE)) + /* True if the symbol is a template member. Need to distinguish between templates and other shared static data so that the latter is not affected by -femit-templates. */ @@ -127,7 +87,6 @@ /* The D front-end does not use the 'binding level' system for a symbol table, It is only needed to get debugging information for local variables and otherwise support the backend. */ - struct binding_level GTY(()) { /* A chain of declarations. These are in the reverse of the order supplied. */ @@ -154,14 +113,12 @@ extern GTY(()) struct binding_level * current_binding_level; extern GTY(()) struct binding_level * global_binding_level; -extern GTY(()) tree d_void_zero_node; #if D_GCC_VER == 33 extern GTY(()) tree boolean_type_node; extern GTY(()) tree boolean_true_node; extern GTY(()) tree boolean_false_node; #endif -/* %% TODO: move these to another file */ extern GTY(()) tree intmax_type_node; extern GTY(()) tree uintmax_type_node; extern GTY(()) tree signed_size_type_node; @@ -169,10 +126,41 @@ extern GTY(()) tree const_string_type_node; extern GTY(()) tree d_null_pointer; +extern GTY(()) tree d_void_zero_node; +extern GTY(()) tree d_vtbl_ptr_type_node; + +#ifdef __cplusplus +/* In d-lang.cc. These are called through function pointers + and do not need to be "extern C". */ +extern bool d_mark_addressable PARAMS ((tree)); +extern tree d_truthvalue_conversion PARAMS ((tree)); +extern tree d_convert_basic PARAMS ((tree, tree)); + +extern void init_global_binding_level(void); +extern void set_decl_binding_chain(tree decl_chain); + +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); + +#if D_GCC_VER == 33 +extern rtx d_expand_expr(tree, rtx, enum machine_mode, int); +#else +extern rtx d_expand_expr(tree, rtx, enum machine_mode, int, rtx *); +#endif + +extern struct lang_type * build_d_type_lang_specific(Type * t); +struct Module; +struct Module * getCurrentModule(void); +#endif #ifdef __cplusplus extern "C" { #endif +/* In d-lang.cc */ +tree pushdecl PARAMS ((tree)); /* In d-builtins.c */ extern void d_init_builtins PARAMS ((void)); @@ -190,9 +178,10 @@ } #endif - /* protect from garbage collection */ extern GTY(()) tree d_keep_list; +#ifdef __cplusplus extern void dkeep(tree t); +#endif #endif diff -uNr gdc-1g/d/dmd/aggregate.h gdc-0.8/d/dmd/aggregate.h --- gdc-1g/d/dmd/aggregate.h 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd/aggregate.h 2004-10-15 01:21:22.000000000 +0200 @@ -7,6 +7,12 @@ // 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, October 2004 +*/ + #ifndef DMD_AGGREGATE_H #define DMD_AGGREGATE_H @@ -46,6 +52,10 @@ InvariantDeclaration *inv; // invariant NewDeclaration *aggNew; // allocator DeleteDeclaration *aggDelete; // deallocator +#ifdef IN_GCC + + Array methods; // flat list of all methods for debug information +#endif AggregateDeclaration(Loc loc, Identifier *id); diff -uNr gdc-1g/d/dmd/constfold.c gdc-0.8/d/dmd/constfold.c --- gdc-1g/d/dmd/constfold.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd/constfold.c 2004-10-10 18:50:41.000000000 +0200 @@ -127,7 +127,11 @@ } if (type->isintegral()) - return new IntegerExp(loc, e1->toInteger(), type); + { + IntegerExp * e = new IntegerExp(loc, e1->toInteger(), type); + e->toInteger(); + return e; + } if (type->isreal()) return new RealExp(loc, e1->toReal(), type); if (type->isimaginary()) diff -uNr gdc-1g/d/dmd/expression.c gdc-0.8/d/dmd/expression.c --- gdc-1g/d/dmd/expression.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd/expression.c 2004-10-18 05:27:20.000000000 +0200 @@ -638,7 +638,7 @@ { switch (t->ty) { - case Tbit: value &= 1; break; + case Tbit: value = value != 0; break; case Tint8: value = (d_int8) value; break; case Tchar: case Tuns8: value = (d_uns8) value; break; @@ -862,7 +862,7 @@ complex_t ImaginaryExp::toComplex() { - return value; + return complex_t(0, value); } Expression *ImaginaryExp::semantic(Scope *sc) diff -uNr gdc-1g/d/dmd/func.c gdc-0.8/d/dmd/func.c --- gdc-1g/d/dmd/func.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd/func.c 2004-10-15 01:21:22.000000000 +0200 @@ -130,6 +130,13 @@ } #endif +#ifdef IN_GCC + AggregateDeclaration *ad; + + ad = parent->isAggregateDeclaration(); + if (ad) + ad->methods.push(this); +#endif sd = parent->isStructDeclaration(); if (sd) { diff -uNr gdc-1g/d/dmd/html.c gdc-0.8/d/dmd/html.c --- gdc-1g/d/dmd/html.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd/html.c 2004-10-23 22:44:51.000000000 +0200 @@ -33,7 +33,7 @@ inline int istagstart(int c) { - return (isalpha(c) || c == '_'); + return (isalpha(c) || c == '_' || c == '!'); } inline int istag(int c) @@ -61,7 +61,7 @@ void Html::error(const char *format, ...) { - printf("%s(%d) : HTML Error: ", sourcename, linnum); + printf("%s:%d: HTML Error: ", sourcename, linnum); va_list ap; va_start(ap, format); @@ -525,6 +525,7 @@ "not", 172, "shy", 173, "reg", 174, + NULL, 0 // BUG: This is only a partial list. // For the rest, consult: @@ -536,7 +537,7 @@ int i; // BUG: this is a dumb, slow linear search - for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) + for (i = 0; names[i].name; i++) { // Do case insensitive compare if (memicmp(names[i].name, (char *)p, length) == 0) diff -uNr gdc-1g/d/dmd/root.c gdc-0.8/d/dmd/root.c --- gdc-1g/d/dmd/root.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd/root.c 2004-10-08 03:26:57.000000000 +0200 @@ -1720,7 +1720,7 @@ // Clear other bits in last word mask = (1 << (bitdim & 31)) - 1; if (mask) - data[allocdim - 1] &= ~mask; + data[allocdim - 1] &= mask; } void Bits::clear() diff -uNr gdc-1g/d/dmd/todt.c gdc-0.8/d/dmd/todt.c --- gdc-1g/d/dmd/todt.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd/todt.c 2004-10-25 00:28:38.000000000 +0200 @@ -115,6 +115,23 @@ { d = v->init->toDt(); } + else if (v->offset >= offset) + { + unsigned k; + unsigned offset2 = v->offset + v->type->size(); + // Make sure this field does not overlap any explicitly + // initialized field. + for (k = j + 1; k < dts.dim; k++) + { + VarDeclaration *v2 = (VarDeclaration *)ad->fields.data[k]; + + if (v2->offset < offset2 && dts.data[k]) { + break; + } + } + if (k == dts.dim) + v->type->toDt(& d); + } } if (d) { @@ -183,7 +200,7 @@ if (dt) pdtend = dtcat(pdtend, dt); else - pdtend = dtnzeros(pdtend, size); + pdtend = tn->toDt(pdtend); } switch (tb->ty) { @@ -232,8 +249,22 @@ Bits databits; Bits initbits; - databits.resize(dim); - initbits.resize(dim); + if (tb->ty == Tsarray) + { + /* Need to resize to the size of the static array, otherwise set() will + affect bits beyond the last specified element. */ + unsigned sdim = ((TypeSArray*)tb)->dim->toInteger(); // missing overflow check + databits.resize(sdim); + initbits.resize(sdim); + } + else + { + databits.resize(dim); + initbits.resize(dim); + } + + if (tb->next->defaultInit()->toInteger()) + databits.set(); size = sizeof(databits.data[0]); @@ -255,7 +286,7 @@ if (initbits.test(length)) error("duplicate initializations for index %d", length); initbits.set(length); - if (bitval & 1) + if (bitval != 0) databits.set(length); else databits.clear(length); @@ -675,17 +706,33 @@ { while (*pdt) pdt = &((*pdt)->DTnext); - next->toDt(pdt); - if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext) + if (next->toBasetype()->ty != Tbit) { - (*pdt)->DTazeros *= len; + next->toDt(pdt); + if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext) + { + (*pdt)->DTazeros *= len; + } + else + { + for (i = 1; i < len; i++) + { + pdt = next->toDt(pdt); + } + } } else { - for (i = 1; i < len; i++) - { - pdt = next->toDt(pdt); - } + Bits databits; + + databits.resize(len); + if (next->defaultInit()->toInteger()) + databits.set(); +#ifdef IN_GCC + pdt = dtnbits(pdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data, sizeof(databits.data[0])); +#else + pdt = dtnbytes(pdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data); +#endif } } return pdt; diff -uNr gdc-1g/d/dmd/toobj.c gdc-0.8/d/dmd/toobj.c --- gdc-1g/d/dmd/toobj.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd/toobj.c 2004-10-08 03:26:57.000000000 +0200 @@ -816,10 +816,27 @@ dim = ((TypeSArray *)tb)->dim->toInteger(); - // Duplicate Sdt 'dim-1' times, as we already have the first one - while (--dim > 0) + if (tb->next->toBasetype()->ty != Tbit) { - ie->exp->toDt(&s->Sdt); + // Duplicate Sdt 'dim-1' times, as we already have the first one + while (--dim > 0) + { + ie->exp->toDt(&s->Sdt); + } + } + else + { + Bits databits; + + databits.resize(dim); + if (ie->exp->toInteger()) + databits.set(); + s->Sdt = NULL; +#ifdef IN_GCC + dtnbits(& s->Sdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data, sizeof(databits.data[0])); +#else + dtnbytes(& s->Sdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data); +#endif } } } diff -uNr gdc-1g/d/dmd-script gdc-0.8/d/dmd-script --- gdc-1g/d/dmd-script 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/dmd-script 2004-10-10 18:50:41.000000000 +0200 @@ -47,7 +47,7 @@ my $gcc_version = `gdc -dumpversion`; chomp $gcc_version; -$gcc_version = m/^(\d+)\.(\d+)/; +$gcc_version =~ m/^(\d+)\.(\d+)/; my ($gcc_maj, $gcc_min) = ( $1, $2 ); my $target_machine = `gdc -dumpmachine`; @@ -83,7 +83,7 @@ } elsif ( $arg =~ m/^-release$/ ) { push @out, '-frelease'; } elsif ( $arg =~ m/^-unittest$/ ) { - push @out, '-funit-test'; + push @out, '-funittest'; } elsif ( $arg =~ m/^-v$/ ) { push @out, '-v'; # not really equivalent } elsif ( $arg =~ m/^-version=(.*)$/ ) { diff -uNr gdc-1g/d/dt.cc gdc-0.8/d/dt.cc --- gdc-1g/d/dt.cc 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.8/d/dt.cc 2004-10-11 02:13:55.000000000 +0200 @@ -0,0 +1,75 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + 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 +*/ + +#include +#include "dt.h" + +dt_t** +dtval(dt_t** pdt, DT t, integer_t i, void * p) +{ + dt_t * d = new dt_t; + d->dt = t; + d->DTnext = 0; + d->DTint = i; + d->DTpointer = p; + return dtcat(pdt, d); +} + +dt_t** +dtcat(dt_t** pdt, dt_t * d) +{ + assert(d); + // wasted time and mem touching... shortcut DTend field? + while (*pdt) + pdt = & (*pdt)->DTnext; + *pdt = d; + return & d->DTnext; +} + +typedef unsigned bitunit_t; + +dt_t** +dtnbits(dt_t** pdt, unsigned count, char * pbytes, unsigned unit_size) +{ + assert(unit_size == sizeof(bitunit_t)); + assert(count % unit_size == 0); + + bitunit_t * p_unit = (bitunit_t *) pbytes, + * p_unit_end = (bitunit_t *) (pbytes + count); + char * pbits = new char[count]; + char * p_out = pbits; + unsigned b = 0; + char outv = 0; + + while (p_unit < p_unit_end) { + bitunit_t inv = *p_unit++; + + for (unsigned i = 0; i < sizeof(bitunit_t)*8; i++) { + outv |= ((inv >> i) & 1) << b; + if (++b == 8) { + *p_out++ = outv; + b = 0; + outv = 0; + } + } + } + assert( (unsigned)(p_out - pbits) == count); + + return dtnbytes(pdt, count, pbits); +} + diff -uNr gdc-1g/d/dt.h gdc-0.8/d/dt.h --- gdc-1g/d/dt.h 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.8/d/dt.h 2004-10-11 02:13:55.000000000 +0200 @@ -0,0 +1,75 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + 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 +*/ + +#ifndef DMD_DT_H +#define DMD_DT_H + +#include "symbol.h" +#include "d-gcc-tree.h" + +enum DT { + DT_azeros, + DT_common, + DT_nbytes, + DT_abytes, + DT_word, + DT_xoff, + DT_tree +}; + +struct dt_t { + enum DT dt; + struct dt_t * DTnext; + union { + integer_t DTint; + integer_t DTazeros; + }; + union { + Symbol * DTsym; + tree DTtree; + void * DTpointer; + }; +}; + +enum TypeType; + +extern dt_t** dtval(dt_t** pdt, DT t, integer_t i, void * p); +extern dt_t** dtcat(dt_t** pdt, dt_t * d); + +inline dt_t** dtnbytes(dt_t** pdt, unsigned count, char * pbytes) { + return dtval(pdt, DT_nbytes, count, pbytes); } +inline dt_t** dtabytes(dt_t** pdt, TypeType ty, int, unsigned count, char * pbytes) { + return dtval(pdt, DT_abytes, count, pbytes); } +inline dt_t** dtnzeros(dt_t** pdt, unsigned count) { + return dtval(pdt, DT_azeros, count, 0); } +inline dt_t** dtdword(dt_t** pdt, unsigned val) { + return dtval(pdt, DT_word, val, 0); } +inline dt_t** dtxoff(dt_t** pdt, Symbol * sym, unsigned offset, TypeType ty) { + return dtval(pdt, DT_xoff, offset, sym); } +inline dt_t** dttree(dt_t** pdt, tree t) { + return dtval(pdt, DT_tree, 0, t); } +inline void dt_optimize(dt_t *) { } +// %% should be integer_t?, but when used in todt.c, it's assigned to an unsigned +unsigned dt_size(dt_t * dt); + +// Added for GCC to get correct byte ordering +extern dt_t** dtnbits(dt_t** pdt, unsigned count, char * pbytes, unsigned unit_size); +extern dt_t** dtnwords(dt_t** pdt, unsigned word_count, void * pwords, unsigned word_size); +extern dt_t** dtawords(dt_t** pdt, unsigned word_count, void * pwords, unsigned word_size); + +#endif diff -uNr gdc-1g/d/gcc-mars.cc gdc-0.8/d/gcc-mars.cc --- gdc-1g/d/gcc-mars.cc 2004-09-29 04:25:48.000000000 +0200 +++ gdc-0.8/d/gcc-mars.cc 2004-10-17 02:54:25.000000000 +0200 @@ -48,7 +48,7 @@ } if (linnum) - buf.printf("(%d)", linnum); + buf.printf(":%d", linnum); buf.writeByte(0); return (char *)buf.extractData(); } diff -uNr gdc-1g/d/INSTALL gdc-0.8/d/INSTALL --- gdc-1g/d/INSTALL 2004-10-04 01:40:02.000000000 +0200 +++ gdc-0.8/d/INSTALL 2004-10-25 01:05:45.000000000 +0200 @@ -1,13 +1,16 @@ Build Instructions Required source packages - * A recent GCC 3.3.x release or 3.4 snapshot. The C++ and Java packages are required. + * A recent GCC 3.3.x release or 3.4 snapshot. The C++ and Java packages are + required. * The gdc package from the main page. + Required software * The usual GCC requirements (http://gcc.gnu.org/install/prerequisites.html) - * An already-installed C++ compiler (bootstrapping is not supported yet). G++ 3.x is known to work. G++ 2.x is known to not work. + * An already-installed C++ compiler (bootstrapping is not supported yet). + G++ 3.x is known to work. G++ 2.x is known to not work. Directories @@ -20,20 +23,26 @@ 1. Unpack the GCC archive. This creates . 2. Change the the /gcc directory. 3. Unpack the DMD-GCC glue archive. This will create a subdirectory named "d". - 4. In the "d" subdirectory, find the GCC patch closest to your version of GCC. These are all named patch-gcc-.... + 4. In the "d" subdirectory, find the GCC patch closest to your version of + GCC. These are all named patch-gcc-.... 5. From /gcc, apply the patch. Example: patch -p1 < d/patch-gcc-3.4.x - 6. Build GCC using the normal install instructions. The only difference is that "d" is added to the --enable-languages option. Unless you will not be using the recls package, you also need to enable the C++ compiler. + 6. Build GCC using the normal install instructions. The only difference is + that "d" is added to the --enable-languages option. Unless you will not + be using the recls package, you also need to enable the C++ compiler. - If you need to specify a compiler to build GCC other than the system's default, use the "CC" and "CXX" environment variables. Example: + If you need to specify a compiler to build GCC other than the system's + default, use the "CC" and "CXX" environment variables. Example: CC=gcc3 CXX=g++3 /configure --prefix=/usr/local/gcc-3.4 --enable-languages=c,d,c++ Remember to always use "gmake" if GNU Make is not the system's default. - IMPORTANT: If you are updating from an earlier version of GDC without doing a fresh build, delete all object files in /gcc/d before building. + IMPORTANT: If you are updating from an earlier version of GDC without + doing a fresh build, delete all object files in /gcc/d before + building. 7. Install normally with "make install". @@ -41,18 +50,31 @@ Phobos does not build automatically nor is it integrated with the GCC target library system. 1. (For Cygwin only) Change to /gcc/d/phobos/ and run prepcygwin.sh. - 2. Choose a build directory for Phobos (e.g., /phobos), create it, and change to it. If you are updating from an earlier version of GDC, completely remove the old Phobos build directory. - 3. Make sure the newly-installed compiler is in your path. Add to the front of the path so that the gcc and g++ that were just built will be used. - 4. Run /gcc/d/phobos/configure. Use the same --prefix argument that you passed to the GCC configure. You can set the environment variable "DFLAGS". Example: + 2. Choose a build directory for Phobos (e.g., /phobos), create it, + and change to it. If you are updating from an earlier version of GDC, + completely remove the old Phobos build directory. + 3. Make sure the newly-installed compiler is in your path. Add to the front + of the path so that the gcc and g++ that were just built will be used. + 4. Run /gcc/d/phobos/configure. Use the same --prefix argument that + you passed to the GCC configure. You can set the environment variable + "DFLAGS". Example: DFLAGS="-O2 -g -frelease" /gcc/d/phobos/configure --prefix=/usr/local/gcc-3.4 - Use --enable-thread-lib= to specify the linker arguments needed to enable threads. The configure script can usually determine this automatically. + Use --enable-thread-lib= to specify the linker arguments needed to + enable threads. The configure script can usually determine this + automatically. 5. Run make and then make install. Notes - * You can build the unittest with "make unittest". The following failures should be expected: - o On Darwin and FreeBSD, std.math tests will fail because there is no 80-bit real (or library support for it.) + * You can build the unittest with "make unittest". The following failures + should be expected: + o On Darwin and FreeBSD, std.math tests will fail because there is no + 80-bit real (or library support for it.) o On FreeBSD and Linux, std.format:725 will fail for various reasons. - * If you use recls, you need to add -lstdc++ and possibly -shared-libgcc to the link flags (or run g++ and add -lphobos and -lpthread.) Also add /lib to LD_LIBRARY_PATH or whatever is necessary for your system to find shared libraries. OR you try building GCC and your programs with a static libstdc++. + * If you use recls, you need to add -lstdc++ and possibly -shared-libgcc to + the link flags (or run g++ and add -lphobos and -lpthread.) Also add + /lib to LD_LIBRARY_PATH or whatever is necessary for your system + to find shared libraries. OR you try building GCC and your programs with a + static libstdc++. diff -uNr gdc-1g/d/lang-specs.h gdc-0.8/d/lang-specs.h --- gdc-1g/d/lang-specs.h 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/lang-specs.h 2004-10-10 18:50:41.000000000 +0200 @@ -25,12 +25,12 @@ /* %(d_options) ? */ -/* +#if D_DRIVER_ONLY {".html", "@d", 0}, {".HTML", "@d", 0}, {".htm", "@d", 0}, {".HTM", "@d", 0}, -*/ +#endif {".d", "@d", 0}, {".D", "@d", 0}, {"@d", diff -uNr gdc-1g/d/Make-lang.in gdc-0.8/d/Make-lang.in --- gdc-1g/d/Make-lang.in 2004-10-04 00:43:18.000000000 +0200 +++ gdc-0.8/d/Make-lang.in 2004-10-25 00:28:38.000000000 +0200 @@ -23,9 +23,6 @@ # For various glibc, we need to define this to get NAN and FP_ constants D_EXTRA_DEFINES += -D_GNU_SOURCE=1 -# Define if the host has a distinct long double type, frexpl, fmodl, and '%L[efg]' printf formats -# D_EXTRA_DEFINES += -DD_HOST_HAS_LONG_DOUBLE=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++ # into the C++ rule, but that needs a little bit of work @@ -44,7 +41,7 @@ gcc_d_include_dir = $(libsubdir)/$(unlibsubdir)/..`echo $(exec_prefix) | sed -e 's|^$(prefix)||' -e 's|/[^/]*|/..|g'`/include/d D_TREE_H = $(TREE_H) d/d-lang.h d/d-codegen.h d/d-irstate.h d/d-backend.h d/d-gcc-includes.h \ - d/d-gcc-real.h d/missing/symbol.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 @@ -77,14 +74,15 @@ D_BORROWED_C_OBJS= attribs.o -D_INCLUDES = -I$(srcdir)/d -I$(srcdir)/d/dmd -I$(srcdir)/d/missing -Id +D_INCLUDES = -I$(srcdir)/d -I$(srcdir)/d/dmd -Id # -Wno-long-double is for MacOS X -- needs to be configurated #D_CC_FLAGS = -fmessage-length=0 -Wno-long-double -D_CC_FLAGS = -fmessage-length=0 +D_CC_FLAGS = -fmessage-length=0 -O0 -g +# -O0 -g ALL_D_COMPILER_FLAGS = $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(D_INCLUDES) $(D_EXTRA_DEFINES) $(D_CC_FLAGS) # Somehow, I started getting problems with the C++ being included.. -ALL_DMD_COMPILER_FLAGS = $(ALL_CFLAGS) $(ALL_CPPFLAGS) -Id -I$(srcdir)/d/dmd -I$(srcdir)/d/missing -I$(srcdir)/d $(D_EXTRA_DEFINES) $(D_CC_FLAGS) +ALL_DMD_COMPILER_FLAGS = $(ALL_CFLAGS) $(ALL_CPPFLAGS) -Id -I$(srcdir)/d/dmd -I$(srcdir)/d $(D_EXTRA_DEFINES) $(D_CC_FLAGS) # Create the compiler driver for D. $(D_DRIVER_NAME)$(exeext): $(D_DRIVER_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS) @@ -104,10 +102,10 @@ d/todt.dmd.o d/toobj.dmd.o d/typinf.dmd.o d/unialpha.dmd.o d/utf.dmd.o d/version.dmd.o D_GENERATED_SRCS = d/id.c d/impcnvtab.c D_GENERATED_OBJS = d/id.gen.o d/impcnvtab.gen.o -D_MISSING_OBJS = d/symbol.miss.o d/asmstmt.miss.o d/dt.miss.o D_GLUE_OBJS = d/d-lang.glue.o d/d-decls.glue.o d/d-codegen.glue.o d/d-irstate.glue.o \ d/d-glue.glue.o d/d-convert.glue.o d/gcc-mars.glue.o d/d-todt.glue.o d/d-gcc-real.glue.o \ - d/d-gt.cglue.o d/d-builtins.cglue.o d/d-misc.cglue.o d/d-builtins2.glue.o + d/d-gt.cglue.o d/d-builtins.cglue.o d/d-misc.cglue.o d/d-builtins2.glue.o \ + d/symbol.glue.o d/asmstmt.glue.o d/dt.glue.o # The full path for -include ...total.h is only needed for g++ < 3.x # ALL_D_COMPILER_FLAGS causes issues -- c++ instead of C @@ -122,9 +120,6 @@ d/%.gen.o: d/%.c $(CXX) $(ALL_DMD_COMPILER_FLAGS) -o d/$*.gen.o -c $< #hmm $(CC) $(ALL_DMD_COMPILER_FLAGS) -o d/$*.gen.o -c -x c++ $< -d/%.miss.o: $(srcdir)/d/missing/%.cc - $(CXX) $(ALL_D_COMPILER_FLAGS) -DGCC_SAFE_DMD=1 -o d/$*.miss.o -c $< -#hmm $(CC) $(ALL_D_COMPILER_FLAGS) -DGCC_SAFE_DMD=1 -o d/$*.miss.o -c $< d/%.glue.o: $(srcdir)/d/%.cc $(CXX) $(ALL_D_COMPILER_FLAGS) -DGCC_SAFE_DMD=1 -o d/$*.glue.o -c $< #hmm $(CC) $(ALL_D_COMPILER_FLAGS) -DGCC_SAFE_DMD=1 -o d/$*.glue.o -c $< @@ -159,22 +154,36 @@ d/gcc-mars.glue.o: d/gcc-mars.cc $(D_TREE_H) d/d-todt.glue.o: d/d-todt.cc $(D_TREE_H) d/d-gcc-real.glue.o: d/d-gcc-real.cc $(D_TREE_H) -d/asmstmt.miss.o: d/missing/asmstmt.cc $(D_TREE_H) -d/symbol.miss.o: d/missing/symbol.cc $(D_TREE_H) +d/asmstmt.glue.o: d/asmstmt.cc $(D_TREE_H) +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-builtins2.glue.o: d/d-builtins.c $(D_TREE_H) d/d-misc.cglue.o: d/d-misc.c $(D_TREE_H) -# d/gdc.o: d/gdc.c -# $(CC) -o $@ -c $(DRIVER_DEFINES) $< -d/d-gcc.o: gcc.c +ifeq ($(D_silly_ver),3.3) +D_CORETYPES= +else +D_CORETYPES=coretypes.h +endif + +d/d-gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) $(D_CORETYPES) $(TM_H) intl.h multilib.h \ + Makefile $(lang_specs_files) specs.h prefix.h $(GCC_H) (SHLIB_LINK='$(SHLIB_LINK)' \ SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \ $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \ - $(DRIVER_DEFINES) $(ALL_D_COMPILER_FLAGS) -DD_DRIVER_ONLY=1 \ + $(DRIVER_DEFINES) -DD_DRIVER_ONLY=1 \ -c $(srcdir)/gcc.c $(OUTPUT_OPTION)) -D_ALL_OBJS = $(D_GENERATED_OBJS) $(D_BORROWED_C_OBJS) $(D_DMD_OBJS) $(D_MISSING_OBJS) $(D_GLUE_OBJS) +d/d-spec.o: $(srcdir)/d/d-spec.c $(SYSTEM_H) $(D_CORETYPES) $(TM_H) $(GCC_H) $(CONFIG_H) + (SHLIB_LINK='$(SHLIB_LINK)' \ + SHLIB_MULTILIB='$(SHLIB_MULTILIB)'; \ + $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \ + $(ALL_D_COMPILER_FLAGS) \ + $(INCLUDES) -o $@ $(srcdir)/d/d-spec.c) + +D_ALL_OBJS = $(D_GENERATED_OBJS) $(D_BORROWED_C_OBJS) $(D_DMD_OBJS) $(D_GLUE_OBJS) $(D_COMPILER_NAME)$(exeext): $(D_ALL_OBJS) $(BACKEND) $(LIBDEPS) $(CXX) $(ALL_D_COMPILER_FLAGS) $(LDFLAGS) -o $@ \ diff -uNr gdc-1g/d/missing/asmstmt.cc gdc-0.8/d/missing/asmstmt.cc --- gdc-1g/d/missing/asmstmt.cc 2004-04-18 04:14:33.000000000 +0200 +++ gdc-0.8/d/missing/asmstmt.cc 1970-01-01 01:00:00.000000000 +0100 @@ -1,40 +0,0 @@ -// Taken from an earlier version of DMD -- why is it missing from 0.79? - -#include "total.h" -#include "statement.h" - -AsmStatement::AsmStatement(Loc loc, Token *tokens) : - Statement(loc) -{ - this->tokens = tokens; // Do I need to copy these? - asmcode = 0; - asmalign = 0; - refparam = 0; - naked = 0; - regs = 0; -} - -Statement *AsmStatement::syntaxCopy() -{ - // copy tokens? copy 'code'? - AsmStatement * a_s = new AsmStatement(loc,tokens); - a_s->asmcode = asmcode; - a_s->refparam = refparam; - a_s->naked = naked; - a_s->regs = a_s->regs; - return a_s; -} - -Statement *AsmStatement::semantic(Scope *sc) -{ - return Statement::semantic(sc); -} - - -void AsmStatement::toCBuffer(OutBuffer *buf) -{ - buf->printf("AsmStatement::toCBuffer()"); - buf->writenl(); -} - - diff -uNr gdc-1g/d/missing/dt.cc gdc-0.8/d/missing/dt.cc --- gdc-1g/d/missing/dt.cc 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/missing/dt.cc 1970-01-01 01:00:00.000000000 +0100 @@ -1,75 +0,0 @@ -/* GDC -- D front-end for GCC - Copyright (C) 2004 David Friedman - - 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 -*/ - -#include -#include "dt.h" - -dt_t** -dtval(dt_t** pdt, DT t, integer_t i, void * p) -{ - dt_t * d = new dt_t; - d->dt = t; - d->DTnext = 0; - d->DTint = i; - d->DTpointer = p; - return dtcat(pdt, d); -} - -dt_t** -dtcat(dt_t** pdt, dt_t * d) -{ - assert(d); - // wasted time and mem touching... shortcut DTend field? - while (*pdt) - pdt = & (*pdt)->DTnext; - *pdt = d; - return & d->DTnext; -} - -typedef unsigned bitunit_t; - -dt_t** -dtnbits(dt_t** pdt, unsigned count, char * pbytes, unsigned unit_size) -{ - assert(unit_size == sizeof(bitunit_t)); - assert(count % unit_size == 0); - - bitunit_t * p_unit = (bitunit_t *) pbytes, - * p_unit_end = (bitunit_t *) (pbytes + count); - char * pbits = new char[count]; - char * p_out = pbits; - unsigned b = 0; - char outv = 0; - - while (p_unit < p_unit_end) { - bitunit_t inv = *p_unit++; - - for (unsigned i = 0; i < sizeof(bitunit_t)*8; i++) { - outv |= ((inv >> i) & 1) << b; - if (++b == 8) { - *p_out++ = outv; - b = 0; - outv = 0; - } - } - } - assert( (unsigned)(p_out - pbits) == count); - - return dtnbytes(pdt, count, pbits); -} - diff -uNr gdc-1g/d/missing/dt.h gdc-0.8/d/missing/dt.h --- gdc-1g/d/missing/dt.h 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/missing/dt.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,75 +0,0 @@ -/* GDC -- D front-end for GCC - Copyright (C) 2004 David Friedman - - 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 -*/ - -#ifndef DMD_DT_H -#define DMD_DT_H - -#include "symbol.h" -#include "d-gcc-tree.h" - -enum DT { - DT_azeros, - DT_common, - DT_nbytes, - DT_abytes, - DT_word, - DT_xoff, - DT_tree -}; - -struct dt_t { - enum DT dt; - struct dt_t * DTnext; - union { - integer_t DTint; - integer_t DTazeros; - }; - union { - Symbol * DTsym; - tree DTtree; - void * DTpointer; - }; -}; - -enum TypeType; - -extern dt_t** dtval(dt_t** pdt, DT t, integer_t i, void * p); -extern dt_t** dtcat(dt_t** pdt, dt_t * d); - -inline dt_t** dtnbytes(dt_t** pdt, unsigned count, char * pbytes) { - return dtval(pdt, DT_nbytes, count, pbytes); } -inline dt_t** dtabytes(dt_t** pdt, TypeType ty, int, unsigned count, char * pbytes) { - return dtval(pdt, DT_abytes, count, pbytes); } -inline dt_t** dtnzeros(dt_t** pdt, unsigned count) { - return dtval(pdt, DT_azeros, count, 0); } -inline dt_t** dtdword(dt_t** pdt, unsigned val) { - return dtval(pdt, DT_word, val, 0); } -inline dt_t** dtxoff(dt_t** pdt, Symbol * sym, unsigned offset, TypeType ty) { - return dtval(pdt, DT_xoff, offset, sym); } -inline dt_t** dttree(dt_t** pdt, tree t) { - return dtval(pdt, DT_tree, 0, t); } -inline void dt_optimize(dt_t *) { } -// %% should be integer_t?, but when used in todt.c, it's assigned to an unsigned -unsigned dt_size(dt_t * dt); - -// Added for GCC to get correct byte ordering -extern dt_t** dtnbits(dt_t** pdt, unsigned count, char * pbytes, unsigned unit_size); -extern dt_t** dtnwords(dt_t** pdt, unsigned word_count, void * pwords, unsigned word_size); -extern dt_t** dtawords(dt_t** pdt, unsigned word_count, void * pwords, unsigned word_size); - -#endif diff -uNr gdc-1g/d/missing/symbol.cc gdc-0.8/d/missing/symbol.cc --- gdc-1g/d/missing/symbol.cc 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/missing/symbol.cc 1970-01-01 01:00:00.000000000 +0100 @@ -1,91 +0,0 @@ -/* GDC -- D front-end for GCC - Copyright (C) 2004 David Friedman - - 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 -*/ - -#include "symbol.h" -#include "mem.h" - -Symbol::Symbol() -{ - Sident = 0; - Stype = 0; - Sclass = SC_INVALID; - Sfl = FL_INVALID; - Sflags = 0; - - Ssymnum = 0; - Sdt = 0; - - Sstruct = 0; - Sstructalign = 0; - - Stree = 0; // %% make it NULL-TREE, include d-gcc-include - ScontextDecl = 0; - memset(& Sspecial, 0, sizeof(Sspecial)); -} - -// %% fwiw, need to dup the string because sometimes the -// string is alloca()'d -Symbol * -symbol_calloc(const char * string) -{ - Symbol * s = new Symbol; - s->Sident = mem.strdup(string); - return s; -} - -Symbol * -symbol_name(const char * id, int /*sclass*/, TYPE * /*t*/) -{ - // %% Nothing special, just do the same as symbol_calloc - // we don't even bother using sclass and t - - return symbol_calloc(id); -} - -Symbol * -struct_calloc() -{ - return new Symbol; -} - -Symbol * -symbol_generate(SymbolStorageClass /*sc*/, TYPE * /*type*/) -{ - return 0; -} - -Thunk::Thunk() -{ - offset = 0; - symbol = 0; -} - -void -symbol_func(Symbol * /*sym*/) -{ - -} - - -Symbol * -symbol_tree(tree t) -{ - Symbol * s = new Symbol; - s->Stree = t; - return s; -} diff -uNr gdc-1g/d/missing/symbol.h gdc-0.8/d/missing/symbol.h --- gdc-1g/d/missing/symbol.h 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/missing/symbol.h 1970-01-01 01:00:00.000000000 +0100 @@ -1,177 +0,0 @@ -/* GDC -- D front-end for GCC - Copyright (C) 2004 David Friedman - - 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 -*/ - -#ifndef DMD_SYMBOL_H -#define DMD_SYMBOL_H - -#include "root.h" - -#include "d-gcc-tree.h" - -#include "mtype.h" - -enum mangle_t -{ - mTY_INVALID, - mTYman_c, - mTYman_cpp, - mTYman_std, - mTYman_pas, - mTYman_d -}; - -enum TypeType -{ - // no clue about which can be used together.. - TYnptr = 0x001, - TYnfunc = 0x010, - TYjfunc = 0x020, - TYstruct = 0x040, - TYarray = 0x080, - TYbit = 0x100, - TYint = 0x200, - mTYconst = 0x1000, - mTYvolatile = 0x2000 -}; - -typedef int tym_t; - -enum TypeFlag -{ - TFsizeunknown = 0x01, - TFforward = 0x02, - TFprototype = 0x04, - TFfixed = 0x08 -}; - -/* -struct TYPE : Object -{ - tym_t Tty; - mangle_t Tmangle; - TYPE * Tnext; - int Tcount; - int Tflags; - void * Ttag; - void * Tparamtypes; - tree Ttree; - - TYPE(); -}; - -extern TYPE * tsvoid; - -extern TYPE * type_alloc(tym_t ty); // ty: combination of TypeType values -extern TYPE * type_fake(tym_t ty); -extern void type_setcv(TYPE ** pp_type, int ty); -extern void type_setmangle(TYPE ** pp_type, mangle_t mangle); -extern int/ *?* / type_paramsize(TYPE * t); -*/ - -enum SymbolStorageClass -{ - SC_INVALID, - SCextern, - SCstatic, - SCauto, - SCglobal, - SCstruct, - SCcomdat -}; - -typedef enum SymbolStorageClass enum_SC; - -enum SymbolFL -{ - FL_INVALID, - FLextern = 0x01, - FLauto = 0x02, - FLdata = 0x04, - - // GDC specific. This flag indicates an anonymous chunk of data that - // does not need a name or a VER_DECL. - FLstatic_sym = 0x100 -}; - -enum SymbolFlag -{ - SFLimplem = 0x01, - SFLnodebug = 0x02, - STRglobal = 0x04 -}; - -enum SymbolSegment -{ - DATA, - CDATA, - UDATA -}; - -// not sure if this needs to inherit object.. -// union tree_node; typedef union tree_node dt_t; -struct dt_t; - -struct Symbol : Object -{ - Symbol(); - // !!! need a dtor for Sident.. - - char *Sident; - TYPE *Stype; // maybe type/TYPE ? - SymbolStorageClass Sclass; - SymbolFL Sfl; - SymbolSegment Sseg; - int Sflags; - - int Ssymnum; - - dt_t * Sdt; - - // fake classsym.... - Symbol * Sstruct; - int Sstructalign; - - // Specific to GNU backend - tree Stree; - tree ScontextDecl; // The DECL_CONTEXT to use for child declarations - union { - AggregateDeclaration * aggDecl; // AggregateDeclaration.sinit set in AggregateDeclaration::toInitializer - Array * thunks; // of struct Thunk; for FuncDeclarations - } Sspecial; -}; - -struct Thunk -{ - int offset; - Symbol * symbol; - Thunk(); -}; - -typedef struct Symbol Classsym; - -extern Symbol * symbol_calloc(const char * string); -extern Symbol * symbol_name(const char * id, int sclass, TYPE * t); -extern Symbol * struct_calloc(); -extern Symbol * symbol_generate(SymbolStorageClass sc, TYPE * type); -extern void symbol_func(Symbol * sym); -extern void outdata(Symbol * sym); -inline void obj_export(Symbol *, int) { } -inline void obj_moduleinfo(Symbol *sym) { } - -extern Symbol * symbol_tree(tree); -#endif diff -uNr gdc-1g/d/phobos/internal/gc/gcx.d gdc-0.8/d/phobos/internal/gc/gcx.d --- gdc-1g/d/phobos/internal/gc/gcx.d 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/phobos/internal/gc/gcx.d 2004-10-23 22:44:51.000000000 +0200 @@ -1358,8 +1358,7 @@ result = fullcollect(sp); version (GNU) { - // TODO - sp = & sp; + // nothing to do } else { diff -uNr gdc-1g/d/phobos/internal/invariant.d gdc-0.8/d/phobos/internal/invariant.d --- gdc-1g/d/phobos/internal/invariant.d 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/phobos/internal/invariant.d 2004-10-17 02:54:25.000000000 +0200 @@ -1,10 +1,5 @@ -/* NOTE: This file has been patched from the original DMD distribution to - work with the GDC compiler. - Modified by David Friedman, September 2004 -*/ - -extern(C) void _d_invariant(Object o) +void _d_invariant(Object o) { ClassInfo c; //printf("__d_invariant(%p)\n", o); diff -uNr gdc-1g/d/phobos/Makefile.in gdc-0.8/d/phobos/Makefile.in --- gdc-1g/d/phobos/Makefile.in 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/phobos/Makefile.in 2004-10-23 22:44:51.000000000 +0200 @@ -110,6 +110,9 @@ # needed until instrinsics are implemented D_EXTRA_OBJS+=std/intrinsic.o +# currently just add compatibility for a bug +D_EXTRA_OBJS+=gcc/support.o + # need frac-ac: frag-ac.in,etc. CONFIG_D_FRAGMENTS = config/config-head frag-ac frag-gen frag-math config/config-mid config/config-tail diff -uNr gdc-1g/d/phobos/phobos-ver-syms.in gdc-0.8/d/phobos/phobos-ver-syms.in --- gdc-1g/d/phobos/phobos-ver-syms.in 2004-09-21 01:02:30.000000000 +0200 +++ gdc-0.8/d/phobos/phobos-ver-syms.in 2004-10-18 05:27:20.000000000 +0200 @@ -5,4 +5,6 @@ @DCFG_GC_BITS@ @DCFG_TRUNC@ @DCFG_EXP2_LOG2@ +@DCFG_EXECVPE@ +@DCFG_FWIDE@ @DCFG_SA_LEN@ diff -uNr gdc-1g/d/phobos/std/c/mach/mach.d gdc-0.8/d/phobos/std/c/mach/mach.d --- gdc-1g/d/phobos/std/c/mach/mach.d 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/phobos/std/c/mach/mach.d 2004-10-23 22:44:51.000000000 +0200 @@ -22,7 +22,6 @@ extern(C): -// sem_init is not supported; use mach semaphores version (BitsPerWord32) { private alias uint natural_t; diff -uNr gdc-1g/d/phobos/std/loader.d gdc-0.8/d/phobos/std/loader.d --- gdc-1g/d/phobos/std/loader.d 2004-09-21 01:02:30.000000000 +0200 +++ gdc-0.8/d/phobos/std/loader.d 2004-10-23 22:44:51.000000000 +0200 @@ -56,6 +56,12 @@ * * ////////////////////////////////////////////////////////////////////////// */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, October 2004 (applied patches from Anders F Björklund.) +*/ + /** \file D/std/loader.d This file contains the \c D standard library @@ -93,7 +99,7 @@ alias HMODULE HModule_; } } -else version(Linux) +else version(linux) { extern(C) { @@ -107,6 +113,104 @@ char *dlerror(); } } +else version(darwin) +{ + extern(C) + { + // #include + + struct mach_header + { + uint magic; /* mach magic number identifier */ + uint cputype; /* cpu specifier */ + uint cpusubtype; /* machine specifier */ + uint filetype; /* type of file */ + uint ncmds; /* number of load commands */ + uint sizeofcmds; /* the size of all the load commands */ + uint flags; /* flags */ + } + + /* Constant for the magic field of the mach_header */ + const uint MH_MAGIC = 0xfeedface; // the mach magic number + const uint MH_CIGAM = 0xcefaedfe; // x86 variant + + // #include + + typedef void *NSObjectFileImage; + + typedef void *NSModule; + + typedef void *NSSymbol; + + enum // DYLD_BOOL: uint + { + FALSE, + TRUE + } + alias uint DYLD_BOOL; + + enum // NSObjectFileImageReturnCode: uint + { + NSObjectFileImageFailure, /* for this a message is printed on stderr */ + NSObjectFileImageSuccess, + NSObjectFileImageInappropriateFile, + NSObjectFileImageArch, + NSObjectFileImageFormat, /* for this a message is printed on stderr */ + NSObjectFileImageAccess + } + alias uint NSObjectFileImageReturnCode; + + enum // NSLinkEditErrors: uint + { + NSLinkEditFileAccessError, + NSLinkEditFileFormatError, + NSLinkEditMachResourceError, + NSLinkEditUnixResourceError, + NSLinkEditOtherError, + NSLinkEditWarningError, + NSLinkEditMultiplyDefinedError, + NSLinkEditUndefinedError + } + alias uint NSLinkEditErrors; + + + alias NSModule HModule_; + + NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(char *pathName, NSObjectFileImage* objectFileImage); + DYLD_BOOL NSDestroyObjectFileImage(NSObjectFileImage objectFileImage); + + mach_header * NSAddImage(char *image_name, uint options); + const uint NSADDIMAGE_OPTION_NONE = 0x0; + const uint NSADDIMAGE_OPTION_RETURN_ON_ERROR = 0x1; + const uint NSADDIMAGE_OPTION_WITH_SEARCHING = 0x2; + const uint NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED = 0x4; + const uint NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME = 0x8; + + NSModule NSLinkModule(NSObjectFileImage objectFileImage, char* moduleName, uint options); + const uint NSLINKMODULE_OPTION_NONE = 0x0; + const uint NSLINKMODULE_OPTION_BINDNOW = 0x01; + const uint NSLINKMODULE_OPTION_PRIVATE = 0x02; + const uint NSLINKMODULE_OPTION_RETURN_ON_ERROR = 0x04; + const uint NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES = 0x08; + const uint NSLINKMODULE_OPTION_TRAILING_PHYS_NAME = 0x10; + DYLD_BOOL NSUnLinkModule(NSModule module_, uint options); + + void NSLinkEditError(NSLinkEditErrors *c, int *errorNumber, char **fileName, char **errorString); + + DYLD_BOOL NSIsSymbolNameDefined(char *symbolName); + DYLD_BOOL NSIsSymbolNameDefinedInImage(mach_header *image, char *symbolName); + NSSymbol NSLookupAndBindSymbol(char *symbolName); + NSSymbol NSLookupSymbolInModule(NSModule module_, char* symbolName); + NSSymbol NSLookupSymbolInImage(mach_header *image, char *symbolName, uint options); + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND = 0x0; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW = 0x1; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY = 0x2; + const uint NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR = 0x4; + + void* NSAddressOfSymbol(NSSymbol symbol); + char* NSNameOfSymbol(NSSymbol symbol); + } +} else { const int platform_not_discriminated = 0; @@ -282,7 +386,7 @@ return szFileName[0 .. cch].dup; } } -else version(Linux) +else version(linux) { private class ExeModuleInfo { @@ -471,6 +575,258 @@ return mi.m_name; } } +else version(darwin) +{ + private class ExeModuleInfo + { + public: + int m_cRefs; + HModule_ m_hmod; + char[] m_name; + + this(HModule_ hmod, char[] name) + { + m_cRefs = 1; + m_hmod = hmod; + m_name = name; + } + }; + + private void record_error_() + { + NSLinkEditErrors error; + int errno; + char *fileName; + char *err = null; + + NSLinkEditError(&error, &errno, &fileName, &err); + printf("NSLinkEditError: %d %d - %s %s\n", cast(uint) error, errno, fileName, err); + + s_lastError = (err == null) ? "" : err[0 .. std.string.strlen(err)]; + } + + private int s_init; + private ExeModuleInfo [char[]] s_modules; + private char[] s_lastError; // This is NOT thread-specific + + private int ExeModule_Init_() + { + if(1 == ++s_init) + { + return 0; + } + + return 1; + } + + private void ExeModule_Uninit_() + { + if(0 == --s_init) + { + } + } + + private HXModule ExeModule_Load_(in char[] moduleName) + in + { + assert(null !== moduleName); + } + body + { + ExeModuleInfo mi = s_modules[moduleName]; + + if(null !== mi) + { + return (++mi.m_cRefs, cast(HXModule)mi); + } + else + { + NSModule handle = null; + NSObjectFileImage fileImage = null; + char * filename = toStringz(moduleName); + // printf("DEBUG Trying to load: %s\n", filename); + + NSObjectFileImageReturnCode returnCode = + NSCreateObjectFileImageFromFile(filename, &fileImage); + if(returnCode == NSObjectFileImageSuccess) + { + handle = NSLinkModule(fileImage,filename, + NSLINKMODULE_OPTION_RETURN_ON_ERROR | + NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_BINDNOW); + NSDestroyObjectFileImage(fileImage); + } + else if(returnCode == NSObjectFileImageInappropriateFile) + { + NSDestroyObjectFileImage(fileImage); + /* Could be dynamic library rather than a bundle */ + handle = cast(NSModule) NSAddImage(filename, + NSADDIMAGE_OPTION_RETURN_ON_ERROR); + } + else + { + // printf("Failed: %d\n", returnCode); + s_lastError = "NSCreateObjectFileImageFromFile failed"; + return null; + } + + if (handle == null) + { + record_error_(); + + return null; + } + else + { + ExeModuleInfo mi = new ExeModuleInfo(handle, moduleName); + + s_modules[moduleName] = mi; + + return cast(HXModule)mi; + } + } + } + + private HXModule ExeModule_AddRef_(in HXModule hModule) + in + { + assert(null !== hModule); + + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + assert(0 < mi.m_cRefs); + assert(null !== mi.m_hmod); + assert(null !== mi.m_name); + assert(null !== s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); + } + body + { + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + if(null !== mi) + { + return (++mi.m_cRefs, hModule); + } + else + { + return null; + } + } + + private void ExeModule_Release_(inout HXModule hModule) + in + { + assert(null !== hModule); + + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + assert(0 < mi.m_cRefs); + assert(null !== mi.m_hmod); + assert(null !== mi.m_name); + assert(null !== s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); + } + body + { + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + if(0 == --mi.m_cRefs) + { + char[] name = mi.m_name; + uint magic; + + magic = (* cast(mach_header *) mi.m_hmod).magic; + if ( magic == MH_MAGIC || magic == MH_CIGAM ) + { + // Can not unlink dynamic libraries on Darwin + } + else if (NSUnLinkModule(mi.m_hmod, 0) == FALSE) + { + // printf("DEBUG: Could not unlink module %.*s\n", name); + } + delete s_modules[name]; + delete mi; + } + + hModule = null; + } + + private void *ExeModule_GetSymbol_(inout HXModule hModule, in char[] symbolName) + in + { + assert(null !== hModule); + + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + assert(0 < mi.m_cRefs); + assert(null !== mi.m_hmod); + assert(null !== mi.m_name); + assert(null !== s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); + } + body + { + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + NSModule handle = mi.m_hmod; + uint magic = (* cast(mach_header *) handle).magic; + char *name = "_" ~ symbolName ~ "\0"; + NSSymbol symbol = null; + + if ( (handle == cast(NSModule) -1) && + NSIsSymbolNameDefined(name)) + /* Global context, use NSLookupAndBindSymbol */ + symbol = NSLookupAndBindSymbol(name); + else if ( ( magic == MH_MAGIC || magic == MH_CIGAM ) && + NSIsSymbolNameDefinedInImage(cast(mach_header *) handle, name)) + symbol = NSLookupSymbolInImage(cast(mach_header *) handle, name, + NSLOOKUPSYMBOLINIMAGE_OPTION_BIND | + NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); + else + symbol = NSLookupSymbolInModule(handle, name); + + if (symbol == null) + { + // printf("DEBUG: Symbol not found: %s\n", name); + return null; + } + + void *address = NSAddressOfSymbol(symbol); + + if(address == null) + { + record_error_(); + } + + return address; + } + + private char[] ExeModule_Error_() + { + return s_lastError; + } + + private char[] ExeModule_GetPath_(HXModule hModule) + in + { + assert(null !== hModule); + + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + assert(0 < mi.m_cRefs); + assert(null !== mi.m_hmod); + assert(null !== mi.m_name); + assert(null !== s_modules[mi.m_name]); + assert(mi is s_modules[mi.m_name]); + } + body + { + ExeModuleInfo mi = cast(ExeModuleInfo)hModule; + + return mi.m_name; + } +} else { const int platform_not_discriminated = 0; @@ -528,6 +884,10 @@ { m_hModule = ExeModule_AddRef(hModule); } + else version (darwin) + { + m_hModule = ExeModule_AddRef(hModule); + } else static assert(0); } @@ -552,6 +912,12 @@ if (null is m_hModule) throw new ExeModuleException(ExeModule_Error()); } + else version (darwin) + { + m_hModule = ExeModule_Load(moduleName); + if (null is m_hModule) + throw new ExeModuleException(ExeModule_Error()); + } else { static assert(0); // unsupported system @@ -583,6 +949,10 @@ { ExeModule_Release(m_hModule); } + else version (darwin) + { + ExeModule_Release(m_hModule); + } else static assert(0); } @@ -616,6 +986,15 @@ throw new ExeModuleException(ExeModule_Error()); } } + else version (darwin) + { + void *symbol = ExeModule_GetSymbol(m_hModule, symbolName); + + if(null is symbol) + { + throw new ExeModuleException(ExeModule_Error()); + } + } else { static assert(0); @@ -667,6 +1046,10 @@ { return ExeModule_GetPath_(m_hModule); } + else version (darwin) + { + return ExeModule_GetPath_(m_hModule); + } else static assert(0); } diff -uNr gdc-1g/d/phobos/std/process.d gdc-0.8/d/phobos/std/process.d --- gdc-1g/d/phobos/std/process.d 2004-09-21 01:02:31.000000000 +0200 +++ gdc-0.8/d/phobos/std/process.d 2004-10-18 05:27:20.000000000 +0200 @@ -21,6 +21,12 @@ * distribution. */ +/* NOTE: This file has been patched from the original DMD distribution to + work with the GDC compiler. + + Modified by David Friedman, October 2004 +*/ + module std.process; @@ -68,13 +74,20 @@ return std.c.process.execvp(toStringz(pathname), argv_); } -int execvpe(char[] pathname, char[][] argv, char[][] envp) +version (GNU_Need_execvpe) { - char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); - char** envp_ = cast(char**)alloca((char*).sizeof * (1 + envp.length)); - toAStringz(argv, argv_); - toAStringz(envp, envp_); - return std.c.process.execvpe(toStringz(pathname), argv_, envp_); + // TODO: Write this. +} +else +{ + int execvpe(char[] pathname, char[][] argv, char[][] envp) + { + char** argv_ = cast(char**)alloca((char*).sizeof * (1 + argv.length)); + char** envp_ = cast(char**)alloca((char*).sizeof * (1 + envp.length)); + toAStringz(argv, argv_); + toAStringz(envp, envp_); + return std.c.process.execvpe(toStringz(pathname), argv_, envp_); + } } /* ////////////////////////////////////////////////////////////////////////// */ diff -uNr gdc-1g/d/phobos/std/stdio.d gdc-0.8/d/phobos/std/stdio.d --- gdc-1g/d/phobos/std/stdio.d 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/phobos/std/stdio.d 2004-10-18 05:27:20.000000000 +0200 @@ -16,11 +16,11 @@ private import std.format; private import std.utf; -// GNU argptr is inoutva_list instead of private void writex(FILE* fp, TypeInfo[] arguments, std.c.stdio.va_list argptr, int newline) { int orientation; - orientation = fwide(fp, 0); + version(GNU_Have_fwide) + orientation = fwide(fp, 0); if (orientation <= 0) // byte orientation or no orientation { void putc(dchar c) @@ -45,40 +45,43 @@ } else if (orientation > 0) // wide orientation { - version (Windows) + version(GNU_Have_fwide) { - void putcw(dchar c) + version (Windows) { - assert(isValidDchar(c)); - if (c <= 0xFFFF) + void putcw(dchar c) { - std.c.stdio.fputwc(c, fp); + assert(isValidDchar(c)); + if (c <= 0xFFFF) + { + std.c.stdio.fputwc(c, fp); + } + else + { wchar[2] buf; + + buf[0] = (((c - 0x10000) >> 10) & 0x3FF) + 0xD800; + buf[1] = ((c - 0x10000) & 0x3FF) + 0xDC00; + std.c.stdio.fputwc(buf[0], fp); + std.c.stdio.fputwc(buf[1], fp); + } } - else - { wchar[2] buf; - - buf[0] = (((c - 0x10000) >> 10) & 0x3FF) + 0xD800; - buf[1] = ((c - 0x10000) & 0x3FF) + 0xDC00; - std.c.stdio.fputwc(buf[0], fp); - std.c.stdio.fputwc(buf[1], fp); + } + else version (Unix) + { + void putcw(dchar c) + { + std.c.stdio.fputwc(c, fp); } } - } - else version (Unix) - { - void putcw(dchar c) + else { - std.c.stdio.fputwc(c, fp); + static assert(0); } - } - else - { - static assert(0); - } - std.format.doFormat(&putcw, arguments, argptr); - if (newline) - std.c.stdio.fputwc('\n', fp); + std.format.doFormat(&putcw, arguments, argptr); + if (newline) + std.c.stdio.fputwc('\n', fp); + } } } diff -uNr gdc-1g/d/phobos/std/string.d gdc-0.8/d/phobos/std/string.d --- gdc-1g/d/phobos/std/string.d 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/phobos/std/string.d 2004-10-14 02:28:08.000000000 +0200 @@ -39,22 +39,40 @@ extern (C) { // Functions from the C library. - int strlen(char *); - int strcmp(char *, char *); - char* strcat(char *, char *); - int memcmp(void *, void *, uint); + version (GNU) // should be: GNU_Use_Builtins / -f[no-]builtins + { + private import gcc.builtins; + alias __builtin_strlen strlen; + alias __builtin_strcmp strcmp; + alias __builtin_strcat strcat; + alias __builtin_memcmp memcmp; + alias __builtin_strcpy strcpy; + alias __builtin_strstr strstr; + alias __builtin_strchr strchr; + alias __builtin_strrchr strrchr; + alias __builtin_memcpy memcpy; + //alias __builtin_memmove memmove;// not in 3.3 + alias __builtin_memset memset; + } + else + { + int strlen(char *); + int strcmp(char *, char *); + char* strcat(char *, char *); + int memcmp(void *, void *, uint); + char *strcpy(char *, char *); + char *strstr(char *, char *); + char *strchr(char *, char); + char *strrchr(char *, char); + void *memcpy(void *, void *, uint); + void *memset(void *, uint, uint); + } + void *memmove(void *, void *, uint); int memicmp(char *, char *, uint); - char *strcpy(char *, char *); int atoi(char *); long atoll(char *); double atof(char *); - char *strstr(char *, char *); - char *strchr(char *, char); - char *strrchr(char *, char); char *memchr(char *, char, uint); - void *memcpy(void *, void *, uint); - void *memmove(void *, void *, uint); - void *memset(void *, uint, uint); int wcslen(wchar *); int wcscmp(wchar *, wchar *); diff -uNr gdc-1g/d/phobos/std/thread.d gdc-0.8/d/phobos/std/thread.d --- gdc-1g/d/phobos/std/thread.d 2004-10-02 19:19:32.000000000 +0200 +++ gdc-0.8/d/phobos/std/thread.d 2004-10-10 18:50:42.000000000 +0200 @@ -628,12 +628,12 @@ else npause++; // count of paused threads } - - // Wait for each paused thread to acknowledge - while (npause--) - { - flagSuspend.wait(); - } + } + + // Wait for each paused thread to acknowledge + while (npause--) + { + flagSuspend.wait(); } } } @@ -1112,12 +1112,12 @@ else npause++; // count of paused threads } + } - // Wait for each paused thread to acknowledge - while (npause--) - { - sem_wait(&flagSuspend); - } + // Wait for each paused thread to acknowledge + while (npause--) + { + sem_wait(&flagSuspend); } } } diff -uNr gdc-1g/d/README gdc-0.8/d/README --- gdc-1g/d/README 2004-10-04 01:44:56.000000000 +0200 +++ gdc-0.8/d/README 2004-10-25 01:05:45.000000000 +0200 @@ -9,11 +9,15 @@ * FreeBSD 5.2.1 * Cygwin -Similar versions should work and other Unix platforms may work. Although the compiler will probably work on most 32-bit architectures, the D runtime library will still need to be updated to support them. +Similar versions should work and other Unix platforms may work. Although +the compiler will probably work on most 32-bit architectures, the D runtime +library will still need to be updated to support them. + Downloads - * Main package (Release 1g) - http://home.earthlink.net/~dvdfrdmn/d/gdc-1g.tgz + * Main package (Release 0.8) + http://home.earthlink.net/~dvdfrdmn/d/gdc-0.8.tgz + http://home.earthlink.net/~dvdfrdmn/d/gdc-0.8.tar.bz2 * Build Instructions http://home.earthlink.net/~dvdfrdmn/d/INSTALL.html (or see INSTALL included in the main package) @@ -40,23 +44,41 @@ Gray Area / Known Issues - * Debugging information isn't working completely. In any case, GDB does not support D name mangling. - * Templates on Mac OS X. The stock compiler doesn't support one-only linkage. Apple's version does support it, but this release will not work with that. The current solution is to make template instantiations private to each module that uses them. This should work as long as the template does not have non-constant static data. If you need more control over how emplates are emitted, use the -femit-templates flag (see below). Note that you don't have to worry about the stdarg templates as they are handled magically. + * Debugging information may have a few problems. In any case, GDB does + not support D name mangling. + * Templates on Mac OS X. The stock compiler doesn't support one-only + linkage. Apple's version does support it, but this release will not + work with that. The current solution is to make template + instantiations private to each module that uses them. This should + work as long as the template does not have non-constant static data. + If you need more control over how emplates are emitted, use the + -femit-templates flag (see below). Note that you don't have to worry + about the stdarg templates as they are handled magically. * Complex floating point operations may not work the same as DMD. - * The 80-bit real type is not supported on Mac OS X and is replaced by the 64-bit double type. - * Some math functions behave differently due to the 80-bit real issue and not being able to access x86 floating-point hardware. Some std.math unit tests will fail because of this. - * In order to prevent nested synchronized statements from deadlocking, pthread recursive mutexes are used. This can cause starvation problems on Linux. I will try the "error-checking" type mutex. + * The 80-bit real type is not supported on Mac OS X and is replaced by + the 64-bit double type. + * Some math functions behave differently due to the 80-bit real issue + and not being able to access x86 floating-point hardware. Some + std.math unit tests will fail because of this. + * In order to prevent nested synchronized statements from deadlocking, + pthread recursive mutexes are used. This can cause starvation + problems on Linux. I will try the "error-checking" type mutex. * Volatile statements probably don't do the right thing. - * Thrown exceptions probably leak memory. - * Delegates that refer to nested functions are not valid after the parent function returns. + * Delegates that refer to nested functions are not valid after the + parent function returns. Known Differences from DMD * Private functions are not exported from the object file. - * The type of _argptr in variadic functions is the target-specific va_list type. It is not portable to assume this is a pointer. The only portable way to use _argptr is the std.stdarg.va_arg template. + * The type of _argptr in variadic functions is the target-specific + va_list type. It is not portable to assume this is a pointer. The + only portable way to use _argptr is the std.stdarg.va_arg template. Usage -The compiler driver is named 'gdc' and accepts the standard GCC options. There is also a script named 'dmd' which has the same interface as the original dmd. + +The compiler driver is named 'gdc' and accepts the standard GCC +options. There is also a script named 'dmd' which has the same interface +as the original dmd. The mapping from DMD options to GCC is as follows: -c @@ -95,16 +117,40 @@ Controls whether or not template code is emitted. "full" 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. +"private" -- Emit templates, but make them private to the translation unit. + The executable will have multiple copies of code and data. "none" Do not emit templates at all. -"auto" -- For targets that support templates, the "full" mode is used. Otherwise, the "private" mode is used. +"auto" -- For targets that support templates, the "full" mode is used. + Otherwise, the "private" mode is used. "none" and -fno-emit-templates are synonyms. "full" and -femit-templates are synonyms. -fall-sources - For each source file on the command line, semantically process each file preceding it. Use this if compilation errors occur due to complicated circular module references. This will slow compilation noticeably. + For each source file on the command line, semantically process each + file preceding it. Use this if compilation errors occur due to + complicated circular module references. This will slow compilation + noticeably. Changes +0.8: + * Fixes + o std.loader module is now enabled + o Proper casting from complex and imaginary types + o Diagnostics are now GCC-style + o Exceptions don't leak memory anymore + o The gdc command processes ".html" as D source files. + o ICE for classes declared in a function + o ICE on empty "if" statement + o Test for existence of "execvpe", "fwide", and "fputwc" before + using them + o Corrected floating point "min_10_exp" properties + o std.date.getLocalTZA returns a correct values + * Improvements + o Debugging information is vastly improved + o DLLs can be built on Cygwin + * Notes + o "DigitalMars" is not longer defined as a version symbol + 1g: * Fixes @@ -112,7 +158,6 @@ o Report more errors and warning with correct line numbers o Registers are now put on the stack for garbage collection o Signed/unsigned expression semantics should match DMD now - o * Improvements o Update to DMD 0.102 @@ -121,12 +166,15 @@ 1f: * Fixes - o Compilation and linking problems when overriding some, but not all interface methods + o Compilation and linking problems when overriding some, but not + all interface methods o Support all comparison operators for arrays - o Static initializers for structs with anonymous unions of anonymous structs + o Static initializers for structs with anonymous unions of + anonymous structs o Continue in foreach statements o Increment key in foreach statements - o ICE when storing to bit variables and for some boolean expression (for GCC 3.3) + o ICE when storing to bit variables and for some boolean + expression (for GCC 3.3) o Critical sections without an object o Semantics of casting to/from void[] o Problems with unaligned bit slices @@ -135,20 +183,14 @@ o Build problems due to missing long double support on the host system. * Improvements o Update to DMD 0.82 - o Use parts of the Boehm garbage collector to determine the stack and data extents. This does not change the behavior of the D garbage collector. - o Support semantic processing of all source files on the command line before generating code. + o Use parts of the Boehm garbage collector to determine the stack + and data extents. This does not change the behavior of the D + garbage collector. + o Support semantic processing of all source files on the command + line before generating code. o Added the 'dmd' wrapper script. - o Automatically generate support for the target Unix, math, and C library configuration. - -1e: - - * Removed debug code from std.thread - * Auto-generate Unix definitions - * Intrinsics implemented in D code - * Correct iteration bounds for foreach on a static array - * Fix ICE when using an assignment expressions as a boolean value - * Fix ICE for new - + o Automatically generate support for the target Unix, math, and C + library configuration. 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 diff -uNr gdc-1g/d/root/aggregate.h gdc-0.8/d/root/aggregate.h --- gdc-1g/d/root/aggregate.h 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/root/aggregate.h 2004-10-15 01:21:22.000000000 +0200 @@ -7,6 +7,12 @@ // 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, October 2004 +*/ + #ifndef DMD_AGGREGATE_H #define DMD_AGGREGATE_H @@ -46,6 +52,10 @@ InvariantDeclaration *inv; // invariant NewDeclaration *aggNew; // allocator DeleteDeclaration *aggDelete; // deallocator +#ifdef IN_GCC + + Array methods; // flat list of all methods for debug information +#endif AggregateDeclaration(Loc loc, Identifier *id); diff -uNr gdc-1g/d/root/constfold.c gdc-0.8/d/root/constfold.c --- gdc-1g/d/root/constfold.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/root/constfold.c 2004-10-10 18:50:41.000000000 +0200 @@ -127,7 +127,11 @@ } if (type->isintegral()) - return new IntegerExp(loc, e1->toInteger(), type); + { + IntegerExp * e = new IntegerExp(loc, e1->toInteger(), type); + e->toInteger(); + return e; + } if (type->isreal()) return new RealExp(loc, e1->toReal(), type); if (type->isimaginary()) diff -uNr gdc-1g/d/root/expression.c gdc-0.8/d/root/expression.c --- gdc-1g/d/root/expression.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/root/expression.c 2004-10-18 05:27:20.000000000 +0200 @@ -638,7 +638,7 @@ { switch (t->ty) { - case Tbit: value &= 1; break; + case Tbit: value = value != 0; break; case Tint8: value = (d_int8) value; break; case Tchar: case Tuns8: value = (d_uns8) value; break; @@ -862,7 +862,7 @@ complex_t ImaginaryExp::toComplex() { - return value; + return complex_t(0, value); } Expression *ImaginaryExp::semantic(Scope *sc) diff -uNr gdc-1g/d/root/func.c gdc-0.8/d/root/func.c --- gdc-1g/d/root/func.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/root/func.c 2004-10-15 01:21:22.000000000 +0200 @@ -130,6 +130,13 @@ } #endif +#ifdef IN_GCC + AggregateDeclaration *ad; + + ad = parent->isAggregateDeclaration(); + if (ad) + ad->methods.push(this); +#endif sd = parent->isStructDeclaration(); if (sd) { diff -uNr gdc-1g/d/root/html.c gdc-0.8/d/root/html.c --- gdc-1g/d/root/html.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/root/html.c 2004-10-23 22:44:51.000000000 +0200 @@ -33,7 +33,7 @@ inline int istagstart(int c) { - return (isalpha(c) || c == '_'); + return (isalpha(c) || c == '_' || c == '!'); } inline int istag(int c) @@ -61,7 +61,7 @@ void Html::error(const char *format, ...) { - printf("%s(%d) : HTML Error: ", sourcename, linnum); + printf("%s:%d: HTML Error: ", sourcename, linnum); va_list ap; va_start(ap, format); @@ -525,6 +525,7 @@ "not", 172, "shy", 173, "reg", 174, + NULL, 0 // BUG: This is only a partial list. // For the rest, consult: @@ -536,7 +537,7 @@ int i; // BUG: this is a dumb, slow linear search - for (i = 0; i < sizeof(names) / sizeof(names[0]); i++) + for (i = 0; names[i].name; i++) { // Do case insensitive compare if (memicmp(names[i].name, (char *)p, length) == 0) diff -uNr gdc-1g/d/root/root.c gdc-0.8/d/root/root.c --- gdc-1g/d/root/root.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/root/root.c 2004-10-08 03:26:57.000000000 +0200 @@ -1720,7 +1720,7 @@ // Clear other bits in last word mask = (1 << (bitdim & 31)) - 1; if (mask) - data[allocdim - 1] &= ~mask; + data[allocdim - 1] &= mask; } void Bits::clear() diff -uNr gdc-1g/d/root/todt.c gdc-0.8/d/root/todt.c --- gdc-1g/d/root/todt.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/root/todt.c 2004-10-25 00:28:38.000000000 +0200 @@ -115,6 +115,23 @@ { d = v->init->toDt(); } + else if (v->offset >= offset) + { + unsigned k; + unsigned offset2 = v->offset + v->type->size(); + // Make sure this field does not overlap any explicitly + // initialized field. + for (k = j + 1; k < dts.dim; k++) + { + VarDeclaration *v2 = (VarDeclaration *)ad->fields.data[k]; + + if (v2->offset < offset2 && dts.data[k]) { + break; + } + } + if (k == dts.dim) + v->type->toDt(& d); + } } if (d) { @@ -183,7 +200,7 @@ if (dt) pdtend = dtcat(pdtend, dt); else - pdtend = dtnzeros(pdtend, size); + pdtend = tn->toDt(pdtend); } switch (tb->ty) { @@ -232,8 +249,22 @@ Bits databits; Bits initbits; - databits.resize(dim); - initbits.resize(dim); + if (tb->ty == Tsarray) + { + /* Need to resize to the size of the static array, otherwise set() will + affect bits beyond the last specified element. */ + unsigned sdim = ((TypeSArray*)tb)->dim->toInteger(); // missing overflow check + databits.resize(sdim); + initbits.resize(sdim); + } + else + { + databits.resize(dim); + initbits.resize(dim); + } + + if (tb->next->defaultInit()->toInteger()) + databits.set(); size = sizeof(databits.data[0]); @@ -255,7 +286,7 @@ if (initbits.test(length)) error("duplicate initializations for index %d", length); initbits.set(length); - if (bitval & 1) + if (bitval != 0) databits.set(length); else databits.clear(length); @@ -675,17 +706,33 @@ { while (*pdt) pdt = &((*pdt)->DTnext); - next->toDt(pdt); - if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext) + if (next->toBasetype()->ty != Tbit) { - (*pdt)->DTazeros *= len; + next->toDt(pdt); + if ((*pdt)->dt == DT_azeros && !(*pdt)->DTnext) + { + (*pdt)->DTazeros *= len; + } + else + { + for (i = 1; i < len; i++) + { + pdt = next->toDt(pdt); + } + } } else { - for (i = 1; i < len; i++) - { - pdt = next->toDt(pdt); - } + Bits databits; + + databits.resize(len); + if (next->defaultInit()->toInteger()) + databits.set(); +#ifdef IN_GCC + pdt = dtnbits(pdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data, sizeof(databits.data[0])); +#else + pdt = dtnbytes(pdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data); +#endif } } return pdt; diff -uNr gdc-1g/d/root/toobj.c gdc-0.8/d/root/toobj.c --- gdc-1g/d/root/toobj.c 2004-10-02 19:19:31.000000000 +0200 +++ gdc-0.8/d/root/toobj.c 2004-10-08 03:26:57.000000000 +0200 @@ -816,10 +816,27 @@ dim = ((TypeSArray *)tb)->dim->toInteger(); - // Duplicate Sdt 'dim-1' times, as we already have the first one - while (--dim > 0) + if (tb->next->toBasetype()->ty != Tbit) { - ie->exp->toDt(&s->Sdt); + // Duplicate Sdt 'dim-1' times, as we already have the first one + while (--dim > 0) + { + ie->exp->toDt(&s->Sdt); + } + } + else + { + Bits databits; + + databits.resize(dim); + if (ie->exp->toInteger()) + databits.set(); + s->Sdt = NULL; +#ifdef IN_GCC + dtnbits(& s->Sdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data, sizeof(databits.data[0])); +#else + dtnbytes(& s->Sdt, databits.allocdim * sizeof(databits.data[0]), (char *)databits.data); +#endif } } } diff -uNr gdc-1g/d/symbol.cc gdc-0.8/d/symbol.cc --- gdc-1g/d/symbol.cc 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.8/d/symbol.cc 2004-10-11 02:13:55.000000000 +0200 @@ -0,0 +1,91 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + 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 +*/ + +#include "symbol.h" +#include "mem.h" + +Symbol::Symbol() +{ + Sident = 0; + Stype = 0; + Sclass = SC_INVALID; + Sfl = FL_INVALID; + Sflags = 0; + + Ssymnum = 0; + Sdt = 0; + + Sstruct = 0; + Sstructalign = 0; + + Stree = 0; // %% make it NULL-TREE, include d-gcc-include + ScontextDecl = 0; + memset(& Sspecial, 0, sizeof(Sspecial)); +} + +// %% fwiw, need to dup the string because sometimes the +// string is alloca()'d +Symbol * +symbol_calloc(const char * string) +{ + Symbol * s = new Symbol; + s->Sident = mem.strdup(string); + return s; +} + +Symbol * +symbol_name(const char * id, int /*sclass*/, TYPE * /*t*/) +{ + // %% Nothing special, just do the same as symbol_calloc + // we don't even bother using sclass and t + + return symbol_calloc(id); +} + +Symbol * +struct_calloc() +{ + return new Symbol; +} + +Symbol * +symbol_generate(SymbolStorageClass /*sc*/, TYPE * /*type*/) +{ + return 0; +} + +Thunk::Thunk() +{ + offset = 0; + symbol = 0; +} + +void +symbol_func(Symbol * /*sym*/) +{ + +} + + +Symbol * +symbol_tree(tree t) +{ + Symbol * s = new Symbol; + s->Stree = t; + return s; +} diff -uNr gdc-1g/d/symbol.h gdc-0.8/d/symbol.h --- gdc-1g/d/symbol.h 1970-01-01 01:00:00.000000000 +0100 +++ gdc-0.8/d/symbol.h 2004-10-14 02:28:08.000000000 +0200 @@ -0,0 +1,177 @@ +/* GDC -- D front-end for GCC + Copyright (C) 2004 David Friedman + + 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 +*/ + +#ifndef DMD_SYMBOL_H +#define DMD_SYMBOL_H + +#include "root.h" + +#include "d-gcc-tree.h" + +#include "mtype.h" + +enum mangle_t +{ + mTY_INVALID, + mTYman_c, + mTYman_cpp, + mTYman_std, + mTYman_pas, + mTYman_d +}; + +enum TypeType +{ + // no clue about which can be used together.. + TYnptr = 0x001, + TYnfunc = 0x010, + TYjfunc = 0x020, + TYstruct = 0x040, + TYarray = 0x080, + TYbit = 0x100, + TYint = 0x200, + mTYconst = 0x1000, + mTYvolatile = 0x2000 +}; + +typedef int tym_t; + +enum TypeFlag +{ + TFsizeunknown = 0x01, + TFforward = 0x02, + TFprototype = 0x04, + TFfixed = 0x08 +}; + +/* +struct TYPE : Object +{ + tym_t Tty; + mangle_t Tmangle; + TYPE * Tnext; + int Tcount; + int Tflags; + void * Ttag; + void * Tparamtypes; + tree Ttree; + + TYPE(); +}; + +extern TYPE * tsvoid; + +extern TYPE * type_alloc(tym_t ty); // ty: combination of TypeType values +extern TYPE * type_fake(tym_t ty); +extern void type_setcv(TYPE ** pp_type, int ty); +extern void type_setmangle(TYPE ** pp_type, mangle_t mangle); +extern int/ *?* / type_paramsize(TYPE * t); +*/ + +enum SymbolStorageClass +{ + SC_INVALID, + SCextern, + SCstatic, + SCauto, + SCglobal, + SCstruct, + SCcomdat +}; + +typedef enum SymbolStorageClass enum_SC; + +enum SymbolFL +{ + FL_INVALID, + FLextern = 0x01, + FLauto = 0x02, + FLdata = 0x04, + + // GDC specific. This flag indicates an anonymous chunk of data that + // does not need a name or a VER_DECL. + FLstatic_sym = 0x100 +}; + +enum SymbolFlag +{ + SFLimplem = 0x01, + SFLnodebug = 0x02, + STRglobal = 0x04 +}; + +enum SymbolSegment +{ + DATA, + CDATA, + UDATA +}; + +// not sure if this needs to inherit object.. +// union tree_node; typedef union tree_node dt_t; +struct dt_t; + +struct Symbol : Object +{ + Symbol(); + // !!! need a dtor for Sident.. + + char *Sident; + TYPE *Stype; // maybe type/TYPE ? + SymbolStorageClass Sclass; + SymbolFL Sfl; + SymbolSegment Sseg; + int Sflags; + + int Ssymnum; + + dt_t * Sdt; + + // fake classsym.... + Symbol * Sstruct; + int Sstructalign; + + // Specific to GNU backend + tree Stree; + tree ScontextDecl; // The DECL_CONTEXT to use for child declarations, but see IRState::declContext + union { + AggregateDeclaration * aggDecl; // AggregateDeclaration.sinit set in AggregateDeclaration::toInitializer + Array * thunks; // of struct Thunk; for FuncDeclarations + } Sspecial; +}; + +struct Thunk +{ + int offset; + Symbol * symbol; + Thunk(); +}; + +typedef struct Symbol Classsym; + +extern Symbol * symbol_calloc(const char * string); +extern Symbol * symbol_name(const char * id, int sclass, TYPE * t); +extern Symbol * struct_calloc(); +extern Symbol * symbol_generate(SymbolStorageClass sc, TYPE * type); +extern void symbol_func(Symbol * sym); +extern void outdata(Symbol * sym); +inline void obj_export(Symbol *, int) { } +inline void obj_moduleinfo(Symbol *sym) { } + +extern Symbol * symbol_tree(tree); +#endif