Пример #1
0
Symbol *VarDeclaration::toSymbol()
{
    //printf("VarDeclaration::toSymbol(%s)\n", toChars());
    //if (needThis()) *(char*)0=0;
    assert(!needThis());
    if (!csym)
    {
        TYPE *t;
        const char *id;

        if (isDataseg())
            id = mangle();
        else
            id = ident->toChars();
        Symbol *s = symbol_calloc(id);
        s->Salignment = alignment;

        if (storage_class & (STCout | STCref))
        {
            // should be TYref, but problems in back end
            t = type_pointer(type->toCtype());
        }
        else if (storage_class & STClazy)
        {
            if (config.exe == EX_WIN64 && isParameter())
                t = type_fake(TYnptr);
            else
                t = type_fake(TYdelegate);          // Tdelegate as C type
            t->Tcount++;
        }
        else if (isParameter())
        {
            if (config.exe == EX_WIN64 && type->size(Loc()) > REGSIZE)
            {
                // should be TYref, but problems in back end
                t = type_pointer(type->toCtype());
            }
            else
            {
                t = type->toCParamtype();
                t->Tcount++;
            }
        }
        else
        {
            t = type->toCtype();
            t->Tcount++;
        }

        if (isDataseg())
        {
            if (isThreadlocal())
            {   /* Thread local storage
                 */
                TYPE *ts = t;
                ts->Tcount++;   // make sure a different t is allocated
                type_setty(&t, t->Tty | mTYthread);
                ts->Tcount--;

                if (global.params.vtls)
                {
                    char *p = loc.toChars();
                    fprintf(stderr, "%s: %s is thread local\n", p ? p : "", toChars());
                    if (p)
                        mem.free(p);
                }
            }
            s->Sclass = SCextern;
            s->Sfl = FLextern;
            slist_add(s);
            /* if it's global or static, then it needs to have a qualified but unmangled name.
             * This gives some explanation of the separation in treating name mangling.
             * It applies to PDB format, but should apply to CV as PDB derives from CV.
             *    http://msdn.microsoft.com/en-us/library/ff553493(VS.85).aspx
             */
            s->prettyIdent = toPrettyChars();
        }
        else
        {
            s->Sclass = SCauto;
            s->Sfl = FLauto;

            if (nestedrefs.dim)
            {
                /* Symbol is accessed by a nested function. Make sure
                 * it is not put in a register, and that the optimizer
                 * assumes it is modified across function calls and pointer
                 * dereferences.
                 */
                //printf("\tnested ref, not register\n");
                type_setcv(&t, t->Tty | mTYvolatile);
            }
        }

        if (ident == Id::va_argsave)
            /* __va_argsave is set outside of the realm of the optimizer,
             * so we tell the optimizer to leave it alone
             */
            type_setcv(&t, t->Tty | mTYvolatile);

        mangle_t m = 0;
        switch (linkage)
        {
            case LINKwindows:
                m = mTYman_std;
                break;

            case LINKpascal:
                m = mTYman_pas;
                break;

            case LINKc:
                m = mTYman_c;
                break;

            case LINKd:
                m = mTYman_d;
                break;

            case LINKcpp:
            {
                m = mTYman_cpp;

                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);
        }
        type_setmangle(&t, m);
        s->Stype = t;

        csym = s;
    }
    return csym;
}
Пример #2
0
Symbol *VarDeclaration::toSymbol()
{
    //printf("VarDeclaration::toSymbol(%s)\n", toChars());
    //if (needThis()) *(char*)0=0;
    assert(!needThis());
    if (!csym)
    {	Symbol *s;
	TYPE *t;
	const char *id;
	mangle_t m = 0;

	if (isDataseg())
	    id = mangle();
	else
	    id = ident->toChars();
	s = symbol_calloc(id);

	if (storage_class & STCout)
	    t = type_fake(TYnptr);
	else if (isParameter())
	    t = type->toCParamtype();
	else
	    t = type->toCtype();
	t->Tcount++;

	if (isDataseg())
	{
	    s->Sclass = SCextern;
	    s->Sfl = FLextern;
	    slist_add(s);
	}
	else
	{
	    s->Sclass = SCauto;
	    s->Sfl = FLauto;

	    if (nestedref)
	    {
		/* Symbol is accessed by a nested function. Make sure
		 * it is not put in a register, and that the optimizer
		 * assumes it is modified across function calls and pointer
		 * dereferences.
		 */
		//printf("\tnested ref, not register\n");
		type_setcv(&t, t->Tty | mTYvolatile);
	    }
	}
	if (storage_class & STCconst)
	{
	    // Insert const modifiers
	    tym_t tym = 0;

	    if (storage_class & STCconst)
		tym |= mTYconst;
	    type_setcv(&t, tym);
	}
	switch (linkage)
	{
	    case LINKwindows:
		m = mTYman_std;
		break;

	    case LINKpascal:
		m = mTYman_pas;
		break;

	    case LINKc:
		m = mTYman_c;
		break;

	    case LINKd:
		m = mTYman_d;
		break;

	    case LINKcpp:
		m = mTYman_cpp;
		break;

	    default:
		printf("linkage = %d\n", linkage);
		assert(0);
	}
	type_setmangle(&t, m);
	s->Stype = t;

	csym = s;
    }
    return csym;
}
Пример #3
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;
}
Пример #4
0
void *PToP(void *arg)
{
	Head* head;
	peer_t * peer=(peer_t *)arg;
	peer->bitmap=malloc(mapcount);		//记录该peer的bitfield
	memset(peer->bitmap,0,mapcount);

	int sockfd=peer->sockfd;
	int i;
	char rcvline[MAXLINE];
	char sendline[MAXLINE];
	char templine[MAXLINE];
	char c;
	memset(rcvline,0,MAXLINE);
	memset(sendline,0,MAXLINE);

	//啥话不说,先来一发
	Hand* hk=(Hand*)sendline;
	hk->len=0x13;
	strcpy(hk->name,"BitTorrent protocol");
	memset(hk->reserve,0,8);
	int hash[5];
	for(i=0;i<5;i++)
		hash[i]=reverse_byte_orderi(g_infohash[i]);
	memcpy(hk->sha,hash,20);
	memcpy(hk->id,g_my_id,20);
	sendme(sockfd,sendline,sizeof(Hand));

	if(recvme(sockfd,rcvline,sizeof(Hand))<=0)
	{
		printf("握手失败\n");
		{
			shutdown(sockfd,SHUT_RDWR);
			close(sockfd);
			peer->sockfd=-1;
			return NULL;
		}
	}
	hk=(Hand*)rcvline;
	/*if(memcmp(hash,hk->sha,20)!=0){
		printf("hash 不匹配\n");
		shutdown(sockfd,SHUT_RDWR);
		close(sockfd);
		peer->sockfd=-1;
		return NULL;
	}*/
	memcpy(peer->name,hk->id,20);		

	//bitfield
	pthread_mutex_lock(&g_isSeed_lock);
	i=g_isSeed;
	pthread_mutex_unlock(&g_isSeed_lock);
	if(i==2)
	{
		memset(sendline,0,MAXLINE);
		head=(Head*)sendline;
		head->len=reverse_byte_orderi(mapcount+1);
		head->id=0x05;
		pthread_mutex_lock(&g_bitmap_lock);
		memcpy(&sendline[HEAD_SIZE],g_bitmap,mapcount);
		pthread_mutex_unlock(&g_bitmap_lock);
		sendme(sockfd,sendline,HEAD_SIZE+mapcount);
	}

	Request* req;
	int temp;
	ReqState reqState;
	reqState.index=-1;
	reqState.offset=-1;
	reqState.len=-1;
	SaveState saveState;
	saveState.index=-1;
	saveState.offset=0;

	int cancel=-1;
	int errcount=0;
	while(!g_done)
	{
		req=NULL;
		memset(rcvline,0,MAXLINE);
		memset(sendline,0,MAXLINE);
		memset(templine,0,MAXLINE);
		head=NULL;
		i=recvme(sockfd,rcvline,sizeof(int));
		if(peer->state||i<=0)
		{
			errcount++;
			if(errcount>1)
			{
				printf("接受信息错误%d\n",peer->state);
				shutdown(sockfd,SHUT_RDWR);
				close(sockfd);
				peer->sockfd=-1;
				return NULL;
			}
			continue;
		}
		errcount=0;
		head=(Head*)rcvline;
		if(reverse_byte_orderi(head->len)<=0)continue;	//keep alive	
		if(recvme(sockfd,rcvline+sizeof(int),1)<0)continue;
		int load_len=reverse_byte_orderi(head->len)-1;
		//printf("状态:%02X\n",head->id);
		switch(head->id)
		{
			case 0x00:			//choke
				printf("被阻塞!\n");
				head=(Head*)sendline;
				head->len=reverse_byte_orderi(1);
				head->id=0x02;
				peer->have_interest=1;
				sendme(sockfd,sendline,HEAD_SIZE);
				break;
			case 0x01:			//unchoke
				if(!peer->have_interest)break;
				peer->choked=0;
				sendRequest(peer,&reqState);	//send request
				break;
			case 0x02:		//interest
				if(peer->choking)break;
				cancel=-1;
				peer->interested=1;
				head=(Head*)sendline;
				head->len=reverse_byte_orderi(1);
				head->id=0x01;		//unchoke
				sendme(sockfd,sendline,HEAD_SIZE);
				//等待对方的request
				break;
			case 0x03:		//not interested
				cancel=-1;
				break;
			case 0x04:		//have
				if(recvme(sockfd,templine,load_len)<=0)
					continue;
				memcpy(&temp,templine,sizeof(int));
				temp=reverse_byte_orderi(temp);
				pthread_mutex_lock(&g_bitmap_lock);
				c=g_bitmap[temp/8];
				pthread_mutex_unlock(&g_bitmap_lock);
				if(isSet(c,8-temp%8))continue;
				head=(Head*)sendline;
				head->len=reverse_byte_orderi(1);
				head->id=0x02;
				sendme(sockfd,sendline,HEAD_SIZE);
				break;
			case 0x05:		//bitfield
				if(recvme(sockfd,templine,load_len)<=0)
					continue;
				if(load_len!=mapcount)
				{
					shutdown(sockfd,SHUT_RDWR);
					close(sockfd);
					peer->sockfd=-1;
					return NULL;
				}
				memcpy(peer->bitmap,templine,mapcount);
				i=needThis(peer->bitmap);	//判断是否有需要该用户,需要记录该用户提供了那些分片
				//printf("是否需要该用户%d\n",i);
				if(i==0)
				{
					shutdown(sockfd,SHUT_RDWR);
					close(sockfd);
					peer->sockfd=-1;
					return NULL;
				}
				else if(i==1)break;		//不感兴趣
				//send interest
				head=(Head*)sendline;
				head->len=reverse_byte_orderi(1);
				head->id=0x02;
				peer->have_interest=1;
				sendme(sockfd,sendline,HEAD_SIZE);
				break;
			case 0x06:		//request
				if(recvme(sockfd,templine,load_len)<=0)
					continue;
				req=(Request *)templine;
				if(reverse_byte_orderi(req->len)>131072)	//2^17
				{
					shutdown(sockfd,SHUT_RDWR);
					close(sockfd);
					peer->sockfd=-1;
					return NULL;
				}
				if(cancel==reverse_byte_orderi(req->index)){
					cancel=-1;
					continue;
				}
				sendPiece(sockfd,req->index,req->offset,req->len);	//发送子分片
				break;
			case 0x07:		//piece
				if(recvme(sockfd,templine,load_len)<=0)
					continue;
				//printf("load len :%d\n",i);
				req=(Request *)templine;
				/*for(i=0;i<8;i++)
				  {
				  for(temp=0;temp<8;temp++)
				  printf("%02X ",templine[i*8+temp]);
				  printf("\n");
				  }*/
				savePiece(reverse_byte_orderi(req->index),reverse_byte_orderi(req->offset),templine+2*sizeof(int),load_len-2*sizeof(int),&saveState);	//存储分片:w
				sendRequest(peer,&reqState);
				break;
			case 0x08:		//cancel
				if(recvme(sockfd,templine,load_len)<=0)continue;
				req=(Request*)templine;
				cancel=reverse_byte_orderi(req->index);
				break;
			default:
				;//printf("没有该状态%02X\n",head->id);return NULL;

		}
	}
	shutdown(sockfd,SHUT_RDWR);
	close(sockfd);
	peer->sockfd=-1;
	return NULL;
}
Пример #5
0
Expression *FuncDeclaration::interpret(InterState *istate, Expressions *arguments)
{
#if LOG
    printf("\n********\nFuncDeclaration::interpret(istate = %p) %s\n", istate, toChars());
    printf("cantInterpret = %d, semanticRun = %d\n", cantInterpret, semanticRun);
#endif
    if (global.errors)
	return NULL;
    if (ident == Id::aaLen)
	return interpret_aaLen(istate, arguments);
    else if (ident == Id::aaKeys)
	return interpret_aaKeys(istate, arguments);
    else if (ident == Id::aaValues)
	return interpret_aaValues(istate, arguments);

    if (cantInterpret || semanticRun == 1)
	return NULL;

    if (needThis() || isNested() || !fbody)
    {	cantInterpret = 1;
	return NULL;
    }

    if (semanticRun == 0 && scope)
    {
	semantic3(scope);
	if (global.errors)	// if errors compiling this function
	    return NULL;
    }
    if (semanticRun < 2)
	return NULL;

    Type *tb = type->toBasetype();
    assert(tb->ty == Tfunction);
    TypeFunction *tf = (TypeFunction *)tb;
    Type *tret = tf->next->toBasetype();
    if (tf->varargs /*|| tret->ty == Tvoid*/)
    {	cantInterpret = 1;
	return NULL;
    }

    if (tf->parameters)
    {	size_t dim = Argument::dim(tf->parameters);
	for (size_t i = 0; i < dim; i++)
	{   Argument *arg = Argument::getNth(tf->parameters, i);
	    if (arg->storageClass & STClazy)
	    {   cantInterpret = 1;
		return NULL;
	    }
	}
    }

    InterState istatex;
    istatex.caller = istate;
    istatex.fd = this;

    Expressions vsave;		// place to save previous parameter values
    size_t dim = 0;
    if (arguments)
    {
	dim = arguments->dim;
	assert(!dim || parameters->dim == dim);
	vsave.setDim(dim);

	/* Evaluate all the arguments to the function,
	 * store the results in eargs[]
	 */
	Expressions eargs;
	eargs.setDim(dim);

	for (size_t i = 0; i < dim; i++)
	{   Expression *earg = (Expression *)arguments->data[i];
	    Argument *arg = Argument::getNth(tf->parameters, i);

	    if (arg->storageClass & (STCout | STCref))
	    {
	    }
	    else
	    {	/* Value parameters
		 */
		Type *ta = arg->type->toBasetype();
		if (ta->ty == Tsarray && earg->op == TOKaddress)
		{
		    /* Static arrays are passed by a simple pointer.
		     * Skip past this to get at the actual arg.
		     */
		    earg = ((AddrExp *)earg)->e1;
		}
		earg = earg->interpret(istate ? istate : &istatex);
		if (earg == EXP_CANT_INTERPRET)
		    return NULL;
	    }
	    eargs.data[i] = earg;
	}

	for (size_t i = 0; i < dim; i++)
	{   Expression *earg = (Expression *)eargs.data[i];
	    Argument *arg = Argument::getNth(tf->parameters, i);
	    VarDeclaration *v = (VarDeclaration *)parameters->data[i];
	    vsave.data[i] = v->value;
#if LOG
	    printf("arg[%d] = %s\n", i, earg->toChars());
#endif
	    if (arg->storageClass & (STCout | STCref))
	    {
		/* Bind out or ref parameter to the corresponding
		 * variable v2
		 */
		if (!istate || earg->op != TOKvar)
		    return NULL;	// can't bind to non-interpreted vars

		VarDeclaration *v2;
		while (1)
		{
		    VarExp *ve = (VarExp *)earg;
		    v2 = ve->var->isVarDeclaration();
		    if (!v2)
			return NULL;
		    if (!v2->value || v2->value->op != TOKvar)
			break;
		    earg = v2->value;
		}

		v->value = new VarExp(earg->loc, v2);

		/* Don't restore the value of v2 upon function return
		 */
		assert(istate);
		for (size_t i = 0; i < istate->vars.dim; i++)
		{   VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
		    if (v == v2)
		    {	istate->vars.data[i] = NULL;
			break;
		    }
		}
	    }
	    else
	    {	/* Value parameters
		 */
		v->value = earg;
	    }
#if LOG
	    printf("interpreted arg[%d] = %s\n", i, earg->toChars());
#endif
	}
    }

    /* Save the values of the local variables used
     */
    Expressions valueSaves;
    if (istate)
    {
	//printf("saving local variables...\n");
	valueSaves.setDim(istate->vars.dim);
	for (size_t i = 0; i < istate->vars.dim; i++)
	{   VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
	    if (v)
	    {
		//printf("\tsaving [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : "");
		valueSaves.data[i] = v->value;
		v->value = NULL;
	    }
	}
    }

    Expression *e = NULL;

    while (1)
    {
	e = fbody->interpret(&istatex);
	if (e == EXP_CANT_INTERPRET)
	{
#if LOG
	    printf("function body failed to interpret\n");
#endif
	    e = NULL;
	}

	/* This is how we deal with a recursive statement AST
	 * that has arbitrary goto statements in it.
	 * Bubble up a 'result' which is the target of the goto
	 * statement, then go recursively down the AST looking
	 * for that statement, then execute starting there.
	 */
	if (e == EXP_GOTO_INTERPRET)
	{
	    istatex.start = istatex.gotoTarget;	// set starting statement
	    istatex.gotoTarget = NULL;
	}
	else
	    break;
    }

    /* Restore the parameter values
     */
    for (size_t i = 0; i < dim; i++)
    {
	VarDeclaration *v = (VarDeclaration *)parameters->data[i];
	v->value = (Expression *)vsave.data[i];
    }

    if (istate)
    {
	/* Restore the variable values
	 */
	//printf("restoring local variables...\n");
	for (size_t i = 0; i < istate->vars.dim; i++)
	{   VarDeclaration *v = (VarDeclaration *)istate->vars.data[i];
	    if (v)
	    {	v->value = (Expression *)valueSaves.data[i];
		//printf("\trestoring [%d] %s = %s\n", i, v->toChars(), v->value ? v->value->toChars() : "");
	    }
	}
    }

    return e;
}
Пример #6
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;
}
Пример #7
0
Symbol *VarDeclaration::toSymbol()
{
    //printf("VarDeclaration::toSymbol(%s)\n", toChars());
    //if (needThis()) *(char*)0=0;
    assert(!needThis());
    if (!csym)
    {   Symbol *s;
        TYPE *t;
        const char *id;

        if (isDataseg())
            id = mangle();
        else
            id = ident->toChars();
        s = symbol_calloc(id);

        if (storage_class & (STCout | STCref))
        {
            if (global.params.symdebug && storage_class & STCparameter)
            {
                t = type_alloc(TYnptr);         // should be TYref, but problems in back end
                t->Tnext = type->toCtype();
                t->Tnext->Tcount++;
            }
            else
                t = type_fake(TYnptr);
        }
        else if (storage_class & STClazy)
            t = type_fake(TYdelegate);          // Tdelegate as C type
        else if (isParameter())
            t = type->toCParamtype();
        else
            t = type->toCtype();
        t->Tcount++;

        if (isDataseg())
        {
            if (isThreadlocal())
            {   /* Thread local storage
                 */
                TYPE *ts = t;
                ts->Tcount++;   // make sure a different t is allocated
                type_setty(&t, t->Tty | mTYthread);
                ts->Tcount--;

                if (global.params.vtls)
                {
                    char *p = loc.toChars();
                    fprintf(stdmsg, "%s: %s is thread local\n", p ? p : "", toChars());
                    if (p)
                        mem.free(p);
                }
            }
            s->Sclass = SCextern;
            s->Sfl = FLextern;
            slist_add(s);
        }
        else
        {
            s->Sclass = SCauto;
            s->Sfl = FLauto;

            if (nestedrefs.dim)
            {
                /* Symbol is accessed by a nested function. Make sure
                 * it is not put in a register, and that the optimizer
                 * assumes it is modified across function calls and pointer
                 * dereferences.
                 */
                //printf("\tnested ref, not register\n");
                type_setcv(&t, t->Tty | mTYvolatile);
            }
        }

        if (ident == Id::va_argsave)
            /* __va_argsave is set outside of the realm of the optimizer,
             * so we tell the optimizer to leave it alone
             */
            type_setcv(&t, t->Tty | mTYvolatile);

        mangle_t m = 0;
        switch (linkage)
        {
            case LINKwindows:
                m = mTYman_std;
                break;

            case LINKpascal:
                m = mTYman_pas;
                break;

            case LINKc:
                m = mTYman_c;
                break;

            case LINKd:
                m = mTYman_d;
                break;

            case LINKcpp:
                m = mTYman_cpp;
                break;

            default:
                printf("linkage = %d\n", linkage);
                assert(0);
        }
        type_setmangle(&t, m);
        s->Stype = t;

        csym = s;
    }
    return csym;
}