File restructure (again)

This commit is contained in:
Ginger Bill
2016-11-02 13:44:04 +00:00
parent fa0eb88b7b
commit 8534e064b9
60 changed files with 7969 additions and 5377 deletions
+17 -5
View File
@@ -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
View File
@@ -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 {
+10
View File
@@ -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
View File
@@ -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;
+143
View File
@@ -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 */
+47
View File
@@ -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 */
+66
View File
@@ -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 */
+42
View File
@@ -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 */
+43
View File
@@ -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 */
+40
View File
@@ -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 */
+45
View File
@@ -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 */
+59
View File
@@ -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_ */
+53
View File
@@ -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_ */
+56
View File
@@ -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 */
+47
View File
@@ -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 */
+289
View File
@@ -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 */
+72
View File
@@ -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 */
+90
View File
@@ -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 */
+42
View File
@@ -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 */
+38
View File
@@ -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 */
+40
View File
@@ -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 */
+55
View File
@@ -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 */
+40
View File
@@ -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 */
+40
View File
@@ -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 */
+75
View File
@@ -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 */
+91
View File
@@ -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 */
+66
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
-1965
View File
File diff suppressed because it is too large Load Diff
-671
View File
@@ -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");
}
-48
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
-495
View File
@@ -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;
}
View File
-114
View File
@@ -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);
}
}
View File
-846
View File
@@ -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"
+11
View File
@@ -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
View File
@@ -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(")");
}
}
}