mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-21 15:05:45 -07:00
File restructure (again)
This commit is contained in:
+17
-5
@@ -4,12 +4,24 @@ Vec2 :: struct {
|
||||
x, y: i64
|
||||
}
|
||||
|
||||
|
||||
main :: proc() {
|
||||
bar :: proc() -> i64 {
|
||||
a := [3]i64{7, 4, 2}
|
||||
v := Vec2{a[0], 2}
|
||||
return v.x
|
||||
foo :: proc() -> i64 {
|
||||
bar :: proc() -> (i64, i64) {
|
||||
a := [3]i64{7, 4, 2}
|
||||
v := Vec2{a[0], 2}
|
||||
return v.x, v.y
|
||||
}
|
||||
|
||||
x, y := bar()
|
||||
|
||||
return x + y
|
||||
}
|
||||
|
||||
bar()
|
||||
test :: proc(s: string) -> string {
|
||||
return s
|
||||
}
|
||||
|
||||
foo()
|
||||
x := test("Hello")
|
||||
}
|
||||
|
||||
+5
-5
@@ -292,11 +292,11 @@ __string_cmp :: proc(a, b : string) -> int {
|
||||
return mem.compare(a.data, b.data, min(a.count, b.count))
|
||||
}
|
||||
|
||||
__string_ne :: proc(a, b : string) -> bool #inline { return !__string_eq(a, b) }
|
||||
__string_lt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) < 0 }
|
||||
__string_gt :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) > 0 }
|
||||
__string_le :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) <= 0 }
|
||||
__string_ge :: proc(a, b : string) -> bool #inline { return __string_cmp(a, b) >= 0 }
|
||||
__string_ne :: proc(a, b: string) -> bool #inline { return !__string_eq(a, b) }
|
||||
__string_lt :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) < 0 }
|
||||
__string_gt :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) > 0 }
|
||||
__string_le :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) <= 0 }
|
||||
__string_ge :: proc(a, b: string) -> bool #inline { return __string_cmp(a, b) >= 0 }
|
||||
|
||||
|
||||
__assert :: proc(file: string, line, column: int, msg: string) #inline {
|
||||
|
||||
@@ -19,6 +19,7 @@ struct Array {
|
||||
};
|
||||
|
||||
template <typename T> void array_init (Array<T> *array, gbAllocator a, isize init_capacity = ARRAY_GROW_FORMULA(0));
|
||||
template <typename T> void array_init_count (Array<T> *array, gbAllocator a, isize count);
|
||||
template <typename T> Array<T> array_make (T *data, isize count, isize capacity);
|
||||
template <typename T> void array_free (Array<T> *array);
|
||||
template <typename T> void array_add (Array<T> *array, T const &t);
|
||||
@@ -37,6 +38,15 @@ void array_init(Array<T> *array, gbAllocator a, isize init_capacity) {
|
||||
array->capacity = init_capacity;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void array_init_count(Array<T> *array, gbAllocator a, isize count) {
|
||||
array->allocator = a;
|
||||
array->data = gb_alloc_array(a, T, count);
|
||||
array->count = count;
|
||||
array->capacity = count;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
Array<T> array_make(T *data, isize count, isize capacity) {
|
||||
Array<T> a = {};
|
||||
|
||||
+23
-6
@@ -150,6 +150,8 @@ struct Type {
|
||||
struct {
|
||||
Entity **variables; // Entity_Variable
|
||||
i32 variable_count;
|
||||
b32 are_offsets_set;
|
||||
i64 * offsets;
|
||||
} Tuple;
|
||||
struct {
|
||||
Scope *scope;
|
||||
@@ -1109,11 +1111,21 @@ i64 *type_set_offsets_of(BaseTypeSizes s, gbAllocator allocator, Entity **fields
|
||||
}
|
||||
|
||||
b32 type_set_offsets(BaseTypeSizes s, gbAllocator allocator, Type *t) {
|
||||
GB_ASSERT(is_type_struct(t));
|
||||
if (!t->Record.struct_are_offsets_set) {
|
||||
t->Record.struct_offsets = type_set_offsets_of(s, allocator, t->Record.fields, t->Record.field_count, t->Record.struct_is_packed);
|
||||
t->Record.struct_are_offsets_set = true;
|
||||
return true;
|
||||
t = base_type(t);
|
||||
if (is_type_struct(t)) {
|
||||
if (!t->Record.struct_are_offsets_set) {
|
||||
t->Record.struct_offsets = type_set_offsets_of(s, allocator, t->Record.fields, t->Record.field_count, t->Record.struct_is_packed);
|
||||
t->Record.struct_are_offsets_set = true;
|
||||
return true;
|
||||
}
|
||||
} else if (is_type_tuple(t)) {
|
||||
if (!t->Tuple.are_offsets_set) {
|
||||
t->Tuple.offsets = type_set_offsets_of(s, allocator, t->Tuple.variables, t->Tuple.variable_count, false);
|
||||
t->Tuple.are_offsets_set = true;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
GB_PANIC("Invalid type for setting offsets");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -1239,7 +1251,12 @@ i64 type_offset_of(BaseTypeSizes s, gbAllocator allocator, Type *t, isize index)
|
||||
if (gb_is_between(index, 0, t->Record.field_count-1)) {
|
||||
return t->Record.struct_offsets[index];
|
||||
}
|
||||
} else if (t->kind == Type_Basic) {
|
||||
} else if (t->kind == Type_Tuple) {
|
||||
type_set_offsets(s, allocator, t);
|
||||
if (gb_is_between(index, 0, t->Tuple.variable_count-1)) {
|
||||
return t->Tuple.offsets[index];
|
||||
}
|
||||
} else if (t->kind == Type_Basic) {
|
||||
if (t->Basic.kind == Basic_string) {
|
||||
switch (index) {
|
||||
case 0: return 0;
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncall
|
||||
File: dyncall/dyncall.h
|
||||
Description: public header for library dyncall
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
dyncall C API
|
||||
|
||||
REVISION
|
||||
2015/07/08 added SYS_PPC64 system call
|
||||
2015/01/16 added SYS_PPC32 system call
|
||||
2007/12/11 initial
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_H
|
||||
#define DYNCALL_H
|
||||
|
||||
#include "dyncall_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct DCCallVM_ DCCallVM;
|
||||
typedef struct DCstruct_ DCstruct;
|
||||
|
||||
/* Supported Calling Convention Modes */
|
||||
|
||||
#define DC_CALL_C_DEFAULT 0
|
||||
#define DC_CALL_C_ELLIPSIS 100
|
||||
#define DC_CALL_C_ELLIPSIS_VARARGS 101
|
||||
#define DC_CALL_C_X86_CDECL 1
|
||||
#define DC_CALL_C_X86_WIN32_STD 2
|
||||
#define DC_CALL_C_X86_WIN32_FAST_MS 3
|
||||
#define DC_CALL_C_X86_WIN32_FAST_GNU 4
|
||||
#define DC_CALL_C_X86_WIN32_THIS_MS 5
|
||||
#define DC_CALL_C_X86_WIN32_THIS_GNU 6
|
||||
#define DC_CALL_C_X64_WIN64 7
|
||||
#define DC_CALL_C_X64_SYSV 8
|
||||
#define DC_CALL_C_PPC32_DARWIN 9
|
||||
#define DC_CALL_C_PPC32_OSX DC_CALL_C_PPC32_DARWIN /* alias */
|
||||
#define DC_CALL_C_ARM_ARM_EABI 10
|
||||
#define DC_CALL_C_ARM_THUMB_EABI 11
|
||||
#define DC_CALL_C_ARM_ARMHF 30
|
||||
#define DC_CALL_C_MIPS32_EABI 12
|
||||
#define DC_CALL_C_MIPS32_PSPSDK DC_CALL_C_MIPS32_EABI /* alias - deprecated. */
|
||||
#define DC_CALL_C_PPC32_SYSV 13
|
||||
#define DC_CALL_C_PPC32_LINUX DC_CALL_C_PPC32_SYSV /* alias */
|
||||
#define DC_CALL_C_ARM_ARM 14
|
||||
#define DC_CALL_C_ARM_THUMB 15
|
||||
#define DC_CALL_C_MIPS32_O32 16
|
||||
#define DC_CALL_C_MIPS64_N32 17
|
||||
#define DC_CALL_C_MIPS64_N64 18
|
||||
#define DC_CALL_C_X86_PLAN9 19
|
||||
#define DC_CALL_C_SPARC32 20
|
||||
#define DC_CALL_C_SPARC64 21
|
||||
#define DC_CALL_C_ARM64 22
|
||||
#define DC_CALL_C_PPC64 23
|
||||
#define DC_CALL_C_PPC64_LINUX DC_CALL_C_PPC64 /* alias */
|
||||
#define DC_CALL_SYS_DEFAULT 200
|
||||
#define DC_CALL_SYS_X86_INT80H_LINUX 201
|
||||
#define DC_CALL_SYS_X86_INT80H_BSD 202
|
||||
#define DC_CALL_SYS_PPC32 210
|
||||
#define DC_CALL_SYS_PPC64 211
|
||||
|
||||
/* Error codes. */
|
||||
|
||||
#define DC_ERROR_NONE 0
|
||||
#define DC_ERROR_UNSUPPORTED_MODE -1
|
||||
|
||||
DC_API DCCallVM* dcNewCallVM (DCsize size);
|
||||
DC_API void dcFree (DCCallVM* vm);
|
||||
DC_API void dcReset (DCCallVM* vm);
|
||||
|
||||
DC_API void dcMode (DCCallVM* vm, DCint mode);
|
||||
|
||||
DC_API void dcArgBool (DCCallVM* vm, DCbool value);
|
||||
DC_API void dcArgChar (DCCallVM* vm, DCchar value);
|
||||
DC_API void dcArgShort (DCCallVM* vm, DCshort value);
|
||||
DC_API void dcArgInt (DCCallVM* vm, DCint value);
|
||||
DC_API void dcArgLong (DCCallVM* vm, DClong value);
|
||||
DC_API void dcArgLongLong (DCCallVM* vm, DClonglong value);
|
||||
DC_API void dcArgFloat (DCCallVM* vm, DCfloat value);
|
||||
DC_API void dcArgDouble (DCCallVM* vm, DCdouble value);
|
||||
DC_API void dcArgPointer (DCCallVM* vm, DCpointer value);
|
||||
DC_API void dcArgStruct (DCCallVM* vm, DCstruct* s, DCpointer value);
|
||||
|
||||
DC_API void dcCallVoid (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DCbool dcCallBool (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DCchar dcCallChar (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DCshort dcCallShort (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DCint dcCallInt (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DClong dcCallLong (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DClonglong dcCallLongLong (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DCfloat dcCallFloat (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DCdouble dcCallDouble (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API DCpointer dcCallPointer (DCCallVM* vm, DCpointer funcptr);
|
||||
DC_API void dcCallStruct (DCCallVM* vm, DCpointer funcptr, DCstruct* s, DCpointer returnValue);
|
||||
|
||||
DC_API DCint dcGetError (DCCallVM* vm);
|
||||
|
||||
#define DEFAULT_ALIGNMENT 0
|
||||
DC_API DCstruct* dcNewStruct (DCsize fieldCount, DCint alignment);
|
||||
DC_API void dcStructField (DCstruct* s, DCint type, DCint alignment, DCsize arrayLength);
|
||||
DC_API void dcSubStruct (DCstruct* s, DCsize fieldCount, DCint alignment, DCsize arrayLength);
|
||||
/* Each dcNewStruct or dcSubStruct call must be paired with a dcCloseStruct. */
|
||||
DC_API void dcCloseStruct (DCstruct* s);
|
||||
DC_API DCsize dcStructSize (DCstruct* s);
|
||||
DC_API DCsize dcStructAlignment(DCstruct* s);
|
||||
DC_API void dcFreeStruct (DCstruct* s);
|
||||
|
||||
DC_API DCstruct* dcDefineStruct (const char* signature);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DYNCALL_H */
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_alloc_wx.h
|
||||
Description: Allocate write/executable memory - Interface
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_ALLOC_WX_HPP
|
||||
#define DYNCALL_ALLOC_WX_HPP
|
||||
|
||||
#include "dyncall_types.h"
|
||||
|
||||
typedef int DCerror;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DCerror dcAllocWX(DCsize size, void** p);
|
||||
void dcFreeWX (void* p, DCsize size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* DYNCALL_ALLOC_WX_HPP */
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args.h
|
||||
Description: Callback's Arguments VM - Interface
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_ARGS_H
|
||||
#define DYNCALL_ARGS_H
|
||||
|
||||
/*
|
||||
* dyncall args C API
|
||||
*
|
||||
* dyncall args provides serialized access to arguments of a function call.
|
||||
* related concepts: callback
|
||||
*
|
||||
*/
|
||||
|
||||
#include "dyncall.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct DCArgs DCArgs;
|
||||
|
||||
DC_API DCbool dcbArgBool (DCArgs*);
|
||||
DC_API DCchar dcbArgChar (DCArgs*);
|
||||
DC_API DCshort dcbArgShort (DCArgs*);
|
||||
DC_API DCint dcbArgInt (DCArgs*);
|
||||
DC_API DClong dcbArgLong (DCArgs*);
|
||||
DC_API DClonglong dcbArgLongLong (DCArgs*);
|
||||
DC_API DCuchar dcbArgUChar (DCArgs*);
|
||||
DC_API DCushort dcbArgUShort (DCArgs*);
|
||||
DC_API DCuint dcbArgUInt (DCArgs*);
|
||||
DC_API DCulong dcbArgULong (DCArgs*);
|
||||
DC_API DCulonglong dcbArgULongLong(DCArgs*);
|
||||
DC_API DCfloat dcbArgFloat (DCArgs*);
|
||||
DC_API DCdouble dcbArgDouble (DCArgs*);
|
||||
DC_API DCpointer dcbArgPointer (DCArgs*);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DYNCALL_ARGS_H */
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_arm32_arm.h
|
||||
Description: Callback's Arguments VM - Header for ARM32 (ARM mode)
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALLBACK_ARGS_ARM32_ARM_H
|
||||
#define DYNCALLBACK_ARGS_ARM32_ARM_H
|
||||
|
||||
#include "dyncall_args.h"
|
||||
|
||||
struct DCArgs
|
||||
{
|
||||
/* Don't change order! */
|
||||
long reg_data[4];
|
||||
int reg_count;
|
||||
long* stack_ptr;
|
||||
#if defined(DC__ABI_ARM_HF)
|
||||
DCfloat f[16];
|
||||
int freg_count;
|
||||
int dreg_count;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* DYNCALLBACK_ARGS_ARM32_ARM_H */
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_arm32_thumb.h
|
||||
Description: Callback's Arguments VM - Header for ARM32 (THUMB mode)
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALLBACK_ARGS_ARM32_THUMB_H
|
||||
#define DYNCALLBACK_ARGS_ARM32_THUMB_H
|
||||
|
||||
#include "dyncall_args_arm32_arm.h" /* Uses same code as ARM mode. */
|
||||
|
||||
#endif /* DYNCALLBACK_ARGS_ARM32_THUMB_H */
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_mips.h
|
||||
Description: Callback's Arguments VM - Header for MIPS
|
||||
License:
|
||||
|
||||
Copyright (c) 2013-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALLBACK_ARGS_MIPS_H
|
||||
#define DYNCALLBACK_ARGS_MIPS_H
|
||||
|
||||
#include "dyncall_args.h"
|
||||
|
||||
struct DCArgs
|
||||
{
|
||||
int ireg_data[8];
|
||||
float freg_data[8];
|
||||
int ireg_count;
|
||||
int freg_count;
|
||||
unsigned char* stackptr;
|
||||
};
|
||||
|
||||
#endif /* DYNCALLBACK_ARGS_MIPS_H */
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_ppc32.h
|
||||
Description: Callback's Arguments VM - Header for ppc32
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALLBACK_ARGS_PPC32_H
|
||||
#define DYNCALLBACK_ARGS_PPC32_H
|
||||
|
||||
#include "dyncall_args.h"
|
||||
|
||||
/* Common Args iterator for Apple and System V ABI. */
|
||||
|
||||
struct DCArgs
|
||||
{
|
||||
int ireg_data[8]; /* offset: 0 size: 4*8 = 32 */
|
||||
double freg_data[13]; /* offset: 32 size: 8*13= 104 */
|
||||
unsigned char* stackptr; /* offset: 136 size: 4 */
|
||||
int ireg_count; /* offset: 140 size: 4 */
|
||||
int freg_count; /* offset: 144 size: 4 */
|
||||
}; /* total size: 148 */
|
||||
|
||||
#endif /* DYNCALLBACK_ARGS_PPC32_H */
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_ppc64.h
|
||||
Description: Callback's Arguments VM - Header for ppc64
|
||||
License:
|
||||
|
||||
Copyright (c) 2014-2015 Masanori Mitsugi <mitsugi@linux.vnet.ibm.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALLBACK_ARGS_PPC64_H
|
||||
#define DYNCALLBACK_ARGS_PPC64_H
|
||||
|
||||
#include "dyncall_args.h"
|
||||
|
||||
struct DCArgs
|
||||
{
|
||||
long long ireg_data[8];
|
||||
double freg_data[13];
|
||||
unsigned char* stackptr;
|
||||
int ireg_count;
|
||||
int freg_count;
|
||||
};
|
||||
|
||||
#endif /* DYNCALLBACK_ARGS_PPC64_H */
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_sparc32.h
|
||||
Description: Callback's Arguments VM - Header for sparc32
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALLBACK_ARGS_SPARC32_H
|
||||
#define DYNCALLBACK_ARGS_SPARC32_H
|
||||
|
||||
#include "dyncall_args.h"
|
||||
|
||||
struct DCArgs
|
||||
{
|
||||
int dummy;
|
||||
};
|
||||
|
||||
#endif /* DYNCALLBACK_ARGS_SPARC32_H */
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_sparc64.h
|
||||
Description: Callback's Arguments VM - Header for sparc32 - not yet
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALLBACK_ARGS_SPARC64_H
|
||||
#define DYNCALLBACK_ARGS_SPARC64_H
|
||||
|
||||
#include "dyncall_args.h"
|
||||
|
||||
struct DCArgs
|
||||
{
|
||||
int dummy;
|
||||
};
|
||||
|
||||
#endif /* DYNCALLBACK_ARGS_SPARC64_H */
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_x64.h
|
||||
Description: Callback's Arguments VM - Header for x64
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALLBACK_ARGS_X64_H
|
||||
#define DYNCALLBACK_ARGS_X64_H
|
||||
|
||||
#include "dyncall_args.h"
|
||||
#include "dyncall_callvm_x64.h" /* reuse structures */
|
||||
|
||||
|
||||
struct DCArgs
|
||||
{
|
||||
/* state */
|
||||
int64* stack_ptr;
|
||||
DCRegCount_x64 reg_count; /* @@@ win64 version should maybe force alignment to 8 in order to be secure */
|
||||
|
||||
/* reg data */
|
||||
DCRegData_x64_s reg_data;
|
||||
};
|
||||
|
||||
#endif /* DYNCALLBACK_ARGS_X64_H */
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_args_x86.h
|
||||
Description: Callback's Arguments VM - Header for x86
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef DYNCALL_ARGS_X86_H_
|
||||
#define DYNCALL_ARGS_X86_H_
|
||||
|
||||
#include "dyncall_args.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
DCint (*i32)(DCArgs*);
|
||||
DClonglong (*i64)(DCArgs*);
|
||||
DCfloat (*f32)(DCArgs*);
|
||||
DCdouble (*f64)(DCArgs*);
|
||||
} DCArgsVT;
|
||||
|
||||
extern DCArgsVT dcArgsVT_default;
|
||||
extern DCArgsVT dcArgsVT_this_ms;
|
||||
extern DCArgsVT dcArgsVT_fast_ms;
|
||||
extern DCArgsVT dcArgsVT_fast_gnu;
|
||||
|
||||
struct DCArgs
|
||||
{
|
||||
/* callmode */
|
||||
DCArgsVT* vt;
|
||||
|
||||
/* state */
|
||||
int* stack_ptr;
|
||||
|
||||
/* fast data / 'this-ptr' info */
|
||||
int fast_data[2];
|
||||
int fast_count;
|
||||
};
|
||||
|
||||
#endif /* DYNCALL_ARGS_X86_H_ */
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback.h
|
||||
Description: Callback - Interface
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_H
|
||||
#define DYNCALL_CALLBACK_H
|
||||
|
||||
#include "dyncall_args.h"
|
||||
#include "dyncall_signature.h"
|
||||
#include "dyncall_value.h"
|
||||
|
||||
typedef struct DCCallback DCCallback;
|
||||
|
||||
// TODO: return value is the type encoded as a signature char (character of the set [vBcCsSiIjJlLfd]).
|
||||
|
||||
typedef char (DCCallbackHandler)(DCCallback* pcb, DCArgs* args, DCValue* result, void* userdata);
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DCCallback* dcbNewCallback(const char* signature, DCCallbackHandler* funcptr, void* userdata);
|
||||
void dcbInitCallback(DCCallback* pcb, const char* signature, DCCallbackHandler* handler, void* userdata);
|
||||
void dcbFreeCallback(DCCallback* pcb);
|
||||
void* dcbGetUserData (DCCallback* pcb);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_H */
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback_arm32_arm.h
|
||||
Description: Callback - Header for ARM32 (ARM mode)
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_ARM32_ARM_H_
|
||||
#define DYNCALL_CALLBACK_ARM32_ARM_H_
|
||||
|
||||
#include "dyncall_callback.h"
|
||||
|
||||
#include "dyncall_thunk.h"
|
||||
#include "dyncall_args_arm32_arm.h"
|
||||
|
||||
|
||||
struct DCCallback
|
||||
{
|
||||
DCThunk thunk; // offset 0
|
||||
DCCallbackHandler* handler; // offset 12
|
||||
void* userdata; // offset 16
|
||||
};
|
||||
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_ARM32_ARM_H_ */
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback_arm32_thumb.h
|
||||
Description: Callback - Header for ARM32 (THUMB mode)
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_ARM32_THUMB_H_
|
||||
#define DYNCALL_CALLBACK_ARM32_THUMB_H_
|
||||
|
||||
#include "dyncall_callback_arm32_arm.h" /* Uses same code as ARM mode. */
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_ARM32_THUMB_H_ */
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback_mips.h
|
||||
Description: Callback - Header for MIPS
|
||||
License:
|
||||
|
||||
Copyright (c) 2013-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_MIPS_H
|
||||
#define DYNCALL_CALLBACK_MIPS_H
|
||||
|
||||
#include "dyncall_callback.h"
|
||||
|
||||
#include "dyncall_thunk.h"
|
||||
#include "dyncall_args_mips.h"
|
||||
|
||||
struct DCCallback
|
||||
{
|
||||
DCThunk thunk; /* offset 0, size 20 */
|
||||
DCCallbackHandler* handler; /* offset 20, size 4 */
|
||||
void* userdata; /* offset 24, size 4 */
|
||||
};
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_MIPS_H */
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback_ppc32.h
|
||||
Description: Callback - Header for ppc32
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_PPC32_H
|
||||
#define DYNCALL_CALLBACK_PPC32_H
|
||||
|
||||
#include "dyncall_callback.h"
|
||||
|
||||
#include "dyncall_thunk.h"
|
||||
#include "dyncall_args_ppc32.h"
|
||||
|
||||
struct DCCallback
|
||||
{
|
||||
DCThunk thunk; /* offset 0, size 24 */
|
||||
DCCallbackHandler* handler; /* offset 24, size 4 */
|
||||
size_t stack_cleanup; /* offset 28, size 4 */
|
||||
void* userdata; /* offset 32, size 4 */
|
||||
}; /* total size 36 */
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_PPC32_H */
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback_ppc64.h
|
||||
Description: Callback - Header for ppc64
|
||||
License:
|
||||
|
||||
Copyright (c) 2014-2015 Masanori Mitsugi <mitsugi@linux.vnet.ibm.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_PPC64_H
|
||||
#define DYNCALL_CALLBACK_PPC64_H
|
||||
|
||||
#include "dyncall_callback.h"
|
||||
|
||||
#include "dyncall_thunk.h"
|
||||
#include "dyncall_args_ppc64.h"
|
||||
|
||||
/*
|
||||
ELF v2
|
||||
thunk : offset 0, size 48
|
||||
handler : offset 48, size 8
|
||||
stack_cleanup : offset 56, size 8
|
||||
userdata : offset 64, size 8
|
||||
|
||||
ELF v1
|
||||
thunk : offset 0, size 64
|
||||
handler : offset 64, size 8
|
||||
stack_cleanup : offset 72, size 8
|
||||
userdata : offset 80, size 8
|
||||
*/
|
||||
|
||||
struct DCCallback
|
||||
{
|
||||
DCThunk thunk;
|
||||
DCCallbackHandler* handler;
|
||||
size_t stack_cleanup;
|
||||
void* userdata;
|
||||
};
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_PPC64_H */
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback_sparc32.h
|
||||
Description: Callback - Header for sparc32
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_SPARC32_H
|
||||
#define DYNCALL_CALLBACK_SPARC32_H
|
||||
|
||||
#include "dyncall_callback.h"
|
||||
|
||||
#include "dyncall_thunk.h"
|
||||
#include "dyncall_args_sparc32.h"
|
||||
|
||||
struct DCCallback
|
||||
{
|
||||
DCThunk thunk; /* offset 0, size ?? */
|
||||
DCCallbackHandler* handler; /* offset ??, size 4 */
|
||||
size_t stack_cleanup; /* offset ??, size 4 */
|
||||
void* userdata; /* offset ??, size 4 */
|
||||
};
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_SPARC32_H */
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback_x64.h
|
||||
Description: Callback - Header for x64
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_X64_H_
|
||||
#define DYNCALL_CALLBACK_X64_H_
|
||||
|
||||
#include "dyncall_callback.h"
|
||||
|
||||
#include "dyncall_thunk.h"
|
||||
#include "dyncall_args_x64.h"
|
||||
|
||||
|
||||
struct DCCallback
|
||||
{
|
||||
DCThunk thunk; // offset 0, size 24
|
||||
DCCallbackHandler* handler; // offset 24
|
||||
void* userdata; // offset 32
|
||||
};
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_X64_H_ */
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_callback_x86.h
|
||||
Description: Callback - Header for x86
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef DYNCALL_CALLBACK_X86_H_
|
||||
#define DYNCALL_CALLBACK_X86_H_
|
||||
|
||||
#include "dyncall_callback.h"
|
||||
|
||||
#include "dyncall_thunk.h"
|
||||
#include "dyncall_args_x86.h"
|
||||
|
||||
struct DCCallback
|
||||
{
|
||||
DCThunk thunk; /* offset 0, size 16 */
|
||||
DCCallbackHandler* handler; /* offset 16 */
|
||||
DCArgsVT* args_vt; /* offset 20 */
|
||||
size_t stack_cleanup; /* offset 24 */
|
||||
void* userdata; /* offset 28 */
|
||||
};
|
||||
|
||||
int dcCleanupSize_x86_cdecl (const char* args_signature);
|
||||
int dcCleanupSize_x86_std (const char* args_signature);
|
||||
int dcCleanupSize_x86_fast_ms (const char* args_signature);
|
||||
int dcCleanupSize_x86_fast_gnu(const char* args_signature);
|
||||
|
||||
#endif /* DYNCALL_CALLBACK_X86_H_ */
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncall
|
||||
File: dyncall/dyncall_callf.h
|
||||
Description: formatted call interface to dyncall
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
dyncall formatted calls C API
|
||||
|
||||
REVISION
|
||||
2007/12/11 initial
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_CALLF_H
|
||||
#define DYNCALL_CALLF_H
|
||||
|
||||
/* dyncall formatted calls */
|
||||
|
||||
#include "dyncall.h"
|
||||
#include "dyncall_signature.h"
|
||||
#include "dyncall_value.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
void dcArgF (DCCallVM* vm, const DCsigchar* signature, ...);
|
||||
void dcVArgF(DCCallVM* vm, const DCsigchar* signature, va_list args);
|
||||
|
||||
void dcCallF (DCCallVM* vm, DCValue* result, DCpointer funcptr, const DCsigchar* signature, ...);
|
||||
void dcVCallF(DCCallVM* vm, DCValue* result, DCpointer funcptr, const DCsigchar* signature, va_list args);
|
||||
|
||||
#endif /* DYNCALL_CALLF_H */
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncall
|
||||
File: dyncall/dyncall_config.h
|
||||
Description: Macro configuration file for non-standard C types
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
dyncall type configuration
|
||||
|
||||
REVISION
|
||||
2007/12/11 initial
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_CONFIG_H
|
||||
#define DYNCALL_CONFIG_H
|
||||
|
||||
#include "dyncall_macros.h"
|
||||
|
||||
#define DC_BOOL int
|
||||
#define DC_LONG_LONG long long
|
||||
#define DC_POINTER void*
|
||||
|
||||
#endif /* DYNCALL_CONFIG_H */
|
||||
|
||||
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncall
|
||||
File: dyncall/dyncall_macros.h
|
||||
Description: Platform detection macros
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
dyncall macros
|
||||
|
||||
Platform detection, specific defines and configuration.
|
||||
The purpose of this file is to provide coherent platform and compiler
|
||||
specific defines. So instead of defines like WIN32, _OpenBSD_ or
|
||||
__GNUC__, one should use DC__OS_Win32, DC__OS_OpenBSD or DC__C_GNU,
|
||||
respectively.
|
||||
|
||||
REVISION
|
||||
2007/12/11 initial
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_MACROS_H
|
||||
#define DYNCALL_MACROS_H
|
||||
|
||||
|
||||
/* Platform specific defines. */
|
||||
|
||||
/* MS Windows XP x64/Vista64 or later. */
|
||||
#if defined(WIN64) || defined(_WIN64) || defined(__WIN64__)
|
||||
#define DC__OS_Win64
|
||||
|
||||
/* MS Windows NT/95/98/ME/2000/XP/Vista32. */
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__WINDOWS__) || defined(_WINDOWS)
|
||||
#define DC__OS_Win32
|
||||
|
||||
/* All the OS' based on Darwin OS (MacOS X, OpenDarwin). Note that '__APPLE__' may be defined for classic MacOS, too. */
|
||||
/* __MACOSX__ is not defined in gcc assembler mode (switch: -S) */
|
||||
/* @@@ TODO: Check for Classic OS */
|
||||
|
||||
#elif defined(__APPLE__) || defined(__Darwin__)
|
||||
# define DC__OS_Darwin
|
||||
# if defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
|
||||
# define DC__OS_IPhone
|
||||
# else /* defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) */
|
||||
# define DC__OS_MacOSX
|
||||
# endif
|
||||
|
||||
/* The most popular open source Unix-like OS - Linux. */
|
||||
#elif defined(__linux__) || defined(__linux) || defined(__gnu_linux__)
|
||||
#define DC__OS_Linux
|
||||
|
||||
/* The most powerful open source Unix-like OS - FreeBSD. */
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
|
||||
#define DC__OS_FreeBSD
|
||||
|
||||
/* The most secure open source Unix-like OS - OpenBSD. */
|
||||
#elif defined(__OpenBSD__)
|
||||
#define DC__OS_OpenBSD
|
||||
|
||||
/* The most portable open source Unix-like OS - NetBSD. */
|
||||
#elif defined(__NetBSD__)
|
||||
#define DC__OS_NetBSD
|
||||
|
||||
/* The FreeBSD fork having heavy clusterization in mind - DragonFlyBSD. */
|
||||
#elif defined(__DragonFly__)
|
||||
#define DC__OS_DragonFlyBSD
|
||||
|
||||
/* Sun's Unix-like OS - SunOS / Solaris. */
|
||||
#elif defined(__sun__) || defined(__sun) || defined(sun)
|
||||
#define DC__OS_SunOS
|
||||
|
||||
/* The "Linux-like environment for Windows" - Cygwin. */
|
||||
#elif defined(__CYGWIN__)
|
||||
#define DC__OS_Cygwin
|
||||
|
||||
/* The "Minimalist GNU for Windows" - MinGW. */
|
||||
#elif defined(__MINGW__)/*@@@*/
|
||||
#define DC__OS_MinGW
|
||||
|
||||
/* The Nintendo DS (homebrew) using devkitpro. */
|
||||
#elif defined(__nds__)
|
||||
#define DC__OS_NDS
|
||||
|
||||
/* The PlayStation Portable (homebrew) SDK. */
|
||||
#elif defined(__psp__) || defined(PSP)
|
||||
#define DC__OS_PSP
|
||||
|
||||
/* Haiku (BeOS alike). */
|
||||
#elif defined(__HAIKU__)
|
||||
#define DC__OS_BeOS
|
||||
|
||||
/* The Unix successor - Plan9 from Bell Labs */
|
||||
#elif defined(Plan9) || defined(__Plan9__)
|
||||
#define DC__OS_Plan9
|
||||
|
||||
/* Digital's Unix-like OS - VMS */
|
||||
#elif defined(__vms)
|
||||
#define DC__OS_VMS
|
||||
|
||||
#elif defined(__minix)
|
||||
#define DC__OS_Minix
|
||||
|
||||
#else
|
||||
#error Unsupported OS.
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Compiler specific defines. Do not change the order, because */
|
||||
/* some of the compilers define flags for compatible ones, too. */
|
||||
|
||||
/* Intel's C/C++ compiler. */
|
||||
#if defined(__INTEL_COMPILER)
|
||||
#define DC__C_Intel
|
||||
|
||||
/* MS C/C++ compiler. */
|
||||
#elif defined(_MSC_VER)
|
||||
#define DC__C_MSVC
|
||||
|
||||
/* LLVM clang. */
|
||||
#elif defined(__clang__)
|
||||
#define DC__C_CLANG
|
||||
|
||||
/* The GNU Compiler Collection - GCC. */
|
||||
#elif defined(__GNUC__)
|
||||
#define DC__C_GNU
|
||||
|
||||
/* Watcom compiler. */
|
||||
#elif defined(__WATCOMC__)
|
||||
#define DC__C_WATCOM
|
||||
|
||||
/* Portable C Compiler. */
|
||||
#elif defined(__PCC__)
|
||||
#define DC__C_PCC
|
||||
|
||||
/* Sun Pro C. */
|
||||
#elif defined(__SUNPRO_C)
|
||||
#define DC__C_SUNPRO
|
||||
|
||||
/* Undetected C Compiler. */
|
||||
#else
|
||||
#define DC__C_UNKNOWN
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Architecture. */
|
||||
|
||||
/* Check architecture. */
|
||||
#if defined(_M_X64_) || defined(_M_AMD64) || defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64)
|
||||
# define DC__Arch_AMD64
|
||||
#elif defined(_M_IX86) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__386__) || defined(__i386)
|
||||
# define DC__Arch_Intel_x86
|
||||
#elif defined(_M_IA64) || defined(__ia64__)
|
||||
# define DC__Arch_Itanium
|
||||
#elif defined(_M_PPC) || defined(__powerpc__) || defined(__powerpc) || defined(__POWERPC__) || defined(__ppc__) || defined(__power__)
|
||||
# if defined(__ppc64__) || defined(_ARCH_PPC64) || defined(__power64__) || defined(__powerpc64__)
|
||||
# define DC__Arch_PPC64
|
||||
# else
|
||||
# define DC__Arch_PPC32
|
||||
# endif
|
||||
#elif defined(__mips64__) || defined(__mips64)
|
||||
# define DC__Arch_MIPS64
|
||||
#elif defined(_M_MRX000) || defined(__mips__) || defined(__mips) || defined(_mips)
|
||||
# define DC__Arch_MIPS
|
||||
#elif defined(__arm__)
|
||||
# define DC__Arch_ARM
|
||||
#elif defined(__aarch64__)
|
||||
# define DC__Arch_ARM64
|
||||
#elif defined(__sh__)
|
||||
# define DC__Arch_SuperH
|
||||
#elif defined(__sparcv9) || defined(__sparc64__) || ( defined(__sparc) && defined(__arch64__) )
|
||||
/* this could be needed on Linux/GNU sparc64 in the future: || ( defined(__sparc) && defined(__arch64__) ) */
|
||||
# define DC__Arch_Sparcv9
|
||||
#elif defined(__sparc)
|
||||
# define DC__Arch_Sparc
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Rough OS classification. */
|
||||
|
||||
#if defined(DC__OS_Win32) || defined(DC__OS_Win64)
|
||||
# define DC_WINDOWS
|
||||
#elif defined(DC__OS_Plan9)
|
||||
# define DC_PLAN9
|
||||
#elif defined(DC__OS_NDS) || defined(DC__OS_PSP)
|
||||
# define DC_OTHER
|
||||
#else
|
||||
# define DC_UNIX
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/* Misc machine-dependent modes, ABIs, etc.. */
|
||||
|
||||
#if defined(__arm__) && !defined(__thumb__)
|
||||
# define DC__Arch_ARM_ARM
|
||||
#elif defined(__arm__) && defined(__thumb__)
|
||||
# define DC__Arch_ARM_THUMB
|
||||
#endif
|
||||
|
||||
#if defined(DC__Arch_ARM_ARM) || defined(DC__Arch_ARM_THUMB)
|
||||
# if defined(__ARM_EABI__) || defined(DC__OS_NDS)
|
||||
# if defined (__ARM_PCS_VFP) && (__ARM_PCS_VFP == 1)
|
||||
# define DC__ABI_ARM_HF
|
||||
# else
|
||||
# define DC__ABI_ARM_EABI
|
||||
# endif
|
||||
# elif defined(__APCS_32__)
|
||||
# define DC__ABI_ARM_OABI
|
||||
# endif
|
||||
#endif /* ARM */
|
||||
|
||||
#if defined(DC__Arch_MIPS) || defined(DC__Arch_MIPS64)
|
||||
# if defined(_ABIO32) || defined(_MIPS_ARCH_MIPS1) || defined(_MIPS_ARCH_MIPS2)
|
||||
# define DC__ABI_MIPS_O32
|
||||
# elif defined(_ABIN32)
|
||||
# define DC__ABI_MIPS_N32
|
||||
# elif defined(_ABI64)
|
||||
# define DC__ABI_MIPS_N64
|
||||
# else
|
||||
# define DC__ABI_MIPS_EABI
|
||||
# endif
|
||||
#endif /* MIPS */
|
||||
|
||||
#if defined(DC__Arch_PPC64)
|
||||
# if defined(_CALL_ELF)
|
||||
# define DC__ABI_PPC64_ELF_V _CALL_ELF
|
||||
# else
|
||||
# define DC__ABI_PPC64_ELF_V 0 /* 0 means not explicitly set, otherwise this is 1 (big endian) and 2 (little endian) */
|
||||
# endif
|
||||
#endif /* MIPS */
|
||||
|
||||
|
||||
/* Endian detection. */
|
||||
#if defined(DC__Arch_Intel_x86) || defined(DC__Arch_AMD64) /* always little */
|
||||
# define DC__Endian_LITTLE
|
||||
#elif defined(DC__Arch_Sparc) /*always big until v9*/
|
||||
# define DC__Endian_BIG
|
||||
#else /* all others are bi-endian */
|
||||
/* @@@check flags used on following bi-endianness archs:
|
||||
DC__Arch_ARM
|
||||
DC__Arch_ARM64
|
||||
DC__Arch_Itanium
|
||||
DC__Arch_MIPS
|
||||
DC__Arch_MIPS64
|
||||
DC__Arch_PPC32
|
||||
DC__Arch_PPC64
|
||||
DC__Arch_Sparcv9
|
||||
DC__Arch_SuperH
|
||||
*/
|
||||
# if (defined(DC__Arch_PPC64) && (DC__ABI_PPC64_ELF_V == 1)) || defined(_BIG_ENDIAN) || defined(MIPSEB)
|
||||
# define DC__Endian_BIG
|
||||
# elif (defined(DC__Arch_PPC64) && (DC__ABI_PPC64_ELF_V == 2)) || defined(_LITTLE_ENDIAN) || defined(MIPSEL)
|
||||
# define DC__Endian_LITTLE
|
||||
# endif /* no else, leave unset if not sure */
|
||||
#endif
|
||||
|
||||
|
||||
/* Internal macro/tag. */
|
||||
#if !defined(DC_API)
|
||||
#define DC_API
|
||||
#endif
|
||||
|
||||
#endif /* DYNCALL_MACROS_H */
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncall
|
||||
File: dyncall/dyncall_signature.h
|
||||
Description: Type and calling-convention signature character defines
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
dyncall signature characters
|
||||
|
||||
REVISION
|
||||
2007/12/11 initial
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_SIGNATURE_H
|
||||
#define DYNCALL_SIGNATURE_H
|
||||
|
||||
typedef char DCsigchar;
|
||||
|
||||
#define DC_SIGCHAR_VOID 'v'
|
||||
#define DC_SIGCHAR_BOOL 'B'
|
||||
#define DC_SIGCHAR_CHAR 'c'
|
||||
#define DC_SIGCHAR_UCHAR 'C'
|
||||
#define DC_SIGCHAR_SHORT 's'
|
||||
#define DC_SIGCHAR_USHORT 'S'
|
||||
#define DC_SIGCHAR_INT 'i'
|
||||
#define DC_SIGCHAR_UINT 'I'
|
||||
#define DC_SIGCHAR_LONG 'j'
|
||||
#define DC_SIGCHAR_ULONG 'J'
|
||||
#define DC_SIGCHAR_LONGLONG 'l'
|
||||
#define DC_SIGCHAR_ULONGLONG 'L'
|
||||
#define DC_SIGCHAR_FLOAT 'f'
|
||||
#define DC_SIGCHAR_DOUBLE 'd'
|
||||
#define DC_SIGCHAR_POINTER 'p'
|
||||
#define DC_SIGCHAR_STRING 'Z'
|
||||
#define DC_SIGCHAR_STRUCT 'T'
|
||||
#define DC_SIGCHAR_ENDARG ')' /* also works for end struct */
|
||||
|
||||
/* callback signatures */
|
||||
|
||||
#define DC_SIGCHAR_CC_PREFIX '_'
|
||||
#define DC_SIGCHAR_CC_ELLIPSIS 'e'
|
||||
#define DC_SIGCHAR_CC_STDCALL 's'
|
||||
#define DC_SIGCHAR_CC_FASTCALL_GNU 'f'
|
||||
#define DC_SIGCHAR_CC_FASTCALL_MS 'F'
|
||||
#define DC_SIGCHAR_CC_THISCALL_MS '+'
|
||||
|
||||
#endif /* DYNCALL_SIGNATURE_H */
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk.h
|
||||
Description: Thunk - Interface
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_THUNK_H
|
||||
#define DYNCALL_THUNK_H
|
||||
|
||||
/**
|
||||
** dyncall thunks
|
||||
**
|
||||
** thunks are small-size hybrid code/data objects, created at run-time to
|
||||
** be used as function pointers with associated data and entry functions.
|
||||
**
|
||||
** The header contains code, that does load its address into a designated scratch
|
||||
** register and will jump to a thunk function.
|
||||
**
|
||||
** Thunk entry procedures are compiled functions, that are called as a result of
|
||||
** a thunk function.
|
||||
** There is one thunk entry currently for supporting callbacks.
|
||||
**
|
||||
** Thunk context register ( ::= an available scratch register in the calling convention):
|
||||
**
|
||||
** x86: eax
|
||||
** x64: rax
|
||||
** ppc: r2
|
||||
** arm: r12
|
||||
** arm64: x9
|
||||
**
|
||||
**/
|
||||
|
||||
#include "dyncall_macros.h"
|
||||
|
||||
typedef struct DCThunk_ DCThunk;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void dcbInitThunk(DCThunk* p, void (*entry)());
|
||||
|
||||
#if defined(DC__Arch_Intel_x86)
|
||||
#include "dyncall_thunk_x86.h"
|
||||
#elif defined (DC__Arch_AMD64)
|
||||
#include "dyncall_thunk_x64.h"
|
||||
#elif defined (DC__Arch_PPC32)
|
||||
#include "dyncall_thunk_ppc32.h"
|
||||
#elif defined (DC__Arch_PPC64)
|
||||
#include "dyncall_thunk_ppc64.h"
|
||||
#elif defined (DC__Arch_ARM_ARM)
|
||||
#include "dyncall_thunk_arm32_arm.h"
|
||||
#elif defined (DC__Arch_ARM_THUMB)
|
||||
#include "dyncall_thunk_arm32_thumb.h"
|
||||
#elif defined (DC__Arch_MIPS)
|
||||
#include "dyncall_thunk_mips.h"
|
||||
#elif defined (DC__Arch_Sparc)
|
||||
#include "dyncall_thunk_sparc32.h"
|
||||
#elif defined (DC__Arch_Sparcv9)
|
||||
#include "dyncall_thunk_sparc64.h"
|
||||
#elif defined (DC__Arch_ARM64)
|
||||
#include "dyncall_thunk_arm64.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* DYNCALL_THUNK_H */
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_arm32_arm.h
|
||||
Description: Thunk - Header for ARM32 (ARM mode)
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_THUNK_ARM32_ARM_H
|
||||
#define DYNCALL_THUNK_ARM32_ARM_H
|
||||
|
||||
|
||||
struct DCThunk_
|
||||
{
|
||||
unsigned int code[2];
|
||||
void (*entry)();
|
||||
};
|
||||
|
||||
#define DCTHUNK_ARM32_ARM_SIZE 12
|
||||
|
||||
|
||||
#endif /* DYNCALL_THUNK_ARM32_ARM_H */
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_arm32_thumb.h
|
||||
Description: Thunk - Header for ARM32 (THUMB mode)
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_THUNK_ARM32_THUMB_H
|
||||
#define DYNCALL_THUNK_ARM32_THUMB_H
|
||||
|
||||
#include "dyncall_thunk_arm32_arm.h" /* Uses same code as ARM mode. */
|
||||
|
||||
#define DCTHUNK_ARM32_THUMB_SIZE 12
|
||||
|
||||
|
||||
#endif /* DYNCALL_THUNK_ARM32_THUMB_H */
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_arm64.h
|
||||
Description: Thunk - Header for ARM64 / ARMv8 / AAPCS64
|
||||
License:
|
||||
|
||||
Copyright (c) 2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_THUNK_ARM64_H
|
||||
#define DYNCALL_THUNK_ARM64_H
|
||||
|
||||
struct DCThunk_
|
||||
{
|
||||
// off size
|
||||
//-----|----------
|
||||
unsigned int code[4]; // 0 16
|
||||
void (*entry)(); // 16 8
|
||||
void* reserved; // 24 8
|
||||
|
||||
// 32 total size
|
||||
|
||||
};
|
||||
|
||||
#endif /* DYNCALL_THUNK_ARM64_H */
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_mips.h
|
||||
Description: Thunk - Header for MIPS
|
||||
License:
|
||||
|
||||
Copyright (c) 2013-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_THUNK_MIPS_H
|
||||
#define DYNCALL_THUNK_MIPS_H
|
||||
|
||||
struct DCThunk_
|
||||
{
|
||||
unsigned short data[6];
|
||||
unsigned int jump;
|
||||
unsigned short bddt[2];
|
||||
};
|
||||
|
||||
#endif /* DYNCALL_THUNK_MIPS_H */
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_ppc32.h
|
||||
Description: Thunk - Header for ppc32 (darwin/sysv)
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_THUNK_PPC32_H
|
||||
#define DYNCALL_THUNK_PPC32_H
|
||||
|
||||
struct DCThunk_
|
||||
{
|
||||
unsigned short code_load_hi, addr_self_hi; /* offset: 0 size: 4 */
|
||||
unsigned short code_load_lo, addr_self_lo; /* offset: 4 size: 4 */
|
||||
unsigned int code_jump[3]; /* offset: 8 size: 12 */
|
||||
void (*addr_entry)(); /* offset: 20 size: 4 */
|
||||
}; /* total size: 24 */
|
||||
|
||||
#define DCTHUNK_SIZE_PPC32 24
|
||||
|
||||
#endif /* DYNCALL_THUNK_PPC32_H */
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_ppc64.h
|
||||
Description: Thunk - Header for ppc64
|
||||
License:
|
||||
|
||||
Copyright (c) 2014-2015 Masanori Mitsugi <mitsugi@linux.vnet.ibm.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_THUNK_PPC64_H
|
||||
#define DYNCALL_THUNK_PPC64_H
|
||||
|
||||
#if DC__ABI_PPC64_ELF_V != 2
|
||||
struct DCThunk_ /* v1 */
|
||||
{
|
||||
void (*thunk_entry)(); /* offset: 0 */
|
||||
long toc_thunk; /* offset: 8 */
|
||||
unsigned short code_load_hi, addr_self_hi; /* offset: 16 */
|
||||
unsigned short code_load_lo, addr_self_lo; /* offset: 20 */
|
||||
unsigned int code_jump[6]; /* offset: 24 */
|
||||
void (*addr_entry)(); /* offset: 48 */
|
||||
long toc_entry; /* offset: 56 */
|
||||
};
|
||||
#define DCTHUNK_SIZE_PPC64 64
|
||||
#else
|
||||
struct DCThunk_ /* v2 */
|
||||
{
|
||||
unsigned short addr_self_hist, code_load_hist; /* offset: 0 */
|
||||
unsigned short addr_self_hier, code_load_hier; /* offset: 4 */
|
||||
unsigned int code_rot; /* offset: 8 */
|
||||
unsigned short addr_self_hi, code_load_hi; /* offset: 12 */
|
||||
unsigned short addr_self_lo, code_load_lo; /* offset: 16 */
|
||||
unsigned int code_jump[5]; /* offset: 20 */
|
||||
void (*addr_entry)(); /* offset: 40 */
|
||||
};
|
||||
#define DCTHUNK_SIZE_PPC64 48
|
||||
#endif
|
||||
|
||||
#endif /* DYNCALL_THUNK_PPC64_H */
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_sparc32.h
|
||||
Description: Thunk - Header for sparc32 - not yet implemented
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_THUNK_SPARC32_H
|
||||
#define DYNCALL_THUNK_SPARC32_H
|
||||
|
||||
struct DCThunk_
|
||||
{
|
||||
int x[4]; /* dummy */
|
||||
};
|
||||
|
||||
#define DCTHUNK_SIZE_SPARC32 32
|
||||
|
||||
#endif /* DYNCALL_THUNK_SPARC32_H */
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_sparc64.h
|
||||
Description: Thunk - Header for sparc64 - not yet implemented
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_THUNK_SPARC64_H
|
||||
#define DYNCALL_THUNK_SPARC64_H
|
||||
|
||||
struct DCThunk_
|
||||
{
|
||||
int x[4]; /* dummy */
|
||||
};
|
||||
|
||||
#define DCTHUNK_SIZE_SPARC64 32
|
||||
|
||||
#endif /* DYNCALL_THUNK_SPARC32_H */
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_x64.h
|
||||
Description: Thunk - Header for x64
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_THUNK_X64_H
|
||||
#define DYNCALL_THUNK_X64_H
|
||||
|
||||
struct DCThunk_
|
||||
{
|
||||
unsigned long long code[2];
|
||||
void (*entry)();
|
||||
};
|
||||
|
||||
#define DCTHUNK_X64_SIZE 24
|
||||
|
||||
|
||||
#endif /* DYNCALL_THUNK_X64_H */
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncallback
|
||||
File: dyncallback/dyncall_thunk_x86.h
|
||||
Description: Thunk - Header for x86
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DYNCALL_THUNK_X86_H
|
||||
#define DYNCALL_THUNK_X86_H
|
||||
|
||||
struct DCThunk_
|
||||
{
|
||||
unsigned int code_load;
|
||||
void* addr_self;
|
||||
unsigned int code_jump;
|
||||
void (*addr_entry)();
|
||||
};
|
||||
|
||||
#define DCTHUNK_X86_SIZE 16
|
||||
|
||||
#endif /* DYNCALL_THUNK_X86_H */
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncall
|
||||
File: dyncall/dyncall_types.h
|
||||
Description: Typedefs
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
|
||||
dyncall argument- and return-types
|
||||
|
||||
REVISION
|
||||
2007/12/11 initial
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_TYPES_H
|
||||
#define DYNCALL_TYPES_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "dyncall_config.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void DCvoid;
|
||||
typedef DC_BOOL DCbool;
|
||||
typedef char DCchar;
|
||||
typedef unsigned char DCuchar;
|
||||
typedef short DCshort;
|
||||
typedef unsigned short DCushort;
|
||||
typedef int DCint;
|
||||
typedef unsigned int DCuint;
|
||||
typedef long DClong;
|
||||
typedef unsigned long DCulong;
|
||||
typedef DC_LONG_LONG DClonglong;
|
||||
typedef unsigned DC_LONG_LONG DCulonglong;
|
||||
typedef float DCfloat;
|
||||
typedef double DCdouble;
|
||||
typedef DC_POINTER DCpointer;
|
||||
typedef const char* DCstring;
|
||||
|
||||
typedef size_t DCsize;
|
||||
|
||||
#define DC_TRUE 1
|
||||
#define DC_FALSE 0
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DYNCALL_TYPES_H */
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dyncall
|
||||
File: dyncall/dyncall_value.h
|
||||
Description: Value variant type
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
dyncall value variant
|
||||
|
||||
a value variant union-type that carries all supported dyncall types.
|
||||
|
||||
REVISION
|
||||
2007/12/11 initial
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DYNCALL_VALUE_H
|
||||
#define DYNCALL_VALUE_H
|
||||
|
||||
#include "dyncall_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef union DCValue_ DCValue;
|
||||
|
||||
union DCValue_
|
||||
{
|
||||
#if defined (DC__Arch_PPC32) && defined(DC__Endian_BIG)
|
||||
DCbool B;
|
||||
struct { DCchar c_pad[3]; DCchar c; };
|
||||
struct { DCuchar C_pad[3]; DCuchar C; };
|
||||
struct { DCshort s_pad; DCshort s; };
|
||||
struct { DCshort S_pad; DCshort S; };
|
||||
DCint i;
|
||||
DCuint I;
|
||||
#elif defined (DC__Arch_PPC64) && defined(DC__Endian_BIG)
|
||||
struct { DCbool B_pad; DCbool B; };
|
||||
struct { DCchar c_pad[7]; DCchar c; };
|
||||
struct { DCuchar C_pad[7]; DCuchar C; };
|
||||
struct { DCshort s_pad[3]; DCshort s; };
|
||||
struct { DCshort S_pad[3]; DCshort S; };
|
||||
struct { DCint i_pad; DCint i; };
|
||||
struct { DCint I_pad; DCuint I; };
|
||||
#else
|
||||
DCbool B;
|
||||
DCchar c;
|
||||
DCuchar C;
|
||||
DCshort s;
|
||||
DCushort S;
|
||||
DCint i;
|
||||
DCuint I;
|
||||
#endif
|
||||
DClong j;
|
||||
DCulong J;
|
||||
DClonglong l;
|
||||
DCulonglong L;
|
||||
DCfloat f;
|
||||
DCdouble d;
|
||||
DCpointer p;
|
||||
DCstring Z;
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DYNCALL_VALUE_H */
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
|
||||
Package: dyncall
|
||||
Library: dynload
|
||||
File: dynload/dynload.h
|
||||
Description: public header for library dynload
|
||||
License:
|
||||
|
||||
Copyright (c) 2007-2015 Daniel Adler <dadler@uni-goettingen.de>,
|
||||
Tassilo Philipp <tphilipp@potion-studios.com>
|
||||
|
||||
Permission to use, copy, modify, and distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef DYNLOAD_H
|
||||
#define DYNLOAD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef DL_API
|
||||
#define DL_API
|
||||
#endif
|
||||
|
||||
/* --- public api ---------------------------------------------------------- */
|
||||
|
||||
/* shared library loading and explicit symbol resolving */
|
||||
|
||||
typedef struct DLLib_ DLLib;
|
||||
|
||||
DL_API DLLib* dlLoadLibrary(const char* libpath);
|
||||
DL_API void dlFreeLibrary(DLLib* pLib);
|
||||
DL_API void* dlFindSymbol(DLLib* pLib, const char* pSymbolName);
|
||||
|
||||
/* symbol table enumeration - only for symbol lookup, not resolve */
|
||||
|
||||
typedef struct DLSyms_ DLSyms;
|
||||
|
||||
DL_API DLSyms* dlSymsInit (const char* libPath);
|
||||
DL_API void dlSymsCleanup(DLSyms* pSyms);
|
||||
|
||||
DL_API int dlSymsCount (DLSyms* pSyms);
|
||||
DL_API const char* dlSymsName (DLSyms* pSyms, int index);
|
||||
DL_API const char* dlSymsNameFromValue(DLSyms* pSyms, void* value); /* symbol must be loaded */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DYNLOAD_H */
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
+4
-5
@@ -7,9 +7,9 @@
|
||||
#include "parser.cpp"
|
||||
// #include "printer.cpp"
|
||||
#include "checker/checker.cpp"
|
||||
#include "ssa/ssa.cpp"
|
||||
#include "llvm/ssa_to_text.cpp"
|
||||
#include "vm/vm.cpp"
|
||||
#include "ssa.cpp"
|
||||
#include "ssa_to_llvm.cpp"
|
||||
#include "vm.cpp"
|
||||
|
||||
// NOTE(bill): `name` is used in debugging and profiling modes
|
||||
i32 win32_exec_command_line_app(char *name, char *fmt, ...) {
|
||||
@@ -172,9 +172,8 @@ int main(int argc, char **argv) {
|
||||
vm_init(&vm, &ssa.module);
|
||||
defer (vm_destroy(&vm));
|
||||
|
||||
ssaProcedure *start_proc = vm_lookup_procedure(&vm, make_string("main"));
|
||||
Array<vmValue> args = {}; // Empty
|
||||
vm_call_procedure(&vm, start_proc, args);
|
||||
vm_call_proc_by_name(&vm, make_string("main"), args);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+5340
File diff suppressed because it is too large
Load Diff
-1965
File diff suppressed because it is too large
Load Diff
@@ -1,671 +0,0 @@
|
||||
struct ssaGen {
|
||||
ssaModule module;
|
||||
gbFile output_file;
|
||||
};
|
||||
|
||||
b32 ssa_gen_init(ssaGen *s, Checker *c) {
|
||||
if (global_error_collector.count != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
isize tc = c->parser->total_token_count;
|
||||
if (tc < 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ssa_init_module(&s->module, c);
|
||||
s->module.generate_debug_info = false;
|
||||
|
||||
// TODO(bill): generate appropriate output name
|
||||
int pos = cast(int)string_extension_position(c->parser->init_fullpath);
|
||||
gbFileError err = gb_file_create(&s->output_file, gb_bprintf("%.*s.ll", pos, c->parser->init_fullpath.text));
|
||||
if (err != gbFileError_None) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ssa_gen_destroy(ssaGen *s) {
|
||||
ssa_destroy_module(&s->module);
|
||||
gb_file_close(&s->output_file);
|
||||
}
|
||||
|
||||
String ssa_mangle_name(ssaGen *s, String path, String name) {
|
||||
// NOTE(bill): prefix names not in the init scope
|
||||
// TODO(bill): make robust and not just rely on the file's name
|
||||
|
||||
ssaModule *m = &s->module;
|
||||
CheckerInfo *info = m->info;
|
||||
gbAllocator a = m->allocator;
|
||||
AstFile *file = *map_get(&info->files, hash_string(path));
|
||||
|
||||
char *str = gb_alloc_array(a, char, path.len+1);
|
||||
gb_memmove(str, path.text, path.len);
|
||||
str[path.len] = 0;
|
||||
for (isize i = 0; i < path.len; i++) {
|
||||
if (str[i] == '\\') {
|
||||
str[i] = '/';
|
||||
}
|
||||
}
|
||||
|
||||
char const *base = gb_path_base_name(str);
|
||||
char const *ext = gb_path_extension(base);
|
||||
isize base_len = ext-1-base;
|
||||
|
||||
isize max_len = base_len + 1 + 10 + 1 + name.len;
|
||||
u8 *new_name = gb_alloc_array(a, u8, max_len);
|
||||
isize new_name_len = gb_snprintf(
|
||||
cast(char *)new_name, max_len,
|
||||
"%.*s-%u.%.*s",
|
||||
cast(int)base_len, base,
|
||||
file->id,
|
||||
LIT(name));
|
||||
|
||||
return make_string(new_name, new_name_len-1);
|
||||
}
|
||||
|
||||
|
||||
void ssa_gen_tree(ssaGen *s) {
|
||||
ssaModule *m = &s->module;
|
||||
CheckerInfo *info = m->info;
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
if (v_zero == NULL) {
|
||||
v_zero = ssa_make_const_int (m->allocator, 0);
|
||||
v_one = ssa_make_const_int (m->allocator, 1);
|
||||
v_zero32 = ssa_make_const_i32 (m->allocator, 0);
|
||||
v_one32 = ssa_make_const_i32 (m->allocator, 1);
|
||||
v_two32 = ssa_make_const_i32 (m->allocator, 2);
|
||||
v_false = ssa_make_const_bool(m->allocator, false);
|
||||
v_true = ssa_make_const_bool(m->allocator, true);
|
||||
}
|
||||
|
||||
isize global_variable_max_count = 0;
|
||||
Entity *entry_point = NULL;
|
||||
|
||||
for_array(i, info->entities.entries) {
|
||||
auto *entry = &info->entities.entries[i];
|
||||
Entity *e = cast(Entity *)cast(uintptr)entry->key.key;
|
||||
String name = e->token.string;
|
||||
if (e->kind == Entity_Variable) {
|
||||
global_variable_max_count++;
|
||||
} else if (e->kind == Entity_Procedure) {
|
||||
if (e->scope->is_init && name == "main") {
|
||||
entry_point = e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ssaGlobalVariable {
|
||||
ssaValue *var, *init;
|
||||
DeclInfo *decl;
|
||||
};
|
||||
Array<ssaGlobalVariable> global_variables;
|
||||
array_init(&global_variables, m->tmp_allocator, global_variable_max_count);
|
||||
|
||||
m->min_dep_map = generate_minimum_dependency_map(info, entry_point);
|
||||
|
||||
for_array(i, info->entities.entries) {
|
||||
auto *entry = &info->entities.entries[i];
|
||||
Entity *e = cast(Entity *)entry->key.ptr;
|
||||
String name = e->token.string;
|
||||
DeclInfo *decl = entry->value;
|
||||
Scope *scope = e->scope;
|
||||
|
||||
if (!scope->is_file) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (map_get(&m->min_dep_map, hash_pointer(e)) == NULL) {
|
||||
// NOTE(bill): Nothing depends upon it so doesn't need to be built
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!scope->is_global && !scope->is_init) {
|
||||
name = ssa_mangle_name(s, e->token.pos.file, name);
|
||||
}
|
||||
|
||||
|
||||
switch (e->kind) {
|
||||
case Entity_TypeName:
|
||||
GB_ASSERT(e->type->kind == Type_Named);
|
||||
map_set(&m->type_names, hash_pointer(e->type), name);
|
||||
ssa_gen_global_type_name(m, e, name);
|
||||
break;
|
||||
|
||||
case Entity_Variable: {
|
||||
ssaValue *g = ssa_make_value_global(a, e, NULL);
|
||||
if (decl->var_decl_tags & VarDeclTag_thread_local) {
|
||||
g->Global.is_thread_local = true;
|
||||
}
|
||||
ssaGlobalVariable var = {};
|
||||
var.var = g;
|
||||
var.decl = decl;
|
||||
|
||||
if (decl->init_expr != NULL) {
|
||||
TypeAndValue *tav = map_get(&info->types, hash_pointer(decl->init_expr));
|
||||
if (tav != NULL) {
|
||||
if (tav->value.kind != ExactValue_Invalid) {
|
||||
ExactValue v = tav->value;
|
||||
// if (v.kind != ExactValue_String) {
|
||||
g->Global.value = ssa_add_module_constant(m, tav->type, v);
|
||||
// }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (g->Global.value == NULL) {
|
||||
array_add(&global_variables, var);
|
||||
}
|
||||
|
||||
map_set(&m->values, hash_pointer(e), g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
} break;
|
||||
|
||||
case Entity_Procedure: {
|
||||
auto *pd = &decl->proc_decl->ProcDecl;
|
||||
String original_name = name;
|
||||
AstNode *body = pd->body;
|
||||
if (pd->tags & ProcTag_foreign) {
|
||||
name = pd->name->Ident.string;
|
||||
}
|
||||
if (pd->foreign_name.len > 0) {
|
||||
name = pd->foreign_name;
|
||||
} else if (pd->link_name.len > 0) {
|
||||
name = pd->link_name;
|
||||
}
|
||||
|
||||
ssaValue *p = ssa_make_value_procedure(a, m, e, e->type, decl->type_expr, body, name);
|
||||
p->Proc.tags = pd->tags;
|
||||
|
||||
map_set(&m->values, hash_pointer(e), p);
|
||||
HashKey hash_name = hash_string(name);
|
||||
if (map_get(&m->members, hash_name) == NULL) {
|
||||
map_set(&m->members, hash_name, p);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
for_array(i, m->members.entries) {
|
||||
auto *entry = &m->members.entries[i];
|
||||
ssaValue *v = entry->value;
|
||||
if (v->kind == ssaValue_Proc)
|
||||
ssa_build_proc(v, NULL);
|
||||
}
|
||||
|
||||
ssaDebugInfo *compile_unit = m->debug_info.entries[0].value;
|
||||
GB_ASSERT(compile_unit->kind == ssaDebugInfo_CompileUnit);
|
||||
ssaDebugInfo *all_procs = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_AllProcs);
|
||||
|
||||
isize all_proc_max_count = 0;
|
||||
for_array(i, m->debug_info.entries) {
|
||||
auto *entry = &m->debug_info.entries[i];
|
||||
ssaDebugInfo *di = entry->value;
|
||||
di->id = i;
|
||||
if (di->kind == ssaDebugInfo_Proc) {
|
||||
all_proc_max_count++;
|
||||
}
|
||||
}
|
||||
|
||||
array_init(&all_procs->AllProcs.procs, m->allocator, all_proc_max_count);
|
||||
map_set(&m->debug_info, hash_pointer(all_procs), all_procs); // NOTE(bill): This doesn't need to be mapped
|
||||
compile_unit->CompileUnit.all_procs = all_procs;
|
||||
|
||||
|
||||
for_array(i, m->debug_info.entries) {
|
||||
auto *entry = &m->debug_info.entries[i];
|
||||
ssaDebugInfo *di = entry->value;
|
||||
di->id = i;
|
||||
if (di->kind == ssaDebugInfo_Proc) {
|
||||
array_add(&all_procs->AllProcs.procs, di);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
{ // Startup Runtime
|
||||
// Cleanup(bill): probably better way of doing code insertion
|
||||
String name = make_string(SSA_STARTUP_RUNTIME_PROC_NAME);
|
||||
Type *proc_type = make_type_proc(a, gb_alloc_item(a, Scope),
|
||||
NULL, 0,
|
||||
NULL, 0, false);
|
||||
AstNode *body = gb_alloc_item(a, AstNode);
|
||||
ssaValue *p = ssa_make_value_procedure(a, m, NULL, proc_type, NULL, body, name);
|
||||
Token token = {};
|
||||
token.string = name;
|
||||
Entity *e = make_entity_procedure(a, NULL, token, proc_type);
|
||||
|
||||
map_set(&m->values, hash_pointer(e), p);
|
||||
map_set(&m->members, hash_string(name), p);
|
||||
|
||||
ssaProcedure *proc = &p->Proc;
|
||||
proc->tags = ProcTag_no_inline; // TODO(bill): is no_inline a good idea?
|
||||
|
||||
ssa_begin_procedure_body(proc);
|
||||
|
||||
// TODO(bill): Should do a dependency graph do check which order to initialize them in?
|
||||
for_array(i, global_variables) {
|
||||
ssaGlobalVariable *var = &global_variables[i];
|
||||
if (var->decl->init_expr != NULL) {
|
||||
var->init = ssa_build_expr(proc, var->decl->init_expr);
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE(bill): Initialize constants first
|
||||
for_array(i, global_variables) {
|
||||
ssaGlobalVariable *var = &global_variables[i];
|
||||
if (var->init != NULL) {
|
||||
if (var->init->kind == ssaValue_Constant) {
|
||||
ssa_emit_store(proc, var->var, var->init);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for_array(i, global_variables) {
|
||||
ssaGlobalVariable *var = &global_variables[i];
|
||||
if (var->init != NULL) {
|
||||
if (var->init->kind != ssaValue_Constant) {
|
||||
ssa_emit_store(proc, var->var, var->init);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ // NOTE(bill): Setup type_info data
|
||||
// TODO(bill): Try and make a lot of this constant aggregate literals in LLVM IR
|
||||
ssaValue *type_info_data = NULL;
|
||||
ssaValue *type_info_member_data = NULL;
|
||||
|
||||
ssaValue **found = NULL;
|
||||
found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_NAME)));
|
||||
GB_ASSERT(found != NULL);
|
||||
type_info_data = *found;
|
||||
|
||||
found = map_get(&proc->module->members, hash_string(make_string(SSA_TYPE_INFO_DATA_MEMBER_NAME)));
|
||||
GB_ASSERT(found != NULL);
|
||||
type_info_member_data = *found;
|
||||
|
||||
CheckerInfo *info = proc->module->info;
|
||||
|
||||
// Useful types
|
||||
Type *t_i64_slice_ptr = make_type_pointer(a, make_type_slice(a, t_i64));
|
||||
Type *t_string_slice_ptr = make_type_pointer(a, make_type_slice(a, t_string));
|
||||
|
||||
auto get_type_info_ptr = [](ssaProcedure *proc, ssaValue *type_info_data, Type *type) -> ssaValue * {
|
||||
i32 index = cast(i32)ssa_type_info_index(proc->module->info, type);
|
||||
// gb_printf_err("%d %s\n", index, type_to_string(type));
|
||||
return ssa_emit_array_ep(proc, type_info_data, index);
|
||||
};
|
||||
|
||||
i32 type_info_member_index = 0;
|
||||
|
||||
auto type_info_member_offset = [](ssaProcedure *proc, ssaValue *data, isize count, i32 *index) -> ssaValue * {
|
||||
ssaValue *offset = ssa_emit_array_ep(proc, data, *index);
|
||||
*index += count;
|
||||
return offset;
|
||||
};
|
||||
|
||||
|
||||
|
||||
for_array(type_info_map_index, info->type_info_map.entries) {
|
||||
auto *entry = &info->type_info_map.entries[type_info_map_index];
|
||||
Type *t = cast(Type *)cast(uintptr)entry->key.key;
|
||||
t = default_type(t);
|
||||
isize entry_index = entry->value;
|
||||
|
||||
ssaValue *tag = NULL;
|
||||
|
||||
switch (t->kind) {
|
||||
case Type_Named: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_named);
|
||||
|
||||
// TODO(bill): Which is better? The mangled name or actual name?
|
||||
ssaValue *name = ssa_make_const_string(a, t->Named.type_name->token.string);
|
||||
ssaValue *gtip = get_type_info_ptr(proc, type_info_data, t->Named.base);
|
||||
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), name);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), gtip);
|
||||
} break;
|
||||
|
||||
case Type_Basic:
|
||||
switch (t->Basic.kind) {
|
||||
case Basic_bool:
|
||||
tag = ssa_add_local_generated(proc, t_type_info_boolean);
|
||||
break;
|
||||
case Basic_i8:
|
||||
case Basic_i16:
|
||||
case Basic_i32:
|
||||
case Basic_i64:
|
||||
case Basic_u8:
|
||||
case Basic_u16:
|
||||
case Basic_u32:
|
||||
case Basic_u64:
|
||||
case Basic_int:
|
||||
case Basic_uint: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_integer);
|
||||
b32 is_unsigned = (t->Basic.flags & BasicFlag_Unsigned) != 0;
|
||||
ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||
ssaValue *is_signed = ssa_make_const_bool(a, !is_unsigned);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), bits);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), is_signed);
|
||||
} break;
|
||||
|
||||
case Basic_f32:
|
||||
case Basic_f64: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_float);
|
||||
ssaValue *bits = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), bits);
|
||||
} break;
|
||||
|
||||
case Basic_rawptr:
|
||||
tag = ssa_add_local_generated(proc, t_type_info_pointer);
|
||||
break;
|
||||
|
||||
case Basic_string:
|
||||
tag = ssa_add_local_generated(proc, t_type_info_string);
|
||||
break;
|
||||
|
||||
case Basic_any:
|
||||
tag = ssa_add_local_generated(proc, t_type_info_any);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Pointer: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_pointer);
|
||||
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Pointer.elem);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), gep);
|
||||
} break;
|
||||
case Type_Maybe: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_maybe);
|
||||
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Maybe.elem);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), gep);
|
||||
} break;
|
||||
case Type_Array: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_array);
|
||||
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Array.elem);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), gep);
|
||||
|
||||
isize ez = type_size_of(m->sizes, a, t->Array.elem);
|
||||
ssaValue *elem_size = ssa_emit_struct_ep(proc, tag, 1);
|
||||
ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
|
||||
|
||||
ssaValue *count = ssa_emit_struct_ep(proc, tag, 2);
|
||||
ssa_emit_store(proc, count, ssa_make_const_int(a, t->Array.count));
|
||||
|
||||
} break;
|
||||
case Type_Slice: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_slice);
|
||||
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Slice.elem);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), gep);
|
||||
|
||||
isize ez = type_size_of(m->sizes, a, t->Slice.elem);
|
||||
ssaValue *elem_size = ssa_emit_struct_ep(proc, tag, 1);
|
||||
ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
|
||||
|
||||
} break;
|
||||
case Type_Vector: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_vector);
|
||||
ssaValue *gep = get_type_info_ptr(proc, type_info_data, t->Vector.elem);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 0), gep);
|
||||
|
||||
isize ez = type_size_of(m->sizes, a, t->Vector.elem);
|
||||
ssaValue *elem_size = ssa_emit_struct_ep(proc, tag, 1);
|
||||
ssa_emit_store(proc, elem_size, ssa_make_const_int(a, ez));
|
||||
|
||||
ssaValue *count = ssa_emit_struct_ep(proc, tag, 2);
|
||||
ssa_emit_store(proc, count, ssa_make_const_int(a, t->Vector.count));
|
||||
|
||||
} break;
|
||||
case Type_Record: {
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_struct);
|
||||
|
||||
{
|
||||
ssaValue *packed = ssa_make_const_bool(a, t->Record.struct_is_packed);
|
||||
ssaValue *ordered = ssa_make_const_bool(a, t->Record.struct_is_ordered);
|
||||
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), size);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 2), align);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 3), packed);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 4), ordered);
|
||||
}
|
||||
|
||||
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
|
||||
|
||||
type_set_offsets(m->sizes, a, t); // NOTE(bill): Just incase the offsets have not been set yet
|
||||
for (isize source_index = 0; source_index < t->Record.field_count; source_index++) {
|
||||
// TODO(bill): Order fields in source order not layout order
|
||||
Entity *f = t->Record.fields_in_src_order[source_index];
|
||||
ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
|
||||
i64 foffset = t->Record.struct_offsets[f->Variable.field_index];
|
||||
GB_ASSERT(f->kind == Entity_Variable && f->flags & EntityFlag_Field);
|
||||
|
||||
ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, source_index));
|
||||
ssaValue *name = ssa_emit_struct_ep(proc, field, 0);
|
||||
ssaValue *type_info = ssa_emit_struct_ep(proc, field, 1);
|
||||
ssaValue *offset = ssa_emit_struct_ep(proc, field, 2);
|
||||
|
||||
if (f->token.string.len > 0) {
|
||||
ssa_emit_store(proc, name, ssa_make_const_string(a, f->token.string));
|
||||
}
|
||||
ssa_emit_store(proc, type_info, tip);
|
||||
ssa_emit_store(proc, offset, ssa_make_const_int(a, foffset));
|
||||
}
|
||||
|
||||
Type *slice_type = make_type_slice(a, t_type_info_member);
|
||||
Type *slice_type_ptr = make_type_pointer(a, slice_type);
|
||||
ssaValue *slice = ssa_emit_struct_ep(proc, tag, 0);
|
||||
ssaValue *field_count = ssa_make_const_int(a, t->Record.field_count);
|
||||
|
||||
ssaValue *elem = ssa_emit_struct_ep(proc, slice, 0);
|
||||
ssaValue *len = ssa_emit_struct_ep(proc, slice, 1);
|
||||
ssaValue *cap = ssa_emit_struct_ep(proc, slice, 2);
|
||||
|
||||
ssa_emit_store(proc, elem, memory);
|
||||
ssa_emit_store(proc, len, field_count);
|
||||
ssa_emit_store(proc, cap, field_count);
|
||||
} break;
|
||||
case TypeRecord_Union:
|
||||
tag = ssa_add_local_generated(proc, t_type_info_union);
|
||||
{
|
||||
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), size);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 2), align);
|
||||
}
|
||||
break;
|
||||
case TypeRecord_RawUnion: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_raw_union);
|
||||
{
|
||||
ssaValue *size = ssa_make_const_int(a, type_size_of(m->sizes, a, t));
|
||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 1), size);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 2), align);
|
||||
}
|
||||
|
||||
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Record.field_count, &type_info_member_index);
|
||||
|
||||
for (isize i = 0; i < t->Record.field_count; i++) {
|
||||
ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, i));
|
||||
ssaValue *name = ssa_emit_struct_ep(proc, field, 0);
|
||||
ssaValue *type_info = ssa_emit_struct_ep(proc, field, 1);
|
||||
ssaValue *offset = ssa_emit_struct_ep(proc, field, 2);
|
||||
|
||||
Entity *f = t->Record.fields[i];
|
||||
ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
|
||||
|
||||
if (f->token.string.len > 0) {
|
||||
ssa_emit_store(proc, name, ssa_make_const_string(a, f->token.string));
|
||||
}
|
||||
ssa_emit_store(proc, type_info, tip);
|
||||
ssa_emit_store(proc, offset, ssa_make_const_int(a, 0));
|
||||
}
|
||||
|
||||
Type *slice_type = make_type_slice(a, t_type_info_member);
|
||||
Type *slice_type_ptr = make_type_pointer(a, slice_type);
|
||||
ssaValue *slice = ssa_emit_struct_ep(proc, tag, 0);
|
||||
ssaValue *field_count = ssa_make_const_int(a, t->Record.field_count);
|
||||
|
||||
ssaValue *elem = ssa_emit_struct_ep(proc, slice, 0);
|
||||
ssaValue *len = ssa_emit_struct_ep(proc, slice, 1);
|
||||
ssaValue *cap = ssa_emit_struct_ep(proc, slice, 2);
|
||||
|
||||
ssa_emit_store(proc, elem, memory);
|
||||
ssa_emit_store(proc, len, field_count);
|
||||
ssa_emit_store(proc, cap, field_count);
|
||||
} break;
|
||||
case TypeRecord_Enum: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_enum);
|
||||
Type *enum_base = t->Record.enum_base;
|
||||
if (enum_base == NULL) {
|
||||
enum_base = t_int;
|
||||
}
|
||||
ssaValue *base = ssa_emit_struct_ep(proc, tag, 0);
|
||||
ssa_emit_store(proc, base, get_type_info_ptr(proc, type_info_data, enum_base));
|
||||
|
||||
if (t->Record.other_field_count > 0) {
|
||||
Entity **fields = t->Record.other_fields;
|
||||
isize count = t->Record.other_field_count;
|
||||
ssaValue *value_array = NULL;
|
||||
ssaValue *name_array = NULL;
|
||||
|
||||
|
||||
{
|
||||
Token token = {Token_Identifier};
|
||||
i32 id = cast(i32)entry_index;
|
||||
char name_base[] = "__$enum_values";
|
||||
isize name_len = gb_size_of(name_base) + 10;
|
||||
token.string.text = gb_alloc_array(a, u8, name_len);
|
||||
token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
|
||||
"%s-%d", name_base, id)-1;
|
||||
Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_i64, count));
|
||||
value_array = ssa_make_value_global(a, e, NULL);
|
||||
value_array->Global.is_private = true;
|
||||
ssa_module_add_value(m, e, value_array);
|
||||
map_set(&m->members, hash_string(token.string), value_array);
|
||||
}
|
||||
{
|
||||
Token token = {Token_Identifier};
|
||||
i32 id = cast(i32)entry_index;
|
||||
char name_base[] = "__$enum_names";
|
||||
isize name_len = gb_size_of(name_base) + 10;
|
||||
token.string.text = gb_alloc_array(a, u8, name_len);
|
||||
token.string.len = gb_snprintf(cast(char *)token.string.text, name_len,
|
||||
"%s-%d", name_base, id)-1;
|
||||
Entity *e = make_entity_variable(a, NULL, token, make_type_array(a, t_string, count));
|
||||
name_array = ssa_make_value_global(a, e, NULL);
|
||||
name_array->Global.is_private = true;
|
||||
ssa_module_add_value(m, e, name_array);
|
||||
map_set(&m->members, hash_string(token.string), name_array);
|
||||
}
|
||||
|
||||
for (isize i = 0; i < count; i++) {
|
||||
ssaValue *value_gep = ssa_emit_struct_ep(proc, value_array, i);
|
||||
ssaValue *name_gep = ssa_emit_struct_ep(proc, name_array, i);
|
||||
|
||||
ssa_emit_store(proc, value_gep, ssa_make_const_i64(a, fields[i]->Constant.value.value_integer));
|
||||
ssa_emit_store(proc, name_gep, ssa_make_const_string(a, fields[i]->token.string));
|
||||
}
|
||||
|
||||
ssaValue *v_count = ssa_make_const_int(a, count);
|
||||
|
||||
|
||||
ssaValue *values = ssa_emit_struct_ep(proc, tag, 1);
|
||||
ssaValue *names = ssa_emit_struct_ep(proc, tag, 2);
|
||||
ssaValue *value_slice = ssa_add_local_generated(proc, type_deref(t_i64_slice_ptr));
|
||||
ssaValue *name_slice = ssa_add_local_generated(proc, type_deref(t_string_slice_ptr));
|
||||
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 0), ssa_array_elem(proc, value_array));
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 1), v_count);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, value_slice, 2), v_count);
|
||||
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 0), ssa_array_elem(proc, name_array));
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 1), v_count);
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, name_slice, 2), v_count);
|
||||
|
||||
ssa_emit_store(proc, values, ssa_emit_load(proc, value_slice));
|
||||
ssa_emit_store(proc, names, ssa_emit_load(proc, name_slice));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Tuple: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_tuple);
|
||||
|
||||
{
|
||||
ssaValue *align = ssa_make_const_int(a, type_align_of(m->sizes, a, t));
|
||||
ssa_emit_store(proc, ssa_emit_struct_ep(proc, tag, 2), align);
|
||||
}
|
||||
|
||||
ssaValue *memory = type_info_member_offset(proc, type_info_member_data, t->Tuple.variable_count, &type_info_member_index);
|
||||
|
||||
for (isize i = 0; i < t->Tuple.variable_count; i++) {
|
||||
ssaValue *field = ssa_emit_ptr_offset(proc, memory, ssa_make_const_int(a, i));
|
||||
ssaValue *name = ssa_emit_struct_ep(proc, field, 0);
|
||||
ssaValue *type_info = ssa_emit_struct_ep(proc, field, 1);
|
||||
// NOTE(bill): offset is not used for tuples
|
||||
|
||||
Entity *f = t->Tuple.variables[i];
|
||||
ssaValue *tip = get_type_info_ptr(proc, type_info_data, f->type);
|
||||
|
||||
if (f->token.string.len > 0) {
|
||||
ssa_emit_store(proc, name, ssa_make_const_string(a, f->token.string));
|
||||
}
|
||||
ssa_emit_store(proc, type_info, tip);
|
||||
}
|
||||
|
||||
Type *slice_type = make_type_slice(a, t_type_info_member);
|
||||
Type *slice_type_ptr = make_type_pointer(a, slice_type);
|
||||
ssaValue *slice = ssa_emit_struct_ep(proc, tag, 0);
|
||||
ssaValue *variable_count = ssa_make_const_int(a, t->Tuple.variable_count);
|
||||
|
||||
ssaValue *elem = ssa_emit_struct_ep(proc, slice, 0);
|
||||
ssaValue *len = ssa_emit_struct_ep(proc, slice, 1);
|
||||
ssaValue *cap = ssa_emit_struct_ep(proc, slice, 2);
|
||||
|
||||
ssa_emit_store(proc, elem, memory);
|
||||
ssa_emit_store(proc, len, variable_count);
|
||||
ssa_emit_store(proc, cap, variable_count);
|
||||
} break;
|
||||
|
||||
case Type_Proc: {
|
||||
tag = ssa_add_local_generated(proc, t_type_info_procedure);
|
||||
|
||||
ssaValue *params = ssa_emit_struct_ep(proc, tag, 0);
|
||||
ssaValue *results = ssa_emit_struct_ep(proc, tag, 1);
|
||||
ssaValue *variadic = ssa_emit_struct_ep(proc, tag, 2);
|
||||
|
||||
if (t->Proc.params) {
|
||||
ssa_emit_store(proc, params, get_type_info_ptr(proc, type_info_data, t->Proc.params));
|
||||
}
|
||||
if (t->Proc.results) {
|
||||
ssa_emit_store(proc, results, get_type_info_ptr(proc, type_info_data, t->Proc.results));
|
||||
}
|
||||
ssa_emit_store(proc, variadic, ssa_make_const_bool(a, t->Proc.variadic));
|
||||
|
||||
// TODO(bill): Type_Info for procedures
|
||||
} break;
|
||||
}
|
||||
|
||||
if (tag != NULL) {
|
||||
ssaValue *gep = ssa_emit_array_ep(proc, type_info_data, entry_index);
|
||||
ssaValue *val = ssa_emit_conv(proc, ssa_emit_load(proc, tag), t_type_info);
|
||||
ssa_emit_store(proc, gep, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssa_end_procedure_body(proc);
|
||||
}
|
||||
|
||||
for_array(i, m->procs) {
|
||||
ssa_build_proc(m->procs[i], m->procs[i]->Proc.parent);
|
||||
}
|
||||
|
||||
|
||||
// m->layout = make_string("e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64");
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
ssaDebugInfo *ssa_add_debug_info_file(ssaProcedure *proc, AstFile *file) {
|
||||
if (!proc->module->generate_debug_info) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GB_ASSERT(file != NULL);
|
||||
ssaDebugInfo *di = ssa_alloc_debug_info(proc->module->allocator, ssaDebugInfo_File);
|
||||
di->File.file = file;
|
||||
|
||||
String filename = file->tokenizer.fullpath;
|
||||
String directory = filename;
|
||||
isize slash_index = 0;
|
||||
for (isize i = filename.len-1; i >= 0; i--) {
|
||||
if (filename.text[i] == '\\' ||
|
||||
filename.text[i] == '/') {
|
||||
break;
|
||||
}
|
||||
slash_index = i;
|
||||
}
|
||||
directory.len = slash_index-1;
|
||||
filename.text = filename.text + slash_index;
|
||||
filename.len -= slash_index;
|
||||
|
||||
|
||||
di->File.filename = filename;
|
||||
di->File.directory = directory;
|
||||
|
||||
map_set(&proc->module->debug_info, hash_pointer(file), di);
|
||||
return di;
|
||||
}
|
||||
|
||||
|
||||
ssaDebugInfo *ssa_add_debug_info_proc(ssaProcedure *proc, Entity *entity, String name, ssaDebugInfo *file) {
|
||||
if (!proc->module->generate_debug_info) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
GB_ASSERT(entity != NULL);
|
||||
ssaDebugInfo *di = ssa_alloc_debug_info(proc->module->allocator, ssaDebugInfo_Proc);
|
||||
di->Proc.entity = entity;
|
||||
di->Proc.name = name;
|
||||
di->Proc.file = file;
|
||||
di->Proc.pos = entity->token.pos;
|
||||
|
||||
map_set(&proc->module->debug_info, hash_pointer(entity), di);
|
||||
return di;
|
||||
}
|
||||
|
||||
-1150
File diff suppressed because it is too large
Load Diff
@@ -1,495 +0,0 @@
|
||||
void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v);
|
||||
ssaValue *ssa_emit_zero_init(ssaProcedure *p, ssaValue *address);
|
||||
ssaValue *ssa_emit_comment(ssaProcedure *p, String text);
|
||||
ssaValue *ssa_emit_store(ssaProcedure *p, ssaValue *address, ssaValue *value);
|
||||
ssaValue *ssa_emit_load(ssaProcedure *p, ssaValue *address);
|
||||
|
||||
|
||||
ssaValue *ssa_alloc_value(gbAllocator a, ssaValueKind kind) {
|
||||
ssaValue *v = gb_alloc_item(a, ssaValue);
|
||||
v->kind = kind;
|
||||
return v;
|
||||
}
|
||||
ssaValue *ssa_alloc_instr(ssaProcedure *proc, ssaInstrKind kind) {
|
||||
ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Instr);
|
||||
v->Instr.kind = kind;
|
||||
proc->instr_count++;
|
||||
return v;
|
||||
}
|
||||
ssaDebugInfo *ssa_alloc_debug_info(gbAllocator a, ssaDebugInfoKind kind) {
|
||||
ssaDebugInfo *di = gb_alloc_item(a, ssaDebugInfo);
|
||||
di->kind = kind;
|
||||
return di;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_make_value_type_name(gbAllocator a, String name, Type *type) {
|
||||
ssaValue *v = ssa_alloc_value(a, ssaValue_TypeName);
|
||||
v->TypeName.name = name;
|
||||
v->TypeName.type = type;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_value_global(gbAllocator a, Entity *e, ssaValue *value) {
|
||||
ssaValue *v = ssa_alloc_value(a, ssaValue_Global);
|
||||
v->Global.entity = e;
|
||||
v->Global.type = make_type_pointer(a, e->type);
|
||||
v->Global.value = value;
|
||||
array_init(&v->Global.referrers, heap_allocator()); // TODO(bill): Replace heap allocator here
|
||||
return v;
|
||||
}
|
||||
ssaValue *ssa_make_value_param(gbAllocator a, ssaProcedure *parent, Entity *e) {
|
||||
ssaValue *v = ssa_alloc_value(a, ssaValue_Param);
|
||||
v->Param.parent = parent;
|
||||
v->Param.entity = e;
|
||||
v->Param.type = e->type;
|
||||
array_init(&v->Param.referrers, heap_allocator()); // TODO(bill): Replace heap allocator here
|
||||
return v;
|
||||
}
|
||||
ssaValue *ssa_make_value_nil(gbAllocator a, Type *type) {
|
||||
ssaValue *v = ssa_alloc_value(a, ssaValue_Nil);
|
||||
v->Nil.type = type;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_make_instr_local(ssaProcedure *p, Entity *e, b32 zero_initialized) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Local);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->Local.entity = e;
|
||||
i->Local.type = make_type_pointer(p->module->allocator, e->type);
|
||||
i->Local.zero_initialized = zero_initialized;
|
||||
array_init(&i->Local.referrers, heap_allocator()); // TODO(bill): Replace heap allocator here
|
||||
ssa_module_add_value(p->module, e, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_make_instr_store(ssaProcedure *p, ssaValue *address, ssaValue *value) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Store);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->Store.address = address;
|
||||
i->Store.value = value;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_zero_init(ssaProcedure *p, ssaValue *address) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_ZeroInit);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->ZeroInit.address = address;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_load(ssaProcedure *p, ssaValue *address) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Load);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->Load.address = address;
|
||||
i->Load.type = type_deref(ssa_type(address));
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_array_element_ptr(ssaProcedure *p, ssaValue *address, ssaValue *elem_index) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_ArrayElementPtr);
|
||||
ssaInstr *i = &v->Instr;
|
||||
Type *t = ssa_type(address);
|
||||
GB_ASSERT(is_type_pointer(t));
|
||||
t = base_type(type_deref(t));
|
||||
GB_ASSERT(is_type_array(t));
|
||||
|
||||
Type *result_type = make_type_pointer(p->module->allocator, t->Array.elem);
|
||||
|
||||
i->ArrayElementPtr.address = address;
|
||||
i->ArrayElementPtr.elem_index = elem_index;
|
||||
i->ArrayElementPtr.result_type = result_type;
|
||||
|
||||
GB_ASSERT_MSG(is_type_pointer(ssa_type(address)),
|
||||
"%s", type_to_string(ssa_type(address)));
|
||||
return v;
|
||||
}
|
||||
ssaValue *ssa_make_instr_struct_element_ptr(ssaProcedure *p, ssaValue *address, i32 elem_index, Type *result_type) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_StructElementPtr);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->StructElementPtr.address = address;
|
||||
i->StructElementPtr.elem_index = elem_index;
|
||||
i->StructElementPtr.result_type = result_type;
|
||||
|
||||
GB_ASSERT_MSG(is_type_pointer(ssa_type(address)),
|
||||
"%s", type_to_string(ssa_type(address)));
|
||||
return v;
|
||||
}
|
||||
ssaValue *ssa_make_instr_ptr_offset(ssaProcedure *p, ssaValue *address, ssaValue *offset) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_PtrOffset);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->PtrOffset.address = address;
|
||||
i->PtrOffset.offset = offset;
|
||||
|
||||
GB_ASSERT_MSG(is_type_pointer(ssa_type(address)),
|
||||
"%s", type_to_string(ssa_type(address)));
|
||||
GB_ASSERT_MSG(is_type_integer(ssa_type(offset)),
|
||||
"%s", type_to_string(ssa_type(address)));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_make_instr_array_extract_value(ssaProcedure *p, ssaValue *address, i32 index) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_ArrayExtractValue);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->ArrayExtractValue.address = address;
|
||||
i->ArrayExtractValue.index = index;
|
||||
Type *t = base_type(ssa_type(address));
|
||||
GB_ASSERT(is_type_array(t));
|
||||
i->ArrayExtractValue.result_type = t->Array.elem;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_struct_extract_value(ssaProcedure *p, ssaValue *address, i32 index, Type *result_type) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_StructExtractValue);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->StructExtractValue.address = address;
|
||||
i->StructExtractValue.index = index;
|
||||
i->StructExtractValue.result_type = result_type;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_binary_op(ssaProcedure *p, TokenKind op, ssaValue *left, ssaValue *right, Type *type) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_BinaryOp);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->BinaryOp.op = op;
|
||||
i->BinaryOp.left = left;
|
||||
i->BinaryOp.right = right;
|
||||
i->BinaryOp.type = type;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_jump(ssaProcedure *p, ssaBlock *block) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Jump);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->Jump.block = block;
|
||||
return v;
|
||||
}
|
||||
ssaValue *ssa_make_instr_if(ssaProcedure *p, ssaValue *cond, ssaBlock *true_block, ssaBlock *false_block) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_If);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->If.cond = cond;
|
||||
i->If.true_block = true_block;
|
||||
i->If.false_block = false_block;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_make_instr_phi(ssaProcedure *p, Array<ssaValue *> edges, Type *type) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Phi);
|
||||
ssaInstr *i = &v->Instr;
|
||||
i->Phi.edges = edges;
|
||||
i->Phi.type = type;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_unreachable(ssaProcedure *p) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Unreachable);
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_return(ssaProcedure *p, ssaValue *value) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Return);
|
||||
v->Instr.Return.value = value;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_select(ssaProcedure *p, ssaValue *cond, ssaValue *t, ssaValue *f) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Select);
|
||||
v->Instr.Select.cond = cond;
|
||||
v->Instr.Select.true_value = t;
|
||||
v->Instr.Select.false_value = f;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_call(ssaProcedure *p, ssaValue *value, ssaValue **args, isize arg_count, Type *result_type) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Call);
|
||||
v->Instr.Call.value = value;
|
||||
v->Instr.Call.args = args;
|
||||
v->Instr.Call.arg_count = arg_count;
|
||||
v->Instr.Call.type = result_type;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_conv(ssaProcedure *p, ssaConvKind kind, ssaValue *value, Type *from, Type *to) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Conv);
|
||||
v->Instr.Conv.kind = kind;
|
||||
v->Instr.Conv.value = value;
|
||||
v->Instr.Conv.from = from;
|
||||
v->Instr.Conv.to = to;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_extract_element(ssaProcedure *p, ssaValue *vector, ssaValue *index) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_VectorExtractElement);
|
||||
v->Instr.VectorExtractElement.vector = vector;
|
||||
v->Instr.VectorExtractElement.index = index;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_insert_element(ssaProcedure *p, ssaValue *vector, ssaValue *elem, ssaValue *index) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_VectorInsertElement);
|
||||
v->Instr.VectorInsertElement.vector = vector;
|
||||
v->Instr.VectorInsertElement.elem = elem;
|
||||
v->Instr.VectorInsertElement.index = index;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_vector_shuffle(ssaProcedure *p, ssaValue *vector, i32 *indices, isize index_count) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_VectorShuffle);
|
||||
v->Instr.VectorShuffle.vector = vector;
|
||||
v->Instr.VectorShuffle.indices = indices;
|
||||
v->Instr.VectorShuffle.index_count = index_count;
|
||||
|
||||
Type *vt = base_type(ssa_type(vector));
|
||||
v->Instr.VectorShuffle.type = make_type_vector(p->module->allocator, vt->Vector.elem, index_count);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_comment(ssaProcedure *p, String text) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_Comment);
|
||||
v->Instr.Comment.text = text;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_instr_bounds_check(ssaProcedure *p, TokenPos pos, ssaValue *index, ssaValue *len) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_BoundsCheck);
|
||||
v->Instr.BoundsCheck.pos = pos;
|
||||
v->Instr.BoundsCheck.index = index;
|
||||
v->Instr.BoundsCheck.len = len;
|
||||
return v;
|
||||
}
|
||||
ssaValue *ssa_make_instr_slice_bounds_check(ssaProcedure *p, TokenPos pos, ssaValue *low, ssaValue *high, ssaValue *max, b32 is_substring) {
|
||||
ssaValue *v = ssa_alloc_instr(p, ssaInstr_SliceBoundsCheck);
|
||||
v->Instr.SliceBoundsCheck.pos = pos;
|
||||
v->Instr.SliceBoundsCheck.low = low;
|
||||
v->Instr.SliceBoundsCheck.high = high;
|
||||
v->Instr.SliceBoundsCheck.max = max;
|
||||
v->Instr.SliceBoundsCheck.is_substring = is_substring;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_make_value_constant(gbAllocator a, Type *type, ExactValue value) {
|
||||
ssaValue *v = ssa_alloc_value(a, ssaValue_Constant);
|
||||
v->Constant.type = type;
|
||||
v->Constant.value = value;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
ssaValue *ssa_make_value_constant_slice(gbAllocator a, Type *type, ssaValue *backing_array, i64 count) {
|
||||
ssaValue *v = ssa_alloc_value(a, ssaValue_ConstantSlice);
|
||||
v->ConstantSlice.type = type;
|
||||
v->ConstantSlice.backing_array = backing_array;
|
||||
v->ConstantSlice.count = count;
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_const_int(gbAllocator a, i64 i) {
|
||||
return ssa_make_value_constant(a, t_int, make_exact_value_integer(i));
|
||||
}
|
||||
ssaValue *ssa_make_const_i32(gbAllocator a, i64 i) {
|
||||
return ssa_make_value_constant(a, t_i32, make_exact_value_integer(i));
|
||||
}
|
||||
ssaValue *ssa_make_const_i64(gbAllocator a, i64 i) {
|
||||
return ssa_make_value_constant(a, t_i64, make_exact_value_integer(i));
|
||||
}
|
||||
ssaValue *ssa_make_const_bool(gbAllocator a, b32 b) {
|
||||
return ssa_make_value_constant(a, t_bool, make_exact_value_bool(b != 0));
|
||||
}
|
||||
ssaValue *ssa_make_const_string(gbAllocator a, String s) {
|
||||
return ssa_make_value_constant(a, t_string, make_exact_value_string(s));
|
||||
}
|
||||
|
||||
ssaValue *ssa_make_value_procedure(gbAllocator a, ssaModule *m, Entity *entity, Type *type, AstNode *type_expr, AstNode *body, String name) {
|
||||
ssaValue *v = ssa_alloc_value(a, ssaValue_Proc);
|
||||
v->Proc.module = m;
|
||||
v->Proc.entity = entity;
|
||||
v->Proc.type = type;
|
||||
v->Proc.type_expr = type_expr;
|
||||
v->Proc.body = body;
|
||||
v->Proc.name = name;
|
||||
array_init(&v->Proc.referrers, heap_allocator(), 0); // TODO(bill): replace heap allocator
|
||||
|
||||
Type *t = base_type(type);
|
||||
GB_ASSERT(is_type_proc(t));
|
||||
array_init(&v->Proc.params, heap_allocator(), t->Proc.param_count);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
ssaBlock *ssa_add_block(ssaProcedure *proc, AstNode *node, char *label) {
|
||||
Scope *scope = NULL;
|
||||
if (node != NULL) {
|
||||
Scope **found = map_get(&proc->module->info->scopes, hash_pointer(node));
|
||||
if (found) {
|
||||
scope = *found;
|
||||
} else {
|
||||
GB_PANIC("Block scope not found for %.*s", LIT(ast_node_strings[node->kind]));
|
||||
}
|
||||
}
|
||||
|
||||
ssaValue *v = ssa_alloc_value(proc->module->allocator, ssaValue_Block);
|
||||
v->Block.label = make_string(label);
|
||||
v->Block.node = node;
|
||||
v->Block.scope = scope;
|
||||
v->Block.parent = proc;
|
||||
|
||||
array_init(&v->Block.instrs, heap_allocator());
|
||||
array_init(&v->Block.locals, heap_allocator());
|
||||
|
||||
array_init(&v->Block.preds, heap_allocator());
|
||||
array_init(&v->Block.succs, heap_allocator());
|
||||
|
||||
ssaBlock *block = &v->Block;
|
||||
|
||||
array_add(&proc->blocks, block);
|
||||
proc->block_count++;
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ssaDefer ssa_add_defer_node(ssaProcedure *proc, isize scope_index, AstNode *stmt) {
|
||||
ssaDefer d = {ssaDefer_Node};
|
||||
d.scope_index = scope_index;
|
||||
d.block = proc->curr_block;
|
||||
d.stmt = stmt;
|
||||
array_add(&proc->defer_stmts, d);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
ssaDefer ssa_add_defer_instr(ssaProcedure *proc, isize scope_index, ssaValue *instr) {
|
||||
ssaDefer d = {ssaDefer_Instr};
|
||||
d.scope_index = proc->scope_index;
|
||||
d.block = proc->curr_block;
|
||||
d.instr = instr; // NOTE(bill): It will make a copy everytime it is called
|
||||
array_add(&proc->defer_stmts, d);
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_add_module_constant(ssaModule *m, Type *type, ExactValue value) {
|
||||
if (is_type_slice(type)) {
|
||||
ast_node(cl, CompoundLit, value.value_compound);
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
isize count = cl->elems.count;
|
||||
if (count == 0) {
|
||||
return ssa_make_value_nil(a, type);
|
||||
}
|
||||
Type *elem = base_type(type)->Slice.elem;
|
||||
Type *t = make_type_array(a, elem, count);
|
||||
ssaValue *backing_array = ssa_add_module_constant(m, t, value);
|
||||
|
||||
|
||||
isize max_len = 7+8+1;
|
||||
u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
|
||||
isize len = gb_snprintf(cast(char *)str, max_len, "__csba$%x", m->global_array_index);
|
||||
m->global_array_index++;
|
||||
|
||||
String name = make_string(str, len-1);
|
||||
|
||||
Entity *e = make_entity_constant(a, NULL, make_token_ident(name), t, value);
|
||||
ssaValue *g = ssa_make_value_global(a, e, backing_array);
|
||||
ssa_module_add_value(m, e, g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
|
||||
return ssa_make_value_constant_slice(a, type, g, count);
|
||||
}
|
||||
|
||||
return ssa_make_value_constant(m->allocator, type, value);
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_global_string_array(ssaModule *m, String string) {
|
||||
gbAllocator a = m->allocator;
|
||||
|
||||
isize max_len = 6+8+1;
|
||||
u8 *str = cast(u8 *)gb_alloc_array(a, u8, max_len);
|
||||
isize len = gb_snprintf(cast(char *)str, max_len, "__str$%x", m->global_string_index);
|
||||
m->global_string_index++;
|
||||
|
||||
String name = make_string(str, len-1);
|
||||
Token token = {Token_String};
|
||||
token.string = name;
|
||||
Type *type = make_type_array(a, t_u8, string.len);
|
||||
ExactValue ev = make_exact_value_string(string);
|
||||
Entity *entity = make_entity_constant(a, NULL, token, type, ev);
|
||||
ssaValue *g = ssa_make_value_global(a, entity, ssa_add_module_constant(m, type, ev));
|
||||
g->Global.is_private = true;
|
||||
// g->Global.is_unnamed_addr = true;
|
||||
// g->Global.is_constant = true;
|
||||
|
||||
ssa_module_add_value(m, entity, g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
|
||||
return g;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ssaValue *ssa_add_local(ssaProcedure *proc, Entity *e, b32 zero_initialized = true) {
|
||||
ssaBlock *b = proc->decl_block; // all variables must be in the first block
|
||||
ssaValue *instr = ssa_make_instr_local(proc, e, zero_initialized);
|
||||
instr->Instr.parent = b;
|
||||
array_add(&b->instrs, instr);
|
||||
array_add(&b->locals, instr);
|
||||
proc->local_count++;
|
||||
|
||||
// if (zero_initialized) {
|
||||
ssa_emit_zero_init(proc, instr);
|
||||
// }
|
||||
|
||||
return instr;
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_local_for_identifier(ssaProcedure *proc, AstNode *name, b32 zero_initialized) {
|
||||
Entity **found = map_get(&proc->module->info->definitions, hash_pointer(name));
|
||||
if (found) {
|
||||
Entity *e = *found;
|
||||
ssa_emit_comment(proc, e->token.string);
|
||||
return ssa_add_local(proc, e, zero_initialized);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_local_generated(ssaProcedure *proc, Type *type) {
|
||||
GB_ASSERT(type != NULL);
|
||||
|
||||
Scope *scope = NULL;
|
||||
if (proc->curr_block) {
|
||||
scope = proc->curr_block->scope;
|
||||
}
|
||||
Entity *e = make_entity_variable(proc->module->allocator,
|
||||
scope,
|
||||
empty_token,
|
||||
type);
|
||||
return ssa_add_local(proc, e, true);
|
||||
}
|
||||
|
||||
ssaValue *ssa_add_param(ssaProcedure *proc, Entity *e) {
|
||||
ssaValue *v = ssa_make_value_param(proc->module->allocator, proc, e);
|
||||
#if 1
|
||||
ssaValue *l = ssa_add_local(proc, e);
|
||||
ssa_emit_store(proc, l, v);
|
||||
#else
|
||||
ssa_module_add_value(proc->module, e, v);
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
void ssa_begin_procedure_body(ssaProcedure *proc) {
|
||||
array_init(&proc->blocks, heap_allocator());
|
||||
array_init(&proc->defer_stmts, heap_allocator());
|
||||
array_init(&proc->children, heap_allocator());
|
||||
|
||||
proc->decl_block = ssa_add_block(proc, proc->type_expr, "decls");
|
||||
proc->entry_block = ssa_add_block(proc, proc->type_expr, "entry");
|
||||
proc->curr_block = proc->entry_block;
|
||||
|
||||
if (proc->type->Proc.params != NULL) {
|
||||
auto *params = &proc->type->Proc.params->Tuple;
|
||||
for (isize i = 0; i < params->variable_count; i++) {
|
||||
Entity *e = params->variables[i];
|
||||
ssaValue *param = ssa_add_param(proc, e);
|
||||
array_add(&proc->params, param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ssa_end_procedure_body(ssaProcedure *proc) {
|
||||
if (proc->type->Proc.result_count == 0) {
|
||||
ssa_emit_return(proc, NULL);
|
||||
}
|
||||
|
||||
if (proc->curr_block->instrs.count == 0) {
|
||||
ssa_emit_unreachable(proc);
|
||||
}
|
||||
|
||||
proc->curr_block = proc->decl_block;
|
||||
ssa_emit_jump(proc, proc->entry_block);
|
||||
|
||||
ssa_opt_proc(proc);
|
||||
|
||||
// Number registers
|
||||
i32 reg_index = 0;
|
||||
for_array(i, proc->blocks) {
|
||||
ssaBlock *b = proc->blocks[i];
|
||||
b->index = i;
|
||||
for_array(j, b->instrs) {
|
||||
ssaValue *value = b->instrs[j];
|
||||
GB_ASSERT(value->kind == ssaValue_Instr);
|
||||
ssaInstr *instr = &value->Instr;
|
||||
if (ssa_instr_type(instr) == NULL) { // NOTE(bill): Ignore non-returning instructions
|
||||
continue;
|
||||
}
|
||||
value->index = reg_index;
|
||||
reg_index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ssa_insert_code_before_proc(ssaProcedure* proc, ssaProcedure *parent) {
|
||||
if (parent == NULL) {
|
||||
if (proc->name == "main") {
|
||||
ssa_emit_startup_runtime(proc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ssa_build_proc(ssaValue *value, ssaProcedure *parent) {
|
||||
ssaProcedure *proc = &value->Proc;
|
||||
|
||||
proc->parent = parent;
|
||||
|
||||
if (proc->entity != NULL) {
|
||||
ssaModule *m = proc->module;
|
||||
CheckerInfo *info = m->info;
|
||||
Entity *e = proc->entity;
|
||||
String filename = e->token.pos.file;
|
||||
AstFile **found = map_get(&info->files, hash_string(filename));
|
||||
GB_ASSERT(found != NULL);
|
||||
AstFile *f = *found;
|
||||
ssaDebugInfo *di_file = NULL;
|
||||
|
||||
ssaDebugInfo **di_file_found = map_get(&m->debug_info, hash_pointer(f));
|
||||
if (di_file_found) {
|
||||
di_file = *di_file_found;
|
||||
GB_ASSERT(di_file->kind == ssaDebugInfo_File);
|
||||
} else {
|
||||
di_file = ssa_add_debug_info_file(proc, f);
|
||||
}
|
||||
|
||||
ssa_add_debug_info_proc(proc, e, proc->name, di_file);
|
||||
}
|
||||
|
||||
if (proc->body != NULL) {
|
||||
u32 prev_stmt_state_flags = proc->module->stmt_state_flags;
|
||||
defer (proc->module->stmt_state_flags = prev_stmt_state_flags);
|
||||
|
||||
if (proc->tags != 0) {
|
||||
u32 in = proc->tags;
|
||||
u32 out = proc->module->stmt_state_flags;
|
||||
defer (proc->module->stmt_state_flags = out);
|
||||
|
||||
if (in & ProcTag_bounds_check) {
|
||||
out |= StmtStateFlag_bounds_check;
|
||||
out &= ~StmtStateFlag_no_bounds_check;
|
||||
} else if (in & ProcTag_no_bounds_check) {
|
||||
out |= StmtStateFlag_no_bounds_check;
|
||||
out &= ~StmtStateFlag_bounds_check;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ssa_begin_procedure_body(proc);
|
||||
ssa_insert_code_before_proc(proc, parent);
|
||||
ssa_build_stmt(proc, proc->body);
|
||||
ssa_end_procedure_body(proc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-846
@@ -1,846 +0,0 @@
|
||||
struct ssaProcedure;
|
||||
struct ssaBlock;
|
||||
struct ssaValue;
|
||||
struct ssaDebugInfo;
|
||||
|
||||
struct ssaModule {
|
||||
CheckerInfo * info;
|
||||
BaseTypeSizes sizes;
|
||||
gbArena arena;
|
||||
gbArena tmp_arena;
|
||||
gbAllocator allocator;
|
||||
gbAllocator tmp_allocator;
|
||||
b32 generate_debug_info;
|
||||
|
||||
u32 stmt_state_flags;
|
||||
|
||||
// String source_filename;
|
||||
String layout;
|
||||
// String triple;
|
||||
|
||||
|
||||
Map<Entity *> min_dep_map; // Key: Entity *
|
||||
Map<ssaValue *> values; // Key: Entity *
|
||||
Map<ssaValue *> members; // Key: String
|
||||
Map<String> type_names; // Key: Type *
|
||||
Map<ssaDebugInfo *> debug_info; // Key: Unique pointer
|
||||
i32 global_string_index;
|
||||
i32 global_array_index; // For ConstantSlice
|
||||
|
||||
Array<ssaValue *> procs; // NOTE(bill): Procedures to generate
|
||||
};
|
||||
|
||||
// NOTE(bill): For more info, see https://en.wikipedia.org/wiki/Dominator_(graph_theory)
|
||||
struct ssaDomNode {
|
||||
ssaBlock * idom; // Parent (Immediate Dominator)
|
||||
Array<ssaBlock *> children;
|
||||
i32 pre, post; // Ordering in tree
|
||||
};
|
||||
|
||||
|
||||
struct ssaBlock {
|
||||
i32 index;
|
||||
String label;
|
||||
ssaProcedure *parent;
|
||||
AstNode * node; // Can be NULL
|
||||
Scope * scope;
|
||||
isize scope_index;
|
||||
ssaDomNode dom;
|
||||
i32 gaps;
|
||||
|
||||
Array<ssaValue *> instrs;
|
||||
Array<ssaValue *> locals;
|
||||
|
||||
Array<ssaBlock *> preds;
|
||||
Array<ssaBlock *> succs;
|
||||
};
|
||||
|
||||
struct ssaTargetList {
|
||||
ssaTargetList *prev;
|
||||
ssaBlock * break_;
|
||||
ssaBlock * continue_;
|
||||
ssaBlock * fallthrough_;
|
||||
};
|
||||
|
||||
enum ssaDeferExitKind {
|
||||
ssaDeferExit_Default,
|
||||
ssaDeferExit_Return,
|
||||
ssaDeferExit_Branch,
|
||||
};
|
||||
enum ssaDeferKind {
|
||||
ssaDefer_Node,
|
||||
ssaDefer_Instr,
|
||||
};
|
||||
|
||||
struct ssaDefer {
|
||||
ssaDeferKind kind;
|
||||
isize scope_index;
|
||||
ssaBlock * block;
|
||||
union {
|
||||
AstNode *stmt;
|
||||
// NOTE(bill): `instr` will be copied every time to create a new one
|
||||
ssaValue *instr;
|
||||
};
|
||||
};
|
||||
|
||||
struct ssaProcedure {
|
||||
ssaProcedure * parent;
|
||||
Array<ssaProcedure *> children;
|
||||
|
||||
Entity * entity;
|
||||
ssaModule * module;
|
||||
String name;
|
||||
Type * type;
|
||||
AstNode * type_expr;
|
||||
AstNode * body;
|
||||
u64 tags;
|
||||
|
||||
Array<ssaValue *> params;
|
||||
Array<ssaDefer> defer_stmts;
|
||||
Array<ssaBlock *> blocks;
|
||||
i32 scope_index;
|
||||
ssaBlock * decl_block;
|
||||
ssaBlock * entry_block;
|
||||
ssaBlock * curr_block;
|
||||
ssaTargetList * target_list;
|
||||
Array<ssaValue *> referrers;
|
||||
|
||||
i32 local_count;
|
||||
i32 instr_count;
|
||||
i32 block_count;
|
||||
};
|
||||
|
||||
#define SSA_STARTUP_RUNTIME_PROC_NAME "__$startup_runtime"
|
||||
#define SSA_TYPE_INFO_DATA_NAME "__$type_info_data"
|
||||
#define SSA_TYPE_INFO_DATA_MEMBER_NAME "__$type_info_data_member"
|
||||
|
||||
|
||||
#define SSA_INSTR_KINDS \
|
||||
SSA_INSTR_KIND(Invalid), \
|
||||
SSA_INSTR_KIND(Comment), \
|
||||
SSA_INSTR_KIND(Local), \
|
||||
SSA_INSTR_KIND(ZeroInit), \
|
||||
SSA_INSTR_KIND(Store), \
|
||||
SSA_INSTR_KIND(Load), \
|
||||
SSA_INSTR_KIND(PtrOffset), \
|
||||
SSA_INSTR_KIND(ArrayElementPtr), \
|
||||
SSA_INSTR_KIND(StructElementPtr), \
|
||||
SSA_INSTR_KIND(ArrayExtractValue), \
|
||||
SSA_INSTR_KIND(StructExtractValue), \
|
||||
SSA_INSTR_KIND(Conv), \
|
||||
SSA_INSTR_KIND(Jump), \
|
||||
SSA_INSTR_KIND(If), \
|
||||
SSA_INSTR_KIND(Return), \
|
||||
SSA_INSTR_KIND(Select), \
|
||||
SSA_INSTR_KIND(Phi), \
|
||||
SSA_INSTR_KIND(Unreachable), \
|
||||
SSA_INSTR_KIND(BinaryOp), \
|
||||
SSA_INSTR_KIND(Call), \
|
||||
SSA_INSTR_KIND(VectorExtractElement), \
|
||||
SSA_INSTR_KIND(VectorInsertElement), \
|
||||
SSA_INSTR_KIND(VectorShuffle), \
|
||||
SSA_INSTR_KIND(StartupRuntime), \
|
||||
SSA_INSTR_KIND(BoundsCheck), \
|
||||
SSA_INSTR_KIND(SliceBoundsCheck), \
|
||||
|
||||
#define SSA_CONV_KINDS \
|
||||
SSA_CONV_KIND(Invalid), \
|
||||
SSA_CONV_KIND(trunc), \
|
||||
SSA_CONV_KIND(zext), \
|
||||
SSA_CONV_KIND(fptrunc), \
|
||||
SSA_CONV_KIND(fpext), \
|
||||
SSA_CONV_KIND(fptoui), \
|
||||
SSA_CONV_KIND(fptosi), \
|
||||
SSA_CONV_KIND(uitofp), \
|
||||
SSA_CONV_KIND(sitofp), \
|
||||
SSA_CONV_KIND(ptrtoint), \
|
||||
SSA_CONV_KIND(inttoptr), \
|
||||
SSA_CONV_KIND(bitcast),
|
||||
|
||||
enum ssaInstrKind {
|
||||
#define SSA_INSTR_KIND(x) GB_JOIN2(ssaInstr_, x)
|
||||
SSA_INSTR_KINDS
|
||||
#undef SSA_INSTR_KIND
|
||||
};
|
||||
|
||||
String const ssa_instr_strings[] = {
|
||||
#define SSA_INSTR_KIND(x) {cast(u8 *)#x, gb_size_of(#x)-1}
|
||||
SSA_INSTR_KINDS
|
||||
#undef SSA_INSTR_KIND
|
||||
};
|
||||
|
||||
enum ssaConvKind {
|
||||
#define SSA_CONV_KIND(x) GB_JOIN2(ssaConv_, x)
|
||||
SSA_CONV_KINDS
|
||||
#undef SSA_CONV_KIND
|
||||
};
|
||||
|
||||
String const ssa_conv_strings[] = {
|
||||
#define SSA_CONV_KIND(x) {cast(u8 *)#x, gb_size_of(#x)-1}
|
||||
SSA_CONV_KINDS
|
||||
#undef SSA_CONV_KIND
|
||||
};
|
||||
|
||||
struct ssaInstr {
|
||||
ssaInstrKind kind;
|
||||
|
||||
ssaBlock *parent;
|
||||
Type *type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
String text;
|
||||
} Comment;
|
||||
struct {
|
||||
Entity * entity;
|
||||
Type * type;
|
||||
b32 zero_initialized;
|
||||
Array<ssaValue *> referrers;
|
||||
} Local;
|
||||
struct {
|
||||
ssaValue *address;
|
||||
} ZeroInit;
|
||||
struct {
|
||||
ssaValue *address;
|
||||
ssaValue *value;
|
||||
} Store;
|
||||
struct {
|
||||
Type *type;
|
||||
ssaValue *address;
|
||||
} Load;
|
||||
struct {
|
||||
ssaValue *address;
|
||||
Type * result_type;
|
||||
ssaValue *elem_index;
|
||||
} ArrayElementPtr;
|
||||
struct {
|
||||
ssaValue *address;
|
||||
Type * result_type;
|
||||
i32 elem_index;
|
||||
} StructElementPtr;
|
||||
struct {
|
||||
ssaValue *address;
|
||||
ssaValue *offset;
|
||||
} PtrOffset;
|
||||
struct {
|
||||
ssaValue *address;
|
||||
Type * result_type;
|
||||
i32 index;
|
||||
} ArrayExtractValue;
|
||||
struct {
|
||||
ssaValue *address;
|
||||
Type * result_type;
|
||||
i32 index;
|
||||
} StructExtractValue;
|
||||
struct {
|
||||
ssaValue *value;
|
||||
ssaValue *elem;
|
||||
i32 index;
|
||||
} InsertValue;
|
||||
struct {
|
||||
ssaConvKind kind;
|
||||
ssaValue *value;
|
||||
Type *from, *to;
|
||||
} Conv;
|
||||
struct {
|
||||
ssaBlock *block;
|
||||
} Jump;
|
||||
struct {
|
||||
ssaValue *cond;
|
||||
ssaBlock *true_block;
|
||||
ssaBlock *false_block;
|
||||
} If;
|
||||
struct {
|
||||
ssaValue *value;
|
||||
} Return;
|
||||
struct {} Unreachable;
|
||||
struct {
|
||||
ssaValue *cond;
|
||||
ssaValue *true_value;
|
||||
ssaValue *false_value;
|
||||
} Select;
|
||||
struct {
|
||||
Array<ssaValue *> edges;
|
||||
Type *type;
|
||||
} Phi;
|
||||
struct {
|
||||
Type *type;
|
||||
TokenKind op;
|
||||
ssaValue *left, *right;
|
||||
} BinaryOp;
|
||||
struct {
|
||||
Type *type; // return type
|
||||
ssaValue *value;
|
||||
ssaValue **args;
|
||||
isize arg_count;
|
||||
} Call;
|
||||
struct {
|
||||
ssaValue *vector;
|
||||
ssaValue *index;
|
||||
} VectorExtractElement;
|
||||
struct {
|
||||
ssaValue *vector;
|
||||
ssaValue *elem;
|
||||
ssaValue *index;
|
||||
} VectorInsertElement;
|
||||
struct {
|
||||
ssaValue *vector;
|
||||
i32 *indices;
|
||||
isize index_count;
|
||||
Type *type;
|
||||
} VectorShuffle;
|
||||
|
||||
struct {} StartupRuntime;
|
||||
struct {
|
||||
TokenPos pos;
|
||||
ssaValue *index;
|
||||
ssaValue *len;
|
||||
} BoundsCheck;
|
||||
struct {
|
||||
TokenPos pos;
|
||||
ssaValue *low;
|
||||
ssaValue *high;
|
||||
ssaValue *max;
|
||||
b32 is_substring;
|
||||
} SliceBoundsCheck;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
enum ssaValueKind {
|
||||
ssaValue_Invalid,
|
||||
|
||||
ssaValue_Constant,
|
||||
ssaValue_ConstantSlice,
|
||||
ssaValue_Nil,
|
||||
ssaValue_TypeName,
|
||||
ssaValue_Global,
|
||||
ssaValue_Param,
|
||||
|
||||
ssaValue_Proc,
|
||||
ssaValue_Block,
|
||||
ssaValue_Instr,
|
||||
|
||||
ssaValue_Count,
|
||||
};
|
||||
|
||||
struct ssaValue {
|
||||
ssaValueKind kind;
|
||||
i32 index;
|
||||
union {
|
||||
struct {
|
||||
Type * type;
|
||||
ExactValue value;
|
||||
} Constant;
|
||||
struct {
|
||||
Type * type;
|
||||
ssaValue *backing_array;
|
||||
i64 count;
|
||||
} ConstantSlice;
|
||||
struct {
|
||||
Type *type;
|
||||
} Nil;
|
||||
struct {
|
||||
Type * type;
|
||||
String name;
|
||||
} TypeName;
|
||||
struct {
|
||||
Entity * entity;
|
||||
Type * type;
|
||||
ssaValue * value;
|
||||
Array<ssaValue *> referrers;
|
||||
b8 is_constant;
|
||||
b8 is_private;
|
||||
b8 is_thread_local;
|
||||
b8 is_unnamed_addr;
|
||||
} Global;
|
||||
struct {
|
||||
ssaProcedure * parent;
|
||||
Entity * entity;
|
||||
Type * type;
|
||||
Array<ssaValue *> referrers;
|
||||
} Param;
|
||||
ssaProcedure Proc;
|
||||
ssaBlock Block;
|
||||
ssaInstr Instr;
|
||||
};
|
||||
};
|
||||
|
||||
gb_global ssaValue *v_zero = NULL;
|
||||
gb_global ssaValue *v_one = NULL;
|
||||
gb_global ssaValue *v_zero32 = NULL;
|
||||
gb_global ssaValue *v_one32 = NULL;
|
||||
gb_global ssaValue *v_two32 = NULL;
|
||||
gb_global ssaValue *v_false = NULL;
|
||||
gb_global ssaValue *v_true = NULL;
|
||||
|
||||
enum ssaAddrKind {
|
||||
ssaAddr_Default,
|
||||
ssaAddr_Vector,
|
||||
};
|
||||
|
||||
struct ssaAddr {
|
||||
ssaValue * addr;
|
||||
AstNode * expr; // NOTE(bill): Just for testing - probably remove later
|
||||
ssaAddrKind kind;
|
||||
union {
|
||||
struct { ssaValue *index; } Vector;
|
||||
};
|
||||
};
|
||||
|
||||
ssaAddr ssa_make_addr(ssaValue *addr, AstNode *expr) {
|
||||
ssaAddr v = {addr, expr};
|
||||
return v;
|
||||
}
|
||||
ssaAddr ssa_make_addr_vector(ssaValue *addr, ssaValue *index, AstNode *expr) {
|
||||
ssaAddr v = ssa_make_addr(addr, expr);
|
||||
v.kind = ssaAddr_Vector;
|
||||
v.Vector.index = index;
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
enum ssaDebugEncoding {
|
||||
ssaDebugBasicEncoding_Invalid = 0,
|
||||
|
||||
ssaDebugBasicEncoding_address = 1,
|
||||
ssaDebugBasicEncoding_boolean = 2,
|
||||
ssaDebugBasicEncoding_float = 3,
|
||||
ssaDebugBasicEncoding_signed = 4,
|
||||
ssaDebugBasicEncoding_signed_char = 5,
|
||||
ssaDebugBasicEncoding_unsigned = 6,
|
||||
ssaDebugBasicEncoding_unsigned_char = 7,
|
||||
|
||||
ssaDebugBasicEncoding_member = 13,
|
||||
ssaDebugBasicEncoding_pointer_type = 15,
|
||||
ssaDebugBasicEncoding_typedef = 22,
|
||||
|
||||
ssaDebugBasicEncoding_array_type = 1,
|
||||
ssaDebugBasicEncoding_enumeration_type = 4,
|
||||
ssaDebugBasicEncoding_structure_type = 19,
|
||||
ssaDebugBasicEncoding_union_type = 23,
|
||||
|
||||
};
|
||||
|
||||
enum ssaDebugInfoKind {
|
||||
ssaDebugInfo_Invalid,
|
||||
|
||||
ssaDebugInfo_CompileUnit,
|
||||
ssaDebugInfo_File,
|
||||
ssaDebugInfo_Scope,
|
||||
ssaDebugInfo_Proc,
|
||||
ssaDebugInfo_AllProcs,
|
||||
|
||||
ssaDebugInfo_BasicType, // basic types
|
||||
ssaDebugInfo_ProcType,
|
||||
ssaDebugInfo_DerivedType, // pointer, typedef
|
||||
ssaDebugInfo_CompositeType, // array, struct, enum, (raw_)union
|
||||
ssaDebugInfo_Enumerator, // For ssaDebugInfo_CompositeType if enum
|
||||
ssaDebugInfo_GlobalVariable,
|
||||
ssaDebugInfo_LocalVariable,
|
||||
|
||||
|
||||
ssaDebugInfo_Count,
|
||||
};
|
||||
|
||||
struct ssaDebugInfo {
|
||||
ssaDebugInfoKind kind;
|
||||
i32 id;
|
||||
|
||||
union {
|
||||
struct {
|
||||
AstFile * file;
|
||||
String producer;
|
||||
ssaDebugInfo *all_procs;
|
||||
} CompileUnit;
|
||||
struct {
|
||||
AstFile *file;
|
||||
String filename;
|
||||
String directory;
|
||||
} File;
|
||||
struct {
|
||||
ssaDebugInfo *parent;
|
||||
ssaDebugInfo *file;
|
||||
TokenPos pos;
|
||||
Scope * scope; // Actual scope
|
||||
} Scope;
|
||||
struct {
|
||||
Entity * entity;
|
||||
String name;
|
||||
ssaDebugInfo *file;
|
||||
TokenPos pos;
|
||||
} Proc;
|
||||
struct {
|
||||
Array<ssaDebugInfo *> procs;
|
||||
} AllProcs;
|
||||
|
||||
|
||||
struct {
|
||||
String name;
|
||||
i32 size;
|
||||
i32 align;
|
||||
ssaDebugEncoding encoding;
|
||||
} BasicType;
|
||||
struct {
|
||||
ssaDebugInfo * return_type;
|
||||
Array<ssaDebugInfo *> param_types;
|
||||
} ProcType;
|
||||
struct {
|
||||
ssaDebugInfo * base_type;
|
||||
ssaDebugEncoding encoding;
|
||||
} DerivedType;
|
||||
struct {
|
||||
ssaDebugEncoding encoding;
|
||||
String name;
|
||||
String identifier;
|
||||
ssaDebugInfo * file;
|
||||
TokenPos pos;
|
||||
i32 size;
|
||||
i32 align;
|
||||
Array<ssaDebugInfo *> elements;
|
||||
} CompositeType;
|
||||
struct {
|
||||
String name;
|
||||
i64 value;
|
||||
} Enumerator;
|
||||
struct {
|
||||
String name;
|
||||
String linkage_name;
|
||||
ssaDebugInfo *scope;
|
||||
ssaDebugInfo *file;
|
||||
TokenPos pos;
|
||||
ssaValue *variable;
|
||||
ssaDebugInfo *declaration;
|
||||
} GlobalVariable;
|
||||
struct {
|
||||
String name;
|
||||
ssaDebugInfo *scope;
|
||||
ssaDebugInfo *file;
|
||||
TokenPos pos;
|
||||
i32 arg; // Non-zero if proc parameter
|
||||
ssaDebugInfo *type;
|
||||
} LocalVariable;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct ssaFileBuffer {
|
||||
gbVirtualMemory vm;
|
||||
isize offset;
|
||||
gbFile *output;
|
||||
};
|
||||
|
||||
void ssa_file_buffer_init(ssaFileBuffer *f, gbFile *output) {
|
||||
isize size = 8*gb_virtual_memory_page_size(NULL);
|
||||
f->vm = gb_vm_alloc(NULL, size);
|
||||
f->offset = 0;
|
||||
f->output = output;
|
||||
}
|
||||
|
||||
void ssa_file_buffer_destroy(ssaFileBuffer *f) {
|
||||
if (f->offset > 0) {
|
||||
// NOTE(bill): finish writing buffered data
|
||||
gb_file_write(f->output, f->vm.data, f->offset);
|
||||
}
|
||||
|
||||
gb_vm_free(f->vm);
|
||||
}
|
||||
|
||||
void ssa_file_buffer_write(ssaFileBuffer *f, void *data, isize len) {
|
||||
if (len > f->vm.size) {
|
||||
gb_file_write(f->output, data, len);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((f->vm.size - f->offset) < len) {
|
||||
gb_file_write(f->output, f->vm.data, f->offset);
|
||||
f->offset = 0;
|
||||
}
|
||||
u8 *cursor = cast(u8 *)f->vm.data + f->offset;
|
||||
gb_memmove(cursor, data, len);
|
||||
f->offset += len;
|
||||
}
|
||||
|
||||
|
||||
void ssa_fprintf(ssaFileBuffer *f, char *fmt, ...) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
char buf[4096] = {};
|
||||
isize len = gb_snprintf_va(buf, gb_size_of(buf), fmt, va);
|
||||
ssa_file_buffer_write(f, buf, len-1);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
|
||||
void ssa_file_write(ssaFileBuffer *f, void *data, isize len) {
|
||||
ssa_file_buffer_write(f, data, len);
|
||||
}
|
||||
|
||||
ssaValue *ssa_lookup_member(ssaModule *m, String name) {
|
||||
ssaValue **v = map_get(&m->members, hash_string(name));
|
||||
if (v != NULL) {
|
||||
return *v;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
Type *ssa_type(ssaValue *value);
|
||||
Type *ssa_instr_type(ssaInstr *instr) {
|
||||
switch (instr->kind) {
|
||||
case ssaInstr_Local:
|
||||
return instr->Local.type;
|
||||
case ssaInstr_Load:
|
||||
return instr->Load.type;
|
||||
case ssaInstr_StructElementPtr:
|
||||
return instr->StructElementPtr.result_type;
|
||||
case ssaInstr_ArrayElementPtr:
|
||||
return instr->ArrayElementPtr.result_type;
|
||||
case ssaInstr_PtrOffset:
|
||||
return ssa_type(instr->PtrOffset.address);
|
||||
case ssaInstr_Phi:
|
||||
return instr->Phi.type;
|
||||
case ssaInstr_ArrayExtractValue:
|
||||
return instr->ArrayExtractValue.result_type;
|
||||
case ssaInstr_StructExtractValue:
|
||||
return instr->StructExtractValue.result_type;
|
||||
case ssaInstr_BinaryOp:
|
||||
return instr->BinaryOp.type;
|
||||
case ssaInstr_Conv:
|
||||
return instr->Conv.to;
|
||||
case ssaInstr_Select:
|
||||
return ssa_type(instr->Select.true_value);
|
||||
case ssaInstr_Call: {
|
||||
Type *pt = base_type(instr->Call.type);
|
||||
if (pt != NULL) {
|
||||
if (pt->kind == Type_Tuple && pt->Tuple.variable_count == 1) {
|
||||
return pt->Tuple.variables[0]->type;
|
||||
}
|
||||
return pt;
|
||||
}
|
||||
return NULL;
|
||||
} break;
|
||||
case ssaInstr_VectorExtractElement: {
|
||||
Type *vt = ssa_type(instr->VectorExtractElement.vector);
|
||||
Type *bt = base_vector_type(vt);
|
||||
GB_ASSERT(!is_type_vector(bt));
|
||||
return bt;
|
||||
} break;
|
||||
case ssaInstr_VectorInsertElement:
|
||||
return ssa_type(instr->VectorInsertElement.vector);
|
||||
case ssaInstr_VectorShuffle:
|
||||
return instr->VectorShuffle.type;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Type *ssa_type(ssaValue *value) {
|
||||
switch (value->kind) {
|
||||
case ssaValue_Constant:
|
||||
return value->Constant.type;
|
||||
case ssaValue_ConstantSlice:
|
||||
return value->ConstantSlice.type;
|
||||
case ssaValue_Nil:
|
||||
return value->Nil.type;
|
||||
case ssaValue_TypeName:
|
||||
return value->TypeName.type;
|
||||
case ssaValue_Global:
|
||||
return value->Global.type;
|
||||
case ssaValue_Param:
|
||||
return value->Param.type;
|
||||
case ssaValue_Proc:
|
||||
return value->Proc.type;
|
||||
case ssaValue_Instr:
|
||||
return ssa_instr_type(&value->Instr);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Type *ssa_addr_type(ssaAddr lval) {
|
||||
if (lval.addr != NULL) {
|
||||
Type *t = ssa_type(lval.addr);
|
||||
GB_ASSERT(is_type_pointer(t));
|
||||
return type_deref(t);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
b32 ssa_is_blank_ident(AstNode *node) {
|
||||
if (node->kind == AstNode_Ident) {
|
||||
ast_node(i, Ident, node);
|
||||
return is_blank_ident(i->string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
ssaInstr *ssa_get_last_instr(ssaBlock *block) {
|
||||
if (block != NULL) {
|
||||
isize len = block->instrs.count;
|
||||
if (len > 0) {
|
||||
ssaValue *v = block->instrs[len-1];
|
||||
GB_ASSERT(v->kind == ssaValue_Instr);
|
||||
return &v->Instr;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
b32 ssa_is_instr_terminating(ssaInstr *i) {
|
||||
if (i != NULL) {
|
||||
switch (i->kind) {
|
||||
case ssaInstr_Return:
|
||||
case ssaInstr_Unreachable:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ssa_add_edge(ssaBlock *from, ssaBlock *to) {
|
||||
array_add(&from->succs, to);
|
||||
array_add(&to->preds, from);
|
||||
}
|
||||
|
||||
void ssa_set_instr_parent(ssaValue *instr, ssaBlock *parent) {
|
||||
if (instr->kind == ssaValue_Instr) {
|
||||
instr->Instr.parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
Array<ssaValue *> *ssa_value_referrers(ssaValue *v) {
|
||||
switch (v->kind) {
|
||||
case ssaValue_Global:
|
||||
return &v->Global.referrers;
|
||||
case ssaValue_Param:
|
||||
return &v->Param.referrers;
|
||||
case ssaValue_Proc: {
|
||||
if (v->Proc.parent != NULL) {
|
||||
return &v->Proc.referrers;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
case ssaValue_Instr: {
|
||||
ssaInstr *i = &v->Instr;
|
||||
switch (i->kind) {
|
||||
case ssaInstr_Local:
|
||||
return &i->Local.referrers;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#include "make.cpp"
|
||||
#include "debug.cpp"
|
||||
#include "emit.cpp"
|
||||
#include "build.cpp"
|
||||
#include "opt.cpp"
|
||||
#include "proc.cpp"
|
||||
|
||||
|
||||
|
||||
|
||||
void ssa_module_add_value(ssaModule *m, Entity *e, ssaValue *v) {
|
||||
map_set(&m->values, hash_pointer(e), v);
|
||||
}
|
||||
|
||||
void ssa_init_module(ssaModule *m, Checker *c) {
|
||||
// TODO(bill): Determine a decent size for the arena
|
||||
isize token_count = c->parser->total_token_count;
|
||||
isize arena_size = 4 * token_count * gb_size_of(ssaValue);
|
||||
gb_arena_init_from_allocator(&m->arena, heap_allocator(), arena_size);
|
||||
gb_arena_init_from_allocator(&m->tmp_arena, heap_allocator(), arena_size);
|
||||
m->allocator = gb_arena_allocator(&m->arena);
|
||||
m->tmp_allocator = gb_arena_allocator(&m->tmp_arena);
|
||||
m->info = &c->info;
|
||||
m->sizes = c->sizes;
|
||||
|
||||
map_init(&m->values, heap_allocator());
|
||||
map_init(&m->members, heap_allocator());
|
||||
map_init(&m->debug_info, heap_allocator());
|
||||
map_init(&m->type_names, heap_allocator());
|
||||
array_init(&m->procs, heap_allocator());
|
||||
|
||||
// Default states
|
||||
m->stmt_state_flags = 0;
|
||||
m->stmt_state_flags |= StmtStateFlag_bounds_check;
|
||||
|
||||
{
|
||||
// Add type info data
|
||||
{
|
||||
String name = make_string(SSA_TYPE_INFO_DATA_NAME);
|
||||
isize count = c->info.type_info_map.entries.count;
|
||||
Entity *e = make_entity_variable(m->allocator, NULL, make_token_ident(name), make_type_array(m->allocator, t_type_info, count));
|
||||
ssaValue *g = ssa_make_value_global(m->allocator, e, NULL);
|
||||
g->Global.is_private = true;
|
||||
ssa_module_add_value(m, e, g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
}
|
||||
|
||||
// Type info member buffer
|
||||
{
|
||||
// NOTE(bill): Removes need for heap allocation by making it global memory
|
||||
isize count = 0;
|
||||
|
||||
for_array(entry_index, m->info->type_info_map.entries) {
|
||||
auto *entry = &m->info->type_info_map.entries[entry_index];
|
||||
Type *t = cast(Type *)cast(uintptr)entry->key.key;
|
||||
|
||||
switch (t->kind) {
|
||||
case Type_Record:
|
||||
switch (t->Record.kind) {
|
||||
case TypeRecord_Struct:
|
||||
case TypeRecord_RawUnion:
|
||||
count += t->Record.field_count;
|
||||
}
|
||||
break;
|
||||
case Type_Tuple:
|
||||
count += t->Tuple.variable_count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String name = make_string(SSA_TYPE_INFO_DATA_MEMBER_NAME);
|
||||
Entity *e = make_entity_variable(m->allocator, NULL, make_token_ident(name),
|
||||
make_type_array(m->allocator, t_type_info_member, count));
|
||||
ssaValue *g = ssa_make_value_global(m->allocator, e, NULL);
|
||||
ssa_module_add_value(m, e, g);
|
||||
map_set(&m->members, hash_string(name), g);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
ssaDebugInfo *di = ssa_alloc_debug_info(m->allocator, ssaDebugInfo_CompileUnit);
|
||||
di->CompileUnit.file = m->info->files.entries[0].value; // Zeroth is the init file
|
||||
di->CompileUnit.producer = make_string("odin");
|
||||
|
||||
map_set(&m->debug_info, hash_pointer(m), di);
|
||||
}
|
||||
}
|
||||
|
||||
void ssa_destroy_module(ssaModule *m) {
|
||||
map_destroy(&m->values);
|
||||
map_destroy(&m->members);
|
||||
map_destroy(&m->type_names);
|
||||
map_destroy(&m->debug_info);
|
||||
array_free(&m->procs);
|
||||
gb_arena_free(&m->arena);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#include "codegen.cpp"
|
||||
|
||||
|
||||
@@ -79,6 +79,17 @@ void ssa_opt_add_operands(Array<ssaValue *> *ops, ssaInstr *i) {
|
||||
break;
|
||||
case ssaInstr_StartupRuntime:
|
||||
break;
|
||||
case ssaInstr_BoundsCheck:
|
||||
array_add(ops, i->BoundsCheck.index);
|
||||
array_add(ops, i->BoundsCheck.len);
|
||||
break;
|
||||
case ssaInstr_SliceBoundsCheck:
|
||||
array_add(ops, i->SliceBoundsCheck.low);
|
||||
array_add(ops, i->SliceBoundsCheck.high);
|
||||
array_add(ops, i->SliceBoundsCheck.max);
|
||||
break;
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
+313
-67
@@ -1,3 +1,5 @@
|
||||
#include "dyncall/include/dyncall.h"
|
||||
|
||||
struct VirtualMachine;
|
||||
|
||||
struct vmValueProc {
|
||||
@@ -37,8 +39,9 @@ struct vmFrame {
|
||||
VirtualMachine * vm;
|
||||
vmFrame * caller;
|
||||
ssaProcedure * curr_proc;
|
||||
ssaBlock * prev_block;
|
||||
ssaBlock * curr_block;
|
||||
isize instr_index; // For the current block
|
||||
i32 instr_index; // For the current block
|
||||
|
||||
Map<vmValue> values; // Key: ssaValue *
|
||||
gbTempArenaMemory temp_arena_memory;
|
||||
@@ -61,6 +64,14 @@ struct VirtualMachine {
|
||||
void vm_exec_instr (VirtualMachine *vm, ssaValue *value);
|
||||
vmValue vm_operand_value(VirtualMachine *vm, ssaValue *value);
|
||||
void vm_store (VirtualMachine *vm, void *dst, vmValue val, Type *type);
|
||||
void vm_print_value (vmValue value, Type *type);
|
||||
|
||||
void vm_jump_block(vmFrame *f, ssaBlock *target) {
|
||||
f->prev_block = f->curr_block;
|
||||
f->curr_block = target;
|
||||
f->instr_index = 0;
|
||||
}
|
||||
|
||||
|
||||
vmFrame *vm_back_frame(VirtualMachine *vm) {
|
||||
if (vm->frame_stack.count > 0) {
|
||||
@@ -123,6 +134,7 @@ void vm_destroy(VirtualMachine *vm) {
|
||||
|
||||
void vm_set_value(vmFrame *f, ssaValue *v, vmValue val) {
|
||||
if (v != NULL) {
|
||||
GB_ASSERT(ssa_type(v) != NULL);
|
||||
map_set(&f->values, hash_pointer(v), val);
|
||||
}
|
||||
}
|
||||
@@ -134,6 +146,7 @@ vmFrame *vm_push_frame(VirtualMachine *vm, ssaProcedure *proc) {
|
||||
|
||||
frame.vm = vm;
|
||||
frame.curr_proc = proc;
|
||||
frame.prev_block = proc->blocks[0];
|
||||
frame.curr_block = proc->blocks[0];
|
||||
frame.instr_index = 0;
|
||||
frame.caller = vm_back_frame(vm);
|
||||
@@ -154,10 +167,10 @@ void vm_pop_frame(VirtualMachine *vm) {
|
||||
map_destroy(&f->values);
|
||||
|
||||
array_pop(&vm->frame_stack);
|
||||
|
||||
}
|
||||
|
||||
vmValue vm_call_procedure(VirtualMachine *vm, ssaProcedure *proc, Array<vmValue> values) {
|
||||
|
||||
vmValue vm_call_proc(VirtualMachine *vm, ssaProcedure *proc, Array<vmValue> values) {
|
||||
Type *type = base_type(proc->type);
|
||||
GB_ASSERT_MSG(type->Proc.param_count == values.count,
|
||||
"Incorrect number of arguments passed into procedure call!\n"
|
||||
@@ -169,7 +182,8 @@ vmValue vm_call_procedure(VirtualMachine *vm, ssaProcedure *proc, Array<vmValue>
|
||||
vmValue result = {};
|
||||
|
||||
if (proc->body == NULL) {
|
||||
GB_PANIC("TODO(bill): external procedure");
|
||||
// GB_PANIC("TODO(bill): external procedure");
|
||||
gb_printf_err("TODO(bill): external procedure: %.*s\n", LIT(proc->name));
|
||||
return result;
|
||||
}
|
||||
gb_printf("call: %.*s\n", LIT(proc->name));
|
||||
@@ -179,6 +193,11 @@ vmValue vm_call_procedure(VirtualMachine *vm, ssaProcedure *proc, Array<vmValue>
|
||||
vm_set_value(f, proc->params[i], values[i]);
|
||||
}
|
||||
|
||||
if (proc->name == SSA_STARTUP_RUNTIME_PROC_NAME) {
|
||||
ssaBlock *block = proc->curr_block;
|
||||
|
||||
}
|
||||
|
||||
while (f->curr_block != NULL) {
|
||||
ssaValue *curr_instr = f->curr_block->instrs[f->instr_index++];
|
||||
vm_exec_instr(vm, curr_instr);
|
||||
@@ -195,20 +214,28 @@ vmValue vm_call_procedure(VirtualMachine *vm, ssaProcedure *proc, Array<vmValue>
|
||||
rt = base_type(rt->Tuple.variables[0]->type);
|
||||
}
|
||||
|
||||
if (is_type_string(rt)) {
|
||||
vmValue data = result.val_comp[0];
|
||||
vmValue count = result.val_comp[1];
|
||||
gb_printf("String: %.*s\n", cast(isize)count.val_int, cast(u8 *)data.val_ptr);
|
||||
} else if (is_type_integer(rt)) {
|
||||
gb_printf("Integer: %lld\n", cast(i64)result.val_int);
|
||||
}
|
||||
// gb_printf("%lld\n", cast(i64)result.val_int);
|
||||
gb_printf("%.*s -> ", LIT(proc->name));
|
||||
vm_print_value(result, rt);
|
||||
gb_printf("\n");
|
||||
}
|
||||
|
||||
vm_pop_frame(vm);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
ssaProcedure *vm_lookup_procedure(VirtualMachine *vm, String name) {
|
||||
ssaValue *v = ssa_lookup_member(vm->module, name);
|
||||
GB_ASSERT(v->kind == ssaValue_Proc);
|
||||
ssaProcedure *proc = &v->Proc;
|
||||
return proc;
|
||||
}
|
||||
|
||||
vmValue vm_call_proc_by_name(VirtualMachine *vm, String name, Array<vmValue> args) {
|
||||
ssaProcedure *proc = vm_lookup_procedure(vm, name);
|
||||
return vm_call_proc(vm, proc, args);
|
||||
}
|
||||
|
||||
vmValue vm_exact_value(VirtualMachine *vm, ssaValue *ptr, ExactValue value, Type *t) {
|
||||
vmValue result = {};
|
||||
Type *original_type = t;
|
||||
@@ -262,8 +289,7 @@ vmValue vm_exact_value(VirtualMachine *vm, ssaValue *ptr, ExactValue value, Type
|
||||
}
|
||||
|
||||
Type *type = base_type(t);
|
||||
array_init(&result.val_comp, vm->heap_allocator, type->Array.count);
|
||||
array_resize(&result.val_comp, type->Array.count);
|
||||
array_init_count(&result.val_comp, vm->heap_allocator, type->Array.count);
|
||||
for (isize i = 0; i < elem_count; i++) {
|
||||
TypeAndValue *tav = type_and_value_of_expression(vm->module->info, cl->elems[i]);
|
||||
vmValue elem = vm_exact_value(vm, NULL, tav->value, tav->type);
|
||||
@@ -283,8 +309,7 @@ vmValue vm_exact_value(VirtualMachine *vm, ssaValue *ptr, ExactValue value, Type
|
||||
}
|
||||
|
||||
isize value_count = t->Record.field_count;
|
||||
array_init(&result.val_comp, vm->heap_allocator, value_count);
|
||||
array_resize(&result.val_comp, value_count);
|
||||
array_init_count(&result.val_comp, vm->heap_allocator, value_count);
|
||||
|
||||
if (cl->elems[0]->kind == AstNode_FieldValue) {
|
||||
isize elem_count = cl->elems.count;
|
||||
@@ -379,6 +404,7 @@ void vm_store_integer(VirtualMachine *vm, void *dst, vmValue val, i64 store_byte
|
||||
|
||||
void vm_store(VirtualMachine *vm, void *dst, vmValue val, Type *type) {
|
||||
i64 size = vm_type_size_of(vm, type);
|
||||
Type *original_type = type;
|
||||
type = base_type(get_enum_base_type(type));
|
||||
|
||||
// TODO(bill): I assume little endian here
|
||||
@@ -431,6 +457,10 @@ void vm_store(VirtualMachine *vm, void *dst, vmValue val, Type *type) {
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Pointer:
|
||||
*cast(void **)dst = val.val_ptr;
|
||||
break;
|
||||
|
||||
case Type_Record: {
|
||||
if (is_type_struct(type)) {
|
||||
u8 *mem = cast(u8 *)dst;
|
||||
@@ -444,13 +474,41 @@ void vm_store(VirtualMachine *vm, void *dst, vmValue val, Type *type) {
|
||||
for (isize i = 0; i < field_count; i++) {
|
||||
Entity *f = type->Record.fields[i];
|
||||
i64 offset = vm_type_offset_of(vm, type, i);
|
||||
void *ptr = mem+offset;
|
||||
vmValue member = val.val_comp[i];
|
||||
vm_store(vm, ptr, member, f->type);
|
||||
vm_store(vm, mem+offset, val.val_comp[i], f->type);
|
||||
}
|
||||
|
||||
} else {
|
||||
gb_printf_err("TODO(bill): records for `vm_store` %s\n", type_to_string(type));
|
||||
// u8 *mem = cast(u8 *)dst;
|
||||
// if (val.val_comp.count == 0) {
|
||||
// gb_printf_err("%s\n", type_to_string(original_type));
|
||||
// // gb_zero_size(mem, vm_type_size_of(vm, type));
|
||||
// } else {
|
||||
// GB_ASSERT(val.val_comp.count == 2);
|
||||
// i64 word_size = vm_type_size_of(vm, t_int);
|
||||
// i64 size_of_union = vm_type_size_of(vm, type) - word_size;
|
||||
// for (isize i = 0; i < size_of_union; i++) {
|
||||
// mem[i] = cast(u8)val.val_comp[0].val_comp[i].val_int;
|
||||
// }
|
||||
// vm_store_integer(vm, mem + size_of_union, val.val_comp[0], word_size);
|
||||
// }
|
||||
|
||||
// gb_printf_err("TODO(bill): records for `vm_store` %s\n", type_to_string(original_type));
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Tuple: {
|
||||
u8 *mem = cast(u8 *)dst;
|
||||
|
||||
GB_ASSERT_MSG(type->Tuple.variable_count >= val.val_comp.count,
|
||||
"%td vs %td",
|
||||
type->Tuple.variable_count, val.val_comp.count);
|
||||
|
||||
isize variable_count = gb_min(val.val_comp.count, type->Tuple.variable_count);
|
||||
|
||||
for (isize i = 0; i < variable_count; i++) {
|
||||
Entity *f = type->Tuple.variables[i];
|
||||
void *ptr = mem + vm_type_offset_of(vm, type, i);
|
||||
vmValue member = val.val_comp[i];
|
||||
vm_store(vm, ptr, member, f->type);
|
||||
}
|
||||
} break;
|
||||
|
||||
@@ -463,11 +521,17 @@ void vm_store(VirtualMachine *vm, void *dst, vmValue val, Type *type) {
|
||||
for (i64 i = 0; i < elem_count; i++) {
|
||||
void *ptr = mem + (elem_size*i);
|
||||
vmValue member = val.val_comp[i];
|
||||
*cast(i64 *)ptr = 123;
|
||||
vm_store(vm, ptr, member, elem_type);
|
||||
}
|
||||
gb_printf_err("%lld\n", *cast(i64 *)mem);
|
||||
} break;
|
||||
|
||||
case Type_Slice: {
|
||||
i64 word_size = vm_type_size_of(vm, t_int);
|
||||
|
||||
u8 *mem = cast(u8 *)dst;
|
||||
vm_store(vm, mem+0*word_size, val.val_comp[0], t_rawptr);
|
||||
vm_store(vm, mem+1*word_size, val.val_comp[1], t_int);
|
||||
vm_store(vm, mem+2*word_size, val.val_comp[2], t_int);
|
||||
} break;
|
||||
|
||||
default:
|
||||
@@ -518,8 +582,8 @@ vmValue vm_load(VirtualMachine *vm, void *ptr, Type *type) {
|
||||
|
||||
case Basic_string: {
|
||||
i64 word_size = vm_type_size_of(vm, t_int);
|
||||
u8 *mem = *cast(u8 **)ptr;
|
||||
array_init(&result.val_comp, vm->heap_allocator, 2);
|
||||
u8 *mem = cast(u8 *)ptr;
|
||||
array_init_count(&result.val_comp, vm->heap_allocator, 2);
|
||||
|
||||
i64 count = 0;
|
||||
u8 *data = mem + 0*word_size;
|
||||
@@ -530,8 +594,8 @@ vmValue vm_load(VirtualMachine *vm, void *ptr, Type *type) {
|
||||
default: GB_PANIC("Unknown int size"); break;
|
||||
}
|
||||
|
||||
array_add(&result.val_comp, vm_make_value_ptr(mem));
|
||||
array_add(&result.val_comp, vm_make_value_int(count));
|
||||
result.val_comp[0].val_ptr = mem;
|
||||
result.val_comp[1].val_int = count;
|
||||
|
||||
} break;
|
||||
|
||||
@@ -541,12 +605,44 @@ vmValue vm_load(VirtualMachine *vm, void *ptr, Type *type) {
|
||||
}
|
||||
break;
|
||||
|
||||
case Type_Pointer:
|
||||
result.val_ptr = *cast(void **)ptr;
|
||||
break;
|
||||
|
||||
case Type_Array: {
|
||||
i64 count = type->Array.count;
|
||||
Type *elem_type = type->Array.elem;
|
||||
i64 elem_size = vm_type_size_of(vm, elem_type);
|
||||
|
||||
array_init_count(&result.val_comp, vm->heap_allocator, count);
|
||||
|
||||
u8 *mem = cast(u8 *)ptr;
|
||||
for (isize i = 0; i < count; i++) {
|
||||
i64 offset = elem_size*i;
|
||||
vmValue val = vm_load(vm, mem+offset, elem_type);
|
||||
result.val_comp[i] = val;
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Slice: {
|
||||
Type *elem_type = type->Slice.elem;
|
||||
i64 elem_size = vm_type_size_of(vm, elem_type);
|
||||
i64 word_size = vm_type_size_of(vm, t_int);
|
||||
|
||||
array_init_count(&result.val_comp, vm->heap_allocator, 3);
|
||||
|
||||
u8 *mem = cast(u8 *)ptr;
|
||||
result.val_comp[0] = vm_load(vm, mem+0*word_size, t_rawptr); // data
|
||||
result.val_comp[1] = vm_load(vm, mem+1*word_size, t_int); // count
|
||||
result.val_comp[2] = vm_load(vm, mem+2*word_size, t_int); // capacity
|
||||
return result;
|
||||
} break;
|
||||
|
||||
case Type_Record: {
|
||||
if (is_type_struct(type)) {
|
||||
isize field_count = type->Record.field_count;
|
||||
|
||||
array_init(&result.val_comp, vm->heap_allocator, field_count);
|
||||
array_resize(&result.val_comp, field_count);
|
||||
array_init_count(&result.val_comp, vm->heap_allocator, field_count);
|
||||
|
||||
u8 *mem = cast(u8 *)ptr;
|
||||
for (isize i = 0; i < field_count; i++) {
|
||||
@@ -558,6 +654,20 @@ vmValue vm_load(VirtualMachine *vm, void *ptr, Type *type) {
|
||||
}
|
||||
} break;
|
||||
|
||||
case Type_Tuple: {
|
||||
isize count = type->Tuple.variable_count;
|
||||
|
||||
array_init_count(&result.val_comp, vm->heap_allocator, count);
|
||||
|
||||
u8 *mem = cast(u8 *)ptr;
|
||||
for (isize i = 0; i < count; i++) {
|
||||
Entity *f = type->Tuple.variables[i];
|
||||
i64 offset = vm_type_offset_of(vm, type, i);
|
||||
vmValue val = vm_load(vm, mem+offset, f->type);
|
||||
result.val_comp[i] = val;
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
GB_PANIC("TODO(bill): other types for `vm_load` %s", type_to_string(type));
|
||||
break;
|
||||
@@ -566,14 +676,8 @@ vmValue vm_load(VirtualMachine *vm, void *ptr, Type *type) {
|
||||
return result;
|
||||
}
|
||||
|
||||
ssaProcedure *vm_lookup_procedure(VirtualMachine *vm, String name) {
|
||||
ssaValue *v = ssa_lookup_member(vm->module, name);
|
||||
GB_ASSERT(v->kind == ssaValue_Proc);
|
||||
ssaProcedure *proc = &v->Proc;
|
||||
return proc;
|
||||
}
|
||||
|
||||
void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
GB_ASSERT(value != NULL);
|
||||
GB_ASSERT(value->kind == ssaValue_Instr);
|
||||
ssaInstr *instr = &value->Instr;
|
||||
vmFrame *f = vm_back_frame(vm);
|
||||
@@ -586,10 +690,10 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
|
||||
switch (instr->kind) {
|
||||
case ssaInstr_StartupRuntime: {
|
||||
#if 0
|
||||
#if 1
|
||||
ssaProcedure *proc = vm_lookup_procedure(vm, make_string(SSA_STARTUP_RUNTIME_PROC_NAME));
|
||||
Array<vmValue> args = {}; // Empty
|
||||
vm_call_procedure(vm, proc, args); // NOTE(bill): No return value
|
||||
vm_call_proc(vm, proc, args); // NOTE(bill): No return value
|
||||
#endif
|
||||
} break;
|
||||
|
||||
@@ -659,7 +763,14 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
} break;
|
||||
|
||||
case ssaInstr_Phi: {
|
||||
GB_PANIC("TODO(bill): ssaInstr_Phi");
|
||||
for_array(i, f->curr_block->preds) {
|
||||
ssaBlock *pred = f->curr_block->preds[i];
|
||||
if (f->prev_block == pred) {
|
||||
vmValue edge = vm_operand_value(vm, instr->Phi.edges[i]);
|
||||
vm_set_value(f, value, edge);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case ssaInstr_ArrayExtractValue: {
|
||||
@@ -675,18 +786,16 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
} break;
|
||||
|
||||
case ssaInstr_Jump: {
|
||||
f->curr_block = instr->Jump.block;
|
||||
f->instr_index = 0;
|
||||
vm_jump_block(f, instr->Jump.block);
|
||||
} break;
|
||||
|
||||
case ssaInstr_If: {
|
||||
vmValue cond = vm_operand_value(vm, instr->If.cond);
|
||||
if (cond.val_int != 0) {
|
||||
f->curr_block = instr->If.true_block;
|
||||
vm_jump_block(f, instr->If.true_block);
|
||||
} else {
|
||||
f->curr_block = instr->If.false_block;
|
||||
vm_jump_block(f, instr->If.false_block);
|
||||
}
|
||||
f->instr_index = 0;
|
||||
} break;
|
||||
|
||||
case ssaInstr_Return: {
|
||||
@@ -700,6 +809,7 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
|
||||
f->result = result;
|
||||
f->curr_block = NULL;
|
||||
f->instr_index = 0;
|
||||
return;
|
||||
} break;
|
||||
|
||||
@@ -732,20 +842,20 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
Type *from = base_type(instr->Conv.from);
|
||||
if (from == t_f64) {
|
||||
u64 u = cast(u64)src.val_f64;
|
||||
gb_memcopy(&dst, &u, to_size);
|
||||
vm_store_integer(vm, &dst, vm_make_value_int(u), to_size);
|
||||
} else {
|
||||
u64 u = cast(u64)src.val_f32;
|
||||
gb_memcopy(&dst, &u, to_size);
|
||||
vm_store_integer(vm, &dst, vm_make_value_int(u), to_size);
|
||||
}
|
||||
} break;
|
||||
case ssaConv_fptosi: {
|
||||
Type *from = base_type(instr->Conv.from);
|
||||
if (from == t_f64) {
|
||||
i64 i = cast(i64)src.val_f64;
|
||||
gb_memcopy(&dst, &i, to_size);
|
||||
vm_store_integer(vm, &dst, vm_make_value_int(i), to_size);
|
||||
} else {
|
||||
i64 i = cast(i64)src.val_f32;
|
||||
gb_memcopy(&dst, &i, to_size);
|
||||
vm_store_integer(vm, &dst, vm_make_value_int(i), to_size);
|
||||
}
|
||||
} break;
|
||||
case ssaConv_uitofp: {
|
||||
@@ -792,16 +902,56 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
}
|
||||
|
||||
if (gb_is_between(bo->op, Token__ComparisonBegin+1, Token__ComparisonEnd-1)) {
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: break;
|
||||
case Token_NotEq: break;
|
||||
case Token_Lt: break;
|
||||
case Token_Gt: break;
|
||||
case Token_LtEq: break;
|
||||
case Token_GtEq: break;
|
||||
vmValue v = {};
|
||||
vmValue l = vm_operand_value(vm, bo->left);
|
||||
vmValue r = vm_operand_value(vm, bo->right);
|
||||
|
||||
if (is_type_integer(t)) {
|
||||
// TODO(bill): Do I need to take into account the size of the integer?
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: v.val_int = l.val_int == r.val_int; break;
|
||||
case Token_NotEq: v.val_int = l.val_int != r.val_int; break;
|
||||
case Token_Lt: v.val_int = l.val_int < r.val_int; break;
|
||||
case Token_Gt: v.val_int = l.val_int > r.val_int; break;
|
||||
case Token_LtEq: v.val_int = l.val_int <= r.val_int; break;
|
||||
case Token_GtEq: v.val_int = l.val_int >= r.val_int; break;
|
||||
}
|
||||
} else if (t == t_f32) {
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: v.val_f32 = l.val_f32 == r.val_f32; break;
|
||||
case Token_NotEq: v.val_f32 = l.val_f32 != r.val_f32; break;
|
||||
case Token_Lt: v.val_f32 = l.val_f32 < r.val_f32; break;
|
||||
case Token_Gt: v.val_f32 = l.val_f32 > r.val_f32; break;
|
||||
case Token_LtEq: v.val_f32 = l.val_f32 <= r.val_f32; break;
|
||||
case Token_GtEq: v.val_f32 = l.val_f32 >= r.val_f32; break;
|
||||
}
|
||||
} else if (t == t_f64) {
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: v.val_f64 = l.val_f64 == r.val_f64; break;
|
||||
case Token_NotEq: v.val_f64 = l.val_f64 != r.val_f64; break;
|
||||
case Token_Lt: v.val_f64 = l.val_f64 < r.val_f64; break;
|
||||
case Token_Gt: v.val_f64 = l.val_f64 > r.val_f64; break;
|
||||
case Token_LtEq: v.val_f64 = l.val_f64 <= r.val_f64; break;
|
||||
case Token_GtEq: v.val_f64 = l.val_f64 >= r.val_f64; break;
|
||||
}
|
||||
} else if (is_type_string(t)) {
|
||||
Array<vmValue> args = {};
|
||||
array_init(&args, vm->stack_allocator, 2);
|
||||
array_add(&args, l);
|
||||
array_add(&args, r);
|
||||
switch (bo->op) {
|
||||
case Token_CmpEq: v = vm_call_proc_by_name(vm, make_string("__string_eq"), args); break;
|
||||
case Token_NotEq: v = vm_call_proc_by_name(vm, make_string("__string_ne"), args); break;
|
||||
case Token_Lt: v = vm_call_proc_by_name(vm, make_string("__string_lt"), args); break;
|
||||
case Token_Gt: v = vm_call_proc_by_name(vm, make_string("__string_gt"), args); break;
|
||||
case Token_LtEq: v = vm_call_proc_by_name(vm, make_string("__string_le"), args); break;
|
||||
case Token_GtEq: v = vm_call_proc_by_name(vm, make_string("__string_ge"), args); break;
|
||||
}
|
||||
} else {
|
||||
GB_PANIC("TODO(bill): Vector BinaryOp");
|
||||
}
|
||||
gb_printf_err("TODO(bill): Comparison operations %.*s\n", LIT(token_strings[bo->op]));
|
||||
vm_set_value(f, value, vm_make_value_int(1)); // HACK(bill): always true
|
||||
|
||||
vm_set_value(f, value, v);
|
||||
} else {
|
||||
vmValue v = {};
|
||||
vmValue l = vm_operand_value(vm, bo->left);
|
||||
@@ -862,7 +1012,7 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
}
|
||||
vmValue proc = vm_operand_value(vm, instr->Call.value);
|
||||
if (proc.val_proc.proc != NULL) {
|
||||
vmValue result = vm_call_procedure(vm, proc.val_proc.proc, args);
|
||||
vmValue result = vm_call_proc(vm, proc.val_proc.proc, args);
|
||||
vm_set_value(f, value, result);
|
||||
} else {
|
||||
GB_PANIC("TODO(bill): external procedure calls");
|
||||
@@ -883,15 +1033,30 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
} break;
|
||||
|
||||
case ssaInstr_VectorExtractElement: {
|
||||
|
||||
vmValue vector = vm_operand_value(vm, instr->VectorExtractElement.vector);
|
||||
vmValue index = vm_operand_value(vm, instr->VectorExtractElement.index);
|
||||
vmValue v = vector.val_comp[index.val_int];
|
||||
vm_set_value(f, value, v);
|
||||
} break;
|
||||
|
||||
case ssaInstr_VectorInsertElement: {
|
||||
|
||||
vmValue vector = vm_operand_value(vm, instr->VectorInsertElement.vector);
|
||||
vmValue elem = vm_operand_value(vm, instr->VectorInsertElement.elem);
|
||||
vmValue index = vm_operand_value(vm, instr->VectorInsertElement.index);
|
||||
vector.val_comp[index.val_int] = elem;
|
||||
} break;
|
||||
|
||||
case ssaInstr_VectorShuffle: {
|
||||
auto *vs = &instr->VectorShuffle;
|
||||
vmValue old_vector = vm_operand_value(vm, instr->VectorShuffle.vector);
|
||||
vmValue new_vector = {};
|
||||
array_init_count(&new_vector.val_comp, vm->stack_allocator, vs->index_count);
|
||||
|
||||
for (i32 i = 0; i < vs->index_count; i++) {
|
||||
new_vector.val_comp[i] = old_vector.val_comp[vs->indices[i]];
|
||||
}
|
||||
|
||||
vm_set_value(f, value, new_vector);
|
||||
} break;
|
||||
|
||||
case ssaInstr_BoundsCheck: {
|
||||
@@ -904,14 +1069,12 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
array_add(&args, vm_operand_value(vm, bc->index));
|
||||
array_add(&args, vm_operand_value(vm, bc->len));
|
||||
|
||||
ssaProcedure *proc = vm_lookup_procedure(vm, make_string("__bounds_check_error"));
|
||||
vm_call_procedure(vm, proc, args);
|
||||
vm_call_proc_by_name(vm, make_string("__bounds_check_error"), args);
|
||||
} break;
|
||||
|
||||
case ssaInstr_SliceBoundsCheck: {
|
||||
auto *bc = &instr->SliceBoundsCheck;
|
||||
Array<vmValue> args = {};
|
||||
ssaProcedure *proc;
|
||||
|
||||
array_init(&args, vm->stack_allocator, 7);
|
||||
array_add(&args, vm_exact_value(vm, NULL, make_exact_value_string(bc->pos.file), t_string));
|
||||
@@ -921,12 +1084,10 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
array_add(&args, vm_operand_value(vm, bc->high));
|
||||
if (!bc->is_substring) {
|
||||
array_add(&args, vm_operand_value(vm, bc->max));
|
||||
proc = vm_lookup_procedure(vm, make_string("__slice_expr_error"));
|
||||
vm_call_proc_by_name(vm, make_string("__slice_expr_error"), args);
|
||||
} else {
|
||||
proc = vm_lookup_procedure(vm, make_string("__substring_expr_error"));
|
||||
vm_call_proc_by_name(vm, make_string("__substring_expr_error"), args);
|
||||
}
|
||||
|
||||
vm_call_procedure(vm, proc, args);
|
||||
} break;
|
||||
|
||||
default: {
|
||||
@@ -934,3 +1095,88 @@ void vm_exec_instr(VirtualMachine *vm, ssaValue *value) {
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void vm_print_value(vmValue value, Type *type) {
|
||||
type = base_type(type);
|
||||
if (is_type_string(type)) {
|
||||
vmValue data = value.val_comp[0];
|
||||
vmValue count = value.val_comp[1];
|
||||
gb_printf("`%.*s`", cast(isize)count.val_int, cast(u8 *)data.val_ptr);
|
||||
} else if (is_type_boolean(type)) {
|
||||
if (value.val_int != 0) {
|
||||
gb_printf("true");
|
||||
} else {
|
||||
gb_printf("false");
|
||||
}
|
||||
} else if (is_type_integer(type)) {
|
||||
gb_printf("%lld", cast(i64)value.val_int);
|
||||
} else if (type == t_f32) {
|
||||
gb_printf("%f", value.val_f32);
|
||||
} else if (type == t_f64) {
|
||||
gb_printf("%f", value.val_f64);
|
||||
} else if (is_type_pointer(type)) {
|
||||
gb_printf("0x%08x", value.val_ptr);
|
||||
} else if (is_type_array(type)) {
|
||||
gb_printf("[");
|
||||
for_array(i, value.val_comp) {
|
||||
if (i > 0) {
|
||||
gb_printf(", ");
|
||||
}
|
||||
vm_print_value(value.val_comp[i], type->Array.elem);
|
||||
}
|
||||
gb_printf("]");
|
||||
} else if (is_type_vector(type)) {
|
||||
gb_printf("<");
|
||||
for_array(i, value.val_comp) {
|
||||
if (i > 0) {
|
||||
gb_printf(", ");
|
||||
}
|
||||
vm_print_value(value.val_comp[i], type->Vector.elem);
|
||||
}
|
||||
gb_printf(">");
|
||||
} else if (is_type_slice(type)) {
|
||||
gb_printf("[");
|
||||
for_array(i, value.val_comp) {
|
||||
if (i > 0) {
|
||||
gb_printf(", ");
|
||||
}
|
||||
vm_print_value(value.val_comp[i], type->Slice.elem);
|
||||
}
|
||||
gb_printf("]");
|
||||
} else if (is_type_maybe(type)) {
|
||||
if (value.val_comp[1].val_int != 0) {
|
||||
gb_printf("?");
|
||||
vm_print_value(value.val_comp[0], type->Maybe.elem);
|
||||
} else {
|
||||
gb_printf("nil");
|
||||
}
|
||||
} else if (is_type_struct(type)) {
|
||||
if (value.val_comp.count == 0) {
|
||||
gb_printf("nil");
|
||||
} else {
|
||||
gb_printf("{");
|
||||
for_array(i, value.val_comp) {
|
||||
if (i > 0) {
|
||||
gb_printf(", ");
|
||||
}
|
||||
vm_print_value(value.val_comp[i], type->Record.fields[i]->type);
|
||||
}
|
||||
gb_printf("}");
|
||||
}
|
||||
} else if (is_type_tuple(type)) {
|
||||
if (value.val_comp.count != 1) {
|
||||
gb_printf("(");
|
||||
}
|
||||
for_array(i, value.val_comp) {
|
||||
if (i > 0) {
|
||||
gb_printf(", ");
|
||||
}
|
||||
vm_print_value(value.val_comp[i], type->Tuple.variables[i]->type);
|
||||
}
|
||||
if (value.val_comp.count != 1) {
|
||||
gb_printf(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user