Function getIntrinsic [src]

Prototype

pub fn getIntrinsic( self: *Builder, id: Intrinsic, overload: []const Type, ) Allocator.Error!Function.Index

Parameters

self: *Builderid: Intrinsicoverload: []const Type

Source

pub fn getIntrinsic( self: *Builder, id: Intrinsic, overload: []const Type, ) Allocator.Error!Function.Index { const ExpectedContents = extern union { attrs: extern struct { params: [expected_args_len]Type, fn_attrs: [FunctionAttributes.params_index + expected_args_len]Attributes, attrs: [expected_attrs_len]Attribute.Index, fields: [expected_fields_len]Type, }, }; var stack align(@max(@alignOf(std.heap.StackFallbackAllocator(0)), @alignOf(ExpectedContents))) = std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); const allocator = stack.get(); const name = name: { const writer = self.strtab_string_bytes.writer(self.gpa); try writer.print("llvm.{s}", .{@tagName(id)}); for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)}); break :name try self.trailingStrtabString(); }; if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function; const signature = Intrinsic.signatures.get(id); const param_types = try allocator.alloc(Type, signature.params.len); defer allocator.free(param_types); const function_attributes = try allocator.alloc( Attributes, FunctionAttributes.params_index + (signature.params.len - signature.ret_len), ); defer allocator.free(function_attributes); var attributes: struct { builder: *Builder, list: std.ArrayList(Attribute.Index), fn deinit(state: *@This()) void { state.list.deinit(); state.* = undefined; } fn get(state: *@This(), attributes: []const Attribute) Allocator.Error!Attributes { try state.list.resize(attributes.len); for (state.list.items, attributes) |*item, attribute| item.* = try state.builder.attr(attribute); return state.builder.attrs(state.list.items); } } = .{ .builder = self, .list = std.ArrayList(Attribute.Index).init(allocator) }; defer attributes.deinit(); var overload_index: usize = 0; function_attributes[FunctionAttributes.function_index] = try attributes.get(signature.attrs); function_attributes[FunctionAttributes.return_index] = .none; // needed for void return for (0.., param_types, signature.params) |param_index, *param_type, signature_param| { switch (signature_param.kind) { .type => |ty| param_type.* = ty, .overloaded => { param_type.* = overload[overload_index]; overload_index += 1; }, .matches, .matches_scalar, .matches_changed_scalar => {}, } function_attributes[ if (param_index < signature.ret_len) FunctionAttributes.return_index else FunctionAttributes.params_index + (param_index - signature.ret_len) ] = try attributes.get(signature_param.attrs); } assert(overload_index == overload.len); for (param_types, signature.params) |*param_type, signature_param| { param_type.* = switch (signature_param.kind) { .type, .overloaded => continue, .matches => |param_index| param_types[param_index], .matches_scalar => |param_index| param_types[param_index].scalarType(self), .matches_changed_scalar => |info| try param_types[info.index] .changeScalar(info.scalar, self), }; } const function_index = try self.addFunction(try self.fnType(switch (signature.ret_len) { 0 => .void, 1 => param_types[0], else => try self.structType(.normal, param_types[0..signature.ret_len]), }, param_types[signature.ret_len..], .normal), name, .default); function_index.ptr(self).attributes = try self.fnAttrs(function_attributes); return function_index; }