namespace EffectiveCPP {

    StatementMatcher ctorCallVtlMatcherEC = compoundStmt(
            hasParent(constructorDecl().bind("cDecl")),
            hasDescendant(callExpr(callee(methodDecl(isVirtual()))))
            );
    
    StatementMatcher dtorCallVtlMatcherEC = compoundStmt(
            hasParent(destructorDecl().bind("dDecl")),
            hasDescendant(callExpr(callee(methodDecl(isVirtual()))))
            );
}
void JitInstanceMemberFunction::setClosures()
{
    if(isVirtual())
    {
        m_pSubroutine->setClosure(jit_function_to_closure((jit_function_t)m_jit_virtual_indirection_function.function));
        Class* pClass = getInstanceMemberFunction()->getOwnerClass();
        for(auto it = pClass->beginVirtualMemberFunctionTables(); it != pClass->endVirtualMemberFunctionTables(); ++it)
        {
            size_t uiOffset = (*it)->getOffset();
            auto it = m_ThisAdjustmentThunks.find(uiOffset);
            if(it == m_ThisAdjustmentThunks.end())
            {
                // No thunk needed, use directly the function as the vtable pointer
                getInstanceMemberFunction()->setVTableClosure(uiOffset, jit_function_to_vtable_pointer((jit_function_t)m_jit_function.function));
            }
            else 
            {
                // Thunk needed
                getInstanceMemberFunction()->setVTableClosure(uiOffset, jit_function_to_vtable_pointer((jit_function_t)it->second.function));
            }
        }
    }
    else
    {
        m_pSubroutine->setClosure(jit_function_to_closure((jit_function_t)m_jit_function.function));
    }
}
Пример #3
0
bool TrackNode::toGPX(QXmlStreamWriter& stream, QProgressDialog * progress, QString element, bool forExport)
{
    bool OK = true;

    if (isVirtual())
        return OK;

    if (!tagValue("_waypoint_","").isEmpty() ||!sizeParents())
        stream.writeStartElement("wpt");
    else
        stream.writeStartElement(element);

    if (!forExport)
        stream.writeAttribute("xml:id", xmlId());
    stream.writeAttribute("lon",COORD2STRING(BBox.topRight().x()));
    stream.writeAttribute("lat", COORD2STRING(BBox.topRight().y()));

    stream.writeTextElement("time", time().toString(Qt::ISODate)+"Z");

    QString s = tagValue("name","");
    if (!s.isEmpty()) {
        stream.writeTextElement("name", s);
    }
    if (elevation()) {
        stream.writeTextElement("ele", QString::number(elevation(),'f',6));
    }
    if (speed()) {
        stream.writeTextElement("speed", QString::number(speed(),'f',6));
    }
    s = tagValue("_comment_","");
    if (!s.isEmpty()) {
        stream.writeTextElement("cmt", s);
    }
    s = tagValue("_description_","");
    if (!s.isEmpty()) {
        stream.writeTextElement("desc", s);
    }

    // OpenStreetBug
    s = tagValue("_special_","");
    if (!s.isEmpty() && id().type & IFeature::Special) {
        stream.writeStartElement("extensions");
        QString sid = stripToOSMId(id());
        stream.writeTextElement("id", sid);
        stream.writeEndElement();
    }
    stream.writeEndElement();

    if (progress)
        progress->setValue(progress->value()+1);

    return OK;
}
void ParentVirtualCallCheck::registerMatchers(MatchFinder *Finder) {
  Finder->addMatcher(
      cxxMemberCallExpr(
          callee(memberExpr(hasDescendant(implicitCastExpr(
                                hasImplicitDestinationType(pointsTo(
                                    type(anything()).bind("castToType"))),
                                hasSourceExpression(cxxThisExpr(hasType(
                                    type(anything()).bind("thisType")))))))
                     .bind("member")),
          callee(cxxMethodDecl(isVirtual()))),
      this);
}
phantom::generic_member_func_ptr JitInstanceMemberFunction::getGenericMemberFunctionPointer() const
{
    generic_member_func_ptr ptr;
    if(isVirtual())
    {
        ptr.setClosurePointer(jit_function_to_closure((jit_function_t)m_jit_virtual_indirection_function.function));
    }
    else
    {
        ptr.setClosurePointer(jit_function_to_closure((jit_function_t)m_jit_function.function));
    }
    return ptr;
}
void UnconventionalAssignOperatorCheck::registerMatchers(
    ast_matchers::MatchFinder *Finder) {
  // Only register the matchers for C++; the functionality currently does not
  // provide any benefit to other languages, despite being benign.
  if (!getLangOpts().CPlusPlus)
    return;

  const auto HasGoodReturnType = cxxMethodDecl(returns(lValueReferenceType(
      pointee(unless(isConstQualified()),
              anyOf(autoType(), hasDeclaration(equalsBoundNode("class")))))));

  const auto IsSelf = qualType(
      anyOf(hasDeclaration(equalsBoundNode("class")),
            referenceType(pointee(hasDeclaration(equalsBoundNode("class"))))));
  const auto IsAssign =
      cxxMethodDecl(unless(anyOf(isDeleted(), isPrivate(), isImplicit())),
                    hasName("operator="), ofClass(recordDecl().bind("class")))
          .bind("method");
  const auto IsSelfAssign =
      cxxMethodDecl(IsAssign, hasParameter(0, parmVarDecl(hasType(IsSelf))))
          .bind("method");

  Finder->addMatcher(
      cxxMethodDecl(IsAssign, unless(HasGoodReturnType)).bind("ReturnType"),
      this);

  const auto BadSelf = referenceType(
      anyOf(lValueReferenceType(pointee(unless(isConstQualified()))),
            rValueReferenceType(pointee(isConstQualified()))));

  Finder->addMatcher(
      cxxMethodDecl(IsSelfAssign,
                    hasParameter(0, parmVarDecl(hasType(BadSelf))))
          .bind("ArgumentType"),
      this);

  Finder->addMatcher(
      cxxMethodDecl(IsSelfAssign, anyOf(isConst(), isVirtual())).bind("cv"),
      this);

  const auto IsBadReturnStatement = returnStmt(unless(has(ignoringParenImpCasts(
      anyOf(unaryOperator(hasOperatorName("*"), hasUnaryOperand(cxxThisExpr())),
            cxxOperatorCallExpr(argumentCountIs(1),
                                callee(unresolvedLookupExpr()),
                                hasArgument(0, cxxThisExpr())))))));
  const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType);

  Finder->addMatcher(returnStmt(IsBadReturnStatement, forFunction(IsGoodAssign))
                         .bind("returnStmt"),
                     this);
}
ostream&
BodyElementGroup::output_emf(ostream& out, short indent_size, short indent_level)
{
  char* QM = "\"";
  short is = indent_size;
  short il = indent_level;


  // Header: Element Group
  LibFront::output_scalar(out, is, il, EMF_ELEMENT_GROUP, NULL, tag);

  // Type (output only if virtual)
  if ( isVirtual() ) {
    LibFront::output_scalar(out, is, 1 + il, EMF_TYPE, NULL, "Virtual");
  }

  // Name
  LibFront::output_scalar(out, is, 1 + il, EMF_NAME, NULL, name);

  int count, i, nof_ids;
  int* bids;
  int* mids;
  int* gids;

  //--BodyElementGroup group type and element tags
  if ( nofElements > 0 ) {
    if ( elemType == OT_FACE ) {
      LibFront::output_vector(out, is, 1 + il, "Faces", NULL, nofElements, elementTags, false);
    } else if ( elemType == OT_EDGE ) {
      LibFront::output_vector(out, is, 1 + il, "Edges", NULL, nofElements, elementTags, false);
    } else if ( elemType == OT_VERTEX ) {
      LibFront::output_vector(out, is, 1 + il, "Vertices", NULL, nofElements, elementTags, false);
    } else {
      LibFront::output_vector(out, is, 1 + il, EMF_ELEMENTS, NULL, nofElements, elementTags, false);
    }

  }

  //--Boundary parameter id
  if ( boundaryParameterId != NO_INDEX ) {
    LibFront::output_scalar(out, is, 1 + il, EMF_BOUNDARY_PARAMETER, NULL, boundaryParameterId);
  }

  //--Boundary condition id
  if ( boundaryConditionId != NO_INDEX ) {
    LibFront::output_scalar(out, is, 1 + il, EMF_BOUNDARY_CONDITION, NULL, boundaryConditionId);
  }

  return out;
}
Пример #8
0
bool Node::toXML(QXmlStreamWriter& stream, QProgressDialog * progress, bool strict, QString changesetid)
{
    bool OK = true;

    if (isVirtual())
        return OK;

    stream.writeStartElement("node");

    Feature::toXML(stream, strict, changesetid);
    stream.writeAttribute("lon",COORD2STRING(BBox.topRight().x()));
    stream.writeAttribute("lat", COORD2STRING(BBox.topRight().y()));

    tagsToXML(stream, strict);
    stream.writeEndElement();

    if (progress)
        progress->setValue(progress->value()+1);

    return OK;
}
Пример #9
0
int FuncDeclaration::cvMember(unsigned char *p)
{
    int nwritten = 0;

    //printf("FuncDeclaration::cvMember() '%s'\n", toChars());

    if (!type)                  // if not compiled in,
        return 0;               // skip it

    char *id = toChars();

    if (!p)
    {
        nwritten = 2 + 2 + cgcv.sz_idx + cv_stringbytes(id);
        nwritten = cv_align(NULL, nwritten);
        return nwritten;
    }
    else
    {
        int count = 0;
        int mlen = 2;
        {
            if (introducing)
                mlen += 4;
            mlen += cgcv.sz_idx * 2;
            count++;
        }

        // Allocate and fill it in
        debtyp_t *d = debtyp_alloc(mlen);
        unsigned char *q = d->data;
        TOWORD(q,config.fulltypes == CV8 ? LF_METHODLIST_V2 : LF_METHODLIST);
        q += 2;
//      for (s = sf; s; s = s->Sfunc->Foversym)
        {
            unsigned attribute = PROTtoATTR(prot());

            /* 0*4 vanilla method
             * 1*4 virtual method
             * 2*4 static method
             * 3*4 friend method
             * 4*4 introducing virtual method
             * 5*4 pure virtual method
             * 6*4 pure introducing virtual method
             * 7*4 reserved
             */

            if (isStatic())
                attribute |= 2*4;
            else if (isVirtual())
            {
                if (introducing)
                {
                    if (isAbstract())
                        attribute |= 6*4;
                    else
                        attribute |= 4*4;
                }
                else
                {
                    if (isAbstract())
                        attribute |= 5*4;
                    else
                        attribute |= 1*4;
                }
            }
            else
                attribute |= 0*4;

            TOIDX(q,attribute);
            q += cgcv.sz_idx;
            TOIDX(q, cv4_memfunctypidx(this));
            q += cgcv.sz_idx;
            if (introducing)
            {   TOLONG(q, vtblIndex * Target::ptrsize);
                q += 4;
            }
        }
        assert(q - d->data == mlen);

        idx_t typidx = cv_debtyp(d);
        if (typidx)
        {
            switch (config.fulltypes)
            {
                case CV8:
                    TOWORD(p,LF_METHOD_V3);
                    goto Lmethod;
                case CV4:
                    TOWORD(p,LF_METHOD);
                Lmethod:
                    TOWORD(p + 2,count);
                    nwritten = 4;
                    TOIDX(p + nwritten, typidx);
                    nwritten += cgcv.sz_idx;
                    nwritten += cv_namestring(p + nwritten, id);
                    break;

                default:
                    assert(0);
            }
        }
        nwritten = cv_align(p + nwritten, nwritten);
#ifdef DEBUG
        assert(nwritten == cvMember(NULL));
#endif
    }
    return nwritten;
}
bool
BodyElementGroup::check()
{
  UserInterface* gui = (UserInterface*)model->getGui();
  strstream strm1, strm2;

  BodyElement* be = NULL;
  bool is_first_bndr = true;

  for (int i = 0; i < nofElements; i++) {

    int elem_tag = elementTags[i];

    switch (elemType) {
    case OT_VERTEX:
      be = model->getBodyElementByTag(OT_VERTEX, elem_tag);
      break;
    case OT_EDGE:
      be = model->getBodyElementByTag(OT_EDGE, elem_tag);
      break;
    case OT_FACE:
      be = model->getBodyElementByTag(OT_FACE, elem_tag);
      break;
    }

    if ( be != NULL ) {

      elementIds[i] = be->Id();

      // For non-virtual groups:
      // -set group info into member boundaries
      // -set parent body info
      // -check that elements are homogenous
      if ( !isVirtual() ) {

        be->setElementGroupTag(tag);
        be->setElementGroupId(id);

        // NOTE: Body info from the first element
        // (boundaries must be homogenous in this respect!)
        //
        if ( is_first_bndr ) {
          is_first_bndr = false;
          parent1Id = be->getParentId(1);
          parent2Id = be->getParentId(2);
          parent1Layer = be->getParentLayer(1);
          parent2Layer = be->getParentLayer(2);
          parent1Tag = be->getParentTag(1);
          parent2Tag = be->getParentTag(2);
        } else if ( parent1Id != be->getParentId(1) ||
                    parent2Id != be->getParentId(2)
                  ) {
            strm1 << "***ERROR in Edge Group " << tag << ends;
            strm2 << "---Edge " << be->Tag() << " is not similar to previous edges!" << ends;
            gui->showMsg(strm1.str());
            gui->showMsg(strm2.str());
            return false;
        }
      }

    // Error!
    } else {
      strm1 << "***ERROR in Edge Group " << tag << ends;
      strm2 << "---Cannot find edge " << elem_tag << ends;
      gui->showMsg(strm1.str());
      gui->showMsg(strm2.str());
      return false;
    }
  }

  return true;
}
Пример #11
0
void FuncDeclaration::toObjFile(bool multiobj)
{
    FuncDeclaration *func = this;
    ClassDeclaration *cd = func->parent->isClassDeclaration();
    int reverse;

    //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars());

    //if (type) printf("type = %s\n", func->type->toChars());
#if 0
    //printf("line = %d\n",func->getWhere() / LINEINC);
    EEcontext *ee = env->getEEcontext();
    if (ee->EEcompile == 2)
    {
        if (ee->EElinnum < (func->getWhere() / LINEINC) ||
            ee->EElinnum > (func->endwhere / LINEINC)
           )
            return;             // don't compile this function
        ee->EEfunc = toSymbol(func);
    }
#endif

    if (semanticRun >= PASSobj) // if toObjFile() already run
        return;

    if (type && type->ty == Tfunction && ((TypeFunction *)type)->next == NULL)
        return;

    // If errors occurred compiling it, such as bugzilla 6118
    if (type && type->ty == Tfunction && ((TypeFunction *)type)->next->ty == Terror)
        return;

    if (global.errors)
        return;

    if (!func->fbody)
        return;

    UnitTestDeclaration *ud = func->isUnitTestDeclaration();
    if (ud && !global.params.useUnitTests)
        return;

    if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration())
    {
        obj_append(this);
        return;
    }

    if (semanticRun == PASSsemanticdone)
    {
        /* What happened is this function failed semantic3() with errors,
         * but the errors were gagged.
         * Try to reproduce those errors, and then fail.
         */
        error("errors compiling the function");
        return;
    }
    assert(semanticRun == PASSsemantic3done);
    assert(ident != Id::empty);

    if (!needsCodegen())
        return;

    FuncDeclaration *fdp = func->toParent2()->isFuncDeclaration();
    if (isNested())
    {
        if (fdp && fdp->semanticRun < PASSobj)
        {
            if (fdp->semantic3Errors)
                return;

            /* Can't do unittest's out of order, they are order dependent in that their
             * execution is done in lexical order.
             */
            if (UnitTestDeclaration *udp = fdp->isUnitTestDeclaration())
            {
                udp->deferredNested.push(func);
                return;
            }
        }
    }

    if (isArrayOp && isDruntimeArrayOp(ident))
    {
        // Implementation is in druntime
        return;
    }

    // start code generation
    semanticRun = PASSobj;

    if (global.params.verbose)
        fprintf(global.stdmsg, "function  %s\n",func->toPrettyChars());

    Symbol *s = toSymbol(func);
    func_t *f = s->Sfunc;

    // tunnel type of "this" to debug info generation
    if (AggregateDeclaration* ad = func->parent->isAggregateDeclaration())
    {
        ::type* t = Type_toCtype(ad->getType());
        if(cd)
            t = t->Tnext; // skip reference
        f->Fclass = (Classsym *)t;
    }

#if TARGET_WINDOS
    /* This is done so that the 'this' pointer on the stack is the same
     * distance away from the function parameters, so that an overriding
     * function can call the nested fdensure or fdrequire of its overridden function
     * and the stack offsets are the same.
     */
    if (isVirtual() && (fensure || frequire))
        f->Fflags3 |= Ffakeeh;
#endif

#if TARGET_OSX
    s->Sclass = SCcomdat;
#else
    s->Sclass = SCglobal;
#endif
    for (Dsymbol *p = parent; p; p = p->parent)
    {
        if (p->isTemplateInstance())
        {
            s->Sclass = SCcomdat;
            break;
        }
    }

    /* Vector operations should be comdat's
     */
    if (isArrayOp)
        s->Sclass = SCcomdat;

    if (isNested())
    {
        //if (!(config.flags3 & CFG3pic))
        //    s->Sclass = SCstatic;
        f->Fflags3 |= Fnested;

        /* The enclosing function must have its code generated first,
         * in order to calculate correct frame pointer offset.
         */
        if (fdp && fdp->semanticRun < PASSobj)
        {
            fdp->toObjFile(multiobj);
        }
    }
    else
    {
        const char *libname = (global.params.symdebug)
                                ? global.params.debuglibname
                                : global.params.defaultlibname;

        // Pull in RTL startup code (but only once)
        if (func->isMain() && onlyOneMain(loc))
        {
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
            objmod->external_def("_main");
            objmod->ehsections();   // initialize exception handling sections
#endif
#if TARGET_WINDOS
            if (I64)
            {
                objmod->external_def("main");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("_main");
                objmod->external_def("__acrtused_con");
            }
#endif
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }
        else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc)
        {
#if TARGET_WINDOS
            if (I64)
            {
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
            }
            else
            {
                objmod->external_def("__acrtused_con");        // bring in C startup code
                objmod->includelib("snn.lib");          // bring in C runtime library
            }
#endif
            s->Sclass = SCglobal;
        }
#if TARGET_WINDOS
        else if (func->isWinMain() && onlyOneMain(loc))
        {
            if (I64)
            {
                objmod->includelib("uuid");
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("__acrtused");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }

        // Pull in RTL startup code
        else if (func->isDllMain() && onlyOneMain(loc))
        {
            if (I64)
            {
                objmod->includelib("uuid");
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("__acrtused_dll");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }
#endif
    }

    symtab_t *symtabsave = cstate.CSpsymtab;
    cstate.CSpsymtab = &f->Flocsym;

    // Find module m for this function
    Module *m = NULL;
    for (Dsymbol *p = parent; p; p = p->parent)
    {
        m = p->isModule();
        if (m)
            break;
    }

    IRState irs(m, func);
    Dsymbols deferToObj;                   // write these to OBJ file later
    irs.deferToObj = &deferToObj;

    TypeFunction *tf;
    RET retmethod;
    symbol *shidden = NULL;
    Symbol *sthis = NULL;
    tym_t tyf;

    tyf = tybasic(s->Stype->Tty);
    //printf("linkage = %d, tyf = x%x\n", linkage, tyf);
    reverse = tyrevfunc(s->Stype->Tty);

    assert(func->type->ty == Tfunction);
    tf = (TypeFunction *)(func->type);
    retmethod = retStyle(tf);
    if (retmethod == RETstack)
    {
        // If function returns a struct, put a pointer to that
        // as the first argument
        ::type *thidden = Type_toCtype(tf->next->pointerTo());
        char hiddenparam[5+4+1];
        static int hiddenparami;    // how many we've generated so far

        sprintf(hiddenparam,"__HID%d",++hiddenparami);
        shidden = symbol_name(hiddenparam,SCparameter,thidden);
        shidden->Sflags |= SFLtrue | SFLfree;
        if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedrefs.dim)
            type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile);
        irs.shidden = shidden;
        this->shidden = shidden;
    }
    else
    {
        // Register return style cannot make nrvo.
        // Auto functions keep the nrvo_can flag up to here,
        // so we should eliminate it before entering backend.
        nrvo_can = 0;
    }

    if (vthis)
    {
        assert(!vthis->csym);
        sthis = toSymbol(vthis);
        irs.sthis = sthis;
        if (!(f->Fflags3 & Fnested))
            f->Fflags3 |= Fmember;
    }

    // Estimate number of parameters, pi
    size_t pi = (v_arguments != NULL);
    if (parameters)
        pi += parameters->dim;

    // Create a temporary buffer, params[], to hold function parameters
    Symbol *paramsbuf[10];
    Symbol **params = paramsbuf;    // allocate on stack if possible
    if (pi + 2 > 10)                // allow extra 2 for sthis and shidden
    {
        params = (Symbol **)malloc((pi + 2) * sizeof(Symbol *));
        assert(params);
    }

    // Get the actual number of parameters, pi, and fill in the params[]
    pi = 0;
    if (v_arguments)
    {
        params[pi] = toSymbol(v_arguments);
        pi += 1;
    }
    if (parameters)
    {
        for (size_t i = 0; i < parameters->dim; i++)
        {
            VarDeclaration *v = (*parameters)[i];
            //printf("param[%d] = %p, %s\n", i, v, v->toChars());
            assert(!v->csym);
            params[pi + i] = toSymbol(v);
        }
        pi += parameters->dim;
    }

    if (reverse)
    {
        // Reverse params[] entries
        for (size_t i = 0; i < pi/2; i++)
        {
            Symbol *sptmp = params[i];
            params[i] = params[pi - 1 - i];
            params[pi - 1 - i] = sptmp;
        }
    }

    if (shidden)
    {
#if 0
        // shidden becomes last parameter
        params[pi] = shidden;
#else
        // shidden becomes first parameter
        memmove(params + 1, params, pi * sizeof(params[0]));
        params[0] = shidden;
#endif
        pi++;
    }


    if (sthis)
    {
#if 0
        // sthis becomes last parameter
        params[pi] = sthis;
#else
        // sthis becomes first parameter
        memmove(params + 1, params, pi * sizeof(params[0]));
        params[0] = sthis;
#endif
        pi++;
    }

    if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
         linkage != LINKd && shidden && sthis)
    {
        /* swap shidden and sthis
         */
        Symbol *sp = params[0];
        params[0] = params[1];
        params[1] = sp;
    }

    for (size_t i = 0; i < pi; i++)
    {
        Symbol *sp = params[i];
        sp->Sclass = SCparameter;
        sp->Sflags &= ~SFLspill;
        sp->Sfl = FLpara;
        symbol_add(sp);
    }

    // Determine register assignments
    if (pi)
    {
        FuncParamRegs fpr(tyf);

        for (size_t i = 0; i < pi; i++)
        {
            Symbol *sp = params[i];
            if (fpr.alloc(sp->Stype, sp->Stype->Tty, &sp->Spreg, &sp->Spreg2))
            {
                sp->Sclass = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar;
                sp->Sfl = (sp->Sclass == SCshadowreg) ? FLpara : FLfast;
            }
        }
    }

    // Done with params
    if (params != paramsbuf)
        free(params);
    params = NULL;

    if (func->fbody)
    {
        localgot = NULL;

        Statement *sbody = func->fbody;

        Blockx bx;
        memset(&bx,0,sizeof(bx));
        bx.startblock = block_calloc();
        bx.curblock = bx.startblock;
        bx.funcsym = s;
        bx.scope_index = -1;
        bx.classdec = cd;
        bx.member = func;
        bx.module = getModule();
        irs.blx = &bx;

        /* Doing this in semantic3() caused all kinds of problems:
         * 1. couldn't reliably get the final mangling of the function name due to fwd refs
         * 2. impact on function inlining
         * 3. what to do when writing out .di files, or other pretty printing
         */
        if (global.params.trace)
        {
            /* Wrap the entire function body in:
             *   trace_pro("funcname");
             *   try
             *     body;
             *   finally
             *     _c_trace_epi();
             */
            StringExp *se = StringExp::create(Loc(), s->Sident);
            se->type = Type::tstring;
            se->type = se->type->semantic(Loc(), NULL);
            Expressions *exps = Expressions_create();
            exps->push(se);
            FuncDeclaration *fdpro = FuncDeclaration::genCfunc(NULL, Type::tvoid, "trace_pro");
            Expression *ec = VarExp::create(Loc(), fdpro);
            Expression *e = CallExp::create(Loc(), ec, exps);
            e->type = Type::tvoid;
            Statement *sp = ExpStatement::create(loc, e);

            FuncDeclaration *fdepi = FuncDeclaration::genCfunc(NULL, Type::tvoid, "_c_trace_epi");
            ec = VarExp::create(Loc(), fdepi);
            e = CallExp::create(Loc(), ec);
            e->type = Type::tvoid;
            Statement *sf = ExpStatement::create(loc, e);

            Statement *stf;
            if (sbody->blockExit(this, tf->isnothrow) == BEfallthru)
                stf = CompoundStatement::create(Loc(), sbody, sf);
            else
                stf = TryFinallyStatement::create(Loc(), sbody, sf);
            sbody = CompoundStatement::create(Loc(), sp, stf);
        }

        buildClosure(this, &irs);

#if TARGET_WINDOS
        if (func->isSynchronized() && cd && config.flags2 & CFG2seh &&
            !func->isStatic() && !sbody->usesEH() && !global.params.trace)
        {
            /* The "jmonitor" hack uses an optimized exception handling frame
             * which is a little shorter than the more general EH frame.
             */
            s->Sfunc->Fflags3 |= Fjmonitor;
        }
#endif

        Statement_toIR(sbody, &irs);
        bx.curblock->BC = BCret;

        f->Fstartblock = bx.startblock;
//      einit = el_combine(einit,bx.init);

        if (isCtorDeclaration())
        {
            assert(sthis);
            for (block *b = f->Fstartblock; b; b = b->Bnext)
            {
                if (b->BC == BCret)
                {
                    b->BC = BCretexp;
                    b->Belem = el_combine(b->Belem, el_var(sthis));
                }
            }
        }
    }

    // If static constructor
    if (isSharedStaticCtorDeclaration())        // must come first because it derives from StaticCtorDeclaration
    {
        ssharedctors.push(s);
    }
    else if (isStaticCtorDeclaration())
    {
        sctors.push(s);
    }

    // If static destructor
    if (isSharedStaticDtorDeclaration())        // must come first because it derives from StaticDtorDeclaration
    {
        SharedStaticDtorDeclaration *f = isSharedStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {
            /* Increment destructor's vgate at construction time
             */
            esharedctorgates.push(f);
        }

        sshareddtors.shift(s);
    }
    else if (isStaticDtorDeclaration())
    {
        StaticDtorDeclaration *f = isStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {
            /* Increment destructor's vgate at construction time
             */
            ectorgates.push(f);
        }

        sdtors.shift(s);
    }

    // If unit test
    if (ud)
    {
        stests.push(s);
    }

    if (global.errors)
    {
        // Restore symbol table
        cstate.CSpsymtab = symtabsave;
        return;
    }

    writefunc(s);
    // Restore symbol table
    cstate.CSpsymtab = symtabsave;

    if (isExport())
        objmod->export_symbol(s, Para.offset);

    for (size_t i = 0; i < irs.deferToObj->dim; i++)
    {
        Dsymbol *s = (*irs.deferToObj)[i];
        s->toObjFile(0);
    }

    if (ud)
    {
        for (size_t i = 0; i < ud->deferredNested.dim; i++)
        {
            FuncDeclaration *fd = ud->deferredNested[i];
            fd->toObjFile(0);
        }
    }

#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
    // A hack to get a pointer to this function put in the .dtors segment
    if (ident && memcmp(ident->toChars(), "_STD", 4) == 0)
        objmod->staticdtor(s);
#endif
    if (irs.startaddress)
    {
        //printf("Setting start address\n");
        objmod->startaddress(irs.startaddress);
    }
}
Пример #12
0
/*
 * Generate the XML for an overload.
 */
static void xmlOverload(sipSpec *pt, moduleDef *mod, classDef *scope,
        memberDef *md, overDef *od, classDef *xtnds, int stat, int indent,
        FILE *fp)
{
    const char *name, *cppname = od->cppname;
    int a, no_res;

    xmlIndent(indent++, fp);
    fprintf(fp, "<Function name=\"");

    if (isReflected(od))
    {
        if ((name = reflectedSlot(md->slot)) != NULL)
            cppname = name;
        else
            name = md->pyname->text;
    }
    else
    {
        name = md->pyname->text;
    }

    prScopedPythonName(fp, scope, name);

    fprintf(fp, "\"");

    xmlRealScopedName(scope, cppname, fp);

    if (hasCppSignature(od->cppsig))
    {
        fprintf(fp, " cppsig=\"");
        xmlCppSignature(fp, od->cppsig, isConst(od));
        fprintf(fp, "\"");
    }

    if (isAbstract(od))
        fprintf(fp, " abstract=\"1\"");

    if (stat)
        fprintf(fp, " static=\"1\"");

    if (isSlot(od))
        fprintf(fp, " slot=\"1\"");

    if (isVirtual(od))
    {
        fprintf(fp, " virtual=\"1\"");
    }

    if (xtnds != NULL)
    {
        fprintf(fp, " extends=\"");
        prScopedPythonName(fp, xtnds->ecd, xtnds->pyname->text);
        fprintf(fp, "\"");
    }

    /* An empty type hint specifies a void return. */
    if (od->pysig.result.typehint_out != NULL && od->pysig.result.typehint_out->raw_hint[0] == '\0')
        no_res = TRUE;
    else
        no_res = (od->pysig.result.atype == void_type && od->pysig.result.nrderefs == 0);

    /* Handle the trivial case. */
    if (no_res && od->pysig.nrArgs == 0)
    {
        fprintf(fp, "/>\n");
        return;
    }

    fprintf(fp, ">\n");

    if (!no_res)
        xmlArgument(pt, mod, &od->pysig.result, TRUE, NoKwArgs,
                isResultTransferredBack(od), indent, fp);

    for (a = 0; a < od->pysig.nrArgs; ++a)
    {
        argDef *ad = &od->pysig.args[a];

        /*
         * Ignore the first argument of non-reflected number slots and the
         * second argument of reflected number slots.
         */
        if (isNumberSlot(md) && od->pysig.nrArgs == 2)
            if ((a == 0 && !isReflected(od)) || (a == 1 && isReflected(od)))
                continue;

        if (isInArg(ad))
            xmlArgument(pt, mod, ad, FALSE, od->kwargs, FALSE, indent, fp);

        if (isOutArg(ad))
            xmlArgument(pt, mod, ad, TRUE, od->kwargs, FALSE, indent, fp);
    }

    xmlIndent(--indent, fp);
    fprintf(fp, "</Function>\n");
}
Пример #13
0
void FuncDeclaration::toObjFile(int multiobj)
{
    FuncDeclaration *func = this;
    ClassDeclaration *cd = func->parent->isClassDeclaration();
    int reverse;
    int has_arguments;

    //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars());
    //if (type) printf("type = %s\n", func->type->toChars());
#if 0
    //printf("line = %d\n",func->getWhere() / LINEINC);
    EEcontext *ee = env->getEEcontext();
    if (ee->EEcompile == 2)
    {
        if (ee->EElinnum < (func->getWhere() / LINEINC) ||
            ee->EElinnum > (func->endwhere / LINEINC)
           )
            return;             // don't compile this function
        ee->EEfunc = func->toSymbol();
    }
#endif

    if (semanticRun >= PASSobj) // if toObjFile() already run
        return;

    // If errors occurred compiling it, such as bugzilla 6118
    if (type && type->ty == Tfunction && ((TypeFunction *)type)->next->ty == Terror)
        return;

    if (!func->fbody)
    {
        return;
    }
    if (func->isUnitTestDeclaration() && !global.params.useUnitTests)
        return;

    if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration())
    {   obj_append(this);
        return;
    }

    if (semanticRun == PASSsemanticdone)
    {
        /* What happened is this function failed semantic3() with errors,
         * but the errors were gagged.
         * Try to reproduce those errors, and then fail.
         */
        error("errors compiling the function");
        return;
    }
    assert(semanticRun == PASSsemantic3done);
    semanticRun = PASSobj;

    if (global.params.verbose)
        printf("function  %s\n",func->toPrettyChars());

    Symbol *s = func->toSymbol();
    func_t *f = s->Sfunc;

    // tunnel type of "this" to debug info generation
    if (AggregateDeclaration* ad = func->parent->isAggregateDeclaration())
    {
        ::type* t = ad->getType()->toCtype();
        if(cd)
            t = t->Tnext; // skip reference
        f->Fclass = (Classsym *)t;
    }

#if TARGET_WINDOS
    /* This is done so that the 'this' pointer on the stack is the same
     * distance away from the function parameters, so that an overriding
     * function can call the nested fdensure or fdrequire of its overridden function
     * and the stack offsets are the same.
     */
    if (isVirtual() && (fensure || frequire))
        f->Fflags3 |= Ffakeeh;
#endif

#if TARGET_OSX
    s->Sclass = SCcomdat;
#else
    s->Sclass = SCglobal;
#endif
    for (Dsymbol *p = parent; p; p = p->parent)
    {
        if (p->isTemplateInstance())
        {
            s->Sclass = SCcomdat;
            break;
        }
    }

    /* Vector operations should be comdat's
     */
    if (isArrayOp)
        s->Sclass = SCcomdat;

    if (isNested())
    {
//      if (!(config.flags3 & CFG3pic))
//          s->Sclass = SCstatic;
        f->Fflags3 |= Fnested;

        /* The enclosing function must have its code generated first,
         * so we know things like where its local symbols are stored.
         */
        FuncDeclaration *fdp = toAliasFunc()->toParent2()->isFuncDeclaration();
        // Bug 8016 - only include the function if it is a template instance
        Dsymbol * owner = NULL;
        if (fdp)
        {   owner =  fdp->toParent();
            while (owner && !owner->isTemplateInstance())
                owner = owner->toParent();
        }

        if (owner && fdp && fdp->semanticRun == PASSsemantic3done &&
            !fdp->isUnitTestDeclaration())
        {
            /* Can't do unittest's out of order, they are order dependent in that their
             * execution is done in lexical order, and some modules (std.datetime *cough*
             * *cough*) rely on this.
             */
            fdp->toObjFile(multiobj);
        }
    }
    else
    {
        const char *libname = (global.params.symdebug)
                                ? global.params.debuglibname
                                : global.params.defaultlibname;

        // Pull in RTL startup code (but only once)
        if (func->isMain() && onlyOneMain(loc))
        {
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
            objmod->external_def("_main");
            objmod->ehsections();   // initialize exception handling sections
#endif
#if TARGET_WINDOS
            if (I64)
            {
                objmod->external_def("main");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("_main");
                objmod->external_def("__acrtused_con");
            }
#endif
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }
        else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc)
        {
#if TARGET_WINDOS
            if (I64)
            {
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
            }
            else
            {
                objmod->external_def("__acrtused_con");        // bring in C startup code
                objmod->includelib("snn.lib");          // bring in C runtime library
            }
#endif
            s->Sclass = SCglobal;
        }
#if TARGET_WINDOS
        else if (func->isWinMain() && onlyOneMain(loc))
        {
            if (I64)
            {
                objmod->includelib("uuid");
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("__acrtused");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }

        // Pull in RTL startup code
        else if (func->isDllMain() && onlyOneMain(loc))
        {
            if (I64)
            {
                objmod->includelib("uuid");
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("__acrtused_dll");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }
#endif
    }

    cstate.CSpsymtab = &f->Flocsym;

    // Find module m for this function
    Module *m = NULL;
    for (Dsymbol *p = parent; p; p = p->parent)
    {
        m = p->isModule();
        if (m)
            break;
    }

    IRState irs(m, func);
    Dsymbols deferToObj;                   // write these to OBJ file later
    irs.deferToObj = &deferToObj;

    TypeFunction *tf;
    enum RET retmethod;
    symbol *shidden = NULL;
    Symbol *sthis = NULL;
    tym_t tyf;

    tyf = tybasic(s->Stype->Tty);
    //printf("linkage = %d, tyf = x%x\n", linkage, tyf);
    reverse = tyrevfunc(s->Stype->Tty);

    assert(func->type->ty == Tfunction);
    tf = (TypeFunction *)(func->type);
    has_arguments = (tf->linkage == LINKd) && (tf->varargs == 1);
    retmethod = tf->retStyle();
    if (retmethod == RETstack)
    {
        // If function returns a struct, put a pointer to that
        // as the first argument
        ::type *thidden = tf->next->pointerTo()->toCtype();
        char hiddenparam[5+4+1];
        static int hiddenparami;    // how many we've generated so far

        sprintf(hiddenparam,"__HID%d",++hiddenparami);
        shidden = symbol_name(hiddenparam,SCparameter,thidden);
        shidden->Sflags |= SFLtrue | SFLfree;
#if DMDV1
        if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedref)
#else
        if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedrefs.dim)
#endif
            type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile);
        irs.shidden = shidden;
        this->shidden = shidden;
    }
    else
    {   // Register return style cannot make nrvo.
        // Auto functions keep the nrvo_can flag up to here,
        // so we should eliminate it before entering backend.
        nrvo_can = 0;
    }

    if (vthis)
    {
        assert(!vthis->csym);
        sthis = vthis->toSymbol();
        irs.sthis = sthis;
        if (!(f->Fflags3 & Fnested))
            f->Fflags3 |= Fmember;
    }

    // Estimate number of parameters, pi
    size_t pi = (v_arguments != NULL);
    if (parameters)
        pi += parameters->dim;

    // Create a temporary buffer, params[], to hold function parameters
    Symbol *paramsbuf[10];
    Symbol **params = paramsbuf;    // allocate on stack if possible
    if (pi + 2 > 10)                // allow extra 2 for sthis and shidden
    {   params = (Symbol **)malloc((pi + 2) * sizeof(Symbol *));
        assert(params);
    }

    // Get the actual number of parameters, pi, and fill in the params[]
    pi = 0;
    if (v_arguments)
    {
        params[pi] = v_arguments->toSymbol();
        pi += 1;
    }
    if (parameters)
    {
        for (size_t i = 0; i < parameters->dim; i++)
        {   VarDeclaration *v = (*parameters)[i];
            if (v->csym)
            {
                error("compiler error, parameter '%s', bugzilla 2962?", v->toChars());
                assert(0);
            }
            params[pi + i] = v->toSymbol();
        }
        pi += parameters->dim;
    }

    if (reverse)
    {   // Reverse params[] entries
        for (size_t i = 0; i < pi/2; i++)
        {
            Symbol *sptmp = params[i];
            params[i] = params[pi - 1 - i];
            params[pi - 1 - i] = sptmp;
        }
    }

    if (shidden)
    {
#if 0
        // shidden becomes last parameter
        params[pi] = shidden;
#else
        // shidden becomes first parameter
        memmove(params + 1, params, pi * sizeof(params[0]));
        params[0] = shidden;
#endif
        pi++;
    }


    if (sthis)
    {
#if 0
        // sthis becomes last parameter
        params[pi] = sthis;
#else
        // sthis becomes first parameter
        memmove(params + 1, params, pi * sizeof(params[0]));
        params[0] = sthis;
#endif
        pi++;
    }

    if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
         linkage != LINKd && shidden && sthis)
    {
        /* swap shidden and sthis
         */
        Symbol *sp = params[0];
        params[0] = params[1];
        params[1] = sp;
    }

    for (size_t i = 0; i < pi; i++)
    {   Symbol *sp = params[i];
        sp->Sclass = SCparameter;
        sp->Sflags &= ~SFLspill;
        sp->Sfl = FLpara;
        symbol_add(sp);
    }

    // Determine register assignments
    if (pi)
    {
        FuncParamRegs fpr(tyf);

        for (size_t i = 0; i < pi; i++)
        {   Symbol *sp = params[i];
            if (fpr.alloc(sp->Stype, sp->Stype->Tty, &sp->Spreg, &sp->Spreg2))
            {
                sp->Sclass = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar;
                sp->Sfl = (sp->Sclass == SCshadowreg) ? FLpara : FLfast;
            }
        }
    }

    // Done with params
    if (params != paramsbuf)
        free(params);
    params = NULL;

    if (func->fbody)
    {
        localgot = NULL;

        Statement *sbody = func->fbody;

        Blockx bx;
        memset(&bx,0,sizeof(bx));
        bx.startblock = block_calloc();
        bx.curblock = bx.startblock;
        bx.funcsym = s;
        bx.scope_index = -1;
        bx.classdec = cd;
        bx.member = func;
        bx.module = getModule();
        irs.blx = &bx;

        /* If profiling, insert call to the profiler here.
         *      _c_trace_pro(char* funcname);
         */
        if (global.params.trace)
        {
            dt_t *dt = NULL;

            char *id = s->Sident;
            size_t len = strlen(id);
            dtnbytes(&dt, len + 1, id);

            Symbol *sfuncname = symbol_generate(SCstatic,type_fake(TYchar));
            sfuncname->Sdt = dt;
            sfuncname->Sfl = FLdata;
            out_readonly(sfuncname);
            outdata(sfuncname);
            elem *efuncname = el_ptr(sfuncname);

            elem *eparam = el_params(efuncname, el_long(TYsize_t, len), NULL);
            elem *e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_TRACE_CPRO]), eparam);
            block_appendexp(bx.curblock, e);
        }

#if DMDV2
        buildClosure(&irs);
#endif

#if TARGET_WINDOS
        if (func->isSynchronized() && cd && config.flags2 & CFG2seh &&
            !func->isStatic() && !sbody->usesEH())
        {
            /* The "jmonitor" hack uses an optimized exception handling frame
             * which is a little shorter than the more general EH frame.
             */
            s->Sfunc->Fflags3 |= Fjmonitor;
        }
#endif

        sbody->toIR(&irs);
        bx.curblock->BC = BCret;

        f->Fstartblock = bx.startblock;
//      einit = el_combine(einit,bx.init);

        if (isCtorDeclaration())
        {
            assert(sthis);
            for (block *b = f->Fstartblock; b; b = b->Bnext)
            {
                if (b->BC == BCret)
                {
                    b->BC = BCretexp;
                    b->Belem = el_combine(b->Belem, el_var(sthis));
                }
            }
        }
    }

    // If static constructor
#if DMDV2
    if (isSharedStaticCtorDeclaration())        // must come first because it derives from StaticCtorDeclaration
    {
        ssharedctors.push(s);
    }
    else
#endif
    if (isStaticCtorDeclaration())
    {
        sctors.push(s);
    }

    // If static destructor
#if DMDV2
    if (isSharedStaticDtorDeclaration())        // must come first because it derives from StaticDtorDeclaration
    {
        SharedStaticDtorDeclaration *f = isSharedStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            esharedctorgates.push(f);
        }

        sshareddtors.shift(s);
    }
    else
#endif
    if (isStaticDtorDeclaration())
    {
        StaticDtorDeclaration *f = isStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            ectorgates.push(f);
        }

        sdtors.shift(s);
    }

    // If unit test
    if (isUnitTestDeclaration())
    {
        stests.push(s);
    }

    if (global.errors)
        return;

    writefunc(s);
    if (isExport())
        objmod->export_symbol(s, Para.offset);

    for (size_t i = 0; i < irs.deferToObj->dim; i++)
    {
        Dsymbol *s = (*irs.deferToObj)[i];

        FuncDeclaration *fd = s->isFuncDeclaration();
        if (fd)
        {   FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration();
            if (fdp && fdp->semanticRun < PASSobj)
            {   /* Bugzilla 7595
                 * FuncDeclaration::buildClosure() relies on nested functions
                 * being toObjFile'd after the outer function. Otherwise, the
                 * v->offset's for the closure variables are wrong.
                 * So, defer fd until after fdp is done.
                 */
                fdp->deferred.push(fd);
                continue;
            }
        }

        s->toObjFile(0);
    }

    for (size_t i = 0; i < deferred.dim; i++)
    {
        FuncDeclaration *fd = deferred[i];
        fd->toObjFile(0);
    }

#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
    // A hack to get a pointer to this function put in the .dtors segment
    if (ident && memcmp(ident->toChars(), "_STD", 4) == 0)
        objmod->staticdtor(s);
#endif
#if DMDV2
    if (irs.startaddress)
    {
        //printf("Setting start address\n");
        objmod->startaddress(irs.startaddress);
    }
#endif
}
Пример #14
0
Файл: glue.c Проект: Geod24/dnet
void FuncDeclaration::toObjFile(int multiobj)
{
    Symbol *s;
    func_t *f;
    Symbol *senter;
    Symbol *sexit;
    FuncDeclaration *func = this;
    ClassDeclaration *cd = func->parent->isClassDeclaration();
    int reverse;
    int i;
    int has_arguments;

    //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars());
#if 0
    //printf("line = %d\n",func->getWhere() / LINEINC);
    EEcontext *ee = env->getEEcontext();
    if (ee->EEcompile == 2)
    {
	if (ee->EElinnum < (func->getWhere() / LINEINC) ||
	    ee->EElinnum > (func->endwhere / LINEINC)
	   )
	    return;		// don't compile this function
	ee->EEfunc = func->toSymbol();
    }
#endif

    if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration())
    {	obj_append(this);
	return;
    }

    if (semanticRun >= 5)	// if toObjFile() already run
	return;
    semanticRun = 5;

    if (!func->fbody)
    {
	return;
    }
    if (func->isUnitTestDeclaration() && !global.params.useUnitTests)
	return;

    if (global.params.verbose)
	printf("function  %s\n",func->toChars());

    s = func->toSymbol();
    f = s->Sfunc;

#if TARGET_WINDOS
    /* This is done so that the 'this' pointer on the stack is the same
     * distance away from the function parameters, so that an overriding
     * function can call the nested fdensure or fdrequire of its overridden function
     * and the stack offsets are the same.
     */
    if (isVirtual() && (fensure || frequire))
	f->Fflags3 |= Ffakeeh;
#endif

#if TARGET_OSX
    s->Sclass = SCcomdat;
#else
    s->Sclass = SCglobal;
#endif
    for (Dsymbol *p = parent; p; p = p->parent)
    {
	if (p->isTemplateInstance())
	{
	    s->Sclass = SCcomdat;
	    break;
	}
    }

    if (isNested())
    {
//	if (!(config.flags3 & CFG3pic))
//	    s->Sclass = SCstatic;
	f->Fflags3 |= Fnested;
    }
    else
    {
	const char *libname = (global.params.symdebug)
				? global.params.debuglibname
				: global.params.defaultlibname;

	// Pull in RTL startup code
	if (func->isMain())
	{   objextdef("_main");
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
	    obj_ehsections();	// initialize exception handling sections
#else
	    objextdef("__acrtused_con");
#endif
	    obj_includelib(libname);
	    s->Sclass = SCglobal;
	}
	else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc)
	    s->Sclass = SCglobal;

	else if (func->isWinMain())
	{
	    objextdef("__acrtused");
	    obj_includelib(libname);
	    s->Sclass = SCglobal;
	}

	// Pull in RTL startup code
	else if (func->isDllMain())
	{
	    objextdef("__acrtused_dll");
	    obj_includelib(libname);
	    s->Sclass = SCglobal;
	}
    }

    cstate.CSpsymtab = &f->Flocsym;

    // Find module m for this function
    Module *m = NULL;
    for (Dsymbol *p = parent; p; p = p->parent)
    {
	m = p->isModule();
	if (m)
	    break;
    }

    IRState irs(m, func);
    Array deferToObj;			// write these to OBJ file later
    irs.deferToObj = &deferToObj;

    TypeFunction *tf;
    enum RET retmethod;
    symbol *shidden = NULL;
    Symbol *sthis = NULL;
    tym_t tyf;

    tyf = tybasic(s->Stype->Tty);
    //printf("linkage = %d, tyf = x%x\n", linkage, tyf);
    reverse = tyrevfunc(s->Stype->Tty);

    assert(func->type->ty == Tfunction);
    tf = (TypeFunction *)(func->type);
    has_arguments = (tf->linkage == LINKd) && (tf->varargs == 1);
    retmethod = tf->retStyle();
    if (retmethod == RETstack)
    {
	// If function returns a struct, put a pointer to that
	// as the first argument
	::type *thidden = tf->next->pointerTo()->toCtype();
	char hiddenparam[5+4+1];
	static int hiddenparami;    // how many we've generated so far

	sprintf(hiddenparam,"__HID%d",++hiddenparami);
	shidden = symbol_name(hiddenparam,SCparameter,thidden);
	shidden->Sflags |= SFLtrue | SFLfree;
#if DMDV1
	if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedref)
#else
	if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedrefs.dim)
#endif
	    type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile);
	irs.shidden = shidden;
	this->shidden = shidden;
    }

    if (vthis)
    {
	assert(!vthis->csym);
	sthis = vthis->toSymbol();
	irs.sthis = sthis;
	if (!(f->Fflags3 & Fnested))
	    f->Fflags3 |= Fmember;
    }

    Symbol **params;
    unsigned pi;

    // Estimate number of parameters, pi
    pi = (v_arguments != NULL);
    if (parameters)
	pi += parameters->dim;
    // Allow extra 2 for sthis and shidden
    params = (Symbol **)alloca((pi + 2) * sizeof(Symbol *));

    // Get the actual number of parameters, pi, and fill in the params[]
    pi = 0;
    if (v_arguments)
    {
	params[pi] = v_arguments->toSymbol();
	pi += 1;
    }
    if (parameters)
    {
	for (i = 0; i < parameters->dim; i++)
	{   VarDeclaration *v = (VarDeclaration *)parameters->data[i];
	    if (v->csym)
	    {
		error("compiler error, parameter '%s', bugzilla 2962?", v->toChars());
		assert(0);
	    }
	    params[pi + i] = v->toSymbol();
	}
	pi += i;
    }

    if (reverse)
    {	// Reverse params[] entries
	for (i = 0; i < pi/2; i++)
	{   Symbol *sptmp;

	    sptmp = params[i];
	    params[i] = params[pi - 1 - i];
	    params[pi - 1 - i] = sptmp;
	}
    }

    if (shidden)
    {
#if 0
	// shidden becomes last parameter
	params[pi] = shidden;
#else
	// shidden becomes first parameter
	memmove(params + 1, params, pi * sizeof(params[0]));
	params[0] = shidden;
#endif
	pi++;
    }


    if (sthis)
    {
#if 0
	// sthis becomes last parameter
	params[pi] = sthis;
#else
	// sthis becomes first parameter
	memmove(params + 1, params, pi * sizeof(params[0]));
	params[0] = sthis;
#endif
	pi++;
    }

    if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
	 linkage != LINKd && shidden && sthis)
    {
	/* swap shidden and sthis
	 */
	Symbol *sp = params[0];
	params[0] = params[1];
	params[1] = sp;
    }

    for (i = 0; i < pi; i++)
    {	Symbol *sp = params[i];
	sp->Sclass = SCparameter;
	sp->Sflags &= ~SFLspill;
	sp->Sfl = FLpara;
	symbol_add(sp);
    }

    // First parameter goes in register
    if (pi)
    {
	Symbol *sp = params[0];
	if ((tyf == TYjfunc || tyf == TYmfunc) &&
	    type_jparam(sp->Stype))
	{   sp->Sclass = SCfastpar;
	    sp->Spreg = (tyf == TYjfunc) ? AX : CX;
	    sp->Sfl = FLauto;
	    //printf("'%s' is SCfastpar\n",sp->Sident);
	}
    }

    if (func->fbody)
    {   block *b;
	Blockx bx;
	Statement *sbody;

	localgot = NULL;

	sbody = func->fbody;
	memset(&bx,0,sizeof(bx));
	bx.startblock = block_calloc();
	bx.curblock = bx.startblock;
	bx.funcsym = s;
	bx.scope_index = -1;
	bx.classdec = cd;
	bx.member = func;
	bx.module = getModule();
	irs.blx = &bx;

	buildClosure(&irs);

#if 0
	if (func->isSynchronized())
	{
	    if (cd)
	    {	elem *esync;
		if (func->isStatic())
		{   // monitor is in ClassInfo
		    esync = el_ptr(cd->toSymbol());
		}
		else
		{   // 'this' is the monitor
		    esync = el_var(sthis);
		}

		if (func->isStatic() || sbody->usesEH() ||
		    !(config.flags2 & CFG2seh))
		{   // BUG: what if frequire or fensure uses EH?

		    sbody = new SynchronizedStatement(func->loc, esync, sbody);
		}
		else
		{
#if TARGET_WINDOS
		    if (config.flags2 & CFG2seh)
		    {
			/* The "jmonitor" uses an optimized exception handling frame
			 * which is a little shorter than the more general EH frame.
			 * It isn't strictly necessary.
			 */
			s->Sfunc->Fflags3 |= Fjmonitor;
		    }
#endif
		    el_free(esync);
		}
	    }
	    else
	    {
		error("synchronized function %s must be a member of a class", func->toChars());
	    }
	}
#elif TARGET_WINDOS
	if (func->isSynchronized() && cd && config.flags2 & CFG2seh &&
	    !func->isStatic() && !sbody->usesEH())
	{
	    /* The "jmonitor" hack uses an optimized exception handling frame
	     * which is a little shorter than the more general EH frame.
	     */
	    s->Sfunc->Fflags3 |= Fjmonitor;
	}
#endif

	sbody->toIR(&irs);
	bx.curblock->BC = BCret;

	f->Fstartblock = bx.startblock;
//	einit = el_combine(einit,bx.init);

	if (isCtorDeclaration())
	{
	    assert(sthis);
	    for (b = f->Fstartblock; b; b = b->Bnext)
	    {
		if (b->BC == BCret)
		{
		    b->BC = BCretexp;
		    b->Belem = el_combine(b->Belem, el_var(sthis));
		}
	    }
	} 
    }

    // If static constructor
    if (isStaticConstructor())
    {
	elem *e = el_una(OPucall, TYvoid, el_var(s));
	ector = el_combine(ector, e);
    }

    // If static destructor
    if (isStaticDestructor())
    {
	elem *e;

#if STATICCTOR
	e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
	ector = el_combine(ector, e);
	dtorcount++;
#else
	StaticDtorDeclaration *f = isStaticDtorDeclaration();
	assert(f);
	if (f->vgate)
	{   /* Increment destructor's vgate at construction time
	     */
	    ectorgates.push(f);
	}

	e = el_una(OPucall, TYvoid, el_var(s));
	edtor = el_combine(e, edtor);
#endif
    }

    // If unit test
    if (isUnitTestDeclaration())
    {
	elem *e = el_una(OPucall, TYvoid, el_var(s));
	etest = el_combine(etest, e);
    }

    if (global.errors)
	return;

    writefunc(s);
    if (isExport())
	obj_export(s, Poffset);

    for (i = 0; i < irs.deferToObj->dim; i++)
    {
	Dsymbol *s = (Dsymbol *)irs.deferToObj->data[i];
	s->toObjFile(0);
    }

#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
    // A hack to get a pointer to this function put in the .dtors segment
    if (ident && memcmp(ident->toChars(), "_STD", 4) == 0)
	obj_staticdtor(s);
#endif
#if DMDV2
    if (irs.startaddress)
    {
	printf("Setting start address\n");
	obj_startaddress(irs.startaddress);
    }
#endif
}
Пример #15
0
Symbol *FuncDeclaration::toSymbol()
{
    if (!csym)
    {   Symbol *s;
        TYPE *t;
        const char *id;

#if 0
        id = ident->toChars();
#else
        id = mangle();
#endif
        //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars());
        //printf("\tid = '%s'\n", id);
        //printf("\ttype = %s\n", type->toChars());
        s = symbol_calloc(id);
        slist_add(s);

        {
            s->prettyIdent = toPrettyChars();
            s->Sclass = SCglobal;
            symbol_func(s);
            func_t *f = s->Sfunc;
            if (isVirtual() && vtblIndex != -1)
                f->Fflags |= Fvirtual;
            else if (isMember2() && isStatic())
                f->Fflags |= Fstatic;
            f->Fstartline.Slinnum = loc.linnum;
            f->Fstartline.Sfilename = (char *)loc.filename;
            if (endloc.linnum)
            {   f->Fendline.Slinnum = endloc.linnum;
                f->Fendline.Sfilename = (char *)endloc.filename;
            }
            else
            {   f->Fendline.Slinnum = loc.linnum;
                f->Fendline.Sfilename = (char *)loc.filename;
            }
            t = type->toCtype();
        }

        mangle_t msave = t->Tmangle;
        if (isMain())
        {
            t->Tty = TYnfunc;
            t->Tmangle = mTYman_c;
        }
        else
        {
            switch (linkage)
            {
                case LINKwindows:
                    t->Tmangle = mTYman_std;
                    break;

                case LINKpascal:
                    t->Tty = TYnpfunc;
                    t->Tmangle = mTYman_pas;
                    break;

                case LINKc:
                    t->Tmangle = mTYman_c;
                    break;

                case LINKd:
                    t->Tmangle = mTYman_d;
                    break;

                case LINKcpp:
                {   t->Tmangle = mTYman_cpp;
                    if (isThis() && !global.params.is64bit && global.params.isWindows)
                        t->Tty = TYmfunc;
                    s->Sflags |= SFLpublic;
                    Dsymbol *parent = toParent();
                    ClassDeclaration *cd = parent->isClassDeclaration();
                    if (cd)
                    {
                        ::type *tc = cd->type->toCtype();
                        s->Sscope = tc->Tnext->Ttag;
                    }
                    StructDeclaration *sd = parent->isStructDeclaration();
                    if (sd)
                    {
                        ::type *ts = sd->type->toCtype();
                        s->Sscope = ts->Ttag;
                    }
                    break;
                }
                default:
                    printf("linkage = %d\n", linkage);
                    assert(0);
            }
        }
        if (msave)
            assert(msave == t->Tmangle);
        //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle);
        t->Tcount++;
        s->Stype = t;
        //s->Sfielddef = this;

        csym = s;
    }
    return csym;
}
bool isDeclaredVirtualWithinClassAncestry(SgFunctionDeclaration *functionDeclaration, SgClassDefinition *classDefinition)
{
  SgType *functionType =
    functionDeclaration->get_type();
  ROSE_ASSERT(functionType != NULL);

  // Look in each of the class' parent classes.
  SgBaseClassPtrList & baseClassList = classDefinition->get_inheritances(); 
  for (SgBaseClassPtrList::iterator i = baseClassList.begin(); 
       i != baseClassList.end(); ++i) {
 
    SgBaseClass *baseClass = *i;
    ROSE_ASSERT(baseClass != NULL);

    SgClassDeclaration *classDeclaration = baseClass->get_base_class(); 
    ROSE_ASSERT(classDeclaration != NULL);

    SgClassDefinition  *parentClassDefinition  = 
      classDeclaration->get_definition(); 

    // Visit all methods in the parent class.
    SgDeclarationStatementPtrList &members = 
      parentClassDefinition->get_members(); 

    bool isDeclaredVirtual = false;

    for (SgDeclarationStatementPtrList::iterator it = members.begin(); 
	 it != members.end(); ++it) { 
    
      SgDeclarationStatement *declarationStatement = *it; 
      ROSE_ASSERT(declarationStatement != NULL);
      
      switch(declarationStatement->variantT()) {
      
      case V_SgMemberFunctionDeclaration:
	{
	  SgMemberFunctionDeclaration *memberFunctionDeclaration =  
	    isSgMemberFunctionDeclaration(declarationStatement); 

	  if ( isVirtual(memberFunctionDeclaration) ) {

	    SgType *parentMemberFunctionType =
	      memberFunctionDeclaration->get_type();
	    ROSE_ASSERT(parentMemberFunctionType != NULL);

	    if ( parentMemberFunctionType == functionType ) {
	      return true;
	    }

	  }
	  break;

	}
      default:
	{
	  break;
	}

      }

    }

    if ( isDeclaredVirtualWithinClassAncestry(functionDeclaration, 
					      parentClassDefinition) ) {
      return true;
    }

  }

  return false;
}
Пример #17
0
int FuncDeclaration::canInline(int hasthis, int hdrscan, int statementsToo)
{
    InlineCostState ics;
    int cost;

#define CANINLINE_LOG 0

#if CANINLINE_LOG
    printf("FuncDeclaration::canInline(hasthis = %d, statementsToo = %d, '%s')\n", hasthis, statementsToo, toPrettyChars());
#endif

    if (needThis() && !hasthis)
        return 0;

    if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan))
    {
#if CANINLINE_LOG
        printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
#endif
        return 0;
    }

#if 1
    switch (statementsToo ? inlineStatusStmt : inlineStatusExp)
    {
        case ILSyes:
#if CANINLINE_LOG
            printf("\t1: yes %s\n", toChars());
#endif
            return 1;

        case ILSno:
#if CANINLINE_LOG
            printf("\t1: no %s\n", toChars());
#endif
            return 0;

        case ILSuninitialized:
            break;

        default:
            assert(0);
    }
#endif

    if (type)
    {   assert(type->ty == Tfunction);
        TypeFunction *tf = (TypeFunction *)type;
        if (tf->varargs == 1)   // no variadic parameter lists
            goto Lno;

        /* Don't inline a function that returns non-void, but has
         * no return expression.
         * No statement inlining for non-voids.
         */
        if (tf->next && tf->next->ty != Tvoid &&
            (!(hasReturnExp & 1) || statementsToo) &&
            !hdrscan)
            goto Lno;
    }

    // cannot inline constructor calls because we need to convert:
    //      return;
    // to:
    //      return this;
    if (
        !fbody ||
        ident == Id::ensure ||  // ensure() has magic properties the inliner loses
        (ident == Id::require &&             // require() has magic properties too
         toParent()->isFuncDeclaration() &&  // see bug 7699
         toParent()->isFuncDeclaration()->needThis()) ||
        !hdrscan &&
        (
        isSynchronized() ||
        isImportedSymbol() ||
        hasNestedFrameRefs() ||      // no nested references to this frame
        (isVirtual() && !isFinalFunc())
       ))
    {
        goto Lno;
    }

#if 0
    /* If any parameters are Tsarray's (which are passed by reference)
     * or out parameters (also passed by reference), don't do inlining.
     */
    if (parameters)
    {
        for (size_t i = 0; i < parameters->dim; i++)
        {
            VarDeclaration *v = (*parameters)[i];
            if (v->type->toBasetype()->ty == Tsarray)
                goto Lno;
        }
    }
#endif

    memset(&ics, 0, sizeof(ics));
    ics.hasthis = hasthis;
    ics.fd = this;
    ics.hdrscan = hdrscan;
    cost = fbody->inlineCost(&ics);
#if CANINLINE_LOG
    printf("cost = %d for %s\n", cost, toChars());
#endif
    if (tooCostly(cost))
        goto Lno;
    if (!statementsToo && cost > COST_MAX)
        goto Lno;

    if (!hdrscan)
    {
        // Don't modify inlineStatus for header content scan
        if (statementsToo)
            inlineStatusStmt = ILSyes;
        else
            inlineStatusExp = ILSyes;

        inlineScan();    // Don't scan recursively for header content scan

        if (inlineStatusExp == ILSuninitialized)
        {
            // Need to redo cost computation, as some statements or expressions have been inlined
            memset(&ics, 0, sizeof(ics));
            ics.hasthis = hasthis;
            ics.fd = this;
            ics.hdrscan = hdrscan;
            cost = fbody->inlineCost(&ics);
        #if CANINLINE_LOG
            printf("recomputed cost = %d for %s\n", cost, toChars());
        #endif
            if (tooCostly(cost))
                goto Lno;
            if (!statementsToo && cost > COST_MAX)
                goto Lno;

            if (statementsToo)
                inlineStatusStmt = ILSyes;
            else
                inlineStatusExp = ILSyes;
        }
    }
#if CANINLINE_LOG
    printf("\t2: yes %s\n", toChars());
#endif
    return 1;

Lno:
    if (!hdrscan)    // Don't modify inlineStatus for header content scan
    {   if (statementsToo)
            inlineStatusStmt = ILSno;
        else
            inlineStatusExp = ILSno;
    }
#if CANINLINE_LOG
    printf("\t2: no %s\n", toChars());
#endif
    return 0;
}
Пример #18
0
int FuncDeclaration::canInline(int hasthis, int hdrscan)
{
    InlineCostState ics;
    int cost;

#define CANINLINE_LOG 0

#if CANINLINE_LOG
    printf("FuncDeclaration::canInline(hasthis = %d, '%s')\n", hasthis, toChars());
#endif

    if (needThis() && !hasthis)
        return 0;

    if (inlineNest || (semanticRun < PASSsemantic3 && !hdrscan))
    {
#if CANINLINE_LOG
        printf("\t1: no, inlineNest = %d, semanticRun = %d\n", inlineNest, semanticRun);
#endif
        return 0;
    }

    switch (inlineStatus)
    {
    case ILSyes:
#if CANINLINE_LOG
        printf("\t1: yes %s\n", toChars());
#endif
        return 1;

    case ILSno:
#if CANINLINE_LOG
        printf("\t1: no %s\n", toChars());
#endif
        return 0;

    case ILSuninitialized:
        break;

    default:
        assert(0);
    }

    if (type)
    {   assert(type->ty == Tfunction);
        TypeFunction *tf = (TypeFunction *)(type);
#if IN_LLVM
        // LDC: Only extern(C) varargs count.
        if (tf->linkage != LINKd)
#endif
            if (tf->varargs == 1)   // no variadic parameter lists
                goto Lno;

        /* Don't inline a function that returns non-void, but has
         * no return expression.
         */
        if (tf->next && tf->next->ty != Tvoid &&
                !(hasReturnExp & 1) &&
                !hdrscan)
            goto Lno;
    }
#if !IN_LLVM
    // LDC: Only extern(C) varargs count, and ctors use extern(D).
    else
    {   CtorDeclaration *ctor = isCtorDeclaration();

        if (ctor && ctor->varargs == 1)
            goto Lno;
    }
#endif

    if (
        !fbody ||
        !hdrscan &&
        (
#if 0
            isCtorDeclaration() ||  // cannot because need to convert:
            //      return;
            // to:
            //      return this;
#endif
            isSynchronized() ||
            isImportedSymbol() ||
#if !IN_LLVM
#if DMDV2
            closureVars.dim ||      // no nested references to this frame
#else
            nestedFrameRef ||       // no nested references to this frame
#endif
#endif // !IN_LLVM
            (isVirtual() && !isFinal())
        ))
    {
        goto Lno;
    }

#if !IN_LLVM
#if !SARRAYVALUE
    /* If any parameters are Tsarray's (which are passed by reference)
     * or out parameters (also passed by reference), don't do inlining.
     */
    if (parameters)
    {
        for (size_t i = 0; i < parameters->dim; i++)
        {
            VarDeclaration *v = (VarDeclaration *)parameters->data[i];
            if (/*v->isOut() || v->isRef() ||*/ v->type->toBasetype()->ty == Tsarray)
                goto Lno;
        }
    }
#endif
#endif

    memset(&ics, 0, sizeof(ics));
    ics.hasthis = hasthis;
    ics.fd = this;
    ics.hdrscan = hdrscan;
    cost = fbody->inlineCost(&ics);
#if CANINLINE_LOG
    printf("cost = %d\n", cost);
#endif
    if (cost >= COST_MAX)
        goto Lno;

#if !IN_LLVM
    if (!hdrscan)    // Don't scan recursively for header content scan
        inlineScan();
#endif

    if (!hdrscan)    // Don't modify inlineStatus for header content scan
        inlineStatus = ILSyes;
#if CANINLINE_LOG
    printf("\t2: yes %s\n", toChars());
#endif
    return 1;

Lno:
    if (!hdrscan)    // Don't modify inlineStatus for header content scan
        inlineStatus = ILSno;
#if CANINLINE_LOG
    printf("\t2: no %s\n", toChars());
#endif
    return 0;
}
int main(int argc, char **argv)
{
  SgProject *project = frontend(argc, argv);
  
  // Instantiate a class hierarchy wrapper.
  ClassHierarchyWrapper classHierarchy( project );

  std::list<SgNode *> nodes2 = NodeQuery::querySubTree(project,
						      V_SgVariableDefinition);

  for (std::list<SgNode *>::iterator it = nodes2.begin();
       it != nodes2.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgVariableDefinition *varDefn =
      isSgVariableDefinition(n);
    ROSE_ASSERT(varDefn != NULL);

    std::cout << "Var defn: " << varDefn->unparseToCompleteString() << std::endl;

  }

  std::list<SgNode *> nodes1 = NodeQuery::querySubTree(project,
						      V_SgVariableDeclaration);

  for (std::list<SgNode *>::iterator it = nodes1.begin();
       it != nodes1.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgVariableDeclaration *varDecl =
      isSgVariableDeclaration(n);
    ROSE_ASSERT(varDecl != NULL);

    SgInitializedNamePtrList &variables =
      varDecl->get_variables();
    SgInitializedNamePtrList::iterator varIter;
    for (varIter = variables.begin(); 
	 varIter != variables.end(); ++varIter) {
      
      SgNode *var = *varIter;
      ROSE_ASSERT(var != NULL);
      
      SgInitializedName *initName =
	isSgInitializedName(var);
      ROSE_ASSERT(initName != NULL);
      
      if ( isSgClassType(initName->get_type()) ) {

	SgClassType *classType = isSgClassType(initName->get_type());
	ROSE_ASSERT(classType != NULL);

	SgDeclarationStatement *declStmt = classType->get_declaration();
	ROSE_ASSERT(declStmt != NULL);
	
	SgClassDeclaration *classDeclaration = isSgClassDeclaration(declStmt);
	ROSE_ASSERT(classDeclaration != NULL);
      
	//	std::cout << "From var decl got: " << classDeclaration->unparseToCompleteString() << std::endl;

	SgClassDefinition *classDefinition =
	  classDeclaration->get_definition();
	if ( classDefinition != NULL ) {
	  std::cout << "From var decl got: " << classDefinition->unparseToCompleteString() << std::endl;
	}

      }

    }
    

  }

  std::list<SgNode *> nodes = NodeQuery::querySubTree(project,
						      V_SgClassDeclaration);

  for (std::list<SgNode *>::iterator it = nodes.begin();
       it != nodes.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgClassDeclaration *classDeclaration1 =
      isSgClassDeclaration(n);
    ROSE_ASSERT(classDeclaration1 != NULL);

    SgDeclarationStatement *definingDecl =
      classDeclaration1->get_definingDeclaration();
    if ( definingDecl == NULL )
      continue;
    
    SgClassDeclaration *classDeclaration =
      isSgClassDeclaration(definingDecl);
    ROSE_ASSERT(classDeclaration != NULL);


    SgClassDefinition *classDefinition =
      classDeclaration->get_definition();
    ROSE_ASSERT(classDefinition != NULL);

    std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl;

    SgClassDefinitionPtrList subclasses = 
      classHierarchy.getSubclasses(classDefinition);

    // Iterate over all subclasses.
    for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin();
	 subclassIt != subclasses.end(); ++subclassIt) {
      
      SgClassDefinition *subclass = *subclassIt;
      ROSE_ASSERT(subclass != NULL);
      
      std::cout << "subclass" << std::endl;

    }

  }
#if 0
#if 0
  std::list<SgNode *> nodes = NodeQuery::querySubTree(project,
						      V_SgClassDefinition);

  for (std::list<SgNode *>::iterator it = nodes.begin();
       it != nodes.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgClassDefinition *classDefinition =
      isSgClassDefinition(n);
    ROSE_ASSERT(classDefinition != NULL);

    std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl;

    SgClassDefinitionPtrList subclasses = 
      classHierarchy.getSubclasses(classDefinition);

    // Iterate over all subclasses.
    for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin();
	 subclassIt != subclasses.end(); ++subclassIt) {
      
      SgClassDefinition *subclass = *subclassIt;
      ROSE_ASSERT(subclass != NULL);
      
      std::cout << "subclass" << std::endl;

    }

  }
#else
  // Collect all function/method invocations.
  std::list<SgNode *> nodes = NodeQuery::querySubTree(project,
						      V_SgFunctionCallExp);

  unsigned int numCallSites = 0;
  unsigned int numMonomorphicCallSites = 0;
  unsigned int numPossibleResolutions = 0;

  // Visit each call site.
  for (std::list<SgNode *>::iterator it = nodes.begin();
       it != nodes.end(); ++it ) {

    SgNode *n = *it;
    ROSE_ASSERT(n != NULL);

    SgFunctionCallExp *functionCallExp =
      isSgFunctionCallExp(n);
    ROSE_ASSERT(functionCallExp != NULL);

    // We are only interested in examining method invocations.
    bool isDotExp = false;
    if ( !isMethodCall(functionCallExp, isDotExp) )
      continue;
    
    numCallSites++;
    // Certainly can be resolved to the static method.
    numPossibleResolutions++;

    if ( isDotExp ) {
      // If this is a dot expression (i.e., a.foo()), we can
      // statically determine its type.
      numMonomorphicCallSites++;
      continue;
    }

    // Retrieve the static function declaration.
    SgFunctionDeclaration *functionDeclaration = 
      getFunctionDeclaration(functionCallExp);

    // Ensure it is actually a method declaration.
    SgMemberFunctionDeclaration *memberFunctionDeclaration =
      isSgMemberFunctionDeclaration(functionDeclaration);
    ROSE_ASSERT(memberFunctionDeclaration != NULL);

    unsigned int numOverridesForMethod = 0;

    if ( ( isVirtual(functionDeclaration) ) ||
	 ( isDeclaredVirtualWithinAncestor(functionDeclaration) ) ) {
      
      SgClassDefinition *classDefinition = 
	isSgClassDefinition(memberFunctionDeclaration->get_scope());
      ROSE_ASSERT(classDefinition != NULL);
      
      SgClassDefinitionPtrList subclasses = 
	classHierarchy.getSubclasses(classDefinition);

      // Iterate over all subclasses.
      for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin();
	   subclassIt != subclasses.end(); ++subclassIt) {

	SgClassDefinition *subclass = *subclassIt;
	ROSE_ASSERT(subclass != NULL);

	std::cout << "subclass" << std::endl;

	// Iterate over all of the methods defined in this subclass.
	SgDeclarationStatementPtrList &decls =
	  subclass->get_members();
	for (SgDeclarationStatementPtrList::iterator declIter = decls.begin();
	     declIter != decls.end(); ++declIter) {

	  SgDeclarationStatement *declStmt = *declIter;
	  ROSE_ASSERT(declStmt != NULL);

	  SgMemberFunctionDeclaration *method =
	    isSgMemberFunctionDeclaration(declStmt);
	  if ( method == NULL ) {
	    continue;
	  }

	  // Determine whether subclass of the class defining this
	  // method overrides the method.
	  if ( methodOverridesVirtualMethod(method, 
					    memberFunctionDeclaration) ) {
	    numOverridesForMethod++;
	  }

	}

      }

      if ( numOverridesForMethod == 0 )
	numMonomorphicCallSites++;
      numPossibleResolutions += numOverridesForMethod;

      std::cout << "Method invocation has " << numOverridesForMethod + 1 << " possible resolutions " << std::endl;
      std::cout << functionCallExp->unparseToCompleteString() << std::endl;

    }

  }
#endif
#endif
  return 0;
}
/**
 * \brief Return true if methodDecl overrides virtualMethodDecl.
 * \param methodDecl  a method declaration.
 * \param virtualMethodDecl a method declaration.
 * \return Returns true if virtualMethodDecl is declared as a virtual
 *         method and methodDecl has the same type signature and name
 *         as virtualMethodDecl.  
 * 
 * NB:  It is assumed that the class defining virtualMethodDecl is a base
 *      class of the class defining methodDecl.
 */
bool
methodOverridesVirtualMethod(SgMemberFunctionDeclaration *methodDecl, 
			     SgMemberFunctionDeclaration *virtualMethodDecl)
{
  if ( !isVirtual(virtualMethodDecl) )
    return false;

#if 1
  // Hmmm ... couldn't we just compare mangled names?
  return ( methodDecl->get_mangled_name() == virtualMethodDecl->get_mangled_name() );

#else
  if ( methodDecl->get_name() != virtualMethodDecl->get_name() )
    return false;
  
  SgType *methodReturnType = methodDecl->get_orig_return_type();
  SgType *virtualMethodReturnType = virtualMethodDecl->get_orig_return_type();

  if ( methodReturnType != virtualMethodReturnType )
    return false;

  int numMethodParams = 0;
  int numVirtualMethodParams = 0;

  SgFunctionParameterList *methodParameterList = 
    methodDecl->get_parameterList(); 

  if (methodParameterList != NULL) {
    numMethodParams = methodParameterList->get_args().size();
  }

  SgFunctionParameterList *virtualMethodParameterList = 
    virtualMethodDecl->get_parameterList(); 

  if (virtualMethodParameterList != NULL) {
    numVirtualMethodParams = virtualMethodParameterList->get_args().size();
  }

  if ( numMethodParams != numVirtualMethodParams )
    return false;

  if ( numMethodParams == 0 )
    return true;

  const SgInitializedNamePtrList &methodFormalParams = 
    methodParameterList->get_args(); 
  const SgInitializedNamePtrList &virtualMethodFormalParams = 
    virtualMethodParameterList->get_args(); 
  SgInitializedNamePtrList::const_iterator methodIt;
  SgInitializedNamePtrList::const_iterator virtualMethodIt;
  for(methodIt = methodFormalParams.begin(), 
	virtualMethodIt = virtualMethodFormalParams.begin();
      methodIt != methodFormalParams.end(); ++methodIt, ++virtualMethodIt) { 
      
      SgInitializedName* methodFormalParam = *methodIt;  
      ROSE_ASSERT(methodFormalParam != NULL); 

      SgInitializedName* virtualMethodFormalParam = *virtualMethodIt;  
      ROSE_ASSERT(virtualMethodFormalParam != NULL); 
      
      if ( methodFormalParam->get_type() != 
	   virtualMethodFormalParam->get_type() )
	return false;

  }

  return true;
#endif
}
Пример #21
0
int FuncDeclaration::cvMember(unsigned char *p)
{
    char *id;
    idx_t typidx;
    unsigned attribute;
    int nwritten = 0;
    debtyp_t *d;

    //printf("FuncDeclaration::cvMember() '%s'\n", toChars());

    if (!type)			// if not compiled in,
	return 0;		// skip it

    id = toChars();

    if (!p)
    {
	nwritten = 6 + cv_stringbytes(id);
    }
    else
    {
	int count;
	int mlen;
	unsigned char *q;

	count = 0;
	mlen = 2;
	{
	    if (introducing)
		mlen += 4;
	    mlen += cgcv.sz_idx * 2;
	    count++;
	}

	// Allocate and fill it in
	d = debtyp_alloc(mlen);
	q = d->data;
	TOWORD(q,LF_METHODLIST);
	q += 2;
//	for (s = sf; s; s = s->Sfunc->Foversym)
	{
	    attribute = PROTtoATTR(prot());

	    /* 0*4 vanilla method
	     * 1*4 virtual method
	     * 2*4 static method
	     * 3*4 friend method
	     * 4*4 introducing virtual method
	     * 5*4 pure virtual method
	     * 6*4 pure introducing virtual method
	     * 7*4 reserved
	     */

	    if (isStatic())
		attribute |= 2*4;
	    else if (isVirtual())
	    {
		if (introducing)
		{
		    if (isAbstract())
			attribute |= 6*4;
		    else
			attribute |= 4*4;
		}
		else
		{
		    if (isAbstract())
			attribute |= 5*4;
		    else
			attribute |= 1*4;
		}
	    }
	    else
		attribute |= 0*4;

	    TOIDX(q,attribute);
	    q += cgcv.sz_idx;
	    TOIDX(q, cv4_memfunctypidx(this));
	    q += cgcv.sz_idx;
	    if (introducing)
	    {   TOLONG(q, vtblIndex * PTRSIZE);
		q += 4;
	    }
	}
	assert(q - d->data == mlen);

	typidx = cv_debtyp(d);
	if (typidx)
	{
	    TOWORD(p,LF_METHOD);
	    TOWORD(p + 2,count);
	    nwritten = 4;
	    TOIDX(p + nwritten, typidx);
	    nwritten += cgcv.sz_idx;
	    nwritten += cv_namestring(p + nwritten, id);
	}
    }
    return nwritten;
}
Пример #22
0
void FuncDeclaration::toObjFile(int multiobj)
{
    FuncDeclaration *func = this;
    ClassDeclaration *cd = func->parent->isClassDeclaration();
    int reverse;
    int has_arguments;

    //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars());
    //if (type) printf("type = %s\n", func->type->toChars());
#if 0
    //printf("line = %d\n",func->getWhere() / LINEINC);
    EEcontext *ee = env->getEEcontext();
    if (ee->EEcompile == 2)
    {
        if (ee->EElinnum < (func->getWhere() / LINEINC) ||
            ee->EElinnum > (func->endwhere / LINEINC)
           )
            return;             // don't compile this function
        ee->EEfunc = func->toSymbol();
    }
#endif

    if (semanticRun >= PASSobj) // if toObjFile() already run
        return;

    // If errors occurred compiling it, such as bugzilla 6118
    if (type && type->ty == Tfunction && ((TypeFunction *)type)->next->ty == Terror)
        return;

    if (!func->fbody)
    {
        return;
    }
    if (func->isUnitTestDeclaration() && !global.params.useUnitTests)
        return;

    if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration())
    {   obj_append(this);
        return;
    }

    assert(semanticRun == PASSsemantic3done);
    semanticRun = PASSobj;

    if (global.params.verbose)
        printf("function  %s\n",func->toChars());

    Symbol *s = func->toSymbol();
    func_t *f = s->Sfunc;

#if TARGET_WINDOS
    /* This is done so that the 'this' pointer on the stack is the same
     * distance away from the function parameters, so that an overriding
     * function can call the nested fdensure or fdrequire of its overridden function
     * and the stack offsets are the same.
     */
    if (isVirtual() && (fensure || frequire))
        f->Fflags3 |= Ffakeeh;
#endif

#if TARGET_OSX
    s->Sclass = SCcomdat;
#else
    s->Sclass = SCglobal;
#endif
    for (Dsymbol *p = parent; p; p = p->parent)
    {
        if (p->isTemplateInstance())
        {
            s->Sclass = SCcomdat;
            break;
        }
    }

    /* Vector operations should be comdat's
     */
    if (isArrayOp)
        s->Sclass = SCcomdat;

    if (isNested())
    {
//      if (!(config.flags3 & CFG3pic))
//          s->Sclass = SCstatic;
        f->Fflags3 |= Fnested;
    }
    else
    {
        const char *libname = (global.params.symdebug)
                                ? global.params.debuglibname
                                : global.params.defaultlibname;

        // Pull in RTL startup code
        if (func->isMain())
        {   objextdef("_main");
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
            obj_ehsections();   // initialize exception handling sections
#endif
#if TARGET_WINDOS
            objextdef("__acrtused_con");
#endif
            obj_includelib(libname);
            s->Sclass = SCglobal;
        }
        else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc)
        {
#if TARGET_WINDOS
            objextdef("__acrtused_con");        // bring in C startup code
            obj_includelib("snn.lib");          // bring in C runtime library
#endif
            s->Sclass = SCglobal;
        }
        else if (func->isWinMain())
        {
            objextdef("__acrtused");
            obj_includelib(libname);
            s->Sclass = SCglobal;
        }

        // Pull in RTL startup code
        else if (func->isDllMain())
        {
            objextdef("__acrtused_dll");
            obj_includelib(libname);
            s->Sclass = SCglobal;
        }
    }

    cstate.CSpsymtab = &f->Flocsym;

    // Find module m for this function
    Module *m = NULL;
    for (Dsymbol *p = parent; p; p = p->parent)
    {
        m = p->isModule();
        if (m)
            break;
    }

    IRState irs(m, func);
    Dsymbols deferToObj;                   // write these to OBJ file later
    irs.deferToObj = &deferToObj;

    TypeFunction *tf;
    enum RET retmethod;
    symbol *shidden = NULL;
    Symbol *sthis = NULL;
    tym_t tyf;

    tyf = tybasic(s->Stype->Tty);
    //printf("linkage = %d, tyf = x%x\n", linkage, tyf);
    reverse = tyrevfunc(s->Stype->Tty);

    assert(func->type->ty == Tfunction);
    tf = (TypeFunction *)(func->type);
    has_arguments = (tf->linkage == LINKd) && (tf->varargs == 1);
    retmethod = tf->retStyle();
    if (retmethod == RETstack)
    {
        // If function returns a struct, put a pointer to that
        // as the first argument
        ::type *thidden = tf->next->pointerTo()->toCtype();
        char hiddenparam[5+4+1];
        static int hiddenparami;    // how many we've generated so far

        sprintf(hiddenparam,"__HID%d",++hiddenparami);
        shidden = symbol_name(hiddenparam,SCparameter,thidden);
        shidden->Sflags |= SFLtrue | SFLfree;
#if DMDV1
        if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedref)
#else
        if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedrefs.dim)
#endif
            type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile);
        irs.shidden = shidden;
        this->shidden = shidden;
    }
    else
    {   // Register return style cannot make nrvo.
        // Auto functions keep the nrvo_can flag up to here,
        // so we should eliminate it before entering backend.
        nrvo_can = 0;
    }

    if (vthis)
    {
        assert(!vthis->csym);
        sthis = vthis->toSymbol();
        irs.sthis = sthis;
        if (!(f->Fflags3 & Fnested))
            f->Fflags3 |= Fmember;
    }

    Symbol **params;
    unsigned pi;

    // Estimate number of parameters, pi
    pi = (v_arguments != NULL);
    if (parameters)
        pi += parameters->dim;
    // Allow extra 2 for sthis and shidden
    params = (Symbol **)alloca((pi + 2) * sizeof(Symbol *));

    // Get the actual number of parameters, pi, and fill in the params[]
    pi = 0;
    if (v_arguments)
    {
        params[pi] = v_arguments->toSymbol();
        pi += 1;
    }
    if (parameters)
    {
        for (size_t i = 0; i < parameters->dim; i++)
        {   VarDeclaration *v = (*parameters)[i];
            if (v->csym)
            {
                error("compiler error, parameter '%s', bugzilla 2962?", v->toChars());
                assert(0);
            }
            params[pi + i] = v->toSymbol();
        }
        pi += parameters->dim;
    }

    if (reverse)
    {   // Reverse params[] entries
        for (size_t i = 0; i < pi/2; i++)
        {
            Symbol *sptmp = params[i];
            params[i] = params[pi - 1 - i];
            params[pi - 1 - i] = sptmp;
        }
    }

    if (shidden)
    {
#if 0
        // shidden becomes last parameter
        params[pi] = shidden;
#else
        // shidden becomes first parameter
        memmove(params + 1, params, pi * sizeof(params[0]));
        params[0] = shidden;
#endif
        pi++;
    }


    if (sthis)
    {
#if 0
        // sthis becomes last parameter
        params[pi] = sthis;
#else
        // sthis becomes first parameter
        memmove(params + 1, params, pi * sizeof(params[0]));
        params[0] = sthis;
#endif
        pi++;
    }

    if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
         linkage != LINKd && shidden && sthis)
    {
        /* swap shidden and sthis
         */
        Symbol *sp = params[0];
        params[0] = params[1];
        params[1] = sp;
    }

    for (size_t i = 0; i < pi; i++)
    {   Symbol *sp = params[i];
        sp->Sclass = SCparameter;
        sp->Sflags &= ~SFLspill;
        sp->Sfl = FLpara;
        symbol_add(sp);
    }

    // Determine register assignments
    if (pi)
    {
        size_t numintegerregs = 0, numfloatregs = 0;
        const unsigned char* argregs = getintegerparamsreglist(tyf, &numintegerregs);
        const unsigned char* floatregs = getfloatparamsreglist(tyf, &numfloatregs);

        // Order of assignment of pointer or integer parameters
        int r = 0;
        int xmmcnt = 0;

        for (size_t i = 0; i < pi; i++)
        {   Symbol *sp = params[i];
            tym_t ty = tybasic(sp->Stype->Tty);
            // BUG: doesn't work for structs
            if (r < numintegerregs)
            {
                if ((I64 || (i == 0 && (tyf == TYjfunc || tyf == TYmfunc))) && type_jparam(sp->Stype))
                {
                    sp->Sclass = SCfastpar;
                    sp->Spreg = argregs[r];
                    sp->Sfl = FLauto;
                    ++r;
                }
            }
            if (xmmcnt < numfloatregs)
            {
                if (tyxmmreg(ty))
                {
                    sp->Sclass = SCfastpar;
                    sp->Spreg = floatregs[xmmcnt];
                    sp->Sfl = FLauto;
                    ++xmmcnt;
                }
            }
        }
    }

    if (func->fbody)
    {   block *b;
        Blockx bx;
        Statement *sbody;

        localgot = NULL;

        sbody = func->fbody;
        memset(&bx,0,sizeof(bx));
        bx.startblock = block_calloc();
        bx.curblock = bx.startblock;
        bx.funcsym = s;
        bx.scope_index = -1;
        bx.classdec = cd;
        bx.member = func;
        bx.module = getModule();
        irs.blx = &bx;
#if DMDV2
        buildClosure(&irs);
#endif

#if 0
        if (func->isSynchronized())
        {
            if (cd)
            {   elem *esync;
                if (func->isStatic())
                {   // monitor is in ClassInfo
                    esync = el_ptr(cd->toSymbol());
                }
                else
                {   // 'this' is the monitor
                    esync = el_var(sthis);
                }

                if (func->isStatic() || sbody->usesEH() ||
                    !(config.flags2 & CFG2seh))
                {   // BUG: what if frequire or fensure uses EH?

                    sbody = new SynchronizedStatement(func->loc, esync, sbody);
                }
                else
                {
#if TARGET_WINDOS
                    if (config.flags2 & CFG2seh)
                    {
                        /* The "jmonitor" uses an optimized exception handling frame
                         * which is a little shorter than the more general EH frame.
                         * It isn't strictly necessary.
                         */
                        s->Sfunc->Fflags3 |= Fjmonitor;
                    }
#endif
                    el_free(esync);
                }
            }
            else
            {
                error("synchronized function %s must be a member of a class", func->toChars());
            }
        }
#elif TARGET_WINDOS
        if (func->isSynchronized() && cd && config.flags2 & CFG2seh &&
            !func->isStatic() && !sbody->usesEH())
        {
            /* The "jmonitor" hack uses an optimized exception handling frame
             * which is a little shorter than the more general EH frame.
             */
            s->Sfunc->Fflags3 |= Fjmonitor;
        }
#endif

        sbody->toIR(&irs);
        bx.curblock->BC = BCret;

        f->Fstartblock = bx.startblock;
//      einit = el_combine(einit,bx.init);

        if (isCtorDeclaration())
        {
            assert(sthis);
            for (b = f->Fstartblock; b; b = b->Bnext)
            {
                if (b->BC == BCret)
                {
                    b->BC = BCretexp;
                    b->Belem = el_combine(b->Belem, el_var(sthis));
                }
            }
        }
    }

    // If static constructor
#if DMDV2
    if (isSharedStaticCtorDeclaration())        // must come first because it derives from StaticCtorDeclaration
    {
        ssharedctors.push(s);
    }
    else
#endif
    if (isStaticCtorDeclaration())
    {
        sctors.push(s);
    }

    // If static destructor
#if DMDV2
    if (isSharedStaticDtorDeclaration())        // must come first because it derives from StaticDtorDeclaration
    {
        SharedStaticDtorDeclaration *f = isSharedStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            esharedctorgates.push(f);
        }

        sshareddtors.shift(s);
    }
    else
#endif
    if (isStaticDtorDeclaration())
    {
        StaticDtorDeclaration *f = isStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            ectorgates.push(f);
        }

        sdtors.shift(s);
    }

    // If unit test
    if (isUnitTestDeclaration())
    {
        stests.push(s);
    }

    if (global.errors)
        return;

    writefunc(s);
    if (isExport())
        obj_export(s, Poffset);

    for (size_t i = 0; i < irs.deferToObj->dim; i++)
    {
        Dsymbol *s = (*irs.deferToObj)[i];

        FuncDeclaration *fd = s->isFuncDeclaration();
        if (fd)
        {   FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration();
            if (fdp && fdp->semanticRun < PASSobj)
            {   /* Bugzilla 7595
                 * FuncDeclaration::buildClosure() relies on nested functions
                 * being toObjFile'd after the outer function. Otherwise, the
                 * v->offset's for the closure variables are wrong.
                 * So, defer fd until after fdp is done.
                 */
                fdp->deferred.push(fd);
                continue;
            }
        }

        s->toObjFile(0);
    }

    for (size_t i = 0; i < deferred.dim; i++)
    {
        FuncDeclaration *fd = deferred[i];
        fd->toObjFile(0);
    }

#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
    // A hack to get a pointer to this function put in the .dtors segment
    if (ident && memcmp(ident->toChars(), "_STD", 4) == 0)
        obj_staticdtor(s);
#endif
#if DMDV2
    if (irs.startaddress)
    {
        printf("Setting start address\n");
        obj_startaddress(irs.startaddress);
    }
#endif
}
Пример #23
0
//---------------------------------------------------------
// Compute x-coordinates (LP-based approach) (for graphs)
//---------------------------------------------------------
void OptimalHierarchyLayout::computeXCoordinates(
	const Hierarchy& H,
	GraphCopyAttributes &AGC)
{
	const GraphCopy &GC = H;
	const int k = H.size();

	//
	// preprocessing: determine nodes that are considered as virtual
	//
	NodeArray<bool> isVirtual(GC);

	int i;
	for(i = 0; i < k; ++i)
	{
		const Level &L = H[i];
		int last = -1;
		for(int j = 0; j < L.size(); ++j)
		{
			node v = L[j];

			if(H.isLongEdgeDummy(v) == true) {
				isVirtual[v] = true;

				node u = v->firstAdj()->theEdge()->target();
				if(u == v) u = v->lastAdj()->theEdge()->target();

				if(H.isLongEdgeDummy(u) == true) {
					int down = H.pos(u);
					if(last != -1 && last > down) {
						isVirtual[v] = false;
					} else {
						last = down;
					}
				}
			} else
				isVirtual[v] = false;
		}
	}

	//
	// determine variables of LP
	//
	int nSegments     = 0; // number of vertical segments
	int nRealVertices = 0; // number of real vertices
	int nEdges        = 0; // number of edges not in vertical segments
	int nBalanced     = 0; // number of real vertices with deg > 1 for which
	                       // balancing constraints may be applied

	NodeArray<int> vIndex(GC,-1); // for real node: index of x[v]
	                              // for dummy: index of corresponding segment
	NodeArray<int> bIndex(GC,-1); // (relative) index of b[v]
	EdgeArray<int> eIndex(GC,-1); // for edge not in vertical segment:
	                              //   its index
	Array<int> count(GC.numberOfEdges());  // counts the number of dummy vertices
	                              // in corresponding segment that are not at
	                              // position 0

	for(i = 0; i < k; ++i)
	{
		const Level &L = H[i];
		for(int j = 0; j < L.size(); ++j) {
			node v = L[j];
			if(isVirtual[v] == true)
				continue;

			// we've found a real vertex
			vIndex[v] = nRealVertices++;
			if(v->degree() > 1)
				bIndex[v] = nBalanced++;

			// consider all outgoing edges
			edge e;
			forall_adj_edges(e,v) {
				node w = e->target();
				if(w == v)
					continue;

				// we've found an edge not belonging to a vetical segment
				eIndex[e] = nEdges++;

				if(isVirtual[w] == false)
					continue;

				// we've found a vertical segment
				count[nSegments] = 0;
				do {
					vIndex[w] = nSegments;
					const int high = H[H.rank(w)].high();
					if(high > 0) {
						if (H.pos(w) == 0 || H.pos(w) == high)
							++count[nSegments];
						else
							count[nSegments] += 2;
					}

					// next edge / dummy in segment
					e = e->adjTarget()->cyclicSucc()->theEdge();
					w = e->target();
				} while(isVirtual[w]);

				// edge following vertical segment
                eIndex[e] = nEdges++;

				++nSegments;
			}
		}
	}
Пример #24
0
Symbol *FuncDeclaration::toSymbol()
{
    if (!csym)
    {   Symbol *s;
        TYPE *t;
        const char *id;

#if 0
        id = ident->toChars();
#else
        id = mangle();
#endif
        //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars());
        //printf("\tid = '%s'\n", id);
        //printf("\ttype = %s\n", type->toChars());
        s = symbol_calloc(id);
        slist_add(s);

        {
            s->prettyIdent = toPrettyChars();
            s->Sclass = SCglobal;
            symbol_func(s);
            func_t *f = s->Sfunc;
            if (isVirtual())
                f->Fflags |= Fvirtual;
            else if (isMember2())
                f->Fflags |= Fstatic;
            f->Fstartline.Slinnum = loc.linnum;
            f->Fstartline.Sfilename = (char *)loc.filename;
            if (endloc.linnum)
            {   f->Fendline.Slinnum = endloc.linnum;
                f->Fendline.Sfilename = (char *)endloc.filename;
            }
            else
            {   f->Fendline.Slinnum = loc.linnum;
                f->Fendline.Sfilename = (char *)loc.filename;
            }
            t = type->toCtype();
        }

        mangle_t msave = t->Tmangle;
        if (isMain())
        {
            t->Tty = TYnfunc;
            t->Tmangle = mTYman_c;
        }
        else
        {
            switch (linkage)
            {
            case LINKwindows:
                t->Tmangle = mTYman_std;
                break;

            case LINKpascal:
                t->Tty = TYnpfunc;
                t->Tmangle = mTYman_pas;
                break;

            case LINKc:
                t->Tmangle = mTYman_c;
                break;

            case LINKd:
                t->Tmangle = mTYman_d;
                break;

            case LINKcpp:
                t->Tmangle = mTYman_cpp;
                break;

            default:
                printf("linkage = %d\n", linkage);
                assert(0);
            }
        }
        if (msave)
            assert(msave == t->Tmangle);
        //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle);
        t->Tcount++;
        s->Stype = t;
        //s->Sfielddef = this;

        csym = s;
    }
    return csym;
}