Merge branch 'master' into windows-llvm-11.1.0

This commit is contained in:
gingerBill
2023-07-08 11:43:59 +01:00
9 changed files with 141 additions and 46 deletions

View File

@@ -3,44 +3,110 @@ package math
import "core:intrinsics"
@(default_calling_convention="none")
@(default_calling_convention="none", private="file")
foreign _ {
@(link_name="llvm.sin.f16", require_results)
sin_f16 :: proc(θ: f16) -> f16 ---
_sin_f16 :: proc(θ: f16) -> f16 ---
@(link_name="llvm.sin.f32", require_results)
sin_f32 :: proc(θ: f32) -> f32 ---
_sin_f32 :: proc(θ: f32) -> f32 ---
@(link_name="llvm.sin.f64", require_results)
sin_f64 :: proc(θ: f64) -> f64 ---
_sin_f64 :: proc(θ: f64) -> f64 ---
@(link_name="llvm.cos.f16", require_results)
cos_f16 :: proc(θ: f16) -> f16 ---
_cos_f16 :: proc(θ: f16) -> f16 ---
@(link_name="llvm.cos.f32", require_results)
cos_f32 :: proc(θ: f32) -> f32 ---
_cos_f32 :: proc(θ: f32) -> f32 ---
@(link_name="llvm.cos.f64", require_results)
cos_f64 :: proc(θ: f64) -> f64 ---
_cos_f64 :: proc(θ: f64) -> f64 ---
@(link_name="llvm.pow.f16", require_results)
pow_f16 :: proc(x, power: f16) -> f16 ---
_pow_f16 :: proc(x, power: f16) -> f16 ---
@(link_name="llvm.pow.f32", require_results)
pow_f32 :: proc(x, power: f32) -> f32 ---
_pow_f32 :: proc(x, power: f32) -> f32 ---
@(link_name="llvm.pow.f64", require_results)
pow_f64 :: proc(x, power: f64) -> f64 ---
_pow_f64 :: proc(x, power: f64) -> f64 ---
@(link_name="llvm.fmuladd.f16", require_results)
fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---
_fmuladd_f16 :: proc(a, b, c: f16) -> f16 ---
@(link_name="llvm.fmuladd.f32", require_results)
fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---
_fmuladd_f32 :: proc(a, b, c: f32) -> f32 ---
@(link_name="llvm.fmuladd.f64", require_results)
fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
_fmuladd_f64 :: proc(a, b, c: f64) -> f64 ---
@(link_name="llvm.exp.f16", require_results)
exp_f16 :: proc(x: f16) -> f16 ---
_exp_f16 :: proc(x: f16) -> f16 ---
@(link_name="llvm.exp.f32", require_results)
exp_f32 :: proc(x: f32) -> f32 ---
_exp_f32 :: proc(x: f32) -> f32 ---
@(link_name="llvm.exp.f64", require_results)
exp_f64 :: proc(x: f64) -> f64 ---
_exp_f64 :: proc(x: f64) -> f64 ---
}
@(require_results)
sin_f16 :: proc "contextless" (θ: f16) -> f16 {
return _sin_f16(θ)
}
@(require_results)
sin_f32 :: proc "contextless" (θ: f32) -> f32 {
return _sin_f32(θ)
}
@(require_results)
sin_f64 :: proc "contextless" (θ: f64) -> f64 {
return _sin_f64(θ)
}
@(require_results)
cos_f16 :: proc "contextless" (θ: f16) -> f16 {
return _cos_f16(θ)
}
@(require_results)
cos_f32 :: proc "contextless" (θ: f32) -> f32 {
return _cos_f32(θ)
}
@(require_results)
cos_f64 :: proc "contextless" (θ: f64) -> f64 {
return _cos_f64(θ)
}
@(require_results)
pow_f16 :: proc "contextless" (x, power: f16) -> f16 {
return _pow_f16(x, power)
}
@(require_results)
pow_f32 :: proc "contextless" (x, power: f32) -> f32 {
return _pow_f32(x, power)
}
@(require_results)
pow_f64 :: proc "contextless" (x, power: f64) -> f64 {
return _pow_f64(x, power)
}
@(require_results)
fmuladd_f16 :: proc "contextless" (a, b, c: f16) -> f16 {
return _fmuladd_f16(a, b, c)
}
@(require_results)
fmuladd_f32 :: proc "contextless" (a, b, c: f32) -> f32 {
return _fmuladd_f32(a, b, c)
}
@(require_results)
fmuladd_f64 :: proc "contextless" (a, b, c: f64) -> f64 {
return _fmuladd_f64(a, b, c)
}
@(require_results)
exp_f16 :: proc "contextless" (x: f16) -> f16 {
return _exp_f16(x)
}
@(require_results)
exp_f32 :: proc "contextless" (x: f32) -> f32 {
return _exp_f32(x)
}
@(require_results)
exp_f64 :: proc "contextless" (x: f64) -> f64 {
return _exp_f64(x)
}
@(require_results)
sqrt_f16 :: proc "contextless" (x: f16) -> f16 {
return intrinsics.sqrt(x)

View File

@@ -664,6 +664,11 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
if (check_representable_as_constant(c, operand->value, dst, nullptr)) {
if (is_type_typed(dst) && src->kind == Type_Basic) {
switch (src->Basic.kind) {
case Basic_UntypedBool:
if (is_type_boolean(dst)) {
return 1;
}
break;
case Basic_UntypedRune:
if (is_type_integer(dst) || is_type_rune(dst)) {
return 1;
@@ -704,46 +709,55 @@ gb_internal i64 check_distance_between_types(CheckerContext *c, Operand *operand
return -1;
}
if (src->kind == Type_Basic) {
Type *d = base_array_type(dst);
i64 score = -1;
switch (src->Basic.kind) {
case Basic_UntypedBool:
if (is_type_boolean(d)) {
score = 1;
}
break;
case Basic_UntypedRune:
if (is_type_integer(dst) || is_type_rune(dst)) {
if (is_type_integer(d) || is_type_rune(d)) {
score = 1;
}
break;
case Basic_UntypedInteger:
if (is_type_integer(dst) || is_type_rune(dst)) {
if (is_type_integer(d) || is_type_rune(d)) {
score = 1;
}
break;
case Basic_UntypedString:
if (is_type_string(dst)) {
if (is_type_string(d)) {
score = 1;
}
break;
case Basic_UntypedFloat:
if (is_type_float(dst)) {
if (is_type_float(d)) {
score = 1;
}
break;
case Basic_UntypedComplex:
if (is_type_complex(dst)) {
if (is_type_complex(d)) {
score = 1;
}
if (is_type_quaternion(dst)) {
if (is_type_quaternion(d)) {
score = 2;
}
break;
case Basic_UntypedQuaternion:
if (is_type_quaternion(dst)) {
if (is_type_quaternion(d)) {
score = 1;
}
break;
}
if (score > 0) {
if (is_type_typed(dst)) {
if (is_type_typed(d)) {
score += 1;
}
if (d != dst) {
score += 6;
}
}
return score;
}
@@ -1705,7 +1719,7 @@ gb_internal bool check_unary_op(CheckerContext *c, Operand *o, Token op) {
break;
case Token_Not:
if (!is_type_boolean(type)) {
if (!is_type_boolean(type) || is_type_array_like(o->type)) {
ERROR_BLOCK();
str = expr_to_string(o->expr);
error(op, "Operator '%.*s' is only allowed on boolean expressions", LIT(op.string));
@@ -4760,7 +4774,10 @@ gb_internal Entity *check_selector(CheckerContext *c, Operand *operand, Ast *nod
if (entity == nullptr && selector->kind == Ast_Ident) {
String field_name = selector->Ident.token.string;
if (is_type_dynamic_array(type_deref(operand->type))) {
Type *t = type_deref(operand->type);
if (t == nullptr) {
error(operand->expr, "Cannot use a selector expression on 0-value expression");
} else if (is_type_dynamic_array(t)) {
init_mem_allocator(c->checker);
}
sel = lookup_field(operand->type, field_name, operand->mode == Addressing_Type);

View File

@@ -285,17 +285,6 @@ gb_internal Scope *create_scope_from_package(CheckerContext *c, AstPackage *pkg)
}
gb_internal void destroy_scope(Scope *scope) {
for (auto const &entry : scope->elements) {
Entity *e = entry.value;
if (e->kind == Entity_Variable) {
if (!(e->flags & EntityFlag_Used)) {
#if 0
warning(e->token, "Unused variable '%.*s'", LIT(e->token.string));
#endif
}
}
}
for (Scope *child = scope->head_child; child != nullptr; child = child->next) {
destroy_scope(child);
}

View File

@@ -346,6 +346,8 @@ struct lbProcedure {
};
#define ABI_PKG_NAME_SEPARATOR "."
#if !ODIN_LLVM_MINIMUM_VERSION_14
#define LLVMConstGEP2(Ty__, ConstantVal__, ConstantIndices__, NumIndices__) LLVMConstGEP(ConstantVal__, ConstantIndices__, NumIndices__)

View File

@@ -483,7 +483,10 @@ gb_internal lbValue lb_const_value(lbModule *m, Type *type, ExactValue value, bo
GB_ASSERT(res.value != nullptr);
GB_ASSERT(LLVMGetValueKind(res.value) == LLVMFunctionValueKind);
res.value = LLVMConstPointerCast(res.value, lb_type(m, res.type));
if (LLVMGetIntrinsicID(res.value) == 0) {
// NOTE(bill): do not cast intrinsics as they are not really procedures that can be casted
res.value = LLVMConstPointerCast(res.value, lb_type(m, res.type));
}
return res;
}

View File

@@ -1395,13 +1395,17 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
return lb_emit_conv(p, cmp, type);
} else if (lb_is_empty_string_constant(be->right)) {
// `x == ""` or `x != ""`
lbValue len = lb_string_len(p, lb_build_expr(p, be->left));
lbValue s = lb_build_expr(p, be->left);
s = lb_emit_conv(p, s, t_string);
lbValue len = lb_string_len(p, s);
lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0));
Type *type = default_type(tv.type);
return lb_emit_conv(p, cmp, type);
} else if (lb_is_empty_string_constant(be->left)) {
// `"" == x` or `"" != x`
lbValue len = lb_string_len(p, lb_build_expr(p, be->right));
lbValue s = lb_build_expr(p, be->right);
s = lb_emit_conv(p, s, t_string);
lbValue len = lb_string_len(p, s);
lbValue cmp = lb_emit_comp(p, be->op.kind, len, lb_const_int(p->module, t_int, 0));
Type *type = default_type(tv.type);
return lb_emit_conv(p, cmp, type);
@@ -2276,7 +2280,10 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
GB_ASSERT(gb_is_between(op_kind, Token__ComparisonBegin+1, Token__ComparisonEnd-1));
lbValue nil_check = {};
if (is_type_untyped_nil(left.type)) {
if (is_type_array_like(left.type) || is_type_array_like(right.type)) {
// don't do `nil` check if it is array-like
} else if (is_type_untyped_nil(left.type)) {
nil_check = lb_emit_comp_against_nil(p, op_kind, right);
} else if (is_type_untyped_nil(right.type)) {
nil_check = lb_emit_comp_against_nil(p, op_kind, left);
@@ -2332,7 +2339,7 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
lbValue res = lb_emit_comp(p, op_kind, val, lb_const_nil(p->module, val.type));
return lb_emit_conv(p, res, t_bool);
}
if (is_type_array(a) || is_type_enumerated_array(a)) {
if (is_type_array_like(a)) {
Type *tl = base_type(a);
lbValue lhs = lb_address_from_load_or_generate_local(p, left);
lbValue rhs = lb_address_from_load_or_generate_local(p, right);

View File

@@ -1403,7 +1403,7 @@ gb_internal String lb_mangle_name(lbModule *m, Entity *e) {
char *new_name = gb_alloc_array(permanent_allocator(), char, max_len);
isize new_name_len = gb_snprintf(
new_name, max_len,
"%.*s.%.*s", LIT(pkgn), LIT(name)
"%.*s" ABI_PKG_NAME_SEPARATOR "%.*s", LIT(pkgn), LIT(name)
);
if (require_suffix_id) {
char *str = new_name + new_name_len-1;
@@ -1453,7 +1453,7 @@ gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedur
isize name_len = p->name.len + 1 + ts_name.len + 1 + 10 + 1;
char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
u32 guid = 1+p->module->nested_type_name_guid.fetch_add(1);
name_len = gb_snprintf(name_text, name_len, "%.*s.%.*s-%u", LIT(p->name), LIT(ts_name), guid);
name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(p->name), LIT(ts_name), guid);
String name = make_string(cast(u8 *)name_text, name_len-1);
e->TypeName.ir_mangled_name = name;
@@ -1463,7 +1463,7 @@ gb_internal String lb_set_nested_type_name_ir_mangled_name(Entity *e, lbProcedur
isize name_len = 9 + 1 + ts_name.len + 1 + 10 + 1;
char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
static std::atomic<u32> guid;
name_len = gb_snprintf(name_text, name_len, "_internal.%.*s-%u", LIT(ts_name), 1+guid.fetch_add(1));
name_len = gb_snprintf(name_text, name_len, "_internal" ABI_PKG_NAME_SEPARATOR "%.*s-%u", LIT(ts_name), 1+guid.fetch_add(1));
String name = make_string(cast(u8 *)name_text, name_len-1);
e->TypeName.ir_mangled_name = name;
@@ -2730,7 +2730,10 @@ gb_internal lbValue lb_find_procedure_value_from_entity(lbModule *m, Entity *e)
} else {
array_add(&m->missing_procedures_to_check, missing_proc);
}
rw_mutex_shared_lock(&m->values_mutex);
found = map_get(&m->values, e);
rw_mutex_shared_unlock(&m->values_mutex);
if (found) {
return *found;
}

View File

@@ -757,7 +757,7 @@ gb_internal void lb_build_nested_proc(lbProcedure *p, AstProcLit *pd, Entity *e)
char *name_text = gb_alloc_array(permanent_allocator(), char, name_len);
i32 guid = cast(i32)p->children.count;
name_len = gb_snprintf(name_text, name_len, "%.*s.%.*s-%d", LIT(p->name), LIT(pd_name), guid);
name_len = gb_snprintf(name_text, name_len, "%.*s" ABI_PKG_NAME_SEPARATOR "%.*s-%d", LIT(p->name), LIT(pd_name), guid);
String name = make_string(cast(u8 *)name_text, name_len-1);
e->Procedure.link_name = name;

View File

@@ -1878,7 +1878,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
} else if (return_count == 1) {
Entity *e = tuple->variables[0];
if (res_count == 0) {
rw_mutex_shared_lock(&p->module->values_mutex);
lbValue found = map_must_get(&p->module->values, e);
rw_mutex_shared_unlock(&p->module->values_mutex);
res = lb_emit_load(p, found);
} else {
res = lb_build_expr(p, return_results[0]);
@@ -1887,7 +1889,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
if (p->type->Proc.has_named_results) {
// NOTE(bill): store the named values before returning
if (e->token.string != "") {
rw_mutex_shared_lock(&p->module->values_mutex);
lbValue found = map_must_get(&p->module->values, e);
rw_mutex_shared_unlock(&p->module->values_mutex);
lb_emit_store(p, found, lb_emit_conv(p, res, e->type));
}
}
@@ -1903,7 +1907,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
} else {
for (isize res_index = 0; res_index < return_count; res_index++) {
Entity *e = tuple->variables[res_index];
rw_mutex_shared_lock(&p->module->values_mutex);
lbValue found = map_must_get(&p->module->values, e);
rw_mutex_shared_unlock(&p->module->values_mutex);
lbValue res = lb_emit_load(p, found);
array_add(&results, res);
}
@@ -1925,7 +1931,9 @@ gb_internal void lb_build_return_stmt(lbProcedure *p, Slice<Ast *> const &return
if (e->token.string == "") {
continue;
}
rw_mutex_shared_lock(&p->module->values_mutex);
named_results[i] = map_must_get(&p->module->values, e);
rw_mutex_shared_unlock(&p->module->values_mutex);
values[i] = lb_emit_conv(p, results[i], e->type);
}