aboutsummaryrefslogtreecommitdiff
path: root/src/llvm_backend_expr.cpp
diff options
context:
space:
mode:
authorColin Davidson <colrdavidson@gmail.com>2025-04-26 18:22:21 -0700
committerColin Davidson <colrdavidson@gmail.com>2025-04-26 18:22:21 -0700
commitf1fdd1a8b9a53d34b59f8bac86ebba5f35189f28 (patch)
tree5d8e0f200c25ae3451f666e7292f9cc9ad3db743 /src/llvm_backend_expr.cpp
parent78d8ed2d391e8def6b303445c82f7d143897c251 (diff)
parent7d4c3d23e6156c1b4be1f91e6d18e51a8e9814f0 (diff)
Merge branch 'master' into macharena
Diffstat (limited to 'src/llvm_backend_expr.cpp')
-rw-r--r--src/llvm_backend_expr.cpp114
1 files changed, 81 insertions, 33 deletions
diff --git a/src/llvm_backend_expr.cpp b/src/llvm_backend_expr.cpp
index 80c469ae6..c5ea0ddac 100644
--- a/src/llvm_backend_expr.cpp
+++ b/src/llvm_backend_expr.cpp
@@ -222,6 +222,7 @@ gb_internal lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x,
return lb_emit_byte_swap(p, res, type);
}
+ Type* bt = base_type(type);
lbValue res = {};
switch (op) {
@@ -233,6 +234,8 @@ gb_internal lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x,
case Token_Sub: // Number negation
if (is_type_integer(x.type)) {
res.value = LLVMBuildNeg(p->builder, x.value, "");
+ } else if (bt->kind == Type_Enum && is_type_integer(bt->Enum.base_type)) {
+ res.value = LLVMBuildNeg(p->builder, x.value, "");
} else if (is_type_float(x.type)) {
res.value = LLVMBuildFNeg(p->builder, x.value, "");
} else if (is_type_complex(x.type)) {
@@ -1554,7 +1557,7 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
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)) {
+ } else if (lb_is_empty_string_constant(be->right) && !is_type_union(be->left->tav.type)) {
// `x == ""` or `x != ""`
lbValue s = lb_build_expr(p, be->left);
s = lb_emit_conv(p, s, t_string);
@@ -1562,7 +1565,7 @@ gb_internal lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
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)) {
+ } else if (lb_is_empty_string_constant(be->left) && !is_type_union(be->right->tav.type)) {
// `"" == x` or `"" != x`
lbValue s = lb_build_expr(p, be->right);
s = lb_emit_conv(p, s, t_string);
@@ -2145,6 +2148,12 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
}
}
for (Type *vt : dst->Union.variants) {
+ if (src_type == t_llvm_bool && is_type_boolean(vt)) {
+ value = lb_emit_conv(p, value, vt);
+ lbAddr parent = lb_add_local_generated(p, t, true);
+ lb_emit_store_union_variant(p, parent.addr, value, vt);
+ return lb_addr_load(p, parent);
+ }
if (are_types_identical(src_type, vt)) {
lbAddr parent = lb_add_local_generated(p, t, true);
lb_emit_store_union_variant(p, parent.addr, value, vt);
@@ -2312,9 +2321,9 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
lbValue array_const_value = {};
array_const_value.type = t;
array_const_value.value = LLVMConstArray(lb_type(m, elem), values, cast(unsigned)index_count);
- v = lb_add_global_generated(m, t, array_const_value);
+ v = lb_add_global_generated_from_procedure(p, t, array_const_value);
} else {
- v = lb_add_global_generated(m, t);
+ v = lb_add_global_generated_from_procedure(p, t);
}
lb_make_global_private_const(v);
@@ -2346,7 +2355,7 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
Type *elem = base_array_type(dst);
lbValue e = lb_emit_conv(p, value, elem);
lbAddr v = lb_add_local_generated(p, t, false);
- lbValue zero = lb_const_value(p->module, elem, exact_value_i64(0), true);
+ lbValue zero = lb_const_value(p->module, elem, exact_value_i64(0), LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL);
for (i64 j = 0; j < dst->Matrix.column_count; j++) {
for (i64 i = 0; i < dst->Matrix.row_count; i++) {
lbValue ptr = lb_emit_matrix_epi(p, v.addr, i, j);
@@ -2383,7 +2392,7 @@ gb_internal lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
lb_emit_store(p, d, s);
} else if (i == j) {
lbValue d = lb_emit_matrix_epi(p, v.addr, i, j);
- lbValue s = lb_const_value(p->module, dst->Matrix.elem, exact_value_i64(1), true);
+ lbValue s = lb_const_value(p->module, dst->Matrix.elem, exact_value_i64(1), LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL);
lb_emit_store(p, d, s);
}
}
@@ -2817,6 +2826,12 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
Type *it = bit_set_to_int(a);
lbValue lhs = lb_emit_transmute(p, left, it);
lbValue rhs = lb_emit_transmute(p, right, it);
+ if (is_type_different_to_arch_endianness(it)) {
+ it = integer_endian_type_to_platform_type(it);
+ lhs = lb_emit_byte_swap(p, lhs, it);
+ rhs = lb_emit_byte_swap(p, rhs, it);
+ }
+
lbValue res = lb_emit_arith(p, Token_And, lhs, rhs, it);
if (op_kind == Token_Lt || op_kind == Token_LtEq) {
@@ -2914,6 +2929,12 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
}
}
+ if (is_type_different_to_arch_endianness(left.type)) {
+ Type *pt = integer_endian_type_to_platform_type(left.type);
+ lhs = lb_emit_byte_swap(p, {lhs, pt}, pt).value;
+ rhs = lb_emit_byte_swap(p, {rhs, pt}, pt).value;
+ }
+
res.value = LLVMBuildICmp(p->builder, pred, lhs, rhs, "");
} else if (is_type_float(a)) {
LLVMRealPredicate pred = {};
@@ -2925,6 +2946,13 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
case Token_LtEq: pred = LLVMRealOLE; break;
case Token_NotEq: pred = LLVMRealONE; break;
}
+
+ if (is_type_different_to_arch_endianness(left.type)) {
+ Type *pt = integer_endian_type_to_platform_type(left.type);
+ left = lb_emit_byte_swap(p, left, pt);
+ right = lb_emit_byte_swap(p, right, pt);
+ }
+
res.value = LLVMBuildFCmp(p->builder, pred, left.value, right.value, "");
} else if (is_type_typeid(a)) {
LLVMIntPredicate pred = {};
@@ -2985,7 +3013,16 @@ gb_internal lbValue lb_emit_comp(lbProcedure *p, TokenKind op_kind, lbValue left
LLVMTypeRef mask_int_type = LLVMIntTypeInContext(p->module->ctx, cast(unsigned)(8*type_size_of(a)));
LLVMValueRef mask_int = LLVMBuildBitCast(p->builder, mask, mask_int_type, "");
- res.value = LLVMBuildICmp(p->builder, LLVMIntNE, mask_int, LLVMConstNull(LLVMTypeOf(mask_int)), "");
+
+ switch (op_kind) {
+ case Token_CmpEq:
+ res.value = LLVMBuildICmp(p->builder, LLVMIntEQ, mask_int, LLVMConstInt(mask_int_type, U64_MAX, true), "");
+ break;
+ case Token_NotEq:
+ res.value = LLVMBuildICmp(p->builder, LLVMIntNE, mask_int, LLVMConstNull(mask_int_type), "");
+ break;
+ }
+
return res;
} else {
@@ -3236,7 +3273,7 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
Type *type = v.type;
lbAddr addr = {};
if (p->is_startup) {
- addr = lb_add_global_generated(p->module, type, v);
+ addr = lb_add_global_generated_from_procedure(p, type, v);
} else {
addr = lb_add_local_generated(p, type, false);
}
@@ -3345,9 +3382,7 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
auto args = array_make<lbValue>(permanent_allocator(), arg_count);
args[0] = ok;
- args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
- args[2] = lb_const_int(p->module, t_i32, pos.line);
- args[3] = lb_const_int(p->module, t_i32, pos.column);
+ lb_set_file_line_col(p, array_slice(args, 1, args.count), pos);
if (!build_context.no_rtti) {
args[4] = lb_typeid(p->module, src_type);
@@ -3374,9 +3409,7 @@ gb_internal lbValue lb_build_unary_and(lbProcedure *p, Ast *expr) {
auto args = array_make<lbValue>(permanent_allocator(), 6);
args[0] = ok;
- args[1] = lb_find_or_add_entity_string(p->module, get_file_path_string(pos.file_id));
- args[2] = lb_const_int(p->module, t_i32, pos.line);
- args[3] = lb_const_int(p->module, t_i32, pos.column);
+ lb_set_file_line_col(p, array_slice(args, 1, args.count), pos);
args[4] = any_id;
args[5] = id;
@@ -3463,7 +3496,7 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
if (tv.value.kind != ExactValue_Invalid) {
// NOTE(bill): Short on constant values
- return lb_const_value(p->module, type, tv.value);
+ return lb_const_value(p->module, type, tv.value, LB_CONST_CONTEXT_DEFAULT_ALLOW_LOCAL);
} else if (tv.mode == Addressing_Type) {
// NOTE(bill, 2023-01-16): is this correct? I hope so at least
return lb_typeid(m, tv.type);
@@ -3483,7 +3516,13 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
case_ast_node(bd, BasicDirective, expr);
TokenPos pos = bd->token.pos;
- GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(bd->name.string));
+ String name = bd->name.string;
+ if (name == "branch_location") {
+ GB_ASSERT(p->uses_branch_location);
+ String proc_name = p->entity->token.string;
+ return lb_emit_source_code_location_as_global(p, proc_name, p->branch_location_pos);
+ }
+ GB_PANIC("Non-constant basic literal %s - %.*s", token_pos_to_string(pos), LIT(name));
case_end;
case_ast_node(i, Implicit, expr);
@@ -3649,7 +3688,7 @@ gb_internal lbValue lb_build_expr_internal(lbProcedure *p, Ast *expr) {
lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
lb_start_block(p, else_);
- lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
+ lb_emit_defer_stmts(p, lbDeferExit_Branch, block, expr);
lb_emit_jump(p, block);
lb_start_block(p, then);
@@ -3821,7 +3860,7 @@ gb_internal lbAddr lb_build_addr_from_entity(lbProcedure *p, Entity *e, Ast *exp
Type *t = default_type(type_of_expr(expr));
lbValue v = lb_const_value(p->module, t, e->Constant.value);
if (LLVMIsConstant(v.value)) {
- lbAddr g = lb_add_global_generated(p->module, t, v);
+ lbAddr g = lb_add_global_generated_from_procedure(p, t, v);
return g;
}
GB_ASSERT(LLVMIsALoadInst(v.value));
@@ -4269,6 +4308,17 @@ gb_internal lbAddr lb_build_addr_index_expr(lbProcedure *p, Ast *expr) {
gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) {
ast_node(se, SliceExpr, expr);
+ lbAddr addr = lb_build_addr(p, se->expr);
+ lbValue base = lb_addr_load(p, addr);
+ Type *type = base_type(base.type);
+
+ if (is_type_pointer(type)) {
+ type = base_type(type_deref(type));
+ addr = lb_addr(base);
+ base = lb_addr_load(p, addr);
+ }
+
+
lbValue low = lb_const_int(p->module, t_int, 0);
lbValue high = {};
@@ -4281,16 +4331,6 @@ gb_internal lbAddr lb_build_addr_slice_expr(lbProcedure *p, Ast *expr) {
bool no_indices = se->low == nullptr && se->high == nullptr;
- lbAddr addr = lb_build_addr(p, se->expr);
- lbValue base = lb_addr_load(p, addr);
- Type *type = base_type(base.type);
-
- if (is_type_pointer(type)) {
- type = base_type(type_deref(type));
- addr = lb_addr(base);
- base = lb_addr_load(p, addr);
- }
-
switch (type->kind) {
case Type_Slice: {
Type *slice_type = type;
@@ -4574,7 +4614,11 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
auto const &f = fields[i];
LLVMValueRef mask = LLVMConstInt(lit, 1, false);
- mask = LLVMConstShl(mask, LLVMConstInt(lit, f.bit_size, false));
+ #if LLVM_VERSION_MAJOR >= 19
+ mask = LLVMBuildShl(p->builder, mask, LLVMConstInt(lit, f.bit_size, false), "");
+ #else
+ mask = LLVMConstShl(mask, LLVMConstInt(lit, f.bit_size, false));
+ #endif
mask = LLVMConstSub(mask, LLVMConstInt(lit, 1, false));
LLVMValueRef elem = values[i].value;
@@ -4622,7 +4666,11 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
bits_to_set -= mask_width;
LLVMValueRef mask = LLVMConstInt(vt, 1, false);
- mask = LLVMConstShl(mask, LLVMConstInt(vt, mask_width, false));
+ #if LLVM_VERSION_MAJOR >= 19
+ mask = LLVMBuildShl(p->builder, mask, LLVMConstInt(vt, mask_width, false), "");
+ #else
+ mask = LLVMConstShl(mask, LLVMConstInt(vt, mask_width, false));
+ #endif
mask = LLVMConstSub(mask, LLVMConstInt(vt, 1, false));
LLVMValueRef to_set = LLVMBuildAnd(p->builder, val, mask, "");
@@ -4780,7 +4828,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (cl->elems.count == 0) {
break;
}
- GB_ASSERT(!build_context.no_dynamic_literals);
+ GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals);
lbValue err = lb_dynamic_map_reserve(p, v.addr, 2*cl->elems.count, pos);
gb_unused(err);
@@ -4869,7 +4917,7 @@ gb_internal lbAddr lb_build_addr_compound_lit(lbProcedure *p, Ast *expr) {
if (cl->elems.count == 0) {
break;
}
- GB_ASSERT(!build_context.no_dynamic_literals);
+ GB_ASSERT(expr->file()->feature_flags & OptInFeatureFlag_DynamicLiterals);
Type *et = bt->DynamicArray.elem;
lbValue size = lb_const_int(p->module, t_int, type_size_of(et));
@@ -5466,7 +5514,7 @@ gb_internal lbAddr lb_build_addr_internal(lbProcedure *p, Ast *expr) {
lb_emit_if(p, lb_emit_try_has_value(p, rhs), then, else_);
lb_start_block(p, else_);
- lb_emit_defer_stmts(p, lbDeferExit_Branch, block);
+ lb_emit_defer_stmts(p, lbDeferExit_Branch, block, expr);
lb_emit_jump(p, block);
lb_start_block(p, then);