changeset 67:f708f0452e81

some of the backend/codegen stuff implemented
author korDen
date Mon, 23 Aug 2010 21:21:05 +0400
parents efb1e5bdf63c
children ee3a9f34dc48
files dmd/InExp.d dmd/ModAssignExp.d dmd/ReturnStatement.d dmd/StructInitializer.d dmd/StructLiteralExp.d dmd/TypeAArray.d dmd/TypeInfoTupleDeclaration.d dmd/TypeSArray.d dmd/TypeTypedef.d dmd/UnrolledLoopStatement.d dmd/XorExp.d dmd/backend/dt_t.d dmd/codegen/Util.d
diffstat 13 files changed, 529 insertions(+), 18 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/InExp.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/InExp.d	Mon Aug 23 21:21:05 2010 +0400
@@ -15,6 +15,11 @@
 import dmd.expression.util.arrayTypeCompatible;
 
 import dmd.backend.elem;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+import dmd.backend.OPER;
+import dmd.backend.Symbol;
+import dmd.backend.Util;
 
 class InExp : BinExp
 {
@@ -75,7 +80,31 @@
 
 	elem* toElem(IRState* irs)
 	{
-		assert(false);
+		elem* e;
+		elem* key = e1.toElem(irs);
+		elem* aa = e2.toElem(irs);
+		elem* ep;
+		elem* keyti;
+		TypeAArray taa = cast(TypeAArray)e2.type.toBasetype();
+		
+
+		// set to:
+		//	aaIn(aa, keyti, key);
+
+		if (tybasic(key.Ety) == TYstruct)
+		{
+			key = el_una(OPstrpar, TYstruct, key);
+			key.Enumbytes = key.E1.Enumbytes;
+			assert(key.Enumbytes);
+		}
+
+		Symbol* s = taa.aaGetSymbol("In", 0);
+		keyti = taa.index.getInternalTypeInfo(null).toElem(irs);
+		ep = el_params(key, keyti, aa, null);
+		e = el_bin(OPcall, type.totym(), el_var(s), ep);
+
+		el_setLoc(e,loc);
+		return e;
 	}
 }
 
--- a/dmd/ModAssignExp.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/ModAssignExp.d	Mon Aug 23 21:21:05 2010 +0400
@@ -10,6 +10,7 @@
 import dmd.Identifier;
 import dmd.IRState;
 import dmd.TOK;
+import dmd.backend.OPER;
 import dmd.Id;
 
 import dmd.backend.elem;
@@ -48,6 +49,6 @@
 
     elem* toElem(IRState* irs)
 	{
-		assert(false);
+		return toElemBin(irs,OPmodass);
 	}
 }
--- a/dmd/ReturnStatement.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/ReturnStatement.d	Mon Aug 23 21:21:05 2010 +0400
@@ -34,6 +34,7 @@
 import dmd.VarDeclaration;
 import dmd.GlobalExpressions;
 import dmd.BE;
+
 import dmd.codegen.Util;
 
 import dmd.backend.Blockx;
@@ -44,6 +45,8 @@
 import dmd.backend.mTY;
 import dmd.backend.BC;
 
+import core.stdc.string;
+
 class ReturnStatement : Statement
 {
     Expression exp;
@@ -417,17 +420,15 @@
 				 */
 				if (exp.op == TOK.TOKstructliteral)
 				{	
-					assert(false);
-					/*
-					StructLiteralExp se = cast(StructLiteralExp)exp;
-					char save[(StructLiteralExp).sizeof];
-					memcpy(save, se, sizeof(StructLiteralExp));
+					scope StructLiteralExp se = cast(StructLiteralExp)exp;
+					enum objectSize = __traits(classInstanceSize, StructLiteralExp);
+					ubyte save[objectSize];
+					memcpy(save.ptr, cast(void*)se, objectSize);
 					se.sym = irs.shidden;
 					se.soffset = 0;
 					se.fillHoles = 1;
 					e = exp.toElem(irs);
-					memcpy(se, save, sizeof(StructLiteralExp));
-					*/
+					memcpy(cast(void*)se, save.ptr, objectSize);
 				}
 				else
 					e = exp.toElem(irs);
--- a/dmd/StructInitializer.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/StructInitializer.d	Mon Aug 23 21:21:05 2010 +0400
@@ -2,6 +2,7 @@
 
 import dmd.Initializer;
 import dmd.TOK;
+import dmd.TypeSArray;
 import dmd.FuncLiteralDeclaration;
 import dmd.TypeFunction;
 import dmd.StructDeclaration;
@@ -27,6 +28,7 @@
 import dmd.LINK;
 
 import dmd.backend.dt_t;
+import dmd.backend.Util;
 
 class StructInitializer : Initializer
 {
@@ -219,7 +221,122 @@
 
     dt_t* toDt()
 	{
-		assert(false);
+		scope Array dts = new Array();
+		uint i;
+		uint j;
+		dt_t* dt;
+		dt_t* d;
+		dt_t** pdtend;
+		uint offset;
+
+		//printf("StructInitializer.toDt('%s')\n", toChars());
+		dts.setDim(ad.fields.dim);
+		dts.zero();
+
+		for (i = 0; i < vars.dim; i++)
+		{
+			VarDeclaration v = cast(VarDeclaration)vars.data[i];
+			Initializer val = cast(Initializer)value.data[i];
+
+			//printf("vars[%d] = %s\n", i, v.toChars());
+
+			for (j = 0; 1; j++)
+			{
+				assert(j < dts.dim);
+				//printf(" adfield[%d] = %s\n", j, ((VarDeclaration *)ad.fields.data[j]).toChars());
+				if (cast(VarDeclaration)ad.fields.data[j] == v)
+				{
+					if (dts.data[j])
+						error(loc, "field %s of %s already initialized", v.toChars(), ad.toChars());
+					dts.data[j] = cast(void*)val.toDt();
+					break;
+				}
+			}
+		}
+
+		dt = null;
+		pdtend = &dt;
+		offset = 0;
+		for (j = 0; j < dts.dim; j++)
+		{
+			VarDeclaration v = cast(VarDeclaration)ad.fields.data[j];
+
+			d = cast(dt_t*)dts.data[j];
+			if (!d)
+			{   
+				// An instance specific initializer was not provided.
+				// Look to see if there's a default initializer from the
+				// struct definition
+				if (v.init)
+				{
+					d = v.init.toDt();
+				}
+				else if (v.offset >= offset)
+				{
+					uint k;
+					uint offset2 = v.offset + cast(uint)v.type.size();
+					// Make sure this field does not overlap any explicitly
+					// initialized field.
+					for (k = j + 1; 1; k++)
+					{
+						if (k == dts.dim)		// didn't find any overlap
+						{
+							v.type.toDt(&d);
+							break;
+						}
+						VarDeclaration v2 = cast(VarDeclaration)ad.fields.data[k];
+
+						if (v2.offset < offset2 && dts.data[k])
+							break;			// overlap
+					}
+				}
+			}
+			if (d)
+			{
+				if (v.offset < offset)
+					error(loc, "duplicate union initialization for %s", v.toChars());
+				else
+				{	
+					uint sz = dt_size(d);
+					uint vsz = cast(uint)v.type.size();
+					uint voffset = v.offset;
+
+					uint dim = 1;
+					for (Type vt = v.type.toBasetype();
+						 vt.ty == Tsarray;
+						 vt = vt.nextOf().toBasetype())
+					{   
+						TypeSArray tsa = cast(TypeSArray)vt;
+						dim *= tsa.dim.toInteger();
+					}
+					assert(sz == vsz || sz * dim <= vsz);
+
+					for (size_t k = 0; k < dim; k++)
+					{
+						if (offset < voffset)
+							pdtend = dtnzeros(pdtend, voffset - offset);
+						if (!d)
+						{
+							if (v.init)
+								d = v.init.toDt();
+							else
+								v.type.toDt(&d);
+						}
+						pdtend = dtcat(pdtend, d);
+						d = null;
+						offset = voffset + sz;
+						voffset += vsz / dim;
+						if (sz == vsz)
+							break;
+					}
+				}
+			}
+		}
+		
+		if (offset < ad.structsize)
+			dtnzeros(pdtend, ad.structsize - offset);
+
+		return dt;
 	}
 
     StructInitializer isStructInitializer() { return this; }
--- a/dmd/StructLiteralExp.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/StructLiteralExp.d	Mon Aug 23 21:21:05 2010 +0400
@@ -3,11 +3,14 @@
 import dmd.Expression;
 import dmd.MOD;
 import dmd.TypeStruct;
+import dmd.TypeSArray;
 import dmd.expression.Util;
 import dmd.ErrorExp;
 import dmd.Dsymbol;
 import dmd.VarDeclaration;
 import dmd.StructDeclaration;
+import dmd.FuncDeclaration;
+import dmd.ThisDeclaration;
 import dmd.backend.elem;
 import dmd.InterState;
 import dmd.MATCH;
@@ -27,6 +30,13 @@
 import dmd.ArrayTypes;
 import dmd.TOK;
 
+import dmd.codegen.Util;
+import dmd.backend.Util;
+import dmd.backend.RTLSYM;
+import dmd.backend.TYM;
+import dmd.backend.mTY;
+import dmd.backend.OPER;
+
 
 class StructLiteralExp : Expression
 {
@@ -158,7 +168,169 @@
 
 	elem* toElem(IRState* irs)
 	{
-		assert(false);
+		elem* e;
+		size_t dim;
+
+		//printf("StructLiteralExp.toElem() %s\n", toChars());
+
+		// struct symbol to initialize with the literal
+		Symbol* stmp = sym ? sym : symbol_genauto(sd.type.toCtype());
+
+		e = null;
+
+		if (fillHoles)
+		{
+			/* Initialize all alignment 'holes' to zero.
+			 * Do before initializing fields, as the hole filling process
+			 * can spill over into the fields.
+			 */
+			size_t offset = 0;
+			for (size_t i = 0; i < sd.fields.dim; i++)
+			{
+				Dsymbol s = cast(Dsymbol)sd.fields.data[i];
+				VarDeclaration v = s.isVarDeclaration();
+				assert(v);
+
+				e = el_combine(e, fillHole(stmp, &offset, v.offset, sd.structsize));
+				size_t vend = v.offset + cast(uint)v.type.size();
+				if (offset < vend)
+					offset = vend;
+			}
+			e = el_combine(e, fillHole(stmp, &offset, sd.structsize, sd.structsize));
+		}
+
+		if (elements)
+		{
+			dim = elements.dim;
+			assert(dim <= sd.fields.dim);
+			for (size_t i = 0; i < dim; i++)
+			{   
+				Expression el = cast(Expression)elements.data[i];
+				if (!el)
+					continue;
+
+				Dsymbol s = cast(Dsymbol)sd.fields.data[i];
+				VarDeclaration v = s.isVarDeclaration();
+				assert(v);
+				assert(!v.isThisDeclaration());
+
+				elem* e1;
+				if (tybasic(stmp.Stype.Tty) == TYnptr)
+				{	
+					e1 = el_var(stmp);
+					e1.EV.sp.Voffset = soffset;
+				}
+				else
+				{	
+					e1 = el_ptr(stmp);
+					if (soffset)
+						e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset));
+				}
+				e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset));
+				elem* ec = e1;			// pointer to destination
+
+				elem* ep = el.toElem(irs);
+
+				Type t1b = v.type.toBasetype();
+				Type t2b = el.type.toBasetype();
+				if (t1b.ty == Tsarray)
+				{
+					if (t2b.implicitConvTo(t1b))
+					{
+		///version (DMDV2) {
+						// Determine if postblit is needed
+						int postblit = 0;
+						if (needsPostblit(t1b))
+							postblit = 1;
+
+						if (postblit)
+						{
+							/* Generate:
+							 *	_d_arrayctor(ti, From: ep, To: e1)
+							 */
+							Expression ti = t1b.nextOf().toBasetype().getTypeInfo(null);
+							elem* esize = el_long(TYsize_t, (cast(TypeSArray)t1b).dim.toInteger());
+							e1 = el_pair(TYdarray, esize, e1);
+							ep = el_pair(TYdarray, el_copytree(esize), array_toPtr(el.type, ep));
+							ep = el_params(e1, ep, ti.toElem(irs), null);
+							int rtl = RTLSYM_ARRAYCTOR;
+							e1 = el_bin(OPcall, type.totym(), el_var(rtlsym[rtl]), ep);
+						}
+						else
+		///}
+						{
+							elem* esize = el_long(TYsize_t, t1b.size());
+							ep = array_toPtr(el.type, ep);
+							e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize));
+						}
+					}
+					else
+					{
+						elem* edim = el_long(TYsize_t, t1b.size() / t2b.size());
+						e1 = setArray(e1, edim, t2b, ep, irs, TOKconstruct);
+					}
+				}
+				else
+				{
+					tym_t ty = v.type.totym();
+					e1 = el_una(OPind, ty, e1);
+					if (tybasic(ty) == TYstruct)
+						e1.Enumbytes = cast(uint)v.type.size();
+					e1 = el_bin(OPeq, ty, e1, ep);
+					if (tybasic(ty) == TYstruct)
+					{   
+						e1.Eoper = OPstreq;
+						e1.Enumbytes = cast(uint)v.type.size();
+					}
+version (DMDV2) {
+					/* Call postblit() on e1
+					 */
+					StructDeclaration sd = needsPostblit(v.type);
+					if (sd)
+					{   
+						FuncDeclaration fd = sd.postblit;
+						ec = el_copytree(ec);
+						ec = callfunc(loc, irs, 1, Type.tvoid, ec, sd.type.pointerTo(), fd, fd.type, null, null);
+						e1 = el_bin(OPcomma, ec.Ety, e1, ec);
+					}
+}
+				}
+				e = el_combine(e, e1);
+			}
+		}
+
+version (DMDV2) {
+		if (sd.isnested)
+		{	// Initialize the hidden 'this' pointer
+			assert(sd.fields.dim);
+			Dsymbol s = cast(Dsymbol)sd.fields.data[sd.fields.dim - 1];
+			ThisDeclaration v = s.isThisDeclaration();
+			assert(v);
+
+			elem* e1;
+			if (tybasic(stmp.Stype.Tty) == TYnptr)
+			{   
+				e1 = el_var(stmp);
+				e1.EV.sp.Voffset = soffset;
+			}
+			else
+			{   
+				e1 = el_ptr(stmp);
+				if (soffset)
+					e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset));
+			}
+			e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset));
+			e1 = setEthis(loc, irs, e1, sd);
+
+			e = el_combine(e, e1);
+		}
+}
+
+		elem* ev = el_var(stmp);
+		ev.Enumbytes = sd.structsize;
+		e = el_combine(e, ev);
+		el_setLoc(e,loc);
+		return e;
 	}
 
 	bool checkSideEffect(int flag)
--- a/dmd/TypeAArray.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/TypeAArray.d	Mon Aug 23 21:21:05 2010 +0400
@@ -7,6 +7,7 @@
 import dmd.Expression;
 import dmd.Scope;
 import dmd.Loc;
+import dmd.Global;
 import dmd.Dsymbol;
 import dmd.Type;
 import dmd.TypeSArray;
@@ -31,6 +32,7 @@
 import dmd.backend.LIST;
 import dmd.backend.TYM;
 import dmd.backend.TF;
+import dmd.backend.Classsym;
 import dmd.backend.mTYman;
 
 import core.stdc.stdio;
@@ -434,6 +436,60 @@
 
     type* toCtype()
 	{
-		assert(false);
+		type* t;
+
+		if (ctype)
+			return ctype;
+
+		if (0 && global.params.symdebug)
+		{
+			/* An associative array is represented by:
+			 *	struct AArray { size_t length; void* ptr; }
+			 */
+
+			static Symbol* s;
+
+			if (!s)
+			{
+				s = symbol_calloc("_AArray");
+				s.Sclass = SCstruct;
+				s.Sstruct = struct_calloc();
+				s.Sstruct.Sflags |= 0;
+				s.Sstruct.Salignsize = alignsize();
+				s.Sstruct.Sstructalign = cast(ubyte)global.structalign;
+				s.Sstruct.Sstructsize = cast(uint)size(Loc(0));
+				slist_add(s);
+
+				Symbol* s1 = symbol_name("length", SCmember, Type.tsize_t.toCtype());
+				list_append(&s.Sstruct.Sfldlst, s1);
+
+				Symbol* s2 = symbol_name("data", SCmember, Type.tvoidptr.toCtype());
+				s2.Smemoff = cast(uint)Type.tsize_t.size();
+				list_append(&s.Sstruct.Sfldlst, s2);
+			}
+
+			t = type_alloc(TYstruct);
+			t.Ttag = cast(Classsym*)s;		// structure tag name
+			t.Tcount++;
+			s.Stype = t;
+		}
+		else
+		{
+		if (global.params.symdebug == 1)
+		{
+			/* Generate D symbolic debug info, rather than C
+			 *   Tnext: element type
+			 *   Tkey: key type
+			 */
+			t = type_allocn(TYaarray, next.toCtype());
+			t.Tkey = index.toCtype();
+			t.Tkey.Tcount++;
+		}
+		else
+			t = type_fake(TYaarray);
+		}
+		t.Tcount++;
+		ctype = t;
+		return t;
 	}
 }
--- a/dmd/TypeInfoTupleDeclaration.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/TypeInfoTupleDeclaration.d	Mon Aug 23 21:21:05 2010 +0400
@@ -2,7 +2,16 @@
 
 import dmd.Type;
 import dmd.TypeInfoDeclaration;
+import dmd.WANT;
+import dmd.TypeTuple;
+import dmd.Argument;
+import dmd.Expression;
+import dmd.TY;
+import dmd.backend.TYM;
+import dmd.backend.Symbol;
 import dmd.backend.dt_t;
+import dmd.backend.Util;
+import dmd.codegen.Util;
 
 class TypeInfoTupleDeclaration : TypeInfoDeclaration
 {
@@ -13,6 +22,31 @@
 
     void toDt(dt_t **pdt)
 	{
-		assert(false);
+		//printf("TypeInfoTupleDeclaration.toDt() %s\n", tinfo.toChars());
+		dtxoff(pdt, Type.typeinfotypelist.toVtblSymbol(), 0, TYnptr); // vtbl for TypeInfoInterface
+		dtdword(pdt, 0);			    // monitor
+
+		assert(tinfo.ty == Ttuple);
+
+		TypeTuple tu = cast(TypeTuple)tinfo;
+
+		size_t dim = tu.arguments.dim;
+		dtdword(pdt, dim);			    // elements.length
+
+		dt_t* d = null;
+		for (size_t i = 0; i < dim; i++)
+		{	
+			Argument arg = cast(Argument)tu.arguments.data[i];
+			Expression e = arg.type.getTypeInfo(null);
+			e = e.optimize(WANTvalue);
+			e.toDt(&d);
+		}
+
+		Symbol *s;
+		s = static_sym();
+		s.Sdt = d;
+		outdata(s);
+
+		dtxoff(pdt, s, 0, TYnptr);		    // elements.ptr
 	}
 }
\ No newline at end of file
--- a/dmd/TypeSArray.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/TypeSArray.d	Mon Aug 23 21:21:05 2010 +0400
@@ -306,7 +306,13 @@
 	
     void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
 	{
-		assert(false);
+		if (mod != this.mod)
+		{	
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		next.toCBuffer2(buf, hgs, this.mod);
+		buf.printf("[%s]", dim.toChars());
 	}
 	
     Expression dotExp(Scope sc, Expression e, Identifier ident)
--- a/dmd/TypeTypedef.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/TypeTypedef.d	Mon Aug 23 21:21:05 2010 +0400
@@ -81,7 +81,14 @@
 	
     void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod)
 	{
-		assert(false);
+		//printf("TypeTypedef.toCBuffer2() '%s'\n", sym.toChars());
+		if (mod != this.mod)
+		{	
+			toCBuffer3(buf, hgs, mod);
+			return;
+		}
+		
+		buf.writestring(sym.toChars());
 	}
 	
     Expression dotExp(Scope sc, Expression e, Identifier ident)
--- a/dmd/UnrolledLoopStatement.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/UnrolledLoopStatement.d	Mon Aug 23 21:21:05 2010 +0400
@@ -14,6 +14,11 @@
 import dmd.InlineScanState;
 import dmd.BE;
 
+import dmd.backend.BC;
+import dmd.backend.Blockx;
+import dmd.backend.block;
+import dmd.backend.Util;
+
 class UnrolledLoopStatement : Statement
 {
 	Statements statements;
@@ -115,7 +120,38 @@
 
 	void toIR(IRState* irs)
 	{
-		assert(false);
+		Blockx* blx = irs.blx;
+
+		IRState mystate = IRState(irs, this);
+		mystate.breakBlock = block_calloc(blx);
+
+		block* bpre = blx.curblock;
+		block_next(blx, BCgoto, null);
+
+		block* bdo = blx.curblock;
+		list_append(&bpre.Bsucc, bdo);
+
+		block* bdox;
+
+		size_t dim = statements.dim;
+		for (size_t i = 0 ; i < dim ; i++)
+		{
+			Statement s = cast(Statement)statements.data[i];
+			if (s !is null)
+			{
+				mystate.contBlock = block_calloc(blx);
+
+				s.toIR(&mystate);
+
+				bdox = blx.curblock;
+				block_next(blx, BCgoto, mystate.contBlock);
+				list_append(&bdox.Bsucc, mystate.contBlock);
+			}
+		}
+
+		bdox = blx.curblock;
+		block_next(blx, BCgoto, mystate.breakBlock);
+		list_append(&bdox.Bsucc, mystate.breakBlock);
 	}
 }
 
--- a/dmd/XorExp.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/XorExp.d	Mon Aug 23 21:21:05 2010 +0400
@@ -16,7 +16,8 @@
 import dmd.TOK;
 import dmd.TY;
 
-import dmd.backend.elem;
+import dmd.backend.elem;
+import dmd.backend.OPER;
 import dmd.expression.Util;
 import dmd.expression.Xor;
 
@@ -127,7 +128,7 @@
 
 	elem* toElem(IRState* irs)
 	{
-		assert(false);
+		return toElemBin(irs,OPxor);
 	}
 }
 
--- a/dmd/backend/dt_t.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/backend/dt_t.d	Mon Aug 23 21:21:05 2010 +0400
@@ -39,6 +39,8 @@
     }
 }
 
+extern (C++) extern uint dt_size(dt_t* dtstart);
+
 import std.stdio;
 
 void dumpDt(dt_t* foo)
--- a/dmd/codegen/Util.d	Mon Aug 23 20:38:30 2010 +0400
+++ b/dmd/codegen/Util.d	Mon Aug 23 21:21:05 2010 +0400
@@ -1151,3 +1151,52 @@
     }
     return s.lblock;
 }
+
+/*******************************************
+ * Generate elem to zero fill contents of Symbol stmp
+ * from *poffset..offset2.
+ * May store anywhere from 0..maxoff, as this function
+ * tries to use aligned int stores whereever possible.
+ * Update *poffset to end of initialized hole; *poffset will be >= offset2.
+ */
+
+elem* fillHole(Symbol* stmp, size_t* poffset, size_t offset2, size_t maxoff)
+{   
+	elem* e = null;
+    int basealign = 1;
+
+    while (*poffset < offset2)
+    {   
+		tym_t ty;
+		elem* e1;
+
+		if (tybasic(stmp.Stype.Tty) == TYnptr)
+			e1 = el_var(stmp);
+		else
+			e1 = el_ptr(stmp);
+			
+		if (basealign)
+			*poffset &= ~3;
+			
+		basealign = 1;
+		size_t sz = maxoff - *poffset;
+		switch (sz)
+		{   
+			case 1: ty = TYchar;	break;
+			case 2: ty = TYshort;	break;
+			case 3:
+				ty = TYshort;
+				basealign = 0;
+				break;
+			default:
+				ty = TYlong;
+				break;
+		}
+		e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, *poffset));
+		e1 = el_una(OPind, ty, e1);
+		e1 = el_bin(OPeq, ty, e1, el_long(ty, 0));
+		e = el_combine(e, e1);
+		*poffset += tysize[ty];
+    }
+    return e;
+}
\ No newline at end of file