-
-
Notifications
You must be signed in to change notification settings - Fork 43
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement some integer operations in C
These use a Rust/runtime fallback for compilers that don't provide checked integer operations.
- Loading branch information
1 parent
5a8f063
commit 445b5a5
Showing
8 changed files
with
293 additions
and
122 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
--- | ||
BasedOnStyle: LLVM | ||
IndentPPDirectives: AfterHash | ||
IndentWidth: 2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
#ifndef INKO_H | ||
#define INKO_H | ||
|
||
// We require a two's complement C compiler so we can emulate certain checked | ||
// integer operations without running into undefined behaviour. | ||
#if (-1 & 3) != 3 | ||
# error "Inko requires the C compiler to use two's complement for integers" | ||
#endif | ||
|
||
#include "stdbool.h" | ||
#include "stddef.h" | ||
#include "stdint.h" | ||
|
||
#if defined(_MSC_VER) | ||
# include "Intsafe.h" | ||
#endif | ||
|
||
#define RUST_STRING_SIZE 24 | ||
#define RUST_VEC_SIZE 24 | ||
|
||
#if defined(__clang__) | ||
# define NO_RETURN __attribute__((noreturn)) | ||
#elif defined(__GNUC__) | ||
# define NO_RETURN __attribute__((noreturn)) | ||
#elif defined(_MSC_VER) | ||
# define NO_RETURN __declspec(noreturn) | ||
#else | ||
# define NO_RETURN | ||
#endif | ||
|
||
#define INKO_INT_MASK 0x1 | ||
#define INKO_INT_READ(val) \ | ||
((((size_t)val & INKO_INT_MASK) == INKO_INT_MASK) ? ((int64_t)val) >> 1 \ | ||
: val->value) | ||
|
||
#define KIND_REGULAR 0 | ||
#define KIND_PERMANENT 1 | ||
#define KIND_REF 2 | ||
#define KIND_ATOMIC 3 | ||
|
||
#define RESULT_OK 0 | ||
#define RESULT_ERROR 1 | ||
#define RESULT_TIMEOUT 2 | ||
#define RESULT_NONE 3 | ||
|
||
typedef struct InkoResult { | ||
uint8_t tag; | ||
void *value; | ||
} InkoResult; | ||
|
||
typedef struct InkoMethod { | ||
uint32_t hash; | ||
void (*code)(); | ||
} InkoMethod; | ||
|
||
typedef struct InkoClass { | ||
uint8_t name[RUST_STRING_SIZE]; | ||
size_t instance_size; | ||
uint16_t method_slots; | ||
void *methods[]; | ||
} InkoClass; | ||
|
||
typedef struct Header { | ||
InkoClass *class; | ||
uint8_t kind; | ||
uint16_t references; | ||
} Header; | ||
|
||
typedef struct InkoArray { | ||
Header header; | ||
uint8_t value[RUST_VEC_SIZE]; | ||
} InkoArray; | ||
|
||
typedef struct InkoByteArray { | ||
Header header; | ||
uint8_t value[RUST_VEC_SIZE]; | ||
} InkoByteArray; | ||
|
||
typedef struct InkoInt { | ||
Header header; | ||
int64_t value; | ||
} InkoInt; | ||
|
||
typedef struct InkoBool { | ||
Header header; | ||
bool value; | ||
} InkoBool; | ||
|
||
typedef struct InkoNil { | ||
Header header; | ||
} InkoNil; | ||
|
||
typedef struct InkoFloat { | ||
Header header; | ||
double value; | ||
} InkoFloat; | ||
|
||
typedef struct InkoString { | ||
Header header; | ||
uint8_t value[RUST_VEC_SIZE]; | ||
} InkoString; | ||
|
||
typedef struct InkoProcess { | ||
Header header; | ||
uint64_t run_lock; | ||
uint8_t write[16]; | ||
InkoResult message_result; | ||
void *stack_pointer; | ||
uint8_t stack[16]; | ||
uint8_t call_stack[RUST_VEC_SIZE]; | ||
void *thread; | ||
uint8_t state[56]; | ||
void *fields[]; | ||
} InkoProcess; | ||
|
||
typedef struct InkoFuture { | ||
Header header; | ||
void *value; | ||
} InkoFuture; | ||
|
||
typedef struct InkoContext { | ||
void *state; | ||
InkoProcess *process; | ||
void **arguments; | ||
} InkoContext; | ||
|
||
typedef struct InkoMethodCounts { | ||
uint16_t int_class; | ||
uint16_t float_class; | ||
uint16_t string_class; | ||
uint16_t array_class; | ||
uint16_t boolean_class; | ||
uint16_t nil_class; | ||
uint16_t byte_array_class; | ||
uint16_t future_class; | ||
} InkoMethodCounts; | ||
|
||
typedef struct InkoStackFrame { | ||
InkoString *name; | ||
InkoString *path; | ||
InkoInt *line; | ||
} InkoStackFrame; | ||
|
||
extern int64_t inko_int64_add(int64_t, int64_t, int64_t *); | ||
extern int64_t inko_int64_sub(int64_t, int64_t, int64_t *); | ||
extern int64_t inko_int64_mul(int64_t, int64_t, int64_t *); | ||
|
||
bool int64_add(int64_t lhs, int64_t rhs, int64_t *result) { | ||
#if defined(__clang__) || defined(__GNUC__) | ||
return __builtin_saddll_overflow(lhs, rhs, (long long *)result); | ||
#elif defined(_MSC_VER) | ||
return LongLongAdd(lhs, rhs, (long long *)result) != S_OK; | ||
#else | ||
return inko_int64_add(lhs, rhs, result); | ||
#endif | ||
} | ||
|
||
bool int64_sub(int64_t lhs, int64_t rhs, int64_t *result) { | ||
#if defined(__clang__) || defined(__GNUC__) | ||
return __builtin_ssubll_overflow(lhs, rhs, (long long *)result); | ||
#elif defined(_MSC_VER) | ||
return LongLongSub(lhs, rhs, (long long *)result) != S_OK; | ||
#else | ||
return inko_int64_sub(lhs, rhs, result); | ||
#endif | ||
} | ||
|
||
bool int64_div(int64_t lhs, int64_t rhs, int64_t *result) { | ||
if (rhs == 0 || (lhs == INT64_MIN && rhs == -1)) { | ||
return true; | ||
} | ||
|
||
*result = lhs / rhs; | ||
|
||
return false; | ||
} | ||
|
||
bool int64_mul(int64_t lhs, int64_t rhs, int64_t *result) { | ||
#if defined(__clang__) || defined(__GNUC__) | ||
return __builtin_smulll_overflow(lhs, rhs, (long long *)result); | ||
#elif defined(_MSC_VER) | ||
return LongLongMult(lhs, rhs, (long long *)result) != S_OK; | ||
#else | ||
return inko_int64_mul(lhs, rhs, result); | ||
#endif | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.