aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_expr.cpp
diff options
context:
space:
mode:
authorftphikari <ftphikari@gmail.com>2023-07-25 15:32:18 +0300
committerGitHub <noreply@github.com>2023-07-25 15:32:18 +0300
commit699aec331d44da58bceddfb788bf349995473ad9 (patch)
tree3f5ce42c72c18fff1fc79f0229797be72f0e7638 /src/llvm_backend_expr.cpp
parentd2375a79f29d8377c813484bce3127ae9c205974 (diff)
parent5ac7fe453f5fbf0995c24f0c1c12ed439ae3aee9 (diff)
Merge branch 'odin-lang:master' into master
Diffstat (limited to 'src/llvm_backend_expr.cpp')
-rw-r--r--src/llvm_backend_expr.cpp46
1 files changed, 38 insertions, 8 deletions
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index f95e351ce..5e6831fc2 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -1325,6 +1325,15 @@ handle_op:;
return {};
}
+gb_internal bool lb_is_empty_string_constant(Ast *expr) {
+ if (expr->tav.value.kind == ExactValue_String &&
+ is_type_string(expr->tav.type)) {
+ String s = expr->tav.value.value_string;
+ return s.len == 0;
+ }
+ return false;
+}
+
gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
ast_node(be, BinaryExpr, expr);
@@ -1373,15 +1382,33 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
case Token_CmpEq:
case Token_NotEq:
if (is_type_untyped_nil(be->right->tav.type)) {
+ // `x == nil` or `x != nil`
lbValue left = lb_build_expr(p, be->left);
lbValue cmp = lb_emit_comp_against_nil(p, be->op.kind, left);
Type *type = default_type(tv.type);
return lb_emit_conv(p, cmp, type);
} else if (is_type_untyped_nil(be->left->tav.type)) {
+ // `nil == x` or `nil != x`
lbValue right = lb_build_expr(p, be->right);
lbValue cmp = lb_emit_comp_against_nil(p, be->op.kind, right);
Type *type = default_type(tv.type);
return lb_emit_conv(p, cmp, type);
+ } else if (lb_is_empty_string_constant(be->right)) {
+ // `x == ""` or `x != ""`
+ 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 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);
}
/*fallthrough*/
case Token_Lt:
@@ -2246,7 +2273,6 @@ gb_internal lbValue lb_compare_records(lbProcedure *p, TokenKind op_kind, lbValu
-
gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left, lbValue right) {
Type *a = core_type(left.type);
Type *b = core_type(right.type);
@@ -2254,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);
@@ -2310,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);
@@ -2984,7 +3013,7 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
isize arg_count = 6;
- if (build_context.disallow_rtti) {
+ if (build_context.no_rtti) {
arg_count = 4;
}
@@ -2996,7 +3025,7 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
args[2] = lb_const_int(p->module, t_i32, pos.line);
args[3] = lb_const_int(p->module, t_i32, pos.column);
- if (!build_context.disallow_rtti) {
+ if (!build_context.no_rtti) {
args[4] = lb_typeid(p->module, src_type);
args[5] = lb_typeid(p->module, dst_type);
}
@@ -3012,7 +3041,7 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
}
lbValue data_ptr = lb_emit_struct_ev(p, v, 0);
if ((p->state_flags & StateFlag_no_type_assert) == 0) {
- GB_ASSERT(!build_context.disallow_rtti);
+ GB_ASSERT(!build_context.no_rtti);
lbValue any_id = lb_emit_struct_ev(p, v, 1);
@@ -4142,7 +4171,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
// HACK TODO(bill): THIS IS A MASSIVE HACK!!!!
if (is_type_union(ft) && !are_types_identical(fet, ft) && !is_type_untyped(fet)) {
- GB_ASSERT_MSG(union_variant_index(ft, fet) > 0, "%s", type_to_string(fet));
+ GB_ASSERT_MSG(union_variant_index(ft, fet) >= 0, "%s", type_to_string(fet));
lb_emit_store_union_variant(p, gep, field_expr, fet);
} else {
@@ -4490,8 +4519,9 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
Selection sel = lookup_field(type, selector, false);
GB_ASSERT(sel.entity != nullptr);
if (sel.pseudo_field) {
- GB_ASSERT(sel.entity->kind == Entity_Procedure);
+ GB_ASSERT(sel.entity->kind == Entity_Procedure || sel.entity->kind == Entity_ProcGroup);
Entity *e = entity_of_node(sel_node);
+ GB_ASSERT(e->kind == Entity_Procedure);
return lb_addr(lb_find_value_from_entity(p->module, e));
}