C ABI rework
This commit is contained in:
parent
39444e4a61
commit
8e7d81d8ff
10
build.zig
10
build.zig
@ -78,9 +78,11 @@ const LLVM = struct {
|
|||||||
else => "HOME",
|
else => "HOME",
|
||||||
};
|
};
|
||||||
const home_path = env.get(home_env) orelse unreachable;
|
const home_path = env.get(home_env) orelse unreachable;
|
||||||
|
const is_ci = std.mem.eql(u8, (env.get("BB_CI") orelse "0"), "1");
|
||||||
const download_dir = try std.mem.concat(b.allocator, u8, &.{ home_path, "/Downloads" });
|
const download_dir = try std.mem.concat(b.allocator, u8, &.{ home_path, "/Downloads" });
|
||||||
std.fs.makeDirAbsolute(download_dir) catch {};
|
std.fs.makeDirAbsolute(download_dir) catch {};
|
||||||
const llvm_base = try std.mem.concat(b.allocator, u8, &.{ "llvm-", @tagName(target.result.cpu.arch), "-", @tagName(target.result.os.tag), "-", @tagName(CmakeBuildType.from_zig_build_type(optimize)) });
|
const cmake_build_type = if (is_ci) CmakeBuildType.from_zig_build_type(optimize) else CmakeBuildType.Release;
|
||||||
|
const llvm_base = try std.mem.concat(b.allocator, u8, &.{ "llvm-", @tagName(target.result.cpu.arch), "-", @tagName(target.result.os.tag), "-", @tagName(cmake_build_type) });
|
||||||
const base = try std.mem.concat(b.allocator, u8, &.{ download_dir, "/", llvm_base });
|
const base = try std.mem.concat(b.allocator, u8, &.{ download_dir, "/", llvm_base });
|
||||||
const full_path = try std.mem.concat(b.allocator, u8, &.{ base, "/bin/llvm-config" });
|
const full_path = try std.mem.concat(b.allocator, u8, &.{ base, "/bin/llvm-config" });
|
||||||
|
|
||||||
@ -306,7 +308,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
env = try std.process.getEnvMap(b.allocator);
|
env = try std.process.getEnvMap(b.allocator);
|
||||||
target = b.standardTargetOptions(.{});
|
target = b.standardTargetOptions(.{});
|
||||||
optimize = b.standardOptimizeOption(.{});
|
optimize = b.standardOptimizeOption(.{});
|
||||||
system_llvm = b.option(bool, "system_llvm", "Link against system LLVM libraries") orelse true;
|
system_llvm = b.option(bool, "system_llvm", "Link against system LLVM libraries") orelse false;
|
||||||
const path = env.get("PATH") orelse unreachable;
|
const path = env.get("PATH") orelse unreachable;
|
||||||
|
|
||||||
const c_abi_module = b.createModule(.{
|
const c_abi_module = b.createModule(.{
|
||||||
@ -322,7 +324,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
c_abi.addCSourceFiles(.{
|
c_abi.addCSourceFiles(.{
|
||||||
.files = &.{"src/c_abi.c"},
|
.files = &.{"tests/c_abi.c"},
|
||||||
.flags = &.{"-g"},
|
.flags = &.{"-g"},
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -363,8 +365,8 @@ pub fn build(b: *std.Build) !void {
|
|||||||
|
|
||||||
const exe_unit_tests = b.addTest(.{
|
const exe_unit_tests = b.addTest(.{
|
||||||
.root_module = exe_mod,
|
.root_module = exe_mod,
|
||||||
|
.link_libc = true,
|
||||||
});
|
});
|
||||||
exe_unit_tests.linkLibC();
|
|
||||||
|
|
||||||
llvm.link(exe);
|
llvm.link(exe);
|
||||||
|
|
||||||
|
623
src/LLVM.zig
623
src/LLVM.zig
@ -33,6 +33,28 @@ pub const Intrinsic = enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Attribute = opaque {
|
pub const Attribute = opaque {
|
||||||
|
pub const List = opaque {
|
||||||
|
pub const Options = extern struct {
|
||||||
|
function: Attribute.Function,
|
||||||
|
@"return": Attribute.Argument,
|
||||||
|
argument_pointer: [*]const Attribute.Argument,
|
||||||
|
argument_length: u64,
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
assert(@sizeOf(Options) == @sizeOf(Attribute.Function) + @sizeOf(Attribute.Argument) + @sizeOf([*]const Attribute.Argument) + @sizeOf(u64));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn build(context: *Context, function_attributes: Attribute.Function, return_attributes: Attribute.Argument, argument_attributes: []const Attribute.Argument, call_site: bool) *Attribute.List {
|
||||||
|
return api.llvm_attribute_list_build(context, &Options{
|
||||||
|
.function = function_attributes,
|
||||||
|
.@"return" = return_attributes,
|
||||||
|
.argument_pointer = argument_attributes.ptr,
|
||||||
|
.argument_length = argument_attributes.len,
|
||||||
|
}, call_site);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const Index = enum(c_uint) {
|
pub const Index = enum(c_uint) {
|
||||||
@"return" = 0,
|
@"return" = 0,
|
||||||
function = 0xffff_ffff,
|
function = 0xffff_ffff,
|
||||||
@ -42,6 +64,172 @@ pub const Attribute = opaque {
|
|||||||
pub const Kind = enum(c_uint) {
|
pub const Kind = enum(c_uint) {
|
||||||
_,
|
_,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const FramePointerKind = enum(u2) {
|
||||||
|
none = 0,
|
||||||
|
reserved = 1,
|
||||||
|
non_leaf = 2,
|
||||||
|
all = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ZeroCallUsedRegsKind = enum(u4) {
|
||||||
|
all = 0,
|
||||||
|
skip = 1 << 0,
|
||||||
|
used_gpr_arg = only_used | only_gpr | only_arg,
|
||||||
|
used_gpr = only_used | only_gpr,
|
||||||
|
used_arg = only_used | only_arg,
|
||||||
|
used = only_used,
|
||||||
|
all_gpr_arg = only_gpr | only_arg,
|
||||||
|
all_gpr = only_gpr,
|
||||||
|
all_arg = only_arg,
|
||||||
|
|
||||||
|
const only_used = 1 << 1;
|
||||||
|
const only_gpr = 1 << 2;
|
||||||
|
const only_arg = 1 << 3;
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const FPClassTest = packed struct(u10) {
|
||||||
|
s_nan: bool = false,
|
||||||
|
q_nan: bool = false,
|
||||||
|
neg_inf: bool = false,
|
||||||
|
neg_normal: bool = false,
|
||||||
|
neg_subnormal: bool = false,
|
||||||
|
neg_zero: bool = false,
|
||||||
|
pos_zero: bool = false,
|
||||||
|
pos_subnormal: bool = false,
|
||||||
|
pos_normal: bool = false,
|
||||||
|
pos_inf: bool = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const UnwindTableKind = enum(u2) {
|
||||||
|
none = 0,
|
||||||
|
sync = 1,
|
||||||
|
@"async" = 2,
|
||||||
|
|
||||||
|
pub const default = UnwindTableKind.@"async";
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Argument = extern struct {
|
||||||
|
semantic_type: *Type,
|
||||||
|
abi_type: *Type,
|
||||||
|
dereferenceable_bytes: u64,
|
||||||
|
alignment: u32,
|
||||||
|
flags: packed struct(u32) {
|
||||||
|
no_alias: bool,
|
||||||
|
non_null: bool,
|
||||||
|
no_undef: bool,
|
||||||
|
sign_extend: bool,
|
||||||
|
zero_extend: bool,
|
||||||
|
in_reg: bool,
|
||||||
|
no_fp_class: FPClassTest,
|
||||||
|
struct_return: bool,
|
||||||
|
writable: bool,
|
||||||
|
dead_on_unwind: bool,
|
||||||
|
in_alloca: bool,
|
||||||
|
dereferenceable: bool,
|
||||||
|
dereferenceable_or_null: bool,
|
||||||
|
nest: bool,
|
||||||
|
by_value: bool,
|
||||||
|
by_reference: bool,
|
||||||
|
no_capture: bool,
|
||||||
|
_: u6 = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
assert(@sizeOf(Attribute.Argument) == 2 * @sizeOf(*Type) + 2 * @sizeOf(u64));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Function = extern struct {
|
||||||
|
prefer_vector_width: String,
|
||||||
|
stack_protector_buffer_size: String,
|
||||||
|
definition_probe_stack: String,
|
||||||
|
definition_stack_probe_size: String,
|
||||||
|
flags0: packed struct(u64) {
|
||||||
|
noreturn: bool,
|
||||||
|
cmse_ns_call: bool,
|
||||||
|
nounwind: bool,
|
||||||
|
returns_twice: bool,
|
||||||
|
cold: bool,
|
||||||
|
hot: bool,
|
||||||
|
no_duplicate: bool,
|
||||||
|
convergent: bool,
|
||||||
|
no_merge: bool,
|
||||||
|
will_return: bool,
|
||||||
|
no_caller_saved_registers: bool,
|
||||||
|
no_cf_check: bool,
|
||||||
|
no_callback: bool,
|
||||||
|
alloc_size: bool,
|
||||||
|
uniform_work_group_size: bool,
|
||||||
|
aarch64_pstate_sm_body: bool,
|
||||||
|
aarch64_pstate_sm_enabled: bool,
|
||||||
|
aarch64_pstate_sm_compatible: bool,
|
||||||
|
aarch64_preserves_za: bool,
|
||||||
|
aarch64_in_za: bool,
|
||||||
|
aarch64_out_za: bool,
|
||||||
|
aarch64_inout_za: bool,
|
||||||
|
aarch64_preserves_zt0: bool,
|
||||||
|
aarch64_in_zt0: bool,
|
||||||
|
aarch64_out_zt0: bool,
|
||||||
|
aarch64_inout_zt0: bool,
|
||||||
|
optimize_for_size: bool,
|
||||||
|
min_size: bool,
|
||||||
|
no_red_zone: bool,
|
||||||
|
indirect_tls_seg_refs: bool,
|
||||||
|
no_implicit_floats: bool,
|
||||||
|
sample_profile_suffix_elision_policy: bool,
|
||||||
|
memory_none: bool,
|
||||||
|
memory_readonly: bool,
|
||||||
|
memory_inaccessible_or_arg_memory_only: bool,
|
||||||
|
memory_arg_memory_only: bool,
|
||||||
|
strict_fp: bool,
|
||||||
|
no_inline: bool,
|
||||||
|
always_inline: bool,
|
||||||
|
guard_no_cf: bool,
|
||||||
|
// TODO: branch protection function attributes
|
||||||
|
// TODO: cpu features
|
||||||
|
|
||||||
|
// CALL-SITE ATTRIBUTES
|
||||||
|
call_no_builtins: bool,
|
||||||
|
|
||||||
|
// DEFINITION-SITE ATTRIBUTES
|
||||||
|
definition_frame_pointer_kind: FramePointerKind,
|
||||||
|
definition_less_precise_fpmad: bool,
|
||||||
|
definition_null_pointer_is_valid: bool,
|
||||||
|
definition_no_trapping_fp_math: bool,
|
||||||
|
definition_no_infs_fp_math: bool,
|
||||||
|
definition_no_nans_fp_math: bool,
|
||||||
|
definition_approx_func_fp_math: bool,
|
||||||
|
definition_unsafe_fp_math: bool,
|
||||||
|
definition_use_soft_float: bool,
|
||||||
|
definition_no_signed_zeroes_fp_math: bool,
|
||||||
|
definition_stack_realignment: bool,
|
||||||
|
definition_backchain: bool,
|
||||||
|
definition_split_stack: bool,
|
||||||
|
definition_speculative_load_hardening: bool,
|
||||||
|
definition_zero_call_used_registers: ZeroCallUsedRegsKind,
|
||||||
|
// TODO: denormal builtins
|
||||||
|
definition_non_lazy_bind: bool,
|
||||||
|
definition_cmse_nonsecure_entry: bool,
|
||||||
|
definition_unwind_table_kind: UnwindTableKind,
|
||||||
|
},
|
||||||
|
flags1: packed struct(u64) {
|
||||||
|
definition_disable_tail_calls: bool,
|
||||||
|
definition_stack_protect_strong: bool,
|
||||||
|
definition_stack_protect: bool,
|
||||||
|
definition_stack_protect_req: bool,
|
||||||
|
definition_aarch64_new_za: bool,
|
||||||
|
definition_aarch64_new_zt0: bool,
|
||||||
|
definition_optimize_none: bool,
|
||||||
|
definition_naked: bool,
|
||||||
|
definition_inline_hint: bool,
|
||||||
|
reserved: u55 = 0,
|
||||||
|
},
|
||||||
|
|
||||||
|
comptime {
|
||||||
|
assert(@sizeOf(Attribute.Function) == 10 * @sizeOf(u64));
|
||||||
|
}
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CodeModel = enum(u8) {
|
pub const CodeModel = enum(u8) {
|
||||||
@ -74,19 +262,19 @@ pub const Target = opaque {
|
|||||||
/// This is ABI-compatible with C++
|
/// This is ABI-compatible with C++
|
||||||
pub const Options = extern struct {
|
pub const Options = extern struct {
|
||||||
flags0: packed struct(u64) {
|
flags0: packed struct(u64) {
|
||||||
unsafe_fp_math: u1,
|
unsafe_fp_math: bool,
|
||||||
no_infs_fp_math: u1,
|
no_infs_fp_math: bool,
|
||||||
no_nans_fp_math: u1,
|
no_nans_fp_math: bool,
|
||||||
no_trapping_fp_math: u1,
|
no_trapping_fp_math: bool,
|
||||||
no_signed_zeroes_fp_math: u1,
|
no_signed_zeroes_fp_math: bool,
|
||||||
approx_func_fp_match: u1,
|
approx_func_fp_math: bool,
|
||||||
enable_aix_extended_altivec_abi: u1,
|
enable_aix_extended_altivec_abi: bool,
|
||||||
honor_sign_dependent_rounding_fp_math: u1,
|
honor_sign_dependent_rounding_fp_math: bool,
|
||||||
no_zeroes_in_bss: u1,
|
no_zeroes_in_bss: bool,
|
||||||
guaranteed_tail_call_optimization: u1,
|
guaranteed_tail_call_optimization: bool,
|
||||||
stack_symbol_ordering: u1,
|
stack_symbol_ordering: bool,
|
||||||
enable_fast_isel: u1,
|
enable_fast_isel: bool,
|
||||||
enable_global_isel: u1,
|
enable_global_isel: bool,
|
||||||
global_isel_abort_mode: enum(u2) {
|
global_isel_abort_mode: enum(u2) {
|
||||||
disable = 0,
|
disable = 0,
|
||||||
enable = 1,
|
enable = 1,
|
||||||
@ -97,27 +285,27 @@ pub const Target = opaque {
|
|||||||
always = 1,
|
always = 1,
|
||||||
never = 2,
|
never = 2,
|
||||||
},
|
},
|
||||||
use_init_array: u1,
|
use_init_array: bool,
|
||||||
disable_integrated_assembler: u1,
|
disable_integrated_assembler: bool,
|
||||||
function_sections: u1,
|
function_sections: bool,
|
||||||
data_sections: u1,
|
data_sections: bool,
|
||||||
ignore_xcoff_visibility: u1,
|
ignore_xcoff_visibility: bool,
|
||||||
xcoff_traceback_table: u1,
|
xcoff_traceback_table: bool,
|
||||||
unique_section_names: u1,
|
unique_section_names: bool,
|
||||||
unique_basic_block_section_names: u1,
|
unique_basic_block_section_names: bool,
|
||||||
separate_named_sections: u1,
|
separate_named_sections: bool,
|
||||||
trap_unreachable: u1,
|
trap_unreachable: bool,
|
||||||
no_trap_after_noreturn: u1,
|
no_trap_after_noreturn: bool,
|
||||||
tls_size: u8,
|
tls_size: u8,
|
||||||
emulated_tls: u1,
|
emulated_tls: bool,
|
||||||
enable_tls_descriptors: u1,
|
enable_tls_descriptors: bool,
|
||||||
enable_ipra: u1,
|
enable_ipra: bool,
|
||||||
emit_stack_size_section: u1,
|
emit_stack_size_section: bool,
|
||||||
enable_machine_outliner: u1,
|
enable_machine_outliner: bool,
|
||||||
enable_machine_function_splitter: u1,
|
enable_machine_function_splitter: bool,
|
||||||
supports_default_outlining: u1,
|
supports_default_outlining: bool,
|
||||||
emit_address_significance_table: u1,
|
emit_address_significance_table: bool,
|
||||||
bb_address_map: u1,
|
bb_address_map: bool,
|
||||||
bb_sections: enum(u3) {
|
bb_sections: enum(u3) {
|
||||||
all = 0,
|
all = 0,
|
||||||
list = 1,
|
list = 1,
|
||||||
@ -125,19 +313,19 @@ pub const Target = opaque {
|
|||||||
preset = 3,
|
preset = 3,
|
||||||
none = 4,
|
none = 4,
|
||||||
},
|
},
|
||||||
emit_call_site_information: u1,
|
emit_call_site_information: bool,
|
||||||
supports_debug_entry_values: u1,
|
supports_debug_entry_values: bool,
|
||||||
enable_debug_entry_values: u1,
|
enable_debug_entry_values: bool,
|
||||||
value_tracking_variable_locations: u1,
|
value_tracking_variable_locations: bool,
|
||||||
force_dwarf_frame_section: u1,
|
force_dwarf_frame_section: bool,
|
||||||
xray_function_index: u1,
|
xray_function_index: bool,
|
||||||
debug_strict_dwarf: u1,
|
debug_strict_dwarf: bool,
|
||||||
hotpatch: u1,
|
hotpatch: bool,
|
||||||
ppc_gen_scalar_mass_entries: u1,
|
ppc_gen_scalar_mass_entries: bool,
|
||||||
jmc_instrument: u1,
|
jmc_instrument: bool,
|
||||||
enable_cfi_fixup: u1,
|
enable_cfi_fixup: bool,
|
||||||
mis_expect: u1,
|
mis_expect: bool,
|
||||||
xcoff_read_only_pointers: u1,
|
xcoff_read_only_pointers: bool,
|
||||||
float_abi: enum(u2) {
|
float_abi: enum(u2) {
|
||||||
default = 0,
|
default = 0,
|
||||||
soft = 1,
|
soft = 1,
|
||||||
@ -200,56 +388,56 @@ pub const Target = opaque {
|
|||||||
return .{
|
return .{
|
||||||
.binutils_version = .{ 0, 0 },
|
.binutils_version = .{ 0, 0 },
|
||||||
.flags0 = .{
|
.flags0 = .{
|
||||||
.unsafe_fp_math = 0,
|
.unsafe_fp_math = false,
|
||||||
.no_infs_fp_math = 0,
|
.no_infs_fp_math = false,
|
||||||
.no_nans_fp_math = 0,
|
.no_nans_fp_math = false,
|
||||||
.no_trapping_fp_math = 1,
|
.no_trapping_fp_math = true,
|
||||||
.no_signed_zeroes_fp_math = 0,
|
.no_signed_zeroes_fp_math = false,
|
||||||
.approx_func_fp_match = 0,
|
.approx_func_fp_math = false,
|
||||||
.enable_aix_extended_altivec_abi = 0,
|
.enable_aix_extended_altivec_abi = false,
|
||||||
.honor_sign_dependent_rounding_fp_math = 0,
|
.honor_sign_dependent_rounding_fp_math = false,
|
||||||
.no_zeroes_in_bss = 0,
|
.no_zeroes_in_bss = false,
|
||||||
.guaranteed_tail_call_optimization = 0,
|
.guaranteed_tail_call_optimization = false,
|
||||||
.stack_symbol_ordering = 1,
|
.stack_symbol_ordering = true,
|
||||||
.enable_fast_isel = 0,
|
.enable_fast_isel = false,
|
||||||
.enable_global_isel = 0,
|
.enable_global_isel = false,
|
||||||
.global_isel_abort_mode = .enable,
|
.global_isel_abort_mode = .enable,
|
||||||
.swift_async_frame_pointer = .always,
|
.swift_async_frame_pointer = .always,
|
||||||
.use_init_array = 0,
|
.use_init_array = false,
|
||||||
.disable_integrated_assembler = 0,
|
.disable_integrated_assembler = false,
|
||||||
.function_sections = 0,
|
.function_sections = false,
|
||||||
.data_sections = 0,
|
.data_sections = false,
|
||||||
.ignore_xcoff_visibility = 0,
|
.ignore_xcoff_visibility = false,
|
||||||
.xcoff_traceback_table = 1,
|
.xcoff_traceback_table = true,
|
||||||
.unique_section_names = 1,
|
.unique_section_names = true,
|
||||||
.unique_basic_block_section_names = 0,
|
.unique_basic_block_section_names = false,
|
||||||
.separate_named_sections = 0,
|
.separate_named_sections = false,
|
||||||
.trap_unreachable = 0,
|
.trap_unreachable = false,
|
||||||
.no_trap_after_noreturn = 0,
|
.no_trap_after_noreturn = false,
|
||||||
.tls_size = 0,
|
.tls_size = 0,
|
||||||
.emulated_tls = 0,
|
.emulated_tls = false,
|
||||||
.enable_tls_descriptors = 0,
|
.enable_tls_descriptors = false,
|
||||||
.enable_ipra = 0,
|
.enable_ipra = false,
|
||||||
.emit_stack_size_section = 0,
|
.emit_stack_size_section = false,
|
||||||
.enable_machine_outliner = 0,
|
.enable_machine_outliner = false,
|
||||||
.enable_machine_function_splitter = 0,
|
.enable_machine_function_splitter = false,
|
||||||
.supports_default_outlining = 0,
|
.supports_default_outlining = false,
|
||||||
.emit_address_significance_table = 0,
|
.emit_address_significance_table = false,
|
||||||
.bb_address_map = 0,
|
.bb_address_map = false,
|
||||||
.bb_sections = .none,
|
.bb_sections = .none,
|
||||||
.emit_call_site_information = 0,
|
.emit_call_site_information = false,
|
||||||
.supports_debug_entry_values = 0,
|
.supports_debug_entry_values = false,
|
||||||
.enable_debug_entry_values = 0,
|
.enable_debug_entry_values = false,
|
||||||
.value_tracking_variable_locations = 0,
|
.value_tracking_variable_locations = false,
|
||||||
.force_dwarf_frame_section = 0,
|
.force_dwarf_frame_section = false,
|
||||||
.xray_function_index = 1,
|
.xray_function_index = true,
|
||||||
.debug_strict_dwarf = 0,
|
.debug_strict_dwarf = false,
|
||||||
.hotpatch = 0,
|
.hotpatch = false,
|
||||||
.ppc_gen_scalar_mass_entries = 0,
|
.ppc_gen_scalar_mass_entries = false,
|
||||||
.jmc_instrument = 0,
|
.jmc_instrument = false,
|
||||||
.enable_cfi_fixup = 0,
|
.enable_cfi_fixup = false,
|
||||||
.mis_expect = 0,
|
.mis_expect = false,
|
||||||
.xcoff_read_only_pointers = 0,
|
.xcoff_read_only_pointers = false,
|
||||||
.float_abi = .default,
|
.float_abi = .default,
|
||||||
.thread_model = .posix,
|
.thread_model = .posix,
|
||||||
},
|
},
|
||||||
@ -271,28 +459,28 @@ pub const Target = opaque {
|
|||||||
.integrated_assembler_search_path_pointer = null,
|
.integrated_assembler_search_path_pointer = null,
|
||||||
.integrated_assembler_search_path_count = 0,
|
.integrated_assembler_search_path_count = 0,
|
||||||
.flags = .{
|
.flags = .{
|
||||||
.relax_all = 0,
|
.relax_all = false,
|
||||||
.no_exec_stack = 0,
|
.no_exec_stack = false,
|
||||||
.fatal_warnings = 0,
|
.fatal_warnings = false,
|
||||||
.no_warn = 0,
|
.no_warn = false,
|
||||||
.no_deprecated_warn = 0,
|
.no_deprecated_warn = false,
|
||||||
.no_type_check = 0,
|
.no_type_check = false,
|
||||||
.save_temp_labels = 0,
|
.save_temp_labels = false,
|
||||||
.incremental_linker_compatible = 0,
|
.incremental_linker_compatible = false,
|
||||||
.fdpic = 0,
|
.fdpic = false,
|
||||||
.show_mc_encoding = 0,
|
.show_mc_encoding = false,
|
||||||
.show_mc_inst = 0,
|
.show_mc_inst = false,
|
||||||
.asm_verbose = 0,
|
.asm_verbose = false,
|
||||||
.preserve_asm_comments = 1,
|
.preserve_asm_comments = true,
|
||||||
.dwarf64 = 0,
|
.dwarf64 = false,
|
||||||
.crel = 0,
|
.crel = false,
|
||||||
.x86_relax_relocations = 1,
|
.x86_relax_relocations = true,
|
||||||
.x86_sse2_avx = 0,
|
.x86_sse2_avx = false,
|
||||||
.emit_dwarf_unwind = .default,
|
.emit_dwarf_unwind = .default,
|
||||||
.use_dwarf_directory = .default,
|
.use_dwarf_directory = .default,
|
||||||
.debug_compression_type = .none,
|
.debug_compression_type = .none,
|
||||||
.emit_compact_unwind_non_canonical = 0,
|
.emit_compact_unwind_non_canonical = false,
|
||||||
.ppc_use_full_register_names = 0,
|
.ppc_use_full_register_names = false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -337,23 +525,23 @@ pub const MCTargetOptions = extern struct {
|
|||||||
integrated_assembler_search_path_pointer: ?[*]const String,
|
integrated_assembler_search_path_pointer: ?[*]const String,
|
||||||
integrated_assembler_search_path_count: u64,
|
integrated_assembler_search_path_count: u64,
|
||||||
flags: packed struct(u32) {
|
flags: packed struct(u32) {
|
||||||
relax_all: u1,
|
relax_all: bool,
|
||||||
no_exec_stack: u1,
|
no_exec_stack: bool,
|
||||||
fatal_warnings: u1,
|
fatal_warnings: bool,
|
||||||
no_warn: u1,
|
no_warn: bool,
|
||||||
no_deprecated_warn: u1,
|
no_deprecated_warn: bool,
|
||||||
no_type_check: u1,
|
no_type_check: bool,
|
||||||
save_temp_labels: u1,
|
save_temp_labels: bool,
|
||||||
incremental_linker_compatible: u1,
|
incremental_linker_compatible: bool,
|
||||||
fdpic: u1,
|
fdpic: bool,
|
||||||
show_mc_encoding: u1,
|
show_mc_encoding: bool,
|
||||||
show_mc_inst: u1,
|
show_mc_inst: bool,
|
||||||
asm_verbose: u1,
|
asm_verbose: bool,
|
||||||
preserve_asm_comments: u1,
|
preserve_asm_comments: bool,
|
||||||
dwarf64: u1,
|
dwarf64: bool,
|
||||||
crel: u1,
|
crel: bool,
|
||||||
x86_relax_relocations: u1,
|
x86_relax_relocations: bool,
|
||||||
x86_sse2_avx: u1,
|
x86_sse2_avx: bool,
|
||||||
emit_dwarf_unwind: enum(u2) {
|
emit_dwarf_unwind: enum(u2) {
|
||||||
always = 0,
|
always = 0,
|
||||||
no_compact_unwind = 1,
|
no_compact_unwind = 1,
|
||||||
@ -369,8 +557,8 @@ pub const MCTargetOptions = extern struct {
|
|||||||
zlib = 1,
|
zlib = 1,
|
||||||
zstd = 2,
|
zstd = 2,
|
||||||
},
|
},
|
||||||
emit_compact_unwind_non_canonical: u1,
|
emit_compact_unwind_non_canonical: bool,
|
||||||
ppc_use_full_register_names: u1,
|
ppc_use_full_register_names: bool,
|
||||||
reserved: PaddingType = 0,
|
reserved: PaddingType = 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -410,16 +598,16 @@ pub const OptimizationLevel = enum(u3) {
|
|||||||
/// This is ABI-compatible with C++
|
/// This is ABI-compatible with C++
|
||||||
pub const OptimizationPipelineOptions = packed struct(u64) {
|
pub const OptimizationPipelineOptions = packed struct(u64) {
|
||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
debug_info: u1,
|
debug_info: bool,
|
||||||
loop_unrolling: u1,
|
loop_unrolling: bool,
|
||||||
loop_interleaving: u1,
|
loop_interleaving: bool,
|
||||||
loop_vectorization: u1,
|
loop_vectorization: bool,
|
||||||
slp_vectorization: u1,
|
slp_vectorization: bool,
|
||||||
merge_functions: u1,
|
merge_functions: bool,
|
||||||
call_graph_profile: u1,
|
call_graph_profile: bool,
|
||||||
unified_lto: u1,
|
unified_lto: bool,
|
||||||
assignment_tracking: u1,
|
assignment_tracking: bool,
|
||||||
verify_module: u1,
|
verify_module: bool,
|
||||||
reserved: PaddingType = 0,
|
reserved: PaddingType = 0,
|
||||||
|
|
||||||
const padding_bit_count = 51;
|
const padding_bit_count = 51;
|
||||||
@ -437,10 +625,10 @@ pub const OptimizationPipelineOptions = packed struct(u64) {
|
|||||||
|
|
||||||
const Create = packed struct {
|
const Create = packed struct {
|
||||||
optimization_level: OptimizationLevel,
|
optimization_level: OptimizationLevel,
|
||||||
debug_info: u1,
|
debug_info: bool,
|
||||||
};
|
};
|
||||||
pub fn default(create: Create) OptimizationPipelineOptions {
|
pub fn default(create: Create) OptimizationPipelineOptions {
|
||||||
const pref_speed = @intFromBool(create.optimization_level.prefers_speed());
|
const pref_speed = create.optimization_level.prefers_speed();
|
||||||
return .{
|
return .{
|
||||||
.optimization_level = create.optimization_level,
|
.optimization_level = create.optimization_level,
|
||||||
.debug_info = create.debug_info,
|
.debug_info = create.debug_info,
|
||||||
@ -449,10 +637,10 @@ pub const OptimizationPipelineOptions = packed struct(u64) {
|
|||||||
.loop_vectorization = pref_speed,
|
.loop_vectorization = pref_speed,
|
||||||
.slp_vectorization = pref_speed,
|
.slp_vectorization = pref_speed,
|
||||||
.merge_functions = pref_speed,
|
.merge_functions = pref_speed,
|
||||||
.call_graph_profile = 0,
|
.call_graph_profile = false,
|
||||||
.unified_lto = 0,
|
.unified_lto = false,
|
||||||
.assignment_tracking = create.debug_info,
|
.assignment_tracking = create.debug_info,
|
||||||
.verify_module = @intFromBool(lib.optimization_mode == .ReleaseSafe or lib.optimization_mode == .Debug),
|
.verify_module = lib.optimization_mode == .ReleaseSafe or lib.optimization_mode == .Debug,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -467,8 +655,8 @@ pub const CodeGenerationPipelineOptions = extern struct {
|
|||||||
object_file = 1,
|
object_file = 1,
|
||||||
null = 2,
|
null = 2,
|
||||||
},
|
},
|
||||||
optimize_when_possible: u1,
|
optimize_when_possible: bool,
|
||||||
verify_module: u1,
|
verify_module: bool,
|
||||||
reserved: PaddingType = 0,
|
reserved: PaddingType = 0,
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -515,7 +703,7 @@ pub const Context = opaque {
|
|||||||
|
|
||||||
pub const create_builder = api.LLVMCreateBuilderInContext;
|
pub const create_builder = api.LLVMCreateBuilderInContext;
|
||||||
|
|
||||||
pub fn create_basic_block(context: *Context, name: []const u8, parent: *Function) *BasicBlock {
|
pub fn create_basic_block(context: *Context, name: []const u8, parent: ?*Function) *BasicBlock {
|
||||||
return api.llvm_context_create_basic_block(context, String.from_slice(name), parent);
|
return api.llvm_context_create_basic_block(context, String.from_slice(name), parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -541,16 +729,30 @@ pub const Context = opaque {
|
|||||||
return api.LLVMIntrinsicGetType(context, intrinsic_id, parameter_types.ptr, parameter_types.len);
|
return api.LLVMIntrinsicGetType(context, intrinsic_id, parameter_types.ptr, parameter_types.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_string_attribute(context: *Context, attribute_name: []const u8, attribute_value: []const u8) *Attribute {
|
pub fn get_anonymous_constant_struct(context: *Context, constant_values: []const *Constant, is_packed: bool) *Constant {
|
||||||
return api.LLVMCreateStringAttribute(context, attribute_name.ptr, @intCast(attribute_name.len), attribute_value.ptr, @intCast(attribute_value.len));
|
return api.LLVMConstStructInContext(context, constant_values.ptr, @intCast(constant_values.len), @intFromBool(is_packed));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const create_enum_attribute = api.LLVMCreateEnumAttribute;
|
// pub fn create_string_attribute(context: *Context, attribute_name: []const u8, attribute_value: []const u8) *Attribute {
|
||||||
pub const create_type_attribute = api.LLVMCreateTypeAttribute;
|
// return api.LLVMCreateStringAttribute(context, attribute_name.ptr, @intCast(attribute_name.len), attribute_value.ptr, @intCast(attribute_value.len));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// pub const create_enum_attribute = api.LLVMCreateEnumAttribute;
|
||||||
|
// pub const create_type_attribute = api.LLVMCreateTypeAttribute;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const BasicBlock = opaque {
|
pub const BasicBlock = opaque {
|
||||||
|
pub const delete = api.llvm_basic_block_delete;
|
||||||
|
pub const erase_from_parent = api.LLVMDeleteBasicBlock;
|
||||||
pub const get_terminator = api.LLVMGetBasicBlockTerminator;
|
pub const get_terminator = api.LLVMGetBasicBlockTerminator;
|
||||||
|
pub const is_empty = api.llvm_basic_block_is_empty;
|
||||||
|
pub const user_begin = api.llvm_basic_block_user_begin;
|
||||||
|
pub const get_next = api.LLVMGetNextBasicBlock;
|
||||||
|
pub const get_parent = api.LLVMGetBasicBlockParent;
|
||||||
|
|
||||||
|
pub fn to_value(basic_block: *BasicBlock) *Value {
|
||||||
|
return @ptrCast(basic_block);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Module = opaque {
|
pub const Module = opaque {
|
||||||
@ -610,6 +812,7 @@ pub const VerifyResult = struct {
|
|||||||
|
|
||||||
pub const Builder = opaque {
|
pub const Builder = opaque {
|
||||||
pub const position_at_end = api.LLVMPositionBuilderAtEnd;
|
pub const position_at_end = api.LLVMPositionBuilderAtEnd;
|
||||||
|
pub const clear_insertion_position = api.LLVMClearInsertionPosition;
|
||||||
pub const get_insert_block = api.LLVMGetInsertBlock;
|
pub const get_insert_block = api.LLVMGetInsertBlock;
|
||||||
|
|
||||||
pub const create_ret = api.LLVMBuildRet;
|
pub const create_ret = api.LLVMBuildRet;
|
||||||
@ -690,6 +893,7 @@ pub const Builder = opaque {
|
|||||||
return api.LLVMBuildICmp(builder, predicate, left, right, "");
|
return api.LLVMBuildICmp(builder, predicate, left, right, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const create_branch = api.LLVMBuildBr;
|
||||||
pub const create_conditional_branch = api.LLVMBuildCondBr;
|
pub const create_conditional_branch = api.LLVMBuildCondBr;
|
||||||
|
|
||||||
pub fn create_call(builder: *Builder, function_type: *Type.Function, function_value: *Value, arguments: []const *Value) *Value {
|
pub fn create_call(builder: *Builder, function_type: *Type.Function, function_value: *Value, arguments: []const *Value) *Value {
|
||||||
@ -708,6 +912,10 @@ pub const Builder = opaque {
|
|||||||
return api.LLVMBuildInsertValue(builder, aggregate, element, index, "");
|
return api.LLVMBuildInsertValue(builder, aggregate, element, index, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_extract_value(builder: *Builder, aggregate: *Value, index: c_uint) *Value {
|
||||||
|
return api.LLVMBuildExtractValue(builder, aggregate, index, "");
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_zero_extend(builder: *Builder, value: *Value, destination_type: *Type) *Value {
|
pub fn create_zero_extend(builder: *Builder, value: *Value, destination_type: *Type) *Value {
|
||||||
return api.LLVMBuildZExt(builder, value, destination_type, "");
|
return api.LLVMBuildZExt(builder, value, destination_type, "");
|
||||||
}
|
}
|
||||||
@ -731,6 +939,12 @@ pub const Builder = opaque {
|
|||||||
pub const create_unreachable = api.LLVMBuildUnreachable;
|
pub const create_unreachable = api.LLVMBuildUnreachable;
|
||||||
|
|
||||||
pub const create_memcpy = api.LLVMBuildMemCpy;
|
pub const create_memcpy = api.LLVMBuildMemCpy;
|
||||||
|
|
||||||
|
pub fn create_vaarg(builder: *Builder, va_list: *Value, arg_type: *Type) *Value {
|
||||||
|
return api.LLVMBuildVAArg(builder, va_list, arg_type, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const find_return_value_dominating_store = api.llvm_find_return_value_dominating_store;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const GlobalValue = opaque {
|
pub const GlobalValue = opaque {
|
||||||
@ -739,6 +953,10 @@ pub const GlobalValue = opaque {
|
|||||||
|
|
||||||
pub const GlobalVariable = opaque {
|
pub const GlobalVariable = opaque {
|
||||||
pub const add_debug_info = api.llvm_global_variable_add_debug_info;
|
pub const add_debug_info = api.llvm_global_variable_add_debug_info;
|
||||||
|
pub const get_initializer = api.LLVMGetInitializer;
|
||||||
|
pub const set_initializer = api.LLVMSetInitializer;
|
||||||
|
pub const erase_from_parent = api.LLVMDeleteGlobal;
|
||||||
|
pub const delete = api.llvm_global_variable_delete;
|
||||||
pub fn to_value(global_variable: *GlobalVariable) *Value {
|
pub fn to_value(global_variable: *GlobalVariable) *Value {
|
||||||
return @ptrCast(global_variable);
|
return @ptrCast(global_variable);
|
||||||
}
|
}
|
||||||
@ -776,7 +994,9 @@ pub const Function = opaque {
|
|||||||
|
|
||||||
pub const get_arguments = api.LLVMGetParams;
|
pub const get_arguments = api.LLVMGetParams;
|
||||||
|
|
||||||
pub const add_attribute = api.LLVMAddAttributeAtIndex;
|
pub const set_attributes = api.llvm_function_set_attributes;
|
||||||
|
pub const get_last_basic_block = api.LLVMGetLastBasicBlock;
|
||||||
|
pub const append_basic_block = api.LLVMAppendExistingBasicBlock;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Constant = opaque {
|
pub const Constant = opaque {
|
||||||
@ -784,17 +1004,19 @@ pub const Constant = opaque {
|
|||||||
return @ptrCast(constant);
|
return @ptrCast(constant);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_global_variable(constant: *Constant) *GlobalVariable {
|
||||||
|
assert(constant.to_value().get_kind() == .global_variable);
|
||||||
|
return @ptrCast(constant);
|
||||||
|
}
|
||||||
|
|
||||||
pub const Integer = opaque {
|
pub const Integer = opaque {
|
||||||
pub fn to_value(constant: *Constant.Integer) *Value {
|
pub fn to_value(constant: *Constant.Integer) *Value {
|
||||||
return @ptrCast(constant);
|
return @ptrCast(constant);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Array = opaque {
|
pub const get_sign_extended_value = api.LLVMConstIntGetSExtValue;
|
||||||
pub fn to_value(constant: *Constant.Array) *Value {
|
pub const get_zero_extended_value = api.LLVMConstIntGetZExtValue;
|
||||||
return @ptrCast(constant);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Argument = opaque {
|
pub const Argument = opaque {
|
||||||
@ -808,7 +1030,20 @@ pub const Value = opaque {
|
|||||||
pub const get_kind = api.LLVMGetValueKind;
|
pub const get_kind = api.LLVMGetValueKind;
|
||||||
pub const set_alignment = api.LLVMSetAlignment;
|
pub const set_alignment = api.LLVMSetAlignment;
|
||||||
|
|
||||||
|
pub fn set_name(value: *Value, name: []const u8) void {
|
||||||
|
api.LLVMSetValueName2(value, name.ptr, name.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The operand API is from the User class, but it would work nonetheless
|
||||||
|
pub const get_operand = api.LLVMGetOperand;
|
||||||
|
|
||||||
pub const is_call_instruction = api.LLVMIsACallInst;
|
pub const is_call_instruction = api.LLVMIsACallInst;
|
||||||
|
pub const use_empty = api.llvm_value_use_empty;
|
||||||
|
pub const has_one_use = api.llvm_value_has_one_use;
|
||||||
|
|
||||||
|
pub const replace_all_uses_with = api.LLVMReplaceAllUsesWith;
|
||||||
|
|
||||||
|
pub const to_branch = api.llvm_value_to_branch;
|
||||||
|
|
||||||
pub fn is_constant(value: *Value) bool {
|
pub fn is_constant(value: *Value) bool {
|
||||||
return api.LLVMIsConstant(value) != 0;
|
return api.LLVMIsConstant(value) != 0;
|
||||||
@ -829,19 +1064,9 @@ pub const Value = opaque {
|
|||||||
return @ptrCast(value);
|
return @ptrCast(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_calling_convention(value: *Value) CallingConvention {
|
pub fn to_global_variable(value: *Value) *GlobalVariable {
|
||||||
const kind = value.get_kind();
|
assert(value.get_kind() == .GlobalVariable);
|
||||||
switch (kind) {
|
return @ptrCast(value);
|
||||||
.Instruction => {
|
|
||||||
const call = value.to_instruction().to_call();
|
|
||||||
return call.get_calling_convention();
|
|
||||||
},
|
|
||||||
.Function => {
|
|
||||||
const function = value.to_function();
|
|
||||||
return function.get_calling_convention();
|
|
||||||
},
|
|
||||||
else => unreachable,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Kind = enum(c_uint) {
|
pub const Kind = enum(c_uint) {
|
||||||
@ -884,14 +1109,35 @@ pub const Instruction = opaque {
|
|||||||
pub fn to_value(instruction: *Instruction) *Value {
|
pub fn to_value(instruction: *Instruction) *Value {
|
||||||
return @ptrCast(instruction);
|
return @ptrCast(instruction);
|
||||||
}
|
}
|
||||||
pub fn to_call(instruction: *Instruction) *Instruction.Call {
|
|
||||||
assert(instruction.to_value().is_call_instruction() != null);
|
pub fn to_call_base(instruction: *Instruction) *Instruction.CallBase {
|
||||||
|
assert(instruction.is_call_base());
|
||||||
return @ptrCast(instruction);
|
return @ptrCast(instruction);
|
||||||
}
|
}
|
||||||
pub const Call = opaque {
|
|
||||||
|
pub const is_call_base = api.llvm_instruction_is_call_base;
|
||||||
|
|
||||||
|
pub const erase_from_parent = api.LLVMInstructionEraseFromParent;
|
||||||
|
pub const get_parent = api.LLVMGetInstructionParent;
|
||||||
|
|
||||||
|
pub const Branch = opaque {
|
||||||
|
pub const is_conditional = api.LLVMIsConditional;
|
||||||
|
pub const get_successor = api.LLVMGetSuccessor;
|
||||||
|
|
||||||
|
pub fn to_instruction(branch: *Branch) *Instruction {
|
||||||
|
return @ptrCast(branch);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const CallBase = opaque {
|
||||||
pub const set_calling_convention = api.LLVMSetInstructionCallConv;
|
pub const set_calling_convention = api.LLVMSetInstructionCallConv;
|
||||||
pub const get_calling_convention = api.LLVMGetInstructionCallConv;
|
pub const set_attributes = api.llvm_call_base_set_attributes;
|
||||||
pub const add_attribute = api.LLVMAddCallSiteAttribute;
|
};
|
||||||
|
|
||||||
|
pub const Store = opaque {
|
||||||
|
pub fn to_instruction(store: *Store) *Instruction {
|
||||||
|
return @ptrCast(store);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -999,6 +1245,10 @@ pub const DI = struct {
|
|||||||
pub const Record = opaque {};
|
pub const Record = opaque {};
|
||||||
|
|
||||||
pub const Type = opaque {
|
pub const Type = opaque {
|
||||||
|
// TODO: typecheck
|
||||||
|
pub fn to_subroutine(ty: *DI.Type) *Subroutine {
|
||||||
|
return @ptrCast(ty);
|
||||||
|
}
|
||||||
pub const Subroutine = opaque {
|
pub const Subroutine = opaque {
|
||||||
pub fn to_type(subroutine: *Subroutine) *DI.Type {
|
pub fn to_type(subroutine: *Subroutine) *DI.Type {
|
||||||
return @ptrCast(subroutine);
|
return @ptrCast(subroutine);
|
||||||
@ -1126,6 +1376,10 @@ pub const Type = opaque {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const Struct = opaque {
|
pub const Struct = opaque {
|
||||||
|
pub fn get_constant(struct_type: *Type.Struct, constant_values: []const *Constant) *Constant {
|
||||||
|
return api.LLVMConstNamedStruct(struct_type, constant_values.ptr, @intCast(constant_values.len));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn to_type(struct_type: *Type.Struct) *Type {
|
pub fn to_type(struct_type: *Type.Struct) *Type {
|
||||||
return @ptrCast(struct_type);
|
return @ptrCast(struct_type);
|
||||||
}
|
}
|
||||||
@ -1152,9 +1406,12 @@ pub const Type = opaque {
|
|||||||
return api.LLVMArrayType2(element_type, element_count);
|
return api.LLVMArrayType2(element_type, element_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_constant_array(element_type: *Type, values: []const *Constant) *Constant.Array {
|
pub fn get_constant_array(element_type: *Type, values: []const *Constant) *Constant {
|
||||||
return api.LLVMConstArray2(element_type, values.ptr, values.len);
|
return api.LLVMConstArray2(element_type, values.ptr, values.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const get_size = api.LLVMSizeOf;
|
||||||
|
pub const get_alignment = api.LLVMAlignOf;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Dwarf = struct {
|
pub const Dwarf = struct {
|
||||||
@ -1285,9 +1542,9 @@ pub fn lookup_intrinsic_id(name: []const u8) Intrinsic.Id {
|
|||||||
return api.LLVMLookupIntrinsicID(name.ptr, name.len);
|
return api.LLVMLookupIntrinsicID(name.ptr, name.len);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_attribute_kind(name: []const u8) Attribute.Kind {
|
// pub fn lookup_attribute_kind(name: []const u8) Attribute.Kind {
|
||||||
return api.LLVMGetEnumAttributeKindForName(name.ptr, name.len);
|
// return api.LLVMGetEnumAttributeKindForName(name.ptr, name.len);
|
||||||
}
|
// }
|
||||||
|
|
||||||
pub const IntPredicate = enum(c_int) {
|
pub const IntPredicate = enum(c_int) {
|
||||||
eq = 32,
|
eq = 32,
|
||||||
@ -1429,14 +1686,14 @@ pub const ObjectGenerate = struct {
|
|||||||
path: []const u8,
|
path: []const u8,
|
||||||
optimization_level: ?OptimizationLevel,
|
optimization_level: ?OptimizationLevel,
|
||||||
debug_info: bool,
|
debug_info: bool,
|
||||||
optimize_when_possible: u1,
|
optimize_when_possible: bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn object_generate(module: *Module, target_machine: *Target.Machine, generate: ObjectGenerate) CodeGenerationPipelineResult {
|
pub fn object_generate(module: *Module, target_machine: *Target.Machine, generate: ObjectGenerate) CodeGenerationPipelineResult {
|
||||||
module.set_target(target_machine);
|
module.set_target(target_machine);
|
||||||
|
|
||||||
if (generate.optimization_level) |optimization_level| {
|
if (generate.optimization_level) |optimization_level| {
|
||||||
module.run_optimization_pipeline(target_machine, OptimizationPipelineOptions.default(.{ .optimization_level = optimization_level, .debug_info = @intFromBool(generate.debug_info) }));
|
module.run_optimization_pipeline(target_machine, OptimizationPipelineOptions.default(.{ .optimization_level = optimization_level, .debug_info = generate.debug_info }));
|
||||||
}
|
}
|
||||||
|
|
||||||
// const mod_string = module.to_string();
|
// const mod_string = module.to_string();
|
||||||
@ -1448,7 +1705,7 @@ pub fn object_generate(module: *Module, target_machine: *Target.Machine, generat
|
|||||||
.flags = .{
|
.flags = .{
|
||||||
.code_generation_file_type = .object_file,
|
.code_generation_file_type = .object_file,
|
||||||
.optimize_when_possible = generate.optimize_when_possible,
|
.optimize_when_possible = generate.optimize_when_possible,
|
||||||
.verify_module = 1,
|
.verify_module = true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
3627
src/converter.zig
3627
src/converter.zig
File diff suppressed because it is too large
Load Diff
@ -22,7 +22,7 @@ fn invoke(name: []const u8) !void {
|
|||||||
|
|
||||||
inline for (@typeInfo(BuildMode).@"enum".fields) |f| {
|
inline for (@typeInfo(BuildMode).@"enum".fields) |f| {
|
||||||
const build_mode = @field(BuildMode, f.name);
|
const build_mode = @field(BuildMode, f.name);
|
||||||
inline for ([2]bool{ false, true }) |has_debug_info| {
|
inline for ([2]bool{ true, false }) |has_debug_info| {
|
||||||
// Bootstrap
|
// Bootstrap
|
||||||
{
|
{
|
||||||
var tmp_dir = std.testing.tmpDir(.{});
|
var tmp_dir = std.testing.tmpDir(.{});
|
||||||
@ -329,6 +329,30 @@ test "c_struct_with_array" {
|
|||||||
try invsrc(@src());
|
try invsrc(@src());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "indirect" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
|
||||||
|
test "indirect_struct" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
|
||||||
|
test "u1_return" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
|
||||||
|
test "small_struct_ints" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
|
||||||
|
test "c_med_struct_ints" {
|
||||||
|
try invsrc(@src());
|
||||||
|
}
|
||||||
|
|
||||||
test "c_abi" {
|
test "c_abi" {
|
||||||
try invsrc(@src());
|
try invsrc(@src());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test "varargs" {
|
||||||
|
// try invsrc(@src());
|
||||||
|
// }
|
||||||
|
21
src/lib.zig
21
src/lib.zig
@ -122,7 +122,6 @@ pub const file = struct {
|
|||||||
}, .{
|
}, .{
|
||||||
.read = 1,
|
.read = 1,
|
||||||
});
|
});
|
||||||
defer fd.close();
|
|
||||||
var result: []u8 = undefined;
|
var result: []u8 = undefined;
|
||||||
const ptr = @as(*[2]u64, @ptrCast(&result));
|
const ptr = @as(*[2]u64, @ptrCast(&result));
|
||||||
ptr[0] = 0;
|
ptr[0] = 0;
|
||||||
@ -133,6 +132,7 @@ pub const file = struct {
|
|||||||
const file_buffer = arena.allocate_bytes(file_size, 1);
|
const file_buffer = arena.allocate_bytes(file_size, 1);
|
||||||
result = file_buffer[0..file_size];
|
result = file_buffer[0..file_size];
|
||||||
fd.read(result, file_size);
|
fd.read(result, file_size);
|
||||||
|
fd.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@ -2504,7 +2504,18 @@ pub fn format_va(buffer: []u8, format_string: [*:0]const u8, variable_arguments:
|
|||||||
switch (next_ch) {
|
switch (next_ch) {
|
||||||
left_brace => os.abort(),
|
left_brace => os.abort(),
|
||||||
'c' => {
|
'c' => {
|
||||||
os.abort();
|
read_byte_count += 1;
|
||||||
|
assert(format_string[read_byte_count] == 's');
|
||||||
|
read_byte_count += 1;
|
||||||
|
assert(format_string[read_byte_count] == 't');
|
||||||
|
read_byte_count += 1;
|
||||||
|
assert(format_string[read_byte_count] == 'r');
|
||||||
|
read_byte_count += 1;
|
||||||
|
|
||||||
|
const c_string = @cVaArg(variable_arguments, [*:0]const u8);
|
||||||
|
const str = cstring.to_slice(c_string);
|
||||||
|
@memcpy(buffer[written_byte_count..][0..str.len], str);
|
||||||
|
written_byte_count += str.len;
|
||||||
},
|
},
|
||||||
'f' => {
|
'f' => {
|
||||||
os.abort();
|
os.abort();
|
||||||
@ -2653,12 +2664,12 @@ test "parse integer hexadecimal" {
|
|||||||
|
|
||||||
fn vprint(format_string: [*:0]const u8, args: *VariableArguments) void {
|
fn vprint(format_string: [*:0]const u8, args: *VariableArguments) void {
|
||||||
var buffer: [16 * 1024]u8 = undefined;
|
var buffer: [16 * 1024]u8 = undefined;
|
||||||
const slice = format_va(&buffer, format_string, args);
|
const byte_count = format_va(&buffer, format_string, args);
|
||||||
print_string(slice);
|
print_string(buffer[0..byte_count]);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn print(format_string: [*:0]const u8, ...) callconv(.C) void {
|
pub fn print(format_string: [*:0]const u8, ...) callconv(.C) void {
|
||||||
const args = @cVaStart();
|
var args = @cVaStart();
|
||||||
vprint(format_string, &args);
|
vprint(format_string, &args);
|
||||||
@cVaEnd(&args);
|
@cVaEnd(&args);
|
||||||
}
|
}
|
||||||
|
822
src/llvm.cpp
822
src/llvm.cpp
@ -7,6 +7,7 @@ typedef uint64_t u64;
|
|||||||
|
|
||||||
#define EXPORT extern "C"
|
#define EXPORT extern "C"
|
||||||
#define fn static
|
#define fn static
|
||||||
|
#define array_length(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
#include "llvm/Config/llvm-config.h"
|
#include "llvm/Config/llvm-config.h"
|
||||||
|
|
||||||
@ -70,6 +71,11 @@ EXPORT void llvm_global_variable_add_debug_info(GlobalVariable& global_variable,
|
|||||||
global_variable.addDebugInfo(debug_global_variable);
|
global_variable.addDebugInfo(debug_global_variable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT void llvm_global_variable_delete(GlobalVariable* global_variable)
|
||||||
|
{
|
||||||
|
delete global_variable;
|
||||||
|
}
|
||||||
|
|
||||||
EXPORT Function* llvm_module_create_function(Module* module, FunctionType* function_type, GlobalValue::LinkageTypes linkage_type, unsigned address_space, BBLLVMString name)
|
EXPORT Function* llvm_module_create_function(Module* module, FunctionType* function_type, GlobalValue::LinkageTypes linkage_type, unsigned address_space, BBLLVMString name)
|
||||||
{
|
{
|
||||||
auto* function = Function::Create(function_type, linkage_type, address_space, name.string_ref(), module);
|
auto* function = Function::Create(function_type, linkage_type, address_space, name.string_ref(), module);
|
||||||
@ -102,6 +108,102 @@ EXPORT BasicBlock* llvm_context_create_basic_block(LLVMContext& context, BBLLVMS
|
|||||||
return basic_block;
|
return basic_block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EXPORT bool llvm_value_has_one_use(Value& value)
|
||||||
|
{
|
||||||
|
auto result = value.hasOneUse();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT Value* llvm_basic_block_user_begin(BasicBlock* basic_block)
|
||||||
|
{
|
||||||
|
Value* value = *basic_block->user_begin();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void llvm_basic_block_delete(BasicBlock* basic_block)
|
||||||
|
{
|
||||||
|
delete basic_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT BranchInst* llvm_value_to_branch(Value* value)
|
||||||
|
{
|
||||||
|
auto* result = dyn_cast<BranchInst>(value);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are multiple uses of the return-value slot, just check
|
||||||
|
// for something immediately preceding the IP. Sometimes this can
|
||||||
|
// happen with how we generate implicit-returns; it can also happen
|
||||||
|
// with noreturn cleanups.
|
||||||
|
fn StoreInst* get_store_if_valid(User* user, Value* return_alloca, Type* element_type)
|
||||||
|
{
|
||||||
|
auto *SI = dyn_cast<llvm::StoreInst>(user);
|
||||||
|
if (!SI || SI->getPointerOperand() != return_alloca ||
|
||||||
|
SI->getValueOperand()->getType() != element_type)
|
||||||
|
return nullptr;
|
||||||
|
// These aren't actually possible for non-coerced returns, and we
|
||||||
|
// only care about non-coerced returns on this code path.
|
||||||
|
// All memory instructions inside __try block are volatile.
|
||||||
|
assert(!SI->isAtomic() &&
|
||||||
|
(!SI->isVolatile()
|
||||||
|
//|| CGF.currentFunctionUsesSEHTry())
|
||||||
|
));
|
||||||
|
return SI;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy of static llvm::StoreInst *findDominatingStoreToReturnValue(CodeGenFunction &CGF) {
|
||||||
|
// in clang/lib/CodeGen/CGCall.cpp:3526 in LLVM 19
|
||||||
|
EXPORT StoreInst* llvm_find_return_value_dominating_store(IRBuilder<>& builder, Value* return_alloca, Type* element_type)
|
||||||
|
{
|
||||||
|
// Check if a User is a store which pointerOperand is the ReturnValue.
|
||||||
|
// We are looking for stores to the ReturnValue, not for stores of the
|
||||||
|
// ReturnValue to some other location.
|
||||||
|
if (!return_alloca->hasOneUse()) {
|
||||||
|
llvm::BasicBlock *IP = builder.GetInsertBlock();
|
||||||
|
if (IP->empty()) return nullptr;
|
||||||
|
|
||||||
|
// Look at directly preceding instruction, skipping bitcasts and lifetime
|
||||||
|
// markers.
|
||||||
|
for (llvm::Instruction &I : make_range(IP->rbegin(), IP->rend())) {
|
||||||
|
if (isa<llvm::BitCastInst>(&I))
|
||||||
|
continue;
|
||||||
|
if (auto *II = dyn_cast<llvm::IntrinsicInst>(&I))
|
||||||
|
if (II->getIntrinsicID() == llvm::Intrinsic::lifetime_end)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return get_store_if_valid(&I, return_alloca, element_type);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
llvm::StoreInst *store = get_store_if_valid(return_alloca->user_back(), return_alloca, element_type);
|
||||||
|
if (!store) return nullptr;
|
||||||
|
|
||||||
|
// Now do a first-and-dirty dominance check: just walk up the
|
||||||
|
// single-predecessors chain from the current insertion point.
|
||||||
|
llvm::BasicBlock *StoreBB = store->getParent();
|
||||||
|
llvm::BasicBlock *IP = builder.GetInsertBlock();
|
||||||
|
llvm::SmallPtrSet<llvm::BasicBlock *, 4> SeenBBs;
|
||||||
|
while (IP != StoreBB) {
|
||||||
|
if (!SeenBBs.insert(IP).second || !(IP = IP->getSinglePredecessor()))
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Okay, the store's basic block dominates the insertion point; we
|
||||||
|
// can do our thing.
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT bool llvm_value_use_empty(Value& value)
|
||||||
|
{
|
||||||
|
return value.use_empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT bool llvm_basic_block_is_empty(BasicBlock& basic_block)
|
||||||
|
{
|
||||||
|
return basic_block.empty();
|
||||||
|
}
|
||||||
|
|
||||||
EXPORT AllocaInst* llvm_builder_create_alloca(IRBuilder<>& builder, Type* type, unsigned address_space, BBLLVMString name)
|
EXPORT AllocaInst* llvm_builder_create_alloca(IRBuilder<>& builder, Type* type, unsigned address_space, BBLLVMString name)
|
||||||
{
|
{
|
||||||
const DataLayout &data_layout = builder.GetInsertBlock()->getDataLayout();
|
const DataLayout &data_layout = builder.GetInsertBlock()->getDataLayout();
|
||||||
@ -109,6 +211,721 @@ EXPORT AllocaInst* llvm_builder_create_alloca(IRBuilder<>& builder, Type* type,
|
|||||||
return builder.Insert(new AllocaInst(type, address_space, 0, alignment), name.string_ref());
|
return builder.Insert(new AllocaInst(type, address_space, 0, alignment), name.string_ref());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class BBLLVMAttributeFramePointerKind : u8
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
Reserved = 1,
|
||||||
|
NonLeaf = 2,
|
||||||
|
All = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
const unsigned BB_LLVM_ONLY_USED = 1U << 1;
|
||||||
|
const unsigned BB_LLVM_ONLY_GPR = 1U << 2;
|
||||||
|
const unsigned BB_LLVM_ONLY_ARG = 1U << 3;
|
||||||
|
|
||||||
|
enum class BBLLVMZeroCallUsedRegsKind : unsigned int
|
||||||
|
{
|
||||||
|
// Don't zero any call-used regs.
|
||||||
|
Skip = 1U << 0,
|
||||||
|
// Only zeros call-used GPRs used in the fn and pass args.
|
||||||
|
UsedGPRArg = BB_LLVM_ONLY_USED | BB_LLVM_ONLY_GPR | BB_LLVM_ONLY_ARG,
|
||||||
|
// Only zeros call-used GPRs used in the fn.
|
||||||
|
UsedGPR = BB_LLVM_ONLY_USED | BB_LLVM_ONLY_GPR,
|
||||||
|
// Only zeros call-used regs used in the fn and pass args.
|
||||||
|
UsedArg = BB_LLVM_ONLY_USED | BB_LLVM_ONLY_ARG,
|
||||||
|
// Only zeros call-used regs used in the fn.
|
||||||
|
Used = BB_LLVM_ONLY_USED,
|
||||||
|
// Zeros all call-used GPRs that pass args.
|
||||||
|
AllGPRArg = BB_LLVM_ONLY_GPR | BB_LLVM_ONLY_ARG,
|
||||||
|
// Zeros all call-used GPRs.
|
||||||
|
AllGPR = BB_LLVM_ONLY_GPR,
|
||||||
|
// Zeros all call-used regs that pass args.
|
||||||
|
AllArg = BB_LLVM_ONLY_ARG,
|
||||||
|
// Zeros all call-used regs.
|
||||||
|
All = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BBLLVMFPClassTest : unsigned
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
|
||||||
|
SNan = 0x0001,
|
||||||
|
QNan = 0x0002,
|
||||||
|
NegInf = 0x0004,
|
||||||
|
NegNormal = 0x0008,
|
||||||
|
NegSubnormal = 0x0010,
|
||||||
|
NegZero = 0x0020,
|
||||||
|
PosZero = 0x0040,
|
||||||
|
PosSubnormal = 0x0080,
|
||||||
|
PosNormal = 0x0100,
|
||||||
|
PosInf = 0x0200,
|
||||||
|
|
||||||
|
Nan = SNan | QNan,
|
||||||
|
Inf = PosInf | NegInf,
|
||||||
|
Normal = PosNormal | NegNormal,
|
||||||
|
Subnormal = PosSubnormal | NegSubnormal,
|
||||||
|
Zero = PosZero | NegZero,
|
||||||
|
PosFinite = PosNormal | PosSubnormal | PosZero,
|
||||||
|
NegFinite = NegNormal | NegSubnormal | NegZero,
|
||||||
|
Finite = PosFinite | NegFinite,
|
||||||
|
Positive = PosFinite | PosInf,
|
||||||
|
Negative = NegFinite | NegInf,
|
||||||
|
|
||||||
|
AllFlags = Nan | Inf | Finite,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class BBLLVMUWTableKind
|
||||||
|
{
|
||||||
|
None = 0, ///< No unwind table requested
|
||||||
|
Sync = 1, ///< "Synchronous" unwind tables
|
||||||
|
Async = 2, ///< "Asynchronous" unwind tables (instr precise)
|
||||||
|
Default = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BBLLVMArgumentAttributes
|
||||||
|
{
|
||||||
|
Type* semantic_type;
|
||||||
|
Type* abi_type;
|
||||||
|
u64 dereferenceable_bytes;
|
||||||
|
u32 alignment;
|
||||||
|
u32 no_alias:1;
|
||||||
|
u32 non_null:1;
|
||||||
|
u32 no_undef:1;
|
||||||
|
u32 sign_extend:1;
|
||||||
|
u32 zero_extend:1;
|
||||||
|
u32 in_reg:1;
|
||||||
|
u32 no_fp_class:10;
|
||||||
|
u32 struct_return:1;
|
||||||
|
u32 writable:1;
|
||||||
|
u32 dead_on_unwind:1;
|
||||||
|
u32 in_alloca:1;
|
||||||
|
u32 dereferenceable:1;
|
||||||
|
u32 dereferenceable_or_null:1;
|
||||||
|
u32 nest:1;
|
||||||
|
u32 by_value:1;
|
||||||
|
u32 by_reference:1;
|
||||||
|
u32 no_capture:1;
|
||||||
|
u32 _:6;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(BBLLVMArgumentAttributes) == 2 * sizeof(Type*) + 2 * sizeof(u64));
|
||||||
|
|
||||||
|
fn AttributeSet build_argument_attributes(LLVMContext& context, const BBLLVMArgumentAttributes& attributes)
|
||||||
|
{
|
||||||
|
AttrBuilder builder(context);
|
||||||
|
|
||||||
|
if (attributes.alignment)
|
||||||
|
{
|
||||||
|
builder.addAlignmentAttr(attributes.alignment);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.no_alias)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::NoAlias);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.non_null)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::NonNull);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.no_undef)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::NoUndef);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.sign_extend)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::SExt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.zero_extend)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::ZExt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.in_reg)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::InReg);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.no_fp_class)
|
||||||
|
{
|
||||||
|
__builtin_trap(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.struct_return)
|
||||||
|
{
|
||||||
|
builder.addStructRetAttr(attributes.semantic_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.writable)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::Writable);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.dead_on_unwind)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::DeadOnUnwind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.in_alloca)
|
||||||
|
{
|
||||||
|
__builtin_trap(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.dereferenceable)
|
||||||
|
{
|
||||||
|
builder.addDereferenceableAttr(attributes.dereferenceable_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.dereferenceable_or_null)
|
||||||
|
{
|
||||||
|
builder.addDereferenceableOrNullAttr(attributes.dereferenceable_bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.nest)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::Nest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.by_value)
|
||||||
|
{
|
||||||
|
builder.addByValAttr(attributes.semantic_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.by_reference)
|
||||||
|
{
|
||||||
|
builder.addByRefAttr(attributes.semantic_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.no_capture)
|
||||||
|
{
|
||||||
|
builder.addAttribute(Attribute::NoCapture);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto attribute_set = AttributeSet::get(context, builder);
|
||||||
|
return attribute_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct BBLLVMFunctionAttributesFlags0
|
||||||
|
{
|
||||||
|
u64 noreturn:1;
|
||||||
|
u64 cmse_ns_call:1;
|
||||||
|
u64 nounwind:1;
|
||||||
|
u64 returns_twice:1;
|
||||||
|
u64 cold:1;
|
||||||
|
u64 hot:1;
|
||||||
|
u64 no_duplicate:1;
|
||||||
|
u64 convergent:1;
|
||||||
|
u64 no_merge:1;
|
||||||
|
u64 will_return:1;
|
||||||
|
u64 no_caller_saved_registers:1;
|
||||||
|
u64 no_cf_check:1;
|
||||||
|
u64 no_callback:1;
|
||||||
|
u64 alloc_size:1;
|
||||||
|
u64 uniform_work_group_size:1;
|
||||||
|
u64 aarch64_pstate_sm_body:1;
|
||||||
|
u64 aarch64_pstate_sm_enabled:1;
|
||||||
|
u64 aarch64_pstate_sm_compatible:1;
|
||||||
|
u64 aarch64_preserves_za:1;
|
||||||
|
u64 aarch64_in_za:1;
|
||||||
|
u64 aarch64_out_za:1;
|
||||||
|
u64 aarch64_inout_za:1;
|
||||||
|
u64 aarch64_preserves_zt0:1;
|
||||||
|
u64 aarch64_in_zt0:1;
|
||||||
|
u64 aarch64_out_zt0:1;
|
||||||
|
u64 aarch64_inout_zt0:1;
|
||||||
|
u64 optimize_for_size:1;
|
||||||
|
u64 min_size:1;
|
||||||
|
u64 no_red_zone:1;
|
||||||
|
u64 indirect_tls_seg_refs:1;
|
||||||
|
u64 no_implicit_floats:1;
|
||||||
|
u64 sample_profile_suffix_elision_policy:1;
|
||||||
|
u64 memory_none:1;
|
||||||
|
u64 memory_readonly:1;
|
||||||
|
u64 memory_inaccessible_or_arg_memory_only:1;
|
||||||
|
u64 memory_arg_memory_only:1;
|
||||||
|
u64 strict_fp:1;
|
||||||
|
u64 no_inline:1;
|
||||||
|
u64 always_inline:1;
|
||||||
|
u64 guard_no_cf:1;
|
||||||
|
|
||||||
|
// TODO: branch protection function attributes
|
||||||
|
// TODO: cpu features
|
||||||
|
|
||||||
|
// Call-site begin
|
||||||
|
u64 call_no_builtins:1;
|
||||||
|
|
||||||
|
u64 definition_frame_pointer_kind:2;
|
||||||
|
u64 definition_less_precise_fpmad:1;
|
||||||
|
u64 definition_null_pointer_is_valid:1;
|
||||||
|
u64 definition_no_trapping_fp_math:1;
|
||||||
|
u64 definition_no_infs_fp_math:1;
|
||||||
|
u64 definition_no_nans_fp_math:1;
|
||||||
|
u64 definition_approx_func_fp_math:1;
|
||||||
|
u64 definition_unsafe_fp_math:1;
|
||||||
|
u64 definition_use_soft_float:1;
|
||||||
|
u64 definition_no_signed_zeroes_fp_math:1;
|
||||||
|
u64 definition_stack_realignment:1;
|
||||||
|
u64 definition_backchain:1;
|
||||||
|
u64 definition_split_stack:1;
|
||||||
|
u64 definition_speculative_load_hardening:1;
|
||||||
|
u64 definition_zero_call_used_registers:4;
|
||||||
|
// TODO: denormal builtins
|
||||||
|
u64 definition_non_lazy_bind:1;
|
||||||
|
u64 definition_cmse_nonsecure_entry:1;
|
||||||
|
u64 definition_unwind_table_kind:2;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(BBLLVMFunctionAttributesFlags0) == sizeof(u64));
|
||||||
|
|
||||||
|
struct BBLLVMFunctionAttributesFlags1
|
||||||
|
{
|
||||||
|
u64 definition_disable_tail_calls:1;
|
||||||
|
u64 definition_stack_protect_strong:1;
|
||||||
|
u64 definition_stack_protect:1;
|
||||||
|
u64 definition_stack_protect_req:1;
|
||||||
|
u64 definition_aarch64_new_za:1;
|
||||||
|
u64 definition_aarch64_new_zt0:1;
|
||||||
|
u64 definition_optimize_none:1;
|
||||||
|
u64 definition_naked:1;
|
||||||
|
u64 definition_inline_hint:1;
|
||||||
|
u64 _:55;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(BBLLVMFunctionAttributesFlags1) == sizeof(u64));
|
||||||
|
|
||||||
|
struct BBLLVMFunctionAttributes
|
||||||
|
{
|
||||||
|
BBLLVMString prefer_vector_width;
|
||||||
|
BBLLVMString stack_protector_buffer_size;
|
||||||
|
BBLLVMString definition_probe_stack;
|
||||||
|
BBLLVMString definition_stack_probe_size;
|
||||||
|
|
||||||
|
BBLLVMFunctionAttributesFlags0 flags0;
|
||||||
|
BBLLVMFunctionAttributesFlags1 flags1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(BBLLVMFunctionAttributes) == 10 * sizeof(u64));
|
||||||
|
|
||||||
|
struct BBLLVMAttributeList
|
||||||
|
{
|
||||||
|
BBLLVMFunctionAttributes function;
|
||||||
|
BBLLVMArgumentAttributes return_;
|
||||||
|
const BBLLVMArgumentAttributes* argument_pointer;
|
||||||
|
u64 argument_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(BBLLVMAttributeList) == sizeof(BBLLVMFunctionAttributes) + sizeof(BBLLVMArgumentAttributes) + sizeof(void*) + sizeof(u64));
|
||||||
|
|
||||||
|
typedef void* BBLLVMAttributeListHandle;
|
||||||
|
|
||||||
|
EXPORT BBLLVMAttributeListHandle llvm_attribute_list_build(LLVMContext& context, const BBLLVMAttributeList& attributes, bool call_site)
|
||||||
|
{
|
||||||
|
AttrBuilder function_attribute_builder(context);
|
||||||
|
|
||||||
|
if (attributes.function.prefer_vector_width.length)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("prefer-vector-width", attributes.function.prefer_vector_width.string_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.stack_protector_buffer_size.length)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("stack-protector-buffer-size", attributes.function.stack_protector_buffer_size.string_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.noreturn)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.cmse_ns_call)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("cmse_nonsecure_call");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.nounwind)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoUnwind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.returns_twice)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::ReturnsTwice);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.cold)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::Cold);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.hot)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::Hot);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.no_duplicate)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoDuplicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.convergent)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::Convergent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.no_merge)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoMerge);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.will_return)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::WillReturn);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.no_caller_saved_registers)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("no-caller-saved-registers");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.no_cf_check)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoCfCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.no_callback)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.alloc_size)
|
||||||
|
{
|
||||||
|
__builtin_trap(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.uniform_work_group_size)
|
||||||
|
{
|
||||||
|
__builtin_trap(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_pstate_sm_body)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_pstate_sm_body");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_pstate_sm_enabled)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_pstate_sm_enabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_pstate_sm_compatible)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_pstate_sm_compatible");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_preserves_za)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_preserves_za");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_in_za)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_in_za");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_out_za)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_out_za");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_inout_za)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_inout_za");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_preserves_zt0)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_preserves_zt0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_in_zt0)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_in_zt0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_out_zt0)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_out_zt0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.aarch64_inout_zt0)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_inout_zt0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.optimize_for_size)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::OptimizeForSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.min_size)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::MinSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.no_red_zone)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoRedZone);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.indirect_tls_seg_refs)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("indirect-tls-seg-refs");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.no_implicit_floats)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoImplicitFloat);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.sample_profile_suffix_elision_policy)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("sample-profile-suffix-elision-policy", "selected");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.memory_none)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addMemoryAttr(llvm::MemoryEffects::none());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.memory_readonly)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addMemoryAttr(llvm::MemoryEffects::readOnly());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.memory_inaccessible_or_arg_memory_only)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addMemoryAttr(llvm::MemoryEffects::inaccessibleOrArgMemOnly());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.memory_arg_memory_only)
|
||||||
|
{
|
||||||
|
Attribute attribute = function_attribute_builder.getAttribute(Attribute::Memory);
|
||||||
|
function_attribute_builder.addMemoryAttr(attribute.getMemoryEffects() | llvm::MemoryEffects::argMemOnly());
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: branch protection function attributes
|
||||||
|
|
||||||
|
// TODO: cpu features
|
||||||
|
|
||||||
|
if (call_site)
|
||||||
|
{
|
||||||
|
if (attributes.function.flags0.call_no_builtins)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NoBuiltin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (attributes.function.definition_probe_stack.length)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("probe-stack", attributes.function.definition_probe_stack.string_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.definition_stack_probe_size.length)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("stack-probe-size", attributes.function.definition_stack_probe_size.string_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
StringRef frame_pointer_kind_name;
|
||||||
|
switch ((BBLLVMAttributeFramePointerKind) attributes.function.flags0.definition_frame_pointer_kind)
|
||||||
|
{
|
||||||
|
case BBLLVMAttributeFramePointerKind::None: frame_pointer_kind_name = "none"; break;
|
||||||
|
case BBLLVMAttributeFramePointerKind::Reserved: frame_pointer_kind_name = "reserved"; break;
|
||||||
|
case BBLLVMAttributeFramePointerKind::NonLeaf: frame_pointer_kind_name = "non-leaf"; break;
|
||||||
|
case BBLLVMAttributeFramePointerKind::All: frame_pointer_kind_name = "all"; break;
|
||||||
|
}
|
||||||
|
function_attribute_builder.addAttribute("frame-pointer", frame_pointer_kind_name);
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_less_precise_fpmad)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("less-precise-fp-mad", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_null_pointer_is_valid)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NullPointerIsValid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_no_trapping_fp_math)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("no-trapping-math", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_no_infs_fp_math)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("no-infs-fp-math", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_no_nans_fp_math)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("no-nans-fp-math", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_approx_func_fp_math)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("approx-func-fp-math", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_unsafe_fp_math)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("unsafe-fp-math", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_use_soft_float)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("use-soft-float", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_no_signed_zeroes_fp_math)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("no-signed-zeros-fp-math", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_stack_realignment)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("stackrealign");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_backchain)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("backchain");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_split_stack)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("split-stack");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_speculative_load_hardening)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("split-stack");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_zero_call_used_registers)
|
||||||
|
{
|
||||||
|
__builtin_trap(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: denormal builtins
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_non_lazy_bind)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::NonLazyBind);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags0.definition_cmse_nonsecure_entry)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("cmse_nonsecure_entry");
|
||||||
|
}
|
||||||
|
|
||||||
|
UWTableKind unwind_table_kind;
|
||||||
|
switch ((BBLLVMUWTableKind)attributes.function.flags0.definition_unwind_table_kind)
|
||||||
|
{
|
||||||
|
case BBLLVMUWTableKind::None: unwind_table_kind = UWTableKind::None; break;
|
||||||
|
case BBLLVMUWTableKind::Sync: unwind_table_kind = UWTableKind::Sync; break;
|
||||||
|
case BBLLVMUWTableKind::Async: unwind_table_kind = UWTableKind::Async; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
function_attribute_builder.addUWTableAttr(unwind_table_kind);
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_disable_tail_calls)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("disable-tail-calls", "true");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_stack_protect_strong)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::StackProtectStrong);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_stack_protect)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::StackProtect);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_stack_protect_req)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::StackProtectReq);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_aarch64_new_za)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_new_za");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_aarch64_new_zt0)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute("aarch64_new_zt0");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_optimize_none)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::OptimizeNone);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_naked)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::Naked);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attributes.function.flags1.definition_inline_hint)
|
||||||
|
{
|
||||||
|
function_attribute_builder.addAttribute(Attribute::InlineHint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto function_attributes = AttributeSet::get(context, function_attribute_builder);
|
||||||
|
|
||||||
|
auto return_attributes = build_argument_attributes(context, attributes.return_);
|
||||||
|
|
||||||
|
AttributeSet argument_attribute_buffer[128];
|
||||||
|
assert(attributes.argument_count < array_length(argument_attribute_buffer));
|
||||||
|
|
||||||
|
for (u64 i = 0; i < attributes.argument_count; i += 1)
|
||||||
|
{
|
||||||
|
auto attribute_set = build_argument_attributes(context, attributes.argument_pointer[i]);
|
||||||
|
argument_attribute_buffer[i] = attribute_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArrayRef<AttributeSet> argument_attributes = ArrayRef(argument_attribute_buffer, attributes.argument_count);
|
||||||
|
|
||||||
|
auto attribute_list = AttributeList::get(context, function_attributes, return_attributes, argument_attributes);
|
||||||
|
|
||||||
|
static_assert(sizeof(AttributeList) == sizeof(uintptr_t));
|
||||||
|
|
||||||
|
return *(BBLLVMAttributeListHandle*)&attribute_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT bool llvm_instruction_is_call_base(Instruction* instruction)
|
||||||
|
{
|
||||||
|
return isa<CallBase>(instruction);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void llvm_function_set_attributes(Function& function, BBLLVMAttributeListHandle attribute_list_handle)
|
||||||
|
{
|
||||||
|
auto attribute_list = *(AttributeList*)&attribute_list_handle;
|
||||||
|
function.setAttributes(attribute_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void llvm_call_base_set_attributes(CallBase& call, BBLLVMAttributeListHandle attribute_list_handle)
|
||||||
|
{
|
||||||
|
auto attribute_list = *(AttributeList*)&attribute_list_handle;
|
||||||
|
call.setAttributes(attribute_list);
|
||||||
|
}
|
||||||
|
|
||||||
fn BBLLVMString stream_to_string(raw_string_ostream& stream)
|
fn BBLLVMString stream_to_string(raw_string_ostream& stream)
|
||||||
{
|
{
|
||||||
// No need to call stream.flush(); because it's string-based
|
// No need to call stream.flush(); because it's string-based
|
||||||
@ -150,7 +967,6 @@ EXPORT bool llvm_function_verify(Function& function, BBLLVMString* error_message
|
|||||||
return !result;
|
return !result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
EXPORT bool llvm_module_verify(const Module& module, BBLLVMString* error_message)
|
EXPORT bool llvm_module_verify(const Module& module, BBLLVMString* error_message)
|
||||||
{
|
{
|
||||||
std::string message_buffer;
|
std::string message_buffer;
|
||||||
@ -396,7 +1212,7 @@ struct BBLLVMTargetOptions
|
|||||||
u64 no_nans_fp_math:1;
|
u64 no_nans_fp_math:1;
|
||||||
u64 no_trapping_fp_math:1;
|
u64 no_trapping_fp_math:1;
|
||||||
u64 no_signed_zeroes_fp_math:1;
|
u64 no_signed_zeroes_fp_math:1;
|
||||||
u64 approx_func_fp_match:1;
|
u64 approx_func_fp_math:1;
|
||||||
u64 enable_aix_extended_altivec_abi:1;
|
u64 enable_aix_extended_altivec_abi:1;
|
||||||
u64 honor_sign_dependent_rounding_fp_math:1;
|
u64 honor_sign_dependent_rounding_fp_math:1;
|
||||||
u64 no_zeroes_in_bss:1;
|
u64 no_zeroes_in_bss:1;
|
||||||
@ -525,7 +1341,7 @@ EXPORT TargetMachine* llvm_create_target_machine(const BBLLVMTargetMachineCreate
|
|||||||
target_options.NoNaNsFPMath = create.target_options.no_nans_fp_math;
|
target_options.NoNaNsFPMath = create.target_options.no_nans_fp_math;
|
||||||
target_options.NoTrappingFPMath = create.target_options.no_trapping_fp_math;
|
target_options.NoTrappingFPMath = create.target_options.no_trapping_fp_math;
|
||||||
target_options.NoSignedZerosFPMath = create.target_options.no_signed_zeroes_fp_math;
|
target_options.NoSignedZerosFPMath = create.target_options.no_signed_zeroes_fp_math;
|
||||||
target_options.ApproxFuncFPMath = create.target_options.approx_func_fp_match;
|
target_options.ApproxFuncFPMath = create.target_options.approx_func_fp_math;
|
||||||
target_options.EnableAIXExtendedAltivecABI = create.target_options.enable_aix_extended_altivec_abi;
|
target_options.EnableAIXExtendedAltivecABI = create.target_options.enable_aix_extended_altivec_abi;
|
||||||
target_options.HonorSignDependentRoundingFPMathOption = create.target_options.honor_sign_dependent_rounding_fp_math;
|
target_options.HonorSignDependentRoundingFPMathOption = create.target_options.honor_sign_dependent_rounding_fp_math;
|
||||||
target_options.NoZerosInBSS = create.target_options.no_zeroes_in_bss;
|
target_options.NoZerosInBSS = create.target_options.no_zeroes_in_bss;
|
||||||
|
@ -7,21 +7,39 @@ pub extern fn llvm_context_create_module(context: *llvm.Context, name: llvm.Stri
|
|||||||
pub extern fn LLVMContextCreate() *llvm.Context;
|
pub extern fn LLVMContextCreate() *llvm.Context;
|
||||||
pub extern fn LLVMCreateBuilderInContext(context: *llvm.Context) *llvm.Builder;
|
pub extern fn LLVMCreateBuilderInContext(context: *llvm.Context) *llvm.Builder;
|
||||||
|
|
||||||
pub extern fn LLVMIsACallInst(value: *llvm.Value) ?*llvm.Instruction.Call;
|
pub extern fn LLVMGetOperand(value: *llvm.Value, index: c_uint) *llvm.Value;
|
||||||
pub extern fn LLVMSetAlignment(value: *llvm.Value, alignment: c_uint) void;
|
pub extern fn LLVMSetAlignment(value: *llvm.Value, alignment: c_uint) void;
|
||||||
|
pub extern fn llvm_instruction_is_call_base(instruction: *llvm.Instruction) bool;
|
||||||
|
|
||||||
// Module
|
// Module
|
||||||
pub extern fn llvm_module_create_global_variable(module: *llvm.Module, global_type: *llvm.Type, is_constant: bool, linkage: llvm.LinkageType, initial_value: *llvm.Constant, name: llvm.String, before: ?*llvm.GlobalVariable, thread_local_mode: llvm.ThreadLocalMode, address_space: c_uint, externally_initialized: bool) *llvm.GlobalVariable;
|
pub extern fn llvm_module_create_global_variable(module: *llvm.Module, global_type: *llvm.Type, is_constant: bool, linkage: llvm.LinkageType, initial_value: *llvm.Constant, name: llvm.String, before: ?*llvm.GlobalVariable, thread_local_mode: llvm.ThreadLocalMode, address_space: c_uint, externally_initialized: bool) *llvm.GlobalVariable;
|
||||||
pub extern fn llvm_module_create_function(module: *llvm.Module, function_type: *llvm.Type.Function, linkage_type: llvm.LinkageType, address_space: c_uint, name: llvm.String) *llvm.Function;
|
pub extern fn llvm_module_create_function(module: *llvm.Module, function_type: *llvm.Type.Function, linkage_type: llvm.LinkageType, address_space: c_uint, name: llvm.String) *llvm.Function;
|
||||||
pub extern fn llvm_context_create_basic_block(context: *llvm.Context, name: llvm.String, parent: *llvm.Function) *llvm.BasicBlock;
|
pub extern fn llvm_context_create_basic_block(context: *llvm.Context, name: llvm.String, parent: ?*llvm.Function) *llvm.BasicBlock;
|
||||||
|
pub extern fn LLVMGetNextBasicBlock(basic_block: *llvm.BasicBlock) ?*llvm.BasicBlock;
|
||||||
|
pub extern fn LLVMDeleteBasicBlock(basic_block: *llvm.BasicBlock) void;
|
||||||
|
pub extern fn LLVMGetLastBasicBlock(function: *llvm.Function) *llvm.BasicBlock;
|
||||||
|
pub extern fn LLVMGetBasicBlockParent(basic_block: *llvm.BasicBlock) ?*llvm.BasicBlock;
|
||||||
|
pub extern fn LLVMAppendExistingBasicBlock(function: *llvm.Function, basic_block: *llvm.BasicBlock) void;
|
||||||
|
|
||||||
|
pub extern fn LLVMSetValueName2(value: *llvm.Value, name_pointer: [*]const u8, name_length: usize) void;
|
||||||
|
pub extern fn llvm_value_use_empty(value: *llvm.Value) bool;
|
||||||
|
pub extern fn llvm_value_has_one_use(value: *llvm.Value) bool;
|
||||||
|
pub extern fn llvm_value_to_branch(value: ?*llvm.Value) ?*llvm.Instruction.Branch;
|
||||||
|
pub extern fn LLVMReplaceAllUsesWith(old: *llvm.Value, new: *llvm.Value) void;
|
||||||
|
|
||||||
|
pub extern fn LLVMGetSuccessor(branch: *llvm.Instruction.Branch, index: c_uint) *llvm.BasicBlock;
|
||||||
|
pub extern fn LLVMIsConditional(branch: *llvm.Instruction.Branch) bool;
|
||||||
|
pub extern fn LLVMGetInstructionParent(instruction: *llvm.Instruction) *llvm.BasicBlock;
|
||||||
|
|
||||||
|
pub extern fn llvm_basic_block_is_empty(basic_block: *llvm.BasicBlock) bool;
|
||||||
|
pub extern fn llvm_basic_block_user_begin(basic_block: *llvm.BasicBlock) ?*llvm.Value;
|
||||||
|
pub extern fn llvm_basic_block_delete(basic_block: *llvm.BasicBlock) void;
|
||||||
pub extern fn LLVMGetBasicBlockTerminator(basic_block: *llvm.BasicBlock) ?*llvm.Value;
|
pub extern fn LLVMGetBasicBlockTerminator(basic_block: *llvm.BasicBlock) ?*llvm.Value;
|
||||||
|
|
||||||
pub extern fn LLVMSetFunctionCallConv(function: *llvm.Function, calling_convention: llvm.CallingConvention) void;
|
pub extern fn LLVMSetFunctionCallConv(function: *llvm.Function, calling_convention: llvm.CallingConvention) void;
|
||||||
pub extern fn LLVMGetFunctionCallConv(function: *llvm.Function) llvm.CallingConvention;
|
pub extern fn LLVMGetFunctionCallConv(function: *llvm.Function) llvm.CallingConvention;
|
||||||
|
|
||||||
pub extern fn LLVMSetInstructionCallConv(instruction: *llvm.Instruction.Call, calling_convention: llvm.CallingConvention) void;
|
pub extern fn LLVMSetInstructionCallConv(instruction: *llvm.Instruction.CallBase, calling_convention: llvm.CallingConvention) void;
|
||||||
pub extern fn LLVMGetInstructionCallConv(instruction: *llvm.Instruction.Call) llvm.CallingConvention;
|
|
||||||
|
|
||||||
pub extern fn LLVMGetParams(function: *llvm.Function, argument_buffer: [*]*llvm.Argument) void;
|
pub extern fn LLVMGetParams(function: *llvm.Function, argument_buffer: [*]*llvm.Argument) void;
|
||||||
|
|
||||||
@ -33,7 +51,13 @@ pub extern fn llvm_module_to_string(module: *llvm.Module) llvm.String;
|
|||||||
|
|
||||||
// Builder API
|
// Builder API
|
||||||
pub extern fn LLVMPositionBuilderAtEnd(builder: *llvm.Builder, basic_block: *llvm.BasicBlock) void;
|
pub extern fn LLVMPositionBuilderAtEnd(builder: *llvm.Builder, basic_block: *llvm.BasicBlock) void;
|
||||||
pub extern fn LLVMGetInsertBlock(builder: *llvm.Builder) *llvm.BasicBlock;
|
pub extern fn LLVMClearInsertionPosition(builder: *llvm.Builder) void;
|
||||||
|
pub extern fn LLVMGetInsertBlock(builder: *llvm.Builder) ?*llvm.BasicBlock;
|
||||||
|
|
||||||
|
pub extern fn llvm_find_return_value_dominating_store(builder: *llvm.Builder, return_alloca: *llvm.Value, element_type: *llvm.Type) ?*llvm.Instruction.Store;
|
||||||
|
|
||||||
|
pub extern fn LLVMDeleteInstruction(instruction: *llvm.Instruction) void;
|
||||||
|
pub extern fn LLVMInstructionEraseFromParent(instruction: *llvm.Instruction) void;
|
||||||
|
|
||||||
pub extern fn LLVMBuildRet(builder: *llvm.Builder, value: ?*llvm.Value) void;
|
pub extern fn LLVMBuildRet(builder: *llvm.Builder, value: ?*llvm.Value) void;
|
||||||
pub extern fn LLVMBuildAdd(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildAdd(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
||||||
@ -50,6 +74,7 @@ pub extern fn LLVMBuildAnd(builder: *llvm.Builder, left: *llvm.Value, right: *ll
|
|||||||
pub extern fn LLVMBuildOr(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildOr(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildXor(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildXor(builder: *llvm.Builder, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildICmp(builder: *llvm.Builder, predicate: llvm.IntPredicate, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildICmp(builder: *llvm.Builder, predicate: llvm.IntPredicate, left: *llvm.Value, right: *llvm.Value, name: [*:0]const u8) *llvm.Value;
|
||||||
|
pub extern fn LLVMBuildBr(builder: *llvm.Builder, block: *llvm.BasicBlock) *llvm.Value;
|
||||||
pub extern fn LLVMBuildCondBr(builder: *llvm.Builder, condition: *llvm.Value, taken: *llvm.BasicBlock, not_taken: *llvm.BasicBlock) *llvm.Value;
|
pub extern fn LLVMBuildCondBr(builder: *llvm.Builder, condition: *llvm.Value, taken: *llvm.BasicBlock, not_taken: *llvm.BasicBlock) *llvm.Value;
|
||||||
|
|
||||||
pub extern fn llvm_builder_create_alloca(builder: *llvm.Builder, ty: *llvm.Type, address_space: c_uint, name: llvm.String) *llvm.Value;
|
pub extern fn llvm_builder_create_alloca(builder: *llvm.Builder, ty: *llvm.Type, address_space: c_uint, name: llvm.String) *llvm.Value;
|
||||||
@ -60,9 +85,12 @@ pub extern fn LLVMBuildStructGEP2(builder: *llvm.Builder, struct_type: *llvm.Typ
|
|||||||
pub extern fn LLVMBuildInBoundsGEP2(builder: *llvm.Builder, ty: *llvm.Type, aggregate: *llvm.Value, index_pointer: [*]const *llvm.Value, index_count: c_uint, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildInBoundsGEP2(builder: *llvm.Builder, ty: *llvm.Type, aggregate: *llvm.Value, index_pointer: [*]const *llvm.Value, index_count: c_uint, name: [*:0]const u8) *llvm.Value;
|
||||||
|
|
||||||
pub extern fn LLVMBuildInsertValue(builder: *llvm.Builder, aggregate: *llvm.Value, element: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildInsertValue(builder: *llvm.Builder, aggregate: *llvm.Value, element: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
||||||
|
pub extern fn LLVMBuildExtractValue(builder: *llvm.Builder, aggregate: *llvm.Value, index: c_uint, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildUnreachable(builder: *llvm.Builder) *llvm.Value;
|
pub extern fn LLVMBuildUnreachable(builder: *llvm.Builder) *llvm.Value;
|
||||||
pub extern fn LLVMBuildMemCpy(builder: *llvm.Builder, destination: *llvm.Value, destination_alignment: c_uint, source: *llvm.Value, source_alignment: c_uint, size: *llvm.Value) *llvm.Value;
|
pub extern fn LLVMBuildMemCpy(builder: *llvm.Builder, destination: *llvm.Value, destination_alignment: c_uint, source: *llvm.Value, source_alignment: c_uint, size: *llvm.Value) *llvm.Value;
|
||||||
|
|
||||||
|
pub extern fn LLVMBuildVAArg(builder: *llvm.Builder, va_list: *llvm.Value, arg_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
|
|
||||||
// Casts
|
// Casts
|
||||||
pub extern fn LLVMBuildZExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildZExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
pub extern fn LLVMBuildSExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
pub extern fn LLVMBuildSExt(builder: *llvm.Builder, value: *llvm.Value, destination_type: *llvm.Type, name: [*:0]const u8) *llvm.Value;
|
||||||
@ -73,7 +101,13 @@ pub extern fn LLVMBuildTrunc(builder: *llvm.Builder, value: *llvm.Value, destina
|
|||||||
pub extern fn LLVMSetCurrentDebugLocation2(builder: *llvm.Builder, location: ?*llvm.DI.Location) void;
|
pub extern fn LLVMSetCurrentDebugLocation2(builder: *llvm.Builder, location: ?*llvm.DI.Location) void;
|
||||||
|
|
||||||
pub extern fn LLVMTypeOf(value: *llvm.Value) *llvm.Type;
|
pub extern fn LLVMTypeOf(value: *llvm.Value) *llvm.Type;
|
||||||
|
pub extern fn LLVMSizeOf(ty: *llvm.Type) *llvm.Constant;
|
||||||
|
pub extern fn LLVMAlignOf(ty: *llvm.Type) *llvm.Constant;
|
||||||
pub extern fn LLVMGlobalGetValueType(value: *llvm.GlobalValue) *llvm.Type;
|
pub extern fn LLVMGlobalGetValueType(value: *llvm.GlobalValue) *llvm.Type;
|
||||||
|
pub extern fn LLVMGetInitializer(global_variable: *llvm.GlobalVariable) *llvm.Constant;
|
||||||
|
pub extern fn LLVMSetInitializer(global_variable: *llvm.GlobalVariable, initializer: *llvm.Constant) void;
|
||||||
|
pub extern fn LLVMDeleteGlobal(global_variable: *llvm.GlobalVariable) void;
|
||||||
|
pub extern fn llvm_global_variable_delete(global_variable: *llvm.GlobalVariable) void;
|
||||||
pub extern fn llvm_value_is_instruction(value: *llvm.Value) bool;
|
pub extern fn llvm_value_is_instruction(value: *llvm.Value) bool;
|
||||||
|
|
||||||
// Intrinsics
|
// Intrinsics
|
||||||
@ -82,15 +116,19 @@ pub extern fn LLVMGetIntrinsicDeclaration(module: *llvm.Module, intrinsic_id: ll
|
|||||||
pub extern fn LLVMIntrinsicGetType(context: *llvm.Context, intrinsic_id: llvm.Intrinsic.Id, parameter_type_pointer: [*]const *llvm.Type, parameter_type_count: usize) *llvm.Type.Function;
|
pub extern fn LLVMIntrinsicGetType(context: *llvm.Context, intrinsic_id: llvm.Intrinsic.Id, parameter_type_pointer: [*]const *llvm.Type, parameter_type_count: usize) *llvm.Type.Function;
|
||||||
|
|
||||||
// Attributes
|
// Attributes
|
||||||
pub extern fn LLVMGetEnumAttributeKindForName(name_pointer: [*]const u8, name_length: usize) llvm.Attribute.Kind;
|
pub extern fn llvm_attribute_list_build(context: *llvm.Context, options: *const llvm.Attribute.List.Options, call_site: bool) *llvm.Attribute.List;
|
||||||
|
pub extern fn llvm_function_set_attributes(function: *llvm.Function, attribute_list: *llvm.Attribute.List) void;
|
||||||
|
pub extern fn llvm_call_base_set_attributes(function: *llvm.Instruction.CallBase, attribute_list: *llvm.Attribute.List) void;
|
||||||
|
|
||||||
pub extern fn LLVMCreateEnumAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, value: u64) *llvm.Attribute;
|
// pub extern fn LLVMGetEnumAttributeKindForName(name_pointer: [*]const u8, name_length: usize) llvm.Attribute.Kind;
|
||||||
pub extern fn LLVMCreateTypeAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, ty: *llvm.Type) *llvm.Attribute;
|
//
|
||||||
pub extern fn LLVMCreateConstantRangeAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, bit_count: c_uint, lower_words: [*]const u64, upper_words: [*]const u64) *llvm.Attribute;
|
// pub extern fn LLVMCreateEnumAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, value: u64) *llvm.Attribute;
|
||||||
pub extern fn LLVMCreateStringAttribute(context: *llvm.Context, key_pointer: [*]const u8, key_length: c_uint, value_pointer: [*]const u8, value_length: usize) *llvm.Attribute;
|
// pub extern fn LLVMCreateTypeAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, ty: *llvm.Type) *llvm.Attribute;
|
||||||
|
// pub extern fn LLVMCreateConstantRangeAttribute(context: *llvm.Context, kind: llvm.Attribute.Kind, bit_count: c_uint, lower_words: [*]const u64, upper_words: [*]const u64) *llvm.Attribute;
|
||||||
pub extern fn LLVMAddAttributeAtIndex(function: *llvm.Function, attribute_index: llvm.Attribute.Index, attribute: *llvm.Attribute) void;
|
// pub extern fn LLVMCreateStringAttribute(context: *llvm.Context, key_pointer: [*]const u8, key_length: c_uint, value_pointer: [*]const u8, value_length: usize) *llvm.Attribute;
|
||||||
pub extern fn LLVMAddCallSiteAttribute(call: *llvm.Instruction.Call, attribute_index: llvm.Attribute.Index, attribute: *llvm.Attribute) void;
|
//
|
||||||
|
// pub extern fn LLVMAddAttributeAtIndex(function: *llvm.Function, attribute_index: llvm.Attribute.Index, attribute: *llvm.Attribute) void;
|
||||||
|
// pub extern fn LLVMAddCallSiteAttribute(call: *llvm.Instruction.Call, attribute_index: llvm.Attribute.Index, attribute: *llvm.Attribute) void;
|
||||||
|
|
||||||
// TYPES
|
// TYPES
|
||||||
// Types: integers
|
// Types: integers
|
||||||
@ -115,7 +153,7 @@ pub extern fn LLVMFunctionType(return_type: *llvm.Type, parameter_type_pointer:
|
|||||||
pub extern fn LLVMIsFunctionVarArg(function_type: *llvm.Type.Function) Bool;
|
pub extern fn LLVMIsFunctionVarArg(function_type: *llvm.Type.Function) Bool;
|
||||||
pub extern fn LLVMGetReturnType(function_type: *llvm.Type.Function) *llvm.Type;
|
pub extern fn LLVMGetReturnType(function_type: *llvm.Type.Function) *llvm.Type;
|
||||||
pub extern fn LLVMSetSubprogram(function: *llvm.Function, subprogram: *llvm.DI.Subprogram) void;
|
pub extern fn LLVMSetSubprogram(function: *llvm.Function, subprogram: *llvm.DI.Subprogram) void;
|
||||||
pub extern fn LLVMGetSubprogram(function: *llvm.Function) *llvm.DI.Subprogram;
|
pub extern fn LLVMGetSubprogram(function: *llvm.Function) ?*llvm.DI.Subprogram;
|
||||||
pub extern fn LLVMCountParamTypes(function_type: *llvm.Type.Function) c_uint;
|
pub extern fn LLVMCountParamTypes(function_type: *llvm.Type.Function) c_uint;
|
||||||
pub extern fn LLVMGetParamTypes(function_type: *llvm.Type.Function, types: [*]*llvm.Type) void;
|
pub extern fn LLVMGetParamTypes(function_type: *llvm.Type.Function, types: [*]*llvm.Type) void;
|
||||||
|
|
||||||
@ -142,7 +180,11 @@ pub extern fn llvm_integer_type_get_bit_count(integer_type: *llvm.Type.Integer)
|
|||||||
// VALUES
|
// VALUES
|
||||||
pub extern fn LLVMGetPoison(type: *llvm.Type) *llvm.Value;
|
pub extern fn LLVMGetPoison(type: *llvm.Type) *llvm.Value;
|
||||||
pub extern fn LLVMConstInt(type: *llvm.Type.Integer, value: c_ulonglong, sign_extend: Bool) *llvm.Constant.Integer;
|
pub extern fn LLVMConstInt(type: *llvm.Type.Integer, value: c_ulonglong, sign_extend: Bool) *llvm.Constant.Integer;
|
||||||
pub extern fn LLVMConstArray2(element_type: *llvm.Type, value_pointer: [*]const *llvm.Constant, value_length: u64) *llvm.Constant.Array;
|
pub extern fn LLVMConstIntGetZExtValue(constant: *llvm.Constant) u64;
|
||||||
|
pub extern fn LLVMConstIntGetSExtValue(constant: *llvm.Constant) i64;
|
||||||
|
pub extern fn LLVMConstArray2(element_type: *llvm.Type, value_pointer: [*]const *llvm.Constant, value_length: u64) *llvm.Constant;
|
||||||
|
pub extern fn LLVMConstStructInContext(context: *llvm.Context, constant_value_pointer: [*]const *llvm.Constant, constant_value_count: c_uint, is_packed: c_uint) *llvm.Constant;
|
||||||
|
pub extern fn LLVMConstNamedStruct(struct_type: *llvm.Type.Struct, constant_value_pointer: [*]const *llvm.Constant, constant_value_count: c_uint) *llvm.Constant;
|
||||||
|
|
||||||
pub extern fn LLVMGetValueKind(value: *llvm.Value) llvm.Value.Kind;
|
pub extern fn LLVMGetValueKind(value: *llvm.Value) llvm.Value.Kind;
|
||||||
pub extern fn LLVMIsConstant(value: *llvm.Value) Bool;
|
pub extern fn LLVMIsConstant(value: *llvm.Value) Bool;
|
||||||
|
@ -45,7 +45,7 @@ pub fn main(argc: c_int, argv: [*:null]const ?[*:0]const u8) callconv(.C) c_int
|
|||||||
.build_mode = .debug_none,
|
.build_mode = .debug_none,
|
||||||
.content = file_content,
|
.content = file_content,
|
||||||
.path = file_path,
|
.path = file_path,
|
||||||
.has_debug_info = true,
|
.has_debug_info = false,
|
||||||
.target = converter.Target.get_native(),
|
.target = converter.Target.get_native(),
|
||||||
});
|
});
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -280,7 +280,7 @@ require = fn (ok: u1) void
|
|||||||
require(x.a == 4);
|
require(x.a == 4);
|
||||||
require(x.b == 155);
|
require(x.b == 155);
|
||||||
|
|
||||||
>res = c_modify_by_ref_param({ .val = 1, .arr = undefined, });
|
>res = c_modify_by_ref_param({ .val = 1, .arr = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] });
|
||||||
require(res.val == 42);
|
require(res.val == 42);
|
||||||
|
|
||||||
>function_pointer = &c_func_ptr_byval;
|
>function_pointer = &c_func_ptr_byval;
|
||||||
|
51
tests/c_med_struct_ints.bbb
Normal file
51
tests/c_med_struct_ints.bbb
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
require = fn (ok: u1) void
|
||||||
|
{
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MedStructInts = struct
|
||||||
|
{
|
||||||
|
x: s32,
|
||||||
|
y: s32,
|
||||||
|
z: s32,
|
||||||
|
}
|
||||||
|
|
||||||
|
bb_ret_med_struct_ints = fn [cc(c)] () MedStructInts
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
.x = 1,
|
||||||
|
.y = 2,
|
||||||
|
.z = 3,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
c_med_struct_ints = fn [cc(c)] (s: MedStructInts) void
|
||||||
|
{
|
||||||
|
require(s.x == 1);
|
||||||
|
require(s.y == 2);
|
||||||
|
require(s.z == 3);
|
||||||
|
|
||||||
|
>s2 = bb_ret_med_struct_ints();
|
||||||
|
|
||||||
|
require(s2.x == 1);
|
||||||
|
require(s2.y == 2);
|
||||||
|
require(s2.z == 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>med: MedStructInts = {
|
||||||
|
.x = 1,
|
||||||
|
.y = 2,
|
||||||
|
.z = 3,
|
||||||
|
};
|
||||||
|
c_med_struct_ints(med);
|
||||||
|
>med2 = bb_ret_med_struct_ints();
|
||||||
|
require(med2.x == 1);
|
||||||
|
require(med2.y == 2);
|
||||||
|
require(med2.z == 3);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -5,8 +5,19 @@ SplitStructInt = struct
|
|||||||
c: u32,
|
c: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require = fn (ok: u1) void
|
||||||
|
{
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bb_split_struct_ints = fn [cc(c)] (x: SplitStructInt) void
|
bb_split_struct_ints = fn [cc(c)] (x: SplitStructInt) void
|
||||||
{
|
{
|
||||||
|
require(x.a == 1234);
|
||||||
|
require(x.b == 100);
|
||||||
|
require(x.c == 1337);
|
||||||
}
|
}
|
||||||
|
|
||||||
[export] main = fn [cc(c)] () s32
|
[export] main = fn [cc(c)] () s32
|
||||||
@ -20,6 +31,6 @@ bb_split_struct_ints = fn [cc(c)] (x: SplitStructInt) void
|
|||||||
bb_split_struct_ints(split);
|
bb_split_struct_ints(split);
|
||||||
>a: s32 = #truncate(split.a);
|
>a: s32 = #truncate(split.a);
|
||||||
>b: s32 = #extend(split.b);
|
>b: s32 = #extend(split.b);
|
||||||
>c: s32 = split.c;
|
>c: s32 = #extend(split.c);
|
||||||
return a + b + 3 - c;
|
return a + b + 3 - c;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
require = fn (ok: u1) void
|
require = fn [cc(c)] (ok: u1) void
|
||||||
{
|
{
|
||||||
if (!ok)
|
if (!ok)
|
||||||
{
|
{
|
||||||
|
45
tests/indirect.bbb
Normal file
45
tests/indirect.bbb
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
require = fn (ok: u1) void
|
||||||
|
{
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
S = struct
|
||||||
|
{
|
||||||
|
a: u32,
|
||||||
|
b: u32,
|
||||||
|
c: u32,
|
||||||
|
d: u32,
|
||||||
|
e: u32,
|
||||||
|
f: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = fn [cc(c)] () S
|
||||||
|
{
|
||||||
|
return { .a = 56, .b = 57, .c = 58, .d = 59, .e = 60, .f = 61 };
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = fn [cc(c)] (s: S) void
|
||||||
|
{
|
||||||
|
require(s.a == 56);
|
||||||
|
require(s.b == 57);
|
||||||
|
require(s.c == 58);
|
||||||
|
require(s.d == 59);
|
||||||
|
require(s.e == 60);
|
||||||
|
require(s.f == 61);
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>s = ret();
|
||||||
|
require(s.a == 56);
|
||||||
|
require(s.b == 57);
|
||||||
|
require(s.c == 58);
|
||||||
|
require(s.d == 59);
|
||||||
|
require(s.e == 60);
|
||||||
|
require(s.f == 61);
|
||||||
|
arg(s);
|
||||||
|
return 0;
|
||||||
|
}
|
46
tests/indirect_struct.bbb
Normal file
46
tests/indirect_struct.bbb
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
Struct_u64_u64 = struct
|
||||||
|
{
|
||||||
|
a: u64,
|
||||||
|
b: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
require = fn (ok: u1) void
|
||||||
|
{
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c_struct_u64_u64_5 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, s: Struct_u64_u64) void
|
||||||
|
{
|
||||||
|
require(s.a == 33);
|
||||||
|
require(s.b == 34);
|
||||||
|
}
|
||||||
|
|
||||||
|
c_struct_u64_u64_6 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, s: Struct_u64_u64) void
|
||||||
|
{
|
||||||
|
require(s.a == 35);
|
||||||
|
require(s.b == 36);
|
||||||
|
}
|
||||||
|
|
||||||
|
c_struct_u64_u64_7 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, s: Struct_u64_u64) void
|
||||||
|
{
|
||||||
|
require(s.a == 37);
|
||||||
|
require(s.b == 38);
|
||||||
|
}
|
||||||
|
|
||||||
|
c_struct_u64_u64_8 = fn [cc(c)] (a: u64, b: u64, c: u64, d: u64, e: u64, f: u64, g: u64, h: u64, s: Struct_u64_u64) void
|
||||||
|
{
|
||||||
|
require(s.a == 39);
|
||||||
|
require(s.b == 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
c_struct_u64_u64_5(0, 0, 0, 0, 0, { .a = 33, .b = 34, });
|
||||||
|
c_struct_u64_u64_6(0, 0, 0, 0, 0, 0, { .a = 35, .b = 36, });
|
||||||
|
c_struct_u64_u64_7(0, 0, 0, 0, 0, 0, 0, { .a = 37, .b = 38, });
|
||||||
|
c_struct_u64_u64_8(0, 0, 0, 0, 0, 0, 0, 0, { .a = 39, .b = 40, });
|
||||||
|
return 0;
|
||||||
|
}
|
@ -7,5 +7,5 @@ modify = fn (v: &s32) void
|
|||||||
{
|
{
|
||||||
>value: s32 = 0;
|
>value: s32 = 0;
|
||||||
modify(&value);
|
modify(&value);
|
||||||
return #extend(value == 1);
|
return #extend(value == 0);
|
||||||
}
|
}
|
||||||
|
47
tests/small_struct_ints.bbb
Normal file
47
tests/small_struct_ints.bbb
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
SmallStructInts = struct
|
||||||
|
{
|
||||||
|
a: u8,
|
||||||
|
b: u8,
|
||||||
|
c: u8,
|
||||||
|
d: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
bb_ret_small_struct_ints = fn [cc(c)] () SmallStructInts
|
||||||
|
{
|
||||||
|
return {
|
||||||
|
.a = 1,
|
||||||
|
.b = 2,
|
||||||
|
.c = 3,
|
||||||
|
.d = 4,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
require = fn(ok: u1) void
|
||||||
|
{
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c_small_struct_ints = fn [cc(c)] (x: SmallStructInts) void
|
||||||
|
{
|
||||||
|
require(x.a == 1);
|
||||||
|
require(x.b == 2);
|
||||||
|
require(x.c == 3);
|
||||||
|
require(x.d == 4);
|
||||||
|
|
||||||
|
>y = bb_ret_small_struct_ints();
|
||||||
|
|
||||||
|
require(y.a == 1);
|
||||||
|
require(y.b == 2);
|
||||||
|
require(y.c == 3);
|
||||||
|
require(y.d == 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>s: SmallStructInts = { .a = 1, .b = 2, .c = 3, .d = 4 };
|
||||||
|
c_small_struct_ints(s);
|
||||||
|
return 0;
|
||||||
|
}
|
11
tests/u1_return.bbb
Normal file
11
tests/u1_return.bbb
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
foo = fn [cc(c)] () u1
|
||||||
|
{
|
||||||
|
>result: u1 = 0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>result = foo();
|
||||||
|
return #extend(result);
|
||||||
|
}
|
66
tests/varargs.bbb
Normal file
66
tests/varargs.bbb
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
S = struct
|
||||||
|
{
|
||||||
|
a: u32,
|
||||||
|
b: u32,
|
||||||
|
c: u64,
|
||||||
|
d: u64,
|
||||||
|
e: u64
|
||||||
|
}
|
||||||
|
|
||||||
|
require = fn (ok: u1) void
|
||||||
|
{
|
||||||
|
if (!ok)
|
||||||
|
{
|
||||||
|
#trap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
va_arg_function = fn [cc(c)] (first_arg: u32, ...) void
|
||||||
|
{
|
||||||
|
>va = #va_start();
|
||||||
|
|
||||||
|
>a = #va_arg(&va, u32);
|
||||||
|
>b = #va_arg(&va, S);
|
||||||
|
>c = #va_arg(&va, s64);
|
||||||
|
>d = #va_arg(&va, s32);
|
||||||
|
|
||||||
|
require(first_arg == 123456789);
|
||||||
|
require(a == 123);
|
||||||
|
require(b.a == 1);
|
||||||
|
require(b.b == 2);
|
||||||
|
require(b.c == 3);
|
||||||
|
require(b.d == 4);
|
||||||
|
require(b.e == 5);
|
||||||
|
require(c == -1);
|
||||||
|
require(d == -2);
|
||||||
|
|
||||||
|
#va_end(&va);
|
||||||
|
}
|
||||||
|
|
||||||
|
S2 = struct
|
||||||
|
{
|
||||||
|
a: u64,
|
||||||
|
b: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
va_arg_function2 = fn [cc(c)] (...) void
|
||||||
|
{
|
||||||
|
>va = #va_start();
|
||||||
|
>s2 = #va_arg(&va, S2);
|
||||||
|
require(s2.a == 8);
|
||||||
|
require(s2.b == 9);
|
||||||
|
#va_end(&va);
|
||||||
|
}
|
||||||
|
|
||||||
|
[export] main = fn [cc(c)] () s32
|
||||||
|
{
|
||||||
|
>first_arg: u32 = 123456789;
|
||||||
|
>a: u32 = 123;
|
||||||
|
>b: S = { .a = 1, .b = 2, .c = 3, .d = 4, .e = 5 };
|
||||||
|
>c: s64 = -1;
|
||||||
|
>d: s32 = -2;
|
||||||
|
va_arg_function(first_arg, a, b, c, d);
|
||||||
|
>s2: S2 = { .a = 8, .b = 9 };
|
||||||
|
va_arg_function2(s2);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user