view dstep/objc/message.d @ 6:c0cfd40362ee

Fixed the bridge to work with ldc and dmd. Added a couple of hooks to manipulate the source code
author Jacob Carlborg <doob@me.com>
date Wed, 08 Jul 2009 14:29:59 +0200
parents 033d260cfc9b
children 19885b43130e
line wrap: on
line source

/**
 * Copyright: Copyright (c) 2009 Jacob Carlborg.
 * Authors: Jacob Carlborg
 * Version: Initial created: Feb 1, 2009
 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
 */
module dstep.objc.message;

import dstep.internal.Version;
import bindings = dstep.objc.bindings;
import dstep.objc.objc;
import dstep.objc.runtime;

alias void* marg_list;

version (X86)
	const int STRUCT_SIZE_LIMIT = 8;

else version (PPC)
	const int STRUCT_SIZE_LIMIT = 4;

else version (X86_64)
	const int STRUCT_SIZE_LIMIT = 16;

else version (PPC64) // Not sure about this
	const int STRUCT_SIZE_LIMIT = 16;

struct objc_super
{
    id receiver;
    Class super_class;
    
    // for dwt compatibility
    alias super_class cls;
    
	R msgSendSuper (R = id, ARGS...) (SEL op, ARGS args)
	{
		alias extern (C) R function (id, SEL, ARGS) fp;
		return (cast(fp)&bindings.objc_msgSendSuper)(this, op, args);
	}
	
	void msgSendSuper_stret (T, ARGS...) (out T stretAddr, id self, SEL op, ARGS args)
	{		
	    if (T.sizeof > STRUCT_SIZE_LIMIT)
	    {
	    	alias extern (C) void function (T*, id, SEL, ARGS) fp;
	    	(cast(fp)&bindings.objc_msgSendSuper_stret)(&stretAddr, self, op, args);
	    }
	    
	    else
	    {
	    	alias extern (C) T function (id, SEL, ARGS) fp;
	    	stretAddr = (*cast(fp)&bindings.objc_msgSendSuper)(self, op, args);
	    }
	}
}

R objc_msgSend (R = id, ARGS...) (id self, SEL op, ARGS args)
{
	alias extern(C) R function (id, SEL, ARGS) fp;
	return (cast(fp)&bindings.objc_msgSend)(self, op, args);
}

R objc_msgSendSuper (R = id, ARGS...) (objc_super* super_, SEL op, ARGS args)
{
	alias extern(C) R function (objc_super*, SEL, ARGS) fp;
	return (cast(fp)&bindings.objc_msgSendSuper)(super_, op, args);
}

void objc_msgSend_stret (T, ARGS...) (out T stretAddr, id self, SEL op, ARGS args)
{		
    if (T.sizeof > STRUCT_SIZE_LIMIT)
    {
    	alias extern(C) void function (T*, id, SEL, ARGS) fp;
    	(cast(void function (fp))&bindings.objc_msgSend_stret)(&stretAddr, self, op, args);
    }
    
    else
    {
    	alias extern (C) T function (id, SEL, ARGS) fp;
        stretAddr = (*cast(fp)&bindings.objc_msgSend)(self, op, args);
    }
}

static if (X86 || X86_64)
{
	R objc_msgSend_fpret (R = id, ARGS...) (id self, SEL op, ARGS args)
	{
		version (X86_64)
			static assert(!is(R : real), "Only real are legal return value for objc_msgSend_fpret");
		
		else
			static assert(!is(R : double) && !is(R : float), "Only double and float are legal return values for objc_msgSend_fpret");
			
		alias extern (C) R function (id, SEL, ARGS) fp;
		return (cast(fp)&bindings.objc_msgSend_fpret)(self, op, args);
	}
}

R method_invoke (R = id, ARGS...) (id receiver, Method m, ARGS args)
{
	static assert(receiver !is null);
	alias extern (C) R function (id, SEL, ARGS) fp;
	return (cast(fp)&bindings.method_invoke)(receiver, m, args);
}

void method_invoke_stret (ARGS...) (id receiver, Method m, ARGS args)
{
	static assert(receiver !is null);
	alias extern (C) R function (id, SEL, ARGS) fp;
	return (cast(fp)&bindings.method_invoke_stret)(receiver, m, args);
}

R objc_msgSendv (R = id, T) (id self, SEL op, size_t arg_size, T arg_frame)
{
	alias extern (C) R function (id, SEL, size_t, T) fp;
	(cast(fp)&bindings.objc_msgSendv)(self, op, arg_size, arg_frame);
}

void objc_msgSendv_stret (R = id, T) (out T stretAddr, id self, SEL op, size_t arg_size, T arg_frame)
{
    if (R.sizeof > STRUCT_SIZE_LIMIT)
    {
    	alias extern (C) void function (R*, id, SEL, size_t, T) fp;
    	(cast(fp)&bindings.objc_msgSendv_stret)(&stretAddr, self, op, arg_size, arg_frame);
    }
    
    else
    {
    	alias extern (C) R function (id, SEL, size_t, T) fp;
    	stretAddr = (*cast(fp)&bindings.objc_msgSendv)(self, op, arg_size, arg_frame);
    }
}

version (X86)
{
	R objc_msgSendv_fpret (R = id, T) (id self, SEL op, uint arg_size, T arg_frame)
	{
		static assert(!is(R : double) && !is(R : float), "Only double and float are legal return values for objc_msgSendv_fpret");
		alias extern (C) R function (id, SEL, uint, T) fp;
		return (cast(fp)&bindings.objc_msgSendv_fpret)(self, op, arg_size, arg_frame);
	}
}