Merge pull request #117 from birth-software/c-abi-tests
Implement basic C ABI support
This commit is contained in:
commit
03f4d6368e
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@ -14,15 +14,17 @@ concurrency:
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
self_hosted_linux:
|
self_hosted_linux:
|
||||||
runs-on: [ self-hosted, Linux, x64 ]
|
#runs-on: [ self-hosted, Linux, x64 ]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 15
|
timeout-minutes: 15
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
- name: Test
|
- name: Test
|
||||||
run: |
|
run: |
|
||||||
zig build test -Dself_hosted_ci=true -Dstatic=true -Dllvm_path=../../../../../dev/llvm/llvm-static-release-zen4-17.0.6/out/x86_64-linux-musl-native
|
echo "TODO"
|
||||||
zig build test -Dself_hosted_ci=true -Dstatic=false
|
#zig build test -Dself_hosted_ci=true -Dstatic=true -Dllvm_path=../../../../../dev/llvm/llvm-static-release-zen4-17.0.6/out/x86_64-linux-musl-native
|
||||||
|
#zig build test -Dself_hosted_ci=true -Dstatic=false
|
||||||
# macos_m1:
|
# macos_m1:
|
||||||
# runs-on: macos-14
|
# runs-on: macos-14
|
||||||
# timeout-minutes: 15
|
# timeout-minutes: 15
|
||||||
|
2
.vscode/launch.json
vendored
2
.vscode/launch.json
vendored
@ -12,7 +12,7 @@
|
|||||||
"args": [
|
"args": [
|
||||||
"exe",
|
"exe",
|
||||||
"-main_source_file",
|
"-main_source_file",
|
||||||
"test/standalone/hello_world/main.nat"
|
"test/build/c-abi/main.nat",
|
||||||
],
|
],
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}",
|
||||||
},
|
},
|
||||||
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -1,3 +1,4 @@
|
|||||||
{
|
{
|
||||||
"zig.initialSetupDone": true
|
"zig.initialSetupDone": true,
|
||||||
|
"cmake.configureOnOpen": false
|
||||||
}
|
}
|
File diff suppressed because it is too large
Load Diff
@ -36,6 +36,7 @@ pub const LLVM = struct {
|
|||||||
llvm_instruction_map: MyHashMap(Compilation.Instruction.Index, *LLVM.Value) = .{},
|
llvm_instruction_map: MyHashMap(Compilation.Instruction.Index, *LLVM.Value) = .{},
|
||||||
llvm_value_map: MyHashMap(Compilation.V, *LLVM.Value) = .{},
|
llvm_value_map: MyHashMap(Compilation.V, *LLVM.Value) = .{},
|
||||||
llvm_block_map: MyHashMap(Compilation.BasicBlock.Index, *LLVM.Value.BasicBlock) = .{},
|
llvm_block_map: MyHashMap(Compilation.BasicBlock.Index, *LLVM.Value.BasicBlock) = .{},
|
||||||
|
llvm_external_functions: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.Function) = .{},
|
||||||
global_variable_map: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.GlobalVariable) = .{},
|
global_variable_map: MyHashMap(*Compilation.Debug.Declaration.Global, *LLVM.Value.Constant.GlobalVariable) = .{},
|
||||||
scope_map: MyHashMap(*Compilation.Debug.Scope, *LLVM.DebugInfo.Scope) = .{},
|
scope_map: MyHashMap(*Compilation.Debug.Scope, *LLVM.DebugInfo.Scope) = .{},
|
||||||
pointer_type: ?*LLVM.Type.Pointer = null,
|
pointer_type: ?*LLVM.Type.Pointer = null,
|
||||||
@ -46,11 +47,20 @@ pub const LLVM = struct {
|
|||||||
return_phi_node: ?*LLVM.Value.Instruction.PhiNode = null,
|
return_phi_node: ?*LLVM.Value.Instruction.PhiNode = null,
|
||||||
scope: *LLVM.DebugInfo.Scope = undefined,
|
scope: *LLVM.DebugInfo.Scope = undefined,
|
||||||
file: *LLVM.DebugInfo.File = undefined,
|
file: *LLVM.DebugInfo.File = undefined,
|
||||||
|
attributes: Attributes,
|
||||||
// subprogram: *LLVM.DebugInfo.Subprogram = undefined,
|
// subprogram: *LLVM.DebugInfo.Subprogram = undefined,
|
||||||
arg_index: u32 = 0,
|
arg_index: u32 = 0,
|
||||||
tag_count: c_uint = 0,
|
tag_count: c_uint = 0,
|
||||||
inside_branch: bool = false,
|
inside_branch: bool = false,
|
||||||
|
|
||||||
|
pub const Attributes = struct {
|
||||||
|
noreturn: *Attribute,
|
||||||
|
naked: *Attribute,
|
||||||
|
nounwind: *Attribute,
|
||||||
|
inreg: *Attribute,
|
||||||
|
@"noalias": *Attribute,
|
||||||
|
};
|
||||||
|
|
||||||
pub const Linkage = enum(c_uint) {
|
pub const Linkage = enum(c_uint) {
|
||||||
@"extern" = 0,
|
@"extern" = 0,
|
||||||
available_external = 1,
|
available_external = 1,
|
||||||
@ -80,6 +90,10 @@ pub const LLVM = struct {
|
|||||||
const getPointerType = bindings.NativityLLVMGetPointerType;
|
const getPointerType = bindings.NativityLLVMGetPointerType;
|
||||||
const getStructType = bindings.NativityLLVMGetStructType;
|
const getStructType = bindings.NativityLLVMGetStructType;
|
||||||
const getIntrinsicType = bindings.NativityLLVMContextGetIntrinsicType;
|
const getIntrinsicType = bindings.NativityLLVMContextGetIntrinsicType;
|
||||||
|
const getAttributeFromEnum = bindings.NativityLLVMContextGetAttributeFromEnum;
|
||||||
|
const getAttributeFromString = bindings.NativityLLVMContextGetAttributeFromString;
|
||||||
|
const getAttributeFromType = bindings.NativityLLVMContextGetAttributeFromType;
|
||||||
|
const getAttributeSet = bindings.NativityLLVMContextGetAttributeSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Module = opaque {
|
pub const Module = opaque {
|
||||||
@ -130,6 +144,7 @@ pub const LLVM = struct {
|
|||||||
const createGlobalString = bindings.NativityLLVMBuilderCreateGlobalString;
|
const createGlobalString = bindings.NativityLLVMBuilderCreateGlobalString;
|
||||||
const createGlobalStringPointer = bindings.NativityLLVMBuilderCreateGlobalStringPointer;
|
const createGlobalStringPointer = bindings.NativityLLVMBuilderCreateGlobalStringPointer;
|
||||||
const createPhi = bindings.NativityLLVMBuilderCreatePhi;
|
const createPhi = bindings.NativityLLVMBuilderCreatePhi;
|
||||||
|
const createMemcpy = bindings.NativityLLVMBuilderCreateMemcpy;
|
||||||
|
|
||||||
const getInsertBlock = bindings.NativityLLVMBuilderGetInsertBlock;
|
const getInsertBlock = bindings.NativityLLVMBuilderGetInsertBlock;
|
||||||
const isCurrentBlockTerminated = bindings.NativityLLVMBuilderIsCurrentBlockTerminated;
|
const isCurrentBlockTerminated = bindings.NativityLLVMBuilderIsCurrentBlockTerminated;
|
||||||
@ -552,90 +567,93 @@ pub const LLVM = struct {
|
|||||||
pub const Tuple = opaque {};
|
pub const Tuple = opaque {};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Attribute = enum(u32) {
|
pub const Attribute = opaque {
|
||||||
AllocAlign = 1,
|
pub const Set = opaque {};
|
||||||
AllocatedPointer = 2,
|
pub const Id = enum(u32) {
|
||||||
AlwaysInline = 3,
|
AllocAlign = 1,
|
||||||
Builtin = 4,
|
AllocatedPointer = 2,
|
||||||
Cold = 5,
|
AlwaysInline = 3,
|
||||||
Convergent = 6,
|
Builtin = 4,
|
||||||
DisableSanitizerInstrumentation = 7,
|
Cold = 5,
|
||||||
FnRetThunkExtern = 8,
|
Convergent = 6,
|
||||||
Hot = 9,
|
DisableSanitizerInstrumentation = 7,
|
||||||
ImmArg = 10,
|
FnRetThunkExtern = 8,
|
||||||
InReg = 11,
|
Hot = 9,
|
||||||
InlineHint = 12,
|
ImmArg = 10,
|
||||||
JumpTable = 13,
|
InReg = 11,
|
||||||
MinSize = 14,
|
InlineHint = 12,
|
||||||
MustProgress = 15,
|
JumpTable = 13,
|
||||||
Naked = 16,
|
MinSize = 14,
|
||||||
Nest = 17,
|
MustProgress = 15,
|
||||||
NoAlias = 18,
|
Naked = 16,
|
||||||
NoBuiltin = 19,
|
Nest = 17,
|
||||||
NoCallback = 20,
|
NoAlias = 18,
|
||||||
NoCapture = 21,
|
NoBuiltin = 19,
|
||||||
NoCfCheck = 22,
|
NoCallback = 20,
|
||||||
NoDuplicate = 23,
|
NoCapture = 21,
|
||||||
NoFree = 24,
|
NoCfCheck = 22,
|
||||||
NoImplicitFloat = 25,
|
NoDuplicate = 23,
|
||||||
NoInline = 26,
|
NoFree = 24,
|
||||||
NoMerge = 27,
|
NoImplicitFloat = 25,
|
||||||
NoProfile = 28,
|
NoInline = 26,
|
||||||
NoRecurse = 29,
|
NoMerge = 27,
|
||||||
NoRedZone = 30,
|
NoProfile = 28,
|
||||||
NoReturn = 31,
|
NoRecurse = 29,
|
||||||
NoSanitizeBounds = 32,
|
NoRedZone = 30,
|
||||||
NoSanitizeCoverage = 33,
|
NoReturn = 31,
|
||||||
NoSync = 34,
|
NoSanitizeBounds = 32,
|
||||||
NoUndef = 35,
|
NoSanitizeCoverage = 33,
|
||||||
NoUnwind = 36,
|
NoSync = 34,
|
||||||
NonLazyBind = 37,
|
NoUndef = 35,
|
||||||
NonNull = 38,
|
NoUnwind = 36,
|
||||||
NullPointerIsValid = 39,
|
NonLazyBind = 37,
|
||||||
OptForFuzzing = 40,
|
NonNull = 38,
|
||||||
OptimizeForSize = 41,
|
NullPointerIsValid = 39,
|
||||||
OptimizeNone = 42,
|
OptForFuzzing = 40,
|
||||||
PresplitCoroutine = 43,
|
OptimizeForSize = 41,
|
||||||
ReadNone = 44,
|
OptimizeNone = 42,
|
||||||
ReadOnly = 45,
|
PresplitCoroutine = 43,
|
||||||
Returned = 46,
|
ReadNone = 44,
|
||||||
ReturnsTwice = 47,
|
ReadOnly = 45,
|
||||||
SExt = 48,
|
Returned = 46,
|
||||||
SafeStack = 49,
|
ReturnsTwice = 47,
|
||||||
SanitizeAddress = 50,
|
SExt = 48,
|
||||||
SanitizeHWAddress = 51,
|
SafeStack = 49,
|
||||||
SanitizeMemTag = 52,
|
SanitizeAddress = 50,
|
||||||
SanitizeMemory = 53,
|
SanitizeHWAddress = 51,
|
||||||
SanitizeThread = 54,
|
SanitizeMemTag = 52,
|
||||||
ShadowCallStack = 55,
|
SanitizeMemory = 53,
|
||||||
SkipProfile = 56,
|
SanitizeThread = 54,
|
||||||
Speculatable = 57,
|
ShadowCallStack = 55,
|
||||||
SpeculativeLoadHardening = 58,
|
SkipProfile = 56,
|
||||||
StackProtect = 59,
|
Speculatable = 57,
|
||||||
StackProtectReq = 60,
|
SpeculativeLoadHardening = 58,
|
||||||
StackProtectStrong = 61,
|
StackProtect = 59,
|
||||||
StrictFP = 62,
|
StackProtectReq = 60,
|
||||||
SwiftAsync = 63,
|
StackProtectStrong = 61,
|
||||||
SwiftError = 64,
|
StrictFP = 62,
|
||||||
SwiftSelf = 65,
|
SwiftAsync = 63,
|
||||||
WillReturn = 66,
|
SwiftError = 64,
|
||||||
WriteOnly = 67,
|
SwiftSelf = 65,
|
||||||
ZExt = 68,
|
WillReturn = 66,
|
||||||
ByRef = 69,
|
WriteOnly = 67,
|
||||||
ByVal = 70,
|
ZExt = 68,
|
||||||
ElementType = 71,
|
ByRef = 69,
|
||||||
InAlloca = 72,
|
ByVal = 70,
|
||||||
Preallocated = 73,
|
ElementType = 71,
|
||||||
StructRet = 74,
|
InAlloca = 72,
|
||||||
Alignment = 75,
|
Preallocated = 73,
|
||||||
AllocKind = 76,
|
StructRet = 74,
|
||||||
AllocSize = 77,
|
Alignment = 75,
|
||||||
Dereferenceable = 78,
|
AllocKind = 76,
|
||||||
DereferenceableOrNull = 79,
|
AllocSize = 77,
|
||||||
Memory = 80,
|
Dereferenceable = 78,
|
||||||
StackAlignment = 81,
|
DereferenceableOrNull = 79,
|
||||||
UWTable = 82,
|
Memory = 80,
|
||||||
VScaleRange = 83,
|
StackAlignment = 81,
|
||||||
|
UWTable = 82,
|
||||||
|
VScaleRange = 83,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Type = opaque {
|
pub const Type = opaque {
|
||||||
@ -647,6 +665,7 @@ pub const LLVM = struct {
|
|||||||
const isPointer = bindings.NativityLLVMTypeIsPointer;
|
const isPointer = bindings.NativityLLVMTypeIsPointer;
|
||||||
const isInteger = bindings.NativityLLVMTypeIsInteger;
|
const isInteger = bindings.NativityLLVMTypeIsInteger;
|
||||||
const isVoid = bindings.NativityLLVMTypeIsVoid;
|
const isVoid = bindings.NativityLLVMTypeIsVoid;
|
||||||
|
const assertEqual = bindings.NativityLLVMTypeAssertEqual;
|
||||||
|
|
||||||
pub const Array = opaque {
|
pub const Array = opaque {
|
||||||
fn toType(integer: *@This()) *Type {
|
fn toType(integer: *@This()) *Type {
|
||||||
@ -748,6 +767,7 @@ pub const LLVM = struct {
|
|||||||
|
|
||||||
pub const Call = opaque {
|
pub const Call = opaque {
|
||||||
const setCallingConvention = bindings.NativityLLVMCallSetCallingConvention;
|
const setCallingConvention = bindings.NativityLLVMCallSetCallingConvention;
|
||||||
|
const setAttributes = bindings.NativityLLVMCallSetAttributes;
|
||||||
fn toValue(this: *@This()) *Value {
|
fn toValue(this: *@This()) *Value {
|
||||||
return @ptrCast(this);
|
return @ptrCast(this);
|
||||||
}
|
}
|
||||||
@ -860,15 +880,17 @@ pub const LLVM = struct {
|
|||||||
|
|
||||||
pub const Constant = opaque {
|
pub const Constant = opaque {
|
||||||
pub const Function = opaque {
|
pub const Function = opaque {
|
||||||
|
const getArgument = bindings.NativityLLVMFunctionGetArgument;
|
||||||
const getArguments = bindings.NativityLLVMFunctionGetArguments;
|
const getArguments = bindings.NativityLLVMFunctionGetArguments;
|
||||||
const getType = bindings.NativityLLVMFunctionGetType;
|
const getType = bindings.NativityLLVMFunctionGetType;
|
||||||
const addAttributeKey = bindings.NativityLLVMFunctionAddAttributeKey;
|
// const addAttributeKey = bindings.NativityLLVMFunctionAddAttributeKey;
|
||||||
const verify = bindings.NativityLLVMVerifyFunction;
|
const verify = bindings.NativityLLVMVerifyFunction;
|
||||||
const toString = bindings.NativityLLVMFunctionToString;
|
const toString = bindings.NativityLLVMFunctionToString;
|
||||||
const setCallingConvention = bindings.NativityLLVMFunctionSetCallingConvention;
|
const setCallingConvention = bindings.NativityLLVMFunctionSetCallingConvention;
|
||||||
const getCallingConvention = bindings.NativityLLVMFunctionGetCallingConvention;
|
const getCallingConvention = bindings.NativityLLVMFunctionGetCallingConvention;
|
||||||
const setSubprogram = bindings.NativityLLVMFunctionSetSubprogram;
|
const setSubprogram = bindings.NativityLLVMFunctionSetSubprogram;
|
||||||
const getSubprogram = bindings.NativityLLVMFunctionGetSubprogram;
|
const getSubprogram = bindings.NativityLLVMFunctionGetSubprogram;
|
||||||
|
const setAttributes = bindings.NativityLLVMFunctionSetAttributes;
|
||||||
|
|
||||||
fn toValue(this: *@This()) *Value {
|
fn toValue(this: *@This()) *Value {
|
||||||
return @ptrCast(this);
|
return @ptrCast(this);
|
||||||
@ -1181,21 +1203,11 @@ pub const LLVM = struct {
|
|||||||
const llvm_type: *LLVM.Type = switch (sema_type.*) {
|
const llvm_type: *LLVM.Type = switch (sema_type.*) {
|
||||||
.function => |function_prototype_index| blk: {
|
.function => |function_prototype_index| blk: {
|
||||||
const sema_function_prototype = unit.function_prototypes.get(function_prototype_index);
|
const sema_function_prototype = unit.function_prototypes.get(function_prototype_index);
|
||||||
const llvm_return_type = try llvm.getType(unit, context, sema_function_prototype.return_type);
|
const llvm_return_type = try llvm.getType(unit, context, sema_function_prototype.abi.return_type);
|
||||||
var parameter_types = try UnpinnedArray(*LLVM.Type).initialize_with_capacity(context.my_allocator, @intCast(sema_function_prototype.argument_types.len));
|
var parameter_types = try UnpinnedArray(*LLVM.Type).initialize_with_capacity(context.my_allocator, @intCast(sema_function_prototype.abi.parameter_types.len));
|
||||||
|
|
||||||
for (sema_function_prototype.argument_types) |argument_type_index| {
|
for (sema_function_prototype.abi.parameter_types) |argument_type_index| {
|
||||||
switch (unit.types.get(argument_type_index).*) {
|
parameter_types.append_with_capacity(try llvm.getType(unit, context, argument_type_index));
|
||||||
// TODO: ABI
|
|
||||||
.integer,
|
|
||||||
.pointer,
|
|
||||||
// .@"enum",
|
|
||||||
.@"struct",
|
|
||||||
.slice,
|
|
||||||
// .bool,
|
|
||||||
=> parameter_types.append_with_capacity(try llvm.getType(unit, context, argument_type_index)),
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const is_var_args = false;
|
const is_var_args = false;
|
||||||
@ -1265,6 +1277,16 @@ pub const LLVM = struct {
|
|||||||
|
|
||||||
break :blk struct_type.toType();
|
break :blk struct_type.toType();
|
||||||
},
|
},
|
||||||
|
.two_struct => |pair| blk: {
|
||||||
|
const types = [2]*LLVM.Type{
|
||||||
|
try llvm.getType(unit, context, pair[0]),
|
||||||
|
try llvm.getType(unit, context, pair[1]),
|
||||||
|
};
|
||||||
|
const is_packed = false;
|
||||||
|
const struct_type = llvm.context.getStructType(&types, types.len, is_packed) orelse return Type.Error.@"struct";
|
||||||
|
|
||||||
|
break :blk struct_type.toType();
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
.array => |array| blk: {
|
.array => |array| blk: {
|
||||||
@ -1289,11 +1311,12 @@ pub const LLVM = struct {
|
|||||||
if (llvm.debug_info_file_map.get(sema_file_index)) |file| {
|
if (llvm.debug_info_file_map.get(sema_file_index)) |file| {
|
||||||
return file;
|
return file;
|
||||||
} else {
|
} else {
|
||||||
|
// if (@intFromEnum(sema_file_index) == 4) @breakpoint();
|
||||||
const sema_file = unit.files.get(sema_file_index);
|
const sema_file = unit.files.get(sema_file_index);
|
||||||
const sub_path = std.fs.path.dirname(sema_file.relative_path) orelse "";
|
const full_path = try Compilation.joinPath(context, sema_file.package.directory.path, sema_file.relative_path);
|
||||||
const file_path = std.fs.path.basename(sema_file.relative_path);
|
const filename = std.fs.path.basename(full_path);
|
||||||
const directory_path = try Compilation.joinPath(context, sema_file.package.directory.path, sub_path);
|
const directory = full_path[0 .. full_path.len - filename.len];
|
||||||
const debug_file = llvm.debug_info_builder.createFile(file_path.ptr, file_path.len, directory_path.ptr, directory_path.len) orelse unreachable;
|
const debug_file = llvm.debug_info_builder.createFile(filename.ptr, filename.len, directory.ptr, directory.len) orelse unreachable;
|
||||||
try llvm.debug_info_file_map.put_no_clobber(context.my_allocator, sema_file_index, debug_file);
|
try llvm.debug_info_file_map.put_no_clobber(context.my_allocator, sema_file_index, debug_file);
|
||||||
return debug_file;
|
return debug_file;
|
||||||
}
|
}
|
||||||
@ -1868,6 +1891,7 @@ pub const LLVM = struct {
|
|||||||
.global => |global| {
|
.global => |global| {
|
||||||
const constant = switch (global.initial_value) {
|
const constant = switch (global.initial_value) {
|
||||||
.function_definition => llvm.function_definition_map.get(global).?.toConstant(),
|
.function_definition => llvm.function_definition_map.get(global).?.toConstant(),
|
||||||
|
.function_declaration => llvm.llvm_external_functions.get(global).?.toConstant(),
|
||||||
else => llvm.global_variable_map.get(global).?.toConstant(),
|
else => llvm.global_variable_map.get(global).?.toConstant(),
|
||||||
};
|
};
|
||||||
return constant;
|
return constant;
|
||||||
@ -1968,7 +1992,7 @@ pub const LLVM = struct {
|
|||||||
const len = llvm.context.getConstantInt(64, 0, false) orelse unreachable;
|
const len = llvm.context.getConstantInt(64, 0, false) orelse unreachable;
|
||||||
break :b .{ ptr.toConstant(), len.toConstant() };
|
break :b .{ ptr.toConstant(), len.toConstant() };
|
||||||
};
|
};
|
||||||
|
|
||||||
const constant_slice = slice_struct_type.getConstant(&slice_fields, slice_fields.len) orelse unreachable;
|
const constant_slice = slice_struct_type.getConstant(&slice_fields, slice_fields.len) orelse unreachable;
|
||||||
return constant_slice;
|
return constant_slice;
|
||||||
}
|
}
|
||||||
@ -2040,7 +2064,97 @@ pub const LLVM = struct {
|
|||||||
return call.toValue();
|
return call.toValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn emitParameterAttributes(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, abi: Compilation.Function.AbiInfo, is_return: bool) !*const LLVM.Attribute.Set {
|
||||||
|
var attributes = UnpinnedArray(*LLVM.Attribute){};
|
||||||
|
if (abi.attributes.by_reg) {
|
||||||
|
try attributes.append(context.my_allocator, llvm.attributes.inreg);
|
||||||
|
}
|
||||||
|
switch (abi.kind) {
|
||||||
|
.ignore => {
|
||||||
|
assert(is_return);
|
||||||
|
},
|
||||||
|
.direct, .direct_pair, .direct_coerce => {},
|
||||||
|
.indirect => |indirect| {
|
||||||
|
const indirect_type = try llvm.getType(unit, context, indirect.type);
|
||||||
|
if (is_return) {
|
||||||
|
const sret = llvm.context.getAttributeFromType(.StructRet, indirect_type);
|
||||||
|
try attributes.append(context.my_allocator, sret);
|
||||||
|
try attributes.append(context.my_allocator, llvm.attributes.@"noalias");
|
||||||
|
// TODO: alignment
|
||||||
|
} else {
|
||||||
|
if (abi.attributes.by_value) {
|
||||||
|
const byval = llvm.context.getAttributeFromType(.ByVal, indirect_type);
|
||||||
|
try attributes.append(context.my_allocator, byval);
|
||||||
|
}
|
||||||
|
//TODO: alignment
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
|
const attribute_set = llvm.context.getAttributeSet(attributes.pointer, attributes.length);
|
||||||
|
return attribute_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getFunctionAttributes(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, function_prototype: *Compilation.Function.Prototype) !*const LLVM.Attribute.Set {
|
||||||
|
var function_attributes = UnpinnedArray(*LLVM.Attribute){};
|
||||||
|
try function_attributes.append(context.my_allocator, llvm.attributes.nounwind);
|
||||||
|
|
||||||
|
switch (unit.types.get(function_prototype.return_type).*) {
|
||||||
|
.noreturn => {
|
||||||
|
try function_attributes.append(context.my_allocator, llvm.attributes.noreturn);
|
||||||
|
},
|
||||||
|
else => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function_prototype.attributes.naked) {
|
||||||
|
try function_attributes.append(context.my_allocator, llvm.attributes.naked);
|
||||||
|
}
|
||||||
|
|
||||||
|
const function_attribute_set = llvm.context.getAttributeSet(function_attributes.pointer, function_attributes.length);
|
||||||
|
return function_attribute_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CallOrFunction = union(enum) {
|
||||||
|
call: *LLVM.Value.Instruction.Call,
|
||||||
|
function: *LLVM.Value.Constant.Function,
|
||||||
|
};
|
||||||
|
|
||||||
|
fn setCallOrFunctionAttributes(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, function_prototype: *Compilation.Function.Prototype, call_or_function: CallOrFunction) !void {
|
||||||
|
const function_attribute_set = try llvm.getFunctionAttributes(unit, context, function_prototype);
|
||||||
|
|
||||||
|
var parameter_attribute_sets = try UnpinnedArray(*const LLVM.Attribute.Set).initialize_with_capacity(context.my_allocator, @intCast(function_prototype.abi.parameter_types_abi.len + @intFromBool(function_prototype.abi.return_type_abi.kind == .indirect)));
|
||||||
|
const return_attribute_set = blk: {
|
||||||
|
const attribute_set = try llvm.emitParameterAttributes(unit, context, function_prototype.abi.return_type_abi, true);
|
||||||
|
break :blk switch (function_prototype.abi.return_type_abi.kind) {
|
||||||
|
.indirect => b: {
|
||||||
|
parameter_attribute_sets.append_with_capacity(attribute_set);
|
||||||
|
break :b llvm.context.getAttributeSet(null, 0);
|
||||||
|
},
|
||||||
|
else => attribute_set,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
for (function_prototype.abi.parameter_types_abi) |parameter_type_abi| {
|
||||||
|
const parameter_attribute_set = try llvm.emitParameterAttributes(unit, context, parameter_type_abi, false);
|
||||||
|
parameter_attribute_sets.append_with_capacity(parameter_attribute_set);
|
||||||
|
}
|
||||||
|
|
||||||
|
const calling_convention = getCallingConvention(function_prototype.calling_convention);
|
||||||
|
|
||||||
|
switch (call_or_function) {
|
||||||
|
.call => |call| {
|
||||||
|
call.setAttributes(llvm.context, function_attribute_set, return_attribute_set, parameter_attribute_sets.pointer, parameter_attribute_sets.length);
|
||||||
|
call.setCallingConvention(calling_convention);
|
||||||
|
},
|
||||||
|
.function => |function| {
|
||||||
|
function.setAttributes(llvm.context, function_attribute_set, return_attribute_set, parameter_attribute_sets.pointer, parameter_attribute_sets.length);
|
||||||
|
function.setCallingConvention(calling_convention);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn emitFunctionDeclaration(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, declaration: *Compilation.Debug.Declaration.Global) !void {
|
fn emitFunctionDeclaration(llvm: *LLVM, unit: *Compilation.Unit, context: *const Compilation.Context, declaration: *Compilation.Debug.Declaration.Global) !void {
|
||||||
|
const name = unit.getIdentifier(declaration.declaration.name);
|
||||||
const function_type = try llvm.getType(unit, context, declaration.declaration.type);
|
const function_type = try llvm.getType(unit, context, declaration.declaration.type);
|
||||||
const is_export = declaration.attributes.contains(.@"export");
|
const is_export = declaration.attributes.contains(.@"export");
|
||||||
const is_extern = declaration.attributes.contains(.@"extern");
|
const is_extern = declaration.attributes.contains(.@"extern");
|
||||||
@ -2053,23 +2167,35 @@ pub const LLVM = struct {
|
|||||||
// TODO: Check name collision
|
// TODO: Check name collision
|
||||||
const mangle_name = !export_or_extern;
|
const mangle_name = !export_or_extern;
|
||||||
_ = mangle_name; // autofix
|
_ = mangle_name; // autofix
|
||||||
const name = unit.getIdentifier(declaration.declaration.name);
|
|
||||||
const function = llvm.module.createFunction(function_type.toFunction() orelse unreachable, linkage, address_space, name.ptr, name.len) orelse return Error.function;
|
const function = llvm.module.createFunction(function_type.toFunction() orelse unreachable, linkage, address_space, name.ptr, name.len) orelse return Error.function;
|
||||||
|
|
||||||
const function_prototype = unit.function_prototypes.get(unit.types.get(declaration.declaration.type).function);
|
const function_prototype = unit.function_prototypes.get(unit.types.get(declaration.declaration.type).function);
|
||||||
switch (unit.types.get(function_prototype.return_type).*) {
|
try llvm.setCallOrFunctionAttributes(unit, context, function_prototype, .{
|
||||||
.noreturn => {
|
.function = function,
|
||||||
function.addAttributeKey(.NoReturn);
|
});
|
||||||
},
|
// const calling_convention = getCallingConvention(function_prototype.calling_convention);
|
||||||
else => {},
|
// function.setCallingConvention(calling_convention);
|
||||||
}
|
//
|
||||||
|
// const function_attribute_set = llvm.getFunctionAttributes(unit, context, function_prototype);
|
||||||
|
//
|
||||||
|
// var parameter_attribute_sets = try UnpinnedArray(*const LLVM.Attribute.Set).initialize_with_capacity(context.my_allocator, @intCast(function_prototype.abi.parameter_types_abi.len + @intFromBool(function_prototype.abi.return_type_abi.kind == .indirect)));
|
||||||
|
// const return_attribute_set = blk: {
|
||||||
|
// const attribute_set = try llvm.emitParameterAttributes(unit, context, function_prototype.abi.return_type_abi, true);
|
||||||
|
// break :blk switch (function_prototype.abi.return_type_abi.kind) {
|
||||||
|
// .indirect => b: {
|
||||||
|
// parameter_attribute_sets.append_with_capacity(attribute_set);
|
||||||
|
// break :b llvm.context.getAttributeSet(null, 0);
|
||||||
|
// },
|
||||||
|
// else => attribute_set,
|
||||||
|
// };
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// for (function_prototype.abi.parameter_types_abi) |parameter_type_abi| {
|
||||||
|
// const parameter_attribute_set = try llvm.emitParameterAttributes(unit, context, parameter_type_abi, false);
|
||||||
|
// parameter_attribute_sets.append_with_capacity(parameter_attribute_set);
|
||||||
|
// }
|
||||||
|
|
||||||
if (function_prototype.attributes.naked) {
|
// function.setAttributes(llvm.context, function_attribute_set, return_attribute_set, parameter_attribute_sets.pointer, parameter_attribute_sets.length);
|
||||||
function.addAttributeKey(.Naked);
|
|
||||||
}
|
|
||||||
|
|
||||||
const calling_convention = getCallingConvention(function_prototype.calling_convention);
|
|
||||||
function.setCallingConvention(calling_convention);
|
|
||||||
|
|
||||||
switch (declaration.initial_value) {
|
switch (declaration.initial_value) {
|
||||||
.function_declaration => try llvm.function_declaration_map.put_no_clobber(context.my_allocator, declaration, function),
|
.function_declaration => try llvm.function_declaration_map.put_no_clobber(context.my_allocator, declaration, function),
|
||||||
@ -2078,6 +2204,7 @@ pub const LLVM = struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unit.descriptor.generate_debug_information) {
|
if (unit.descriptor.generate_debug_information) {
|
||||||
|
// if (data_structures.byte_equal(name, "nat_split_struct_ints")) @breakpoint();
|
||||||
const debug_file = try llvm.getDebugInfoFile(unit, context, declaration.declaration.scope.file);
|
const debug_file = try llvm.getDebugInfoFile(unit, context, declaration.declaration.scope.file);
|
||||||
var parameter_types = try UnpinnedArray(*LLVM.DebugInfo.Type).initialize_with_capacity(context.my_allocator, @intCast(function_prototype.argument_types.len));
|
var parameter_types = try UnpinnedArray(*LLVM.DebugInfo.Type).initialize_with_capacity(context.my_allocator, @intCast(function_prototype.argument_types.len));
|
||||||
for (function_prototype.argument_types) |argument_type_index| {
|
for (function_prototype.argument_types) |argument_type_index| {
|
||||||
@ -2116,7 +2243,6 @@ pub const LLVM = struct {
|
|||||||
};
|
};
|
||||||
const subroutine_type_calling_convention = LLVM.DebugInfo.CallingConvention.none;
|
const subroutine_type_calling_convention = LLVM.DebugInfo.CallingConvention.none;
|
||||||
const subroutine_type = llvm.debug_info_builder.createSubroutineType(parameter_types.pointer, parameter_types.length, subroutine_type_flags, subroutine_type_calling_convention) orelse unreachable;
|
const subroutine_type = llvm.debug_info_builder.createSubroutineType(parameter_types.pointer, parameter_types.length, subroutine_type_flags, subroutine_type_calling_convention) orelse unreachable;
|
||||||
const scope_line = 0;
|
|
||||||
const subprogram_flags = LLVM.DebugInfo.Subprogram.Flags{
|
const subprogram_flags = LLVM.DebugInfo.Subprogram.Flags{
|
||||||
.virtuality = .none,
|
.virtuality = .none,
|
||||||
.local_to_unit = !export_or_extern,
|
.local_to_unit = !export_or_extern,
|
||||||
@ -2131,11 +2257,13 @@ pub const LLVM = struct {
|
|||||||
};
|
};
|
||||||
const subprogram_declaration = null;
|
const subprogram_declaration = null;
|
||||||
const function_name = unit.getIdentifier(declaration.declaration.name);
|
const function_name = unit.getIdentifier(declaration.declaration.name);
|
||||||
const subprogram = llvm.debug_info_builder.createFunction(debug_file.toScope(), function_name.ptr, function_name.len, function_name.ptr, function_name.len, debug_file, declaration.declaration.line + 1, subroutine_type, scope_line, subroutine_type_flags, subprogram_flags, subprogram_declaration) orelse unreachable;
|
const subprogram = llvm.debug_info_builder.createFunction(debug_file.toScope(), function_name.ptr, function_name.len, function_name.ptr, function_name.len, debug_file, declaration.declaration.line + 1, subroutine_type, declaration.declaration.line + 1, subroutine_type_flags, subprogram_flags, subprogram_declaration) orelse unreachable;
|
||||||
function.setSubprogram(subprogram);
|
function.setSubprogram(subprogram);
|
||||||
|
|
||||||
switch (declaration.initial_value) {
|
switch (declaration.initial_value) {
|
||||||
.function_declaration => {},
|
.function_declaration => {
|
||||||
|
try llvm.llvm_external_functions.put_no_clobber(context.my_allocator, declaration, function);
|
||||||
|
},
|
||||||
.function_definition => |function_definition_index| {
|
.function_definition => |function_definition_index| {
|
||||||
const function_definition = unit.function_definitions.get(function_definition_index);
|
const function_definition = unit.function_definitions.get(function_definition_index);
|
||||||
const scope = subprogram.toLocalScope().toScope();
|
const scope = subprogram.toLocalScope().toScope();
|
||||||
@ -2185,12 +2313,20 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.module = module,
|
.module = module,
|
||||||
.builder = builder,
|
.builder = builder,
|
||||||
.debug_info_builder = module.createDebugInfoBuilder() orelse return Error.debug_info_builder,
|
.debug_info_builder = module.createDebugInfoBuilder() orelse return Error.debug_info_builder,
|
||||||
|
.attributes = .{
|
||||||
|
.naked = llvm_context.getAttributeFromEnum(.Naked, 0),
|
||||||
|
.noreturn = llvm_context.getAttributeFromEnum(.NoReturn, 0),
|
||||||
|
.nounwind = llvm_context.getAttributeFromEnum(.NoUnwind, 0),
|
||||||
|
.inreg = llvm_context.getAttributeFromEnum(.InReg, 0),
|
||||||
|
.@"noalias" = llvm_context.getAttributeFromEnum(.NoAlias, 0),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (unit.descriptor.generate_debug_information) {
|
if (unit.descriptor.generate_debug_information) {
|
||||||
const filename = "main";
|
const full_path = try std.fs.cwd().realpathAlloc(context.allocator, unit.descriptor.main_package_path);
|
||||||
const directory = ".";
|
const filename = std.fs.path.basename(full_path);
|
||||||
const debug_info_file = llvm.debug_info_builder.createFile(filename, filename.len, directory, directory.len) orelse unreachable;
|
const directory = full_path[0 .. full_path.len - filename.len];
|
||||||
|
const debug_info_file = llvm.debug_info_builder.createFile(filename.ptr, filename.len, directory.ptr, directory.len) orelse unreachable;
|
||||||
const producer = "nativity";
|
const producer = "nativity";
|
||||||
const is_optimized = false;
|
const is_optimized = false;
|
||||||
const flags = "";
|
const flags = "";
|
||||||
@ -2291,7 +2427,6 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
llvm.scope = subprogram.toLocalScope().toScope();
|
llvm.scope = subprogram.toLocalScope().toScope();
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm.arg_index = 0;
|
|
||||||
var alloca_map = MyHashMap(Compilation.Instruction.Index, *LLVM.Value){};
|
var alloca_map = MyHashMap(Compilation.Instruction.Index, *LLVM.Value){};
|
||||||
|
|
||||||
var block_command_list = BasicBlockList{};
|
var block_command_list = BasicBlockList{};
|
||||||
@ -2438,18 +2573,23 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, call.toValue());
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, call.toValue());
|
||||||
},
|
},
|
||||||
.stack_slot => |stack_slot| {
|
.stack_slot => |stack_slot| {
|
||||||
|
// const stack_slot_type = unit.types.get(stack_slot.type);
|
||||||
|
// const stack_slot_alignment = stack_slot_type.getAbiAlignment(unit);
|
||||||
const declaration_type = try llvm.getType(unit, context, stack_slot.type);
|
const declaration_type = try llvm.getType(unit, context, stack_slot.type);
|
||||||
|
const type_alignment = unit.types.get(stack_slot.type).getAbiAlignment(unit);
|
||||||
const alloca_array_size = null;
|
const alloca_array_size = null;
|
||||||
const declaration_alloca = llvm.builder.createAlloca(declaration_type, address_space, alloca_array_size, "", "".len) orelse return LLVM.Value.Instruction.Error.alloca;
|
const declaration_alloca = llvm.builder.createAlloca(declaration_type, address_space, alloca_array_size, "", "".len, type_alignment) orelse return LLVM.Value.Instruction.Error.alloca;
|
||||||
try alloca_map.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue());
|
try alloca_map.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue());
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue());
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue());
|
||||||
},
|
},
|
||||||
.store => |store| {
|
.store => |store| {
|
||||||
const right = try llvm.emitRightValue(unit, context, store.source);
|
const right = try llvm.emitRightValue(unit, context, store.source);
|
||||||
|
const source_type = unit.types.get(store.source.type);
|
||||||
|
const alignment = source_type.getAbiAlignment(unit);
|
||||||
|
|
||||||
const is_volatile = false;
|
const is_volatile = false;
|
||||||
const left = try llvm.emitLeftValue(unit, context, store.destination);
|
const left = try llvm.emitLeftValue(unit, context, store.destination);
|
||||||
const store_instruction = llvm.builder.createStore(right, left, is_volatile) orelse return LLVM.Value.Instruction.Error.store;
|
const store_instruction = llvm.builder.createStore(right, left, is_volatile, alignment) orelse return LLVM.Value.Instruction.Error.store;
|
||||||
_ = store_instruction; // autofix
|
_ = store_instruction; // autofix
|
||||||
},
|
},
|
||||||
.cast => |cast| {
|
.cast => |cast| {
|
||||||
@ -2469,6 +2609,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.slice_to_nullable,
|
.slice_to_nullable,
|
||||||
.slice_to_not_null,
|
.slice_to_not_null,
|
||||||
.slice_coerce_to_zero_termination,
|
.slice_coerce_to_zero_termination,
|
||||||
|
.slice_zero_to_no_termination,
|
||||||
.pointer_to_nullable,
|
.pointer_to_nullable,
|
||||||
.pointer_const_to_var,
|
.pointer_const_to_var,
|
||||||
.pointer_to_array_to_pointer_to_many,
|
.pointer_to_array_to_pointer_to_many,
|
||||||
@ -2515,9 +2656,11 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
break :blk value;
|
break :blk value;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const load_type = unit.types.get(load.type);
|
||||||
|
const alignment = if (load.alignment) |alignment| alignment else load_type.getAbiAlignment(unit);
|
||||||
const value_type = try llvm.getType(unit, context, load.type);
|
const value_type = try llvm.getType(unit, context, load.type);
|
||||||
const is_volatile = false;
|
const is_volatile = false;
|
||||||
const load_i = llvm.builder.createLoad(value_type, value, is_volatile, "", "".len) orelse return LLVM.Value.Instruction.Error.load;
|
const load_i = llvm.builder.createLoad(value_type, value, is_volatile, "", "".len, alignment) orelse return LLVM.Value.Instruction.Error.load;
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, load_i.toValue());
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, load_i.toValue());
|
||||||
},
|
},
|
||||||
.integer_binary_operation => |binary_operation| {
|
.integer_binary_operation => |binary_operation| {
|
||||||
@ -2553,66 +2696,60 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
};
|
};
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, instruction);
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, instruction);
|
||||||
},
|
},
|
||||||
.call => |call| {
|
.call => |sema_call| {
|
||||||
var argument_buffer: [32]*LLVM.Value = undefined;
|
var argument_buffer: [32]*LLVM.Value = undefined;
|
||||||
const argument_count = call.arguments.len;
|
const argument_count = sema_call.arguments.len;
|
||||||
const arguments = argument_buffer[0..argument_count];
|
const arguments = argument_buffer[0..argument_count];
|
||||||
|
|
||||||
switch (call.callable.value) {
|
const call_function_type = unit.types.get(sema_call.function_type);
|
||||||
.@"comptime" => |ct| switch (ct) {
|
const function_prototype = unit.function_prototypes.get(call_function_type.function);
|
||||||
.global => |call_function_declaration| {
|
const call_type = try llvm.getType(unit, context, sema_call.function_type);
|
||||||
const call_function_type = call_function_declaration.declaration.type;
|
|
||||||
const call_function_prototype = unit.function_prototypes.get(unit.types.get(call_function_type).function);
|
|
||||||
assert(call_function_type == call.function_type);
|
|
||||||
|
|
||||||
|
const call = switch (sema_call.callable.value) {
|
||||||
|
.@"comptime" => |ct| switch (ct) {
|
||||||
|
.global => |call_function_declaration| b: {
|
||||||
const callee = switch (call_function_declaration.initial_value) {
|
const callee = switch (call_function_declaration.initial_value) {
|
||||||
.function_definition => llvm.function_definition_map.get(call_function_declaration).?,
|
.function_definition => llvm.function_definition_map.get(call_function_declaration).?,
|
||||||
.function_declaration => llvm.function_declaration_map.get(call_function_declaration).?,
|
.function_declaration => llvm.function_declaration_map.get(call_function_declaration).?,
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
|
|
||||||
for (call.arguments, arguments) |argument_value, *argument| {
|
for (sema_call.arguments, arguments) |argument_value, *argument| {
|
||||||
argument.* = try llvm.emitRightValue(unit, context, argument_value);
|
argument.* = try llvm.emitRightValue(unit, context, argument_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const llvm_calling_convention = callee.getCallingConvention();
|
|
||||||
const name = "";
|
const name = "";
|
||||||
const call_type = try llvm.getType(unit, context, call.function_type);
|
const function_name = unit.getIdentifier(call_function_declaration.declaration.name);
|
||||||
|
_ = function_name; // autofix
|
||||||
const function_type = call_type.toFunction() orelse unreachable;
|
const function_type = call_type.toFunction() orelse unreachable;
|
||||||
for (call.arguments, arguments, call_function_prototype.argument_types, 0..) |sema_argument, argument, sema_argument_type, i| {
|
for (sema_call.arguments, arguments, function_prototype.abi.parameter_types, 0..) |sema_argument, argument, sema_argument_type, i| {
|
||||||
assert(sema_argument.type == sema_argument_type);
|
assert(sema_argument.type == sema_argument_type);
|
||||||
const argument_type = function_type.getArgumentType(@intCast(i));
|
const argument_type = function_type.getArgumentType(@intCast(i));
|
||||||
assert(argument_type == argument.getType());
|
argument_type.assertEqual(argument.getType());
|
||||||
}
|
}
|
||||||
const call_instruction = llvm.builder.createCall(function_type, callee.toValue(), arguments.ptr, arguments.len, name.ptr, name.len, null) orelse return LLVM.Value.Instruction.Error.call;
|
const call_instruction = llvm.builder.createCall(function_type, callee.toValue(), arguments.ptr, arguments.len, name.ptr, name.len, null) orelse return LLVM.Value.Instruction.Error.call;
|
||||||
call_instruction.setCallingConvention(llvm_calling_convention);
|
break :b call_instruction;
|
||||||
|
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, call_instruction.toValue());
|
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
},
|
},
|
||||||
.runtime => |ii| {
|
.runtime => |ii| b: {
|
||||||
const callee = llvm.llvm_instruction_map.get(ii).?;
|
const callee = llvm.llvm_instruction_map.get(ii).?;
|
||||||
const callable_type = unit.types.get(call.function_type);
|
for (sema_call.arguments, arguments) |argument_value, *argument| {
|
||||||
const sema_calling_convention = switch (callable_type.*) {
|
|
||||||
.function => |function_prototype_index| unit.function_prototypes.get(function_prototype_index).calling_convention,
|
|
||||||
else => |t| @panic(@tagName(t)),
|
|
||||||
};
|
|
||||||
const calling_convention = getCallingConvention(sema_calling_convention);
|
|
||||||
for (call.arguments, arguments) |argument_value, *argument| {
|
|
||||||
argument.* = try llvm.emitRightValue(unit, context, argument_value);
|
argument.* = try llvm.emitRightValue(unit, context, argument_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
const name = "";
|
const name = "";
|
||||||
const call_type = try llvm.getType(unit, context, call.function_type);
|
|
||||||
const function_type = call_type.toFunction() orelse unreachable;
|
const function_type = call_type.toFunction() orelse unreachable;
|
||||||
const call_instruction = llvm.builder.createCall(function_type, callee, arguments.ptr, arguments.len, name.ptr, name.len, null) orelse return LLVM.Value.Instruction.Error.call;
|
const call_instruction = llvm.builder.createCall(function_type, callee, arguments.ptr, arguments.len, name.ptr, name.len, null) orelse return LLVM.Value.Instruction.Error.call;
|
||||||
call_instruction.setCallingConvention(calling_convention);
|
break :b call_instruction;
|
||||||
|
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, call_instruction.toValue());
|
|
||||||
},
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
};
|
||||||
|
|
||||||
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, call.toValue());
|
||||||
|
|
||||||
|
try llvm.setCallOrFunctionAttributes(unit, context, function_prototype, .{
|
||||||
|
.call = call,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
.ret => |return_value| {
|
.ret => |return_value| {
|
||||||
const value = switch (return_value.type) {
|
const value = switch (return_value.type) {
|
||||||
@ -2670,25 +2807,16 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.@"unreachable" => {
|
.@"unreachable" => {
|
||||||
_ = llvm.builder.createUnreachable() orelse return LLVM.Value.Instruction.Error.@"unreachable";
|
_ = llvm.builder.createUnreachable() orelse return LLVM.Value.Instruction.Error.@"unreachable";
|
||||||
},
|
},
|
||||||
.argument_declaration => |argument_declaration| {
|
.abi_argument => |argument_index| {
|
||||||
var argument_buffer: [16]*LLVM.Value.Argument = undefined;
|
const argument = llvm.function.getArgument(argument_index) orelse unreachable;
|
||||||
var argument_count: usize = argument_buffer.len;
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, argument.toValue());
|
||||||
llvm.function.getArguments(&argument_buffer, &argument_count);
|
},
|
||||||
const arguments = argument_buffer[0..argument_count];
|
.debug_declare_argument => |debug_declare| {
|
||||||
const argument_index = llvm.arg_index;
|
|
||||||
llvm.arg_index += 1;
|
|
||||||
const argument = arguments[argument_index];
|
|
||||||
const name = unit.getIdentifier(argument_declaration.declaration.name);
|
|
||||||
argument.toValue().setName(name.ptr, name.len);
|
|
||||||
const argument_type_index = argument_declaration.declaration.type;
|
|
||||||
_ = argument_type_index; // autofix
|
|
||||||
const argument_type = argument.toValue().getType();
|
|
||||||
const alloca_array_size: ?*LLVM.Value = null;
|
|
||||||
const argument_value = argument.toValue();
|
|
||||||
const declaration_alloca = llvm.builder.createAlloca(argument_type, address_space, alloca_array_size, "", "".len) orelse return LLVM.Value.Instruction.Error.alloca;
|
|
||||||
|
|
||||||
if (unit.descriptor.generate_debug_information) {
|
if (unit.descriptor.generate_debug_information) {
|
||||||
const debug_declaration_type = try llvm.getDebugType(unit, context, argument_declaration.declaration.type);
|
const argument_index: c_uint = debug_declare.argument.index;
|
||||||
|
const declaration = &debug_declare.argument.declaration;
|
||||||
|
const debug_declaration_type = try llvm.getDebugType(unit, context, declaration.type);
|
||||||
|
const declaration_alloca = llvm.llvm_instruction_map.get(debug_declare.stack).?;
|
||||||
const always_preserve = true;
|
const always_preserve = true;
|
||||||
const flags = LLVM.DebugInfo.Node.Flags{
|
const flags = LLVM.DebugInfo.Node.Flags{
|
||||||
.visibility = .none,
|
.visibility = .none,
|
||||||
@ -2719,65 +2847,61 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
.little_endian = false,
|
.little_endian = false,
|
||||||
.all_calls_described = false,
|
.all_calls_described = false,
|
||||||
};
|
};
|
||||||
const declaration_name = unit.getIdentifier(argument_declaration.declaration.name);
|
const declaration_name = unit.getIdentifier(declaration.name);
|
||||||
const line = argument_declaration.declaration.line;
|
const line = declaration.line;
|
||||||
const column = argument_declaration.declaration.column;
|
const column = declaration.column;
|
||||||
const debug_parameter_variable = llvm.debug_info_builder.createParameterVariable(llvm.scope, declaration_name.ptr, declaration_name.len, argument_index + 1, llvm.file, line, debug_declaration_type, always_preserve, flags) orelse unreachable;
|
const debug_parameter_variable = llvm.debug_info_builder.createParameterVariable(llvm.scope, declaration_name.ptr, declaration_name.len, argument_index + 1, llvm.file, line, debug_declaration_type, always_preserve, flags) orelse unreachable;
|
||||||
|
|
||||||
const insert_declare = llvm.debug_info_builder.insertDeclare(declaration_alloca.toValue(), debug_parameter_variable, llvm.context, line, column, (llvm.function.getSubprogram() orelse unreachable).toLocalScope().toScope(), llvm.builder.getInsertBlock() orelse unreachable);
|
const insert_declare = llvm.debug_info_builder.insertDeclare(declaration_alloca, debug_parameter_variable, llvm.context, line, column, (llvm.function.getSubprogram() orelse unreachable).toLocalScope().toScope(), llvm.builder.getInsertBlock() orelse unreachable);
|
||||||
_ = insert_declare;
|
_ = insert_declare;
|
||||||
}
|
}
|
||||||
|
|
||||||
const is_volatile = false;
|
|
||||||
const store = llvm.builder.createStore(argument_value, declaration_alloca.toValue(), is_volatile) orelse return LLVM.Value.Instruction.Error.store;
|
|
||||||
_ = store; // autofix
|
|
||||||
try llvm.argument_allocas.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue());
|
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, declaration_alloca.toValue());
|
|
||||||
},
|
},
|
||||||
.debug_declare_local_variable => |declare_local_variable| {
|
.debug_declare_local_variable => |declare_local_variable| {
|
||||||
const local_variable = declare_local_variable.variable;
|
if (unit.descriptor.generate_debug_information) {
|
||||||
const debug_declaration_type = try llvm.getDebugType(unit, context, local_variable.declaration.type);
|
const local_variable = declare_local_variable.variable;
|
||||||
const always_preserve = true;
|
const debug_declaration_type = try llvm.getDebugType(unit, context, local_variable.declaration.type);
|
||||||
const flags = LLVM.DebugInfo.Node.Flags{
|
const always_preserve = true;
|
||||||
.visibility = .none,
|
const flags = LLVM.DebugInfo.Node.Flags{
|
||||||
.forward_declaration = false,
|
.visibility = .none,
|
||||||
.apple_block = false,
|
.forward_declaration = false,
|
||||||
.block_by_ref_struct = false,
|
.apple_block = false,
|
||||||
.virtual = false,
|
.block_by_ref_struct = false,
|
||||||
.artificial = false,
|
.virtual = false,
|
||||||
.explicit = false,
|
.artificial = false,
|
||||||
.prototyped = false,
|
.explicit = false,
|
||||||
.objective_c_class_complete = false,
|
.prototyped = false,
|
||||||
.object_pointer = false,
|
.objective_c_class_complete = false,
|
||||||
.vector = false,
|
.object_pointer = false,
|
||||||
.static_member = false,
|
.vector = false,
|
||||||
.lvalue_reference = false,
|
.static_member = false,
|
||||||
.rvalue_reference = false,
|
.lvalue_reference = false,
|
||||||
.reserved = false,
|
.rvalue_reference = false,
|
||||||
.inheritance = .none,
|
.reserved = false,
|
||||||
.introduced_virtual = false,
|
.inheritance = .none,
|
||||||
.bit_field = false,
|
.introduced_virtual = false,
|
||||||
.no_return = false,
|
.bit_field = false,
|
||||||
.type_pass_by_value = false,
|
.no_return = false,
|
||||||
.type_pass_by_reference = false,
|
.type_pass_by_value = false,
|
||||||
.enum_class = false,
|
.type_pass_by_reference = false,
|
||||||
.thunk = false,
|
.enum_class = false,
|
||||||
.non_trivial = false,
|
.thunk = false,
|
||||||
.big_endian = false,
|
.non_trivial = false,
|
||||||
.little_endian = false,
|
.big_endian = false,
|
||||||
.all_calls_described = false,
|
.little_endian = false,
|
||||||
};
|
.all_calls_described = false,
|
||||||
|
};
|
||||||
|
|
||||||
const alignment = 0;
|
const alignment = 0;
|
||||||
const declaration_name = unit.getIdentifier(local_variable.declaration.name);
|
const declaration_name = unit.getIdentifier(local_variable.declaration.name);
|
||||||
const line = local_variable.declaration.line;
|
const line = local_variable.declaration.line;
|
||||||
const column = local_variable.declaration.column;
|
const column = local_variable.declaration.column;
|
||||||
const debug_local_variable = llvm.debug_info_builder.createAutoVariable(llvm.scope, declaration_name.ptr, declaration_name.len, llvm.file, line, debug_declaration_type, always_preserve, flags, alignment) orelse unreachable;
|
const debug_local_variable = llvm.debug_info_builder.createAutoVariable(llvm.scope, declaration_name.ptr, declaration_name.len, llvm.file, line, debug_declaration_type, always_preserve, flags, alignment) orelse unreachable;
|
||||||
|
|
||||||
const local = alloca_map.get(declare_local_variable.stack).?;
|
const local = alloca_map.get(declare_local_variable.stack).?;
|
||||||
|
|
||||||
const insert_declare = llvm.debug_info_builder.insertDeclare(local, debug_local_variable, llvm.context, line, column, (llvm.function.getSubprogram() orelse unreachable).toLocalScope().toScope(), llvm.builder.getInsertBlock() orelse unreachable);
|
const insert_declare = llvm.debug_info_builder.insertDeclare(local, debug_local_variable, llvm.context, line, column, (llvm.function.getSubprogram() orelse unreachable).toLocalScope().toScope(), llvm.builder.getInsertBlock() orelse unreachable);
|
||||||
_ = insert_declare;
|
_ = insert_declare;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.insert_value => |insert_value| {
|
.insert_value => |insert_value| {
|
||||||
const aggregate = try llvm.emitRightValue(unit, context, insert_value.expression);
|
const aggregate = try llvm.emitRightValue(unit, context, insert_value.expression);
|
||||||
@ -2916,6 +3040,21 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
const switch_instruction = llvm.builder.createSwitch(condition, else_block, condition_array.pointer, basic_block_array.pointer, condition_array.length, branch_weights, unpredictable);
|
const switch_instruction = llvm.builder.createSwitch(condition, else_block, condition_array.pointer, basic_block_array.pointer, condition_array.length, branch_weights, unpredictable);
|
||||||
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, switch_instruction.toValue());
|
try llvm.llvm_instruction_map.put_no_clobber(context.my_allocator, instruction_index, switch_instruction.toValue());
|
||||||
},
|
},
|
||||||
|
.memcpy => |memcpy| {
|
||||||
|
const destination = try llvm.emitLeftValue(unit, context, memcpy.destination);
|
||||||
|
const source = try llvm.emitLeftValue(unit, context, memcpy.source);
|
||||||
|
const destination_alignment = if (memcpy.destination_alignment) |alignment| alignment else b: {
|
||||||
|
const ty = unit.types.get(memcpy.destination.type);
|
||||||
|
const alignment = ty.getAbiAlignment(unit);
|
||||||
|
break :b alignment;
|
||||||
|
};
|
||||||
|
const source_alignment = if (memcpy.source_alignment) |alignment| alignment else b: {
|
||||||
|
const ty = unit.types.get(memcpy.source.type);
|
||||||
|
const alignment = ty.getAbiAlignment(unit);
|
||||||
|
break :b alignment;
|
||||||
|
};
|
||||||
|
_ = llvm.builder.createMemcpy(destination, destination_alignment, source, source_alignment, memcpy.size, memcpy.is_volatile);
|
||||||
|
},
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2965,7 +3104,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
const module_dump = module_ptr[0..module_len];
|
const module_dump = module_ptr[0..module_len];
|
||||||
_ = module_dump; // autofix
|
_ = module_dump; // autofix
|
||||||
|
|
||||||
try write(.llvm, function_ir);
|
try write(.panic, function_ir);
|
||||||
const error_message = message_ptr[0..message_len];
|
const error_message = message_ptr[0..message_len];
|
||||||
try write(.panic, error_message);
|
try write(.panic, error_message);
|
||||||
// std.debug.print("\nLLVM verification for function inside module failed:\nFull module: {s}\n```\n{s}\n```\n{s}\n", .{ module_dump, function_ir, error_message });
|
// std.debug.print("\nLLVM verification for function inside module failed:\nFull module: {s}\n```\n{s}\n```\n{s}\n", .{ module_dump, function_ir, error_message });
|
||||||
@ -2982,6 +3121,7 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
// logln(.llvm, .print_module, "{s}", .{module_string});
|
// logln(.llvm, .print_module, "{s}", .{module_string});
|
||||||
|
|
||||||
const verify_module = true;
|
const verify_module = true;
|
||||||
|
const print_module = true;
|
||||||
if (verify_module) {
|
if (verify_module) {
|
||||||
var message_ptr: [*]const u8 = undefined;
|
var message_ptr: [*]const u8 = undefined;
|
||||||
var message_len: usize = 0;
|
var message_len: usize = 0;
|
||||||
@ -2995,6 +3135,12 @@ pub fn codegen(unit: *Compilation.Unit, context: *const Compilation.Context) !vo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (print_module) {
|
||||||
|
try write(.llvm, "Module: \n");
|
||||||
|
try write(.llvm, module_string);
|
||||||
|
try write(.llvm, "\n");
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: initialize only the target we are going to use
|
// TODO: initialize only the target we are going to use
|
||||||
bindings.NativityLLVMInitializeCodeGeneration();
|
bindings.NativityLLVMInitializeCodeGeneration();
|
||||||
// TODO: proper target selection
|
// TODO: proper target selection
|
||||||
|
@ -50,21 +50,29 @@ pub extern fn NativityLLVMValueSetName(value: *LLVM.Value, name_ptr: [*]const u8
|
|||||||
pub extern fn NativityLLVMValueGetType(value: *LLVM.Value) *LLVM.Type;
|
pub extern fn NativityLLVMValueGetType(value: *LLVM.Value) *LLVM.Type;
|
||||||
pub extern fn NativityLLVMArgumentGetIndex(argument: *LLVM.Value.Argument) c_uint;
|
pub extern fn NativityLLVMArgumentGetIndex(argument: *LLVM.Value.Argument) c_uint;
|
||||||
pub extern fn NativityLLVMFunctionGetArguments(function: *LLVM.Value.Constant.Function, argument_ptr: [*]*LLVM.Value.Argument, argument_len: *usize) void;
|
pub extern fn NativityLLVMFunctionGetArguments(function: *LLVM.Value.Constant.Function, argument_ptr: [*]*LLVM.Value.Argument, argument_len: *usize) void;
|
||||||
|
pub extern fn NativityLLVMFunctionGetArgument(function: *LLVM.Value.Constant.Function, index: c_uint) ?*LLVM.Value.Argument;
|
||||||
pub extern fn NativityLLVMFunctionGetType(function: *LLVM.Value.Constant.Function) *LLVM.Type.Function;
|
pub extern fn NativityLLVMFunctionGetType(function: *LLVM.Value.Constant.Function) *LLVM.Type.Function;
|
||||||
pub extern fn NativityLLVMFunctionTypeGetReturnType(function_type: *LLVM.Type.Function) *LLVM.Type;
|
pub extern fn NativityLLVMFunctionTypeGetReturnType(function_type: *LLVM.Type.Function) *LLVM.Type;
|
||||||
pub extern fn NativityLLVMTypeIsVoid(type: *LLVM.Type) bool;
|
pub extern fn NativityLLVMTypeIsVoid(type: *LLVM.Type) bool;
|
||||||
pub extern fn NativityLLVMBuilderCreateAlloca(builder: *LLVM.Builder, type: *LLVM.Type, address_space: c_uint, array_size: ?*LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value.Instruction.Alloca;
|
pub extern fn NativityLLVMBuilderCreateAlloca(builder: *LLVM.Builder, type: *LLVM.Type, address_space: c_uint, array_size: ?*LLVM.Value, name_ptr: [*]const u8, name_len: usize, alignment: u32) ?*LLVM.Value.Instruction.Alloca;
|
||||||
pub extern fn NativityLLVMBuilderCreateStore(builder: *LLVM.Builder, value: *LLVM.Value, pointer: *LLVM.Value, is_volatile: bool) ?*LLVM.Value.Instruction.Store;
|
pub extern fn NativityLLVMBuilderCreateStore(builder: *LLVM.Builder, value: *LLVM.Value, pointer: *LLVM.Value, is_volatile: bool, alignment: u32) ?*LLVM.Value.Instruction.Store;
|
||||||
|
pub extern fn NativityLLVMBuilderCreateMemcpy(builder: *LLVM.Builder, destination: *LLVM.Value, destination_alignment: u32, source: *LLVM.Value, source_alignment: u32, size: u64, is_volatile: bool) *LLVM.Value.Instruction.Call;
|
||||||
pub extern fn NativityLLVMContextGetConstantInt(context: *LLVM.Context, bit_count: c_uint, value: u64, is_signed: bool) ?*LLVM.Value.Constant.Int;
|
pub extern fn NativityLLVMContextGetConstantInt(context: *LLVM.Context, bit_count: c_uint, value: u64, is_signed: bool) ?*LLVM.Value.Constant.Int;
|
||||||
pub extern fn NativityLLVMContextGetConstantString(context: *LLVM.Context, name_ptr: [*]const u8, name_len: usize, null_terminate: bool) ?*LLVM.Value.Constant;
|
pub extern fn NativityLLVMContextGetConstantString(context: *LLVM.Context, name_ptr: [*]const u8, name_len: usize, null_terminate: bool) ?*LLVM.Value.Constant;
|
||||||
pub extern fn NativityLLVMGetConstantArray(array_type: *LLVM.Type.Array, value_ptr: [*]const *LLVM.Value.Constant, value_count: usize) ?*LLVM.Value.Constant;
|
pub extern fn NativityLLVMGetConstantArray(array_type: *LLVM.Type.Array, value_ptr: [*]const *LLVM.Value.Constant, value_count: usize) ?*LLVM.Value.Constant;
|
||||||
pub extern fn NativityLLVMGetConstantStruct(struct_type: *LLVM.Type.Struct, constant_ptr: [*]const *LLVM.Value.Constant, constant_len: usize) ?*LLVM.Value.Constant;
|
pub extern fn NativityLLVMGetConstantStruct(struct_type: *LLVM.Type.Struct, constant_ptr: [*]const *LLVM.Value.Constant, constant_len: usize) ?*LLVM.Value.Constant;
|
||||||
pub extern fn NativityLLVMConstantToInt(constant: *LLVM.Value.Constant) ?*LLVM.Value.Constant.Int;
|
pub extern fn NativityLLVMConstantToInt(constant: *LLVM.Value.Constant) ?*LLVM.Value.Constant.Int;
|
||||||
pub extern fn NativityLLVMBuilderCreateICmp(builder: *LLVM.Builder, integer_comparison: LLVM.Value.Instruction.ICmp.Kind, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
pub extern fn NativityLLVMBuilderCreateICmp(builder: *LLVM.Builder, integer_comparison: LLVM.Value.Instruction.ICmp.Kind, left: *LLVM.Value, right: *LLVM.Value, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||||
pub extern fn NativityLLVMBuilderCreateLoad(builder: *LLVM.Builder, type: *LLVM.Type, value: *LLVM.Value, is_volatile: bool, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value.Instruction.Load;
|
pub extern fn NativityLLVMBuilderCreateLoad(builder: *LLVM.Builder, type: *LLVM.Type, value: *LLVM.Value, is_volatile: bool, name_ptr: [*]const u8, name_len: usize, alignment: u32) ?*LLVM.Value.Instruction.Load;
|
||||||
pub extern fn NativityLLVMBuilderCreateRet(builder: *LLVM.Builder, value: ?*LLVM.Value) ?*LLVM.Value.Instruction.Ret;
|
pub extern fn NativityLLVMBuilderCreateRet(builder: *LLVM.Builder, value: ?*LLVM.Value) ?*LLVM.Value.Instruction.Ret;
|
||||||
pub extern fn NativityLLVMBuilderCreateCast(builder: *LLVM.Builder, cast_type: LLVM.Value.Instruction.Cast.Type, value: *LLVM.Value, type: *LLVM.Type, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
pub extern fn NativityLLVMBuilderCreateCast(builder: *LLVM.Builder, cast_type: LLVM.Value.Instruction.Cast.Type, value: *LLVM.Value, type: *LLVM.Type, name_ptr: [*]const u8, name_len: usize) ?*LLVM.Value;
|
||||||
pub extern fn NativityLLVMFunctionAddAttributeKey(builder: *LLVM.Value.Constant.Function, attribute_key: LLVM.Attribute) void;
|
pub extern fn NativityLLVMContextGetAttributeFromEnum(context: *LLVM.Context, attribute_key: LLVM.Attribute.Id, attribute_value: u64) *LLVM.Attribute;
|
||||||
|
pub extern fn NativityLLVMContextGetAttributeFromString(context: *LLVM.Context, key_ptr: [*]const u8, key_len: usize, value_ptr: [*]const u8, value_len: usize) *LLVM.Attribute;
|
||||||
|
pub extern fn NativityLLVMContextGetAttributeFromType(context: *LLVM.Context, attribute_key: LLVM.Attribute.Id, type: *LLVM.Type) *LLVM.Attribute;
|
||||||
|
pub extern fn NativityLLVMContextGetAttributeSet(context: *LLVM.Context, attribute_ptr: ?[*]const *LLVM.Attribute, attribute_count: usize) *const LLVM.Attribute.Set;
|
||||||
|
pub extern fn NativityLLVMFunctionSetAttributes(function: *LLVM.Value.Constant.Function, context: *LLVM.Context, function_attributes: *const LLVM.Attribute.Set, return_attributes: *const LLVM.Attribute.Set, parameter_attribute_set_ptr: [*]const *const LLVM.Attribute.Set, parameter_attribute_set_count: usize) void;
|
||||||
|
pub extern fn NativityLLVMCallSetAttributes(call: *LLVM.Value.Instruction.Call, context: *LLVM.Context, function_attributes: *const LLVM.Attribute.Set, return_attributes: *const LLVM.Attribute.Set, parameter_attribute_set_ptr: [*]const *const LLVM.Attribute.Set, parameter_attribute_set_count: usize) void;
|
||||||
|
// pub extern fn NativityLLVMFunctionAddAttributeKey(builder: *LLVM.Value.Constant.Function, attribute_key: LLVM.Attribute) void;
|
||||||
pub extern fn NativityLLVMGetVoidType(context: *LLVM.Context) ?*LLVM.Type;
|
pub extern fn NativityLLVMGetVoidType(context: *LLVM.Context) ?*LLVM.Type;
|
||||||
pub extern fn NativityLLVMGetInlineAssembly(function_type: *LLVM.Type.Function, assembly_ptr: [*]const u8, assembly_len: usize, constraints_ptr: [*]const u8, constrains_len: usize, has_side_effects: bool, is_align_stack: bool, dialect: LLVM.Value.InlineAssembly.Dialect, can_throw: bool) ?*LLVM.Value.InlineAssembly;
|
pub extern fn NativityLLVMGetInlineAssembly(function_type: *LLVM.Type.Function, assembly_ptr: [*]const u8, assembly_len: usize, constraints_ptr: [*]const u8, constrains_len: usize, has_side_effects: bool, is_align_stack: bool, dialect: LLVM.Value.InlineAssembly.Dialect, can_throw: bool) ?*LLVM.Value.InlineAssembly;
|
||||||
pub extern fn NativityLLVMBuilderCreateCall(builder: *LLVM.Builder, function_type: *LLVM.Type.Function, callee: *LLVM.Value, argument_ptr: [*]const *LLVM.Value, argument_count: usize, name_ptr: [*]const u8, name_len: usize, fp_math_tag: ?*LLVM.Metadata.Node) ?*LLVM.Value.Instruction.Call;
|
pub extern fn NativityLLVMBuilderCreateCall(builder: *LLVM.Builder, function_type: *LLVM.Type.Function, callee: *LLVM.Value, argument_ptr: [*]const *LLVM.Value, argument_count: usize, name_ptr: [*]const u8, name_len: usize, fp_math_tag: ?*LLVM.Metadata.Node) ?*LLVM.Value.Instruction.Call;
|
||||||
@ -143,6 +151,7 @@ pub extern fn NativityLLVMTargetCreateTargetMachine(target: *LLVM.Target, target
|
|||||||
pub extern fn NativityLLVMModuleSetTargetMachineDataLayout(module: *LLVM.Module, target_machine: *LLVM.Target.Machine) void;
|
pub extern fn NativityLLVMModuleSetTargetMachineDataLayout(module: *LLVM.Module, target_machine: *LLVM.Target.Machine) void;
|
||||||
pub extern fn NativityLLVMModuleSetTargetTriple(module: *LLVM.Module, target_triple_ptr: [*]const u8, target_triple_len: usize) void;
|
pub extern fn NativityLLVMModuleSetTargetTriple(module: *LLVM.Module, target_triple_ptr: [*]const u8, target_triple_len: usize) void;
|
||||||
pub extern fn NativityLLVMModuleAddPassesToEmitFile(module: *LLVM.Module, target_machine: *LLVM.Target.Machine, object_file_path_ptr: [*]const u8, object_file_path_len: usize, codegen_file_type: LLVM.CodeGenFileType, disable_verify: bool) bool;
|
pub extern fn NativityLLVMModuleAddPassesToEmitFile(module: *LLVM.Module, target_machine: *LLVM.Target.Machine, object_file_path_ptr: [*]const u8, object_file_path_len: usize, codegen_file_type: LLVM.CodeGenFileType, disable_verify: bool) bool;
|
||||||
|
pub extern fn NativityLLVMTypeAssertEqual(a: *LLVM.Type, b: *LLVM.Type) void;
|
||||||
pub extern fn NativityLLDLinkELF(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
pub extern fn NativityLLDLinkELF(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||||
pub extern fn NativityLLDLinkCOFF(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
pub extern fn NativityLLDLinkCOFF(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||||
pub extern fn NativityLLDLinkMachO(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
pub extern fn NativityLLDLinkMachO(argument_ptr: [*]const [*:0]const u8, argument_count: usize, stdout_ptr: *[*]const u8, stdout_len: *usize, stderr_ptr: *[*]const u8, stderr_len: *usize) bool;
|
||||||
|
@ -67,7 +67,7 @@ pub fn analyze(allocator: *MyAllocator, text: []const u8, token_buffer: *Token.B
|
|||||||
var index: u32 = 0;
|
var index: u32 = 0;
|
||||||
var line_index: u32 = lexer.line_offset;
|
var line_index: u32 = lexer.line_offset;
|
||||||
|
|
||||||
try token_buffer.ensure_with_capacity(allocator, len / 4);
|
try token_buffer.ensure_with_capacity(allocator, len / 3);
|
||||||
|
|
||||||
// logln(.lexer, .end, "START LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{ Token.unwrap(lexer.offset), lexer.line_offset });
|
// logln(.lexer, .end, "START LEXER - TOKEN OFFSET: {} - LINE OFFSET: {}", .{ Token.unwrap(lexer.offset), lexer.line_offset });
|
||||||
|
|
||||||
|
@ -420,13 +420,23 @@ const Analyzer = struct {
|
|||||||
if (data_structures.byte_equal(identifier_name, enum_field.name)) {
|
if (data_structures.byte_equal(identifier_name, enum_field.name)) {
|
||||||
const attribute = @field(Compilation.Function.Attribute, enum_field.name);
|
const attribute = @field(Compilation.Function.Attribute, enum_field.name);
|
||||||
const attribute_node = switch (attribute) {
|
const attribute_node = switch (attribute) {
|
||||||
.naked,
|
.naked => try analyzer.addNode(.{
|
||||||
=> try analyzer.addNode(.{
|
|
||||||
.id = @field(Node.Id, "function_attribute_" ++ @tagName(attribute)),
|
.id = @field(Node.Id, "function_attribute_" ++ @tagName(attribute)),
|
||||||
.token = identifier,
|
.token = identifier,
|
||||||
.left = .null,
|
.left = .null,
|
||||||
.right = .null,
|
.right = .null,
|
||||||
}),
|
}),
|
||||||
|
.cc => try analyzer.addNode(.{
|
||||||
|
.id = .function_attribute_cc,
|
||||||
|
.token = identifier,
|
||||||
|
.left = b: {
|
||||||
|
_ = try analyzer.expectToken(.operator_left_parenthesis);
|
||||||
|
const cc = try analyzer.expression();
|
||||||
|
_ = try analyzer.expectToken(.operator_right_parenthesis);
|
||||||
|
break :b cc;
|
||||||
|
},
|
||||||
|
.right = .null,
|
||||||
|
}),
|
||||||
else => |t| @panic(@tagName(t)),
|
else => |t| @panic(@tagName(t)),
|
||||||
};
|
};
|
||||||
break attribute_node;
|
break attribute_node;
|
||||||
@ -462,7 +472,11 @@ const Analyzer = struct {
|
|||||||
var list = UnpinnedArray(Node.Index){};
|
var list = UnpinnedArray(Node.Index){};
|
||||||
|
|
||||||
while (analyzer.peekToken() != end_token) {
|
while (analyzer.peekToken() != end_token) {
|
||||||
const identifier = try analyzer.expectToken(.identifier);
|
const identifier_token = analyzer.token_i;
|
||||||
|
switch (analyzer.peekToken()) {
|
||||||
|
.identifier, .discard => analyzer.consumeToken(),
|
||||||
|
else => |t| @panic(@tagName(t)),
|
||||||
|
}
|
||||||
_ = try analyzer.expectToken(.operator_colon);
|
_ = try analyzer.expectToken(.operator_colon);
|
||||||
const type_expression = try analyzer.typeExpression();
|
const type_expression = try analyzer.typeExpression();
|
||||||
|
|
||||||
@ -472,7 +486,7 @@ const Analyzer = struct {
|
|||||||
|
|
||||||
try list.append(analyzer.my_allocator, try analyzer.addNode(.{
|
try list.append(analyzer.my_allocator, try analyzer.addNode(.{
|
||||||
.id = .argument_declaration,
|
.id = .argument_declaration,
|
||||||
.token = identifier,
|
.token = identifier_token,
|
||||||
.left = type_expression,
|
.left = type_expression,
|
||||||
.right = Node.Index.null,
|
.right = Node.Index.null,
|
||||||
}));
|
}));
|
||||||
|
@ -2,6 +2,7 @@ const std = @import("std");
|
|||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
const os = builtin.os.tag;
|
const os = builtin.os.tag;
|
||||||
const arch = builtin.cpu.arch;
|
const arch = builtin.cpu.arch;
|
||||||
|
const page_size = std.mem.page_size;
|
||||||
|
|
||||||
pub fn assert(ok: bool) void {
|
pub fn assert(ok: bool) void {
|
||||||
if (!ok) unreachable;
|
if (!ok) unreachable;
|
||||||
@ -257,7 +258,7 @@ pub fn MyHashMap(comptime K: type, comptime V: type) type {
|
|||||||
.Slice => byte_equal(k, key),
|
.Slice => byte_equal(k, key),
|
||||||
else => k == key,
|
else => k == key,
|
||||||
},
|
},
|
||||||
.Struct => equal(k, key),
|
.Struct, .Array => equal(k, key),
|
||||||
else => k == key,
|
else => k == key,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -331,7 +332,6 @@ pub fn enumFromString(comptime E: type, string: []const u8) ?E {
|
|||||||
} else null;
|
} else null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const page_size = std.mem.page_size;
|
|
||||||
extern fn pthread_jit_write_protect_np(enabled: bool) void;
|
extern fn pthread_jit_write_protect_np(enabled: bool) void;
|
||||||
|
|
||||||
pub fn allocate_virtual_memory(size: usize, flags: packed struct {
|
pub fn allocate_virtual_memory(size: usize, flags: packed struct {
|
||||||
@ -353,10 +353,10 @@ pub fn allocate_virtual_memory(size: usize, flags: packed struct {
|
|||||||
.linux => u32,
|
.linux => u32,
|
||||||
.macos => c_int,
|
.macos => c_int,
|
||||||
else => @compileError("OS not supported"),
|
else => @compileError("OS not supported"),
|
||||||
} = if (flags.executable) std.os.PROT.EXEC else 0;
|
} = if (flags.executable) std.posix.PROT.EXEC else 0;
|
||||||
const protection_flags: u32 = @intCast(std.os.PROT.READ | std.os.PROT.WRITE | execute_flag);
|
const protection_flags: u32 = @intCast(std.posix.PROT.READ | std.posix.PROT.WRITE | execute_flag);
|
||||||
|
|
||||||
const result = try std.os.mmap(null, size, protection_flags, .{
|
const result = try std.posix.mmap(null, size, protection_flags, .{
|
||||||
.TYPE = .PRIVATE,
|
.TYPE = .PRIVATE,
|
||||||
.ANONYMOUS = true,
|
.ANONYMOUS = true,
|
||||||
}, -1, 0);
|
}, -1, 0);
|
||||||
@ -372,13 +372,13 @@ pub fn allocate_virtual_memory(size: usize, flags: packed struct {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn free_virtual_memory(slice: []align(0x1000) const u8) void {
|
pub fn free_virtual_memory(slice: []align(page_size) const u8) void {
|
||||||
switch (os) {
|
switch (os) {
|
||||||
.windows => {
|
.windows => {
|
||||||
std.os.windows.VirtualFree(slice.ptr, slice.len, std.os.windows.MEM_RELEASE);
|
std.os.windows.VirtualFree(slice.ptr, slice.len, std.os.windows.MEM_RELEASE);
|
||||||
},
|
},
|
||||||
else => {
|
else => {
|
||||||
std.os.munmap(slice);
|
std.posix.munmap(slice);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -726,7 +726,7 @@ pub fn span(ptr: [*:0]const u8) [:0]const u8 {
|
|||||||
|
|
||||||
pub fn last(bytes: []const u8, byte: u8) ?usize {
|
pub fn last(bytes: []const u8, byte: u8) ?usize {
|
||||||
var i = bytes.len;
|
var i = bytes.len;
|
||||||
while (i > 0) {
|
while (i > 0) {
|
||||||
i -= 1;
|
i -= 1;
|
||||||
|
|
||||||
if (bytes[i] == byte) {
|
if (bytes[i] == byte) {
|
||||||
@ -736,3 +736,8 @@ pub fn last(bytes: []const u8, byte: u8) ?usize {
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn align_forward(value: u64, alignment: u64) u64 {
|
||||||
|
const mask = alignment - 1;
|
||||||
|
return (value + mask) & ~mask;
|
||||||
|
}
|
||||||
|
@ -55,7 +55,7 @@ pub fn entry_point(arguments: [][*:0]u8) !void {
|
|||||||
return error.InvalidInput;
|
return error.InvalidInput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (std.process.can_execv and std.os.getenvZ(env_detecting_libc_paths) != null) {
|
if (std.process.can_execv and std.posix.getenvZ(env_detecting_libc_paths) != null) {
|
||||||
todo();
|
todo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
558
build.zig
558
build.zig
@ -1,14 +1,32 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
const builtin = @import("builtin");
|
||||||
|
const arch = builtin.cpu.arch;
|
||||||
|
const os = builtin.os.tag;
|
||||||
|
|
||||||
|
fn discover_brew_prefix(b: *std.Build, library_name: []const u8) ![]const u8 {
|
||||||
|
assert(os == .macos);
|
||||||
|
const result = try std.ChildProcess.run(.{
|
||||||
|
.allocator = b.allocator,
|
||||||
|
.argv = &.{ "brew", "--prefix", library_name },
|
||||||
|
});
|
||||||
|
|
||||||
|
var i = result.stdout.len - 1;
|
||||||
|
while (result.stdout[i] == '\n' or result.stdout[i] == ' ') {
|
||||||
|
i -= 1;
|
||||||
|
}
|
||||||
|
const trimmed_path = result.stdout[0 .. i + 1];
|
||||||
|
return trimmed_path;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(b: *std.Build) !void {
|
pub fn build(b: *std.Build) !void {
|
||||||
const self_hosted_ci = b.option(bool, "self_hosted_ci", "This option enables the self-hosted CI behavior") orelse false;
|
const self_hosted_ci = b.option(bool, "self_hosted_ci", "This option enables the self-hosted CI behavior") orelse false;
|
||||||
const third_party_ci = b.option(bool, "third_party_ci", "This option enables the third-party CI behavior") orelse false;
|
const third_party_ci = b.option(bool, "third_party_ci", "This option enables the third-party CI behavior") orelse false;
|
||||||
const is_ci = self_hosted_ci or third_party_ci;
|
const is_ci = self_hosted_ci or third_party_ci;
|
||||||
const print_stack_trace = b.option(bool, "print_stack_trace", "This option enables printing stack traces inside the compiler") orelse is_ci or @import("builtin").os.tag == .macos;
|
const print_stack_trace = b.option(bool, "print_stack_trace", "This option enables printing stack traces inside the compiler") orelse is_ci or os == .macos;
|
||||||
const native_target = b.resolveTargetQuery(.{});
|
const native_target = b.resolveTargetQuery(.{});
|
||||||
const optimization = b.standardOptimizeOption(.{});
|
const optimization = b.standardOptimizeOption(.{});
|
||||||
const static = b.option(bool, "static", "This option enables the compiler to be built statically") orelse false;
|
const static = b.option(bool, "static", "This option enables the compiler to be built statically") orelse true;
|
||||||
const compiler_options = b.addOptions();
|
const compiler_options = b.addOptions();
|
||||||
compiler_options.addOption(bool, "print_stack_trace", print_stack_trace);
|
compiler_options.addOption(bool, "print_stack_trace", print_stack_trace);
|
||||||
|
|
||||||
@ -21,7 +39,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
var target_query = b.standardTargetOptionsQueryOnly(.{});
|
var target_query = b.standardTargetOptionsQueryOnly(.{});
|
||||||
const abi = b.option(std.Target.Abi, "abi", "This option modifies the ABI used for the compiler") orelse if (static) switch (native_target.result.os.tag) {
|
const abi = b.option(std.Target.Abi, "abi", "This option modifies the ABI used for the compiler") orelse if (static) switch (os) {
|
||||||
else => target_query.abi,
|
else => target_query.abi,
|
||||||
.linux => b: {
|
.linux => b: {
|
||||||
const os_release = try std.fs.cwd().readFileAlloc(b.allocator, "/etc/os-release", 0xffff);
|
const os_release = try std.fs.cwd().readFileAlloc(b.allocator, "/etc/os-release", 0xffff);
|
||||||
@ -86,8 +104,249 @@ pub fn build(b: *std.Build) !void {
|
|||||||
|
|
||||||
compiler.linkLibC();
|
compiler.linkLibC();
|
||||||
|
|
||||||
|
const zstd = if (target.result.os.tag == .windows) "zstd.lib" else "libzstd.a";
|
||||||
|
|
||||||
|
const static_llvm_libraries = [_][]const u8{
|
||||||
|
"libLLVMAArch64AsmParser.a",
|
||||||
|
"libLLVMAArch64CodeGen.a",
|
||||||
|
"libLLVMAArch64Desc.a",
|
||||||
|
"libLLVMAArch64Disassembler.a",
|
||||||
|
"libLLVMAArch64Info.a",
|
||||||
|
"libLLVMAArch64Utils.a",
|
||||||
|
"libLLVMAggressiveInstCombine.a",
|
||||||
|
"libLLVMAMDGPUAsmParser.a",
|
||||||
|
"libLLVMAMDGPUCodeGen.a",
|
||||||
|
"libLLVMAMDGPUDesc.a",
|
||||||
|
"libLLVMAMDGPUDisassembler.a",
|
||||||
|
"libLLVMAMDGPUInfo.a",
|
||||||
|
"libLLVMAMDGPUTargetMCA.a",
|
||||||
|
"libLLVMAMDGPUUtils.a",
|
||||||
|
"libLLVMAnalysis.a",
|
||||||
|
"libLLVMARMAsmParser.a",
|
||||||
|
"libLLVMARMCodeGen.a",
|
||||||
|
"libLLVMARMDesc.a",
|
||||||
|
"libLLVMARMDisassembler.a",
|
||||||
|
"libLLVMARMInfo.a",
|
||||||
|
"libLLVMARMUtils.a",
|
||||||
|
"libLLVMAsmParser.a",
|
||||||
|
"libLLVMAsmPrinter.a",
|
||||||
|
"libLLVMAVRAsmParser.a",
|
||||||
|
"libLLVMAVRCodeGen.a",
|
||||||
|
"libLLVMAVRDesc.a",
|
||||||
|
"libLLVMAVRDisassembler.a",
|
||||||
|
"libLLVMAVRInfo.a",
|
||||||
|
"libLLVMBinaryFormat.a",
|
||||||
|
"libLLVMBitReader.a",
|
||||||
|
"libLLVMBitstreamReader.a",
|
||||||
|
"libLLVMBitWriter.a",
|
||||||
|
"libLLVMBPFAsmParser.a",
|
||||||
|
"libLLVMBPFCodeGen.a",
|
||||||
|
"libLLVMBPFDesc.a",
|
||||||
|
"libLLVMBPFDisassembler.a",
|
||||||
|
"libLLVMBPFInfo.a",
|
||||||
|
"libLLVMCFGuard.a",
|
||||||
|
"libLLVMCFIVerify.a",
|
||||||
|
"libLLVMCodeGen.a",
|
||||||
|
"libLLVMCodeGenTypes.a",
|
||||||
|
"libLLVMCore.a",
|
||||||
|
"libLLVMCoroutines.a",
|
||||||
|
"libLLVMCoverage.a",
|
||||||
|
"libLLVMDebugInfoBTF.a",
|
||||||
|
"libLLVMDebugInfoCodeView.a",
|
||||||
|
"libLLVMDebuginfod.a",
|
||||||
|
"libLLVMDebugInfoDWARF.a",
|
||||||
|
"libLLVMDebugInfoGSYM.a",
|
||||||
|
"libLLVMDebugInfoLogicalView.a",
|
||||||
|
"libLLVMDebugInfoMSF.a",
|
||||||
|
"libLLVMDebugInfoPDB.a",
|
||||||
|
"libLLVMDemangle.a",
|
||||||
|
"libLLVMDiff.a",
|
||||||
|
"libLLVMDlltoolDriver.a",
|
||||||
|
"libLLVMDWARFLinker.a",
|
||||||
|
"libLLVMDWARFLinkerParallel.a",
|
||||||
|
"libLLVMDWP.a",
|
||||||
|
"libLLVMExecutionEngine.a",
|
||||||
|
"libLLVMExtensions.a",
|
||||||
|
"libLLVMFileCheck.a",
|
||||||
|
"libLLVMFrontendHLSL.a",
|
||||||
|
"libLLVMFrontendOpenACC.a",
|
||||||
|
"libLLVMFrontendOpenMP.a",
|
||||||
|
"libLLVMFuzzerCLI.a",
|
||||||
|
"libLLVMFuzzMutate.a",
|
||||||
|
"libLLVMGlobalISel.a",
|
||||||
|
"libLLVMHexagonAsmParser.a",
|
||||||
|
"libLLVMHexagonCodeGen.a",
|
||||||
|
"libLLVMHexagonDesc.a",
|
||||||
|
"libLLVMHexagonDisassembler.a",
|
||||||
|
"libLLVMHexagonInfo.a",
|
||||||
|
"libLLVMInstCombine.a",
|
||||||
|
"libLLVMInstrumentation.a",
|
||||||
|
"libLLVMInterfaceStub.a",
|
||||||
|
"libLLVMInterpreter.a",
|
||||||
|
"libLLVMipo.a",
|
||||||
|
"libLLVMIRPrinter.a",
|
||||||
|
"libLLVMIRReader.a",
|
||||||
|
"libLLVMJITLink.a",
|
||||||
|
"libLLVMLanaiAsmParser.a",
|
||||||
|
"libLLVMLanaiCodeGen.a",
|
||||||
|
"libLLVMLanaiDesc.a",
|
||||||
|
"libLLVMLanaiDisassembler.a",
|
||||||
|
"libLLVMLanaiInfo.a",
|
||||||
|
"libLLVMLibDriver.a",
|
||||||
|
"libLLVMLineEditor.a",
|
||||||
|
"libLLVMLinker.a",
|
||||||
|
"libLLVMLoongArchAsmParser.a",
|
||||||
|
"libLLVMLoongArchCodeGen.a",
|
||||||
|
"libLLVMLoongArchDesc.a",
|
||||||
|
"libLLVMLoongArchDisassembler.a",
|
||||||
|
"libLLVMLoongArchInfo.a",
|
||||||
|
"libLLVMLTO.a",
|
||||||
|
"libLLVMMC.a",
|
||||||
|
"libLLVMMCA.a",
|
||||||
|
"libLLVMMCDisassembler.a",
|
||||||
|
"libLLVMMCJIT.a",
|
||||||
|
"libLLVMMCParser.a",
|
||||||
|
"libLLVMMipsAsmParser.a",
|
||||||
|
"libLLVMMipsCodeGen.a",
|
||||||
|
"libLLVMMipsDesc.a",
|
||||||
|
"libLLVMMipsDisassembler.a",
|
||||||
|
"libLLVMMipsInfo.a",
|
||||||
|
"libLLVMMIRParser.a",
|
||||||
|
"libLLVMMSP430AsmParser.a",
|
||||||
|
"libLLVMMSP430CodeGen.a",
|
||||||
|
"libLLVMMSP430Desc.a",
|
||||||
|
"libLLVMMSP430Disassembler.a",
|
||||||
|
"libLLVMMSP430Info.a",
|
||||||
|
"libLLVMNVPTXCodeGen.a",
|
||||||
|
"libLLVMNVPTXDesc.a",
|
||||||
|
"libLLVMNVPTXInfo.a",
|
||||||
|
"libLLVMObjCARCOpts.a",
|
||||||
|
"libLLVMObjCopy.a",
|
||||||
|
"libLLVMObject.a",
|
||||||
|
"libLLVMObjectYAML.a",
|
||||||
|
"libLLVMOption.a",
|
||||||
|
"libLLVMOrcJIT.a",
|
||||||
|
"libLLVMOrcShared.a",
|
||||||
|
"libLLVMOrcTargetProcess.a",
|
||||||
|
"libLLVMPasses.a",
|
||||||
|
"libLLVMPowerPCAsmParser.a",
|
||||||
|
"libLLVMPowerPCCodeGen.a",
|
||||||
|
"libLLVMPowerPCDesc.a",
|
||||||
|
"libLLVMPowerPCDisassembler.a",
|
||||||
|
"libLLVMPowerPCInfo.a",
|
||||||
|
"libLLVMProfileData.a",
|
||||||
|
"libLLVMRemarks.a",
|
||||||
|
"libLLVMRISCVAsmParser.a",
|
||||||
|
"libLLVMRISCVCodeGen.a",
|
||||||
|
"libLLVMRISCVDesc.a",
|
||||||
|
"libLLVMRISCVDisassembler.a",
|
||||||
|
"libLLVMRISCVInfo.a",
|
||||||
|
"libLLVMRISCVTargetMCA.a",
|
||||||
|
"libLLVMRuntimeDyld.a",
|
||||||
|
"libLLVMScalarOpts.a",
|
||||||
|
"libLLVMSelectionDAG.a",
|
||||||
|
"libLLVMSparcAsmParser.a",
|
||||||
|
"libLLVMSparcCodeGen.a",
|
||||||
|
"libLLVMSparcDesc.a",
|
||||||
|
"libLLVMSparcDisassembler.a",
|
||||||
|
"libLLVMSparcInfo.a",
|
||||||
|
"libLLVMSupport.a",
|
||||||
|
"libLLVMSymbolize.a",
|
||||||
|
"libLLVMSystemZAsmParser.a",
|
||||||
|
"libLLVMSystemZCodeGen.a",
|
||||||
|
"libLLVMSystemZDesc.a",
|
||||||
|
"libLLVMSystemZDisassembler.a",
|
||||||
|
"libLLVMSystemZInfo.a",
|
||||||
|
"libLLVMTableGen.a",
|
||||||
|
"libLLVMTableGenCommon.a",
|
||||||
|
"libLLVMTableGenGlobalISel.a",
|
||||||
|
"libLLVMTarget.a",
|
||||||
|
"libLLVMTargetParser.a",
|
||||||
|
"libLLVMTextAPI.a",
|
||||||
|
"libLLVMTransformUtils.a",
|
||||||
|
"libLLVMVEAsmParser.a",
|
||||||
|
"libLLVMVECodeGen.a",
|
||||||
|
"libLLVMVectorize.a",
|
||||||
|
"libLLVMVEDesc.a",
|
||||||
|
"libLLVMVEDisassembler.a",
|
||||||
|
"libLLVMVEInfo.a",
|
||||||
|
"libLLVMWebAssemblyAsmParser.a",
|
||||||
|
"libLLVMWebAssemblyCodeGen.a",
|
||||||
|
"libLLVMWebAssemblyDesc.a",
|
||||||
|
"libLLVMWebAssemblyDisassembler.a",
|
||||||
|
"libLLVMWebAssemblyInfo.a",
|
||||||
|
"libLLVMWebAssemblyUtils.a",
|
||||||
|
"libLLVMWindowsDriver.a",
|
||||||
|
"libLLVMWindowsManifest.a",
|
||||||
|
"libLLVMX86AsmParser.a",
|
||||||
|
"libLLVMX86CodeGen.a",
|
||||||
|
"libLLVMX86Desc.a",
|
||||||
|
"libLLVMX86Disassembler.a",
|
||||||
|
"libLLVMX86Info.a",
|
||||||
|
"libLLVMX86TargetMCA.a",
|
||||||
|
"libLLVMXCoreCodeGen.a",
|
||||||
|
"libLLVMXCoreDesc.a",
|
||||||
|
"libLLVMXCoreDisassembler.a",
|
||||||
|
"libLLVMXCoreInfo.a",
|
||||||
|
"libLLVMXRay.a",
|
||||||
|
//LLD
|
||||||
|
"liblldCOFF.a",
|
||||||
|
"liblldCommon.a",
|
||||||
|
"liblldELF.a",
|
||||||
|
"liblldMachO.a",
|
||||||
|
"liblldMinGW.a",
|
||||||
|
"liblldWasm.a",
|
||||||
|
// Zlib
|
||||||
|
"libz.a",
|
||||||
|
// Zstd
|
||||||
|
zstd,
|
||||||
|
// Clang
|
||||||
|
"libclangAnalysis.a",
|
||||||
|
"libclangAnalysisFlowSensitive.a",
|
||||||
|
"libclangAnalysisFlowSensitiveModels.a",
|
||||||
|
"libclangAPINotes.a",
|
||||||
|
"libclangARCMigrate.a",
|
||||||
|
"libclangAST.a",
|
||||||
|
"libclangASTMatchers.a",
|
||||||
|
"libclangBasic.a",
|
||||||
|
"libclangCodeGen.a",
|
||||||
|
"libclangCrossTU.a",
|
||||||
|
"libclangDependencyScanning.a",
|
||||||
|
"libclangDirectoryWatcher.a",
|
||||||
|
"libclangDriver.a",
|
||||||
|
"libclangDynamicASTMatchers.a",
|
||||||
|
"libclangEdit.a",
|
||||||
|
"libclangExtractAPI.a",
|
||||||
|
"libclangFormat.a",
|
||||||
|
"libclangFrontend.a",
|
||||||
|
"libclangFrontendTool.a",
|
||||||
|
"libclangHandleCXX.a",
|
||||||
|
"libclangHandleLLVM.a",
|
||||||
|
"libclangIndex.a",
|
||||||
|
"libclangIndexSerialization.a",
|
||||||
|
"libclangInterpreter.a",
|
||||||
|
"libclangLex.a",
|
||||||
|
"libclangParse.a",
|
||||||
|
"libclangRewrite.a",
|
||||||
|
"libclangRewriteFrontend.a",
|
||||||
|
"libclangSema.a",
|
||||||
|
"libclangSerialization.a",
|
||||||
|
"libclangStaticAnalyzerCheckers.a",
|
||||||
|
"libclangStaticAnalyzerCore.a",
|
||||||
|
"libclangStaticAnalyzerFrontend.a",
|
||||||
|
"libclangSupport.a",
|
||||||
|
"libclangTooling.a",
|
||||||
|
"libclangToolingASTDiff.a",
|
||||||
|
"libclangToolingCore.a",
|
||||||
|
"libclangToolingInclusions.a",
|
||||||
|
"libclangToolingInclusionsStdlib.a",
|
||||||
|
"libclangToolingRefactoring.a",
|
||||||
|
"libclangToolingSyntax.a",
|
||||||
|
"libclangTransformer.a",
|
||||||
|
};
|
||||||
|
|
||||||
if (static) {
|
if (static) {
|
||||||
compiler.linkage = .static;
|
if (os == .linux) compiler.linkage = .static;
|
||||||
compiler.linkLibCpp();
|
compiler.linkLibCpp();
|
||||||
|
|
||||||
const prefix = "nat/cache";
|
const prefix = "nat/cache";
|
||||||
@ -137,257 +396,11 @@ pub fn build(b: *std.Build) !void {
|
|||||||
compiler.addIncludePath(std.Build.LazyPath.relative(llvm_include_dir));
|
compiler.addIncludePath(std.Build.LazyPath.relative(llvm_include_dir));
|
||||||
const llvm_lib_dir = try std.mem.concat(b.allocator, u8, &.{ llvm_path, "/lib" });
|
const llvm_lib_dir = try std.mem.concat(b.allocator, u8, &.{ llvm_path, "/lib" });
|
||||||
|
|
||||||
const zstd = if (target.result.os.tag == .windows) "zstd.lib" else "libzstd.a";
|
for (static_llvm_libraries) |llvm_library| {
|
||||||
|
|
||||||
const llvm_libraries = [_][]const u8{
|
|
||||||
"libLLVMAArch64AsmParser.a",
|
|
||||||
"libLLVMAArch64CodeGen.a",
|
|
||||||
"libLLVMAArch64Desc.a",
|
|
||||||
"libLLVMAArch64Disassembler.a",
|
|
||||||
"libLLVMAArch64Info.a",
|
|
||||||
"libLLVMAArch64Utils.a",
|
|
||||||
"libLLVMAggressiveInstCombine.a",
|
|
||||||
"libLLVMAMDGPUAsmParser.a",
|
|
||||||
"libLLVMAMDGPUCodeGen.a",
|
|
||||||
"libLLVMAMDGPUDesc.a",
|
|
||||||
"libLLVMAMDGPUDisassembler.a",
|
|
||||||
"libLLVMAMDGPUInfo.a",
|
|
||||||
"libLLVMAMDGPUTargetMCA.a",
|
|
||||||
"libLLVMAMDGPUUtils.a",
|
|
||||||
"libLLVMAnalysis.a",
|
|
||||||
"libLLVMARMAsmParser.a",
|
|
||||||
"libLLVMARMCodeGen.a",
|
|
||||||
"libLLVMARMDesc.a",
|
|
||||||
"libLLVMARMDisassembler.a",
|
|
||||||
"libLLVMARMInfo.a",
|
|
||||||
"libLLVMARMUtils.a",
|
|
||||||
"libLLVMAsmParser.a",
|
|
||||||
"libLLVMAsmPrinter.a",
|
|
||||||
"libLLVMAVRAsmParser.a",
|
|
||||||
"libLLVMAVRCodeGen.a",
|
|
||||||
"libLLVMAVRDesc.a",
|
|
||||||
"libLLVMAVRDisassembler.a",
|
|
||||||
"libLLVMAVRInfo.a",
|
|
||||||
"libLLVMBinaryFormat.a",
|
|
||||||
"libLLVMBitReader.a",
|
|
||||||
"libLLVMBitstreamReader.a",
|
|
||||||
"libLLVMBitWriter.a",
|
|
||||||
"libLLVMBPFAsmParser.a",
|
|
||||||
"libLLVMBPFCodeGen.a",
|
|
||||||
"libLLVMBPFDesc.a",
|
|
||||||
"libLLVMBPFDisassembler.a",
|
|
||||||
"libLLVMBPFInfo.a",
|
|
||||||
"libLLVMCFGuard.a",
|
|
||||||
"libLLVMCFIVerify.a",
|
|
||||||
"libLLVMCodeGen.a",
|
|
||||||
"libLLVMCodeGenTypes.a",
|
|
||||||
"libLLVMCore.a",
|
|
||||||
"libLLVMCoroutines.a",
|
|
||||||
"libLLVMCoverage.a",
|
|
||||||
"libLLVMDebugInfoBTF.a",
|
|
||||||
"libLLVMDebugInfoCodeView.a",
|
|
||||||
"libLLVMDebuginfod.a",
|
|
||||||
"libLLVMDebugInfoDWARF.a",
|
|
||||||
"libLLVMDebugInfoGSYM.a",
|
|
||||||
"libLLVMDebugInfoLogicalView.a",
|
|
||||||
"libLLVMDebugInfoMSF.a",
|
|
||||||
"libLLVMDebugInfoPDB.a",
|
|
||||||
"libLLVMDemangle.a",
|
|
||||||
"libLLVMDiff.a",
|
|
||||||
"libLLVMDlltoolDriver.a",
|
|
||||||
"libLLVMDWARFLinker.a",
|
|
||||||
"libLLVMDWARFLinkerParallel.a",
|
|
||||||
"libLLVMDWP.a",
|
|
||||||
"libLLVMExecutionEngine.a",
|
|
||||||
"libLLVMExtensions.a",
|
|
||||||
"libLLVMFileCheck.a",
|
|
||||||
"libLLVMFrontendHLSL.a",
|
|
||||||
"libLLVMFrontendOpenACC.a",
|
|
||||||
"libLLVMFrontendOpenMP.a",
|
|
||||||
"libLLVMFuzzerCLI.a",
|
|
||||||
"libLLVMFuzzMutate.a",
|
|
||||||
"libLLVMGlobalISel.a",
|
|
||||||
"libLLVMHexagonAsmParser.a",
|
|
||||||
"libLLVMHexagonCodeGen.a",
|
|
||||||
"libLLVMHexagonDesc.a",
|
|
||||||
"libLLVMHexagonDisassembler.a",
|
|
||||||
"libLLVMHexagonInfo.a",
|
|
||||||
"libLLVMInstCombine.a",
|
|
||||||
"libLLVMInstrumentation.a",
|
|
||||||
"libLLVMInterfaceStub.a",
|
|
||||||
"libLLVMInterpreter.a",
|
|
||||||
"libLLVMipo.a",
|
|
||||||
"libLLVMIRPrinter.a",
|
|
||||||
"libLLVMIRReader.a",
|
|
||||||
"libLLVMJITLink.a",
|
|
||||||
"libLLVMLanaiAsmParser.a",
|
|
||||||
"libLLVMLanaiCodeGen.a",
|
|
||||||
"libLLVMLanaiDesc.a",
|
|
||||||
"libLLVMLanaiDisassembler.a",
|
|
||||||
"libLLVMLanaiInfo.a",
|
|
||||||
"libLLVMLibDriver.a",
|
|
||||||
"libLLVMLineEditor.a",
|
|
||||||
"libLLVMLinker.a",
|
|
||||||
"libLLVMLoongArchAsmParser.a",
|
|
||||||
"libLLVMLoongArchCodeGen.a",
|
|
||||||
"libLLVMLoongArchDesc.a",
|
|
||||||
"libLLVMLoongArchDisassembler.a",
|
|
||||||
"libLLVMLoongArchInfo.a",
|
|
||||||
"libLLVMLTO.a",
|
|
||||||
"libLLVMMC.a",
|
|
||||||
"libLLVMMCA.a",
|
|
||||||
"libLLVMMCDisassembler.a",
|
|
||||||
"libLLVMMCJIT.a",
|
|
||||||
"libLLVMMCParser.a",
|
|
||||||
"libLLVMMipsAsmParser.a",
|
|
||||||
"libLLVMMipsCodeGen.a",
|
|
||||||
"libLLVMMipsDesc.a",
|
|
||||||
"libLLVMMipsDisassembler.a",
|
|
||||||
"libLLVMMipsInfo.a",
|
|
||||||
"libLLVMMIRParser.a",
|
|
||||||
"libLLVMMSP430AsmParser.a",
|
|
||||||
"libLLVMMSP430CodeGen.a",
|
|
||||||
"libLLVMMSP430Desc.a",
|
|
||||||
"libLLVMMSP430Disassembler.a",
|
|
||||||
"libLLVMMSP430Info.a",
|
|
||||||
"libLLVMNVPTXCodeGen.a",
|
|
||||||
"libLLVMNVPTXDesc.a",
|
|
||||||
"libLLVMNVPTXInfo.a",
|
|
||||||
"libLLVMObjCARCOpts.a",
|
|
||||||
"libLLVMObjCopy.a",
|
|
||||||
"libLLVMObject.a",
|
|
||||||
"libLLVMObjectYAML.a",
|
|
||||||
"libLLVMOption.a",
|
|
||||||
"libLLVMOrcJIT.a",
|
|
||||||
"libLLVMOrcShared.a",
|
|
||||||
"libLLVMOrcTargetProcess.a",
|
|
||||||
"libLLVMPasses.a",
|
|
||||||
"libLLVMPowerPCAsmParser.a",
|
|
||||||
"libLLVMPowerPCCodeGen.a",
|
|
||||||
"libLLVMPowerPCDesc.a",
|
|
||||||
"libLLVMPowerPCDisassembler.a",
|
|
||||||
"libLLVMPowerPCInfo.a",
|
|
||||||
"libLLVMProfileData.a",
|
|
||||||
"libLLVMRemarks.a",
|
|
||||||
"libLLVMRISCVAsmParser.a",
|
|
||||||
"libLLVMRISCVCodeGen.a",
|
|
||||||
"libLLVMRISCVDesc.a",
|
|
||||||
"libLLVMRISCVDisassembler.a",
|
|
||||||
"libLLVMRISCVInfo.a",
|
|
||||||
"libLLVMRISCVTargetMCA.a",
|
|
||||||
"libLLVMRuntimeDyld.a",
|
|
||||||
"libLLVMScalarOpts.a",
|
|
||||||
"libLLVMSelectionDAG.a",
|
|
||||||
"libLLVMSparcAsmParser.a",
|
|
||||||
"libLLVMSparcCodeGen.a",
|
|
||||||
"libLLVMSparcDesc.a",
|
|
||||||
"libLLVMSparcDisassembler.a",
|
|
||||||
"libLLVMSparcInfo.a",
|
|
||||||
"libLLVMSupport.a",
|
|
||||||
"libLLVMSymbolize.a",
|
|
||||||
"libLLVMSystemZAsmParser.a",
|
|
||||||
"libLLVMSystemZCodeGen.a",
|
|
||||||
"libLLVMSystemZDesc.a",
|
|
||||||
"libLLVMSystemZDisassembler.a",
|
|
||||||
"libLLVMSystemZInfo.a",
|
|
||||||
"libLLVMTableGen.a",
|
|
||||||
"libLLVMTableGenCommon.a",
|
|
||||||
"libLLVMTableGenGlobalISel.a",
|
|
||||||
"libLLVMTarget.a",
|
|
||||||
"libLLVMTargetParser.a",
|
|
||||||
"libLLVMTextAPI.a",
|
|
||||||
"libLLVMTransformUtils.a",
|
|
||||||
"libLLVMVEAsmParser.a",
|
|
||||||
"libLLVMVECodeGen.a",
|
|
||||||
"libLLVMVectorize.a",
|
|
||||||
"libLLVMVEDesc.a",
|
|
||||||
"libLLVMVEDisassembler.a",
|
|
||||||
"libLLVMVEInfo.a",
|
|
||||||
"libLLVMWebAssemblyAsmParser.a",
|
|
||||||
"libLLVMWebAssemblyCodeGen.a",
|
|
||||||
"libLLVMWebAssemblyDesc.a",
|
|
||||||
"libLLVMWebAssemblyDisassembler.a",
|
|
||||||
"libLLVMWebAssemblyInfo.a",
|
|
||||||
"libLLVMWebAssemblyUtils.a",
|
|
||||||
"libLLVMWindowsDriver.a",
|
|
||||||
"libLLVMWindowsManifest.a",
|
|
||||||
"libLLVMX86AsmParser.a",
|
|
||||||
"libLLVMX86CodeGen.a",
|
|
||||||
"libLLVMX86Desc.a",
|
|
||||||
"libLLVMX86Disassembler.a",
|
|
||||||
"libLLVMX86Info.a",
|
|
||||||
"libLLVMX86TargetMCA.a",
|
|
||||||
"libLLVMXCoreCodeGen.a",
|
|
||||||
"libLLVMXCoreDesc.a",
|
|
||||||
"libLLVMXCoreDisassembler.a",
|
|
||||||
"libLLVMXCoreInfo.a",
|
|
||||||
"libLLVMXRay.a",
|
|
||||||
//LLD
|
|
||||||
"liblldCOFF.a",
|
|
||||||
"liblldCommon.a",
|
|
||||||
"liblldELF.a",
|
|
||||||
"liblldMachO.a",
|
|
||||||
"liblldMinGW.a",
|
|
||||||
"liblldWasm.a",
|
|
||||||
// Zlib
|
|
||||||
"libz.a",
|
|
||||||
// Zstd
|
|
||||||
zstd,
|
|
||||||
// Clang
|
|
||||||
"libclangAnalysis.a",
|
|
||||||
"libclangAnalysisFlowSensitive.a",
|
|
||||||
"libclangAnalysisFlowSensitiveModels.a",
|
|
||||||
"libclangAPINotes.a",
|
|
||||||
"libclangARCMigrate.a",
|
|
||||||
"libclangAST.a",
|
|
||||||
"libclangASTMatchers.a",
|
|
||||||
"libclangBasic.a",
|
|
||||||
"libclangCodeGen.a",
|
|
||||||
"libclangCrossTU.a",
|
|
||||||
"libclangDependencyScanning.a",
|
|
||||||
"libclangDirectoryWatcher.a",
|
|
||||||
"libclangDriver.a",
|
|
||||||
"libclangDynamicASTMatchers.a",
|
|
||||||
"libclangEdit.a",
|
|
||||||
"libclangExtractAPI.a",
|
|
||||||
"libclangFormat.a",
|
|
||||||
"libclangFrontend.a",
|
|
||||||
"libclangFrontendTool.a",
|
|
||||||
"libclangHandleCXX.a",
|
|
||||||
"libclangHandleLLVM.a",
|
|
||||||
"libclangIndex.a",
|
|
||||||
"libclangIndexSerialization.a",
|
|
||||||
"libclangInterpreter.a",
|
|
||||||
"libclangLex.a",
|
|
||||||
"libclangParse.a",
|
|
||||||
"libclangRewrite.a",
|
|
||||||
"libclangRewriteFrontend.a",
|
|
||||||
"libclangSema.a",
|
|
||||||
"libclangSerialization.a",
|
|
||||||
"libclangStaticAnalyzerCheckers.a",
|
|
||||||
"libclangStaticAnalyzerCore.a",
|
|
||||||
"libclangStaticAnalyzerFrontend.a",
|
|
||||||
"libclangSupport.a",
|
|
||||||
"libclangTooling.a",
|
|
||||||
"libclangToolingASTDiff.a",
|
|
||||||
"libclangToolingCore.a",
|
|
||||||
"libclangToolingInclusions.a",
|
|
||||||
"libclangToolingInclusionsStdlib.a",
|
|
||||||
"libclangToolingRefactoring.a",
|
|
||||||
"libclangToolingSyntax.a",
|
|
||||||
"libclangTransformer.a",
|
|
||||||
};
|
|
||||||
|
|
||||||
for (llvm_libraries) |llvm_library| {
|
|
||||||
compiler.addObjectFile(std.Build.LazyPath.relative(try std.mem.concat(b.allocator, u8, &.{ llvm_lib_dir, "/", llvm_library })));
|
compiler.addObjectFile(std.Build.LazyPath.relative(try std.mem.concat(b.allocator, u8, &.{ llvm_lib_dir, "/", llvm_library })));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
compiler.addObjectFile(.{ .cwd_relative = "/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../lib/libstdc++.so" });
|
compiler.linkSystemLibrary("LLVM-17");
|
||||||
compiler.addIncludePath(.{ .cwd_relative = "/usr/include" });
|
|
||||||
compiler.addIncludePath(.{ .cwd_relative = "/usr/include/c++/13.2.1" });
|
|
||||||
compiler.addIncludePath(.{ .cwd_relative = "/usr/include/c++/13.2.1/x86_64-pc-linux-gnu" });
|
|
||||||
compiler.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
|
|
||||||
compiler.linkSystemLibrary("LLVM");
|
|
||||||
compiler.linkSystemLibrary("clang-cpp");
|
compiler.linkSystemLibrary("clang-cpp");
|
||||||
compiler.linkSystemLibrary("lldCommon");
|
compiler.linkSystemLibrary("lldCommon");
|
||||||
compiler.linkSystemLibrary("lldCOFF");
|
compiler.linkSystemLibrary("lldCOFF");
|
||||||
@ -395,6 +408,45 @@ pub fn build(b: *std.Build) !void {
|
|||||||
compiler.linkSystemLibrary("lldMachO");
|
compiler.linkSystemLibrary("lldMachO");
|
||||||
compiler.linkSystemLibrary("lldWasm");
|
compiler.linkSystemLibrary("lldWasm");
|
||||||
compiler.linkSystemLibrary("unwind");
|
compiler.linkSystemLibrary("unwind");
|
||||||
|
compiler.linkSystemLibrary("zlib");
|
||||||
|
compiler.linkSystemLibrary("zstd");
|
||||||
|
|
||||||
|
switch (target.result.os.tag) {
|
||||||
|
.linux => {
|
||||||
|
compiler.addObjectFile(.{ .cwd_relative = "/usr/lib/gcc/x86_64-pc-linux-gnu/13.2.1/../../../../lib/libstdc++.so" });
|
||||||
|
compiler.addIncludePath(.{ .cwd_relative = "/usr/include" });
|
||||||
|
compiler.addIncludePath(.{ .cwd_relative = "/usr/include/c++/13.2.1" });
|
||||||
|
compiler.addIncludePath(.{ .cwd_relative = "/usr/include/c++/13.2.1/x86_64-pc-linux-gnu" });
|
||||||
|
compiler.addLibraryPath(.{ .cwd_relative = "/usr/lib" });
|
||||||
|
},
|
||||||
|
.macos => {
|
||||||
|
compiler.linkLibCpp();
|
||||||
|
|
||||||
|
if (discover_brew_prefix(b, "llvm")) |llvm_prefix| {
|
||||||
|
const llvm_include_path = try std.mem.concat(b.allocator, u8, &.{ llvm_prefix, "/include" });
|
||||||
|
const llvm_lib_path = try std.mem.concat(b.allocator, u8, &.{ llvm_prefix, "/lib" });
|
||||||
|
compiler.addIncludePath(.{ .cwd_relative = llvm_include_path });
|
||||||
|
compiler.addLibraryPath(.{ .cwd_relative = llvm_lib_path });
|
||||||
|
} else |err| {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discover_brew_prefix(b, "zstd")) |zstd_prefix| {
|
||||||
|
const zstd_lib_path = try std.mem.concat(b.allocator, u8, &.{ zstd_prefix, "/lib" });
|
||||||
|
compiler.addLibraryPath(.{ .cwd_relative = zstd_lib_path });
|
||||||
|
} else |err| {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (discover_brew_prefix(b, "zlib")) |zlib_prefix| {
|
||||||
|
const zlib_lib_path = try std.mem.concat(b.allocator, u8, &.{ zlib_prefix, "/lib" });
|
||||||
|
compiler.addLibraryPath(.{ .cwd_relative = zlib_lib_path });
|
||||||
|
} else |err| {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
else => |tag| @panic(@tagName(tag)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const install_exe = b.addInstallArtifact(compiler, .{});
|
const install_exe = b.addInstallArtifact(compiler, .{});
|
||||||
@ -409,7 +461,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const run_command = b.addSystemCommand(&.{compiler_exe_path});
|
const run_command = b.addSystemCommand(&.{compiler_exe_path});
|
||||||
run_command.step.dependOn(b.getInstallStep());
|
run_command.step.dependOn(b.getInstallStep());
|
||||||
|
|
||||||
const debug_command = switch (@import("builtin").os.tag) {
|
const debug_command = switch (os) {
|
||||||
.linux => blk: {
|
.linux => blk: {
|
||||||
const result = b.addSystemCommand(&.{"gf2"});
|
const result = b.addSystemCommand(&.{"gf2"});
|
||||||
result.addArgs(&.{ "-ex", "set disassembly-flavor intel" });
|
result.addArgs(&.{ "-ex", "set disassembly-flavor intel" });
|
||||||
|
@ -8,7 +8,7 @@ pub fn main() !void {
|
|||||||
var url_arg: ?[:0]const u8 = null;
|
var url_arg: ?[:0]const u8 = null;
|
||||||
var prefix_arg: [:0]const u8 = "nat";
|
var prefix_arg: [:0]const u8 = "nat";
|
||||||
|
|
||||||
const State = enum{
|
const State = enum {
|
||||||
none,
|
none,
|
||||||
prefix,
|
prefix,
|
||||||
url,
|
url,
|
||||||
@ -16,7 +16,6 @@ pub fn main() !void {
|
|||||||
|
|
||||||
var state = State.none;
|
var state = State.none;
|
||||||
|
|
||||||
|
|
||||||
for (arguments[1..]) |argument| {
|
for (arguments[1..]) |argument| {
|
||||||
switch (state) {
|
switch (state) {
|
||||||
.none => {
|
.none => {
|
||||||
@ -43,8 +42,8 @@ pub fn main() !void {
|
|||||||
if (state != .none) return error.InvalidInput;
|
if (state != .none) return error.InvalidInput;
|
||||||
|
|
||||||
const dot_index = std.mem.lastIndexOfScalar(u8, url, '.') orelse return error.InvalidInput;
|
const dot_index = std.mem.lastIndexOfScalar(u8, url, '.') orelse return error.InvalidInput;
|
||||||
const extension_string = url[dot_index + 1..];
|
const extension_string = url[dot_index + 1 ..];
|
||||||
const Extension = enum{
|
const Extension = enum {
|
||||||
xz,
|
xz,
|
||||||
gz,
|
gz,
|
||||||
zip,
|
zip,
|
||||||
@ -61,7 +60,7 @@ pub fn main() !void {
|
|||||||
};
|
};
|
||||||
defer http_client.deinit();
|
defer http_client.deinit();
|
||||||
|
|
||||||
var buffer: [16*1024]u8 = undefined;
|
var buffer: [16 * 1024]u8 = undefined;
|
||||||
var request = try http_client.open(.GET, uri, .{
|
var request = try http_client.open(.GET, uri, .{
|
||||||
.server_header_buffer = &buffer,
|
.server_header_buffer = &buffer,
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@ const TestError = error{
|
|||||||
fail,
|
fail,
|
||||||
};
|
};
|
||||||
|
|
||||||
fn collectDirectoryDirEntries(allocator: Allocator, path: []const u8) ![]const []const u8{
|
fn collectDirectoryDirEntries(allocator: Allocator, path: []const u8) ![]const []const u8 {
|
||||||
var dir = try std.fs.cwd().openDir(path, .{
|
var dir = try std.fs.cwd().openDir(path, .{
|
||||||
.iterate = true,
|
.iterate = true,
|
||||||
});
|
});
|
||||||
@ -48,11 +48,11 @@ fn runStandalone(allocator: Allocator, args: struct {
|
|||||||
|
|
||||||
for (test_names) |test_name| {
|
for (test_names) |test_name| {
|
||||||
std.debug.print("{s}... ", .{test_name});
|
std.debug.print("{s}... ", .{test_name});
|
||||||
const source_file_path = try std.mem.concat(allocator, u8, &.{args.directory_path, "/", test_name, "/main.nat"});
|
const source_file_path = try std.mem.concat(allocator, u8, &.{ args.directory_path, "/", test_name, "/main.nat" });
|
||||||
const compile_run = try std.ChildProcess.run(.{
|
const compile_run = try std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
// TODO: delete -main_source_file?
|
||||||
.argv = &.{"zig-out/bin/nat", if (args.is_test) "test" else "exe", "-main_source_file", source_file_path},
|
.argv = &.{ "zig-out/bin/nat", if (args.is_test) "test" else "exe", "-main_source_file", source_file_path },
|
||||||
});
|
});
|
||||||
ran_compilation_count += 1;
|
ran_compilation_count += 1;
|
||||||
|
|
||||||
@ -77,11 +77,11 @@ fn runStandalone(allocator: Allocator, args: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compilation_success) {
|
if (compilation_success) {
|
||||||
const test_path = try std.mem.concat(allocator, u8, &.{"nat/", test_name});
|
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name });
|
||||||
const test_run = try std.ChildProcess.run(.{
|
const test_run = try std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
// TODO: delete -main_source_file?
|
||||||
.argv = &.{ test_path },
|
.argv = &.{test_path},
|
||||||
});
|
});
|
||||||
ran_test_count += 1;
|
ran_test_count += 1;
|
||||||
const test_result: TestError!bool = switch (test_run.term) {
|
const test_result: TestError!bool = switch (test_run.term) {
|
||||||
@ -107,8 +107,8 @@ fn runStandalone(allocator: Allocator, args: struct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std.debug.print("\n{s} COMPILATIONS: {}. FAILED: {}\n", .{args.group_name, total_compilation_count, failed_compilation_count});
|
std.debug.print("\n{s} COMPILATIONS: {}. FAILED: {}\n", .{ args.group_name, total_compilation_count, failed_compilation_count });
|
||||||
std.debug.print("{s} TESTS: {}. RAN: {}. FAILED: {}\n", .{args.group_name, total_test_count, ran_test_count, failed_test_count});
|
std.debug.print("{s} TESTS: {}. RAN: {}. FAILED: {}\n", .{ args.group_name, total_test_count, ran_test_count, failed_test_count });
|
||||||
|
|
||||||
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
||||||
return error.fail;
|
return error.fail;
|
||||||
@ -129,11 +129,11 @@ fn runStandaloneTests(allocator: Allocator) !void {
|
|||||||
|
|
||||||
for (standalone_test_names) |standalone_test_name| {
|
for (standalone_test_names) |standalone_test_name| {
|
||||||
std.debug.print("{s}... ", .{standalone_test_name});
|
std.debug.print("{s}... ", .{standalone_test_name});
|
||||||
const source_file_path = try std.mem.concat(allocator, u8, &.{standalone_test_dir_path, "/", standalone_test_name, "/main.nat"});
|
const source_file_path = try std.mem.concat(allocator, u8, &.{ standalone_test_dir_path, "/", standalone_test_name, "/main.nat" });
|
||||||
const compile_run = try std.ChildProcess.run(.{
|
const compile_run = try std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
// TODO: delete -main_source_file?
|
||||||
.argv = &.{"zig-out/bin/nat", "exe", "-main_source_file", source_file_path},
|
.argv = &.{ "zig-out/bin/nat", "exe", "-main_source_file", source_file_path },
|
||||||
});
|
});
|
||||||
ran_compilation_count += 1;
|
ran_compilation_count += 1;
|
||||||
|
|
||||||
@ -158,11 +158,11 @@ fn runStandaloneTests(allocator: Allocator) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compilation_success) {
|
if (compilation_success) {
|
||||||
const test_path = try std.mem.concat(allocator, u8, &.{"nat/", standalone_test_name});
|
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", standalone_test_name });
|
||||||
const test_run = try std.ChildProcess.run(.{
|
const test_run = try std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
// TODO: delete -main_source_file?
|
||||||
.argv = &.{ test_path },
|
.argv = &.{test_path},
|
||||||
});
|
});
|
||||||
ran_test_count += 1;
|
ran_test_count += 1;
|
||||||
const test_result: TestError!bool = switch (test_run.term) {
|
const test_result: TestError!bool = switch (test_run.term) {
|
||||||
@ -188,8 +188,8 @@ fn runStandaloneTests(allocator: Allocator) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std.debug.print("\nTOTAL COMPILATIONS: {}. FAILED: {}\n", .{total_compilation_count, failed_compilation_count});
|
std.debug.print("\nTOTAL COMPILATIONS: {}. FAILED: {}\n", .{ total_compilation_count, failed_compilation_count });
|
||||||
std.debug.print("TOTAL TESTS: {}. RAN: {}. FAILED: {}\n", .{total_test_count, ran_test_count, failed_test_count});
|
std.debug.print("TOTAL TESTS: {}. RAN: {}. FAILED: {}\n", .{ total_test_count, ran_test_count, failed_test_count });
|
||||||
|
|
||||||
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
||||||
return error.fail;
|
return error.fail;
|
||||||
@ -203,7 +203,7 @@ fn runBuildTests(allocator: Allocator) !void {
|
|||||||
const test_names = try collectDirectoryDirEntries(allocator, test_dir_path);
|
const test_names = try collectDirectoryDirEntries(allocator, test_dir_path);
|
||||||
const test_dir_realpath = try std.fs.cwd().realpathAlloc(allocator, test_dir_path);
|
const test_dir_realpath = try std.fs.cwd().realpathAlloc(allocator, test_dir_path);
|
||||||
const compiler_realpath = try std.fs.cwd().realpathAlloc(allocator, "zig-out/bin/nat");
|
const compiler_realpath = try std.fs.cwd().realpathAlloc(allocator, "zig-out/bin/nat");
|
||||||
try std.os.chdir(test_dir_realpath);
|
try std.posix.chdir(test_dir_realpath);
|
||||||
|
|
||||||
const total_compilation_count = test_names.len;
|
const total_compilation_count = test_names.len;
|
||||||
var ran_compilation_count: usize = 0;
|
var ran_compilation_count: usize = 0;
|
||||||
@ -215,12 +215,12 @@ fn runBuildTests(allocator: Allocator) !void {
|
|||||||
|
|
||||||
for (test_names) |test_name| {
|
for (test_names) |test_name| {
|
||||||
std.debug.print("{s}... ", .{test_name});
|
std.debug.print("{s}... ", .{test_name});
|
||||||
try std.os.chdir(test_name);
|
try std.posix.chdir(test_name);
|
||||||
|
|
||||||
const compile_run = try std.ChildProcess.run(.{
|
const compile_run = try std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
// TODO: delete -main_source_file?
|
||||||
.argv = &.{compiler_realpath, "build"},
|
.argv = &.{ compiler_realpath, "build" },
|
||||||
});
|
});
|
||||||
|
|
||||||
ran_compilation_count += 1;
|
ran_compilation_count += 1;
|
||||||
@ -246,11 +246,11 @@ fn runBuildTests(allocator: Allocator) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (compilation_success) {
|
if (compilation_success) {
|
||||||
const test_path = try std.mem.concat(allocator, u8, &.{"nat/", test_name});
|
const test_path = try std.mem.concat(allocator, u8, &.{ "nat/", test_name });
|
||||||
const test_run = try std.ChildProcess.run(.{
|
const test_run = try std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
// TODO: delete -main_source_file?
|
||||||
.argv = &.{ test_path },
|
.argv = &.{test_path},
|
||||||
});
|
});
|
||||||
ran_test_count += 1;
|
ran_test_count += 1;
|
||||||
const test_result: TestError!bool = switch (test_run.term) {
|
const test_result: TestError!bool = switch (test_run.term) {
|
||||||
@ -275,13 +275,13 @@ fn runBuildTests(allocator: Allocator) !void {
|
|||||||
std.debug.print("\n", .{});
|
std.debug.print("\n", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
try std.os.chdir(test_dir_realpath);
|
try std.posix.chdir(test_dir_realpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
std.debug.print("\nTOTAL COMPILATIONS: {}. FAILED: {}\n", .{total_compilation_count, failed_compilation_count});
|
std.debug.print("\nTOTAL COMPILATIONS: {}. FAILED: {}\n", .{ total_compilation_count, failed_compilation_count });
|
||||||
std.debug.print("TOTAL TESTS: {}. RAN: {}. FAILED: {}\n", .{total_test_count, ran_test_count, failed_test_count});
|
std.debug.print("TOTAL TESTS: {}. RAN: {}. FAILED: {}\n", .{ total_test_count, ran_test_count, failed_test_count });
|
||||||
|
|
||||||
try std.os.chdir(previous_cwd);
|
try std.posix.chdir(previous_cwd);
|
||||||
|
|
||||||
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
if (failed_compilation_count > 0 or failed_test_count > 0) {
|
||||||
return error.fail;
|
return error.fail;
|
||||||
@ -289,24 +289,31 @@ fn runBuildTests(allocator: Allocator) !void {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn main() !void {
|
pub fn main() !void {
|
||||||
|
var errors = false;
|
||||||
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
|
||||||
const allocator = arena.allocator();
|
const allocator = arena.allocator();
|
||||||
try runStandalone(allocator, .{
|
runStandalone(allocator, .{
|
||||||
.directory_path = "test/standalone",
|
.directory_path = "test/standalone",
|
||||||
.group_name = "STANDALONE",
|
.group_name = "STANDALONE",
|
||||||
.is_test = false,
|
.is_test = false,
|
||||||
});
|
}) catch {
|
||||||
try runBuildTests(allocator);
|
errors = true;
|
||||||
try runStandalone(allocator, .{
|
};
|
||||||
|
runBuildTests(allocator) catch {
|
||||||
|
errors = true;
|
||||||
|
};
|
||||||
|
runStandalone(allocator, .{
|
||||||
.directory_path = "test/tests",
|
.directory_path = "test/tests",
|
||||||
.group_name = "TEST EXECUTABLE",
|
.group_name = "TEST EXECUTABLE",
|
||||||
.is_test = true,
|
.is_test = true,
|
||||||
});
|
}) catch {
|
||||||
|
errors = true;
|
||||||
|
};
|
||||||
|
|
||||||
std.debug.print("std... ", .{});
|
std.debug.print("std... ", .{});
|
||||||
|
|
||||||
const result = try std.ChildProcess.run(.{
|
const result = try std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.argv = &.{ "zig-out/bin/nat", "test", "-main_source_file", "lib/std/std.nat", "-name", "std" },
|
.argv = &.{ "zig-out/bin/nat", "test", "-main_source_file", "lib/std/std.nat", "-name", "std" },
|
||||||
});
|
});
|
||||||
const compilation_result: TestError!bool = switch (result.term) {
|
const compilation_result: TestError!bool = switch (result.term) {
|
||||||
@ -317,6 +324,7 @@ pub fn main() !void {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const compilation_success = compilation_result catch b: {
|
const compilation_success = compilation_result catch b: {
|
||||||
|
errors = true;
|
||||||
break :b false;
|
break :b false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -330,9 +338,9 @@ pub fn main() !void {
|
|||||||
|
|
||||||
if (compilation_success) {
|
if (compilation_success) {
|
||||||
const test_run = try std.ChildProcess.run(.{
|
const test_run = try std.ChildProcess.run(.{
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
// TODO: delete -main_source_file?
|
// TODO: delete -main_source_file?
|
||||||
.argv = &.{ "nat/std" },
|
.argv = &.{"nat/std"},
|
||||||
});
|
});
|
||||||
const test_result: TestError!bool = switch (test_run.term) {
|
const test_result: TestError!bool = switch (test_run.term) {
|
||||||
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
.Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,
|
||||||
@ -342,6 +350,7 @@ pub fn main() !void {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const test_success = test_result catch b: {
|
const test_success = test_result catch b: {
|
||||||
|
errors = true;
|
||||||
break :b false;
|
break :b false;
|
||||||
};
|
};
|
||||||
std.debug.print("[TEST {s}]\n", .{if (test_success) "\x1b[32mOK\x1b[0m" else "\x1b[31mFAILED\x1b[0m"});
|
std.debug.print("[TEST {s}]\n", .{if (test_success) "\x1b[32mOK\x1b[0m" else "\x1b[31mFAILED\x1b[0m"});
|
||||||
@ -352,4 +361,8 @@ pub fn main() !void {
|
|||||||
std.debug.print("STDERR:\n\n{s}\n\n", .{test_run.stderr});
|
std.debug.print("STDERR:\n\n{s}\n\n", .{test_run.stderr});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (errors) {
|
||||||
|
return error.fail;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ const Abi = enum{
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CallingConvention = enum{
|
const CallingConvention = enum{
|
||||||
|
c,
|
||||||
system_v,
|
system_v,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -0,0 +1,83 @@
|
|||||||
|
const std = #import("std");
|
||||||
|
const linux = std.os.linux;
|
||||||
|
const macos = std.os.macos;
|
||||||
|
const builtin = #import("builtin");
|
||||||
|
const os = builtin.os;
|
||||||
|
|
||||||
|
const Error = switch (os) {
|
||||||
|
.linux => linux.Error,
|
||||||
|
.macos => macos.Error,
|
||||||
|
else => #error("OS not supported"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const unwrap_syscall = fn(syscall_result: ssize) Error!usize {
|
||||||
|
if (syscall_result == -1) {
|
||||||
|
const absolute_error: u64 = #cast(-syscall_result);
|
||||||
|
const error_int: u32 = #cast(absolute_error);
|
||||||
|
const err: Error = #cast(error_int);
|
||||||
|
return err;
|
||||||
|
} else {
|
||||||
|
const result: usize = #cast(syscall_result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const MapFlags = switch (os) {
|
||||||
|
.macos => bitfield(u32){
|
||||||
|
shared: bool,
|
||||||
|
private: bool,
|
||||||
|
reserved: u2 = 0,
|
||||||
|
fixed: bool,
|
||||||
|
reserved0: bool = 0,
|
||||||
|
noreserve: bool,
|
||||||
|
reserved1: u2 = 0,
|
||||||
|
has_semaphore: bool,
|
||||||
|
no_cache: bool,
|
||||||
|
reserved2: u1 = 0,
|
||||||
|
anonymous: bool,
|
||||||
|
reserved3: u19 = 0,
|
||||||
|
},
|
||||||
|
.linux => linux.MapFlags,
|
||||||
|
else => #error("OS not supported"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const FileDescriptor = s32;
|
||||||
|
const ProcessId = s32;
|
||||||
|
const MAP_FAILED = 0xffffffffffffffff;
|
||||||
|
|
||||||
|
const ProtectionFlags = bitfield(u32) {
|
||||||
|
read: bool,
|
||||||
|
write: bool,
|
||||||
|
execute: bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
const get_protection_flags = fn(flags: std.os.ProtectionFlags) ProtectionFlags {
|
||||||
|
return ProtectionFlags{
|
||||||
|
.read = flags.read,
|
||||||
|
.write = flags.write,
|
||||||
|
.execute = flags.execute,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const get_map_flags = fn(flags: std.os.MapFlags) MapFlags{
|
||||||
|
return MapFlags{
|
||||||
|
.shared = false,
|
||||||
|
.private = true,
|
||||||
|
.fixed = false,
|
||||||
|
.noreserve = false,
|
||||||
|
.has_semaphore = false,
|
||||||
|
.no_cache = false,
|
||||||
|
.anonymous = true,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const write :: extern = fn cc(.c) (file_descriptor: FileDescriptor, bytes_ptr: [&]const u8, bytes_len: usize) ssize;
|
||||||
|
const exit :: extern = fn cc(.c) (exit_code: s32) noreturn;
|
||||||
|
const fork :: extern = fn cc(.c) () ProcessId;
|
||||||
|
const mmap :: extern = fn cc(.c) (address: ?[&]const u8, length: usize, protection_flags: ProtectionFlags, map_flags: MapFlags, file_descriptor: FileDescriptor, offset: u64) usize;
|
||||||
|
const munmap :: extern = fn cc(.c) (address: [&]const u8, length: usize) s32;
|
||||||
|
const execve :: extern = fn cc(.c) (path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) s32;
|
||||||
|
const realpath :: extern = fn cc(.c) (path: [&:0]const u8, resolved_path: [&:0]u8) ?[&:0]u8;
|
||||||
|
const waitpid :: extern = fn cc(.c) (pid: ProcessId, status: &s32, flags: s32) s32;
|
||||||
|
|
||||||
|
const _NSGetExecutablePath :: extern = fn cc(.c) (buffer: [&:0]u8, buffer_size: &u32) s32;
|
@ -15,7 +15,7 @@ const system = switch (link_libc) {
|
|||||||
true => c,
|
true => c,
|
||||||
false => switch (current) {
|
false => switch (current) {
|
||||||
.linux => linux,
|
.linux => linux,
|
||||||
.macos => macos,
|
.macos => c,
|
||||||
.windows => windows,
|
.windows => windows,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -25,7 +25,7 @@ const unwrap_syscall = system.unwrap_syscall;
|
|||||||
const exit = fn(exit_code: s32) noreturn {
|
const exit = fn(exit_code: s32) noreturn {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux => _ = #syscall(#cast(linux.Syscall.exit_group), #cast(exit_code)),
|
.linux => _ = #syscall(#cast(linux.Syscall.exit_group), #cast(exit_code)),
|
||||||
.macos => macos.exit(exit_code),
|
.macos => system.exit(exit_code),
|
||||||
.windows => windows.ExitProcess(#cast(exit_code)),
|
.windows => windows.ExitProcess(#cast(exit_code)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,7 +46,15 @@ const FileDescriptor = struct{
|
|||||||
const read = fn(file_descriptor: FileDescriptor, bytes: []u8) ReadError!usize {
|
const read = fn(file_descriptor: FileDescriptor, bytes: []u8) ReadError!usize {
|
||||||
if (bytes.len > 0) {
|
if (bytes.len > 0) {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux, .macos => {
|
.linux => {
|
||||||
|
const len: usize = #min(max_file_operation_byte_count, bytes.len);
|
||||||
|
const syscall_result = system.read(file_descriptor, bytes);
|
||||||
|
const byte_count = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
return byte_count;
|
||||||
|
},
|
||||||
|
.macos => {
|
||||||
const len: usize = #min(max_file_operation_byte_count, bytes.len);
|
const len: usize = #min(max_file_operation_byte_count, bytes.len);
|
||||||
const syscall_result = system.read(file_descriptor, bytes);
|
const syscall_result = system.read(file_descriptor, bytes);
|
||||||
const byte_count = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
const byte_count = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
||||||
@ -67,7 +75,7 @@ const FileDescriptor = struct{
|
|||||||
|
|
||||||
const write = fn (file_descriptor: FileDescriptor, bytes: []const u8) WriteError!usize {
|
const write = fn (file_descriptor: FileDescriptor, bytes: []const u8) WriteError!usize {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux, .macos => {
|
.linux => {
|
||||||
const len: usize = #min(max_file_operation_byte_count, bytes.len);
|
const len: usize = #min(max_file_operation_byte_count, bytes.len);
|
||||||
const syscall_result = system.write(file_descriptor.handle, bytes[0..len]);
|
const syscall_result = system.write(file_descriptor.handle, bytes[0..len]);
|
||||||
const byte_count = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
const byte_count = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
||||||
@ -75,6 +83,14 @@ const FileDescriptor = struct{
|
|||||||
};
|
};
|
||||||
return byte_count;
|
return byte_count;
|
||||||
},
|
},
|
||||||
|
.macos => {
|
||||||
|
const len: usize = #min(max_file_operation_byte_count, bytes.len);
|
||||||
|
const syscall_result = system.write(file_descriptor.handle, bytes.ptr, bytes.len);
|
||||||
|
const byte_count = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
||||||
|
else => return WriteError.write_failed,
|
||||||
|
};
|
||||||
|
return byte_count;
|
||||||
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -122,8 +138,8 @@ const allocate_virtual_memory = fn(address: ?[&]u8, length: usize, general_prote
|
|||||||
.linux, .macos => {
|
.linux, .macos => {
|
||||||
const syscall_result = system.mmap(address, length, protection_flags, map_flags, file_descriptor, offset);
|
const syscall_result = system.mmap(address, length, protection_flags, map_flags, file_descriptor, offset);
|
||||||
if (link_libc) {
|
if (link_libc) {
|
||||||
if (result != system.MAP_FAILED) {
|
if (syscall_result != system.MAP_FAILED) {
|
||||||
const result_address: [&]u8 = #cast(result);
|
const result_address: [&]u8 = #cast(syscall_result);
|
||||||
return result_address;
|
return result_address;
|
||||||
} else {
|
} else {
|
||||||
// TODO:
|
// TODO:
|
||||||
@ -147,12 +163,18 @@ const FreeError = error{
|
|||||||
};
|
};
|
||||||
const free_virtual_memory = fn(bytes: []const u8) FreeError!void {
|
const free_virtual_memory = fn(bytes: []const u8) FreeError!void {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux, .macos => {
|
.linux => {
|
||||||
const syscall_result = system.munmap(bytes);
|
const syscall_result = system.munmap(bytes);
|
||||||
_ = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
_ = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
.macos => {
|
||||||
|
const syscall_result = system.munmap(bytes.ptr, bytes.len);
|
||||||
|
_ = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
||||||
|
else => unreachable,
|
||||||
|
};
|
||||||
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -194,32 +216,31 @@ const current_executable_path = fn(buffer: [:0]u8) CurrentExecutablePath![]u8 {
|
|||||||
};
|
};
|
||||||
return bytes;
|
return bytes;
|
||||||
},
|
},
|
||||||
//.macos => {
|
.macos => {
|
||||||
// TODO:
|
var symlink_path_buffer: [max_path_byte_count:0]u8 = undefined;
|
||||||
//var symlink_path_buffer: [max_path_byte_count:0]u8 = undefined;
|
var symlink_path_len: u32 = symlink_path_buffer.len + 1;
|
||||||
//var symlink_path_len: u32 = symlink_path_buffer.len + 1;
|
const ns_result = c._NSGetExecutablePath(symlink_path_buffer.&, symlink_path_len.&);
|
||||||
//const ns_result = macos._NSGetExecutablePath(symlink_path_buffer.&, symlink_path_len.&);
|
if (ns_result == 0) {
|
||||||
//if (ns_result == 0) {
|
const symlink_path = symlink_path_buffer[0..symlink_path_len];
|
||||||
// const symlink_path = symlink_path_buffer[0..symlink_path_len];
|
if (c.realpath(symlink_path.ptr, buffer.ptr)) |result| {
|
||||||
// const result = macos.realpath(symlink_path.ptr, buffer.ptr);
|
var i: usize = 0;
|
||||||
// if (result != null) {
|
while (i < buffer.len) {
|
||||||
// var i: usize = 0;
|
if (result[i] == 0) {
|
||||||
// while (i < buffer.len) {
|
break;
|
||||||
// if (result[i] == 0) {
|
}
|
||||||
// break;
|
i += 1;
|
||||||
// }
|
}
|
||||||
// i += 1;
|
assert(i < buffer.len);
|
||||||
// }
|
|
||||||
// assert(i < buffer.len);
|
|
||||||
|
|
||||||
// return result[0..i];
|
const r: []u8 = result[0..i];
|
||||||
// } else {
|
return r;
|
||||||
// return null;
|
} else {
|
||||||
// }
|
return CurrentExecutablePath.failed;
|
||||||
//} else {
|
}
|
||||||
// return null;
|
} else {
|
||||||
//}
|
return CurrentExecutablePath.failed;
|
||||||
//},
|
}
|
||||||
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -256,13 +277,11 @@ const ExecveError = error{
|
|||||||
const execute = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) ExecveError!noreturn {
|
const execute = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) ExecveError!noreturn {
|
||||||
switch (current) {
|
switch (current) {
|
||||||
.linux, .macos => {
|
.linux, .macos => {
|
||||||
const syscall_result = linux.execve(path, argv, env);
|
const syscall_result = system.execve(path, argv, env);
|
||||||
const signed_syscall_result: ssize = #cast(syscall_result);
|
_ = unwrap_syscall(syscall_result) catch |err| switch (err) {
|
||||||
if (signed_syscall_result == -1) {
|
else => return ExecveError.execve_failed,
|
||||||
return ExecveError.execve_failed;
|
};
|
||||||
} else {
|
unreachable;
|
||||||
unreachable;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
else => #error("OS not supported"),
|
else => #error("OS not supported"),
|
||||||
}
|
}
|
||||||
@ -410,7 +429,7 @@ const waitpid = fn(pid: Process.Id, flags: u32) WaitPidError!u32 {
|
|||||||
},
|
},
|
||||||
.macos => {
|
.macos => {
|
||||||
var status: s32 = undefined;
|
var status: s32 = undefined;
|
||||||
if (macos.waitpid(pid, status.&, #cast(flags)) != -1) {
|
if (system.waitpid(pid, status.&, #cast(flags)) != -1) {
|
||||||
const status_u: u32 = #cast(status);
|
const status_u: u32 = #cast(status);
|
||||||
return status_u;
|
return status_u;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,57 +1,337 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
|
|
||||||
const FileDescriptor = s32;
|
const Error = error{
|
||||||
const ProcessId = s32;
|
/// No error occurred.
|
||||||
const MAP_FAILED = 0xffffffffffffffff;
|
SUCCESS = 0,
|
||||||
|
|
||||||
const MapFlags = bitfield(u32){
|
/// Operation not permitted
|
||||||
shared: bool,
|
PERM = 1,
|
||||||
private: bool,
|
|
||||||
reserved: u2 = 0,
|
/// No such file or directory
|
||||||
fixed: bool,
|
NOENT = 2,
|
||||||
reserved0: bool = 0,
|
|
||||||
noreserve: bool,
|
/// No such process
|
||||||
reserved1: u2 = 0,
|
SRCH = 3,
|
||||||
has_semaphore: bool,
|
|
||||||
no_cache: bool,
|
/// Interrupted system call
|
||||||
reserved2: u1 = 0,
|
INTR = 4,
|
||||||
anonymous: bool,
|
|
||||||
reserved3: u19 = 0,
|
/// Input/output error
|
||||||
|
IO = 5,
|
||||||
|
|
||||||
|
/// Device not configured
|
||||||
|
NXIO = 6,
|
||||||
|
|
||||||
|
/// Argument list too long
|
||||||
|
TOO_BIG = 7,
|
||||||
|
|
||||||
|
/// Exec format error
|
||||||
|
NOEXEC = 8,
|
||||||
|
|
||||||
|
/// Bad file descriptor
|
||||||
|
BADF = 9,
|
||||||
|
|
||||||
|
/// No child processes
|
||||||
|
CHILD = 10,
|
||||||
|
|
||||||
|
/// Resource deadlock avoided
|
||||||
|
DEADLK = 11,
|
||||||
|
|
||||||
|
/// Cannot allocate memory
|
||||||
|
NOMEM = 12,
|
||||||
|
|
||||||
|
/// Permission denied
|
||||||
|
ACCES = 13,
|
||||||
|
|
||||||
|
/// Bad address
|
||||||
|
FAULT = 14,
|
||||||
|
|
||||||
|
/// Block device required
|
||||||
|
NOTBLK = 15,
|
||||||
|
|
||||||
|
/// Device / Resource busy
|
||||||
|
BUSY = 16,
|
||||||
|
|
||||||
|
/// File exists
|
||||||
|
EXIST = 17,
|
||||||
|
|
||||||
|
/// Cross-device link
|
||||||
|
XDEV = 18,
|
||||||
|
|
||||||
|
/// Operation not supported by device
|
||||||
|
NODEV = 19,
|
||||||
|
|
||||||
|
/// Not a directory
|
||||||
|
NOTDIR = 20,
|
||||||
|
|
||||||
|
/// Is a directory
|
||||||
|
ISDIR = 21,
|
||||||
|
|
||||||
|
/// Invalid argument
|
||||||
|
INVAL = 22,
|
||||||
|
|
||||||
|
/// Too many open files in system
|
||||||
|
NFILE = 23,
|
||||||
|
|
||||||
|
/// Too many open files
|
||||||
|
MFILE = 24,
|
||||||
|
|
||||||
|
/// Inappropriate ioctl for device
|
||||||
|
NOTTY = 25,
|
||||||
|
|
||||||
|
/// Text file busy
|
||||||
|
TXTBSY = 26,
|
||||||
|
|
||||||
|
/// File too large
|
||||||
|
FBIG = 27,
|
||||||
|
|
||||||
|
/// No space left on device
|
||||||
|
NOSPC = 28,
|
||||||
|
|
||||||
|
/// Illegal seek
|
||||||
|
SPIPE = 29,
|
||||||
|
|
||||||
|
/// Read-only file system
|
||||||
|
ROFS = 30,
|
||||||
|
|
||||||
|
/// Too many links
|
||||||
|
MLINK = 31,
|
||||||
|
|
||||||
|
/// Broken pipe
|
||||||
|
PIPE = 32,
|
||||||
|
|
||||||
|
// math software
|
||||||
|
|
||||||
|
/// Numerical argument out of domain
|
||||||
|
DOM = 33,
|
||||||
|
|
||||||
|
/// Result too large
|
||||||
|
RANGE = 34,
|
||||||
|
|
||||||
|
// non-blocking and interrupt i/o
|
||||||
|
|
||||||
|
/// Resource temporarily unavailable
|
||||||
|
/// This is the same code used for `WOULDBLOCK`.
|
||||||
|
AGAIN = 35,
|
||||||
|
|
||||||
|
/// Operation now in progress
|
||||||
|
INPROGRESS = 36,
|
||||||
|
|
||||||
|
/// Operation already in progress
|
||||||
|
ALREADY = 37,
|
||||||
|
|
||||||
|
// ipc/network software -- argument errors
|
||||||
|
|
||||||
|
/// Socket operation on non-socket
|
||||||
|
NOTSOCK = 38,
|
||||||
|
|
||||||
|
/// Destination address required
|
||||||
|
DESTADDRREQ = 39,
|
||||||
|
|
||||||
|
/// Message too long
|
||||||
|
MSGSIZE = 40,
|
||||||
|
|
||||||
|
/// Protocol wrong type for socket
|
||||||
|
PROTOTYPE = 41,
|
||||||
|
|
||||||
|
/// Protocol not available
|
||||||
|
NOPROTOOPT = 42,
|
||||||
|
|
||||||
|
/// Protocol not supported
|
||||||
|
PROTONOSUPPORT = 43,
|
||||||
|
|
||||||
|
/// Socket type not supported
|
||||||
|
SOCKTNOSUPPORT = 44,
|
||||||
|
|
||||||
|
/// Operation not supported
|
||||||
|
/// The same code is used for `NOTSUP`.
|
||||||
|
OPNOTSUPP = 45,
|
||||||
|
|
||||||
|
/// Protocol family not supported
|
||||||
|
PFNOSUPPORT = 46,
|
||||||
|
|
||||||
|
/// Address family not supported by protocol family
|
||||||
|
AFNOSUPPORT = 47,
|
||||||
|
|
||||||
|
/// Address already in use
|
||||||
|
ADDRINUSE = 48,
|
||||||
|
/// Can't assign requested address
|
||||||
|
|
||||||
|
// ipc/network software -- operational errors
|
||||||
|
ADDRNOTAVAIL = 49,
|
||||||
|
|
||||||
|
/// Network is down
|
||||||
|
NETDOWN = 50,
|
||||||
|
|
||||||
|
/// Network is unreachable
|
||||||
|
NETUNREACH = 51,
|
||||||
|
|
||||||
|
/// Network dropped connection on reset
|
||||||
|
NETRESET = 52,
|
||||||
|
|
||||||
|
/// Software caused connection abort
|
||||||
|
CONNABORTED = 53,
|
||||||
|
|
||||||
|
/// Connection reset by peer
|
||||||
|
CONNRESET = 54,
|
||||||
|
|
||||||
|
/// No buffer space available
|
||||||
|
NOBUFS = 55,
|
||||||
|
|
||||||
|
/// Socket is already connected
|
||||||
|
ISCONN = 56,
|
||||||
|
|
||||||
|
/// Socket is not connected
|
||||||
|
NOTCONN = 57,
|
||||||
|
|
||||||
|
/// Can't send after socket shutdown
|
||||||
|
SHUTDOWN = 58,
|
||||||
|
|
||||||
|
/// Too many references: can't splice
|
||||||
|
TOOMANYREFS = 59,
|
||||||
|
|
||||||
|
/// Operation timed out
|
||||||
|
TIMEDOUT = 60,
|
||||||
|
|
||||||
|
/// Connection refused
|
||||||
|
CONNREFUSED = 61,
|
||||||
|
|
||||||
|
/// Too many levels of symbolic links
|
||||||
|
LOOP = 62,
|
||||||
|
|
||||||
|
/// File name too long
|
||||||
|
NAMETOOLONG = 63,
|
||||||
|
|
||||||
|
/// Host is down
|
||||||
|
HOSTDOWN = 64,
|
||||||
|
|
||||||
|
/// No route to host
|
||||||
|
HOSTUNREACH = 65,
|
||||||
|
/// Directory not empty
|
||||||
|
|
||||||
|
// quotas & mush
|
||||||
|
NOTEMPTY = 66,
|
||||||
|
|
||||||
|
/// Too many processes
|
||||||
|
PROCLIM = 67,
|
||||||
|
|
||||||
|
/// Too many users
|
||||||
|
USERS = 68,
|
||||||
|
/// Disc quota exceeded
|
||||||
|
|
||||||
|
// Network File System
|
||||||
|
DQUOT = 69,
|
||||||
|
|
||||||
|
/// Stale NFS file handle
|
||||||
|
STALE = 70,
|
||||||
|
|
||||||
|
/// Too many levels of remote in path
|
||||||
|
REMOTE = 71,
|
||||||
|
|
||||||
|
/// RPC struct is bad
|
||||||
|
BADRPC = 72,
|
||||||
|
|
||||||
|
/// RPC version wrong
|
||||||
|
RPCMISMATCH = 73,
|
||||||
|
|
||||||
|
/// RPC prog. not avail
|
||||||
|
PROGUNAVAIL = 74,
|
||||||
|
|
||||||
|
/// Program version wrong
|
||||||
|
PROGMISMATCH = 75,
|
||||||
|
|
||||||
|
/// Bad procedure for program
|
||||||
|
PROCUNAVAIL = 76,
|
||||||
|
|
||||||
|
/// No locks available
|
||||||
|
NOLCK = 77,
|
||||||
|
|
||||||
|
/// Function not implemented
|
||||||
|
NOSYS = 78,
|
||||||
|
|
||||||
|
/// Inappropriate file type or format
|
||||||
|
FTYPE = 79,
|
||||||
|
|
||||||
|
/// Authentication error
|
||||||
|
AUTH = 80,
|
||||||
|
|
||||||
|
/// Need authenticator
|
||||||
|
NEEDAUTH = 81,
|
||||||
|
|
||||||
|
// Intelligent device errors
|
||||||
|
|
||||||
|
/// Device power is off
|
||||||
|
PWROFF = 82,
|
||||||
|
|
||||||
|
/// Device error, e.g. paper out
|
||||||
|
DEVERR = 83,
|
||||||
|
|
||||||
|
/// Value too large to be stored in data type
|
||||||
|
OVERFLOW = 84,
|
||||||
|
|
||||||
|
// Program loading errors
|
||||||
|
|
||||||
|
/// Bad executable
|
||||||
|
BADEXEC = 85,
|
||||||
|
|
||||||
|
/// Bad CPU type in executable
|
||||||
|
BADARCH = 86,
|
||||||
|
|
||||||
|
/// Shared library version mismatch
|
||||||
|
SHLIBVERS = 87,
|
||||||
|
|
||||||
|
/// Malformed Macho file
|
||||||
|
BADMACHO = 88,
|
||||||
|
|
||||||
|
/// Operation canceled
|
||||||
|
CANCELED = 89,
|
||||||
|
|
||||||
|
/// Identifier removed
|
||||||
|
IDRM = 90,
|
||||||
|
|
||||||
|
/// No message of desired type
|
||||||
|
NOMSG = 91,
|
||||||
|
|
||||||
|
/// Illegal byte sequence
|
||||||
|
ILSEQ = 92,
|
||||||
|
|
||||||
|
/// Attribute not found
|
||||||
|
NOATTR = 93,
|
||||||
|
|
||||||
|
/// Bad message
|
||||||
|
BADMSG = 94,
|
||||||
|
|
||||||
|
/// Reserved
|
||||||
|
MULTIHOP = 95,
|
||||||
|
|
||||||
|
/// No message available on STREAM
|
||||||
|
NODATA = 96,
|
||||||
|
|
||||||
|
/// Reserved
|
||||||
|
NOLINK = 97,
|
||||||
|
|
||||||
|
/// No STREAM resources
|
||||||
|
NOSR = 98,
|
||||||
|
|
||||||
|
/// Not a STREAM
|
||||||
|
NOSTR = 99,
|
||||||
|
|
||||||
|
/// Protocol error
|
||||||
|
PROTO = 100,
|
||||||
|
|
||||||
|
/// STREAM ioctl timeout
|
||||||
|
TIME = 101,
|
||||||
|
|
||||||
|
/// No such policy registered
|
||||||
|
NOPOLICY = 103,
|
||||||
|
|
||||||
|
/// State not recoverable
|
||||||
|
NOTRECOVERABLE = 104,
|
||||||
|
|
||||||
|
/// Previous owner died
|
||||||
|
OWNERDEAD = 105,
|
||||||
|
|
||||||
|
/// Interface output queue is full
|
||||||
|
QFULL = 106,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ProtectionFlags = bitfield(u32) {
|
|
||||||
read: bool,
|
|
||||||
write: bool,
|
|
||||||
execute: bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
const get_protection_flags = fn(flags: std.os.ProtectionFlags) ProtectionFlags {
|
|
||||||
return ProtectionFlags{
|
|
||||||
.read = flags.read,
|
|
||||||
.write = flags.write,
|
|
||||||
.execute = flags.execute,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const get_map_flags = fn(flags: std.os.MapFlags) MapFlags{
|
|
||||||
return MapFlags{
|
|
||||||
.shared = false,
|
|
||||||
.private = true,
|
|
||||||
.fixed = false,
|
|
||||||
.noreserve = false,
|
|
||||||
.has_semaphore = false,
|
|
||||||
.no_cache = false,
|
|
||||||
.anonymous = true,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
const write :: extern = fn (file_descriptor: FileDescriptor, bytes_ptr: [&]const u8, bytes_len: usize) ssize;
|
|
||||||
const exit :: extern = fn (exit_code: s32) noreturn;
|
|
||||||
const fork :: extern = fn () ProcessId;
|
|
||||||
const mmap :: extern = fn (address: ?[&]const u8, length: usize, protection_flags: ProtectionFlags, map_flags: MapFlags, file_descriptor: FileDescriptor, offset: u64) usize;
|
|
||||||
const munmap :: extern = fn (address: [&]const u8, length: usize) s32;
|
|
||||||
const execve :: extern = fn(path: [&:0]const u8, argv: [&:null]const ?[&:0]const u8, env: [&:null]const ?[&:null]const u8) s32;
|
|
||||||
const realpath :: extern = fn(path: [&:0]const u8, resolved_path: [&:0]u8) [&:0]u8;
|
|
||||||
const waitpid :: extern = fn(pid: ProcessId, status: &s32, flags: s32) s32;
|
|
||||||
|
|
||||||
const _NSGetExecutablePath :: extern = fn (buffer: [&:0]u8, buffer_size: &u32) s32;
|
|
||||||
|
@ -2,13 +2,13 @@ const std = #import("std");
|
|||||||
const builtin = #import("builtin");
|
const builtin = #import("builtin");
|
||||||
comptime {
|
comptime {
|
||||||
if (builtin.link_libc) {
|
if (builtin.link_libc) {
|
||||||
_ = main;
|
#export(main);
|
||||||
} else {
|
} else {
|
||||||
_ = _start;
|
#export(_start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const _start :: export = fn naked() noreturn {
|
const _start = fn naked cc(.c) () noreturn {
|
||||||
#asm(`
|
#asm(`
|
||||||
xor ebp, ebp;
|
xor ebp, ebp;
|
||||||
mov rdi, rsp;
|
mov rdi, rsp;
|
||||||
@ -21,7 +21,7 @@ var argument_count: usize = 0;
|
|||||||
var argument_values: [&]const [&:0]const u8 = undefined;
|
var argument_values: [&]const [&:0]const u8 = undefined;
|
||||||
var environment_values: [&:null]const ?[&:null]const u8 = undefined;
|
var environment_values: [&:null]const ?[&:null]const u8 = undefined;
|
||||||
|
|
||||||
const start :: export = fn (argc_argv_address: usize) noreturn {
|
const start = fn cc(.c) (argc_argv_address: usize) noreturn {
|
||||||
var argument_address_iterator = argc_argv_address;
|
var argument_address_iterator = argc_argv_address;
|
||||||
const argument_count_ptr: &usize = #cast(argument_address_iterator);
|
const argument_count_ptr: &usize = #cast(argument_address_iterator);
|
||||||
argument_count = argument_count_ptr.@;
|
argument_count = argument_count_ptr.@;
|
||||||
@ -35,7 +35,7 @@ const start :: export = fn (argc_argv_address: usize) noreturn {
|
|||||||
std.os.exit(0);
|
std.os.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const main :: export = fn (argc: s32, argv: [&]const [&:0]const u8, env: [&:null]const ?[&:null]const u8) s32 {
|
const main = fn cc(.c) (argc: s32, argv: [&]const [&:0]const u8, env: [&:null]const ?[&:null]const u8) s32 {
|
||||||
const argc_u: u32 = #cast(argc);
|
const argc_u: u32 = #cast(argc);
|
||||||
argument_count = argc_u;
|
argument_count = argc_u;
|
||||||
argument_values = argv;
|
argument_values = argv;
|
||||||
|
@ -12,6 +12,7 @@ test {
|
|||||||
const build = #import("build.nat");
|
const build = #import("build.nat");
|
||||||
const builtin = #import("builtin.nat");
|
const builtin = #import("builtin.nat");
|
||||||
const os = #import("os.nat");
|
const os = #import("os.nat");
|
||||||
|
const c = #import("c.nat");
|
||||||
const start = #import("start.nat");
|
const start = #import("start.nat");
|
||||||
const testing = #import("testing.nat");
|
const testing = #import("testing.nat");
|
||||||
|
|
||||||
|
@ -288,6 +288,7 @@ extern "C" Function* NativityLLVMModuleGetFunction(Module& module, const char* n
|
|||||||
|
|
||||||
extern "C" void NativityLLVMFunctionAddAttributeKey(Function& function, Attribute::AttrKind attribute)
|
extern "C" void NativityLLVMFunctionAddAttributeKey(Function& function, Attribute::AttrKind attribute)
|
||||||
{
|
{
|
||||||
|
static_assert(sizeof(Attribute) == sizeof(size_t));
|
||||||
function.addFnAttr(attribute);
|
function.addFnAttr(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -357,6 +358,12 @@ extern "C" void NativityLLVMFunctionGetArguments(Function& function, Argument**
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" Argument* NativityLLVMFunctionGetArgument(Function& function, unsigned index)
|
||||||
|
{
|
||||||
|
auto* arg = function.getArg(index);
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void NativityLLVMFunctionSetSubprogram(Function& function, DISubprogram* subprogram)
|
extern "C" void NativityLLVMFunctionSetSubprogram(Function& function, DISubprogram* subprogram)
|
||||||
{
|
{
|
||||||
function.setSubprogram(subprogram);
|
function.setSubprogram(subprogram);
|
||||||
@ -386,16 +393,21 @@ extern "C" ConstantInt* NativityLLVMConstantToInt(Constant* constant)
|
|||||||
return constant_int;
|
return constant_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" StoreInst* NativityLLVMBuilderCreateStore(IRBuilder<>& builder, Value* value, Value* pointer, bool is_volatile)
|
extern "C" StoreInst* NativityLLVMBuilderCreateStore(IRBuilder<>& builder, Value* value, Value* pointer, bool is_volatile, uint32_t alignment)
|
||||||
{
|
{
|
||||||
auto* store = builder.CreateStore(value, pointer, is_volatile);
|
auto align = Align{alignment};
|
||||||
|
auto* basic_block = builder.GetInsertBlock();
|
||||||
|
auto* store = new StoreInst(value, pointer, is_volatile, align,
|
||||||
|
AtomicOrdering::NotAtomic, SyncScope::System, basic_block);
|
||||||
return store;
|
return store;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" AllocaInst* NativityLLVMBuilderCreateAlloca(IRBuilder<>& builder, Type* type, unsigned address_space, Value* array_size, const char* name_ptr, size_t name_len)
|
extern "C" AllocaInst* NativityLLVMBuilderCreateAlloca(IRBuilder<>& builder, Type* type, unsigned address_space, Value* array_size, const char* name_ptr, size_t name_len, uint32_t alignment)
|
||||||
{
|
{
|
||||||
auto name = StringRef(name_ptr, name_len);
|
auto name = StringRef(name_ptr, name_len);
|
||||||
auto* alloca = builder.CreateAlloca(type, address_space, array_size, name);
|
auto align = Align{ alignment };
|
||||||
|
BasicBlock* insert_block = builder.GetInsertBlock();
|
||||||
|
AllocaInst* alloca = new AllocaInst(type, address_space, array_size, align, name, insert_block);
|
||||||
return alloca;
|
return alloca;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,10 +424,13 @@ extern "C" Value* NativityLLVMBuilderCreateICmp(IRBuilder<>& builder, CmpInst::P
|
|||||||
return icmp;
|
return icmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" LoadInst* NativityLLVMBuilderCreateLoad(IRBuilder<>& builder, Type* type, Value* value, bool is_volatile, const char* name_ptr, size_t name_len)
|
extern "C" LoadInst* NativityLLVMBuilderCreateLoad(IRBuilder<>& builder, Type* type, Value* pointer, bool is_volatile, const char* name_ptr, size_t name_len, uint32_t alignment)
|
||||||
{
|
{
|
||||||
|
auto align = Align{alignment};
|
||||||
auto name = StringRef(name_ptr, name_len);
|
auto name = StringRef(name_ptr, name_len);
|
||||||
auto* load = builder.CreateLoad(type, value, is_volatile, name);
|
auto* basic_block = builder.GetInsertBlock();
|
||||||
|
auto* load = new LoadInst(type, pointer, name, is_volatile,
|
||||||
|
align, AtomicOrdering::NotAtomic, SyncScope::System, basic_block);
|
||||||
return load;
|
return load;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -940,15 +955,61 @@ extern "C" bool NativityLLVMModuleAddPassesToEmitFile(Module& module, TargetMach
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" bool NativityLLVMCompareTypes(Type* a, Type* b)
|
extern "C" Attribute NativityLLVMContextGetAttributeFromEnum(LLVMContext& context, Attribute::AttrKind kind, uint64_t value)
|
||||||
{
|
{
|
||||||
if (auto* int_a = dyn_cast<IntegerType>(a)) {
|
static_assert(sizeof(Attribute) == sizeof(uintptr_t));
|
||||||
auto* int_b = dyn_cast<IntegerType>(b);
|
auto attribute = Attribute::get(context, kind, value);
|
||||||
assert(int_b);
|
return attribute;
|
||||||
auto a_bit_count = int_a->getBitWidth();
|
}
|
||||||
auto b_bit_count = int_b->getBitWidth();
|
|
||||||
assert(a_bit_count == b_bit_count);
|
extern "C" Attribute NativityLLVMContextGetAttributeFromType(LLVMContext& context, Attribute::AttrKind kind, Type* type)
|
||||||
}
|
{
|
||||||
|
static_assert(sizeof(Attribute) == sizeof(uintptr_t));
|
||||||
return a == b;
|
auto attribute = Attribute::get(context, kind, type);
|
||||||
|
return attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" Attribute NativityLLVMContextGetAttributeFromString(LLVMContext& context, const char* kind_ptr, size_t kind_len, const char* value_ptr, size_t value_len)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(Attribute) == sizeof(uintptr_t));
|
||||||
|
auto kind = StringRef(kind_ptr, kind_len);
|
||||||
|
auto value = StringRef(value_ptr, value_len);
|
||||||
|
auto attribute = Attribute::get(context, kind, value);
|
||||||
|
return attribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" AttributeSet NativityLLVMContextGetAttributeSet(LLVMContext& context, const Attribute* attribute_ptr, size_t attribute_count)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(AttributeSet) == sizeof(uintptr_t));
|
||||||
|
auto attributes = ArrayRef<Attribute>(attribute_ptr, attribute_count);
|
||||||
|
auto attribute_set = AttributeSet::get(context, attributes);
|
||||||
|
return attribute_set;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void NativityLLVMFunctionSetAttributes(Function& function, LLVMContext& context, AttributeSet function_attributes, AttributeSet return_attributes, const AttributeSet* parameter_attribute_set_ptr, size_t parameter_attribute_set_count)
|
||||||
|
{
|
||||||
|
auto parameter_attribute_sets = ArrayRef<AttributeSet>(parameter_attribute_set_ptr, parameter_attribute_set_count);
|
||||||
|
auto attribute_list = AttributeList::get(context, function_attributes, return_attributes, parameter_attribute_sets);
|
||||||
|
function.setAttributes(attribute_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void NativityLLVMCallSetAttributes(CallInst& call, LLVMContext& context, AttributeSet function_attributes, AttributeSet return_attributes, const AttributeSet* parameter_attribute_set_ptr, size_t parameter_attribute_set_count)
|
||||||
|
{
|
||||||
|
auto parameter_attribute_sets = ArrayRef<AttributeSet>(parameter_attribute_set_ptr, parameter_attribute_set_count);
|
||||||
|
auto attribute_list = AttributeList::get(context, function_attributes, return_attributes, parameter_attribute_sets);
|
||||||
|
call.setAttributes(attribute_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" CallInst* NativityLLVMBuilderCreateMemcpy(IRBuilder<>& builder, Value* destination, uint32_t destination_alignment, Value* source, uint32_t source_alignment, uint64_t size, bool is_volatile)
|
||||||
|
{
|
||||||
|
auto dst_alignment = MaybeAlign(destination_alignment);
|
||||||
|
auto src_alignment = MaybeAlign(source_alignment);
|
||||||
|
auto memcpy = builder.CreateMemCpy(destination, dst_alignment, source, src_alignment, size, is_volatile);
|
||||||
|
|
||||||
|
return memcpy;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern "C" void NativityLLVMTypeAssertEqual(Type* a, Type* b)
|
||||||
|
{
|
||||||
|
assert(a == b);
|
||||||
}
|
}
|
||||||
|
17
test/build/c-abi/.vscode/launch.json
vendored
Normal file
17
test/build/c-abi/.vscode/launch.json
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "cppdbg",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Debug",
|
||||||
|
"program": "${workspaceFolder}/nat/c-abi",
|
||||||
|
"args": [],
|
||||||
|
"MIMode": "lldb",
|
||||||
|
"cwd": "${workspaceFolder}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
@ -10,7 +10,7 @@ const main = fn() *!void {
|
|||||||
},
|
},
|
||||||
.main_source_path = "main.nat",
|
.main_source_path = "main.nat",
|
||||||
.name = "c-abi",
|
.name = "c-abi",
|
||||||
.c_source_files = .{ "foo.c" }.&,
|
.c_source_files = .{ "c.c" }.&,
|
||||||
};
|
};
|
||||||
|
|
||||||
try executable.compile();
|
try executable.compile();
|
||||||
|
5483
test/build/c-abi/c.c
Normal file
5483
test/build/c-abi/c.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +0,0 @@
|
|||||||
typedef unsigned u32;
|
|
||||||
u32 foo(u32 arg)
|
|
||||||
{
|
|
||||||
return arg;
|
|
||||||
}
|
|
@ -1,7 +1,490 @@
|
|||||||
const std = #import("std");
|
const std = #import("std");
|
||||||
const expect = std.testing.expect;
|
const expect = std.testing.expect;
|
||||||
const foo :: extern = fn(arg: u32) u32;
|
const run_c_tests :: extern = fn cc(.c) () void;
|
||||||
|
const has_i128 = false;
|
||||||
|
|
||||||
const main = fn () *!void {
|
const main = fn () *!void {
|
||||||
const arg = 0xabcdef;
|
run_c_tests();
|
||||||
try expect(foo(arg) == arg);
|
|
||||||
|
c_u8(0xff);
|
||||||
|
c_u16(0xfffe);
|
||||||
|
c_u32(0xfffffffd);
|
||||||
|
c_u64(0xfffffffffffffffc);
|
||||||
|
|
||||||
|
if (has_i128) {
|
||||||
|
c_struct_u128(.{ .value = 0xfffffffffffffffc, });
|
||||||
|
}
|
||||||
|
|
||||||
|
c_s8(-1);
|
||||||
|
c_s16(-2);
|
||||||
|
c_s32(-3);
|
||||||
|
c_s64(-4);
|
||||||
|
|
||||||
|
if (has_i128) {
|
||||||
|
c_struct_i128(.{ .value = -6, });
|
||||||
|
}
|
||||||
|
|
||||||
|
c_bool(true);
|
||||||
|
|
||||||
|
c_five_integers(12, 34, 56, 78, 90);
|
||||||
|
|
||||||
|
const s = c_ret_struct_u64_u64();
|
||||||
|
try expect(s.a == 21);
|
||||||
|
try expect(s.b == 22);
|
||||||
|
c_struct_u64_u64_0(.{ .a = 23, .b = 24, });
|
||||||
|
c_struct_u64_u64_1(0, .{ .a = 25, .b = 26, });
|
||||||
|
c_struct_u64_u64_2(0, 1, .{ .a = 27, .b = 28, });
|
||||||
|
c_struct_u64_u64_3(0, 1, 2, .{ .a = 29, .b = 30, });
|
||||||
|
c_struct_u64_u64_4(0, 1, 2, 3, .{ .a = 31, .b = 32, });
|
||||||
|
c_struct_u64_u64_5(0, 1, 2, 3, 4, .{ .a = 33, .b = 34, });
|
||||||
|
c_struct_u64_u64_6(0, 1, 2, 3, 4, 5, .{ .a = 35, .b = 36, });
|
||||||
|
c_struct_u64_u64_7(0, 1, 2, 3, 4, 5, 6, .{ .a = 37, .b = 38, });
|
||||||
|
c_struct_u64_u64_8(0, 1, 2, 3, 4, 5, 6, 7, .{ .a = 39, .b = 40, });
|
||||||
|
|
||||||
|
const big_struct = BigStruct{
|
||||||
|
.a = 1,
|
||||||
|
.b = 2,
|
||||||
|
.c = 3,
|
||||||
|
.d = 4,
|
||||||
|
.e = 5,
|
||||||
|
};
|
||||||
|
c_big_struct(big_struct);
|
||||||
|
|
||||||
|
const small = SmallStructInts{
|
||||||
|
.a = 1,
|
||||||
|
.b = 2,
|
||||||
|
.c = 3,
|
||||||
|
.d = 4,
|
||||||
|
};
|
||||||
|
c_small_struct_ints(small);
|
||||||
|
const small2 = c_ret_small_struct_ints();
|
||||||
|
try expect(small2.a == 1);
|
||||||
|
try expect(small2.b == 2);
|
||||||
|
try expect(small2.c == 3);
|
||||||
|
try expect(small2.d == 4);
|
||||||
|
|
||||||
|
const med = MedStructInts{
|
||||||
|
.x = 1,
|
||||||
|
.y = 2,
|
||||||
|
.z = 3,
|
||||||
|
};
|
||||||
|
c_med_struct_ints(med);
|
||||||
|
const med2 = c_ret_med_struct_ints();
|
||||||
|
try expect(med2.x == 1);
|
||||||
|
try expect(med2.y == 2);
|
||||||
|
try expect(med2.z == 3);
|
||||||
|
|
||||||
|
const p = SmallPackedStruct{ .a = 0, .b = 1, .c = 2, .d = 3, };
|
||||||
|
c_small_packed_struct(p);
|
||||||
|
const p2 = c_ret_small_packed_struct();
|
||||||
|
try expect(p2.a == 0);
|
||||||
|
try expect(p2.b == 1);
|
||||||
|
try expect(p2.c == 2);
|
||||||
|
try expect(p2.d == 3);
|
||||||
|
|
||||||
|
const split = SplitStructInt{
|
||||||
|
.a = 1234,
|
||||||
|
.b = 100,
|
||||||
|
.c = 1337,
|
||||||
|
};
|
||||||
|
c_split_struct_ints(split);
|
||||||
|
|
||||||
|
const big = BigStruct{
|
||||||
|
.a = 1,
|
||||||
|
.b = 2,
|
||||||
|
.c = 3,
|
||||||
|
.d = 4,
|
||||||
|
.e = 5,
|
||||||
|
};
|
||||||
|
const big2 = c_big_struct_both(big);
|
||||||
|
try expect(big2.a == 10);
|
||||||
|
try expect(big2.b == 11);
|
||||||
|
try expect(big2.c == 12);
|
||||||
|
try expect(big2.d == 13);
|
||||||
|
try expect(big2.e == 14);
|
||||||
|
|
||||||
|
const r1 = Rect{
|
||||||
|
.left = 1,
|
||||||
|
.right = 21,
|
||||||
|
.top = 16,
|
||||||
|
.bottom = 4,
|
||||||
|
};
|
||||||
|
const r2 = Rect{
|
||||||
|
.left = 178,
|
||||||
|
.right = 189,
|
||||||
|
.top = 21,
|
||||||
|
.bottom = 15,
|
||||||
|
};
|
||||||
|
c_multiple_struct_ints(r1, r2);
|
||||||
|
|
||||||
|
try expect(c_ret_bool() == true);
|
||||||
|
|
||||||
|
try expect(c_ret_u8() == 0xff);
|
||||||
|
try expect(c_ret_u16() == 0xffff);
|
||||||
|
try expect(c_ret_u32() == 0xffffffff);
|
||||||
|
try expect(c_ret_u64() == 0xffffffffffffffff);
|
||||||
|
|
||||||
|
try expect(c_ret_s8() == -1);
|
||||||
|
try expect(c_ret_s16() == -1);
|
||||||
|
try expect(c_ret_s32() == -1);
|
||||||
|
try expect(c_ret_s64() == -1);
|
||||||
|
|
||||||
|
c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2, });
|
||||||
|
|
||||||
|
const x = c_ret_struct_with_array();
|
||||||
|
try expect(x.a == 4);
|
||||||
|
try expect(x.b == 155);
|
||||||
|
|
||||||
|
const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined, });
|
||||||
|
try expect(res.val == 42);
|
||||||
|
|
||||||
|
var function_pointer = c_func_ptr_byval.&;
|
||||||
|
function_pointer(1, 2, .{ .origin = .{ .x = 9, .y = 10, .z = 11, }, .size = .{ .width = 12, .height = 13, .depth = 14, }, }, 3, 4, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ByRef = struct {
|
||||||
|
val: s32,
|
||||||
|
arr: [15]s32,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ByVal = struct {
|
||||||
|
origin: ByValOrigin,
|
||||||
|
size: ByValSize,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ByValOrigin = struct{
|
||||||
|
x: u64,
|
||||||
|
y: u64,
|
||||||
|
z: u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
const ByValSize = struct{
|
||||||
|
width: u64,
|
||||||
|
height: u64,
|
||||||
|
depth: u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
const c_u8 :: extern = fn cc(.c) (x: u8) void;
|
||||||
|
const c_u16 :: extern = fn cc(.c) (x: u16) void;
|
||||||
|
const c_u32 :: extern = fn cc(.c) (x: u32) void;
|
||||||
|
const c_u64 :: extern = fn cc(.c) (x: u64) void;
|
||||||
|
|
||||||
|
const c_s8 :: extern = fn cc(.c) (x: s8) void;
|
||||||
|
const c_s16 :: extern = fn cc(.c) (x: s16) void;
|
||||||
|
const c_s32 :: extern = fn cc(.c) (x: s32) void;
|
||||||
|
const c_s64 :: extern = fn cc(.c) (x: s64) void;
|
||||||
|
|
||||||
|
const c_bool :: extern = fn cc(.c) (x: bool) void;
|
||||||
|
|
||||||
|
const c_five_integers :: extern = fn cc(.c) (a: s32, b: s32, c: s32, d: s32, e: s32) void;
|
||||||
|
|
||||||
|
const c_ret_struct_u64_u64 :: extern = fn cc(.c) () Struct_u64_u64;
|
||||||
|
|
||||||
|
const c_struct_u64_u64_0 :: extern = fn cc(.c) (x: Struct_u64_u64) void;
|
||||||
|
const c_struct_u64_u64_1 :: extern = fn cc(.c) (a: usize, b: Struct_u64_u64) void;
|
||||||
|
const c_struct_u64_u64_2 :: extern = fn cc(.c) (a: usize, b: usize, c: Struct_u64_u64) void;
|
||||||
|
const c_struct_u64_u64_3 :: extern = fn cc(.c) (a: usize, b: usize, c: usize, d: Struct_u64_u64) void;
|
||||||
|
const c_struct_u64_u64_4 :: extern = fn cc(.c) (a: usize, b: usize, c: usize, d: usize, e: Struct_u64_u64) void;
|
||||||
|
const c_struct_u64_u64_5 :: extern = fn cc(.c) (a: usize, b: usize, c: usize, d: usize, e: usize, f: Struct_u64_u64) void;
|
||||||
|
const c_struct_u64_u64_6 :: extern = fn cc(.c) (a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: Struct_u64_u64) void;
|
||||||
|
const c_struct_u64_u64_7 :: extern = fn cc(.c) (a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: Struct_u64_u64) void;
|
||||||
|
const c_struct_u64_u64_8 :: extern = fn cc(.c) (a: usize, b: usize, c: usize, d: usize, e: usize, f: usize, g: usize, h: usize, i: Struct_u64_u64) void;
|
||||||
|
|
||||||
|
const c_big_struct :: extern = fn cc(.c) (x: BigStruct) void;
|
||||||
|
|
||||||
|
const c_small_struct_ints :: extern = fn cc(.c) (x: SmallStructInts) void;
|
||||||
|
const c_ret_small_struct_ints :: extern = fn cc(.c) () SmallStructInts;
|
||||||
|
|
||||||
|
const c_med_struct_ints :: extern = fn cc(.c) (x: MedStructInts) void;
|
||||||
|
const c_ret_med_struct_ints :: extern = fn cc(.c) () MedStructInts;
|
||||||
|
|
||||||
|
const c_small_packed_struct :: extern = fn cc(.c) (x: SmallPackedStruct) void;
|
||||||
|
const c_ret_small_packed_struct :: extern = fn cc(.c) () SmallPackedStruct;
|
||||||
|
|
||||||
|
const c_split_struct_ints :: extern = fn cc(.c) (x: SplitStructInt) void;
|
||||||
|
|
||||||
|
const c_big_struct_both :: extern = fn cc(.c) (x: BigStruct) BigStruct;
|
||||||
|
|
||||||
|
const c_multiple_struct_ints :: extern = fn cc(.c) (r1: Rect, r2: Rect) void;
|
||||||
|
|
||||||
|
const c_ret_bool :: extern = fn cc(.c) () bool;
|
||||||
|
|
||||||
|
const c_ret_u8 :: extern = fn cc(.c) () u8;
|
||||||
|
const c_ret_u16 :: extern = fn cc(.c) () u16;
|
||||||
|
const c_ret_u32 :: extern = fn cc(.c) () u32;
|
||||||
|
const c_ret_u64 :: extern = fn cc(.c) () u64;
|
||||||
|
|
||||||
|
const c_ret_s8 :: extern = fn cc(.c) () s8;
|
||||||
|
const c_ret_s16 :: extern = fn cc(.c) () s16;
|
||||||
|
const c_ret_s32 :: extern = fn cc(.c) () s32;
|
||||||
|
const c_ret_s64 :: extern = fn cc(.c) () s64;
|
||||||
|
|
||||||
|
const StructWithArray = struct{
|
||||||
|
a: s32,
|
||||||
|
padding: [4]u8,
|
||||||
|
b: s64,
|
||||||
|
};
|
||||||
|
|
||||||
|
const c_struct_with_array :: extern = fn cc(.c) (x: StructWithArray) void;
|
||||||
|
const c_ret_struct_with_array :: extern = fn cc(.c) () StructWithArray;
|
||||||
|
const c_modify_by_ref_param :: extern = fn cc(.c) (x: ByRef) ByRef;
|
||||||
|
|
||||||
|
const c_func_ptr_byval :: extern = fn cc(.c) (a: usize, b: usize, c: ByVal, d: u64, e: u64, f: u64) void;
|
||||||
|
|
||||||
|
const nat_u8 :: export = fn cc(.c) (x: u8) void {
|
||||||
|
expect(x == 0xff) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_u16 :: export = fn cc(.c) (x: u16) void {
|
||||||
|
expect(x == 0xfffe) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_u32 :: export = fn cc(.c) (x: u32) void {
|
||||||
|
expect(x == 0xfffffffd) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_u64 :: export = fn cc(.c) (x: u64) void {
|
||||||
|
expect(x == 0xfffffffffffffffc) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_s8 :: export = fn cc(.c) (x: s8) void {
|
||||||
|
expect(x == -1) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_s16 :: export = fn cc(.c) (x: s16) void {
|
||||||
|
expect(x == -2) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_s32 :: export = fn cc(.c) (x: s32) void {
|
||||||
|
expect(x == -3) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_s64 :: export = fn cc(.c) (x: s64) void {
|
||||||
|
expect(x == -4) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: transform into a real pointer
|
||||||
|
const nat_ptr :: export = fn cc(.c) (x: usize) void {
|
||||||
|
expect(x == 0xdeadbeef) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_five_integers :: export = fn cc(.c) (a: s32, b: s32, c: s32, d: s32, e: s32) void {
|
||||||
|
expect(a == 12) catch #trap();
|
||||||
|
expect(b == 34) catch #trap();
|
||||||
|
expect(c == 56) catch #trap();
|
||||||
|
expect(d == 78) catch #trap();
|
||||||
|
expect(e == 90) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_bool:: export = fn cc(.c) (x: bool) void {
|
||||||
|
expect(x) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Struct_u64_u64 = struct{
|
||||||
|
a: u64,
|
||||||
|
b: u64,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nat_ret_struct_u64_u64 :: export = fn cc(.c) () Struct_u64_u64 {
|
||||||
|
return .{ .a = 1, .b = 2, };
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_0 :: export = fn cc(.c) (s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 3) catch #trap();
|
||||||
|
expect(s.b == 4) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_1 :: export = fn cc(.c) (_: usize, s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 5) catch #trap();
|
||||||
|
expect(s.b == 6) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_2 :: export = fn cc(.c) (_: usize, _: usize, s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 7) catch #trap();
|
||||||
|
expect(s.b == 8) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_3 :: export = fn cc(.c) (_: usize, _: usize, _: usize, s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 9) catch #trap();
|
||||||
|
expect(s.b == 10) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_4 :: export = fn cc(.c) (_: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 11) catch #trap();
|
||||||
|
expect(s.b == 12) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_5 :: export = fn cc(.c) (_: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 13) catch #trap();
|
||||||
|
expect(s.b == 14) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_6 :: export = fn cc(.c) (_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 15) catch #trap();
|
||||||
|
expect(s.b == 16) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_7 :: export = fn cc(.c) (_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 17) catch #trap();
|
||||||
|
expect(s.b == 18) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_struct_u64_u64_8 :: export = fn cc(.c) (_: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, _: usize, s: Struct_u64_u64) void {
|
||||||
|
expect(s.a == 19) catch #trap();
|
||||||
|
expect(s.b == 20) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const BigStruct = struct {
|
||||||
|
a: u64,
|
||||||
|
b: u64,
|
||||||
|
c: u64,
|
||||||
|
d: u64,
|
||||||
|
e: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nat_big_struct:: export = fn cc(.c) (x: BigStruct) void {
|
||||||
|
expect(x.a == 1) catch #trap();
|
||||||
|
expect(x.b == 2) catch #trap();
|
||||||
|
expect(x.c == 3) catch #trap();
|
||||||
|
expect(x.d == 4) catch #trap();
|
||||||
|
expect(x.e == 5) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SmallStructInts = struct {
|
||||||
|
a: u8,
|
||||||
|
b: u8,
|
||||||
|
c: u8,
|
||||||
|
d: u8,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nat_small_struct_ints :: export = fn cc(.c) (x: SmallStructInts) void {
|
||||||
|
expect(x.a == 1) catch #trap();
|
||||||
|
expect(x.b == 2) catch #trap();
|
||||||
|
expect(x.c == 3) catch #trap();
|
||||||
|
expect(x.d == 4) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const MedStructInts = struct {
|
||||||
|
x: s32,
|
||||||
|
y: s32,
|
||||||
|
z: s32,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nat_med_struct_ints :: export = fn cc(.c) (s: MedStructInts) void {
|
||||||
|
expect(s.x == 1) catch #trap();
|
||||||
|
expect(s.y == 2) catch #trap();
|
||||||
|
expect(s.z == 3) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SmallPackedStruct = bitfield(u8) {
|
||||||
|
a: u2,
|
||||||
|
b: u2,
|
||||||
|
c: u2,
|
||||||
|
d: u2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nat_small_packed_struct :: export = fn cc(.c) (x: SmallPackedStruct) void {
|
||||||
|
expect(x.a == 0) catch #trap();
|
||||||
|
expect(x.b == 1) catch #trap();
|
||||||
|
expect(x.c == 2) catch #trap();
|
||||||
|
expect(x.d == 3) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SplitStructInt = struct {
|
||||||
|
a: u64,
|
||||||
|
b: u8,
|
||||||
|
c: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nat_split_struct_ints :: export = fn cc(.c) (x: SplitStructInt) void {
|
||||||
|
expect(x.a == 1234) catch #trap();
|
||||||
|
expect(x.b == 100) catch #trap();
|
||||||
|
expect(x.c == 1337) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_big_struct_both :: export = fn cc(.c) (x: BigStruct) BigStruct {
|
||||||
|
expect(x.a == 30) catch #trap();
|
||||||
|
expect(x.b == 31) catch #trap();
|
||||||
|
expect(x.c == 32) catch #trap();
|
||||||
|
expect(x.d == 33) catch #trap();
|
||||||
|
expect(x.e == 34) catch #trap();
|
||||||
|
const s = BigStruct{
|
||||||
|
.a = 20,
|
||||||
|
.b = 21,
|
||||||
|
.c = 22,
|
||||||
|
.d = 23,
|
||||||
|
.e = 24,
|
||||||
|
};
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Rect = struct {
|
||||||
|
left: u32,
|
||||||
|
right: u32,
|
||||||
|
top: u32,
|
||||||
|
bottom: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
const nat_multiple_struct_ints :: export = fn cc(.c) (x: Rect, y: Rect) void {
|
||||||
|
expect(x.left == 1) catch #trap();
|
||||||
|
expect(x.right == 21) catch #trap();
|
||||||
|
expect(x.top == 16) catch #trap();
|
||||||
|
expect(x.bottom == 4) catch #trap();
|
||||||
|
expect(y.left == 178) catch #trap();
|
||||||
|
expect(y.right == 189) catch #trap();
|
||||||
|
expect(y.top == 21) catch #trap();
|
||||||
|
expect(y.bottom == 15) catch #trap();
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_bool :: export = fn cc(.c) () bool {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_u8 :: export = fn cc(.c) () u8 {
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_u16 :: export = fn cc(.c) () u16 {
|
||||||
|
return 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_u32 :: export = fn cc(.c) () u32 {
|
||||||
|
return 0xffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_u64 :: export = fn cc(.c) () u64 {
|
||||||
|
return 0xffffffffffffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_s8 :: export = fn cc(.c) () s8 {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_s16 :: export = fn cc(.c) () s16 {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_s32 :: export = fn cc(.c) () s32 {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_s64 :: export = fn cc(.c) () s64 {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_small_struct_ints :: export = fn cc(.c) () SmallStructInts {
|
||||||
|
return .{
|
||||||
|
.a = 1,
|
||||||
|
.b = 2,
|
||||||
|
.c = 3,
|
||||||
|
.d = 4,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const nat_ret_med_struct_ints :: export = fn cc(.c) () MedStructInts {
|
||||||
|
return .{
|
||||||
|
.x = 1,
|
||||||
|
.y = 2,
|
||||||
|
.z = 3,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user