lib/chant/src/lower/expression/call.zig
daab053ee43316e1809a84551d573ddd1e5bf3d2
1 const std = @import("std");
2 const choir = @import("choir");
3 const ast = @import("../../ast/root.zig");
4 const lower_mod = @import("../root.zig");
5 const builtin = @import("builtin.zig");
6 const types = @import("types.zig");
7
8 const FuncDialect = choir.dialects.FuncDialect;
9 const Error = lower_mod.Error;
10 const Lowerer = lower_mod.Lowerer;
11 const Typed = types.Typed;
12
13 pub fn lower(lowerer: *Lowerer, call: ast.expr.Call, comptime recurse: types.LowerExpression) Error!Typed {
14 if (try builtin.lower(lowerer, call, recurse)) |result| return result;
15
16 const signature = lowerer.functions.get(call.callee) orelse return error.UndefinedName;
17 if (signature.params.len != call.arguments.len) return error.UnsupportedConstruct;
18
19 var arguments = std.ArrayListUnmanaged(*choir.Value).empty;
20 defer arguments.deinit(lowerer.gpa);
21 for (call.arguments, 0..) |argument, i| {
22 const lowered = try recurse(lowerer, argument);
23 const converted = try lower_mod.convert.convert(lowerer, lowered.value, lowered.c_type, signature.params[i].type);
24 try arguments.append(lowerer.gpa, converted);
25 }
26
27 const return_c_type = signature.child orelse return error.UnsupportedType;
28 var result_types = std.ArrayListUnmanaged(choir.Type).empty;
29 defer result_types.deinit(lowerer.gpa);
30 if (return_c_type.kind != .void_type) {
31 try result_types.append(lowerer.gpa, try lower_mod.convert.scalarType(lowerer, return_c_type));
32 }
33
34 const call_op = FuncDialect.CallOp.create(lowerer.ctx, lowerer.loc, call.callee, arguments.items, result_types.items) catch return error.OutOfMemory;
35 try lower_mod.emit.append(lowerer, call_op.op);
36 if (return_c_type.kind == .void_type) {
37 return .{ .value = undefined, .c_type = &ast.types.void_type };
38 }
39 const result = call_op.getResult(0) orelse return error.UnsupportedConstruct;
40 return .{ .value = result, .c_type = return_c_type };
41 }