mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-13 23:01:24 -07:00
General functionality without context
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
package demo
|
||||
|
||||
import "core:os"
|
||||
import "core:fmt"
|
||||
|
||||
main :: proc() {
|
||||
os.write_string(os.stdout, "Hellope\n");
|
||||
fmt.fprintln(os.stdout, "Hellope!", 123, true, 1.3);
|
||||
}
|
||||
|
||||
// BarBar :: struct {x, y: int};
|
||||
|
||||
|
||||
+205
-22
@@ -1196,13 +1196,17 @@ lbValue lb_add_param(lbProcedure *p, Entity *e, Ast *expr, Type *abi_type, i32 i
|
||||
return {};
|
||||
}
|
||||
|
||||
|
||||
void lb_start_block(lbProcedure *p, lbBlock *b) {
|
||||
GB_ASSERT(b != nullptr);
|
||||
p->curr_block = b;
|
||||
if (!b->appended) {
|
||||
b->appended = true;
|
||||
LLVMAppendExistingBasicBlock(p->value, b->block);
|
||||
}
|
||||
LLVMPositionBuilderAtEnd(p->builder, b->block);
|
||||
p->curr_block = b;
|
||||
}
|
||||
|
||||
|
||||
void lb_begin_procedure_body(lbProcedure *p) {
|
||||
DeclInfo *decl = decl_info_of_entity(p->entity);
|
||||
if (decl != nullptr) {
|
||||
@@ -1215,8 +1219,8 @@ void lb_begin_procedure_body(lbProcedure *p) {
|
||||
|
||||
p->builder = LLVMCreateBuilder();
|
||||
|
||||
p->decl_block = lb_create_block(p, "decls");
|
||||
p->entry_block = lb_create_block(p, "entry");
|
||||
p->decl_block = lb_create_block(p, "decls", true);
|
||||
p->entry_block = lb_create_block(p, "entry", true);
|
||||
lb_start_block(p, p->entry_block);
|
||||
|
||||
GB_ASSERT(p->type != nullptr);
|
||||
@@ -1391,9 +1395,15 @@ void lb_add_edge(lbBlock *from, lbBlock *to) {
|
||||
}
|
||||
|
||||
|
||||
lbBlock *lb_create_block(lbProcedure *p, char const *name) {
|
||||
lbBlock *lb_create_block(lbProcedure *p, char const *name, bool append) {
|
||||
lbBlock *b = gb_alloc_item(heap_allocator(), lbBlock);
|
||||
b->block = LLVMAppendBasicBlockInContext(p->module->ctx, p->value, name);
|
||||
b->block = LLVMCreateBasicBlockInContext(p->module->ctx, name);
|
||||
b->appended = false;
|
||||
if (append) {
|
||||
b->appended = true;
|
||||
LLVMAppendExistingBasicBlock(p->value, b->block);
|
||||
}
|
||||
|
||||
b->scope = p->curr_scope;
|
||||
b->scope_index = p->scope_index;
|
||||
|
||||
@@ -1431,7 +1441,10 @@ void lb_emit_if(lbProcedure *p, lbValue cond, lbBlock *true_block, lbBlock *fals
|
||||
|
||||
lb_add_edge(b, true_block);
|
||||
lb_add_edge(b, false_block);
|
||||
LLVMBuildCondBr(p->builder, cond.value, true_block->block, false_block->block);
|
||||
|
||||
LLVMValueRef cv = cond.value;
|
||||
cv = LLVMBuildTruncOrBitCast(p->builder, cv, lb_type(p->module, t_llvm_bool), "");
|
||||
LLVMBuildCondBr(p->builder, cv, true_block->block, false_block->block);
|
||||
}
|
||||
|
||||
lbValue lb_build_cond(lbProcedure *p, Ast *cond, lbBlock *true_block, lbBlock *false_block) {
|
||||
@@ -2689,8 +2702,9 @@ lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast
|
||||
|
||||
lb_start_block(p, rhs);
|
||||
lbValue edge = lb_build_expr(p, right);
|
||||
|
||||
incoming_values[done->preds.count] = edge.value;
|
||||
incoming_blocks[done->preds.count] = rhs->block;
|
||||
incoming_blocks[done->preds.count] = p->curr_block->block;
|
||||
|
||||
lb_emit_jump(p, done);
|
||||
lb_start_block(p, done);
|
||||
@@ -2698,10 +2712,10 @@ lbValue lb_emit_logical_binary_expr(lbProcedure *p, TokenKind op, Ast *left, Ast
|
||||
lbValue res = {};
|
||||
res.type = type;
|
||||
res.value = LLVMBuildPhi(p->builder, lb_type(m, type), "");
|
||||
|
||||
GB_ASSERT(incoming_values.count == incoming_blocks.count);
|
||||
LLVMAddIncoming(res.value, incoming_values.data, incoming_blocks.data, cast(unsigned)incoming_values.count);
|
||||
|
||||
return res;
|
||||
return short_circuit;
|
||||
}
|
||||
|
||||
|
||||
@@ -4031,11 +4045,8 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type)
|
||||
|
||||
switch (op) {
|
||||
case Token_Not: // Boolean not
|
||||
res.value = LLVMBuildNot(p->builder, x.value, "");
|
||||
res.type = x.type;
|
||||
return res;
|
||||
case Token_Xor: // Bitwise not
|
||||
res.value = LLVMBuildXor(p->builder, x.value, LLVMConstAllOnes(lb_type(p->module, x.type)), "");
|
||||
res.value = LLVMBuildNot(p->builder, x.value, "");
|
||||
res.type = x.type;
|
||||
return res;
|
||||
case Token_Sub: // Number negation
|
||||
@@ -4058,14 +4069,172 @@ lbValue lb_emit_unary_arith(lbProcedure *p, TokenKind op, lbValue x, Type *type)
|
||||
lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type) {
|
||||
lbModule *m = p->module;
|
||||
|
||||
if (is_type_array(lhs.type) || is_type_array(rhs.type)) {
|
||||
lhs = lb_emit_conv(p, lhs, type);
|
||||
rhs = lb_emit_conv(p, rhs, type);
|
||||
|
||||
lbValue x = lb_address_from_load_or_generate_local(p, lhs);
|
||||
lbValue y = lb_address_from_load_or_generate_local(p, rhs);
|
||||
|
||||
GB_ASSERT(is_type_array(type));
|
||||
Type *elem_type = base_array_type(type);
|
||||
|
||||
lbAddr res = lb_add_local_generated(p, type, false);
|
||||
|
||||
i64 count = base_type(type)->Array.count;
|
||||
|
||||
bool inline_array_arith = type_size_of(type) <= build_context.max_align;
|
||||
|
||||
if (inline_array_arith) {
|
||||
for (i64 i = 0; i < count; i++) {
|
||||
lbValue a = lb_emit_load(p, lb_emit_array_epi(p, x, i));
|
||||
lbValue b = lb_emit_load(p, lb_emit_array_epi(p, y, i));
|
||||
lbValue c = lb_emit_arith(p, op, a, b, elem_type);
|
||||
lb_emit_store(p, lb_emit_array_epi(p, res.addr, i), c);
|
||||
}
|
||||
} else {
|
||||
auto loop_data = lb_loop_start(p, count);
|
||||
|
||||
lbValue a = lb_emit_load(p, lb_emit_array_ep(p, x, loop_data.idx));
|
||||
lbValue b = lb_emit_load(p, lb_emit_array_ep(p, y, loop_data.idx));
|
||||
lbValue c = lb_emit_arith(p, op, a, b, elem_type);
|
||||
lb_emit_store(p, lb_emit_array_ep(p, res.addr, loop_data.idx), c);
|
||||
|
||||
lb_loop_end(p, loop_data);
|
||||
}
|
||||
|
||||
return lb_addr_load(p, res);
|
||||
} else if (is_type_complex(type)) {
|
||||
lhs = lb_emit_conv(p, lhs, type);
|
||||
rhs = lb_emit_conv(p, rhs, type);
|
||||
|
||||
Type *ft = base_complex_elem_type(type);
|
||||
|
||||
if (op == Token_Quo) {
|
||||
auto args = array_make<lbValue>(heap_allocator(), 2);
|
||||
args[0] = lhs;
|
||||
args[1] = rhs;
|
||||
|
||||
switch (type_size_of(ft)) {
|
||||
case 4: return lb_emit_runtime_call(p, "quo_complex64", args);
|
||||
case 8: return lb_emit_runtime_call(p, "quo_complex128", args);
|
||||
default: GB_PANIC("Unknown float type"); break;
|
||||
}
|
||||
}
|
||||
|
||||
lbAddr res = lb_add_local_generated(p, type, false); // NOTE: initialized in full later
|
||||
lbValue a = lb_emit_struct_ev(p, lhs, 0);
|
||||
lbValue b = lb_emit_struct_ev(p, lhs, 1);
|
||||
lbValue c = lb_emit_struct_ev(p, rhs, 0);
|
||||
lbValue d = lb_emit_struct_ev(p, rhs, 1);
|
||||
|
||||
lbValue real = {};
|
||||
lbValue imag = {};
|
||||
|
||||
switch (op) {
|
||||
case Token_Add:
|
||||
real = lb_emit_arith(p, Token_Add, a, c, ft);
|
||||
imag = lb_emit_arith(p, Token_Add, b, d, ft);
|
||||
break;
|
||||
case Token_Sub:
|
||||
real = lb_emit_arith(p, Token_Sub, a, c, ft);
|
||||
imag = lb_emit_arith(p, Token_Sub, b, d, ft);
|
||||
break;
|
||||
case Token_Mul: {
|
||||
lbValue x = lb_emit_arith(p, Token_Mul, a, c, ft);
|
||||
lbValue y = lb_emit_arith(p, Token_Mul, b, d, ft);
|
||||
real = lb_emit_arith(p, Token_Sub, x, y, ft);
|
||||
lbValue z = lb_emit_arith(p, Token_Mul, b, c, ft);
|
||||
lbValue w = lb_emit_arith(p, Token_Mul, a, d, ft);
|
||||
imag = lb_emit_arith(p, Token_Add, z, w, ft);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), real);
|
||||
lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), imag);
|
||||
|
||||
return lb_addr_load(p, res);
|
||||
} else if (is_type_quaternion(type)) {
|
||||
lhs = lb_emit_conv(p, lhs, type);
|
||||
rhs = lb_emit_conv(p, rhs, type);
|
||||
|
||||
Type *ft = base_complex_elem_type(type);
|
||||
|
||||
if (op == Token_Add || op == Token_Sub) {
|
||||
lbAddr res = lb_add_local_generated(p, type, false); // NOTE: initialized in full later
|
||||
lbValue x0 = lb_emit_struct_ev(p, lhs, 0);
|
||||
lbValue x1 = lb_emit_struct_ev(p, lhs, 1);
|
||||
lbValue x2 = lb_emit_struct_ev(p, lhs, 2);
|
||||
lbValue x3 = lb_emit_struct_ev(p, lhs, 3);
|
||||
|
||||
lbValue y0 = lb_emit_struct_ev(p, rhs, 0);
|
||||
lbValue y1 = lb_emit_struct_ev(p, rhs, 1);
|
||||
lbValue y2 = lb_emit_struct_ev(p, rhs, 2);
|
||||
lbValue y3 = lb_emit_struct_ev(p, rhs, 3);
|
||||
|
||||
lbValue z0 = lb_emit_arith(p, op, x0, y0, ft);
|
||||
lbValue z1 = lb_emit_arith(p, op, x1, y1, ft);
|
||||
lbValue z2 = lb_emit_arith(p, op, x2, y2, ft);
|
||||
lbValue z3 = lb_emit_arith(p, op, x3, y3, ft);
|
||||
|
||||
lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 0), z0);
|
||||
lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 1), z1);
|
||||
lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 2), z2);
|
||||
lb_emit_store(p, lb_emit_struct_ep(p, res.addr, 3), z3);
|
||||
|
||||
return lb_addr_load(p, res);
|
||||
} else if (op == Token_Mul) {
|
||||
auto args = array_make<lbValue>(heap_allocator(), 2);
|
||||
args[0] = lhs;
|
||||
args[1] = rhs;
|
||||
|
||||
switch (8*type_size_of(ft)) {
|
||||
case 32: return lb_emit_runtime_call(p, "mul_quaternion128", args);
|
||||
case 64: return lb_emit_runtime_call(p, "mul_quaternion256", args);
|
||||
default: GB_PANIC("Unknown float type"); break;
|
||||
}
|
||||
} else if (op == Token_Quo) {
|
||||
auto args = array_make<lbValue>(heap_allocator(), 2);
|
||||
args[0] = lhs;
|
||||
args[1] = rhs;
|
||||
|
||||
switch (8*type_size_of(ft)) {
|
||||
case 32: return lb_emit_runtime_call(p, "quo_quaternion128", args);
|
||||
case 64: return lb_emit_runtime_call(p, "quo_quaternion256", args);
|
||||
default: GB_PANIC("Unknown float type"); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_type_integer(type) && is_type_different_to_arch_endianness(type)) {
|
||||
switch (op) {
|
||||
case Token_AndNot:
|
||||
case Token_And:
|
||||
case Token_Or:
|
||||
case Token_Xor:
|
||||
goto handle_op;
|
||||
}
|
||||
|
||||
Type *platform_type = integer_endian_type_to_platform_type(type);
|
||||
lbValue x = lb_emit_byte_swap(p, lhs, integer_endian_type_to_platform_type(lhs.type));
|
||||
lbValue y = lb_emit_byte_swap(p, rhs, integer_endian_type_to_platform_type(rhs.type));
|
||||
|
||||
lbValue res = lb_emit_arith(p, op, x, y, platform_type);
|
||||
|
||||
return lb_emit_byte_swap(p, res, type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
handle_op:
|
||||
lhs = lb_emit_conv(p, lhs, type);
|
||||
rhs = lb_emit_conv(p, rhs, type);
|
||||
|
||||
|
||||
lbValue res = {};
|
||||
res.type = type;
|
||||
|
||||
|
||||
switch (op) {
|
||||
case Token_Add:
|
||||
if (is_type_float(type)) {
|
||||
@@ -4143,8 +4312,7 @@ lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Ty
|
||||
return res;
|
||||
case Token_AndNot:
|
||||
{
|
||||
LLVMValueRef all_ones = LLVMConstAllOnes(lb_type(m, type));
|
||||
LLVMValueRef new_rhs = LLVMBuildXor(p->builder, all_ones, rhs.value, "");
|
||||
LLVMValueRef new_rhs = LLVMBuildNot(p->builder, rhs.value, "");
|
||||
res.value = LLVMBuildAnd(p->builder, lhs.value, new_rhs, "");
|
||||
return res;
|
||||
}
|
||||
@@ -4852,7 +5020,7 @@ void lb_emit_init_context(lbProcedure *p, lbValue c) {
|
||||
gbAllocator a = heap_allocator();
|
||||
auto args = array_make<lbValue>(a, 1);
|
||||
args[0] = c.value != nullptr ? c : m->global_default_context.addr;
|
||||
// lb_emit_runtime_call(p, "__init_context", args);
|
||||
lb_emit_runtime_call(p, "__init_context", args);
|
||||
}
|
||||
|
||||
void lb_push_context_onto_stack(lbProcedure *p, lbAddr ctx) {
|
||||
@@ -4866,10 +5034,6 @@ lbAddr lb_find_or_generate_context_ptr(lbProcedure *p) {
|
||||
return p->context_stack[p->context_stack.count-1].ctx;
|
||||
}
|
||||
|
||||
// lbBlock *tmp_block = p->curr_block;
|
||||
// p->curr_block = p->blocks[0];
|
||||
// defer (p->curr_block = tmp_block);
|
||||
|
||||
lbAddr c = lb_add_local_generated(p, t_context, false);
|
||||
c.kind = lbAddr_Context;
|
||||
lb_push_context_onto_stack(p, c);
|
||||
@@ -6495,10 +6659,29 @@ void lb_emit_increment(lbProcedure *p, lbValue addr) {
|
||||
lbValue lb_emit_byte_swap(lbProcedure *p, lbValue value, Type *platform_type) {
|
||||
Type *vt = core_type(value.type);
|
||||
GB_ASSERT(type_size_of(vt) == type_size_of(platform_type));
|
||||
GB_ASSERT(is_type_integer(vt));
|
||||
|
||||
// TODO(bill): lb_emit_byte_swap
|
||||
lbValue res = {};
|
||||
res.type = platform_type;
|
||||
res.value = value.value;
|
||||
|
||||
// int sz = cast(int)type_size_of(vt);
|
||||
// if (sz > 1) {
|
||||
// char buf[32] = {};
|
||||
// gb_snprintf(buf, gb_count_of(buf), "llvm.bswap.i%d", sz*8);
|
||||
// unsigned id = LLVMLookupIntrinsicID(buf, gb_strlen(buf));
|
||||
// gb_printf(">>> %s %u\n", buf, id);
|
||||
|
||||
// LLVMTypeRef types[2] = {};
|
||||
// types[0] = lb_type(p->module, value.type);
|
||||
// types[1] = lb_type(p->module, value.type);
|
||||
|
||||
// LLVMValueRef fn = LLVMGetIntrinsicDeclaration(p->module->mod, id, types, gb_count_of(types));
|
||||
|
||||
// res.value = LLVMBuildCall(p->builder, fn, &value.value, 1, "");
|
||||
// }
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ struct lbBlock {
|
||||
LLVMBasicBlockRef block;
|
||||
Scope *scope;
|
||||
isize scope_index;
|
||||
bool appended;
|
||||
|
||||
Array<lbBlock *> preds;
|
||||
Array<lbBlock *> succs;
|
||||
@@ -220,7 +221,7 @@ void lb_end_procedure(lbProcedure *p);
|
||||
|
||||
LLVMTypeRef lb_type(lbModule *m, Type *type);
|
||||
|
||||
lbBlock *lb_create_block(lbProcedure *p, char const *name);
|
||||
lbBlock *lb_create_block(lbProcedure *p, char const *name, bool append=false);
|
||||
|
||||
lbValue lb_const_nil(lbModule *m, Type *type);
|
||||
lbValue lb_const_undef(lbModule *m, Type *type);
|
||||
|
||||
@@ -101,6 +101,14 @@ char *alloc_cstring(gbAllocator a, String s) {
|
||||
return c_str;
|
||||
}
|
||||
|
||||
char *cstring_duplicate(gbAllocator a, char const *s) {
|
||||
isize len = gb_strlen(s);
|
||||
char *c_str = gb_alloc_array(a, char, len+1);
|
||||
gb_memmove(c_str, s, len);
|
||||
c_str[len] = '\0';
|
||||
return c_str;
|
||||
}
|
||||
|
||||
|
||||
|
||||
gb_inline bool str_eq_ignore_case(String const &a, String const &b) {
|
||||
|
||||
Reference in New Issue
Block a user