mirror of
https://github.com/odin-lang/Odin.git
synced 2026-02-13 23:03:16 +00:00
Port code for lb_build_call_expr
This commit is contained in:
@@ -1,45 +1,39 @@
|
||||
package demo
|
||||
|
||||
import "core:os"
|
||||
|
||||
// Foo :: struct {
|
||||
// x, y: int,
|
||||
// };
|
||||
// foo :: proc(x: int) -> (f: Foo) {
|
||||
// return;
|
||||
// }
|
||||
BarBar :: struct {
|
||||
x, y: int,
|
||||
};
|
||||
foo :: proc(x: int) -> (b: BarBar) {
|
||||
return;
|
||||
}
|
||||
|
||||
main :: proc() {
|
||||
Foo :: enum {A=1, B, C, D};
|
||||
Foo_Set :: bit_set[Foo];
|
||||
x := Foo_Set{.A, .C};
|
||||
foo_set := Foo_Set{.A, .C};
|
||||
|
||||
y := [4]int{3 = 1, 0 .. 1 = 3, 2 = 9};
|
||||
z := []int{1, 2, 3, 4};
|
||||
array := [4]int{3 = 1, 0 .. 1 = 3, 2 = 9};
|
||||
slice := []int{1, 2, 3, 4};
|
||||
|
||||
// @thread_local a: int;
|
||||
@thread_local a: int;
|
||||
|
||||
// x := i32(1);
|
||||
// y := i32(2);
|
||||
// z := x + y;
|
||||
// w := z - 2;
|
||||
x := i32(1);
|
||||
y := i32(2);
|
||||
z := x + y;
|
||||
w := z - 2;
|
||||
|
||||
// foo(123);
|
||||
f := foo;
|
||||
|
||||
c := 1 + 2i;
|
||||
q := 1 + 2i + 3j + 4k;
|
||||
|
||||
// c := 1 + 2i;
|
||||
// q := 1 + 2i + 3j + 4k;
|
||||
s := "Hellope";
|
||||
|
||||
// s := "Hellope";
|
||||
|
||||
// f := Foo{1, 2};
|
||||
// pc: proc "contextless" (x: i32) -> Foo;
|
||||
// po: proc "odin" (x: i32) -> Foo;
|
||||
// e: enum{A, B, C};
|
||||
// u: union{i32, bool};
|
||||
// u1: union{i32};
|
||||
// um: union #maybe {^int};
|
||||
|
||||
// os.write_string(os.stdout, "Hellope\n");
|
||||
return;
|
||||
bb := BarBar{1, 2};
|
||||
pc: proc "contextless" (x: i32) -> BarBar;
|
||||
po: proc "odin" (x: i32) -> BarBar;
|
||||
e: enum{A, B, C};
|
||||
u: union{i32, bool};
|
||||
u1: union{i32};
|
||||
um: union #maybe {^int};
|
||||
}
|
||||
|
||||
@@ -27,6 +27,11 @@ void lb_addr_store(lbProcedure *p, lbAddr const &addr, lbValue const &value) {
|
||||
}
|
||||
|
||||
|
||||
void lb_emit_store(lbProcedure *p, lbValue ptr, lbValue value) {
|
||||
GB_ASSERT(value.value != nullptr);
|
||||
LLVMValueRef v = LLVMBuildStore(p->builder, value.value, ptr.value);
|
||||
}
|
||||
|
||||
lbValue lb_emit_load(lbProcedure *p, lbValue value) {
|
||||
GB_ASSERT(value.value != nullptr);
|
||||
Type *t = type_deref(value.type);
|
||||
@@ -99,14 +104,25 @@ String lb_mangle_name(lbModule *m, Entity *e) {
|
||||
return make_string(new_name, new_name_len-1);
|
||||
}
|
||||
|
||||
String lb_get_entity_name(lbModule *m, Entity *e, String name) {
|
||||
String lb_get_entity_name(lbModule *m, Entity *e, String default_name) {
|
||||
if (e != nullptr && e->kind == Entity_TypeName && e->TypeName.ir_mangled_name.len != 0) {
|
||||
return e->TypeName.ir_mangled_name;
|
||||
}
|
||||
|
||||
String name = {};
|
||||
|
||||
bool no_name_mangle = false;
|
||||
|
||||
if (e->kind == Entity_Variable) {
|
||||
bool is_foreign = e->Variable.is_foreign;
|
||||
bool is_export = e->Variable.is_export;
|
||||
no_name_mangle = e->Variable.link_name.len > 0 || is_foreign || is_export;
|
||||
} else if (e->kind == Entity_Procedure && e->Procedure.is_export) {
|
||||
no_name_mangle = true;
|
||||
} else if (e->kind == Entity_Procedure && e->Procedure.link_name.len > 0) {
|
||||
no_name_mangle = true;
|
||||
}
|
||||
|
||||
if (!no_name_mangle) {
|
||||
name = lb_mangle_name(m, e);
|
||||
}
|
||||
@@ -116,8 +132,10 @@ String lb_get_entity_name(lbModule *m, Entity *e, String name) {
|
||||
|
||||
if (e != nullptr && e->kind == Entity_TypeName) {
|
||||
e->TypeName.ir_mangled_name = name;
|
||||
|
||||
} else if (e != nullptr && e->kind == Entity_Procedure) {
|
||||
e->Procedure.link_name = name;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -519,6 +537,8 @@ LLVMTypeRef lb_type_internal(Type *type) {
|
||||
}
|
||||
|
||||
LLVMTypeRef lb_type(Type *type) {
|
||||
type = default_type(type);
|
||||
|
||||
if (type->llvm_type) {
|
||||
return type->llvm_type;
|
||||
}
|
||||
@@ -726,11 +746,20 @@ lbAddr lb_add_local(lbProcedure *p, Type *type, Entity *e=nullptr) {
|
||||
val.value = ptr;
|
||||
val.type = alloc_type_pointer(type);
|
||||
|
||||
lb_add_entity(p->module, e, val);
|
||||
if (e != nullptr) {
|
||||
lb_add_entity(p->module, e, val);
|
||||
}
|
||||
|
||||
return lb_addr(val);
|
||||
}
|
||||
|
||||
lbAddr lb_add_local_generated(lbProcedure *p, Type *type, bool zero_init) {
|
||||
lbAddr addr = lb_add_local(p, type, nullptr);
|
||||
lb_addr_store(p, addr, lb_const_nil(type));
|
||||
return addr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool lb_init_generator(lbGenerator *gen, Checker *c) {
|
||||
if (global_error_collector.count != 0) {
|
||||
@@ -994,7 +1023,7 @@ void lb_build_stmt(lbProcedure *p, Ast *node) {
|
||||
// res = lb_emit_load(p, *found);
|
||||
} else {
|
||||
res = lb_build_expr(p, rs->results[0]);
|
||||
// res = ir_emit_conv(p, v, e->type);
|
||||
res = lb_emit_conv(p, res, e->type);
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1041,6 +1070,13 @@ lbValue lb_const_nil(Type *type) {
|
||||
return lbValue{v, type};
|
||||
}
|
||||
|
||||
lbValue lb_const_int(Type *type, u64 value) {
|
||||
lbValue res = {};
|
||||
res.value = LLVMConstInt(lb_type(type), value, !is_type_unsigned(type));
|
||||
res.type = type;
|
||||
return res;
|
||||
}
|
||||
|
||||
LLVMValueRef llvm_const_f32(f32 f, Type *type=t_f32) {
|
||||
u32 u = bit_cast<u32>(f);
|
||||
LLVMValueRef i = LLVMConstInt(LLVMInt32Type(), u, false);
|
||||
@@ -1048,6 +1084,8 @@ LLVMValueRef llvm_const_f32(f32 f, Type *type=t_f32) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
lbValue lb_find_or_add_entity_string(lbModule *m, String const &str) {
|
||||
HashKey key = hash_string(str);
|
||||
lbValue *found = map_get(&m->const_strings, key);
|
||||
@@ -1662,6 +1700,31 @@ lbValue lb_const_value(lbModule *m, Type *type, ExactValue value) {
|
||||
return lb_const_nil(original_type);
|
||||
}
|
||||
|
||||
u64 lb_generate_source_code_location_hash(TokenPos const &pos) {
|
||||
u64 h = 0xcbf29ce484222325;
|
||||
for (isize i = 0; i < pos.file.len; i++) {
|
||||
h = (h ^ u64(pos.file[i])) * 0x100000001b3;
|
||||
}
|
||||
h = h ^ (u64(pos.line) * 0x100000001b3);
|
||||
h = h ^ (u64(pos.column) * 0x100000001b3);
|
||||
return h;
|
||||
}
|
||||
|
||||
lbValue lb_emit_source_code_location(lbProcedure *p, String const &procedure, TokenPos const &pos) {
|
||||
LLVMValueRef fields[5] = {};
|
||||
fields[0]/*file*/ = lb_find_or_add_entity_string(p->module, pos.file).value;
|
||||
fields[1]/*line*/ = lb_const_int(t_int, pos.line).value;
|
||||
fields[2]/*column*/ = lb_const_int(t_int, pos.column).value;
|
||||
fields[3]/*procedure*/ = lb_find_or_add_entity_string(p->module, procedure).value;
|
||||
fields[4]/*hash*/ = lb_const_int(t_u64, lb_generate_source_code_location_hash(pos)).value;
|
||||
|
||||
lbValue res = {};
|
||||
res.value = LLVMConstNamedStruct(lb_type(t_source_code_location), fields, 5);
|
||||
res.type = t_source_code_location;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
lbValue lb_emit_arith(lbProcedure *p, TokenKind op, lbValue lhs, lbValue rhs, Type *type) {
|
||||
lbValue res = {};
|
||||
res.type = type;
|
||||
@@ -1784,6 +1847,339 @@ lbValue lb_build_binary_expr(lbProcedure *p, Ast *expr) {
|
||||
return {};
|
||||
}
|
||||
|
||||
lbValue lb_emit_conv(lbProcedure *p, lbValue value, Type *t) {
|
||||
// TODO(bill): lb_emit_conv
|
||||
return value;
|
||||
}
|
||||
|
||||
lbValue lb_emit_call(lbProcedure *p, lbValue value, Array<lbValue > const &args, ProcInlining inlining = ProcInlining_none, bool use_return_ptr_hint = false) {
|
||||
return {};
|
||||
}
|
||||
|
||||
lbValue lb_emit_ev(lbProcedure *p, lbValue value, i32 index) {
|
||||
return {};
|
||||
}
|
||||
|
||||
lbValue lb_emit_array_epi(lbProcedure *p, lbValue value, i32 index){
|
||||
return {};
|
||||
}
|
||||
|
||||
void lb_fill_slice(lbProcedure *p, lbAddr slice, lbValue base_elem, lbValue len) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
lbValue lb_build_call_expr(lbProcedure *p, Ast *expr) {
|
||||
TypeAndValue tv = type_and_value_of_expr(expr);
|
||||
|
||||
ast_node(ce, CallExpr, expr);
|
||||
|
||||
TypeAndValue proc_tv = type_and_value_of_expr(ce->proc);
|
||||
AddressingMode proc_mode = proc_tv.mode;
|
||||
if (proc_mode == Addressing_Type) {
|
||||
GB_ASSERT(ce->args.count == 1);
|
||||
lbValue x = lb_build_expr(p, ce->args[0]);
|
||||
lbValue y = lb_emit_conv(p, x, tv.type);
|
||||
return y;
|
||||
}
|
||||
|
||||
Ast *pexpr = unparen_expr(ce->proc);
|
||||
if (proc_mode == Addressing_Builtin) {
|
||||
Entity *e = entity_of_node(pexpr);
|
||||
BuiltinProcId id = BuiltinProc_Invalid;
|
||||
if (e != nullptr) {
|
||||
id = cast(BuiltinProcId)e->Builtin.id;
|
||||
} else {
|
||||
id = BuiltinProc_DIRECTIVE;
|
||||
}
|
||||
GB_PANIC("lb_build_builtin_proc");
|
||||
// return lb_build_builtin_proc(p, expr, tv, id);
|
||||
}
|
||||
|
||||
// NOTE(bill): Regular call
|
||||
lbValue value = {};
|
||||
Ast *proc_expr = unparen_expr(ce->proc);
|
||||
if (proc_expr->tav.mode == Addressing_Constant) {
|
||||
ExactValue v = proc_expr->tav.value;
|
||||
switch (v.kind) {
|
||||
case ExactValue_Integer:
|
||||
{
|
||||
u64 u = big_int_to_u64(&v.value_integer);
|
||||
lbValue x = {};
|
||||
x.value = LLVMConstInt(lb_type(t_uintptr), u, false);
|
||||
x.type = t_uintptr;
|
||||
x = lb_emit_conv(p, x, t_rawptr);
|
||||
value = lb_emit_conv(p, x, proc_expr->tav.type);
|
||||
break;
|
||||
}
|
||||
case ExactValue_Pointer:
|
||||
{
|
||||
u64 u = cast(u64)v.value_pointer;
|
||||
lbValue x = {};
|
||||
x.value = LLVMConstInt(lb_type(t_uintptr), u, false);
|
||||
x.type = t_uintptr;
|
||||
x = lb_emit_conv(p, x, t_rawptr);
|
||||
value = lb_emit_conv(p, x, proc_expr->tav.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (value.value == nullptr) {
|
||||
value = lb_build_expr(p, proc_expr);
|
||||
}
|
||||
|
||||
GB_ASSERT(value.value != nullptr);
|
||||
Type *proc_type_ = base_type(value.type);
|
||||
GB_ASSERT(proc_type_->kind == Type_Proc);
|
||||
TypeProc *pt = &proc_type_->Proc;
|
||||
set_procedure_abi_types(heap_allocator(), proc_type_);
|
||||
|
||||
if (is_call_expr_field_value(ce)) {
|
||||
auto args = array_make<lbValue >(heap_allocator(), pt->param_count);
|
||||
|
||||
for_array(arg_index, ce->args) {
|
||||
Ast *arg = ce->args[arg_index];
|
||||
ast_node(fv, FieldValue, arg);
|
||||
GB_ASSERT(fv->field->kind == Ast_Ident);
|
||||
String name = fv->field->Ident.token.string;
|
||||
isize index = lookup_procedure_parameter(pt, name);
|
||||
GB_ASSERT(index >= 0);
|
||||
TypeAndValue tav = type_and_value_of_expr(fv->value);
|
||||
if (tav.mode == Addressing_Type) {
|
||||
args[index] = lb_const_nil(tav.type);
|
||||
} else {
|
||||
args[index] = lb_build_expr(p, fv->value);
|
||||
}
|
||||
}
|
||||
TypeTuple *params = &pt->params->Tuple;
|
||||
for (isize i = 0; i < args.count; i++) {
|
||||
Entity *e = params->variables[i];
|
||||
if (e->kind == Entity_TypeName) {
|
||||
args[i] = lb_const_nil(e->type);
|
||||
} else if (e->kind == Entity_Constant) {
|
||||
continue;
|
||||
} else {
|
||||
GB_ASSERT(e->kind == Entity_Variable);
|
||||
if (args[i].value == nullptr) {
|
||||
switch (e->Variable.param_value.kind) {
|
||||
case ParameterValue_Constant:
|
||||
args[i] = lb_const_value(p->module, e->type, e->Variable.param_value.value);
|
||||
break;
|
||||
case ParameterValue_Nil:
|
||||
args[i] = lb_const_nil(e->type);
|
||||
break;
|
||||
case ParameterValue_Location:
|
||||
args[i] = lb_emit_source_code_location(p, p->entity->token.string, ast_token(expr).pos);
|
||||
break;
|
||||
case ParameterValue_Value:
|
||||
args[i] = lb_build_expr(p, e->Variable.param_value.ast_value);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
args[i] = lb_emit_conv(p, args[i], e->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return lb_emit_call(p, value, args, ce->inlining, p->return_ptr_hint_ast == expr);
|
||||
}
|
||||
|
||||
isize arg_index = 0;
|
||||
|
||||
isize arg_count = 0;
|
||||
for_array(i, ce->args) {
|
||||
Ast *arg = ce->args[i];
|
||||
TypeAndValue tav = type_and_value_of_expr(arg);
|
||||
GB_ASSERT_MSG(tav.mode != Addressing_Invalid, "%s %s", expr_to_string(arg), expr_to_string(expr));
|
||||
GB_ASSERT_MSG(tav.mode != Addressing_ProcGroup, "%s", expr_to_string(arg));
|
||||
Type *at = tav.type;
|
||||
if (at->kind == Type_Tuple) {
|
||||
arg_count += at->Tuple.variables.count;
|
||||
} else {
|
||||
arg_count++;
|
||||
}
|
||||
}
|
||||
|
||||
isize param_count = 0;
|
||||
if (pt->params) {
|
||||
GB_ASSERT(pt->params->kind == Type_Tuple);
|
||||
param_count = pt->params->Tuple.variables.count;
|
||||
}
|
||||
|
||||
auto args = array_make<lbValue >(heap_allocator(), cast(isize)gb_max(param_count, arg_count));
|
||||
isize variadic_index = pt->variadic_index;
|
||||
bool variadic = pt->variadic && variadic_index >= 0;
|
||||
bool vari_expand = ce->ellipsis.pos.line != 0;
|
||||
bool is_c_vararg = pt->c_vararg;
|
||||
|
||||
String proc_name = {};
|
||||
if (p->entity != nullptr) {
|
||||
proc_name = p->entity->token.string;
|
||||
}
|
||||
TokenPos pos = ast_token(ce->proc).pos;
|
||||
|
||||
TypeTuple *param_tuple = nullptr;
|
||||
if (pt->params) {
|
||||
GB_ASSERT(pt->params->kind == Type_Tuple);
|
||||
param_tuple = &pt->params->Tuple;
|
||||
}
|
||||
|
||||
for_array(i, ce->args) {
|
||||
Ast *arg = ce->args[i];
|
||||
TypeAndValue arg_tv = type_and_value_of_expr(arg);
|
||||
if (arg_tv.mode == Addressing_Type) {
|
||||
args[arg_index++] = lb_const_nil(arg_tv.type);
|
||||
} else {
|
||||
lbValue a = lb_build_expr(p, arg);
|
||||
Type *at = a.type;
|
||||
if (at->kind == Type_Tuple) {
|
||||
for_array(i, at->Tuple.variables) {
|
||||
Entity *e = at->Tuple.variables[i];
|
||||
lbValue v = lb_emit_ev(p, a, cast(i32)i);
|
||||
args[arg_index++] = v;
|
||||
}
|
||||
} else {
|
||||
args[arg_index++] = a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (param_count > 0) {
|
||||
GB_ASSERT_MSG(pt->params != nullptr, "%s %td", expr_to_string(expr), pt->param_count);
|
||||
GB_ASSERT(param_count < 1000000);
|
||||
|
||||
if (arg_count < param_count) {
|
||||
isize end = cast(isize)param_count;
|
||||
if (variadic) {
|
||||
end = variadic_index;
|
||||
}
|
||||
while (arg_index < end) {
|
||||
Entity *e = param_tuple->variables[arg_index];
|
||||
GB_ASSERT(e->kind == Entity_Variable);
|
||||
|
||||
switch (e->Variable.param_value.kind) {
|
||||
case ParameterValue_Constant:
|
||||
args[arg_index++] = lb_const_value(p->module, e->type, e->Variable.param_value.value);
|
||||
break;
|
||||
case ParameterValue_Nil:
|
||||
args[arg_index++] = lb_const_nil(e->type);
|
||||
break;
|
||||
case ParameterValue_Location:
|
||||
args[arg_index++] = lb_emit_source_code_location(p, proc_name, pos);
|
||||
break;
|
||||
case ParameterValue_Value:
|
||||
args[arg_index++] = lb_build_expr(p, e->Variable.param_value.ast_value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_c_vararg) {
|
||||
GB_ASSERT(variadic);
|
||||
GB_ASSERT(!vari_expand);
|
||||
isize i = 0;
|
||||
for (; i < variadic_index; i++) {
|
||||
Entity *e = param_tuple->variables[i];
|
||||
if (e->kind == Entity_Variable) {
|
||||
args[i] = lb_emit_conv(p, args[i], e->type);
|
||||
}
|
||||
}
|
||||
Type *variadic_type = param_tuple->variables[i]->type;
|
||||
GB_ASSERT(is_type_slice(variadic_type));
|
||||
variadic_type = base_type(variadic_type)->Slice.elem;
|
||||
if (!is_type_any(variadic_type)) {
|
||||
for (; i < arg_count; i++) {
|
||||
args[i] = lb_emit_conv(p, args[i], variadic_type);
|
||||
}
|
||||
} else {
|
||||
for (; i < arg_count; i++) {
|
||||
args[i] = lb_emit_conv(p, args[i], default_type(args[i].type));
|
||||
}
|
||||
}
|
||||
} else if (variadic) {
|
||||
isize i = 0;
|
||||
for (; i < variadic_index; i++) {
|
||||
Entity *e = param_tuple->variables[i];
|
||||
if (e->kind == Entity_Variable) {
|
||||
args[i] = lb_emit_conv(p, args[i], e->type);
|
||||
}
|
||||
}
|
||||
if (!vari_expand) {
|
||||
Type *variadic_type = param_tuple->variables[i]->type;
|
||||
GB_ASSERT(is_type_slice(variadic_type));
|
||||
variadic_type = base_type(variadic_type)->Slice.elem;
|
||||
for (; i < arg_count; i++) {
|
||||
args[i] = lb_emit_conv(p, args[i], variadic_type);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (isize i = 0; i < param_count; i++) {
|
||||
Entity *e = param_tuple->variables[i];
|
||||
if (e->kind == Entity_Variable) {
|
||||
GB_ASSERT(args[i].value != nullptr);
|
||||
args[i] = lb_emit_conv(p, args[i], e->type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (variadic && !vari_expand && !is_c_vararg) {
|
||||
// variadic call argument generation
|
||||
gbAllocator allocator = heap_allocator();
|
||||
Type *slice_type = param_tuple->variables[variadic_index]->type;
|
||||
Type *elem_type = base_type(slice_type)->Slice.elem;
|
||||
lbAddr slice = lb_add_local_generated(p, slice_type, true);
|
||||
isize slice_len = arg_count+1 - (variadic_index+1);
|
||||
|
||||
if (slice_len > 0) {
|
||||
lbAddr base_array = lb_add_local_generated(p, alloc_type_array(elem_type, slice_len), true);
|
||||
|
||||
for (isize i = variadic_index, j = 0; i < arg_count; i++, j++) {
|
||||
lbValue addr = lb_emit_array_epi(p, base_array.addr, cast(i32)j);
|
||||
lb_emit_store(p, addr, args[i]);
|
||||
}
|
||||
|
||||
lbValue base_elem = lb_emit_array_epi(p, base_array.addr, 0);
|
||||
lbValue len = lb_const_int(t_int, slice_len);
|
||||
lb_fill_slice(p, slice, base_elem, len);
|
||||
}
|
||||
|
||||
arg_count = param_count;
|
||||
args[variadic_index] = lb_addr_load(p, slice);
|
||||
}
|
||||
}
|
||||
|
||||
if (variadic && variadic_index+1 < param_count) {
|
||||
for (isize i = variadic_index+1; i < param_count; i++) {
|
||||
Entity *e = param_tuple->variables[i];
|
||||
switch (e->Variable.param_value.kind) {
|
||||
case ParameterValue_Constant:
|
||||
args[i] = lb_const_value(p->module, e->type, e->Variable.param_value.value);
|
||||
break;
|
||||
case ParameterValue_Nil:
|
||||
args[i] = lb_const_nil(e->type);
|
||||
break;
|
||||
case ParameterValue_Location:
|
||||
args[i] = lb_emit_source_code_location(p, proc_name, pos);
|
||||
break;
|
||||
case ParameterValue_Value:
|
||||
args[i] = lb_build_expr(p, e->Variable.param_value.ast_value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isize final_count = param_count;
|
||||
if (is_c_vararg) {
|
||||
final_count = arg_count;
|
||||
}
|
||||
|
||||
auto call_args = array_slice(args, 0, final_count);
|
||||
return lb_emit_call(p, value, call_args, ce->inlining, p->return_ptr_hint_ast == expr);
|
||||
}
|
||||
|
||||
|
||||
lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
expr = unparen_expr(expr);
|
||||
|
||||
@@ -1809,7 +2205,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
case_end;
|
||||
|
||||
case_ast_node(i, Implicit, expr);
|
||||
// return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||
// return ir_addr_load(p, ir_build_addr(p, expr));
|
||||
GB_PANIC("TODO(bill): Implicit");
|
||||
case_end;
|
||||
|
||||
@@ -1822,7 +2218,7 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
GB_ASSERT_MSG(e != nullptr, "%s", expr_to_string(expr));
|
||||
if (e->kind == Entity_Builtin) {
|
||||
Token token = ast_token(expr);
|
||||
GB_PANIC("TODO(bill): ir_build_expr Entity_Builtin '%.*s'\n"
|
||||
GB_PANIC("TODO(bill): lb_build_expr Entity_Builtin '%.*s'\n"
|
||||
"\t at %.*s(%td:%td)", LIT(builtin_procs[e->Builtin.id].name),
|
||||
LIT(token.pos.file), token.pos.line, token.pos.column);
|
||||
return {};
|
||||
@@ -1833,13 +2229,13 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
auto *found = map_get(&p->module->values, hash_entity(e));
|
||||
if (found) {
|
||||
auto v = *found;
|
||||
LLVMTypeKind kind = LLVMGetTypeKind(LLVMTypeOf(v.value));
|
||||
if (kind == LLVMFunctionTypeKind) {
|
||||
// NOTE(bill): This is because pointers are already pointers in LLVM
|
||||
if (is_type_proc(v.type)) {
|
||||
return v;
|
||||
}
|
||||
return lb_emit_load(p, v);
|
||||
// } else if (e != nullptr && e->kind == Entity_Variable) {
|
||||
// return ir_addr_load(proc, ir_build_addr(proc, expr));
|
||||
// return ir_addr_load(p, ir_build_addr(p, expr));
|
||||
}
|
||||
GB_PANIC("nullptr value for expression from identifier: %.*s : %s @ %p", LIT(i->token.string), type_to_string(e->type), expr);
|
||||
return {};
|
||||
@@ -1848,6 +2244,11 @@ lbValue lb_build_expr(lbProcedure *p, Ast *expr) {
|
||||
case_ast_node(be, BinaryExpr, expr);
|
||||
return lb_build_binary_expr(p, expr);
|
||||
case_end;
|
||||
|
||||
|
||||
case_ast_node(ce, CallExpr, expr);
|
||||
return lb_build_call_expr(p, expr);
|
||||
case_end;
|
||||
}
|
||||
|
||||
return {};
|
||||
@@ -1941,17 +2342,7 @@ void lb_generate_module(lbGenerator *gen) {
|
||||
defer (LLVMDisposeMessage(llvm_error));
|
||||
|
||||
|
||||
// LLVMPassManagerRef pass_manager = LLVMCreatePassManager();
|
||||
// defer (LLVMDisposePassManager(pass_manager));
|
||||
|
||||
// LLVMAddAggressiveInstCombinerPass(pass_manager);
|
||||
// LLVMAddConstantMergePass(pass_manager);
|
||||
// LLVMAddDeadArgEliminationPass(pass_manager);
|
||||
|
||||
// LLVMRunPassManager(pass_manager, mod);
|
||||
|
||||
LLVMVerifyModule(mod, LLVMAbortProcessAction, &llvm_error);
|
||||
llvm_error = nullptr;
|
||||
|
||||
LLVMDumpModule(mod);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user