advance llvm well enough
This commit is contained in:
parent
745e74cc3d
commit
589677fa5b
135
build.zig
135
build.zig
@ -1,4 +1,5 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
|
||||||
fn run_process_and_capture_stdout(b: *std.Build, argv: []const []const u8) ![]const u8 {
|
fn run_process_and_capture_stdout(b: *std.Build, argv: []const []const u8) ![]const u8 {
|
||||||
const result = std.process.Child.run(.{
|
const result = std.process.Child.run(.{
|
||||||
@ -17,11 +18,115 @@ fn run_process_and_capture_stdout(b: *std.Build, argv: []const []const u8) ![]co
|
|||||||
return result.stdout;
|
return result.stdout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn file_find_in_path(allocator: std.mem.Allocator, file_name: []const u8, path_env: []const u8, extension: []const u8) ?[]const u8 {
|
||||||
|
const path_env_separator = switch (builtin.os.tag) {
|
||||||
|
.windows => ';',
|
||||||
|
else => ':',
|
||||||
|
};
|
||||||
|
const path_separator = switch (builtin.os.tag) {
|
||||||
|
.windows => '\\',
|
||||||
|
else => '/',
|
||||||
|
};
|
||||||
|
var env_it = std.mem.splitScalar(u8, path_env, path_env_separator);
|
||||||
|
const result: ?[]const u8 = while (env_it.next()) |dir_path| {
|
||||||
|
const full_path = std.mem.concatWithSentinel(allocator, u8, &.{ dir_path, &[1]u8{path_separator}, file_name, extension }, 0) catch unreachable;
|
||||||
|
const file = std.fs.cwd().openFile(full_path, .{}) catch continue;
|
||||||
|
file.close();
|
||||||
|
break full_path;
|
||||||
|
} else null;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn executable_find_in_path(allocator: std.mem.Allocator, file_name: []const u8, path_env: []const u8) ?[]const u8 {
|
||||||
|
const extension = switch (builtin.os.tag) {
|
||||||
|
.windows => ".exe",
|
||||||
|
else => "",
|
||||||
|
};
|
||||||
|
return file_find_in_path(allocator, file_name, path_env, extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
const LLVM = struct {
|
||||||
|
module: *std.Build.Module,
|
||||||
|
|
||||||
|
fn setup(b: *std.Build, path: []const u8, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) !LLVM {
|
||||||
|
var llvm_libs = std.ArrayList([]const u8).init(b.allocator);
|
||||||
|
var flags = std.ArrayList([]const u8).init(b.allocator);
|
||||||
|
const llvm_config_path = if (b.option([]const u8, "llvm_prefix", "LLVM prefix")) |llvm_prefix| blk: {
|
||||||
|
const full_path = try std.mem.concat(b.allocator, u8, &.{ llvm_prefix, "/bin/llvm-config" });
|
||||||
|
const f = std.fs.cwd().openFile(full_path, .{}) catch return error.llvm_not_found;
|
||||||
|
f.close();
|
||||||
|
break :blk full_path;
|
||||||
|
} else executable_find_in_path(b.allocator, "llvm-config", path) orelse return error.llvm_not_found;
|
||||||
|
const llvm_components_result = try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--components" });
|
||||||
|
var it = std.mem.splitScalar(u8, llvm_components_result, ' ');
|
||||||
|
var args = std.ArrayList([]const u8).init(b.allocator);
|
||||||
|
try args.append(llvm_config_path);
|
||||||
|
try args.append("--libs");
|
||||||
|
while (it.next()) |component| {
|
||||||
|
try args.append(std.mem.trimRight(u8, component, "\n"));
|
||||||
|
}
|
||||||
|
const llvm_libs_result = try run_process_and_capture_stdout(b, args.items);
|
||||||
|
it = std.mem.splitScalar(u8, llvm_libs_result, ' ');
|
||||||
|
|
||||||
|
while (it.next()) |lib| {
|
||||||
|
const llvm_lib = std.mem.trimLeft(u8, std.mem.trimRight(u8, lib, "\n"), "-l");
|
||||||
|
try llvm_libs.append(llvm_lib);
|
||||||
|
}
|
||||||
|
|
||||||
|
const llvm_cxx_flags_result = try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--cxxflags" });
|
||||||
|
it = std.mem.splitScalar(u8, llvm_cxx_flags_result, ' ');
|
||||||
|
while (it.next()) |flag| {
|
||||||
|
const llvm_cxx_flag = std.mem.trimRight(u8, flag, "\n");
|
||||||
|
try flags.append(llvm_cxx_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
const llvm_lib_dir = std.mem.trimRight(u8, try run_process_and_capture_stdout(b, &.{ llvm_config_path, "--libdir" }), "\n");
|
||||||
|
|
||||||
|
if (optimize != .ReleaseSmall) {
|
||||||
|
try flags.append("-g");
|
||||||
|
}
|
||||||
|
|
||||||
|
try flags.append("-fno-rtti");
|
||||||
|
|
||||||
|
const llvm = b.createModule(.{
|
||||||
|
.target = target,
|
||||||
|
.optimize = optimize,
|
||||||
|
});
|
||||||
|
|
||||||
|
llvm.addLibraryPath(.{ .cwd_relative = llvm_lib_dir });
|
||||||
|
|
||||||
|
llvm.addCSourceFiles(.{
|
||||||
|
.files = &.{"src/llvm.cpp"},
|
||||||
|
.flags = flags.items,
|
||||||
|
});
|
||||||
|
llvm.addIncludePath(.{ .cwd_relative = "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1" });
|
||||||
|
llvm.addIncludePath(.{ .cwd_relative = "/usr/bin/../lib64/gcc/x86_64-pc-linux-gnu/14.2.1/../../../../include/c++/14.2.1/x86_64-pc-linux-gnu" });
|
||||||
|
|
||||||
|
llvm.addObjectFile(.{ .cwd_relative = "/usr/lib/libstdc++.so.6" });
|
||||||
|
llvm.linkSystemLibrary("unwind", .{});
|
||||||
|
llvm.linkSystemLibrary("z", .{});
|
||||||
|
|
||||||
|
for (llvm_libs.items) |llvm_lib| {
|
||||||
|
llvm.linkSystemLibrary(llvm_lib, .{});
|
||||||
|
}
|
||||||
|
|
||||||
|
return LLVM{
|
||||||
|
.module = llvm,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn link(llvm: LLVM, target: *std.Build.Step.Compile) void {
|
||||||
|
if (target.root_module != llvm.module) {
|
||||||
|
target.root_module.addImport("llvm", llvm.module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub fn build(b: *std.Build) !void {
|
pub fn build(b: *std.Build) !void {
|
||||||
const ci = b.option(bool, "ci", "");
|
|
||||||
_ = &ci;
|
|
||||||
const target = b.standardTargetOptions(.{});
|
const target = b.standardTargetOptions(.{});
|
||||||
const optimize = b.standardOptimizeOption(.{});
|
const optimize = b.standardOptimizeOption(.{});
|
||||||
|
const env = try std.process.getEnvMap(b.allocator);
|
||||||
|
const path = env.get("PATH") orelse unreachable;
|
||||||
|
|
||||||
const exe_mod = b.createModule(.{
|
const exe_mod = b.createModule(.{
|
||||||
.root_source_file = b.path("src/main.zig"),
|
.root_source_file = b.path("src/main.zig"),
|
||||||
@ -29,33 +134,14 @@ pub fn build(b: *std.Build) !void {
|
|||||||
.optimize = optimize,
|
.optimize = optimize,
|
||||||
});
|
});
|
||||||
|
|
||||||
var llvm_libs = std.ArrayList([]const u8).init(b.allocator);
|
const llvm = try LLVM.setup(b, path, target, optimize);
|
||||||
{
|
|
||||||
const llvm_components_result = try run_process_and_capture_stdout(b, &.{ "llvm-config", "--components" });
|
|
||||||
var it = std.mem.splitScalar(u8, llvm_components_result, ' ');
|
|
||||||
var args = std.ArrayList([]const u8).init(b.allocator);
|
|
||||||
try args.append("llvm-config");
|
|
||||||
try args.append("--libs");
|
|
||||||
while (it.next()) |component| {
|
|
||||||
try args.append(std.mem.trim(u8, component, "\n"));
|
|
||||||
}
|
|
||||||
const llvm_libs_result = try run_process_and_capture_stdout(b, args.items);
|
|
||||||
it = std.mem.splitScalar(u8, llvm_libs_result, ' ');
|
|
||||||
|
|
||||||
while (it.next()) |component| {
|
|
||||||
const llvm_lib = std.mem.trim(u8, std.mem.trim(u8, component, "\n"), "-l");
|
|
||||||
try llvm_libs.append(llvm_lib);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const exe = b.addExecutable(.{
|
const exe = b.addExecutable(.{
|
||||||
.name = "bloat-buster",
|
.name = "bloat-buster",
|
||||||
.root_module = exe_mod,
|
.root_module = exe_mod,
|
||||||
});
|
});
|
||||||
exe.linkLibC();
|
|
||||||
for (llvm_libs.items) |llvm_lib| {
|
llvm.link(exe);
|
||||||
exe.linkSystemLibrary(llvm_lib);
|
|
||||||
}
|
|
||||||
|
|
||||||
b.installArtifact(exe);
|
b.installArtifact(exe);
|
||||||
|
|
||||||
@ -70,6 +156,7 @@ 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,
|
||||||
});
|
});
|
||||||
|
llvm.link(exe_unit_tests);
|
||||||
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests);
|
||||||
|
|
||||||
const test_step = b.step("test", "Run unit tests");
|
const test_step = b.step("test", "Run unit tests");
|
||||||
|
280
src/LLVM.zig
Normal file
280
src/LLVM.zig
Normal file
@ -0,0 +1,280 @@
|
|||||||
|
const lib = @import("lib.zig");
|
||||||
|
const Arena = lib.Arena;
|
||||||
|
const api = @import("llvm_api.zig");
|
||||||
|
pub const Architecture = enum {
|
||||||
|
X86,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const TargetInitializerOptions = struct {
|
||||||
|
asm_parser: bool = true,
|
||||||
|
asm_printer: bool = true,
|
||||||
|
disassembler: bool = false,
|
||||||
|
};
|
||||||
|
|
||||||
|
const targets = [@typeInfo(Architecture).@"enum".fields.len]type{
|
||||||
|
api.get_initializer(.X86),
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Context = opaque {
|
||||||
|
pub const create = api.LLVMContextCreate;
|
||||||
|
pub fn create_module(context: *Context, name: [:0]const u8) *Module {
|
||||||
|
return api.llvm_context_create_module(context, name.ptr, name.len);
|
||||||
|
}
|
||||||
|
pub const create_builder = api.LLVMCreateBuilderInContext;
|
||||||
|
pub fn create_basic_block(context: *Context, name: []const u8, parent: *Function) *BasicBlock {
|
||||||
|
return api.llvm_context_create_basic_block(context, name.ptr, name.len, parent);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BasicBlock = opaque {};
|
||||||
|
|
||||||
|
pub const Module = opaque {
|
||||||
|
pub const create_di_builder = api.LLVMCreateDIBuilder;
|
||||||
|
|
||||||
|
pub fn to_string(module: *Module) []const u8 {
|
||||||
|
var result: []const u8 = undefined;
|
||||||
|
api.llvm_module_to_string(module, &result.ptr, &result.len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FunctionCreate = struct {
|
||||||
|
type: *Type.Function,
|
||||||
|
linkage: LinkageType,
|
||||||
|
address_space: c_uint = 0,
|
||||||
|
name: []const u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn create_function(module: *Module, create: FunctionCreate) *Function {
|
||||||
|
return api.llvm_module_create_function(module, create.type, create.linkage, create.address_space, create.name.ptr, create.name.len);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(module: *Module) VerifyResult {
|
||||||
|
var result: VerifyResult = undefined;
|
||||||
|
result.success = api.llvm_module_verify(module, &result.error_message.ptr, &result.error_message.len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VerifyResult = struct {
|
||||||
|
error_message: []const u8,
|
||||||
|
success: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Builder = opaque {
|
||||||
|
pub const position_at_end = api.LLVMPositionBuilderAtEnd;
|
||||||
|
|
||||||
|
pub const create_ret = api.LLVMBuildRet;
|
||||||
|
|
||||||
|
pub fn create_ret_void(builder: *Builder) void {
|
||||||
|
builder.create_ret(null);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Function = opaque {
|
||||||
|
pub fn verify(function: *Function) VerifyResult {
|
||||||
|
var result: VerifyResult = undefined;
|
||||||
|
result.success = api.llvm_function_verify(function, &result.error_message.ptr, &result.error_message.len);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Constant = opaque {
|
||||||
|
pub fn to_value(constant: *Constant) *Value {
|
||||||
|
return @ptrCast(constant);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const Integer = opaque {
|
||||||
|
pub fn to_value(constant: *Constant.Integer) *Value {
|
||||||
|
return @ptrCast(constant);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Value = opaque {};
|
||||||
|
|
||||||
|
pub const DI = struct {
|
||||||
|
pub const Builder = opaque {
|
||||||
|
pub fn create_file(builder: *DI.Builder, file_name: []const u8, directory_name: []const u8) *File {
|
||||||
|
return api.LLVMCreateDIBuilder(builder, file_name.ptr, file_name.len, directory_name.ptr, directory_name.len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pub const File = opaque {};
|
||||||
|
|
||||||
|
const Flags = enum(c_int) {
|
||||||
|
_,
|
||||||
|
const Zero = 0;
|
||||||
|
const Private = 1;
|
||||||
|
const Protected = 2;
|
||||||
|
const Public = 3;
|
||||||
|
const FwdDecl = 1 << 2;
|
||||||
|
const AppleBlock = 1 << 3;
|
||||||
|
const ReservedBit4 = 1 << 4;
|
||||||
|
const Virtual = 1 << 5;
|
||||||
|
const Artificial = 1 << 6;
|
||||||
|
const Explicit = 1 << 7;
|
||||||
|
const Prototyped = 1 << 8;
|
||||||
|
const ObjcClassComplete = 1 << 9;
|
||||||
|
const ObjectPointer = 1 << 10;
|
||||||
|
const Vector = 1 << 11;
|
||||||
|
const StaticMember = 1 << 12;
|
||||||
|
const LValueReference = 1 << 13;
|
||||||
|
const RValueReference = 1 << 14;
|
||||||
|
const Reserved = 1 << 15;
|
||||||
|
const SingleInheritance = 1 << 16;
|
||||||
|
const MultipleInheritance = 2 << 16;
|
||||||
|
const VirtualInheritance = 3 << 16;
|
||||||
|
const IntroducedVirtual = 1 << 18;
|
||||||
|
const BitField = 1 << 19;
|
||||||
|
const NoReturn = 1 << 20;
|
||||||
|
const TypePassByValue = 1 << 22;
|
||||||
|
const TypePassByReference = 1 << 23;
|
||||||
|
const EnumClass = 1 << 24;
|
||||||
|
const Thunk = 1 << 25;
|
||||||
|
const NonTrivial = 1 << 26;
|
||||||
|
const BigEndian = 1 << 27;
|
||||||
|
const LittleEndian = 1 << 28;
|
||||||
|
const IndirectVirtualBase = (1 << 2) | (1 << 5);
|
||||||
|
const Accessibility = Private | Protected | Public;
|
||||||
|
const PtrToMemberRep = SingleInheritance | MultipleInheritance | VirtualInheritance;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Type = opaque {
|
||||||
|
pub const Function = opaque {
|
||||||
|
pub fn get(return_type: *Type, parameter_types: []const *Type, is_var_args: c_int) *Type.Function {
|
||||||
|
return api.LLVMFunctionType(return_type, parameter_types.ptr, @intCast(parameter_types.len), is_var_args);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Integer = opaque {
|
||||||
|
pub const get_constant = api.LLVMConstInt;
|
||||||
|
pub fn to_type(integer: *Type.Integer) *Type {
|
||||||
|
return @ptrCast(integer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const LinkageType = enum(c_int) {
|
||||||
|
ExternalLinkage,
|
||||||
|
AvailableExternallyLinkage,
|
||||||
|
LinkOnceAnyLinkage,
|
||||||
|
LinkOnceODRLinkage,
|
||||||
|
WeakAnyLinkage,
|
||||||
|
WeakODRLinkage,
|
||||||
|
AppendingLinkage,
|
||||||
|
InternalLinkage,
|
||||||
|
PrivateLinkage,
|
||||||
|
ExternalWeakLinkage,
|
||||||
|
CommonLinkage,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const DwarfSourceLanguage = enum(c_int) {
|
||||||
|
c17 = 0x2c,
|
||||||
|
};
|
||||||
|
pub const DwarfEmissionKind = enum(c_int) {
|
||||||
|
none,
|
||||||
|
full,
|
||||||
|
line_tables_only,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const Thread = struct {
|
||||||
|
context: *Context,
|
||||||
|
i1: Integer,
|
||||||
|
i8: Integer,
|
||||||
|
i16: Integer,
|
||||||
|
i32: Integer,
|
||||||
|
i64: Integer,
|
||||||
|
i128: Integer,
|
||||||
|
|
||||||
|
pub const Integer = struct {
|
||||||
|
type: *Type.Integer,
|
||||||
|
zero: *Constant.Integer,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn initialize(thread: *Thread) void {
|
||||||
|
const context = Context.create();
|
||||||
|
const type_i1 = api.LLVMInt1TypeInContext(context);
|
||||||
|
const type_i8 = api.LLVMInt8TypeInContext(context);
|
||||||
|
const type_i16 = api.LLVMInt16TypeInContext(context);
|
||||||
|
const type_i32 = api.LLVMInt32TypeInContext(context);
|
||||||
|
const type_i64 = api.LLVMInt64TypeInContext(context);
|
||||||
|
const type_i128 = api.LLVMInt128TypeInContext(context);
|
||||||
|
const zero_i1 = type_i1.get_constant(0, 0);
|
||||||
|
const zero_i8 = type_i8.get_constant(0, 0);
|
||||||
|
const zero_i16 = type_i16.get_constant(0, 0);
|
||||||
|
const zero_i32 = type_i32.get_constant(0, 0);
|
||||||
|
const zero_i64 = type_i64.get_constant(0, 0);
|
||||||
|
const zero_i128 = type_i128.get_constant(0, 0);
|
||||||
|
|
||||||
|
thread.* = .{
|
||||||
|
.context = context,
|
||||||
|
.i1 = .{
|
||||||
|
.type = type_i1,
|
||||||
|
.zero = zero_i1,
|
||||||
|
},
|
||||||
|
.i8 = .{
|
||||||
|
.type = type_i8,
|
||||||
|
.zero = zero_i8,
|
||||||
|
},
|
||||||
|
.i16 = .{
|
||||||
|
.type = type_i16,
|
||||||
|
.zero = zero_i16,
|
||||||
|
},
|
||||||
|
.i32 = .{
|
||||||
|
.type = type_i32,
|
||||||
|
.zero = zero_i32,
|
||||||
|
},
|
||||||
|
.i64 = .{
|
||||||
|
.type = type_i64,
|
||||||
|
.zero = zero_i64,
|
||||||
|
},
|
||||||
|
.i128 = .{
|
||||||
|
.type = type_i128,
|
||||||
|
.zero = zero_i128,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub var threads: []Thread = undefined;
|
||||||
|
|
||||||
|
// This is meant to call globally, only once per execution
|
||||||
|
pub fn initialize_all() void {
|
||||||
|
threads = lib.global.arena.allocate(Thread, lib.global.thread_count);
|
||||||
|
inline for (targets) |target| {
|
||||||
|
target.initialize(.{});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn experiment() void {
|
||||||
|
const thread = &threads[0];
|
||||||
|
thread.initialize();
|
||||||
|
const module = thread.context.create_module("first_module");
|
||||||
|
const builder = thread.context.create_builder();
|
||||||
|
// const di_builder = module.create_di_builder();
|
||||||
|
const return_type = thread.i32.type;
|
||||||
|
const return_value = thread.i32.zero;
|
||||||
|
// const return_value = thread.
|
||||||
|
const function_type = Type.Function.get(return_type.to_type(), &.{}, 0);
|
||||||
|
const function = module.create_function(.{
|
||||||
|
.type = function_type,
|
||||||
|
.linkage = .ExternalLinkage,
|
||||||
|
.name = "main",
|
||||||
|
});
|
||||||
|
const entry_basic_block = thread.context.create_basic_block("entry", function);
|
||||||
|
builder.position_at_end(entry_basic_block);
|
||||||
|
builder.create_ret(return_value.to_value());
|
||||||
|
const function_verify = function.verify();
|
||||||
|
if (!function_verify.success) {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
const module_verify = module.verify();
|
||||||
|
if (!module_verify.success) {
|
||||||
|
unreachable;
|
||||||
|
}
|
||||||
|
|
||||||
|
const module_z = api.LLVMPrintModuleToString(module);
|
||||||
|
_ = module_z;
|
||||||
|
const module_string = module.to_string();
|
||||||
|
lib.print_string(module_string);
|
||||||
|
}
|
130
src/lib.zig
130
src/lib.zig
@ -3,6 +3,10 @@ const VariableArguments = @import("std").builtin.VaList;
|
|||||||
extern "c" fn IsDebuggerPresent() bool;
|
extern "c" fn IsDebuggerPresent() bool;
|
||||||
extern "c" fn __errno_location() *c_int;
|
extern "c" fn __errno_location() *c_int;
|
||||||
|
|
||||||
|
test {
|
||||||
|
_ = @import("lib_test.zig");
|
||||||
|
}
|
||||||
|
|
||||||
pub const KB = 1024;
|
pub const KB = 1024;
|
||||||
pub const MB = 1024 * 1024;
|
pub const MB = 1024 * 1024;
|
||||||
pub const GB = 1024 * 1024 * 1024;
|
pub const GB = 1024 * 1024 * 1024;
|
||||||
@ -59,48 +63,6 @@ pub fn value_from_flag(value: anytype, flag: anytype) @TypeOf(value) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
test "value_from_flag" {
|
|
||||||
const std = @import("std");
|
|
||||||
const expect = std.testing.expect;
|
|
||||||
|
|
||||||
try expect(value_from_flag(1, 1) == 1);
|
|
||||||
try expect(value_from_flag(2, true) == 2);
|
|
||||||
try expect(value_from_flag(3, false) == 0);
|
|
||||||
try expect(value_from_flag(3, true) == 3);
|
|
||||||
try expect(value_from_flag(3, 1) == 3);
|
|
||||||
|
|
||||||
try expect(value_from_flag(0xffff, 1) == 0xffff);
|
|
||||||
try expect(value_from_flag(0xffff, 0) == 0);
|
|
||||||
try expect(value_from_flag(0xffff, true) == 0xffff);
|
|
||||||
try expect(value_from_flag(0xffff, false) == 0);
|
|
||||||
|
|
||||||
try expect(value_from_flag(0xffffffff, 1) == 0xffffffff);
|
|
||||||
try expect(value_from_flag(0xffffffff, 0) == 0);
|
|
||||||
try expect(value_from_flag(0xffffffff, true) == 0xffffffff);
|
|
||||||
try expect(value_from_flag(0xffffffff, false) == 0);
|
|
||||||
|
|
||||||
try expect(value_from_flag(0xffffffffffffffff, 1) == 0xffffffffffffffff);
|
|
||||||
try expect(value_from_flag(0xffffffffffffffff, 0) == 0);
|
|
||||||
try expect(value_from_flag(0xffffffffffffffff, true) == 0xffffffffffffffff);
|
|
||||||
try expect(value_from_flag(0xffffffffffffffff, false) == 0);
|
|
||||||
|
|
||||||
const a: u32 = 1235;
|
|
||||||
const b_true: bool = true;
|
|
||||||
const b_false: bool = false;
|
|
||||||
const u_true: u1 = 1;
|
|
||||||
const u_false: u1 = 0;
|
|
||||||
try expect(value_from_flag(a, b_true) == a);
|
|
||||||
try expect(value_from_flag(a, b_false) == 0);
|
|
||||||
try expect(value_from_flag(a, u_true) == a);
|
|
||||||
try expect(value_from_flag(a, u_false) == 0);
|
|
||||||
|
|
||||||
const b: u64 = 0xffffffffffffffff;
|
|
||||||
try expect(value_from_flag(b, b_true) == b);
|
|
||||||
try expect(value_from_flag(b, b_false) == 0);
|
|
||||||
try expect(value_from_flag(b, u_true) == b);
|
|
||||||
try expect(value_from_flag(b, u_false) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const Error = enum(c_int) {
|
pub const Error = enum(c_int) {
|
||||||
SUCCESS = 0,
|
SUCCESS = 0,
|
||||||
PERM = 1,
|
PERM = 1,
|
||||||
@ -302,7 +264,37 @@ pub const os = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_cpu_count() usize {
|
||||||
|
switch (builtin.os.tag) {
|
||||||
|
.windows => @compileError("TODO"),
|
||||||
|
else => {
|
||||||
|
var cpu_set: posix.cpu_set_t = undefined;
|
||||||
|
const result = posix.sched_getaffinity(0, @sizeOf(posix.cpu_set_t), &cpu_set);
|
||||||
|
assert(result == 0);
|
||||||
|
const cpu_count = posix.CPU_COUNT(cpu_set);
|
||||||
|
return cpu_count;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const linux = struct {
|
const linux = struct {
|
||||||
|
pub const CPU_SETSIZE = 128;
|
||||||
|
pub const cpu_set_t = [CPU_SETSIZE / @sizeOf(usize)]usize;
|
||||||
|
pub const cpu_count_t = @Type(.{
|
||||||
|
.int = .{
|
||||||
|
.signedness = .unsigned,
|
||||||
|
.bits = log2_int(@as(u64, CPU_SETSIZE * 8)),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn CPU_COUNT(set: cpu_set_t) cpu_count_t {
|
||||||
|
var sum: cpu_count_t = 0;
|
||||||
|
for (set) |x| {
|
||||||
|
sum += @popCount(x);
|
||||||
|
}
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
const FileDescriptor = c_int;
|
const FileDescriptor = c_int;
|
||||||
|
|
||||||
fn fd_is_valid(fd: FileDescriptor) bool {
|
fn fd_is_valid(fd: FileDescriptor) bool {
|
||||||
@ -414,6 +406,7 @@ pub const os = struct {
|
|||||||
extern "c" fn fstat(fd: system.FileDescriptor, stat: *Stat) c_int;
|
extern "c" fn fstat(fd: system.FileDescriptor, stat: *Stat) c_int;
|
||||||
extern "c" fn read(fd: system.FileDescriptor, pointer: [*]u8, byte_count: usize) isize;
|
extern "c" fn read(fd: system.FileDescriptor, pointer: [*]u8, byte_count: usize) isize;
|
||||||
extern "c" fn write(fd: system.FileDescriptor, pointer: [*]const u8, byte_count: usize) isize;
|
extern "c" fn write(fd: system.FileDescriptor, pointer: [*]const u8, byte_count: usize) isize;
|
||||||
|
extern "c" fn sched_getaffinity(pid: c_int, size: usize, set: *cpu_set_t) c_int;
|
||||||
|
|
||||||
const mode_t = usize;
|
const mode_t = usize;
|
||||||
|
|
||||||
@ -490,6 +483,17 @@ pub const os = struct {
|
|||||||
libc.exit(1);
|
libc.exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_stdout() File {
|
||||||
|
return switch (builtin.os.tag) {
|
||||||
|
.windows => @compileError("TODO"),
|
||||||
|
else => {
|
||||||
|
return File{
|
||||||
|
.fd = 1,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const libc = struct {
|
pub const libc = struct {
|
||||||
@ -586,6 +590,18 @@ pub const Arena = struct {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn allocate(arena: *Arena, T: type, count: usize) []T {
|
||||||
|
const result = arena.allocate_bytes(@sizeOf(T) * count, @alignOf(T));
|
||||||
|
const t_ptr: [*]T = @alignCast(@ptrCast(result));
|
||||||
|
const t_len = count;
|
||||||
|
return t_ptr[0..t_len];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn allocate_one(arena: *Arena, T: type) *T {
|
||||||
|
const result = arena.allocate(T, 1);
|
||||||
|
return &result[0];
|
||||||
|
}
|
||||||
|
|
||||||
pub fn join_string(arena: *Arena, pieces: []const []const u8) [:0]u8 {
|
pub fn join_string(arena: *Arena, pieces: []const []const u8) [:0]u8 {
|
||||||
var size: u64 = 0;
|
var size: u64 = 0;
|
||||||
for (pieces) |piece| {
|
for (pieces) |piece| {
|
||||||
@ -2424,6 +2440,20 @@ pub fn format(buffer_pointer: [*]u8, buffer_length: usize, format_string: [*:0]c
|
|||||||
return byte_count;
|
return byte_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const GlobalState = struct {
|
||||||
|
arena: *Arena,
|
||||||
|
thread_count: usize,
|
||||||
|
|
||||||
|
pub fn initialize() void {
|
||||||
|
const thread_count = os.get_cpu_count();
|
||||||
|
global = .{
|
||||||
|
.arena = Arena.initialize_default(2 * MB),
|
||||||
|
.thread_count = thread_count,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
pub var global: GlobalState = undefined;
|
||||||
|
|
||||||
pub const parse = struct {
|
pub const parse = struct {
|
||||||
fn integer_decimal(str: []const u8) u64 {
|
fn integer_decimal(str: []const u8) u64 {
|
||||||
var value: u64 = 0;
|
var value: u64 = 0;
|
||||||
@ -2436,3 +2466,19 @@ pub const parse = struct {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn vprint(format_string: [*:0]const u8, args: *VariableArguments) void {
|
||||||
|
var buffer: [16 * 1024]u8 = undefined;
|
||||||
|
const slice = format_va(&buffer, format_string, args);
|
||||||
|
print_string(slice);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print(format_string: [*:0]const u8, ...) callconv(.C) void {
|
||||||
|
const args = @cVaStart();
|
||||||
|
vprint(format_string, &args);
|
||||||
|
@cVaEnd(&args);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn print_string(str: []const u8) void {
|
||||||
|
os.get_stdout().write(str);
|
||||||
|
}
|
||||||
|
44
src/lib_test.zig
Normal file
44
src/lib_test.zig
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
const lib = @import("lib.zig");
|
||||||
|
|
||||||
|
test "value_from_flag" {
|
||||||
|
const std = @import("std");
|
||||||
|
const expect = std.testing.expect;
|
||||||
|
const value_from_flag = lib.value_from_flag;
|
||||||
|
|
||||||
|
try expect(value_from_flag(1, 1) == 1);
|
||||||
|
try expect(value_from_flag(2, true) == 2);
|
||||||
|
try expect(value_from_flag(3, false) == 0);
|
||||||
|
try expect(value_from_flag(3, true) == 3);
|
||||||
|
try expect(value_from_flag(3, 1) == 3);
|
||||||
|
|
||||||
|
try expect(value_from_flag(0xffff, 1) == 0xffff);
|
||||||
|
try expect(value_from_flag(0xffff, 0) == 0);
|
||||||
|
try expect(value_from_flag(0xffff, true) == 0xffff);
|
||||||
|
try expect(value_from_flag(0xffff, false) == 0);
|
||||||
|
|
||||||
|
try expect(value_from_flag(0xffffffff, 1) == 0xffffffff);
|
||||||
|
try expect(value_from_flag(0xffffffff, 0) == 0);
|
||||||
|
try expect(value_from_flag(0xffffffff, true) == 0xffffffff);
|
||||||
|
try expect(value_from_flag(0xffffffff, false) == 0);
|
||||||
|
|
||||||
|
try expect(value_from_flag(0xffffffffffffffff, 1) == 0xffffffffffffffff);
|
||||||
|
try expect(value_from_flag(0xffffffffffffffff, 0) == 0);
|
||||||
|
try expect(value_from_flag(0xffffffffffffffff, true) == 0xffffffffffffffff);
|
||||||
|
try expect(value_from_flag(0xffffffffffffffff, false) == 0);
|
||||||
|
|
||||||
|
const a: u32 = 1235;
|
||||||
|
const b_true: bool = true;
|
||||||
|
const b_false: bool = false;
|
||||||
|
const u_true: u1 = 1;
|
||||||
|
const u_false: u1 = 0;
|
||||||
|
try expect(value_from_flag(a, b_true) == a);
|
||||||
|
try expect(value_from_flag(a, b_false) == 0);
|
||||||
|
try expect(value_from_flag(a, u_true) == a);
|
||||||
|
try expect(value_from_flag(a, u_false) == 0);
|
||||||
|
|
||||||
|
const b: u64 = 0xffffffffffffffff;
|
||||||
|
try expect(value_from_flag(b, b_true) == b);
|
||||||
|
try expect(value_from_flag(b, b_false) == 0);
|
||||||
|
try expect(value_from_flag(b, u_true) == b);
|
||||||
|
try expect(value_from_flag(b, u_false) == 0);
|
||||||
|
}
|
104
src/llvm.cpp
Normal file
104
src/llvm.cpp
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
#include "llvm/IR/IRBuilder.h"
|
||||||
|
#include "llvm/IR/Module.h"
|
||||||
|
#include "llvm/IR/Verifier.h"
|
||||||
|
|
||||||
|
#define EXPORT extern "C"
|
||||||
|
#define fn static
|
||||||
|
|
||||||
|
using namespace llvm;
|
||||||
|
|
||||||
|
EXPORT Module* llvm_context_create_module(LLVMContext& context, const char* name_pointer, size_t name_length)
|
||||||
|
{
|
||||||
|
auto name = StringRef(name_pointer, name_length);
|
||||||
|
return new Module(name, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT Value* llvm_builder_create_add(IRBuilder<>& builder, Value* left, Value* right, bool nuw, bool nsw)
|
||||||
|
{
|
||||||
|
auto* result = builder.CreateAdd(left, right, "", nuw, nsw);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT Function* llvm_module_create_function(Module* module, FunctionType* function_type, GlobalValue::LinkageTypes linkage_type, unsigned address_space, const char* name_pointer, size_t name_length)
|
||||||
|
{
|
||||||
|
auto name = StringRef(name_pointer, name_length);
|
||||||
|
auto* function = Function::Create(function_type, linkage_type, address_space, name, module);
|
||||||
|
return function;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT StructType* llvm_context_create_struct_type(LLVMContext& context, Type** type_pointer, size_t type_count, const char* name_pointer, size_t name_length, bool is_packed)
|
||||||
|
{
|
||||||
|
auto types = ArrayRef<Type*>(type_pointer, type_count);
|
||||||
|
auto name = StringRef(name_pointer, name_length);
|
||||||
|
auto* struct_type = StructType::create(context, types, name, is_packed);
|
||||||
|
return struct_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT StructType* llvm_context_get_struct_type(LLVMContext& context, Type** type_pointer, size_t type_count, bool is_packed)
|
||||||
|
{
|
||||||
|
auto types = ArrayRef<Type*>(type_pointer, type_count);
|
||||||
|
auto* struct_type = StructType::get(context, types, is_packed);
|
||||||
|
return struct_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT BasicBlock* llvm_context_create_basic_block(LLVMContext& context, const char* name_pointer, size_t name_length, Function* parent)
|
||||||
|
{
|
||||||
|
auto name = StringRef(name_pointer, name_length);
|
||||||
|
auto* basic_block = BasicBlock::Create(context, name, parent);
|
||||||
|
return basic_block;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn void stream_to_string(raw_string_ostream& stream, const char** message_pointer, size_t* message_length)
|
||||||
|
{
|
||||||
|
// No need to call stream.flush(); because it's string-based
|
||||||
|
stream.flush();
|
||||||
|
|
||||||
|
auto string = stream.str();
|
||||||
|
auto length = string.length();
|
||||||
|
|
||||||
|
char* result = 0;
|
||||||
|
if (length)
|
||||||
|
{
|
||||||
|
result = new char[length];
|
||||||
|
memcpy(result, string.c_str(), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
*message_pointer = result;
|
||||||
|
*message_length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT bool llvm_function_verify(Function& function, const char** message_pointer, size_t* message_length)
|
||||||
|
{
|
||||||
|
std::string message_buffer;
|
||||||
|
raw_string_ostream message_stream(message_buffer);
|
||||||
|
|
||||||
|
bool result = verifyFunction(function, &message_stream);
|
||||||
|
auto size = message_stream.str().size();
|
||||||
|
stream_to_string(message_stream, message_pointer, message_length);
|
||||||
|
|
||||||
|
// We invert the condition because LLVM conventions are just stupid
|
||||||
|
return !result;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT bool llvm_module_verify(const Module& module, const char** message_pointer, size_t* message_length)
|
||||||
|
{
|
||||||
|
std::string message_buffer;
|
||||||
|
raw_string_ostream message_stream(message_buffer);
|
||||||
|
|
||||||
|
bool result = verifyModule(module, &message_stream);
|
||||||
|
stream_to_string(message_stream, message_pointer, message_length);
|
||||||
|
|
||||||
|
// We invert the condition because LLVM conventions are just stupid
|
||||||
|
return !result;
|
||||||
|
}
|
||||||
|
|
||||||
|
EXPORT void llvm_module_to_string(Module* module, const char** module_pointer, size_t* module_length)
|
||||||
|
{
|
||||||
|
std::string buffer;
|
||||||
|
raw_string_ostream stream(buffer);
|
||||||
|
module->print(stream, nullptr);
|
||||||
|
|
||||||
|
stream_to_string(stream, module_pointer, module_length);
|
||||||
|
}
|
||||||
|
|
110
src/llvm_api.zig
Normal file
110
src/llvm_api.zig
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
const llvm = @import("LLVM.zig");
|
||||||
|
|
||||||
|
const Bool = c_int;
|
||||||
|
|
||||||
|
pub extern fn llvm_context_create_module(context: *llvm.Context, name_pointer: [*]const u8, name_length: usize) *llvm.Module;
|
||||||
|
pub extern fn LLVMContextCreate() *llvm.Context;
|
||||||
|
pub extern fn LLVMCreateBuilderInContext(context: *llvm.Context) *llvm.Builder;
|
||||||
|
|
||||||
|
// Module
|
||||||
|
pub extern fn llvm_module_create_function(module: *llvm.Module, function_type: *llvm.Type.Function, linkage_type: llvm.LinkageType, address_space: c_uint, name_pointer: [*]const u8, name_length: usize) *llvm.Function;
|
||||||
|
pub extern fn llvm_context_create_basic_block(context: *llvm.Context, name_pointer: [*]const u8, name_length: usize, parent: *llvm.Function) *llvm.BasicBlock;
|
||||||
|
|
||||||
|
pub extern fn llvm_function_verify(function: *llvm.Function, message_pointer: *[*]const u8, message_length: *usize) bool;
|
||||||
|
pub extern fn llvm_module_verify(module: *llvm.Module, message_pointer: *[*]const u8, message_length: *usize) bool;
|
||||||
|
|
||||||
|
pub extern fn llvm_module_to_string(module: *llvm.Module, module_pointer: *[*]const u8, module_length: *usize) void;
|
||||||
|
pub extern fn LLVMPrintModuleToString(module: *llvm.Module) [*:0]const u8;
|
||||||
|
|
||||||
|
// Builder API
|
||||||
|
pub extern fn LLVMPositionBuilderAtEnd(builder: *llvm.Builder, basic_block: *llvm.BasicBlock) void;
|
||||||
|
pub extern fn LLVMBuildRet(builder: *llvm.Builder, value: ?*llvm.Value) void;
|
||||||
|
|
||||||
|
// TYPES
|
||||||
|
// Types: integers
|
||||||
|
pub extern fn LLVMInt1TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
||||||
|
pub extern fn LLVMInt8TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
||||||
|
pub extern fn LLVMInt16TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
||||||
|
pub extern fn LLVMInt32TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
||||||
|
pub extern fn LLVMInt64TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
||||||
|
pub extern fn LLVMInt128TypeInContext(context: *llvm.Context) *llvm.Type.Integer;
|
||||||
|
pub extern fn LLVMIntTypeInContext(context: *llvm.Context, bit_count: c_uint) *llvm.Type.Integer;
|
||||||
|
|
||||||
|
// Types: floating point
|
||||||
|
pub extern fn LLVMHalfTypeInContext(context: *llvm.Context) *llvm.Type;
|
||||||
|
pub extern fn LLVMBFloatTypeInContext(context: *llvm.Context) *llvm.Type;
|
||||||
|
pub extern fn LLVMFloatTypeInContext(context: *llvm.Context) *llvm.Type;
|
||||||
|
pub extern fn LLVMDoubleTypeInContext(context: *llvm.Context) *llvm.Type;
|
||||||
|
pub extern fn LLVMFP128TypeInContext(context: *llvm.Context) *llvm.Type;
|
||||||
|
|
||||||
|
// Types: functions
|
||||||
|
pub extern fn LLVMFunctionType(return_type: *llvm.Type, parameter_type_pointer: [*]const *llvm.Type, parameter_type_count: c_uint, is_var_arg: Bool) *llvm.Type.Function;
|
||||||
|
pub extern fn LLVMIsFunctionVarArg(function_type: *llvm.Type.Function) Bool;
|
||||||
|
pub extern fn LLVMGetReturnType(function_type: *llvm.Type.Function) *llvm.Type;
|
||||||
|
pub extern fn LLVMCountParamTypes(function_type: *llvm.Type.Function) c_uint;
|
||||||
|
pub extern fn LLVMGetParamTypes(function_type: *llvm.Type.Function, types: [*]*llvm.Type) void;
|
||||||
|
|
||||||
|
// Types: struct
|
||||||
|
pub extern fn llvm_context_create_struct_type(context: *llvm.Context, element_types_pointer: [*]const *llvm.Type, element_type_count: usize, name_pointer: [*]const u8, name_length: usize, is_packed: bool) *llvm.Type.Struct;
|
||||||
|
pub extern fn llvm_context_get_struct_type(context: *llvm.Context, element_types_pointer: [*]const *llvm.Type, element_type_count: usize, is_packed: bool) *llvm.Type.Struct;
|
||||||
|
|
||||||
|
// Types: arrays
|
||||||
|
pub extern fn LLVMArrayType2(element_type: *llvm.Type, element_count: u64) *llvm.Type.Array;
|
||||||
|
|
||||||
|
// Types: pointers
|
||||||
|
pub extern fn LLVMPointerTypeInContext(context: *llvm.Context, address_space: c_uint) *llvm.Type.Pointer;
|
||||||
|
|
||||||
|
// Types: vectors
|
||||||
|
pub extern fn LLVMVectorType(element_type: *llvm.Type, element_count: c_uint) *llvm.Type.FixedVector;
|
||||||
|
pub extern fn LLVMScalableVectorType(element_type: *llvm.Type, element_count: c_uint) *llvm.Type.ScalableVector;
|
||||||
|
|
||||||
|
// VALUES
|
||||||
|
pub extern fn LLVMConstInt(type: *llvm.Type.Integer, value: c_ulonglong, sign_extend: Bool) *llvm.Constant.Integer;
|
||||||
|
|
||||||
|
// Debug info API
|
||||||
|
pub extern fn LLVMCreateDIBuilder(module: *llvm.Module) *llvm.DI.Builder;
|
||||||
|
pub extern fn LLVMDIBuilderCreateFile(builder: *llvm.DI.Builder, file_name_pointer: [*]const u8, file_name_length: usize, directory_name_pointer: [*]const u8, directory_name_length: usize) *llvm.DI.File;
|
||||||
|
pub extern fn LLVMDIBuilderCreateCompileUnit(builder: *llvm.DI.Builder, language: llvm.DwarfSourceLanguage, file: *llvm.DI.File, producer_name_pointer: [*]const u8, producer_name_length: usize, optimized: Bool, flags_pointer: [*]const u8, flags_length: usize, runtime_version: c_uint, split_name_pointer: [*]const u8, split_name_length: usize, dwarf_emission_kind: llvm.DwarfEmissionKind, debug_with_offset_id: c_uint, split_debug_inlining: Bool, debug_info_for_profiling: Bool, sysroot_pointer: [*]const u8, sysroot_length: usize, sdk_pointer: [*]const u8, sdk_length: usize) *llvm.DI.CompileUnit;
|
||||||
|
pub extern fn LLVMDIBuilderCreateFunction(builder: *llvm.DI.Builder, scope: *llvm.DI.Scope, name_pointer: [*]const u8, name_length: usize, linkage_name_pointer: [*]const u8, linkage_name_length: usize, file: *llvm.DI.File, line_number: c_uint, type: *llvm.DI.Type.Subroutine, local_to_unit: Bool, is_definition: Bool, scope_line: c_uint, flags: llvm.DI.Flags, is_optimized: Bool) *llvm.DI.Subprogram;
|
||||||
|
|
||||||
|
pub fn get_initializer(comptime llvm_arch: llvm.Architecture) type {
|
||||||
|
const arch_name = @tagName(llvm_arch);
|
||||||
|
return struct {
|
||||||
|
pub const initialize_target_info = @extern(*const fn () callconv(.C) void, .{
|
||||||
|
.name = "LLVMInitialize" ++ arch_name ++ "TargetInfo",
|
||||||
|
});
|
||||||
|
pub const initialize_target = @extern(*const fn () callconv(.C) void, .{
|
||||||
|
.name = "LLVMInitialize" ++ arch_name ++ "Target",
|
||||||
|
});
|
||||||
|
pub const initialize_target_mc = @extern(*const fn () callconv(.C) void, .{
|
||||||
|
.name = "LLVMInitialize" ++ arch_name ++ "TargetMC",
|
||||||
|
});
|
||||||
|
pub const initialize_asm_printer = @extern(*const fn () callconv(.C) void, .{
|
||||||
|
.name = "LLVMInitialize" ++ arch_name ++ "AsmPrinter",
|
||||||
|
});
|
||||||
|
pub const initialize_asm_parser = @extern(*const fn () callconv(.C) void, .{
|
||||||
|
.name = "LLVMInitialize" ++ arch_name ++ "AsmParser",
|
||||||
|
});
|
||||||
|
pub const initialize_disassembler = @extern(*const fn () callconv(.C) void, .{
|
||||||
|
.name = "LLVMInitialize" ++ arch_name ++ "Disassembler",
|
||||||
|
});
|
||||||
|
|
||||||
|
pub fn initialize(options: llvm.TargetInitializerOptions) void {
|
||||||
|
initialize_target_info();
|
||||||
|
initialize_target();
|
||||||
|
initialize_target_mc();
|
||||||
|
|
||||||
|
if (options.asm_printer) {
|
||||||
|
initialize_asm_printer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.asm_parser) {
|
||||||
|
initialize_asm_parser();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.disassembler) {
|
||||||
|
initialize_disassembler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
21
src/main.zig
21
src/main.zig
@ -1,4 +1,6 @@
|
|||||||
const lib = @import("lib.zig");
|
const lib = @import("lib.zig");
|
||||||
|
const llvm = @import("LLVM.zig");
|
||||||
|
const Arena = lib.Arena;
|
||||||
|
|
||||||
pub const panic = struct {
|
pub const panic = struct {
|
||||||
const abort = lib.os.abort;
|
const abort = lib.os.abort;
|
||||||
@ -133,19 +135,13 @@ pub const panic = struct {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() callconv(.C) c_int {
|
var global_persistent_arena: *Arena = undefined;
|
||||||
const arena = lib.Arena.initialize_default(2 * lib.MB);
|
|
||||||
_ = arena.allocate_bytes(1024, 1);
|
|
||||||
_ = arena.join_string(&.{ "foo", "fa" });
|
|
||||||
arena.reset();
|
|
||||||
lib.file.write(".zig-cache/foo", "fafu", .{});
|
|
||||||
const a = lib.file.read(arena, ".zig-cache/foo");
|
|
||||||
lib.assert(lib.string.equal(a, "fafu"));
|
|
||||||
|
|
||||||
var buffer: [100]u8 = undefined;
|
pub fn main() callconv(.C) c_int {
|
||||||
const written_character_count = lib.format(&buffer, buffer.len, "fjaksdjkasd {u64}\n", @as(u64, 123123));
|
lib.GlobalState.initialize();
|
||||||
const result_str = buffer[0..written_character_count];
|
|
||||||
lib.assert(lib.string.equal(result_str, "fjaksdjkasd 123123\n"));
|
llvm.initialize_all();
|
||||||
|
llvm.experiment();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,4 +155,5 @@ comptime {
|
|||||||
|
|
||||||
test {
|
test {
|
||||||
_ = lib;
|
_ = lib;
|
||||||
|
_ = llvm;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user