view dmd/PragmaDeclaration.d @ 178:e3afd1303184

Many small bugs fixed Made all classes derive from TObject to detect memory leaks (functionality is disabled for now) Began work on overriding backend memory allocations (to avoid memory leaks)
author korDen
date Sun, 17 Oct 2010 07:42:00 +0400
parents 438eaa11eed4
children 0622fff7810a
line wrap: on
line source

module dmd.PragmaDeclaration;

import dmd.common;
import dmd.ArrayTypes;
import dmd.AttribDeclaration;
import dmd.Loc;
import dmd.Identifier;
import dmd.StringExp;
import dmd.TOK;
import dmd.WANT;
import dmd.Global;
import dmd.Id;
import dmd.Array;
import dmd.Dsymbol;
import dmd.Scope;
import dmd.OutBuffer;
import dmd.HdrGenState;
import dmd.Expression;
import dmd.FuncDeclaration;

import dmd.backend.Util;
import dmd.backend.Symbol;

import core.memory;

class PragmaDeclaration : AttribDeclaration
{
    Expressions args;		// array of Expression's

    this(Loc loc, Identifier ident, Expressions args, Dsymbols decl)
	{
		register();
		super(decl);
		this.loc = loc;
		this.ident = ident;
		this.args = args;
	}

    override Dsymbol syntaxCopy(Dsymbol s)
	{
		//printf("PragmaDeclaration.syntaxCopy(%s)\n", toChars());
		PragmaDeclaration pd;

		assert(!s);
		pd = new PragmaDeclaration(loc, ident, Expression.arraySyntaxCopy(args), Dsymbol.arraySyntaxCopy(decl));
		return pd;
	}
	
    override void semantic(Scope sc)
	{
		// Should be merged with PragmaStatement

		//printf("\tPragmaDeclaration.semantic '%s'\n",toChars());
		if (ident == Id.msg)
		{
			if (args)
			{
				foreach (e; args)
				{
					e = e.semantic(sc);
					e = e.optimize(WANTvalue | WANTinterpret);
					if (e.op == TOKstring)
					{
						auto se = cast(StringExp)e;
						writef("%s", se.toChars()[1..$-2]); // strip the '"'s, TODO: change to original?: /*se.len, cast(char*)se.string_*/
					}
					else
						writef(e.toChars());
				}
				writef("\n");
			}
			goto Lnodecl;
		}
		else if (ident == Id.lib)
		{
			if (!args || args.dim != 1)
				error("string expected for library name");
			else
			{
				auto e = args[0];

				e = e.semantic(sc);
				e = e.optimize(WANTvalue | WANTinterpret);
				args[0] = e;
				if (e.op != TOKstring)
					error("string expected for library name, not '%s'", e.toChars());
				else if (global.params.verbose)
				{
					StringExp se = cast(StringExp)e;
					writef("library   %.*s\n", cast(int)se.len, cast(char*)se.string_);
				}
			}
			goto Lnodecl;
		}
///	version (IN_GCC) {
///		else if (ident == Id.GNU_asm)
///		{
///		if (! args || args.dim != 2)
///			error("identifier and string expected for asm name");
///		else
///		{
///			Expression *e;
///			Declaration *d = null;
///			StringExp *s = null;
///
///			e = (Expression *)args.data[0];
///			e = e.semantic(sc);
///			if (e.op == TOKvar)
///			{
///			d = ((VarExp *)e).var;
///			if (! d.isFuncDeclaration() && ! d.isVarDeclaration())
///				d = null;
///			}
///			if (!d)
///			error("first argument of GNU_asm must be a function or variable declaration");
///
///			e = (Expression *)args.data[1];
///			e = e.semantic(sc);
///			e = e.optimize(WANTvalue);
///			if (e.op == TOKstring && ((StringExp *)e).sz == 1)
///			s = ((StringExp *)e);
///			else
///			error("second argument of GNU_asm must be a char string");
///
///			if (d && s)
///			d.c_ident = Lexer.idPool((char*) s.string);
///		}
///		goto Lnodecl;
///		}
///	}
///version(DMDV2) {
		else if (ident == Id.startaddress)
		{
			if (!args || args.dim != 1)
				error("function name expected for start address");
			else
			{
				auto e = args[0];
				e = e.semantic(sc);
				e = e.optimize(WANTvalue | WANTinterpret);
				args[0] = e;
				Dsymbol sa = getDsymbol(e);
				if (!sa || !sa.isFuncDeclaration())
					error("function name expected for start address, not '%s'", e.toChars());
			}
			goto Lnodecl;
		}
///}
///	version (TARGET_NET) {
///		else if (ident == Lexer.idPool("assembly"))
///		{
///		}
///	} // TARGET_NET
		else if (global.params.ignoreUnsupportedPragmas)
		{
			if (global.params.verbose)
			{
				/* Print unrecognized pragmas
				 */
				writef("pragma    %s", ident.toChars());
				if (args)
				{
					foreach (size_t i, Expression e; args)
					{
						e = e.semantic(sc);
						e = e.optimize(WANTvalue | WANTinterpret);
						if (i == 0)
							writef(" (");
						else
							writef(",");
						writef("%s", e.toChars());
					}
					if (args.dim)
						writef(")");
				}
				writef("\n");
			}
			goto Lnodecl;
		}
		else
			error("unrecognized pragma(%s)", ident.toChars());

		if (decl)
		{
			foreach(Dsymbol s; decl)
				s.semantic(sc);
		}
		return;

	Lnodecl:
		if (decl)
			error("pragma is missing closing ';'");
	}
	
    override void setScope(Scope sc)
	{
version (TARGET_NET) {
    if (ident == Lexer.idPool("assembly"))
    {
        if (!args || args.dim != 1)
        {
            error("pragma has invalid number of arguments");
        }
        else
        {
            Expression e = cast(Expression)args.data[0];
            e = e.semantic(sc);
            e = e.optimize(WANTvalue | WANTinterpret);
            args.data[0] = cast(void*)e;
            if (e.op != TOKstring)
            {
                error("string expected, not '%s'", e.toChars());
            }
            PragmaScope pragma_ = new PragmaScope(this, sc.parent, cast(StringExp)e);

            assert(sc);
            pragma_.setScope(sc);

            //add to module members
            assert(sc.module_);
            assert(sc.module_.members);
            sc.module_.members.push(cast(void*)pragma_);
        }
    }
}
	}
	
    override bool oneMember(Dsymbol* ps)
	{
		*ps = null;
		return true;
	}
	
    override void toCBuffer(OutBuffer buf, HdrGenState* hgs)
	{
		assert(false);
	}
	
    override string kind()
	{
		assert(false);
	}
	
    override void toObjFile(int multiobj)			// compile to .obj file
	{
		if (ident == Id.lib)
		{
			assert(args && args.dim == 1);

			auto e = args[0];

			assert(e.op == TOKstring);

			auto se = cast(StringExp)e;
			char* name = cast(char*)GC.malloc(se.len + 1);
			memcpy(name, se.string_, se.len);
			name[se.len] = 0;
		version (OMFOBJ) {
			/* The OMF format allows library names to be inserted
			 * into the object file. The linker will then automatically
			 * search that library, too.
			 */
			obj_includelib(name);
		} else version (ELFOBJ_OR_MACHOBJ) {
			/* The format does not allow embedded library names,
			 * so instead append the library name to the list to be passed
			 * to the linker.
			 */
			global.params.libfiles.push(cast(void*) name);
		} else {
			error("pragma lib not supported");
		}
		}
///	version (DMDV2) {
		else if (ident == Id.startaddress)
		{
			assert(args && args.dim == 1);
			auto e = args[0];
			Dsymbol sa = getDsymbol(e);
			FuncDeclaration f = sa.isFuncDeclaration();
			assert(f);
			Symbol* s = f.toSymbol();
			obj_startaddress(s);
		}
///	}
		AttribDeclaration.toObjFile(multiobj);
	}
}