Ejemplo n.º 1
0
protected void
ct_conv_buff_resize(ct_buffer_t *conv, size_t mincsize, size_t minwsize)
{
	void *p;
	if (mincsize > conv->csize) {
		conv->csize = mincsize;
		p = el_realloc(conv->cbuff, conv->csize * sizeof(char));
		if (p == NULL) {
			conv->csize = 0;
			el_free(conv->cbuff);
			conv->cbuff = NULL;
		} else 
			conv->cbuff = p;
	}

	if (minwsize > conv->wsize) {
		conv->wsize = minwsize;
		p = el_realloc(conv->wbuff, conv->wsize * sizeof(Char));
		if (p == NULL) {
			conv->wsize = 0;
			el_free(conv->wbuff);
			conv->wbuff = NULL;
		} else
			conv->wbuff = p;
	}
}
Ejemplo n.º 2
0
/* el_read_end():
 *	Free the data structures used by the read stuff.
 */
libedit_private void
read_end(struct el_read_t *el_read)
{
	read_clearmacros(&el_read->macros);
	el_free(el_read->macros.macro);
	el_read->macros.macro = NULL;
	el_free(el_read);
}
Ejemplo n.º 3
0
/* hist_end():
 *	clean up history;
 */
libedit_private void
hist_end(EditLine *el)
{

	el_free(el->el_history.buf);
	el->el_history.buf = NULL;
}
Ejemplo n.º 4
0
/* sig_end():
 *	Clear all signal stuff
 */
libedit_private void
sig_end(EditLine *el)
{

	el_free(el->el_signal);
	el->el_signal = NULL;
}
Ejemplo n.º 5
0
static void
ch__clearmacro(EditLine *el)
{
	c_macro_t *ma = &el->el_chared.c_macro;
	while (ma->level >= 0)
		el_free(ma->macro[ma->level--]);
}
Ejemplo n.º 6
0
Archivo: type.c Proyecto: michelf/dmd
void param_free(param_t **pparamlst)
{   param_t *p,*pn;

#if !TX86
    debug_assert(PARSER);
#endif
    for (p = *pparamlst; p; p = pn)
    {   param_debug(p);
        pn = p->Pnext;
        type_free(p->Ptype);
#if TX86
        mem_free(p->Pident);
#else
        MEM_PH_FREE(p->Pident);
#endif
        el_free(p->Pelem);
        type_free(p->Pdeftype);
        if (p->Pptpl)
            param_free(&p->Pptpl);
#ifdef DEBUG
        p->id = 0;
#endif
        p->Pnext = param_list;
        param_list = p;
    }
    *pparamlst = NULL;
}
Ejemplo n.º 7
0
/**
 * Destroy all elements in queue and queue itself. Also notifies squeue_pop
 * Doesn't deallocate squeue_t
 *
 * @param sq synchronized queue to destroy
 * @param free helper to destroy element's data
 *
 * @note squeue_destroy() will notify consumer but doesn't guarantee that it \
 * 		will leave squeue_pop(). You need to check this on your own.		 \
 * 		It could be easily done by joining consumer thread.
 * */
void squeue_destroy(squeue_t* sq, void (*el_free)(void* obj)) {
	squeue_el_t* el;
	squeue_el_t* next;

	mutex_lock(&sq->sq_mutex);

	el = sq->sq_head;

	while(el != NULL) {
		next = el->s_next;

		el_free(el->s_data);
		mp_free(el);

		el = next;
	}

	sq->sq_is_destroyed = B_TRUE;
	cv_notify_all(&sq->sq_cv);

	mutex_unlock(&sq->sq_mutex);

	mutex_destroy(&sq->sq_mutex);
	cv_destroy(&sq->sq_cv);
}
Ejemplo n.º 8
0
static void
read_clearmacros(struct macros *ma)
{
	while (ma->level >= 0)
		el_free(ma->macro[ma->level--]);
	ma->offset = 0;
}
Ejemplo n.º 9
0
/* el_init():
 *	Initialize editline and set default parameters.
 */
public EditLine *
el_init(const char *prog, FILE *fin, FILE *fout, FILE *ferr)
{

	EditLine *el = (EditLine *) el_malloc(sizeof(EditLine));

	if (el == NULL)
		return (NULL);

	memset(el, 0, sizeof(EditLine));

	el->el_infile = fin;
	el->el_outfile = fout;
	el->el_errfile = ferr;

	el->el_infd = fileno(fin);

	if ((el->el_prog = el_strdup(prog)) == NULL) {
		el_free(el);
		return NULL;
	}

	/*
         * Initialize all the modules. Order is important!!!
         */
	el->el_flags = 0;

	if (term_init(el) == -1) {
		el_free(el->el_prog);
		el_free(el);
		return NULL;
	}
	(void) key_init(el);
	(void) map_init(el);
	if (tty_init(el) == -1)
		el->el_flags |= NO_TTY;
	(void) ch_init(el);
	(void) search_init(el);
	(void) hist_init(el);
	(void) prompt_init(el);
	(void) sig_init(el);
	(void) read_init(el);

	return (el);
}
Ejemplo n.º 10
0
/* ch_end():
 *	Free the data structures used by the editor
 */
libedit_private void
ch_end(EditLine *el)
{
	el_free(el->el_line.buffer);
	el->el_line.buffer = NULL;
	el->el_line.limit = NULL;
	el_free(el->el_chared.c_undo.buf);
	el->el_chared.c_undo.buf = NULL;
	el_free(el->el_chared.c_redo.buf);
	el->el_chared.c_redo.buf = NULL;
	el->el_chared.c_redo.pos = NULL;
	el->el_chared.c_redo.lim = NULL;
	el->el_chared.c_redo.cmd = ED_UNASSIGNED;
	el_free(el->el_chared.c_kill.buf);
	el->el_chared.c_kill.buf = NULL;
	ch_reset(el, 1);
	el_free(el->el_chared.c_macro.macro);
	el->el_chared.c_macro.macro = NULL;
}
Ejemplo n.º 11
0
/* read_pop():
 *	Pop a macro from the stack
 */
static void
read_pop(struct macros *ma)
{
	int i;

	el_free(ma->macro[0]);
	for (i = 0; i < ma->level; i++)
		ma->macro[i] = ma->macro[i + 1];
	ma->level--;
	ma->offset = 0;
}
Ejemplo n.º 12
0
static const char *
append_char_function(const char *name)
{
	struct stat stbuf;
	char *expname = *name == '~' ? fn_tilde_expand(name) : NULL;
	const char *rs = " ";

	if (stat(expname ? expname : name, &stbuf) == -1)
		goto out;
	if (S_ISDIR(stbuf.st_mode))
		rs = "/";
out:
	if (expname)
		el_free(expname);
	return rs;
}
Ejemplo n.º 13
0
Archivo: type.c Proyecto: sgraf812/dmd
void type_free(type *t)
{   type *tn;
    tym_t ty;

    while (t)
    {
        //dbg_printf("type_free(%p, Tcount = %d)\n", t, t->Tcount);
        type_debug(t);
        assert((int)t->Tcount != -1);
        if (--t->Tcount)                /* if usage count doesn't go to 0 */
            break;
        ty = tybasic(t->Tty);
        if (tyfunc(ty))
        {   param_free(&t->Tparamtypes);
            list_free(&t->Texcspec, (list_free_fp)type_free);
        }
#if !MARS
        else if (ty == TYtemplate)
            param_free(&t->Tparamtypes);
        else if (ty == TYident)
            MEM_PH_FREE(t->Tident);
#endif
        else if (t->Tflags & TFvla && t->Tel)
            el_free(t->Tel);
#if SCPP
        else if (t->Talternate && typtr(ty))
            type_free(t->Talternate);
#endif
#if MARS
        else if (t->Tkey && typtr(ty))
            type_free(t->Tkey);
#endif
#ifdef DEBUG
        type_num--;
        //dbg_printf("Free'ing type %p ",t); WRTYxx(t->Tty); dbg_printf("\n");
        t->id = 0;                      /* no longer a valid type       */
#endif
        tn = t->Tnext;
        t->Tnext = type_list;
        type_list = t;                  /* link into free list          */
        t = tn;
    }
}
Ejemplo n.º 14
0
static int
ct_conv_wbuff_resize(ct_buffer_t *conv, size_t wsize)
{
	void *p;

	if (wsize <= conv->wsize)
		return 0;

	conv->wsize = wsize;

	p = el_realloc(conv->wbuff, conv->wsize * sizeof(*conv->wbuff));
	if (p == NULL) {
		conv->wsize = 0;
		el_free(conv->wbuff);
		conv->wbuff = NULL;
		return -1;
	}
	conv->wbuff = p;
	return 0;
}
Ejemplo n.º 15
0
/*
 * does tilde expansion of strings of type ``~user/foo''
 * if ``user'' isn't valid user name or ``txt'' doesn't start
 * w/ '~', returns pointer to strdup()ed copy of ``txt''
 *
 * it's callers's responsibility to free() returned string
 */
char *
fn_tilde_expand(const char *txt)
{
#if defined(HAVE_GETPW_R_POSIX) || defined(HAVE_GETPW_R_DRAFT)
	struct passwd pwres;
	char pwbuf[1024];
#endif
	struct passwd *pass;
	char *temp;
	size_t len = 0;

	if (txt[0] != '~')
		return strdup(txt);

	temp = strchr(txt + 1, '/');
	if (temp == NULL) {
		temp = strdup(txt + 1);
		if (temp == NULL)
			return NULL;
	} else {
		/* text until string after slash */
		len = (size_t)(temp - txt + 1);
		temp = el_malloc(len * sizeof(*temp));
		if (temp == NULL)
			return NULL;
		(void)strncpy(temp, txt + 1, len - 2);
		temp[len - 2] = '\0';
	}
	if (temp[0] == 0) {
#ifdef HAVE_GETPW_R_POSIX
 		if (getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf),
		    &pass) != 0)
 			pass = NULL;
#elif HAVE_GETPW_R_DRAFT
		pass = getpwuid_r(getuid(), &pwres, pwbuf, sizeof(pwbuf));
#else
		pass = getpwuid(getuid());
#endif
	} else {
#ifdef HAVE_GETPW_R_POSIX
		if (getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf), &pass) != 0)
			pass = NULL;
#elif HAVE_GETPW_R_DRAFT
		pass = getpwnam_r(temp, &pwres, pwbuf, sizeof(pwbuf));
#else
		pass = getpwnam(temp);
#endif
	}
	el_free(temp);		/* value no more needed */
	if (pass == NULL)
		return strdup(txt);

	/* update pointer txt to point at string immedially following */
	/* first slash */
	txt += len;

	len = strlen(pass->pw_dir) + 1 + strlen(txt) + 1;
	temp = el_malloc(len * sizeof(*temp));
	if (temp == NULL)
		return NULL;
	(void)snprintf(temp, len, "%s/%s", pass->pw_dir, txt);

	return temp;
}
Ejemplo n.º 16
0
/*
 * Complete the word at or before point,
 * 'what_to_do' says what to do with the completion.
 * \t   means do standard completion.
 * `?' means list the possible completions.
 * `*' means insert all of the possible completions.
 * `!' means to do standard completion, and list all possible completions if
 * there is more than one.
 *
 * Note: '*' support is not implemented
 *       '!' could never be invoked
 */
int
fn_complete(EditLine *el,
	char *(*complet_func)(const char *, int),
	char **(*attempted_completion_function)(const char *, int, int),
	const Char *word_break, const Char *special_prefixes,
	const char *(*app_func)(const char *), size_t query_items,
	int *completion_type, int *over, int *point, int *end)
{
	const TYPE(LineInfo) *li;
	Char *temp;
        char **matches;
	const Char *ctemp;
	size_t len;
	int what_to_do = '\t';
	int retval = CC_NORM;

	if (el->el_state.lastcmd == el->el_state.thiscmd)
		what_to_do = '?';

	/* readline's rl_complete() has to be told what we did... */
	if (completion_type != NULL)
		*completion_type = what_to_do;

	if (!complet_func)
		complet_func = fn_filename_completion_function;
	if (!app_func)
		app_func = append_char_function;

	/* We now look backwards for the start of a filename/variable word */
	li = FUN(el,line)(el);
	ctemp = li->cursor;
	while (ctemp > li->buffer
	    && !Strchr(word_break, ctemp[-1])
	    && (!special_prefixes || !Strchr(special_prefixes, ctemp[-1]) ) )
		ctemp--;

	len = (size_t)(li->cursor - ctemp);
	temp = el_malloc((len + 1) * sizeof(*temp));
	(void)Strncpy(temp, ctemp, len);
	temp[len] = '\0';

	/* these can be used by function called in completion_matches() */
	/* or (*attempted_completion_function)() */
	if (point != NULL)
		*point = (int)(li->cursor - li->buffer);
	if (end != NULL)
		*end = (int)(li->lastchar - li->buffer);

	if (attempted_completion_function) {
		int cur_off = (int)(li->cursor - li->buffer);
		matches = (*attempted_completion_function)(
		    ct_encode_string(temp, &el->el_scratch),
		    cur_off - (int)len, cur_off);
	} else
		matches = NULL;
	if (!attempted_completion_function || 
	    (over != NULL && !*over && !matches))
		matches = completion_matches(
		    ct_encode_string(temp, &el->el_scratch), complet_func);

	if (over != NULL)
		*over = 0;

	if (matches) {
		int i;
		size_t matches_num, maxlen, match_len, match_display=1;

		retval = CC_REFRESH;
		/*
		 * Only replace the completed string with common part of
		 * possible matches if there is possible completion.
		 */
		if (matches[0][0] != '\0') {
			el_deletestr(el, (int) len);
			FUN(el,insertstr)(el,
			    ct_decode_string(matches[0], &el->el_scratch));
		}

		if (what_to_do == '?')
			goto display_matches;

		if (matches[2] == NULL &&
		    (matches[1] == NULL || strcmp(matches[0], matches[1]) == 0)) {
			/*
			 * We found exact match. Add a space after
			 * it, unless we do filename completion and the
			 * object is a directory.
			 */
			FUN(el,insertstr)(el,
			    ct_decode_string((*app_func)(matches[0]),
			    &el->el_scratch));
		} else if (what_to_do == '!') {
    display_matches:
			/*
			 * More than one match and requested to list possible
			 * matches.
			 */

			for(i = 1, maxlen = 0; matches[i]; i++) {
				match_len = strlen(matches[i]);
				if (match_len > maxlen)
					maxlen = match_len;
			}
			/* matches[1] through matches[i-1] are available */
			matches_num = (size_t)(i - 1);
				
			/* newline to get on next line from command line */
			(void)fprintf(el->el_outfile, "\n");

			/*
			 * If there are too many items, ask user for display
			 * confirmation.
			 */
			if (matches_num > query_items) {
				(void)fprintf(el->el_outfile,
				    "Display all %zu possibilities? (y or n) ",
				    matches_num);
				(void)fflush(el->el_outfile);
				if (getc(stdin) != 'y')
					match_display = 0;
				(void)fprintf(el->el_outfile, "\n");
			}

			if (match_display) {
				/*
				 * Interface of this function requires the
				 * strings be matches[1..num-1] for compat.
				 * We have matches_num strings not counting
				 * the prefix in matches[0], so we need to
				 * add 1 to matches_num for the call.
				 */
				fn_display_match_list(el, matches,
				    matches_num+1, maxlen);
			}
			retval = CC_REDISPLAY;
		} else if (matches[0][0]) {
			/*
			 * There was some common match, but the name was
			 * not complete enough. Next tab will print possible
			 * completions.
			 */
			el_beep(el);
		} else {
			/* lcd is not a valid object - further specification */
			/* is needed */
			el_beep(el);
			retval = CC_NORM;
		}

		/* free elements of array and the array itself */
		for (i = 0; matches[i]; i++)
			el_free(matches[i]);
		el_free(matches);
		matches = NULL;
	}
	el_free(temp);
	return retval;
}
Ejemplo n.º 17
0
/*
 * return first found file name starting by the ``text'' or NULL if no
 * such file can be found
 * value of ``state'' is ignored
 *
 * it's caller's responsibility to free returned string
 */
char *
fn_filename_completion_function(const char *text, int state)
{
	static DIR *dir = NULL;
	static char *filename = NULL, *dirname = NULL, *dirpath = NULL;
	static size_t filename_len = 0;
	struct dirent *entry;
	char *temp;
	size_t len;

	if (state == 0 || dir == NULL) {
		temp = strrchr(text, '/');
		if (temp) {
			char *nptr;
			temp++;
			nptr = el_realloc(filename, (strlen(temp) + 1) *
			    sizeof(*nptr));
			if (nptr == NULL) {
				el_free(filename);
				filename = NULL;
				return NULL;
			}
			filename = nptr;
			(void)strcpy(filename, temp);
			len = (size_t)(temp - text);	/* including last slash */

			nptr = el_realloc(dirname, (len + 1) *
			    sizeof(*nptr));
			if (nptr == NULL) {
				el_free(dirname);
				dirname = NULL;
				return NULL;
			}
			dirname = nptr;
			(void)strncpy(dirname, text, len);
			dirname[len] = '\0';
		} else {
			el_free(filename);
			if (*text == 0)
				filename = NULL;
			else {
				filename = strdup(text);
				if (filename == NULL)
					return NULL;
			}
			el_free(dirname);
			dirname = NULL;
		}

		if (dir != NULL) {
			(void)closedir(dir);
			dir = NULL;
		}

		/* support for ``~user'' syntax */

		el_free(dirpath);
		dirpath = NULL;
		if (dirname == NULL) {
			if ((dirname = strdup("")) == NULL)
				return NULL;
			dirpath = strdup("./");
		} else if (*dirname == '~')
			dirpath = fn_tilde_expand(dirname);
		else
			dirpath = strdup(dirname);

		if (dirpath == NULL)
			return NULL;

		dir = opendir(dirpath);
		if (!dir)
			return NULL;	/* cannot open the directory */

		/* will be used in cycle */
		filename_len = filename ? strlen(filename) : 0;
	}

	/* find the match */
	while ((entry = readdir(dir)) != NULL) {
		/* skip . and .. */
		if (entry->d_name[0] == '.' && (!entry->d_name[1]
		    || (entry->d_name[1] == '.' && !entry->d_name[2])))
			continue;
		if (filename_len == 0)
			break;
		/* otherwise, get first entry where first */
		/* filename_len characters are equal	  */
		if (entry->d_name[0] == filename[0]
          /* Some dirents have d_namlen, but it is not portable. */
		    && strlen(entry->d_name) >= filename_len
		    && strncmp(entry->d_name, filename,
			filename_len) == 0)
			break;
	}

	if (entry) {		/* match found */

       /* Some dirents have d_namlen, but it is not portable. */
		len = strlen(entry->d_name);

		len = strlen(dirname) + len + 1;
		temp = el_malloc(len * sizeof(*temp));
		if (temp == NULL)
			return NULL;
		(void)snprintf(temp, len, "%s%s", dirname, entry->d_name);
	} else {
		(void)closedir(dir);
		dir = NULL;
		temp = NULL;
	}

	return temp;
}
Ejemplo n.º 18
0
/* vi_histedit():
 *	Vi edit history line with vi
 *	[v]
 */
libedit_private el_action_t
/*ARGSUSED*/
vi_histedit(EditLine *el, wint_t c __attribute__((__unused__)))
{
	int fd;
	pid_t pid;
	ssize_t st;
	int status;
	char tempfile[] = "/tmp/histedit.XXXXXXXXXX";
	char *cp = NULL;
	size_t len;
	wchar_t *line = NULL;

	if (el->el_state.doingarg) {
		if (vi_to_history_line(el, 0) == CC_ERROR)
			return CC_ERROR;
	}

	fd = mkstemp(tempfile);
	if (fd < 0)
		return CC_ERROR;
	len = (size_t)(el->el_line.lastchar - el->el_line.buffer);
#define TMP_BUFSIZ (EL_BUFSIZ * MB_LEN_MAX)
	cp = el_malloc(TMP_BUFSIZ * sizeof(*cp));
	if (cp == NULL)
		goto error;
	line = el_malloc(len * sizeof(*line) + 1);
	if (line == NULL)
		goto error;
	wcsncpy(line, el->el_line.buffer, len);
	line[len] = '\0';
	wcstombs(cp, line, TMP_BUFSIZ - 1);
	cp[TMP_BUFSIZ - 1] = '\0';
	len = strlen(cp);
	write(fd, cp, len);
	write(fd, "\n", (size_t)1);
	pid = fork();
	switch (pid) {
	case -1:
		goto error;
	case 0:
		close(fd);
		execlp("vi", "vi", tempfile, (char *)NULL);
		exit(0);
		/*NOTREACHED*/
	default:
		while (waitpid(pid, &status, 0) != pid)
			continue;
		lseek(fd, (off_t)0, SEEK_SET);
		st = read(fd, cp, TMP_BUFSIZ - 1);
		if (st > 0) {
			cp[st] = '\0';
			len = (size_t)(el->el_line.limit - el->el_line.buffer);
			len = mbstowcs(el->el_line.buffer, cp, len);
			if (len > 0 && el->el_line.buffer[len - 1] == '\n')
				--len;
		}
		else
			len = 0;
                el->el_line.cursor = el->el_line.buffer;
                el->el_line.lastchar = el->el_line.buffer + len;
		el_free(cp);
                el_free(line);
		break;
	}

	close(fd);
	unlink(tempfile);
	/* return CC_REFRESH; */
	return ed_newline(el, 0);
error:
	el_free(line);
	el_free(cp);
	close(fd);
	unlink(tempfile);
	return CC_ERROR;
}
Ejemplo n.º 19
0
Archivo: cgcs.c Proyecto: Abscissa/dmd
STATIC void ecom(elem **pe)
{ int i,op,hcstopsave;
  unsigned hash;
  elem *e,*ehash;
  tym_t tym;

  e = *pe;
  assert(e);
  elem_debug(e);
#ifdef DEBUG
  assert(e->Ecount == 0);
  //assert(e->Ecomsub == 0);
#endif
  tym = tybasic(e->Ety);
  op = e->Eoper;
  switch (op)
  {
    case OPconst:
    case OPvar:
    case OPrelconst:
        break;
    case OPstreq:
    case OPpostinc:
    case OPpostdec:
    case OPeq:
    case OPaddass:
    case OPminass:
    case OPmulass:
    case OPdivass:
    case OPmodass:
    case OPshrass:
    case OPashrass:
    case OPshlass:
    case OPandass:
    case OPxorass:
    case OPorass:
#if TX86
        /* Reverse order of evaluation for double op=. This is so that  */
        /* the pushing of the address of the second operand is easier.  */
        /* However, with the 8087 we don't need the kludge.             */
        if (op != OPeq && tym == TYdouble && !config.inline8087)
        {       if (EOP(e->E1))
                        ecom(&e->E1->E1);
                ecom(&e->E2);
        }
        else
#endif
        {
            /* Don't mark the increment of an i++ or i-- as a CSE, if it */
            /* can be done with an INC or DEC instruction.               */
            if (!(OTpost(op) && elemisone(e->E2)))
                ecom(&e->E2);           /* evaluate 2nd operand first   */
    case OPnegass:
            if (EOP(e->E1))             /* if lvalue is an operator     */
            {
#ifdef DEBUG
                if (e->E1->Eoper != OPind)
                    elem_print(e);
#endif
                assert(e->E1->Eoper == OPind);
                ecom(&(e->E1->E1));
            }
        }
        touchlvalue(e->E1);
        if (!OTpost(op))                /* lvalue of i++ or i-- is not a cse*/
        {
            hash = cs_comphash(e->E1);
            vec_setbit(hash % CSVECDIM,csvec);
            addhcstab(e->E1,hash);              // add lvalue to hcstab[]
        }
        return;

    case OPbtc:
    case OPbts:
    case OPbtr:
        ecom(&e->E1);
        ecom(&e->E2);
        touchfunc(0);                   // indirect assignment
        return;

    case OPandand:
    case OPoror:
        ecom(&e->E1);
        hcstopsave = hcstop;
        ecom(&e->E2);
        hcstop = hcstopsave;            /* no common subs by E2         */
        return;                         /* if comsub then logexp() will */
                                        /* break                        */
    case OPcond:
        ecom(&e->E1);
        hcstopsave = hcstop;
        ecom(&e->E2->E1);               /* left condition               */
        hcstop = hcstopsave;            /* no common subs by E2         */
        ecom(&e->E2->E2);               /* right condition              */
        hcstop = hcstopsave;            /* no common subs by E2         */
        return;                         /* can't be a common sub        */
    case OPcall:
    case OPcallns:
        ecom(&e->E2);                   /* eval right first             */
        /* FALL-THROUGH */
    case OPucall:
    case OPucallns:
        ecom(&e->E1);
        touchfunc(1);
        return;
    case OPstrpar:                      /* so we don't break logexp()   */
#if TX86
    case OPinp:                 /* never CSE the I/O instruction itself */
#endif
    case OPdctor:
        ecom(&e->E1);
        /* FALL-THROUGH */
    case OPasm:
    case OPstrthis:             // don't CSE these
    case OPframeptr:
    case OPgot:
    case OPctor:
    case OPdtor:
    case OPmark:
        return;

    case OPddtor:
        return;

    case OPparam:
#if TX86
    case OPoutp:
#endif
        ecom(&e->E1);
    case OPinfo:
        ecom(&e->E2);
        return;
    case OPcomma:
    case OPremquo:
        ecom(&e->E1);
        ecom(&e->E2);
        break;
#if TARGET_SEGMENTED
    case OPvp_fp:
    case OPcvp_fp:
        ecom(&e->E1);
        touchaccess(e);
        break;
#endif
    case OPind:
        ecom(&e->E1);
        /* Generally, CSEing a *(double *) results in worse code        */
        if (tyfloating(tym))
            return;
        break;
#if TX86
    case OPstrcpy:
    case OPstrcat:
    case OPmemcpy:
    case OPmemset:
        ecom(&e->E2);
    case OPsetjmp:
        ecom(&e->E1);
        touchfunc(0);
        return;
#endif
    default:                            /* other operators */
#if TX86
#ifdef DEBUG
        if (!EBIN(e)) WROP(e->Eoper);
#endif
        assert(EBIN(e));
    case OPadd:
    case OPmin:
    case OPmul:
    case OPdiv:
    case OPor:
    case OPxor:
    case OPand:
    case OPeqeq:
    case OPne:
    case OPscale:
    case OPyl2x:
    case OPyl2xp1:
        ecom(&e->E1);
        ecom(&e->E2);
        break;
#else
#ifdef DEBUG
        if (!EOP(e)) WROP(e->Eoper);
#endif
        assert(EOP(e));
        ecom(&e->E1);
        if (EBIN(e))
                ecom(&e->E2);           /* eval left first              */
        break;
#endif
    case OPstring:
    case OPaddr:
    case OPbit:
#ifdef DEBUG
        WROP(e->Eoper);
        elem_print(e);
#endif
        assert(0);              /* optelem() should have removed these  */
        /* NOTREACHED */

    // Explicitly list all the unary ops for speed
    case OPnot: case OPcom: case OPneg: case OPuadd:
    case OPabs: case OPsqrt: case OPrndtol: case OPsin: case OPcos: case OPrint:
    case OPpreinc: case OPpredec:
    case OPbool: case OPstrlen: case OPs16_32: case OPu16_32:
    case OPd_s32: case OPd_u32:
    case OPs32_d: case OPu32_d: case OPd_s16: case OPs16_d: case OP32_16:
    case OPd_f: case OPf_d:
    case OPd_ld: case OPld_d:
    case OPc_r: case OPc_i:
    case OPu8_16: case OPs8_16: case OP16_8:
    case OPu32_64: case OPs32_64: case OP64_32: case OPmsw:
    case OPu64_128: case OPs64_128: case OP128_64:
    case OPd_s64: case OPs64_d: case OPd_u64: case OPu64_d:
    case OPstrctor: case OPu16_d: case OPd_u16:
    case OParrow:
    case OPvoid: case OPnullcheck:
    case OPbsf: case OPbsr: case OPbswap:
    case OPld_u64:
#if TARGET_SEGMENTED
    case OPoffset: case OPnp_fp: case OPnp_f16p: case OPf16p_np:
#endif
        ecom(&e->E1);
        break;
    case OPhalt:
        return;
  }

  /* don't CSE structures or unions or volatile stuff   */
  if (tym == TYstruct ||
      tym == TYvoid ||
      e->Ety & mTYvolatile
#if TX86
    // don't CSE doubles if inline 8087 code (code generator can't handle it)
      || (tyfloating(tym) && config.inline8087)
#endif
     )
        return;

  hash = cs_comphash(e);                /* must be AFTER leaves are done */

  /* Search for a match in hcstab[].
   * Search backwards, as most likely matches will be towards the end
   * of the list.
   */

#ifdef DEBUG
  if (debugx) dbg_printf("elem: %p hash: %6d\n",e,hash);
#endif
  int csveci = hash % CSVECDIM;
  if (vec_testbit(csveci,csvec))
  {
    for (i = hcstop; i--;)
    {
#ifdef DEBUG
        if (debugx)
            dbg_printf("i: %2d Hhash: %6d Helem: %p\n",
                i,hcstab[i].Hhash,hcstab[i].Helem);
#endif
        if (hash == hcstab[i].Hhash && (ehash = hcstab[i].Helem) != NULL)
        {
            /* if elems are the same and we still have room for more    */
            if (el_match(e,ehash) && ehash->Ecount < 0xFF)
            {
                /* Make sure leaves are also common subexpressions
                 * to avoid false matches.
                 */
                if (!OTleaf(op))
                {
                    if (!e->E1->Ecount)
                        continue;
                    if (OTbinary(op) && !e->E2->Ecount)
                        continue;
                }
                ehash->Ecount++;
                *pe = ehash;
#ifdef DEBUG
                if (debugx)
                        dbg_printf("**MATCH** %p with %p\n",e,*pe);
#endif
                el_free(e);
                return;
            }
        }
    }
  }
  else
    vec_setbit(csveci,csvec);
  addhcstab(e,hash);                    // add this elem to hcstab[]
}
Ejemplo n.º 20
0
Archivo: glue.c Proyecto: 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
}
Ejemplo n.º 21
0
Archivo: glue.c Proyecto: iteratif/dmd
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
}