Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mak/COPY
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ COPY=\
$(IMPDIR)\core\internal\string.d \
$(IMPDIR)\core\internal\traits.d \
\
$(IMPDIR)\core\stdc\clang_block.d \
$(IMPDIR)\core\stdc\complex.d \
$(IMPDIR)\core\stdc\config.d \
$(IMPDIR)\core\stdc\ctype.d \
Expand Down
1 change: 1 addition & 0 deletions mak/SRCS
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ SRCS=\
src\core\internal\string.d \
src\core\internal\traits.d \
\
src\core\stdc\clang_block.d \
src\core\stdc\config.d \
src\core\stdc\ctype.d \
src\core\stdc\errno.d \
Expand Down
12 changes: 6 additions & 6 deletions posix.mak
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,11 @@ IMPDIR=import
OPTIONAL_PIC:=$(if $(PIC),-fPIC,)

ifeq (osx,$(OS))
CLANG_BLOCKS:=1
DOTDLL:=.dylib
DOTLIB:=.a
else
CLANG_BLOCKS:=0
DOTDLL:=.so
DOTLIB:=.a
endif
Expand Down Expand Up @@ -90,12 +92,6 @@ SRCS:=$(subst \,/,$(SRCS))

OBJS= $(ROOT)/errno_c.o $(ROOT)/bss_section.o $(ROOT)/threadasm.o

ifeq ($(OS),osx)
ifeq ($(MODEL), 64)
OBJS+=$(ROOT)/osx_tls.o
endif
endif

# build with shared library support
SHARED=$(if $(findstring $(OS),linux freebsd),1,)

Expand Down Expand Up @@ -194,6 +190,10 @@ HAS_ADDITIONAL_TESTS:=$(shell test -d test && echo 1)
ifeq ($(HAS_ADDITIONAL_TESTS),1)
ADDITIONAL_TESTS:=test/init_fini test/exceptions test/coverage test/profile
ADDITIONAL_TESTS+=$(if $(SHARED),test/shared,)

ifeq ($(CLANG_BLOCKS),1)
ADDITIONAL_TESTS+=test/clang_block
endif
endif

.PHONY : unittest
Expand Down
206 changes: 206 additions & 0 deletions src/core/stdc/clang_block.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
/**
* This module contains functionality for interfacing with
* $(LINK2 http://clang.llvm.org/docs/BlockLanguageSpec.html, Clang Blocks).
*
* The examples below first shows a C function, using Clang Blocks, to call and
* then the D code for calling the C function.
*
* Examples:
*
* Basic example of calling a function taking a block with no arguments that
* returns void.
*
* $(CCODE void foo(void (^block)(void));)
*
* Will look like:
*
* ---
* import core.stdc.clang_block;
*
* // The `Block` type is used to represent the Clang block in D
* extern(C) void foo(Block!()* block);
*
* void main()
* {
* // The `block` function is used to initialize an instance of `Block`.
* // A delegate will be passed to the `block` function which will be the
* // body of the block.
* auto b = block({ writeln("foo"); });
* foo(&b);
* }
* ---
*
* Example of calling a function taking a block with arguments that returns
* void.
*
* $(CCODE void foo(void (^block)(int));)
*
* Will look like:
*
* ---
* import core.stdc.clang_block;
*
* // The type parameters to the instantiation of `Block` is first the return
* // type, `void`, and then the parameter types, `int`.
* extern(C) void foo(Block!(void, int)* block);
*
* void main()
* {
* // The delegate to the `block` function cannot use inferred type
* // parameters.
* auto b = block((int a){ writeln(a); });
* foo(&b);
* }
* ---
*
* Example of calling a function taking a block with no arguments that returns
* an int.
*
* $(CCODE void foo(int (^block)(void));)
*
* Will look like:
*
* ---
* import core.stdc.clang_block;
*
* extern(C) void foo(Block!(int)* block);
*
* void main()
* {
* // The return type can be inferred
* auto b = block({ return 3; });
* foo(&b);
* }
* ---
*
* To build on non Apple platforms the C code needs to be compiled using Clang
* and it's required to link with the
* $(LINK2 http://compiler-rt.llvm.org, Blocks runtime). On Debian based
* platforms install the following packages:
* "llvm", "clang" and "libblocksruntime-dev". Example of compiling on Linux:
*
* $(CCODE
* $ clang foo.c -o foo.o
* $ dmd main.d foo.o -L-lBlocksRuntime
* )
*
* Copyright: Copyright Jacob Carlborg 2016.
* License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
* Authors: Jacob Carlborg
* Source: $(DRUNTIMESRC core/_clang_block.d)
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kudos for documentation !

module core.stdc.clang_block;

import core.stdc.config;

/**
* This struct is the D representation of a Clang Block.
*
* Params:
* R = the return type of the block
* Params = the parameter types of the block
*/
struct Block(R = void, Params...)
{
private:

alias extern(C) R function(Block*, Params) Invoke;

void* isa;
int flags;
int reserved = 0;
Invoke invoke;
Descriptor* descriptor;

// Imported variables go here
R delegate(Params) dg;

this(void* isa, int flags, Invoke invoke, R delegate(Params) dg)
{
this.isa = isa;
this.flags = flags;
this.invoke = invoke;
this.dg = dg;
this.descriptor = &.descriptor;
}
}

/**
* Creates a new block that can be passed to a C function expecting a
* Clang Block.
*
* Params:
* R = the return type of the block
* Params = the parameter types of the block
* dg = the body of the block
*
* Returns: the newly created block
*/
Block!(R, Params) block(R, Params...)(R delegate(Params) dg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should function be supported as well ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. I tried to keep it simple. What's required for supporting both, a union? Or should I just force a function pointer into the delegate, i.e. dg.funcptr = ...?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both would work, though the union will complicate things. It's up to you if you want to support it, just though I would raise the point.

{
static if (Params.length == 0)
enum flags = 0x50000000;
else
enum flags = 0x40000000;

return Block!(R, Params)(
&_NSConcreteStackBlock, flags, &invoke!(R, Params), dg
);
}

private:

/*
* The the block implementation specification is available here:
* http://clang.llvm.org/docs/Block-ABI-Apple.html
*/

// Block descriptor
struct Descriptor
{
// null/0
c_ulong reserved;

// Block!(R, Params).sizeof
c_ulong size;

// Optional helper functions
// extern(C) void function(void* dst, void* src) copy_helper;
// extern(C) void function(void* src) dispose_helper;

/*
* Signature of the block, using Objective-C type encoding.
* Seems not to be used.
*/
const(char)* signature;
}

// Block of uninitialized memory used for stack block literals
extern(C) extern __gshared void*[32] _NSConcreteStackBlock;

/*
* Shared block descriptor. Since the descriptor will always look the same we
* can reuse a single descriptor.
*/
__gshared auto descriptor = Descriptor(0, Block!().sizeof);

/*
* The body of a block that the C runtime will call.
*
* The implementation forwards to the delegate stored in the block struct
* containing the real D body.
*
* Since a delegate is used to store the actual D body of the block a single
* body can be shared for all blocks.
*
* Params:
* R = the return type of the block
* Args = the parameter types of the block
* args = the argument that was passed to the block
*
* Returns: whatever the delegate stored in the block returns
*/
extern(C) R invoke(R, Args...)(Block!(R, Args)* block, Args args)
{
return block.dg(args);
}
51 changes: 0 additions & 51 deletions src/rt/osx_tls.c

This file was deleted.

Loading