FFI relocation

cvs
Slava Pestov 2004-12-25 23:08:20 +00:00
parent 0deedd48f9
commit 54ff898359
23 changed files with 125 additions and 87 deletions

View File

@ -26,6 +26,7 @@
+ ffi:
- figure out how to load an image referring to missing libraries
- is signed -vs- unsigned pointers an issue?
- bitfields in C structs
- SDL_Rect** type
@ -44,6 +45,7 @@
+ kernel:
- do partial objects cause problems?
- profiler is inaccurate: wrong word on cs
- better i/o scheduler
- remove sbufs

View File

@ -1,9 +1,15 @@
! DeJong attractor renderer.
! To run this code, start your interpreter like so:
!
! ./f -libraries:sdl:name=libSDL.so -libraries:sdl-gfx:name=libSDL_gfx.so
! To run this code, bootstrap Factor like so:
!
! Then, enter this at the interpreter prompt:
! ./f boot.image.le32
! -libraries:sdl:name=libSDL.so
! -libraries:sdl-gfx:name=libSDL_gfx.
!
! (But all on one line)
!
! Then, start Factor as usual (./f factor.image) and enter this
! at the listener:
!
! "examples/dejong.factor" run-file
@ -19,6 +25,8 @@ USE: sdl-video
USE: namespaces
USE: math
USE: kernel
USE: test
USE: compiler
SYMBOL: a
SYMBOL: b
@ -58,6 +66,6 @@ SYMBOL: d
<event> event-loop
SDL_Quit
] with-screen ;
] with-screen ; compiled
dejong
[ dejong ] time

View File

@ -1,8 +1,15 @@
! A simple space shooter.
!
! To play the game:
! To run this code, bootstrap Factor like so:
!
! ./f -libraries:sdl:name=libSDL.so -libraries:sdl-gfx:name=libSDL_gfx.so
! ./f boot.image.le32
! -libraries:sdl:name=libSDL.so
! -libraries:sdl-gfx:name=libSDL_gfx.
!
! (But all on one line)
!
! Then, start Factor as usual (./f factor.image) and enter this
! at the listener:
!
! "examples/factoroids.factor" run-file

View File

@ -1,9 +1,15 @@
! Graphical mandelbrot fractal renderer.
! To run this code, start your interpreter like so:
!
! ./f -libraries:sdl:name=libSDL.so -libraries:sdl-gfx:name=libSDL_gfx.so
! To run this code, bootstrap Factor like so:
!
! Then, enter this at the interpreter prompt:
! ./f boot.image.le32
! -libraries:sdl:name=libSDL.so
! -libraries:sdl-gfx:name=libSDL_gfx.
!
! (But all on one line)
!
! Then, start Factor as usual (./f factor.image) and enter this
! at the listener:
!
! "examples/mandel.factor" run-file
@ -50,7 +56,7 @@ USE: test
nip nip
] [
pred >r sq dupd + r> iter
] ifte ; compiled
] ifte ;
: max-color 360 ;
@ -71,17 +77,16 @@ SYMBOL: center
x-inc get * center get real x-inc get width get 2 / * - + >float
r>
y-inc get * center get imaginary y-inc get height get 2 / * - + >float
rect> ; compiled
rect> ;
: render ( -- )
init-mandel
width get height get [
c 0 nb-iter get iter dup 0 = [
drop 0
] [
cols get [ vector-length mod ] keep vector-nth
] ifte
] with-pixels ;
] with-pixels ; compiled
: mandel ( -- )
640 480 32 SDL_HWSURFACE [
@ -89,6 +94,7 @@ SYMBOL: center
0.8 zoom-fact set
-0.65 center set
100 nb-iter set
init-mandel
[ render ] time
"Done." print flush
] with-surface

View File

@ -57,14 +57,6 @@ USE: kernel-internals
init-random
default-cli-args
parse-command-line
os "win32" = "compile" get and [
"kernel32" "kernel32.dll" "stdcall" add-library
"user32" "user32.dll" "stdcall" add-library
"gdi32" "gdi32.dll" "stdcall" add-library
"libc" "msvcrt.dll" "cdecl" add-library
] when
init-smart-terminal
run-user-init ;
@ -89,6 +81,13 @@ init-error-handler
default-cli-args
parse-command-line
os "win32" = "compile" get and [
"kernel32" "kernel32.dll" "stdcall" add-library
"user32" "user32.dll" "stdcall" add-library
"gdi32" "gdi32.dll" "stdcall" add-library
"libc" "msvcrt.dll" "cdecl" add-library
] when
"Compiling system..." print
"compile" get [ compile-all ] when

View File

@ -197,7 +197,6 @@ vocabularies get [
[ "kernel" | "address" ]
[ "alien" | "dlopen" ]
[ "alien" | "dlsym" ]
[ "alien" | "dlsym-self" ]
[ "alien" | "dlclose" ]
[ "alien" | "<alien>" ]
[ "alien" | "<local-alien>" ]

View File

@ -70,11 +70,16 @@ M: alien = ( obj obj -- ? )
: library ( name -- object )
dup [ "libraries" get hash ] when ;
: load-dll ( library -- dll )
"dll" get dup [
drop "name" get dlopen dup "dll" set
] unless ;
: load-dll ( name -- dll )
#! Higher level wrapper around dlopen primitive.
library dup [
[
"dll" get dup [
drop "name" get dlopen dup "dll" set
] unless
] bind
] when ;
: add-library ( library name abi -- )
"libraries" get [
<namespace> [
@ -93,9 +98,6 @@ SYMBOL: #box ( move EAX to datastack )
: library-abi ( library -- abi )
library [ [ "abi" get ] bind ] [ "cdecl" ] ifte* ;
: alien-symbol ( function library -- address )
library [ [ load-dll ] bind dlsym ] [ dlsym-self ] ifte* ;
SYMBOL: #alien-invoke
! These are set in the #alien-invoke dataflow IR node.
@ -149,7 +151,7 @@ SYMBOL: alien-parameters
: linearize-alien ( node -- )
dup linearize-parameters >r
dup [ node-param get ] bind #c-call swons ,
dup [ node-param get car "stdcall" = ] bind
dup [ node-param get car library-abi "stdcall" = ] bind
r> swap [ drop ] [ #cleanup swons , ] ifte
linearize-returns ;

View File

@ -34,12 +34,12 @@ USE: words
USE: lists
USE: math
: DS ( -- address ) "ds" dlsym-self ;
: DS ( -- address ) "ds" f dlsym ;
: absolute-ds ( -- )
#! Add an entry to the relocation table for the 32-bit
#! immediate just compiled.
"ds" f rel-dlsym-self ;
"ds" f f rel-dlsym ;
: POP-DS ( -- )
#! Pop datastack to EAX.
@ -129,17 +129,17 @@ USE: math
] "generator" set-word-property
#c-call [
uncons alien-symbol CALL JUMP-FIXUP
uncons load-dll 2dup dlsym CALL JUMP-FIXUP t rel-dlsym
] "generator" set-word-property
#unbox [
dlsym-self CALL JUMP-FIXUP
dup f dlsym CALL JUMP-FIXUP f t rel-dlsym
EAX PUSH-R
] "generator" set-word-property
#box [
EAX PUSH-R
dlsym-self CALL JUMP-FIXUP
dup f dlsym CALL JUMP-FIXUP f t rel-dlsym
4 ESP R+I
] "generator" set-word-property

View File

@ -52,9 +52,9 @@ SYMBOL: relocation-table
#! If flag is true; relative.
over primitive? [ rel-primitive ] [ 2drop ] ifte ;
: rel-dlsym-self ( name rel/abs -- )
: rel-dlsym ( name dll rel/abs -- )
#! If flag is true; relative.
2 3 ? rel, relocating intern-literal rel, ;
2 3 ? rel, relocating cons intern-literal rel, ;
: rel-address ( -- )
#! Relocate address just compiled.

View File

@ -61,19 +61,19 @@ USE: kernel
nip real succ
] [
nip >rect succ rect>
] ifte ;
] ifte ; inline
: 2times<= ( #{ a b } #{ c d } -- ? )
swap real swap real <= ;
swap real swap real <= ; inline
: (2times) ( limit n quot -- )
pick pick 2times<= [
3drop
] [
rot pick dupd 2times-succ pick 3slip (2times)
] ifte ;
] ifte ; inline
: 2times* ( #{ w h } quot -- )
#! Apply a quotation to each pair of complex numbers
#! #{ a b } such that a < w, b < h.
0 swap (2times) ;
0 swap (2times) ; inline

View File

@ -192,8 +192,7 @@ USE: words
[ set-literal-top " ptr -- " [ [ integer ] [ ] ] ]
[ address " obj -- ptr " [ [ object ] [ integer ] ] ]
[ dlopen " path -- dll " [ [ string ] [ dll ] ] ]
[ dlsym " name dll -- ptr " [ [ string dll ] [ integer ] ] ]
[ dlsym-self " name -- ptr " [ [ string ] [ integer ] ] ]
[ dlsym " name dll -- ptr " [ [ string object ] [ integer ] ] ]
[ dlclose " dll -- " [ [ dll ] [ ] ] ]
[ <alien> " ptr -- alien " [ [ integer ] [ alien ] ] ]
[ <local-alien> " len -- alien " [ [ integer ] [ alien ] ] ]

View File

@ -53,7 +53,7 @@ SYMBOL: surface
>r 3dup bpp set height set width set r>
SDL_SetVideoMode surface set
r> call SDL_Quit
] with-scope ;
] with-scope ; inline
: rgba ( r g b a -- n )
swap 8 shift bitor
@ -71,20 +71,21 @@ SYMBOL: surface
: pixel-step ( quot #{ x y } -- )
tuck >r call >r surface get r> r> >rect rot pixelColor ;
inline
: with-pixels ( w h quot -- )
-rot rect> [ over >r pixel-step r> ] 2times* drop ;
-rot rect> [ over >r pixel-step r> ] 2times* drop ; inline
: with-surface ( quot -- )
#! Execute a quotation, locking the current surface if it
#! is required (eg, hardware surface).
[
surface get dup must-lock-surface? [
dup SDL_LockSurface slip dup SDL_UnlockSurface
dup SDL_LockSurface drop slip dup SDL_UnlockSurface
] [
slip
] ifte SDL_Flip drop
] with-scope ;
] with-scope ; inline
: event-loop ( event -- )
dup SDL_WaitEvent 1 = [

View File

@ -153,7 +153,7 @@ END-STRUCT
"bool" "sdl" "SDL_FillRect"
[ "surface*" "rect*" "uint" ] alien-invoke ;
: SDL_LockSurface ( surface -- )
: SDL_LockSurface ( surface -- ? )
"bool" "sdl" "SDL_LockSurface" [ "surface*" ] alien-invoke ;
: SDL_UnlockSurface ( surface -- )

View File

@ -196,7 +196,7 @@ SYMBOL: sym-test
[ [ 1 | 1 ] ] [ [ get ] infer old-effect ] unit-test
[ [ 1 | 1 ] ] [ [ str>number ] infer old-effect ] unit-test
! [ [ 1 | 1 ] ] [ [ str>number ] infer old-effect ] unit-test
! Type inference

View File

@ -50,7 +50,7 @@ USE: strings
: words ( vocab -- list )
#! Push a list of all words in a vocabulary.
#! Filter empty slots.
vocab hash-values [ ] subset word-sort ;
vocab dup [ hash-values [ ] subset word-sort ] when ;
: each-word ( quot -- )
#! Apply a quotation to each word in the image.
@ -100,20 +100,17 @@ USE: strings
: init-search-path ( -- )
! For files
"scratchpad" "file-in" set
[ "builtins" "syntax" "scratchpad" ] "file-use" set
[ "syntax" "scratchpad" ] "file-use" set
! For interactive
"scratchpad" "in" set
[
"user"
"arithmetic"
"builtins"
"compiler"
"debugger"
"errors"
"files"
"generic"
"hashtables"
"inference"
"inferior"
"interpreter"
"jedit"
"kernel"
@ -125,7 +122,6 @@ USE: strings
"prettyprint"
"processes"
"profiler"
"stack"
"streams"
"stdio"
"strings"
@ -134,7 +130,6 @@ USE: strings
"threads"
"unparser"
"vectors"
"vocabularies"
"words"
"scratchpad"
] "use" set ;

View File

@ -50,7 +50,7 @@ CELL to_cell(CELL x)
return (CELL)fixnum;
break;
case BIGNUM_TYPE:
bignum = to_bignum(dpop());
bignum = to_bignum(x);
if(BIGNUM_NEGATIVE_P(bignum))
{
range_error(F,0,tag_object(bignum),FIXNUM_MAX);
@ -63,6 +63,7 @@ CELL to_cell(CELL x)
return 0;
}
}
/* FFI calls this */
CELL unbox_cell(void)
{

View File

@ -2,20 +2,32 @@
void primitive_dlopen(void)
{
DLL* dll;
F_STRING* path;
maybe_garbage_collection();
dpush(tag_object(ffi_dlopen(untag_string(dpop()))));
path = untag_string(dpop());
dll = allot_object(DLL_TYPE,sizeof(DLL));
dll->path = tag_object(path);
ffi_dlopen(dll);
dpush(tag_object(dll));
}
void primitive_dlsym(void)
{
DLL *dll;
F_STRING *sym;
CELL dll;
F_STRING* sym;
maybe_garbage_collection();
dll = untag_dll(dpop());
dll = dpop();
sym = untag_string(dpop());
dpush(tag_cell(ffi_dlsym(dll, sym)));
dpush(tag_cell((CELL)ffi_dlsym(
dll == F ? NULL : untag_dll(dll),
sym)));
}
void primitive_dlclose(void)
@ -24,12 +36,6 @@ void primitive_dlclose(void)
ffi_dlclose(untag_dll(dpop()));
}
void primitive_dlsym_self(void)
{
maybe_garbage_collection();
dpush(tag_cell(ffi_dlsym(NULL, untag_string(dpop()))));
}
DLL* untag_dll(CELL tagged)
{
DLL* dll = (DLL*)UNTAG(tagged);
@ -148,7 +154,13 @@ void primitive_set_alien_1(void)
void fixup_dll(DLL* dll)
{
dll->dll = NULL;
data_fixup(&dll->path);
ffi_dlopen(dll);
}
void collect_dll(DLL* dll)
{
copy_object(&dll->path);
}
void fixup_alien(ALIEN* alien)

View File

@ -1,5 +1,8 @@
typedef struct {
CELL header;
/* tagged string */
CELL path;
/* OS-specific handle */
void* dll;
} DLL;
@ -18,13 +21,12 @@ INLINE ALIEN* untag_alien(CELL tagged)
return (ALIEN*)UNTAG(tagged);
}
DLL *ffi_dlopen(F_STRING *path);
void ffi_dlopen(DLL *dll);
void *ffi_dlsym(DLL *dll, F_STRING *symbol);
void ffi_dlclose(DLL *dll);
void primitive_dlopen(void);
void primitive_dlsym(void);
void primitive_dlsym_self(void);
void primitive_dlclose(void);
void primitive_alien(void);
void primitive_local_alien(void);

View File

@ -79,6 +79,12 @@ INLINE void collect_object(CELL scan)
case PORT_TYPE:
collect_port((F_PORT*)scan);
break;
case ALIEN_TYPE:
collect_alien((ALIEN*)scan);
break;
case DLL_TYPE:
collect_dll((ALIEN*)scan);
break;
}
}

View File

@ -150,7 +150,6 @@ XT primitives[] = {
primitive_address,
primitive_dlopen,
primitive_dlsym,
primitive_dlsym_self,
primitive_dlclose,
primitive_alien,
primitive_local_alien,

View File

@ -105,8 +105,10 @@ void relocate_primitive(F_REL* rel, bool relative)
void relocate_dlsym(F_REL* rel, bool relative)
{
F_STRING* str = untag_string(get(rel->argument));
put(rel->offset,(CELL)ffi_dlsym(NULL,str)
F_CONS* cons = untag_cons(get(rel->argument));
F_STRING* symbol = untag_string(cons->car);
DLL* dll = (cons->cdr == F ? NULL : untag_dll(cons->cdr));
put(rel->offset,(CELL)ffi_dlsym(dll,symbol)
- (relative ? rel->offset + CELLS : 0));
}
@ -141,11 +143,11 @@ INLINE CELL relocate_code_next(CELL relocating)
case F_ABSOLUTE_PRIMITIVE:
relocate_primitive(rel,false);
break;
case F_RELATIVE_DLSYM_SELF:
case F_RELATIVE_DLSYM:
code_fixup(&rel->argument);
relocate_dlsym(rel,true);
break;
case F_ABSOLUTE_DLSYM_SELF:
case F_ABSOLUTE_DLSYM:
code_fixup(&rel->argument);
relocate_dlsym(rel,false);
break;

View File

@ -11,9 +11,10 @@ typedef enum {
/* arg is a primitive number */
F_RELATIVE_PRIMITIVE,
F_ABSOLUTE_PRIMITIVE,
/* arg is an pointer in the literal table holding a tagged string */
F_RELATIVE_DLSYM_SELF,
F_ABSOLUTE_DLSYM_SELF,
/* arg is a pointer in the literal table hodling a cons where the
car is a symbol string, and the cdr is a dll */
F_RELATIVE_DLSYM,
F_ABSOLUTE_DLSYM,
/* relocate an address to start of code heap */
F_ABSOLUTE
} F_RELTYPE;

View File

@ -1,12 +1,11 @@
#include "../factor.h"
DLL *ffi_dlopen(F_STRING *path)
void ffi_dlopen(DLL* dll)
{
#ifdef FFI
void* dllptr;
DLL* dll;
dllptr = dlopen(to_c_string(path), RTLD_LAZY);
dllptr = dlopen(to_c_string(untag_string(dll->path)), RTLD_LAZY);
if(dllptr == NULL)
{
@ -14,9 +13,7 @@ DLL *ffi_dlopen(F_STRING *path)
from_c_string(dlerror())));
}
dll = allot_object(DLL_TYPE,sizeof(DLL));
dll->dll = dllptr;
return dll;
#else
general_error(ERROR_FFI_DISABLED,F);
#endif