Beispiel #1
0
/*
 * Create a reference for an extern variable.
 */
static NODE *
picext(NODE *p)
{
	NODE *q, *r;
	struct symtab *sp;
	char *name;

	q = tempnode(gotnr, PTR|VOID, 0, 0);
	name = getexname(p->n_sp);

#ifdef notdef
	struct attr *ga;
	if ((ga = attr_find(p->n_sp->sap, GCC_ATYP_VISIBILITY)) &&
	    strcmp(ga->sarg(0), "hidden") == 0) {
		/* For hidden vars use GOTOFF */
		sp = picsymtab("", name, "@GOTOFF");
		r = xbcon(0, sp, INT);
		q = buildtree(PLUS, q, r);
		q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
		q->n_sp = p->n_sp; /* for init */
		nfree(p);
		return q;
	}
#endif

	sp = picsymtab("", name, "@GOT");
	r = xbcon(0, sp, INT);
	q = buildtree(PLUS, q, r);
	q = block(UMUL, q, 0, PTR|VOID, 0, 0);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */
	nfree(p);
	return q;
}
Beispiel #2
0
static P1ND *
tlsnonpic(P1ND *p)
{
	P1ND *q, *r;
	struct symtab *sp, *sp2;
	int ext = p->n_sp->sclass;
	char *name;

	name = getsoname(p->n_sp);
	sp = picsymtab("", name,
	    ext == EXTERN ? "@INDNTPOFF" : "@NTPOFF");
	q = xbcon(0, sp, INT);
	if (ext == EXTERN)
		q = block(UMUL, q, NIL, PTR|VOID, 0, 0);

	sp2 = lookup("%gs:0", 0);
	sp2->stype = EXTERN|INT;
	r = nametree(sp2);

	q = buildtree(PLUS, q, r);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */

	p1nfree(p);
	return q;
}
Beispiel #3
0
/*
 * Allocate off bits on the stack.  p is a tree that when evaluated
 * is the multiply count for off, t is a storeable node where to write
 * the allocated address.
 */
void
spalloc(NODE *t, NODE *p, OFFSZ off)
{
	NODE *sp;

	p = buildtree(MUL, p, bcon(off/SZCHAR));
	p = buildtree(PLUS, p, bcon(30));
	p = buildtree(AND, p, xbcon(-16, NULL, UNSIGNED));
	p = cast(p, UNSIGNED, 0);

	/* sub the size from sp */
	sp = block(REG, NIL, NIL, UNSIGNED+PTR, 0, 0);
	slval(sp, 0);
	sp->n_rval = STKREG;
	p = (buildtree(MINUSEQ, sp, p));
	ecomp(p);

	/* save the address of sp */
	sp = block(REG, NIL, NIL, PTR+UNSIGNED, t->n_df, t->n_ap);
	slval(sp, 0);
	sp->n_rval = STKREG;
	t->n_type = sp->n_type;
	p = (buildtree(ASSIGN, t, sp)); /* Emit! */
	ecomp(p);

}
Beispiel #4
0
static NODE *
picstatic(NODE *p)
{
	NODE *q, *r;
	struct symtab *sp;

	q = tempnode(gotnr, PTR|VOID, 0, 0);
	if (p->n_sp->slevel > 0) {
		char buf[32];
		if ((p->n_sp->sflags & SMASK) == SSTRING)
			p->n_sp->sflags |= SASG;
		snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset);
		sp = picsymtab("", buf, "@GOT");
	} else {
		sp = picsymtab("", getsoname(p->n_sp), "@GOT");
	}
	
	sp->sclass = STATIC;
	sp->stype = p->n_sp->stype;
	r = xbcon(0, sp, INT);
	q = buildtree(PLUS, q, r);
	q = block(UMUL, q, 0, PTR|VOID, 0, 0);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */
	nfree(p);
	return q;
}
Beispiel #5
0
NODE *
builtin_return_address(const struct bitable *bt, NODE *a)
{
	NODE *f;
	int v;

	if (a->n_op != ICON)
		goto bad;
	v =a->n_lval;
	tfree(a);

	if (v != 0) {
		werror("unsupported argument");
		return xbcon(0, NULL, VOID|PTR);
	}

	f = block(REG, NIL, NIL, INCREF(PTR+CHAR), 0, 0);
	regno(f) = FPREG;
	f = block(UMUL,
		block(PLUS, f,
		    bcon(16), INCREF(PTR+CHAR), 0, 0), NIL, PTR+CHAR, 0, 0);
	f = makety(f, PTR+VOID, 0, 0, 0);

	return f;
bad:
	uerror("bad argument to __builtin_return_address");
	return bcon(0);
}
Beispiel #6
0
/*
 * Get size of object, if possible.
 * Currently does nothing,
 */
static NODE *
builtin_object_size(NODE *f, NODE *a, TWORD rt)
{
	CONSZ v = icons(a->n_right);
	if (v < 0 || v > 3)
		uerror("arg2 must be between 0 and 3");

	tfree(f);
	f = buildtree(COMOP, a->n_left, xbcon(v < 2 ? -1 : 0, NULL, rt));
	nfree(a);
	return f;
}
/*
 * Get size of object, if possible.
 * Currently does nothing,
 */
static NODE *
builtin_object_size(const struct bitable *bt, NODE *a)
{
    CONSZ v = icons(a->n_right);
    NODE *f;

    if (v < 0 || v > 3)
        uerror("arg2 must be between 0 and 3");

    f = buildtree(COMOP, a->n_left, xbcon(v < 2 ? -1 : 0, NULL, bt->rt));
    nfree(a);
    return f;
}
Beispiel #8
0
static P1ND *
import(P1ND *p)
{
	struct attr *ap;
	P1ND *q;
	char *name;
	struct symtab *sp;

	name = getexname(p->n_sp);

	sp = picsymtab("__imp_", name, "");
	q = xbcon(0, sp, PTR+VOID);
	q = block(UMUL, q, 0, PTR|VOID, 0, 0);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */
	p1nfree(p);

	return q;
}
Beispiel #9
0
/*
 * Sanitycheck "new" keyword.
 */
NODE *
cxx_new(NODE *p)
{
	NODE *q = p;
	NODE *t1 = bcon(1);
	int nw = NM_NEW;

	while (p->n_op == LB) {
		nw = NM_NWA;
		t1 = buildtree(MUL, t1, eve(p->n_right));
		p->n_right = bcon(0);
		p = p->n_left;
	}
	if (p->n_op != TYPE)
		uerror("new used illegally");
	t1 = buildtree(MUL, t1, 
	    xbcon(tsize(p->n_type, p->n_df, p->n_ap)/SZCHAR, NULL, INTPTR));
	tfree(q);
	return callftn(decoratename(NULL, nw), t1, NULL);
}
Beispiel #10
0
/*
 * Create a reference for a TLS variable.
 */
static P1ND *
tlspic(P1ND *p)
{
	P1ND *q, *r;
	struct symtab *sp, *sp2;
	char *name;

	/*
	 * creates:
	 *   leal var@TLSGD(%ebx),%eax
	 *   call ___tls_get_addr@PLT
	 */

	/* calc address of var@TLSGD */
	q = tempnode(gotnr, PTR|VOID, 0, 0);
	name = getsoname(p->n_sp);
	sp = picsymtab("", name, "@TLSGD");
	r = xbcon(0, sp, INT);
	q = buildtree(PLUS, q, r);

	/* assign to %eax */
	r = block(REG, NIL, NIL, PTR|VOID, 0, 0);
	r->n_rval = EAX;
	q = buildtree(ASSIGN, r, q);

	/* call ___tls_get_addr */
	sp2 = lookup("___tls_get_addr@PLT", 0);
	sp2->stype = EXTERN|INT|FTN;
	r = nametree(sp2);
	r = buildtree(ADDROF, r, NIL);
	r = block(UCALL, r, NIL, INT, 0, 0);

	/* fusion both parts together */
	q = buildtree(COMOP, q, r);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */

	p1nfree(p);
	return q;
}
Beispiel #11
0
/*
 * Create a reference for a static variable.
 */
static P1ND *
picstatic(P1ND *p)
{
#if defined(ELFABI)

	P1ND *q, *r;
	struct symtab *sp;

	q = tempnode(gotnr, PTR|VOID, 0, 0);
	if (p->n_sp->slevel > 0) {
		char buf[32];
		if ((p->n_sp->sflags & SMASK) == SSTRING)
			p->n_sp->sflags |= SASG;
		snprintf(buf, 32, LABFMT, (int)p->n_sp->soffset);
		sp = picsymtab("", buf, "@GOTOFF");
	} else
		sp = picsymtab("", getsoname(p->n_sp), "@GOTOFF");
	
	sp->sclass = STATIC;
	sp->stype = p->n_sp->stype;
	r = xbcon(0, sp, INT);
	q = buildtree(PLUS, q, r);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */
	p1nfree(p);
	return q;

#elif defined(MACHOABI)

	P1ND *q, *r;
	struct symtab *sp;
	char buf2[256];

	snprintf(buf2, 256, "-L%s$pb",
	    cftnsp->soname ? cftnsp->soname : cftnsp->sname);

	if (p->n_sp->slevel > 0) {
		char buf1[32];
		snprintf(buf1, 32, LABFMT, (int)p->n_sp->soffset);
		sp = picsymtab("", buf1, buf2);
	} else  {
		char *name = getexname(p->n_sp);
		sp = picsymtab("", name, buf2);
	}
	sp->sclass = STATIC;
	sp->stype = p->n_sp->stype;
	q = tempnode(gotnr, PTR+VOID, 0, 0);
	r = xbcon(0, sp, INT);
	q = buildtree(PLUS, q, r);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp;
	p1nfree(p);
	return q;

#else /* defined(PECOFFABI) || defined(AOUTABI) */

	return p;

#endif

}
Beispiel #12
0
/*
 * Create a reference for an extern variable.
 */
static P1ND *
picext(P1ND *p)
{
	struct attr *ap;

#if defined(ELFABI)
	P1ND *q, *r;
	struct symtab *sp;
	char *name;

	q = tempnode(gotnr, PTR|VOID, 0, 0);
	name = getexname(p->n_sp);

#ifdef GCC_COMPAT
	if ((ap = attr_find(p->n_sp->sap, GCC_ATYP_VISIBILITY)) &&
	    strcmp(ap->sarg(0), "hidden") == 0) {
		/* For hidden vars use GOTOFF */
		sp = picsymtab("", name, "@GOTOFF");
		r = xbcon(0, sp, INT);
		q = buildtree(PLUS, q, r);
		q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
		q->n_sp = p->n_sp; /* for init */
		p1nfree(p);
		return q;
	}
#endif

	sp = picsymtab("", name, "@GOT");
#ifdef GCC_COMPAT
	if (attr_find(p->n_sp->sap, GCC_ATYP_STDCALL) != NULL)
		p->n_sp->sflags |= SSTDCALL;
#endif
	sp->sflags = p->n_sp->sflags & SSTDCALL;
	sp->sap = attr_add(p->n_sp->sap, sp->sap);
	r = xbcon(0, sp, INT);
	q = buildtree(PLUS, q, r);
	q = block(UMUL, q, 0, PTR|VOID, 0, 0);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */
	p1nfree(p);
	return q;

#elif defined(MACHOABI)

	P1ND *q, *r;
	struct symtab *sp;
	char buf2[256], *name, *pspn;

	name = getsoname(cftnsp);
	pspn = getexname(p->n_sp);

	if (p->n_sp->sclass == EXTDEF) {
		snprintf(buf2, 256, "-L%s$pb", name);
		sp = picsymtab("", pspn, buf2);
	} else {
		snprintf(buf2, 256, "$non_lazy_ptr-L%s$pb", name);
		sp = picsymtab("L", pspn, buf2);
		addstub(&nlplist, pspn);
	}

	sp->stype = p->n_sp->stype;

	q = tempnode(gotnr, PTR+VOID, 0, 0);
	r = xbcon(0, sp, INT);
	q = buildtree(PLUS, q, r);

	if (p->n_sp->sclass != EXTDEF)
		q = block(UMUL, q, 0, PTR+VOID, 0, 0);
	q = block(UMUL, q, 0, p->n_type, p->n_df, p->n_ap);
	q->n_sp = p->n_sp; /* for init */
	p1nfree(p);
	return q;

#else /* defined(PECOFFABI) || defined(AOUTABI) */

	return p;

#endif

}