mirror of
https://github.com/Ed94/Odin.git
synced 2026-06-19 12:22:23 -07:00
Merge branch 'master' into new-matrix-type
This commit is contained in:
@@ -93,7 +93,7 @@ jobs:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
python-version: '3.8.x'
|
||||
|
||||
- name: Install B2 CLI
|
||||
shell: bash
|
||||
@@ -127,16 +127,23 @@ jobs:
|
||||
BUCKET: ${{ secrets.B2_BUCKET }}
|
||||
DAYS_TO_KEEP: ${{ secrets.B2_DAYS_TO_KEEP }}
|
||||
run: |
|
||||
echo Authorizing B2 account
|
||||
b2 authorize-account "$APPID" "$APPKEY"
|
||||
|
||||
|
||||
echo Uploading artifcates to B2
|
||||
chmod +x ./ci/upload_create_nightly.sh
|
||||
./ci/upload_create_nightly.sh "$BUCKET" windows-amd64 windows_artifacts/
|
||||
./ci/upload_create_nightly.sh "$BUCKET" ubuntu-amd64 ubuntu_artifacts/
|
||||
./ci/upload_create_nightly.sh "$BUCKET" macos-amd64 macos_artifacts/
|
||||
|
||||
echo Deleting old artifacts in B2
|
||||
python3 ci/delete_old_binaries.py "$BUCKET" "$DAYS_TO_KEEP"
|
||||
|
||||
echo Creating nightly.json
|
||||
python3 ci/create_nightly_json.py "$BUCKET" > nightly.json
|
||||
|
||||
echo Uploading nightly.json
|
||||
b2 upload-file "$BUCKET" nightly.json nightly.json
|
||||
|
||||
echo Clear B2 account info
|
||||
b2 clear-account
|
||||
|
||||
@@ -13,6 +13,8 @@ create_multi_logger :: proc(logs: ..Logger) -> Logger {
|
||||
}
|
||||
|
||||
destroy_multi_logger :: proc(log : ^Logger) {
|
||||
data := (^Multi_Logger_Data)(log.data)
|
||||
delete(data.loggers)
|
||||
free(log.data)
|
||||
log^ = nil_logger()
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ package runtime
|
||||
default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||
size, alignment: int,
|
||||
old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) {
|
||||
return nil, .None;
|
||||
return nil, .None
|
||||
}
|
||||
|
||||
default_allocator :: proc() -> Allocator {
|
||||
return Allocator{
|
||||
procedure = default_allocator_proc,
|
||||
data = nil,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+71
-11
@@ -177,8 +177,70 @@ mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment
|
||||
new_ptr = raw_data(new_data)
|
||||
return
|
||||
}
|
||||
memory_equal :: proc "contextless" (a, b: rawptr, n: int) -> bool {
|
||||
return memory_compare(a, b, n) == 0
|
||||
memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool {
|
||||
switch {
|
||||
case n == 0: return true
|
||||
case x == y: return true
|
||||
}
|
||||
|
||||
a, b := ([^]byte)(x), ([^]byte)(y)
|
||||
length := uint(n)
|
||||
|
||||
when size_of(uint) == 8 {
|
||||
if word_length := length >> 3; word_length != 0 {
|
||||
for i in 0..<word_length {
|
||||
if intrinsics.unaligned_load((^u64)(a)) != intrinsics.unaligned_load((^u64)(b)) {
|
||||
return false
|
||||
}
|
||||
a = a[size_of(u64):]
|
||||
b = b[size_of(u64):]
|
||||
}
|
||||
}
|
||||
|
||||
if length & 4 != 0 {
|
||||
if intrinsics.unaligned_load((^u32)(a)) != intrinsics.unaligned_load((^u32)(b)) {
|
||||
return false
|
||||
}
|
||||
a = a[size_of(u32):]
|
||||
b = b[size_of(u32):]
|
||||
}
|
||||
|
||||
if length & 2 != 0 {
|
||||
if intrinsics.unaligned_load((^u16)(a)) != intrinsics.unaligned_load((^u16)(b)) {
|
||||
return false
|
||||
}
|
||||
a = a[size_of(u16):]
|
||||
b = b[size_of(u16):]
|
||||
}
|
||||
|
||||
if length & 1 != 0 && a[0] != b[0] {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
} else {
|
||||
if word_length := length >> 2; word_length != 0 {
|
||||
for i in 0..<word_length {
|
||||
if intrinsics.unaligned_load((^u32)(a)) != intrinsics.unaligned_load((^u32)(b)) {
|
||||
return false
|
||||
}
|
||||
a = a[size_of(u32):]
|
||||
b = b[size_of(u32):]
|
||||
}
|
||||
}
|
||||
|
||||
length &= 3
|
||||
|
||||
if length != 0 {
|
||||
for i in 0..<length {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
}
|
||||
memory_compare :: proc "contextless" (a, b: rawptr, n: int) -> int #no_bounds_check {
|
||||
switch {
|
||||
@@ -258,15 +320,13 @@ memory_compare_zero :: proc "contextless" (a: rawptr, n: int) -> int #no_bounds_
|
||||
return 0
|
||||
}
|
||||
|
||||
string_eq :: proc "contextless" (a, b: string) -> bool {
|
||||
x := transmute(Raw_String)a
|
||||
y := transmute(Raw_String)b
|
||||
switch {
|
||||
case x.len != y.len: return false
|
||||
case x.len == 0: return true
|
||||
case x.data == y.data: return true
|
||||
string_eq :: proc "contextless" (lhs, rhs: string) -> bool {
|
||||
x := transmute(Raw_String)lhs
|
||||
y := transmute(Raw_String)rhs
|
||||
if x.len != y.len {
|
||||
return false
|
||||
}
|
||||
return string_cmp(a, b) == 0
|
||||
return #force_inline memory_equal(x.data, y.data, x.len)
|
||||
}
|
||||
|
||||
string_cmp :: proc "contextless" (a, b: string) -> int {
|
||||
@@ -708,7 +768,7 @@ floattidf :: proc "c" (a: i128) -> f64 {
|
||||
a += 1
|
||||
a >>= 2
|
||||
|
||||
if a & (1 << DBL_MANT_DIG) != 0 {
|
||||
if a & (i128(1) << DBL_MANT_DIG) != 0 {
|
||||
a >>= 1
|
||||
e += 1
|
||||
}
|
||||
|
||||
@@ -3,5 +3,5 @@ package runtime
|
||||
|
||||
// TODO(bill): reimplement `os.write`
|
||||
_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
return 0, -1;
|
||||
return 0, -1
|
||||
}
|
||||
|
||||
@@ -2749,6 +2749,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
|
||||
case BuiltinProc_volatile_store:
|
||||
/*fallthrough*/
|
||||
case BuiltinProc_unaligned_store:
|
||||
/*fallthrough*/
|
||||
case BuiltinProc_atomic_store:
|
||||
case BuiltinProc_atomic_store_rel:
|
||||
case BuiltinProc_atomic_store_relaxed:
|
||||
@@ -2770,6 +2772,8 @@ bool check_builtin_procedure(CheckerContext *c, Operand *operand, Ast *call, i32
|
||||
|
||||
case BuiltinProc_volatile_load:
|
||||
/*fallthrough*/
|
||||
case BuiltinProc_unaligned_load:
|
||||
/*fallthrough*/
|
||||
case BuiltinProc_atomic_load:
|
||||
case BuiltinProc_atomic_load_acq:
|
||||
case BuiltinProc_atomic_load_relaxed:
|
||||
|
||||
+21
-9
@@ -837,7 +837,7 @@ void check_assignment(CheckerContext *c, Operand *operand, Type *type, String co
|
||||
operand->mode = Addressing_Invalid;
|
||||
}
|
||||
|
||||
|
||||
convert_to_typed(c, operand, type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3208,6 +3208,10 @@ void update_untyped_expr_type(CheckerContext *c, Ast *e, Type *type, bool final)
|
||||
if (type != nullptr && type != t_invalid) {
|
||||
if (e->tav.type == nullptr || e->tav.type == t_invalid) {
|
||||
add_type_and_value(c->info, e, e->tav.mode, type ? type : e->tav.type, e->tav.value);
|
||||
if (e->kind == Ast_TernaryIfExpr) {
|
||||
update_untyped_expr_type(c, e->TernaryIfExpr.x, type, final);
|
||||
update_untyped_expr_type(c, e->TernaryIfExpr.y, type, final);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -3414,9 +3418,9 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
|
||||
|
||||
case Basic_UntypedNil:
|
||||
if (is_type_any(target_type)) {
|
||||
target_type = t_untyped_nil;
|
||||
// target_type = t_untyped_nil;
|
||||
} else if (is_type_cstring(target_type)) {
|
||||
target_type = t_untyped_nil;
|
||||
// target_type = t_untyped_nil;
|
||||
} else if (!type_has_nil(target_type)) {
|
||||
operand->mode = Addressing_Invalid;
|
||||
convert_untyped_error(c, operand, target_type);
|
||||
@@ -3587,6 +3591,14 @@ void convert_to_typed(CheckerContext *c, Operand *operand, Type *target_type) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (is_type_any(target_type) && is_type_untyped(operand->type)) {
|
||||
if (is_type_untyped_nil(operand->type) && is_type_untyped_undef(operand->type)) {
|
||||
|
||||
} else {
|
||||
target_type = default_type(operand->type);
|
||||
}
|
||||
}
|
||||
|
||||
update_untyped_expr_type(c, operand->expr, target_type, true);
|
||||
operand->type = target_type;
|
||||
@@ -7030,18 +7042,18 @@ ExprKind check_expr_base_internal(CheckerContext *c, Operand *o, Ast *node, Type
|
||||
return kind;
|
||||
}
|
||||
|
||||
Type *type = x.type;
|
||||
if (is_type_untyped_nil(type) || is_type_untyped_undef(type)) {
|
||||
type = y.type;
|
||||
o->type = x.type;
|
||||
if (is_type_untyped_nil(o->type) || is_type_untyped_undef(o->type)) {
|
||||
o->type = y.type;
|
||||
}
|
||||
|
||||
o->type = type;
|
||||
o->mode = Addressing_Value;
|
||||
if (type_hint != nullptr && is_type_untyped(type)) {
|
||||
o->expr = node;
|
||||
if (type_hint != nullptr && is_type_untyped(o->type)) {
|
||||
if (check_cast_internal(c, &x, type_hint) &&
|
||||
check_cast_internal(c, &y, type_hint)) {
|
||||
convert_to_typed(c, o, type_hint);
|
||||
update_untyped_expr_type(c, node, type_hint, !is_type_untyped(type_hint));
|
||||
o->type = type_hint;
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
+11
-2
@@ -1111,9 +1111,12 @@ void check_set_expr_info(CheckerContext *c, Ast *expr, AddressingMode mode, Type
|
||||
void check_remove_expr_info(CheckerContext *c, Ast *e) {
|
||||
if (c->untyped != nullptr) {
|
||||
map_remove(c->untyped, hash_pointer(e));
|
||||
GB_ASSERT(map_get(c->untyped, hash_pointer(e)) == nullptr);
|
||||
} else {
|
||||
auto *untyped = &c->info->global_untyped;
|
||||
mutex_lock(&c->info->global_untyped_mutex);
|
||||
map_remove(&c->info->global_untyped, hash_pointer(e));
|
||||
map_remove(untyped, hash_pointer(e));
|
||||
GB_ASSERT(map_get(untyped, hash_pointer(e)) == nullptr);
|
||||
mutex_unlock(&c->info->global_untyped_mutex);
|
||||
}
|
||||
}
|
||||
@@ -1190,7 +1193,13 @@ void add_type_and_value(CheckerInfo *i, Ast *expr, AddressingMode mode, Type *ty
|
||||
while (prev_expr != expr) {
|
||||
prev_expr = expr;
|
||||
expr->tav.mode = mode;
|
||||
expr->tav.type = type;
|
||||
if (type != nullptr && expr->tav.type != nullptr &&
|
||||
is_type_any(type) && is_type_untyped(expr->tav.type)) {
|
||||
// ignore
|
||||
} else {
|
||||
expr->tav.type = type;
|
||||
}
|
||||
|
||||
if (mode == Addressing_Constant || mode == Addressing_Invalid) {
|
||||
expr->tav.value = value;
|
||||
} else if (mode == Addressing_Value && is_type_typeid(type)) {
|
||||
|
||||
@@ -77,6 +77,9 @@ enum BuiltinProcId {
|
||||
BuiltinProc_volatile_store,
|
||||
BuiltinProc_volatile_load,
|
||||
|
||||
BuiltinProc_unaligned_store,
|
||||
BuiltinProc_unaligned_load,
|
||||
|
||||
BuiltinProc_prefetch_read_instruction,
|
||||
BuiltinProc_prefetch_read_data,
|
||||
BuiltinProc_prefetch_write_instruction,
|
||||
@@ -326,6 +329,9 @@ gb_global BuiltinProc builtin_procs[BuiltinProc_COUNT] = {
|
||||
{STR_LIT("volatile_store"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("volatile_load"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("unaligned_store"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("unaligned_load"), 1, false, Expr_Expr, BuiltinProcPkg_intrinsics},
|
||||
|
||||
{STR_LIT("prefetch_read_instruction"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("prefetch_read_data"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
{STR_LIT("prefetch_write_instruction"), 2, false, Expr_Stmt, BuiltinProcPkg_intrinsics},
|
||||
|
||||
@@ -329,7 +329,7 @@ LLVMValueRef lb_big_int_to_llvm(lbModule *m, Type *original_type, BigInt const *
|
||||
debug_print_big_int(a);
|
||||
gb_printf_err("%s -> %tu\n", type_to_string(original_type), sz);;
|
||||
}
|
||||
GB_ASSERT_MSG(sz >= max_count, "max_count: %tu, sz: %tu, written: %tu", max_count, sz, written);
|
||||
GB_ASSERT_MSG(sz >= max_count, "max_count: %tu, sz: %tu, written: %tu, type %s", max_count, sz, written, type_to_string(original_type));
|
||||
GB_ASSERT(gb_size_of(rop64) >= sz);
|
||||
|
||||
mp_err err = mp_pack(rop, sz, &written,
|
||||
|
||||
+13
-13
@@ -2806,17 +2806,18 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
|
||||
TokenPos expr_pos = ast_token(expr).pos;
|
||||
TypeAndValue tv = type_and_value_of_expr(expr);
|
||||
Type *type = type_of_expr(expr);
|
||||
GB_ASSERT_MSG(tv.mode != Addressing_Invalid, "invalid expression '%s' (tv.mode = %d, tv.type = %s) @ %s\n Current Proc: %.*s : %s", expr_to_string(expr), tv.mode, type_to_string(tv.type), token_pos_to_string(expr_pos), LIT(p->name), type_to_string(p->type));
|
||||
|
||||
if (tv.value.kind != ExactValue_Invalid) {
|
||||
// NOTE(bill): The commented out code below is just for debug purposes only
|
||||
// GB_ASSERT_MSG(!is_type_untyped(tv.type), "%s @ %s\n%s", type_to_string(tv.type), token_pos_to_string(expr_pos), expr_to_string(expr));
|
||||
// if (is_type_untyped(tv.type)) {
|
||||
// gb_printf_err("%s %s\n", token_pos_to_string(expr_pos), expr_to_string(expr));
|
||||
// if (is_type_untyped(type)) {
|
||||
// gb_printf_err("%s %s : %s @ %p\n", token_pos_to_string(expr_pos), expr_to_string(expr), type_to_string(expr->tav.type), expr);
|
||||
// GB_PANIC("%s\n", type_to_string(tv.type));
|
||||
// }
|
||||
|
||||
// NOTE(bill): Short on constant values
|
||||
return lb_const_value(p->module, tv.type, tv.value);
|
||||
return lb_const_value(p->module, type, tv.value);
|
||||
}
|
||||
|
||||
#if 0
|
||||
@@ -2847,12 +2848,12 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
|
||||
case_ast_node(u, Undef, expr)
|
||||
lbValue res = {};
|
||||
if (is_type_untyped(tv.type)) {
|
||||
if (is_type_untyped(type)) {
|
||||
res.value = nullptr;
|
||||
res.type = t_untyped_undef;
|
||||
} else {
|
||||
res.value = LLVMGetUndef(lb_type(m, tv.type));
|
||||
res.type = tv.type;
|
||||
res.value = LLVMGetUndef(lb_type(m, type));
|
||||
res.type = type;
|
||||
}
|
||||
return res;
|
||||
case_end;
|
||||
@@ -2893,7 +2894,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
TypeAndValue tav = type_and_value_of_expr(expr);
|
||||
GB_ASSERT(tav.mode == Addressing_Constant);
|
||||
|
||||
return lb_const_value(p->module, tv.type, tv.value);
|
||||
return lb_const_value(p->module, type, tv.value);
|
||||
case_end;
|
||||
|
||||
case_ast_node(se, SelectorCallExpr, expr);
|
||||
@@ -2966,7 +2967,6 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
|
||||
case_ast_node(ta, TypeAssertion, expr);
|
||||
TokenPos pos = ast_token(expr).pos;
|
||||
Type *type = tv.type;
|
||||
lbValue e = lb_build_expr(p, ta->expr);
|
||||
Type *t = type_deref(e.type);
|
||||
if (is_type_union(t)) {
|
||||
@@ -2986,16 +2986,16 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
lbValue e = lb_build_expr(p, tc->expr);
|
||||
switch (tc->token.kind) {
|
||||
case Token_cast:
|
||||
return lb_emit_conv(p, e, tv.type);
|
||||
return lb_emit_conv(p, e, type);
|
||||
case Token_transmute:
|
||||
return lb_emit_transmute(p, e, tv.type);
|
||||
return lb_emit_transmute(p, e, type);
|
||||
}
|
||||
GB_PANIC("Invalid AST TypeCast");
|
||||
case_end;
|
||||
|
||||
case_ast_node(ac, AutoCast, expr);
|
||||
lbValue value = lb_build_expr(p, ac->expr);
|
||||
return lb_emit_conv(p, value, tv.type);
|
||||
return lb_emit_conv(p, value, type);
|
||||
case_end;
|
||||
|
||||
case_ast_node(ue, UnaryExpr, expr);
|
||||
@@ -3005,7 +3005,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
default:
|
||||
{
|
||||
lbValue v = lb_build_expr(p, ue->expr);
|
||||
return lb_emit_unary_arith(p, ue->op.kind, v, tv.type);
|
||||
return lb_emit_unary_arith(p, ue->op.kind, v, type);
|
||||
}
|
||||
}
|
||||
case_end;
|
||||
|
||||
+88
-50
@@ -1,3 +1,62 @@
|
||||
void lb_mem_copy_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false) {
|
||||
dst = lb_emit_conv(p, dst, t_rawptr);
|
||||
src = lb_emit_conv(p, src, t_rawptr);
|
||||
len = lb_emit_conv(p, len, t_int);
|
||||
|
||||
char const *name = "llvm.memmove";
|
||||
if (LLVMIsConstant(len.value)) {
|
||||
i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value);
|
||||
if (const_len <= 4*build_context.word_size) {
|
||||
name = "llvm.memmove.inline";
|
||||
}
|
||||
}
|
||||
|
||||
LLVMTypeRef types[3] = {
|
||||
lb_type(p->module, t_rawptr),
|
||||
lb_type(p->module, t_rawptr),
|
||||
lb_type(p->module, t_int)
|
||||
};
|
||||
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
|
||||
GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]), LLVMPrintTypeToString(types[2]));
|
||||
LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
|
||||
|
||||
LLVMValueRef args[4] = {};
|
||||
args[0] = dst.value;
|
||||
args[1] = src.value;
|
||||
args[2] = len.value;
|
||||
args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, is_volatile);
|
||||
LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
|
||||
}
|
||||
void lb_mem_copy_non_overlapping(lbProcedure *p, lbValue dst, lbValue src, lbValue len, bool is_volatile=false) {
|
||||
dst = lb_emit_conv(p, dst, t_rawptr);
|
||||
src = lb_emit_conv(p, src, t_rawptr);
|
||||
len = lb_emit_conv(p, len, t_int);
|
||||
|
||||
char const *name = "llvm.memcpy";
|
||||
if (LLVMIsConstant(len.value)) {
|
||||
i64 const_len = cast(i64)LLVMConstIntGetSExtValue(len.value);
|
||||
if (const_len <= 4*build_context.word_size) {
|
||||
name = "llvm.memcpy.inline";
|
||||
}
|
||||
}
|
||||
|
||||
LLVMTypeRef types[3] = {
|
||||
lb_type(p->module, t_rawptr),
|
||||
lb_type(p->module, t_rawptr),
|
||||
lb_type(p->module, t_int)
|
||||
};
|
||||
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
|
||||
GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]), LLVMPrintTypeToString(types[2]));
|
||||
LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
|
||||
|
||||
LLVMValueRef args[4] = {};
|
||||
args[0] = dst.value;
|
||||
args[1] = src.value;
|
||||
args[2] = len.value;
|
||||
args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, is_volatile);
|
||||
LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
|
||||
}
|
||||
|
||||
|
||||
lbProcedure *lb_create_procedure(lbModule *m, Entity *entity, bool ignore_body) {
|
||||
GB_ASSERT(entity != nullptr);
|
||||
@@ -1487,61 +1546,21 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
|
||||
}
|
||||
|
||||
case BuiltinProc_mem_copy:
|
||||
{
|
||||
lbValue dst = lb_build_expr(p, ce->args[0]);
|
||||
lbValue src = lb_build_expr(p, ce->args[1]);
|
||||
lbValue len = lb_build_expr(p, ce->args[2]);
|
||||
|
||||
lb_mem_copy_overlapping(p, dst, src, len, false);
|
||||
return {};
|
||||
}
|
||||
case BuiltinProc_mem_copy_non_overlapping:
|
||||
{
|
||||
lbValue dst = lb_build_expr(p, ce->args[0]);
|
||||
lbValue src = lb_build_expr(p, ce->args[1]);
|
||||
lbValue len = lb_build_expr(p, ce->args[2]);
|
||||
dst = lb_emit_conv(p, dst, t_rawptr);
|
||||
src = lb_emit_conv(p, src, t_rawptr);
|
||||
len = lb_emit_conv(p, len, t_int);
|
||||
|
||||
bool is_inlinable = false;
|
||||
|
||||
if (ce->args[2]->tav.mode == Addressing_Constant) {
|
||||
ExactValue ev = exact_value_to_integer(ce->args[2]->tav.value);
|
||||
i64 const_len = exact_value_to_i64(ev);
|
||||
// TODO(bill): Determine when it is better to do the `*.inline` versions
|
||||
if (const_len <= 4*build_context.word_size) {
|
||||
is_inlinable = true;
|
||||
}
|
||||
}
|
||||
|
||||
char const *name = nullptr;
|
||||
switch (id) {
|
||||
case BuiltinProc_mem_copy:
|
||||
if (is_inlinable) {
|
||||
name = "llvm.memmove.inline";
|
||||
} else {
|
||||
name = "llvm.memmove";
|
||||
}
|
||||
break;
|
||||
case BuiltinProc_mem_copy_non_overlapping:
|
||||
if (is_inlinable) {
|
||||
name = "llvm.memcpy.line";
|
||||
} else {
|
||||
name = "llvm.memcpy";
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
LLVMTypeRef types[3] = {
|
||||
lb_type(p->module, t_rawptr),
|
||||
lb_type(p->module, t_rawptr),
|
||||
lb_type(p->module, t_int)
|
||||
};
|
||||
unsigned id = LLVMLookupIntrinsicID(name, gb_strlen(name));
|
||||
GB_ASSERT_MSG(id != 0, "Unable to find %s.%s.%s.%s", name, LLVMPrintTypeToString(types[0]), LLVMPrintTypeToString(types[1]), LLVMPrintTypeToString(types[2]));
|
||||
LLVMValueRef ip = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
|
||||
|
||||
LLVMValueRef args[4] = {};
|
||||
args[0] = dst.value;
|
||||
args[1] = src.value;
|
||||
args[2] = len.value;
|
||||
args[3] = LLVMConstInt(LLVMInt1TypeInContext(p->module->ctx), 0, false); // is_volatile parameter
|
||||
|
||||
LLVMBuildCall(p->builder, ip, args, gb_count_of(args), "");
|
||||
|
||||
|
||||
lb_mem_copy_non_overlapping(p, dst, src, len, false);
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -1647,6 +1666,25 @@ lbValue lb_build_builtin_proc(lbProcedure *p, Ast *expr, TypeAndValue const &tv,
|
||||
res.type = type_deref(dst.type);
|
||||
return res;
|
||||
}
|
||||
|
||||
case BuiltinProc_unaligned_store:
|
||||
{
|
||||
lbValue dst = lb_build_expr(p, ce->args[0]);
|
||||
lbValue src = lb_build_expr(p, ce->args[1]);
|
||||
src = lb_address_from_load_or_generate_local(p, src);
|
||||
Type *t = type_deref(dst.type);
|
||||
lb_mem_copy_non_overlapping(p, dst, src, lb_const_int(p->module, t_int, type_size_of(t)), false);
|
||||
return {};
|
||||
}
|
||||
|
||||
case BuiltinProc_unaligned_load:
|
||||
{
|
||||
lbValue src = lb_build_expr(p, ce->args[0]);
|
||||
Type *t = type_deref(src.type);
|
||||
lbAddr dst = lb_add_local_generated(p, t, false);
|
||||
lb_mem_copy_non_overlapping(p, dst.addr, src, lb_const_int(p->module, t_int, type_size_of(t)), false);
|
||||
return lb_addr_load(p, dst);
|
||||
}
|
||||
|
||||
case BuiltinProc_atomic_add:
|
||||
case BuiltinProc_atomic_add_acq:
|
||||
|
||||
+6
-3
@@ -632,7 +632,9 @@ enum BuildFlagKind {
|
||||
BuildFlag_IgnoreWarnings,
|
||||
BuildFlag_WarningsAsErrors,
|
||||
BuildFlag_VerboseErrors,
|
||||
BuildFlag_IgnoreLazy, // internal use only
|
||||
|
||||
// internal use only
|
||||
BuildFlag_InternalIgnoreLazy,
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
BuildFlag_IgnoreVsSearch,
|
||||
@@ -779,7 +781,8 @@ bool parse_build_flags(Array<String> args) {
|
||||
add_flag(&build_flags, BuildFlag_IgnoreWarnings, str_lit("ignore-warnings"), BuildFlagParam_None, Command_all);
|
||||
add_flag(&build_flags, BuildFlag_WarningsAsErrors, str_lit("warnings-as-errors"), BuildFlagParam_None, Command_all);
|
||||
add_flag(&build_flags, BuildFlag_VerboseErrors, str_lit("verbose-errors"), BuildFlagParam_None, Command_all);
|
||||
add_flag(&build_flags, BuildFlag_IgnoreLazy, str_lit("ignore-lazy"), BuildFlagParam_None, Command_all);
|
||||
|
||||
add_flag(&build_flags, BuildFlag_InternalIgnoreLazy, str_lit("internal-ignore-lazy"), BuildFlagParam_None, Command_all);
|
||||
|
||||
#if defined(GB_SYSTEM_WINDOWS)
|
||||
add_flag(&build_flags, BuildFlag_IgnoreVsSearch, str_lit("ignore-vs-search"), BuildFlagParam_None, Command__does_build);
|
||||
@@ -1393,7 +1396,7 @@ bool parse_build_flags(Array<String> args) {
|
||||
build_context.show_error_line = true;
|
||||
break;
|
||||
|
||||
case BuildFlag_IgnoreLazy:
|
||||
case BuildFlag_InternalIgnoreLazy:
|
||||
build_context.ignore_lazy = true;
|
||||
break;
|
||||
|
||||
|
||||
+22
-18
@@ -114,16 +114,17 @@ gb_internal isize map__add_entry(Map<T> *h, HashKey const &key) {
|
||||
template <typename T>
|
||||
gb_internal MapFindResult map__find(Map<T> *h, HashKey const &key) {
|
||||
MapFindResult fr = {-1, -1, -1};
|
||||
if (h->hashes.count > 0) {
|
||||
fr.hash_index = key.key & (h->hashes.count-1);
|
||||
fr.entry_index = h->hashes.data[fr.hash_index];
|
||||
while (fr.entry_index >= 0) {
|
||||
if (hash_key_equal(h->entries.data[fr.entry_index].key, key)) {
|
||||
return fr;
|
||||
}
|
||||
fr.entry_prev = fr.entry_index;
|
||||
fr.entry_index = h->entries.data[fr.entry_index].next;
|
||||
if (h->hashes.count == 0) {
|
||||
return fr;
|
||||
}
|
||||
fr.hash_index = key.key & (h->hashes.count-1);
|
||||
fr.entry_index = h->hashes.data[fr.hash_index];
|
||||
while (fr.entry_index >= 0) {
|
||||
if (hash_key_equal(h->entries.data[fr.entry_index].key, key)) {
|
||||
return fr;
|
||||
}
|
||||
fr.entry_prev = fr.entry_index;
|
||||
fr.entry_index = h->entries.data[fr.entry_index].next;
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
@@ -131,16 +132,17 @@ gb_internal MapFindResult map__find(Map<T> *h, HashKey const &key) {
|
||||
template <typename T>
|
||||
gb_internal MapFindResult map__find_from_entry(Map<T> *h, MapEntry<T> *e) {
|
||||
MapFindResult fr = {-1, -1, -1};
|
||||
if (h->hashes.count > 0) {
|
||||
fr.hash_index = e->key.key & (h->hashes.count-1);
|
||||
fr.entry_index = h->hashes.data[fr.hash_index];
|
||||
while (fr.entry_index >= 0) {
|
||||
if (&h->entries.data[fr.entry_index] == e) {
|
||||
return fr;
|
||||
}
|
||||
fr.entry_prev = fr.entry_index;
|
||||
fr.entry_index = h->entries.data[fr.entry_index].next;
|
||||
if (h->hashes.count == 0) {
|
||||
return fr;
|
||||
}
|
||||
fr.hash_index = e->key.key & (h->hashes.count-1);
|
||||
fr.entry_index = h->hashes.data[fr.hash_index];
|
||||
while (fr.entry_index >= 0) {
|
||||
if (&h->entries.data[fr.entry_index] == e) {
|
||||
return fr;
|
||||
}
|
||||
fr.entry_prev = fr.entry_index;
|
||||
fr.entry_index = h->entries.data[fr.entry_index].next;
|
||||
}
|
||||
return fr;
|
||||
}
|
||||
@@ -246,6 +248,8 @@ void map__erase(Map<T> *h, MapFindResult const &fr) {
|
||||
return;
|
||||
}
|
||||
h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1];
|
||||
array_pop(&h->entries);
|
||||
|
||||
last = map__find(h, h->entries.data[fr.entry_index].key);
|
||||
if (last.entry_prev >= 0) {
|
||||
h->entries.data[last.entry_prev].next = fr.entry_index;
|
||||
|
||||
+4
-2
@@ -2572,6 +2572,9 @@ bool is_literal_type(Ast *node) {
|
||||
case Ast_MatrixType:
|
||||
case Ast_CallExpr:
|
||||
return true;
|
||||
case Ast_MultiPointerType:
|
||||
// For better error messages
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -5426,8 +5429,7 @@ bool parse_file(Parser *p, AstFile *f) {
|
||||
// Ignore
|
||||
} else if (f->flags & AstFile_IsTest) {
|
||||
// Ignore
|
||||
} else if (build_context.command_kind == Command_doc &&
|
||||
f->pkg->kind == Package_Init) {
|
||||
} else if (f->pkg->kind == Package_Init && build_context.command_kind == Command_doc) {
|
||||
// Ignore
|
||||
} else {
|
||||
f->flags |= AstFile_IsLazy;
|
||||
|
||||
+1
-1
@@ -28,9 +28,9 @@ enum AddressingMode : u8 {
|
||||
};
|
||||
|
||||
struct TypeAndValue {
|
||||
Type * type;
|
||||
AddressingMode mode;
|
||||
bool is_lhs; // Debug info
|
||||
Type * type;
|
||||
ExactValue value;
|
||||
};
|
||||
|
||||
|
||||
Vendored
+5
-5
@@ -9,7 +9,7 @@ when ODIN_OS == "freebsd" { foreign import lib "system:SDL2" }
|
||||
|
||||
Keysym :: struct {
|
||||
scancode: Scancode, /**< SDL physical key code - see ::SDL_Scancode for details */
|
||||
sym: KeyCode, /**< SDL virtual key code - see ::SDL_KeyCode for details */
|
||||
sym: Keycode, /**< SDL virtual key code - see ::SDL_Keycode for details */
|
||||
mod: Keymod, /**< current key modifiers */
|
||||
unused: u32,
|
||||
}
|
||||
@@ -19,12 +19,12 @@ Keysym :: struct {
|
||||
foreign lib {
|
||||
GetKeyboardFocus :: proc() -> ^Window ---
|
||||
GetKeyboardState :: proc(numkeys: ^c.int) -> [^]u8 ---
|
||||
GetKeyFromScancode :: proc(scancode: Scancode) -> KeyCode ---
|
||||
GetScancodeFromKey :: proc(key: KeyCode) -> Scancode ---
|
||||
GetKeyFromScancode :: proc(scancode: Scancode) -> Keycode ---
|
||||
GetScancodeFromKey :: proc(key: Keycode) -> Scancode ---
|
||||
GetScancodeName :: proc(scancode: Scancode) -> cstring ---
|
||||
GetScancodeFromName :: proc(name: cstring) -> Scancode ---
|
||||
GetKeyName :: proc(key: KeyCode) -> cstring ---
|
||||
GetKeyFromName :: proc(name: cstring) -> KeyCode ---
|
||||
GetKeyName :: proc(key: Keycode) -> cstring ---
|
||||
GetKeyFromName :: proc(name: cstring) -> Keycode ---
|
||||
StartTextInput :: proc() ---
|
||||
IsTextInputActive :: proc() -> bool ---
|
||||
StopTextInput :: proc() ---
|
||||
|
||||
Vendored
+3
-3
@@ -2,11 +2,11 @@ package sdl2
|
||||
|
||||
|
||||
SCANCODE_MASK :: 1<<30
|
||||
SCANCODE_TO_KEYCODE :: #force_inline proc "c" (X: Scancode) -> KeyCode {
|
||||
return KeyCode(i32(X) | SCANCODE_MASK)
|
||||
SCANCODE_TO_KEYCODE :: #force_inline proc "c" (X: Scancode) -> Keycode {
|
||||
return Keycode(i32(X) | SCANCODE_MASK)
|
||||
}
|
||||
|
||||
KeyCode :: enum i32 {
|
||||
Keycode :: enum i32 {
|
||||
UNKNOWN = 0,
|
||||
|
||||
RETURN = '\r',
|
||||
|
||||
Reference in New Issue
Block a user