The {#syntax#}@import("builtin").single_threaded{#endsyntax#} becomes {#syntax#}true{#endsyntax#}
@@ -7343,12 +7690,30 @@ fn bar(f: *Foo) void {
f.float = 12.34;
}
{#code_end#}
+ {#see_also|union|extern union#}
{#header_close#}
- {#header_open|Out of Bounds Float To Integer Cast#}
+ {#header_open|Out of Bounds Float to Integer Cast#}
TODO
{#header_close#}
+ {#header_open|Pointer Cast Invalid Null#}
+ At compile-time:
+ {#code_begin|test_err|null pointer casted to type#}
+comptime {
+ const opt_ptr: ?*i32 = null;
+ const ptr = @ptrCast(*i32, opt_ptr);
+}
+ {#code_end#}
+ At runtime:
+ {#code_begin|exe_err#}
+pub fn main() void {
+ var opt_ptr: ?*i32 = null;
+ var ptr = @ptrCast(*i32, opt_ptr);
+}
+ {#code_end#}
+ {#header_close#}
+
{#header_close#}
{#header_open|Memory#}
TODO: explain no default allocator in zig
@@ -7439,6 +7804,7 @@ pub fn main() void {
{#code_end#}
{#see_also|String Literals#}
{#header_close#}
+
{#header_open|Import from C Header File#}
The {#syntax#}@cImport{#endsyntax#} builtin function can be used
@@ -7477,6 +7843,36 @@ const c = @cImport({
{#code_end#}
{#see_also|@cImport|@cInclude|@cDefine|@cUndef|@import#}
{#header_close#}
+
+ {#header_open|C Pointers#}
+
+ This type is to be avoided whenever possible. The only valid reason for using a C pointer is in
+ auto-generated code from translating C code.
+
+
+ When importing C header files, it is ambiguous whether pointers should be translated as
+ single-item pointers ({#syntax#}*T{#endsyntax#}) or unknown-length pointers ({#syntax#}[*]T{#endsyntax#}).
+ C pointers are a compromise so that Zig code can utilize translated header files directly.
+
+ {#syntax#}[*c]T{#endsyntax#} - C pointer.
+
+ - Supports all the syntax of the other two pointer types.
+ - Implicitly casts to other pointer types, as well as {#link|Optional Pointers#}.
+ When a C pointer is implicitly casted to a non-optional pointer, safety-checked
+ {#link|Undefined Behavior#} occurs if the address is 0.
+
+ - Allows address 0. On non-freestanding targets, dereferencing address 0 is safety-checked
+ {#link|Undefined Behavior#}. Optional C pointers introduce another bit to keep track of
+ null, just like {#syntax#}?usize{#endsyntax#}. Note that creating an optional C pointer
+ is unnecessary as one can use normal {#link|Optional Pointers#}.
+
+ - Supports {#link|implicit casting|Implicit Casts#} to and from integers.
+ - Supports comparison with integers.
+ - Does not support Zig-only pointer attributes such as alignment. Use normal {#link|Pointers#}
+ please!
+
+ {#header_close#}
+
{#header_open|Exporting a C Library#}
One of the primary use cases for Zig is exporting a library with the C ABI for other programming languages
@@ -7729,7 +8125,7 @@ Environments:
coreclr
opencl
- The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating sytsem
+ The Zig Standard Library ({#syntax#}@import("std"){#endsyntax#}) has architecture, environment, and operating system
abstractions, and thus takes additional work to support more platforms.
Not all standard library code requires operating system abstractions, however,
so things such as generic data structures work an all above platforms.
@@ -8164,7 +8560,8 @@ ArrayTypeStart <- LBRACKET Expr? RBRACKET
PtrTypeStart
<- ASTERISK
/ ASTERISK2
- / LBRACKET ASTERISK RBRACKET
+ / PTRUNKNOWN
+ / PTRC
# ContainerDecl specific
ContainerDeclAuto <- ContainerDeclType LBRACE ContainerMembers RBRACE
@@ -8262,7 +8659,7 @@ LARROW2 <- '<<' ![=] skip
LARROW2EQUAL <- '<<=' skip
LARROWEQUAL <- '<=' skip
LBRACE <- '{' skip
-LBRACKET <- '[' skip
+LBRACKET <- '[' ![*] skip
LPAREN <- '(' skip
MINUS <- '-' ![%=>] skip
MINUSEQUAL <- '-=' skip
@@ -8279,6 +8676,8 @@ PLUS2 <- '++' skip
PLUSEQUAL <- '+=' skip
PLUSPERCENT <- '+%' ![=] skip
PLUSPERCENTEQUAL <- '+%=' skip
+PTRC <- '[*c]' skip
+PTRUNKNOWN <- '[*]' skip
QUESTIONMARK <- '?' skip
RARROW <- '>' ![>=] skip
RARROW2 <- '>>' ![=] skip
diff --git a/example/mix_o_files/build.zig b/example/mix_o_files/build.zig
index a4e7fbbf8f..623ec63de9 100644
--- a/example/mix_o_files/build.zig
+++ b/example/mix_o_files/build.zig
@@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
const obj = b.addObject("base64", "base64.zig");
- const exe = b.addCExecutable("test");
- exe.addCompileFlags([][]const u8{"-std=c99"});
- exe.addSourceFile("test.c");
+ const exe = b.addExecutable("test", null);
+ exe.addCSourceFile("test.c",[][]const u8{"-std=c99"});
exe.addObject(obj);
+ exe.linkSystemLibrary("c");
b.default_step.dependOn(&exe.step);
diff --git a/example/shared_library/build.zig b/example/shared_library/build.zig
index 05648cf9eb..5eaa4f4402 100644
--- a/example/shared_library/build.zig
+++ b/example/shared_library/build.zig
@@ -3,10 +3,10 @@ const Builder = @import("std").build.Builder;
pub fn build(b: *Builder) void {
const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0));
- const exe = b.addCExecutable("test");
- exe.addCompileFlags([][]const u8{"-std=c99"});
- exe.addSourceFile("test.c");
+ const exe = b.addExecutable("test", null);
+ exe.addCSourceFile("test.c", [][]const u8{"-std=c99"});
exe.linkLibrary(lib);
+ exe.linkSystemLibrary("c");
b.default_step.dependOn(&exe.step);
diff --git a/example/shared_library/mathtest.zig b/example/shared_library/mathtest.zig
index 96e41f847c..a04ec1544d 100644
--- a/example/shared_library/mathtest.zig
+++ b/example/shared_library/mathtest.zig
@@ -1,12 +1,3 @@
-// TODO Remove this workaround
-comptime {
- const builtin = @import("builtin");
- if (builtin.os == builtin.Os.macosx) {
- @export("__mh_execute_header", _mh_execute_header, builtin.GlobalLinkage.Weak);
- }
-}
-var _mh_execute_header = extern struct {x: usize}{.x = 0};
-
export fn add(a: i32, b: i32) i32 {
return a + b;
}
diff --git a/src-self-hosted/codegen.zig b/src-self-hosted/codegen.zig
index 45cfa98942..1c671b61e2 100644
--- a/src-self-hosted/codegen.zig
+++ b/src-self-hosted/codegen.zig
@@ -137,10 +137,10 @@ pub async fn renderToLlvm(comp: *Compilation, fn_val: *Value.Fn, code: *ir.Code)
pub const ObjectFile = struct {
comp: *Compilation,
- module: llvm.ModuleRef,
- builder: llvm.BuilderRef,
+ module: *llvm.Module,
+ builder: *llvm.Builder,
dibuilder: *llvm.DIBuilder,
- context: llvm.ContextRef,
+ context: *llvm.Context,
lock: event.Lock,
arena: *std.mem.Allocator,
@@ -323,7 +323,7 @@ pub fn renderToLlvmModule(ofile: *ObjectFile, fn_val: *Value.Fn, code: *ir.Code)
fn addLLVMAttr(
ofile: *ObjectFile,
- val: llvm.ValueRef,
+ val: *llvm.Value,
attr_index: llvm.AttributeIndex,
attr_name: []const u8,
) !void {
@@ -335,7 +335,7 @@ fn addLLVMAttr(
fn addLLVMAttrStr(
ofile: *ObjectFile,
- val: llvm.ValueRef,
+ val: *llvm.Value,
attr_index: llvm.AttributeIndex,
attr_name: []const u8,
attr_val: []const u8,
@@ -351,7 +351,7 @@ fn addLLVMAttrStr(
}
fn addLLVMAttrInt(
- val: llvm.ValueRef,
+ val: *llvm.Value,
attr_index: llvm.AttributeIndex,
attr_name: []const u8,
attr_val: u64,
@@ -362,25 +362,25 @@ fn addLLVMAttrInt(
llvm.AddAttributeAtIndex(val, attr_index, llvm_attr);
}
-fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8) !void {
+fn addLLVMFnAttr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8) !void {
return addLLVMAttr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name);
}
-fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: []const u8) !void {
+fn addLLVMFnAttrStr(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: []const u8) !void {
return addLLVMAttrStr(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
}
-fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: llvm.ValueRef, attr_name: []const u8, attr_val: u64) !void {
+fn addLLVMFnAttrInt(ofile: *ObjectFile, fn_val: *llvm.Value, attr_name: []const u8, attr_val: u64) !void {
return addLLVMAttrInt(ofile, fn_val, maxInt(llvm.AttributeIndex), attr_name, attr_val);
}
fn renderLoadUntyped(
ofile: *ObjectFile,
- ptr: llvm.ValueRef,
+ ptr: *llvm.Value,
alignment: Type.Pointer.Align,
vol: Type.Pointer.Vol,
name: [*]const u8,
-) !llvm.ValueRef {
+) !*llvm.Value {
const result = llvm.BuildLoad(ofile.builder, ptr, name) orelse return error.OutOfMemory;
switch (vol) {
Type.Pointer.Vol.Non => {},
@@ -390,11 +390,11 @@ fn renderLoadUntyped(
return result;
}
-fn renderLoad(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer, name: [*]const u8) !llvm.ValueRef {
+fn renderLoad(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer, name: [*]const u8) !*llvm.Value {
return renderLoadUntyped(ofile, ptr, ptr_type.key.alignment, ptr_type.key.vol, name);
}
-pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Pointer) !?llvm.ValueRef {
+pub fn getHandleValue(ofile: *ObjectFile, ptr: *llvm.Value, ptr_type: *Type.Pointer) !?*llvm.Value {
const child_type = ptr_type.key.child_type;
if (!child_type.hasBits()) {
return null;
@@ -407,11 +407,11 @@ pub fn getHandleValue(ofile: *ObjectFile, ptr: llvm.ValueRef, ptr_type: *Type.Po
pub fn renderStoreUntyped(
ofile: *ObjectFile,
- value: llvm.ValueRef,
- ptr: llvm.ValueRef,
+ value: *llvm.Value,
+ ptr: *llvm.Value,
alignment: Type.Pointer.Align,
vol: Type.Pointer.Vol,
-) !llvm.ValueRef {
+) !*llvm.Value {
const result = llvm.BuildStore(ofile.builder, value, ptr) orelse return error.OutOfMemory;
switch (vol) {
Type.Pointer.Vol.Non => {},
@@ -423,10 +423,10 @@ pub fn renderStoreUntyped(
pub fn renderStore(
ofile: *ObjectFile,
- value: llvm.ValueRef,
- ptr: llvm.ValueRef,
+ value: *llvm.Value,
+ ptr: *llvm.Value,
ptr_type: *Type.Pointer,
-) !llvm.ValueRef {
+) !*llvm.Value {
return renderStoreUntyped(ofile, value, ptr, ptr_type.key.alignment, ptr_type.key.vol);
}
@@ -435,7 +435,7 @@ pub fn renderAlloca(
var_type: *Type,
name: []const u8,
alignment: Type.Pointer.Align,
-) !llvm.ValueRef {
+) !*llvm.Value {
const llvm_var_type = try var_type.getLlvmType(ofile.arena, ofile.context);
const name_with_null = try std.cstr.addNullByte(ofile.arena, name);
const result = llvm.BuildAlloca(ofile.builder, llvm_var_type, name_with_null.ptr) orelse return error.OutOfMemory;
@@ -443,7 +443,7 @@ pub fn renderAlloca(
return result;
}
-pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: llvm.TypeRef) u32 {
+pub fn resolveAlign(ofile: *ObjectFile, alignment: Type.Pointer.Align, llvm_type: *llvm.Type) u32 {
return switch (alignment) {
Type.Pointer.Align.Abi => return llvm.ABIAlignmentOfType(ofile.comp.target_data_ref, llvm_type),
Type.Pointer.Align.Override => |a| a,
diff --git a/src-self-hosted/compilation.zig b/src-self-hosted/compilation.zig
index e55d8ccda6..de956f1525 100644
--- a/src-self-hosted/compilation.zig
+++ b/src-self-hosted/compilation.zig
@@ -37,7 +37,7 @@ const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
/// Data that is local to the event loop.
pub const ZigCompiler = struct {
loop: *event.Loop,
- llvm_handle_pool: std.atomic.Stack(llvm.ContextRef),
+ llvm_handle_pool: std.atomic.Stack(*llvm.Context),
lld_lock: event.Lock,
/// TODO pool these so that it doesn't have to lock
@@ -60,7 +60,7 @@ pub const ZigCompiler = struct {
return ZigCompiler{
.loop = loop,
.lld_lock = event.Lock.init(loop),
- .llvm_handle_pool = std.atomic.Stack(llvm.ContextRef).init(),
+ .llvm_handle_pool = std.atomic.Stack(*llvm.Context).init(),
.prng = event.Locked(std.rand.DefaultPrng).init(loop, std.rand.DefaultPrng.init(seed)),
.native_libc = event.Future(LibCInstallation).init(loop),
};
@@ -70,7 +70,7 @@ pub const ZigCompiler = struct {
fn deinit(self: *ZigCompiler) void {
self.lld_lock.deinit();
while (self.llvm_handle_pool.pop()) |node| {
- c.LLVMContextDispose(node.data);
+ llvm.ContextDispose(node.data);
self.loop.allocator.destroy(node);
}
}
@@ -80,11 +80,11 @@ pub const ZigCompiler = struct {
pub fn getAnyLlvmContext(self: *ZigCompiler) !LlvmHandle {
if (self.llvm_handle_pool.pop()) |node| return LlvmHandle{ .node = node };
- const context_ref = c.LLVMContextCreate() orelse return error.OutOfMemory;
- errdefer c.LLVMContextDispose(context_ref);
+ const context_ref = llvm.ContextCreate() orelse return error.OutOfMemory;
+ errdefer llvm.ContextDispose(context_ref);
- const node = try self.loop.allocator.create(std.atomic.Stack(llvm.ContextRef).Node);
- node.* = std.atomic.Stack(llvm.ContextRef).Node{
+ const node = try self.loop.allocator.create(std.atomic.Stack(*llvm.Context).Node);
+ node.* = std.atomic.Stack(*llvm.Context).Node{
.next = undefined,
.data = context_ref,
};
@@ -114,7 +114,7 @@ pub const ZigCompiler = struct {
};
pub const LlvmHandle = struct {
- node: *std.atomic.Stack(llvm.ContextRef).Node,
+ node: *std.atomic.Stack(*llvm.Context).Node,
pub fn release(self: LlvmHandle, zig_compiler: *ZigCompiler) void {
zig_compiler.llvm_handle_pool.push(self.node);
@@ -128,7 +128,7 @@ pub const Compilation = struct {
llvm_triple: Buffer,
root_src_path: ?[]const u8,
target: Target,
- llvm_target: llvm.TargetRef,
+ llvm_target: *llvm.Target,
build_mode: builtin.Mode,
zig_lib_dir: []const u8,
zig_std_dir: []const u8,
@@ -212,8 +212,8 @@ pub const Compilation = struct {
false_value: *Value.Bool,
noreturn_value: *Value.NoReturn,
- target_machine: llvm.TargetMachineRef,
- target_data_ref: llvm.TargetDataRef,
+ target_machine: *llvm.TargetMachine,
+ target_data_ref: *llvm.TargetData,
target_layout_str: [*]u8,
target_ptr_bits: u32,
diff --git a/src-self-hosted/ir.zig b/src-self-hosted/ir.zig
index 0362bb4ef8..dc1b0dc943 100644
--- a/src-self-hosted/ir.zig
+++ b/src-self-hosted/ir.zig
@@ -67,7 +67,7 @@ pub const Inst = struct {
parent: ?*Inst,
/// populated durign codegen
- llvm_value: ?llvm.ValueRef,
+ llvm_value: ?*llvm.Value,
pub fn cast(base: *Inst, comptime T: type) ?*T {
if (base.id == comptime typeToId(T)) {
@@ -129,7 +129,7 @@ pub const Inst = struct {
}
}
- pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?llvm.ValueRef) {
+ pub fn render(base: *Inst, ofile: *ObjectFile, fn_val: *Value.Fn) (error{OutOfMemory}!?*llvm.Value) {
switch (base.id) {
Id.Return => return @fieldParentPtr(Return, "base", base).render(ofile, fn_val),
Id.Const => return @fieldParentPtr(Const, "base", base).render(ofile, fn_val),
@@ -313,10 +313,10 @@ pub const Inst = struct {
return new_inst;
}
- pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
+ pub fn render(self: *Call, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
const fn_ref = self.params.fn_ref.llvm_value.?;
- const args = try ofile.arena.alloc(llvm.ValueRef, self.params.args.len);
+ const args = try ofile.arena.alloc(*llvm.Value, self.params.args.len);
for (self.params.args) |arg, i| {
args[i] = arg.llvm_value.?;
}
@@ -360,7 +360,7 @@ pub const Inst = struct {
return new_inst;
}
- pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
+ pub fn render(self: *Const, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
return self.base.val.KnownValue.getLlvmConst(ofile);
}
};
@@ -392,7 +392,7 @@ pub const Inst = struct {
return ira.irb.build(Return, self.base.scope, self.base.span, Params{ .return_value = casted_value });
}
- pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
+ pub fn render(self: *Return, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
const value = self.params.return_value.llvm_value;
const return_type = self.params.return_value.getKnownType();
@@ -540,7 +540,7 @@ pub const Inst = struct {
}
}
- pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) llvm.ValueRef {
+ pub fn render(self: *VarPtr, ofile: *ObjectFile, fn_val: *Value.Fn) *llvm.Value {
switch (self.params.var_scope.data) {
Scope.Var.Data.Const => unreachable, // turned into Inst.Const in analyze pass
Scope.Var.Data.Param => |param| return param.llvm_value,
@@ -596,7 +596,7 @@ pub const Inst = struct {
return new_inst;
}
- pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?llvm.ValueRef {
+ pub fn render(self: *LoadPtr, ofile: *ObjectFile, fn_val: *Value.Fn) !?*llvm.Value {
const child_type = self.base.getKnownType();
if (!child_type.hasBits()) {
return null;
@@ -935,8 +935,8 @@ pub const BasicBlock = struct {
ref_instruction: ?*Inst,
/// for codegen
- llvm_block: llvm.BasicBlockRef,
- llvm_exit_block: llvm.BasicBlockRef,
+ llvm_block: *llvm.BasicBlock,
+ llvm_exit_block: *llvm.BasicBlock,
/// the basic block that is derived from this one in analysis
child: ?*BasicBlock,
diff --git a/src-self-hosted/libc_installation.zig b/src-self-hosted/libc_installation.zig
index edcb9dc579..6a530da1f0 100644
--- a/src-self-hosted/libc_installation.zig
+++ b/src-self-hosted/libc_installation.zig
@@ -154,8 +154,8 @@ pub const LibCInstallation = struct {
c.ZigFindWindowsSdkError.None => {
windows_sdk = sdk;
- if (sdk.msvc_lib_dir_ptr) |ptr| {
- self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, ptr[0..sdk.msvc_lib_dir_len]);
+ if (sdk.msvc_lib_dir_ptr != 0) {
+ self.msvc_lib_dir = try std.mem.dupe(loop.allocator, u8, sdk.msvc_lib_dir_ptr[0..sdk.msvc_lib_dir_len]);
}
try group.call(findNativeKernel32LibDir, self, loop, sdk);
try group.call(findNativeIncludeDirWindows, self, loop, sdk);
@@ -172,7 +172,7 @@ pub const LibCInstallation = struct {
try group.call(findNativeStaticLibDir, self, loop);
try group.call(findNativeDynamicLinker, self, loop);
},
- builtin.Os.macosx, builtin.Os.freebsd => {
+ builtin.Os.macosx, builtin.Os.freebsd, builtin.Os.netbsd => {
self.include_dir = try std.mem.dupe(loop.allocator, u8, "/usr/include");
},
else => @compileError("unimplemented: find libc for this OS"),
@@ -283,7 +283,7 @@ pub const LibCInstallation = struct {
switch (builtin.arch) {
builtin.Arch.i386 => try stream.write("x86"),
builtin.Arch.x86_64 => try stream.write("x64"),
- builtin.Arch.aarch64v8 => try stream.write("arm"),
+ builtin.Arch.aarch64 => try stream.write("arm"),
else => return error.UnsupportedArchitecture,
}
const ucrt_lib_path = try std.os.path.join(
@@ -361,7 +361,7 @@ pub const LibCInstallation = struct {
switch (builtin.arch) {
builtin.Arch.i386 => try stream.write("x86\\"),
builtin.Arch.x86_64 => try stream.write("x64\\"),
- builtin.Arch.aarch64v8 => try stream.write("arm\\"),
+ builtin.Arch.aarch64 => try stream.write("arm\\"),
else => return error.UnsupportedArchitecture,
}
const kernel32_path = try std.os.path.join(
@@ -437,20 +437,20 @@ const Search = struct {
fn fillSearch(search_buf: *[2]Search, sdk: *c.ZigWindowsSDK) []Search {
var search_end: usize = 0;
- if (sdk.path10_ptr) |path10_ptr| {
- if (sdk.version10_ptr) |ver10_ptr| {
+ if (sdk.path10_ptr != 0) {
+ if (sdk.version10_ptr != 0) {
search_buf[search_end] = Search{
- .path = path10_ptr[0..sdk.path10_len],
- .version = ver10_ptr[0..sdk.version10_len],
+ .path = sdk.path10_ptr[0..sdk.path10_len],
+ .version = sdk.version10_ptr[0..sdk.version10_len],
};
search_end += 1;
}
}
- if (sdk.path81_ptr) |path81_ptr| {
- if (sdk.version81_ptr) |ver81_ptr| {
+ if (sdk.path81_ptr != 0) {
+ if (sdk.version81_ptr != 0) {
search_buf[search_end] = Search{
- .path = path81_ptr[0..sdk.path81_len],
- .version = ver81_ptr[0..sdk.version81_len],
+ .path = sdk.path81_ptr[0..sdk.path81_len],
+ .version = sdk.version81_ptr[0..sdk.version81_len],
};
search_end += 1;
}
diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig
index fadc9b0189..5689ee7925 100644
--- a/src-self-hosted/link.zig
+++ b/src-self-hosted/link.zig
@@ -145,10 +145,6 @@ fn constructLinkerArgsElf(ctx: *Context) !void {
// lj->args.append("-T");
// lj->args.append(g->linker_script);
//}
-
- //if (g->no_rosegment_workaround) {
- // lj->args.append("--no-rosegment");
- //}
try ctx.args.append(c"--gc-sections");
//lj->args.append("-m");
@@ -330,7 +326,7 @@ fn constructLinkerArgsCoff(ctx: *Context) !void {
switch (ctx.comp.target.getArch()) {
builtin.Arch.i386 => try ctx.args.append(c"-MACHINE:X86"),
builtin.Arch.x86_64 => try ctx.args.append(c"-MACHINE:X64"),
- builtin.Arch.aarch64v8 => try ctx.args.append(c"-MACHINE:ARM"),
+ builtin.Arch.aarch64 => try ctx.args.append(c"-MACHINE:ARM"),
else => return error.UnsupportedLinkArchitecture,
}
@@ -556,7 +552,7 @@ fn constructLinkerArgsMachO(ctx: *Context) !void {
}
},
DarwinPlatform.Kind.IPhoneOS => {
- if (ctx.comp.target.getArch() == builtin.Arch.aarch64v8) {
+ if (ctx.comp.target.getArch() == builtin.Arch.aarch64) {
// iOS does not need any crt1 files for arm64
} else if (platform.versionLessThan(3, 1)) {
try ctx.args.append(c"-lcrt1.o");
diff --git a/src-self-hosted/llvm.zig b/src-self-hosted/llvm.zig
index 778d3fae07..5cb95682ab 100644
--- a/src-self-hosted/llvm.zig
+++ b/src-self-hosted/llvm.zig
@@ -11,45 +11,31 @@ const assert = @import("std").debug.assert;
pub const AttributeIndex = c_uint;
pub const Bool = c_int;
-pub const BuilderRef = removeNullability(c.LLVMBuilderRef);
-pub const ContextRef = removeNullability(c.LLVMContextRef);
-pub const ModuleRef = removeNullability(c.LLVMModuleRef);
-pub const ValueRef = removeNullability(c.LLVMValueRef);
-pub const TypeRef = removeNullability(c.LLVMTypeRef);
-pub const BasicBlockRef = removeNullability(c.LLVMBasicBlockRef);
-pub const AttributeRef = removeNullability(c.LLVMAttributeRef);
-pub const TargetRef = removeNullability(c.LLVMTargetRef);
-pub const TargetMachineRef = removeNullability(c.LLVMTargetMachineRef);
-pub const TargetDataRef = removeNullability(c.LLVMTargetDataRef);
+pub const Builder = c.LLVMBuilderRef.Child.Child;
+pub const Context = c.LLVMContextRef.Child.Child;
+pub const Module = c.LLVMModuleRef.Child.Child;
+pub const Value = c.LLVMValueRef.Child.Child;
+pub const Type = c.LLVMTypeRef.Child.Child;
+pub const BasicBlock = c.LLVMBasicBlockRef.Child.Child;
+pub const Attribute = c.LLVMAttributeRef.Child.Child;
+pub const Target = c.LLVMTargetRef.Child.Child;
+pub const TargetMachine = c.LLVMTargetMachineRef.Child.Child;
+pub const TargetData = c.LLVMTargetDataRef.Child.Child;
pub const DIBuilder = c.ZigLLVMDIBuilder;
+pub const DIFile = c.ZigLLVMDIFile;
+pub const DICompileUnit = c.ZigLLVMDICompileUnit;
pub const ABIAlignmentOfType = c.LLVMABIAlignmentOfType;
pub const AddAttributeAtIndex = c.LLVMAddAttributeAtIndex;
-pub const AddFunction = c.LLVMAddFunction;
-pub const AddGlobal = c.LLVMAddGlobal;
pub const AddModuleCodeViewFlag = c.ZigLLVMAddModuleCodeViewFlag;
pub const AddModuleDebugInfoFlag = c.ZigLLVMAddModuleDebugInfoFlag;
-pub const ArrayType = c.LLVMArrayType;
-pub const BuildLoad = c.LLVMBuildLoad;
pub const ClearCurrentDebugLocation = c.ZigLLVMClearCurrentDebugLocation;
pub const ConstAllOnes = c.LLVMConstAllOnes;
pub const ConstArray = c.LLVMConstArray;
pub const ConstBitCast = c.LLVMConstBitCast;
-pub const ConstInt = c.LLVMConstInt;
pub const ConstIntOfArbitraryPrecision = c.LLVMConstIntOfArbitraryPrecision;
pub const ConstNeg = c.LLVMConstNeg;
-pub const ConstNull = c.LLVMConstNull;
-pub const ConstStringInContext = c.LLVMConstStringInContext;
pub const ConstStructInContext = c.LLVMConstStructInContext;
-pub const CopyStringRepOfTargetData = c.LLVMCopyStringRepOfTargetData;
-pub const CreateBuilderInContext = c.LLVMCreateBuilderInContext;
-pub const CreateCompileUnit = c.ZigLLVMCreateCompileUnit;
-pub const CreateDIBuilder = c.ZigLLVMCreateDIBuilder;
-pub const CreateEnumAttribute = c.LLVMCreateEnumAttribute;
-pub const CreateFile = c.ZigLLVMCreateFile;
-pub const CreateStringAttribute = c.LLVMCreateStringAttribute;
-pub const CreateTargetDataLayout = c.LLVMCreateTargetDataLayout;
-pub const CreateTargetMachine = c.LLVMCreateTargetMachine;
pub const DIBuilderFinalize = c.ZigLLVMDIBuilderFinalize;
pub const DisposeBuilder = c.LLVMDisposeBuilder;
pub const DisposeDIBuilder = c.ZigLLVMDisposeDIBuilder;
@@ -62,9 +48,7 @@ pub const DumpModule = c.LLVMDumpModule;
pub const FP128TypeInContext = c.LLVMFP128TypeInContext;
pub const FloatTypeInContext = c.LLVMFloatTypeInContext;
pub const GetEnumAttributeKindForName = c.LLVMGetEnumAttributeKindForName;
-pub const GetHostCPUName = c.ZigLLVMGetHostCPUName;
pub const GetMDKindIDInContext = c.LLVMGetMDKindIDInContext;
-pub const GetNativeFeatures = c.ZigLLVMGetNativeFeatures;
pub const GetUndef = c.LLVMGetUndef;
pub const HalfTypeInContext = c.LLVMHalfTypeInContext;
pub const InitializeAllAsmParsers = c.LLVMInitializeAllAsmParsers;
@@ -81,14 +65,11 @@ pub const Int64TypeInContext = c.LLVMInt64TypeInContext;
pub const Int8TypeInContext = c.LLVMInt8TypeInContext;
pub const IntPtrTypeForASInContext = c.LLVMIntPtrTypeForASInContext;
pub const IntPtrTypeInContext = c.LLVMIntPtrTypeInContext;
-pub const IntTypeInContext = c.LLVMIntTypeInContext;
pub const LabelTypeInContext = c.LLVMLabelTypeInContext;
pub const MDNodeInContext = c.LLVMMDNodeInContext;
pub const MDStringInContext = c.LLVMMDStringInContext;
pub const MetadataTypeInContext = c.LLVMMetadataTypeInContext;
-pub const ModuleCreateWithNameInContext = c.LLVMModuleCreateWithNameInContext;
pub const PPCFP128TypeInContext = c.LLVMPPCFP128TypeInContext;
-pub const PointerType = c.LLVMPointerType;
pub const SetAlignment = c.LLVMSetAlignment;
pub const SetDataLayout = c.LLVMSetDataLayout;
pub const SetGlobalConstant = c.LLVMSetGlobalConstant;
@@ -99,50 +80,146 @@ pub const SetUnnamedAddr = c.LLVMSetUnnamedAddr;
pub const SetVolatile = c.LLVMSetVolatile;
pub const StructTypeInContext = c.LLVMStructTypeInContext;
pub const TokenTypeInContext = c.LLVMTokenTypeInContext;
-pub const VoidTypeInContext = c.LLVMVoidTypeInContext;
pub const X86FP80TypeInContext = c.LLVMX86FP80TypeInContext;
pub const X86MMXTypeInContext = c.LLVMX86MMXTypeInContext;
+pub const AddGlobal = LLVMAddGlobal;
+extern fn LLVMAddGlobal(M: *Module, Ty: *Type, Name: [*]const u8) ?*Value;
+
+pub const ConstStringInContext = LLVMConstStringInContext;
+extern fn LLVMConstStringInContext(C: *Context, Str: [*]const u8, Length: c_uint, DontNullTerminate: Bool) ?*Value;
+
+pub const ConstInt = LLVMConstInt;
+extern fn LLVMConstInt(IntTy: *Type, N: c_ulonglong, SignExtend: Bool) ?*Value;
+
+pub const BuildLoad = LLVMBuildLoad;
+extern fn LLVMBuildLoad(arg0: *Builder, PointerVal: *Value, Name: [*]const u8) ?*Value;
+
+pub const ConstNull = LLVMConstNull;
+extern fn LLVMConstNull(Ty: *Type) ?*Value;
+
+pub const CreateStringAttribute = LLVMCreateStringAttribute;
+extern fn LLVMCreateStringAttribute(
+ C: *Context,
+ K: [*]const u8,
+ KLength: c_uint,
+ V: [*]const u8,
+ VLength: c_uint,
+) ?*Attribute;
+
+pub const CreateEnumAttribute = LLVMCreateEnumAttribute;
+extern fn LLVMCreateEnumAttribute(C: *Context, KindID: c_uint, Val: u64) ?*Attribute;
+
+pub const AddFunction = LLVMAddFunction;
+extern fn LLVMAddFunction(M: *Module, Name: [*]const u8, FunctionTy: *Type) ?*Value;
+
+pub const CreateCompileUnit = ZigLLVMCreateCompileUnit;
+extern fn ZigLLVMCreateCompileUnit(
+ dibuilder: *DIBuilder,
+ lang: c_uint,
+ difile: *DIFile,
+ producer: [*]const u8,
+ is_optimized: bool,
+ flags: [*]const u8,
+ runtime_version: c_uint,
+ split_name: [*]const u8,
+ dwo_id: u64,
+ emit_debug_info: bool,
+) ?*DICompileUnit;
+
+pub const CreateFile = ZigLLVMCreateFile;
+extern fn ZigLLVMCreateFile(dibuilder: *DIBuilder, filename: [*]const u8, directory: [*]const u8) ?*DIFile;
+
+pub const ArrayType = LLVMArrayType;
+extern fn LLVMArrayType(ElementType: *Type, ElementCount: c_uint) ?*Type;
+
+pub const CreateDIBuilder = ZigLLVMCreateDIBuilder;
+extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) ?*DIBuilder;
+
+pub const PointerType = LLVMPointerType;
+extern fn LLVMPointerType(ElementType: *Type, AddressSpace: c_uint) ?*Type;
+
+pub const CreateBuilderInContext = LLVMCreateBuilderInContext;
+extern fn LLVMCreateBuilderInContext(C: *Context) ?*Builder;
+
+pub const IntTypeInContext = LLVMIntTypeInContext;
+extern fn LLVMIntTypeInContext(C: *Context, NumBits: c_uint) ?*Type;
+
+pub const ModuleCreateWithNameInContext = LLVMModuleCreateWithNameInContext;
+extern fn LLVMModuleCreateWithNameInContext(ModuleID: [*]const u8, C: *Context) ?*Module;
+
+pub const VoidTypeInContext = LLVMVoidTypeInContext;
+extern fn LLVMVoidTypeInContext(C: *Context) ?*Type;
+
+pub const ContextCreate = LLVMContextCreate;
+extern fn LLVMContextCreate() ?*Context;
+
+pub const ContextDispose = LLVMContextDispose;
+extern fn LLVMContextDispose(C: *Context) void;
+
+pub const CopyStringRepOfTargetData = LLVMCopyStringRepOfTargetData;
+extern fn LLVMCopyStringRepOfTargetData(TD: *TargetData) ?[*]u8;
+
+pub const CreateTargetDataLayout = LLVMCreateTargetDataLayout;
+extern fn LLVMCreateTargetDataLayout(T: *TargetMachine) ?*TargetData;
+
+pub const CreateTargetMachine = LLVMCreateTargetMachine;
+extern fn LLVMCreateTargetMachine(
+ T: *Target,
+ Triple: [*]const u8,
+ CPU: [*]const u8,
+ Features: [*]const u8,
+ Level: CodeGenOptLevel,
+ Reloc: RelocMode,
+ CodeModel: CodeModel,
+) ?*TargetMachine;
+
+pub const GetHostCPUName = LLVMGetHostCPUName;
+extern fn LLVMGetHostCPUName() ?[*]u8;
+
+pub const GetNativeFeatures = ZigLLVMGetNativeFeatures;
+extern fn ZigLLVMGetNativeFeatures() ?[*]u8;
+
pub const GetElementType = LLVMGetElementType;
-extern fn LLVMGetElementType(Ty: TypeRef) TypeRef;
+extern fn LLVMGetElementType(Ty: *Type) *Type;
pub const TypeOf = LLVMTypeOf;
-extern fn LLVMTypeOf(Val: ValueRef) TypeRef;
+extern fn LLVMTypeOf(Val: *Value) *Type;
pub const BuildStore = LLVMBuildStore;
-extern fn LLVMBuildStore(arg0: BuilderRef, Val: ValueRef, Ptr: ValueRef) ?ValueRef;
+extern fn LLVMBuildStore(arg0: *Builder, Val: *Value, Ptr: *Value) ?*Value;
pub const BuildAlloca = LLVMBuildAlloca;
-extern fn LLVMBuildAlloca(arg0: BuilderRef, Ty: TypeRef, Name: ?[*]const u8) ?ValueRef;
+extern fn LLVMBuildAlloca(arg0: *Builder, Ty: *Type, Name: ?[*]const u8) ?*Value;
pub const ConstInBoundsGEP = LLVMConstInBoundsGEP;
-pub extern fn LLVMConstInBoundsGEP(ConstantVal: ValueRef, ConstantIndices: [*]ValueRef, NumIndices: c_uint) ?ValueRef;
+pub extern fn LLVMConstInBoundsGEP(ConstantVal: *Value, ConstantIndices: [*]*Value, NumIndices: c_uint) ?*Value;
pub const GetTargetFromTriple = LLVMGetTargetFromTriple;
-extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: *TargetRef, ErrorMessage: ?*[*]u8) Bool;
+extern fn LLVMGetTargetFromTriple(Triple: [*]const u8, T: **Target, ErrorMessage: ?*[*]u8) Bool;
pub const VerifyModule = LLVMVerifyModule;
-extern fn LLVMVerifyModule(M: ModuleRef, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
+extern fn LLVMVerifyModule(M: *Module, Action: VerifierFailureAction, OutMessage: *?[*]u8) Bool;
pub const GetInsertBlock = LLVMGetInsertBlock;
-extern fn LLVMGetInsertBlock(Builder: BuilderRef) BasicBlockRef;
+extern fn LLVMGetInsertBlock(Builder: *Builder) *BasicBlock;
pub const FunctionType = LLVMFunctionType;
extern fn LLVMFunctionType(
- ReturnType: TypeRef,
- ParamTypes: [*]TypeRef,
+ ReturnType: *Type,
+ ParamTypes: [*]*Type,
ParamCount: c_uint,
IsVarArg: Bool,
-) ?TypeRef;
+) ?*Type;
pub const GetParam = LLVMGetParam;
-extern fn LLVMGetParam(Fn: ValueRef, Index: c_uint) ValueRef;
+extern fn LLVMGetParam(Fn: *Value, Index: c_uint) *Value;
pub const AppendBasicBlockInContext = LLVMAppendBasicBlockInContext;
-extern fn LLVMAppendBasicBlockInContext(C: ContextRef, Fn: ValueRef, Name: [*]const u8) ?BasicBlockRef;
+extern fn LLVMAppendBasicBlockInContext(C: *Context, Fn: *Value, Name: [*]const u8) ?*BasicBlock;
pub const PositionBuilderAtEnd = LLVMPositionBuilderAtEnd;
-extern fn LLVMPositionBuilderAtEnd(Builder: BuilderRef, Block: BasicBlockRef) void;
+extern fn LLVMPositionBuilderAtEnd(Builder: *Builder, Block: *BasicBlock) void;
pub const AbortProcessAction = VerifierFailureAction.LLVMAbortProcessAction;
pub const PrintMessageAction = VerifierFailureAction.LLVMPrintMessageAction;
@@ -190,17 +267,17 @@ pub const FnInline = extern enum {
};
fn removeNullability(comptime T: type) type {
- comptime assert(@typeId(T) == builtin.TypeId.Optional);
- return T.Child;
+ comptime assert(@typeInfo(T).Pointer.size == @import("builtin").TypeInfo.Pointer.Size.C);
+ return *T.Child;
}
pub const BuildRet = LLVMBuildRet;
-extern fn LLVMBuildRet(arg0: BuilderRef, V: ?ValueRef) ?ValueRef;
+extern fn LLVMBuildRet(arg0: *Builder, V: ?*Value) ?*Value;
pub const TargetMachineEmitToFile = ZigLLVMTargetMachineEmitToFile;
extern fn ZigLLVMTargetMachineEmitToFile(
- targ_machine_ref: TargetMachineRef,
- module_ref: ModuleRef,
+ targ_machine_ref: *TargetMachine,
+ module_ref: *Module,
filename: [*]const u8,
output_type: EmitOutputType,
error_message: *[*]u8,
@@ -209,6 +286,6 @@ extern fn ZigLLVMTargetMachineEmitToFile(
) bool;
pub const BuildCall = ZigLLVMBuildCall;
-extern fn ZigLLVMBuildCall(B: BuilderRef, Fn: ValueRef, Args: [*]ValueRef, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?ValueRef;
+extern fn ZigLLVMBuildCall(B: *Builder, Fn: *Value, Args: [*]*Value, NumArgs: c_uint, CC: c_uint, fn_inline: FnInline, Name: [*]const u8) ?*Value;
pub const PrivateLinkage = c.LLVMLinkage.LLVMPrivateLinkage;
diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig
index 64aa729469..4c3edf6d5d 100644
--- a/src-self-hosted/main.zig
+++ b/src-self-hosted/main.zig
@@ -24,7 +24,7 @@ var stderr_file: os.File = undefined;
var stderr: *io.OutStream(os.File.WriteError) = undefined;
var stdout: *io.OutStream(os.File.WriteError) = undefined;
-const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
+pub const max_src_size = 2 * 1024 * 1024 * 1024; // 2 GiB
const usage =
\\usage: zig [command] [options]
@@ -154,9 +154,7 @@ const usage_build_generic =
\\ release-small optimize for small binary, safety off
\\ --static Output will be statically linked
\\ --strip Exclude debug symbols
- \\ --target-arch [name] Specify target architecture
- \\ --target-environ [name] Specify target environment
- \\ --target-os [name] Specify target operating system
+ \\ -target [name] -- see the targets command
\\ --verbose-tokenize Turn on compiler debug output for tokenization
\\ --verbose-ast-tree Turn on compiler debug output for parsing into an AST (tree view)
\\ --verbose-ast-fmt Turn on compiler debug output for parsing into an AST (render source)
@@ -220,9 +218,7 @@ const args_build_generic = []Flag{
Flag.Bool("--pkg-end"),
Flag.Bool("--static"),
Flag.Bool("--strip"),
- Flag.Arg1("--target-arch"),
- Flag.Arg1("--target-environ"),
- Flag.Arg1("--target-os"),
+ Flag.Arg1("-target"),
Flag.Bool("--verbose-tokenize"),
Flag.Bool("--verbose-ast-tree"),
Flag.Bool("--verbose-ast-fmt"),
@@ -510,7 +506,7 @@ fn cmdBuildObj(allocator: *Allocator, args: []const []const u8) !void {
return buildOutputType(allocator, args, Compilation.Kind.Obj);
}
-const usage_fmt =
+pub const usage_fmt =
\\usage: zig fmt [file]...
\\
\\ Formats the input files and modifies them in-place.
@@ -527,7 +523,7 @@ const usage_fmt =
\\
;
-const args_fmt_spec = []Flag{
+pub const args_fmt_spec = []Flag{
Flag.Bool("--help"),
Flag.Bool("--check"),
Flag.Option("--color", []const []const u8{
@@ -839,15 +835,15 @@ fn cmdTargets(allocator: *Allocator, args: []const []const u8) !void {
}
try stdout.write("\n");
- try stdout.write("Environments:\n");
+ try stdout.write("C ABIs:\n");
{
comptime var i: usize = 0;
- inline while (i < @memberCount(builtin.Environ)) : (i += 1) {
- comptime const environ_tag = @memberName(builtin.Environ, i);
+ inline while (i < @memberCount(builtin.Abi)) : (i += 1) {
+ comptime const abi_tag = @memberName(builtin.Abi, i);
// NOTE: Cannot use empty string, see #918.
- comptime const native_str = if (comptime mem.eql(u8, environ_tag, @tagName(builtin.environ))) " (native)\n" else "\n";
+ comptime const native_str = if (comptime mem.eql(u8, abi_tag, @tagName(builtin.abi))) " (native)\n" else "\n";
- try stdout.print(" {}{}", environ_tag, native_str);
+ try stdout.print(" {}{}", abi_tag, native_str);
}
}
}
diff --git a/src-self-hosted/scope.zig b/src-self-hosted/scope.zig
index b14c073a9e..9a84ad256e 100644
--- a/src-self-hosted/scope.zig
+++ b/src-self-hosted/scope.zig
@@ -362,7 +362,7 @@ pub const Scope = struct {
pub const Param = struct {
index: usize,
typ: *Type,
- llvm_value: llvm.ValueRef,
+ llvm_value: *llvm.Value,
};
pub fn createParam(
diff --git a/src-self-hosted/target.zig b/src-self-hosted/target.zig
index ed6c2b0710..05cf092c9e 100644
--- a/src-self-hosted/target.zig
+++ b/src-self-hosted/target.zig
@@ -16,7 +16,7 @@ pub const Target = union(enum) {
pub const Cross = struct {
arch: builtin.Arch,
os: builtin.Os,
- environ: builtin.Environ,
+ abi: builtin.Abi,
object_format: builtin.ObjectFormat,
};
@@ -49,16 +49,16 @@ pub const Target = union(enum) {
}
pub fn getArch(self: Target) builtin.Arch {
- return switch (self) {
- Target.Native => builtin.arch,
- @TagType(Target).Cross => |t| t.arch,
- };
+ switch (self) {
+ Target.Native => return builtin.arch,
+ @TagType(Target).Cross => |t| return t.arch,
+ }
}
- pub fn getEnviron(self: Target) builtin.Environ {
+ pub fn getAbi(self: Target) builtin.Abi {
return switch (self) {
- Target.Native => builtin.environ,
- @TagType(Target).Cross => |t| t.environ,
+ Target.Native => builtin.abi,
+ @TagType(Target).Cross => |t| t.abi,
};
}
@@ -93,50 +93,10 @@ pub const Target = union(enum) {
/// TODO expose the arch and subarch separately
pub fn isArmOrThumb(self: Target) bool {
return switch (self.getArch()) {
- builtin.Arch.armv8_5a,
- builtin.Arch.armv8_4a,
- builtin.Arch.armv8_3a,
- builtin.Arch.armv8_2a,
- builtin.Arch.armv8_1a,
- builtin.Arch.armv8,
- builtin.Arch.armv8r,
- builtin.Arch.armv8m_baseline,
- builtin.Arch.armv8m_mainline,
- builtin.Arch.armv7,
- builtin.Arch.armv7em,
- builtin.Arch.armv7m,
- builtin.Arch.armv7s,
- builtin.Arch.armv7k,
- builtin.Arch.armv7ve,
- builtin.Arch.armv6,
- builtin.Arch.armv6m,
- builtin.Arch.armv6k,
- builtin.Arch.armv6t2,
- builtin.Arch.armv5,
- builtin.Arch.armv5te,
- builtin.Arch.armv4t,
- builtin.Arch.armebv8_5a,
- builtin.Arch.armebv8_4a,
- builtin.Arch.armebv8_3a,
- builtin.Arch.armebv8_2a,
- builtin.Arch.armebv8_1a,
- builtin.Arch.armebv8,
- builtin.Arch.armebv8r,
- builtin.Arch.armebv8m_baseline,
- builtin.Arch.armebv8m_mainline,
- builtin.Arch.armebv7,
- builtin.Arch.armebv7em,
- builtin.Arch.armebv7m,
- builtin.Arch.armebv7s,
- builtin.Arch.armebv7k,
- builtin.Arch.armebv7ve,
- builtin.Arch.armebv6,
- builtin.Arch.armebv6m,
- builtin.Arch.armebv6k,
- builtin.Arch.armebv6t2,
- builtin.Arch.armebv5,
- builtin.Arch.armebv5te,
- builtin.Arch.armebv4t,
+ builtin.Arch.arm,
+ builtin.Arch.armeb,
+ builtin.Arch.aarch64,
+ builtin.Arch.aarch64_be,
builtin.Arch.thumb,
builtin.Arch.thumbeb,
=> true,
@@ -159,14 +119,14 @@ pub const Target = union(enum) {
// LLVM WebAssembly output support requires the target to be activated at
// build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.
//
- // LLVM determines the output format based on the environment suffix,
+ // LLVM determines the output format based on the abi suffix,
// defaulting to an object based on the architecture. The default format in
// LLVM 6 sets the wasm arch output incorrectly to ELF. We need to
// explicitly set this ourself in order for it to work.
//
// This is fixed in LLVM 7 and you will be able to get wasm output by
// using the target triple `wasm32-unknown-unknown-unknown`.
- const env_name = if (self.isWasm()) "wasm" else @tagName(self.getEnviron());
+ const env_name = if (self.isWasm()) "wasm" else @tagName(self.getAbi());
var out = &std.io.BufferOutStream.init(&result).stream;
try out.print("{}-unknown-{}-{}", @tagName(self.getArch()), @tagName(self.getOs()), env_name);
@@ -185,50 +145,8 @@ pub const Target = union(enum) {
=> return 16,
builtin.Arch.arc,
- builtin.Arch.armv8_5a,
- builtin.Arch.armv8_4a,
- builtin.Arch.armv8_3a,
- builtin.Arch.armv8_2a,
- builtin.Arch.armv8_1a,
- builtin.Arch.armv8,
- builtin.Arch.armv8r,
- builtin.Arch.armv8m_baseline,
- builtin.Arch.armv8m_mainline,
- builtin.Arch.armv7,
- builtin.Arch.armv7em,
- builtin.Arch.armv7m,
- builtin.Arch.armv7s,
- builtin.Arch.armv7k,
- builtin.Arch.armv7ve,
- builtin.Arch.armv6,
- builtin.Arch.armv6m,
- builtin.Arch.armv6k,
- builtin.Arch.armv6t2,
- builtin.Arch.armv5,
- builtin.Arch.armv5te,
- builtin.Arch.armv4t,
- builtin.Arch.armebv8_5a,
- builtin.Arch.armebv8_4a,
- builtin.Arch.armebv8_3a,
- builtin.Arch.armebv8_2a,
- builtin.Arch.armebv8_1a,
- builtin.Arch.armebv8,
- builtin.Arch.armebv8r,
- builtin.Arch.armebv8m_baseline,
- builtin.Arch.armebv8m_mainline,
- builtin.Arch.armebv7,
- builtin.Arch.armebv7em,
- builtin.Arch.armebv7m,
- builtin.Arch.armebv7s,
- builtin.Arch.armebv7k,
- builtin.Arch.armebv7ve,
- builtin.Arch.armebv6,
- builtin.Arch.armebv6m,
- builtin.Arch.armebv6k,
- builtin.Arch.armebv6t2,
- builtin.Arch.armebv5,
- builtin.Arch.armebv5te,
- builtin.Arch.armebv4t,
+ builtin.Arch.arm,
+ builtin.Arch.armeb,
builtin.Arch.hexagon,
builtin.Arch.le32,
builtin.Arch.mipsr6,
@@ -248,35 +166,17 @@ pub const Target = union(enum) {
builtin.Arch.amdil,
builtin.Arch.hsail,
builtin.Arch.spir,
- builtin.Arch.kalimbav3,
- builtin.Arch.kalimbav4,
- builtin.Arch.kalimbav5,
+ builtin.Arch.kalimba,
builtin.Arch.shave,
builtin.Arch.lanai,
builtin.Arch.wasm32,
builtin.Arch.renderscript32,
=> return 32,
- builtin.Arch.aarch64v8_5a,
- builtin.Arch.aarch64v8_4a,
- builtin.Arch.aarch64v8_3a,
- builtin.Arch.aarch64v8_2a,
- builtin.Arch.aarch64v8_1a,
- builtin.Arch.aarch64v8,
- builtin.Arch.aarch64v8r,
- builtin.Arch.aarch64v8m_baseline,
- builtin.Arch.aarch64v8m_mainline,
- builtin.Arch.aarch64_bev8_5a,
- builtin.Arch.aarch64_bev8_4a,
- builtin.Arch.aarch64_bev8_3a,
- builtin.Arch.aarch64_bev8_2a,
- builtin.Arch.aarch64_bev8_1a,
- builtin.Arch.aarch64_bev8,
- builtin.Arch.aarch64_bev8r,
- builtin.Arch.aarch64_bev8m_baseline,
- builtin.Arch.aarch64_bev8m_mainline,
- builtin.Arch.mips64r6,
- builtin.Arch.mips64elr6,
+ builtin.Arch.aarch64,
+ builtin.Arch.aarch64_be,
+ builtin.Arch.mips64,
+ builtin.Arch.mips64el,
builtin.Arch.powerpc64,
builtin.Arch.powerpc64le,
builtin.Arch.riscv64,
@@ -298,17 +198,17 @@ pub const Target = union(enum) {
}
pub fn getFloatAbi(self: Target) FloatAbi {
- return switch (self.getEnviron()) {
- builtin.Environ.gnueabihf,
- builtin.Environ.eabihf,
- builtin.Environ.musleabihf,
+ return switch (self.getAbi()) {
+ builtin.Abi.gnueabihf,
+ builtin.Abi.eabihf,
+ builtin.Abi.musleabihf,
=> FloatAbi.Hard,
else => FloatAbi.Soft,
};
}
pub fn getDynamicLinkerPath(self: Target) ?[]const u8 {
- const env = self.getEnviron();
+ const env = self.getAbi();
const arch = self.getArch();
const os = self.getOs();
switch (os) {
@@ -317,21 +217,21 @@ pub const Target = union(enum) {
},
builtin.Os.linux => {
switch (env) {
- builtin.Environ.android => {
+ builtin.Abi.android => {
if (self.is64bit()) {
return "/system/bin/linker64";
} else {
return "/system/bin/linker";
}
},
- builtin.Environ.gnux32 => {
+ builtin.Abi.gnux32 => {
if (arch == builtin.Arch.x86_64) {
return "/libx32/ld-linux-x32.so.2";
}
},
- builtin.Environ.musl,
- builtin.Environ.musleabi,
- builtin.Environ.musleabihf,
+ builtin.Abi.musl,
+ builtin.Abi.musleabi,
+ builtin.Abi.musleabihf,
=> {
if (arch == builtin.Arch.x86_64) {
return "/lib/ld-musl-x86_64.so.1";
@@ -345,73 +245,18 @@ pub const Target = union(enum) {
builtin.Arch.sparcel,
=> return "/lib/ld-linux.so.2",
- builtin.Arch.aarch64v8_5a,
- builtin.Arch.aarch64v8_4a,
- builtin.Arch.aarch64v8_3a,
- builtin.Arch.aarch64v8_2a,
- builtin.Arch.aarch64v8_1a,
- builtin.Arch.aarch64v8,
- builtin.Arch.aarch64v8r,
- builtin.Arch.aarch64v8m_baseline,
- builtin.Arch.aarch64v8m_mainline,
- => return "/lib/ld-linux-aarch64.so.1",
+ builtin.Arch.aarch64 => return "/lib/ld-linux-aarch64.so.1",
- builtin.Arch.aarch64_bev8_5a,
- builtin.Arch.aarch64_bev8_4a,
- builtin.Arch.aarch64_bev8_3a,
- builtin.Arch.aarch64_bev8_2a,
- builtin.Arch.aarch64_bev8_1a,
- builtin.Arch.aarch64_bev8,
- builtin.Arch.aarch64_bev8r,
- builtin.Arch.aarch64_bev8m_baseline,
- builtin.Arch.aarch64_bev8m_mainline,
- => return "/lib/ld-linux-aarch64_be.so.1",
+ builtin.Arch.aarch64_be => return "/lib/ld-linux-aarch64_be.so.1",
- builtin.Arch.armv8_5a,
- builtin.Arch.armv8_4a,
- builtin.Arch.armv8_3a,
- builtin.Arch.armv8_2a,
- builtin.Arch.armv8_1a,
- builtin.Arch.armv8,
- builtin.Arch.armv8r,
- builtin.Arch.armv8m_baseline,
- builtin.Arch.armv8m_mainline,
- builtin.Arch.armv7,
- builtin.Arch.armv7em,
- builtin.Arch.armv7m,
- builtin.Arch.armv7s,
- builtin.Arch.armv7k,
- builtin.Arch.armv7ve,
- builtin.Arch.armv6,
- builtin.Arch.armv6m,
- builtin.Arch.armv6k,
- builtin.Arch.armv6t2,
- builtin.Arch.armv5,
- builtin.Arch.armv5te,
- builtin.Arch.armv4t,
+ builtin.Arch.arm,
builtin.Arch.thumb,
- builtin.Arch.armebv8_5a,
- builtin.Arch.armebv8_4a,
- builtin.Arch.armebv8_3a,
- builtin.Arch.armebv8_2a,
- builtin.Arch.armebv8_1a,
- builtin.Arch.armebv8,
- builtin.Arch.armebv8r,
- builtin.Arch.armebv8m_baseline,
- builtin.Arch.armebv8m_mainline,
- builtin.Arch.armebv7,
- builtin.Arch.armebv7em,
- builtin.Arch.armebv7m,
- builtin.Arch.armebv7s,
- builtin.Arch.armebv7k,
- builtin.Arch.armebv7ve,
- builtin.Arch.armebv6,
- builtin.Arch.armebv6m,
- builtin.Arch.armebv6k,
- builtin.Arch.armebv6t2,
- builtin.Arch.armebv5,
- builtin.Arch.armebv5te,
- builtin.Arch.armebv4t,
+ => return switch (self.getFloatAbi()) {
+ FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
+ else => return "/lib/ld-linux.so.3",
+ },
+
+ builtin.Arch.armeb,
builtin.Arch.thumbeb,
=> return switch (self.getFloatAbi()) {
FloatAbi.Hard => return "/lib/ld-linux-armhf.so.3",
@@ -454,9 +299,7 @@ pub const Target = union(enum) {
builtin.Arch.hsail64,
builtin.Arch.spir,
builtin.Arch.spir64,
- builtin.Arch.kalimbav3,
- builtin.Arch.kalimbav4,
- builtin.Arch.kalimbav5,
+ builtin.Arch.kalimba,
builtin.Arch.shave,
builtin.Arch.lanai,
builtin.Arch.wasm32,
@@ -470,8 +313,8 @@ pub const Target = union(enum) {
}
}
- pub fn llvmTargetFromTriple(triple: std.Buffer) !llvm.TargetRef {
- var result: llvm.TargetRef = undefined;
+ pub fn llvmTargetFromTriple(triple: std.Buffer) !*llvm.Target {
+ var result: *llvm.Target = undefined;
var err_msg: [*]u8 = undefined;
if (llvm.GetTargetFromTriple(triple.ptr(), &result, &err_msg) != 0) {
std.debug.warn("triple: {s} error: {s}\n", triple.ptr(), err_msg);
@@ -582,39 +425,9 @@ pub const Target = union(enum) {
pub fn getDarwinArchString(self: Target) []const u8 {
const arch = self.getArch();
switch (arch) {
- builtin.Arch.aarch64v8_5a,
- builtin.Arch.aarch64v8_4a,
- builtin.Arch.aarch64v8_3a,
- builtin.Arch.aarch64v8_2a,
- builtin.Arch.aarch64v8_1a,
- builtin.Arch.aarch64v8,
- builtin.Arch.aarch64v8r,
- builtin.Arch.aarch64v8m_baseline,
- builtin.Arch.aarch64v8m_mainline,
- => return "arm64",
+ builtin.Arch.aarch64 => return "arm64",
builtin.Arch.thumb,
- builtin.Arch.armv8_5a,
- builtin.Arch.armv8_4a,
- builtin.Arch.armv8_3a,
- builtin.Arch.armv8_2a,
- builtin.Arch.armv8_1a,
- builtin.Arch.armv8,
- builtin.Arch.armv8r,
- builtin.Arch.armv8m_baseline,
- builtin.Arch.armv8m_mainline,
- builtin.Arch.armv7,
- builtin.Arch.armv7em,
- builtin.Arch.armv7m,
- builtin.Arch.armv7s,
- builtin.Arch.armv7k,
- builtin.Arch.armv7ve,
- builtin.Arch.armv6,
- builtin.Arch.armv6m,
- builtin.Arch.armv6k,
- builtin.Arch.armv6t2,
- builtin.Arch.armv5,
- builtin.Arch.armv5te,
- builtin.Arch.armv4t,
+ builtin.Arch.arm,
=> return "arm",
builtin.Arch.powerpc => return "ppc",
builtin.Arch.powerpc64 => return "ppc64",
diff --git a/src-self-hosted/type.zig b/src-self-hosted/type.zig
index 8a05594b30..7d611bb787 100644
--- a/src-self-hosted/type.zig
+++ b/src-self-hosted/type.zig
@@ -51,8 +51,8 @@ pub const Type = struct {
pub fn getLlvmType(
base: *Type,
allocator: *Allocator,
- llvm_context: llvm.ContextRef,
- ) (error{OutOfMemory}!llvm.TypeRef) {
+ llvm_context: *llvm.Context,
+ ) (error{OutOfMemory}!*llvm.Type) {
switch (base.id) {
Id.Struct => return @fieldParentPtr(Struct, "base", base).getLlvmType(allocator, llvm_context),
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmType(allocator, llvm_context),
@@ -196,7 +196,7 @@ pub const Type = struct {
}
/// If you have an llvm conext handy, you can use it here.
- pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 {
+ pub async fn getAbiAlignmentInContext(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
if (await (async base.abi_alignment.start() catch unreachable)) |ptr| return ptr.*;
base.abi_alignment.data = await (async base.resolveAbiAlignment(comp, llvm_context) catch unreachable);
@@ -205,7 +205,7 @@ pub const Type = struct {
}
/// Lower level function that does the work. See getAbiAlignment.
- async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: llvm.ContextRef) !u32 {
+ async fn resolveAbiAlignment(base: *Type, comp: *Compilation, llvm_context: *llvm.Context) !u32 {
const llvm_type = try base.getLlvmType(comp.gpa(), llvm_context);
return @intCast(u32, llvm.ABIAlignmentOfType(comp.target_data_ref, llvm_type));
}
@@ -218,7 +218,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Struct, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -496,13 +496,13 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Fn, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
const normal = &self.key.data.Normal;
const llvm_return_type = switch (normal.return_type.id) {
Type.Id.Void => llvm.VoidTypeInContext(llvm_context) orelse return error.OutOfMemory,
else => try normal.return_type.getLlvmType(allocator, llvm_context),
};
- const llvm_param_types = try allocator.alloc(llvm.TypeRef, normal.params.len);
+ const llvm_param_types = try allocator.alloc(*llvm.Type, normal.params.len);
defer allocator.free(llvm_param_types);
for (llvm_param_types) |*llvm_param_type, i| {
llvm_param_type.* = try normal.params[i].typ.getLlvmType(allocator, llvm_context);
@@ -559,7 +559,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Bool, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -658,7 +658,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Int, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
return llvm.IntTypeInContext(llvm_context, self.key.bit_count) orelse return error.OutOfMemory;
}
};
@@ -670,7 +670,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Float, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -794,6 +794,7 @@ pub const Type = struct {
Size.One => "*",
Size.Many => "[*]",
Size.Slice => "[]",
+ Size.C => "[*c]",
};
const mut_str = switch (self.key.mut) {
Mut.Const => "const ",
@@ -835,7 +836,7 @@ pub const Type = struct {
return self;
}
- pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Pointer, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
const elem_llvm_type = try self.key.child_type.getLlvmType(allocator, llvm_context);
return llvm.PointerType(elem_llvm_type, 0) orelse return error.OutOfMemory;
}
@@ -903,7 +904,7 @@ pub const Type = struct {
return self;
}
- pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: llvm.ContextRef) !llvm.TypeRef {
+ pub fn getLlvmType(self: *Array, allocator: *Allocator, llvm_context: *llvm.Context) !*llvm.Type {
const elem_llvm_type = try self.key.elem_type.getLlvmType(allocator, llvm_context);
return llvm.ArrayType(elem_llvm_type, @intCast(c_uint, self.key.len)) orelse return error.OutOfMemory;
}
@@ -916,7 +917,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Vector, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -966,7 +967,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Optional, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -978,7 +979,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *ErrorUnion, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -990,7 +991,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *ErrorSet, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1002,7 +1003,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Enum, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1014,7 +1015,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Union, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1034,7 +1035,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *BoundFn, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1054,7 +1055,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Opaque, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1066,7 +1067,7 @@ pub const Type = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: llvm.ContextRef) llvm.TypeRef {
+ pub fn getLlvmType(self: *Promise, allocator: *Allocator, llvm_context: *llvm.Context) *llvm.Type {
@panic("TODO");
}
};
@@ -1088,6 +1089,7 @@ fn hashAny(x: var, comptime seed: u64) u32 {
builtin.TypeInfo.Pointer.Size.One => return hashAny(@ptrToInt(x), seed),
builtin.TypeInfo.Pointer.Size.Many => @compileError("implement hash function"),
builtin.TypeInfo.Pointer.Size.Slice => @compileError("implement hash function"),
+ builtin.TypeInfo.Pointer.Size.C => unreachable,
}
},
builtin.TypeId.Enum => return hashAny(@enumToInt(x), seed),
diff --git a/src-self-hosted/value.zig b/src-self-hosted/value.zig
index 9431c614b9..d8c0f7b5c8 100644
--- a/src-self-hosted/value.zig
+++ b/src-self-hosted/value.zig
@@ -57,7 +57,7 @@ pub const Value = struct {
std.debug.warn("{}", @tagName(base.id));
}
- pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?llvm.ValueRef) {
+ pub fn getLlvmConst(base: *Value, ofile: *ObjectFile) (error{OutOfMemory}!?*llvm.Value) {
switch (base.id) {
Id.Type => unreachable,
Id.Fn => return @fieldParentPtr(Fn, "base", base).getLlvmConst(ofile),
@@ -153,7 +153,7 @@ pub const Value = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *FnProto, ofile: *ObjectFile) !?*llvm.Value {
const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
const llvm_fn = llvm.AddFunction(
ofile.module,
@@ -238,7 +238,7 @@ pub const Value = struct {
/// We know that the function definition will end up in an .o file somewhere.
/// Here, all we have to do is generate a global prototype.
/// TODO cache the prototype per ObjectFile
- pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *Fn, ofile: *ObjectFile) !?*llvm.Value {
const llvm_fn_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
const llvm_fn = llvm.AddFunction(
ofile.module,
@@ -283,8 +283,8 @@ pub const Value = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) ?llvm.ValueRef {
- const llvm_type = llvm.Int1TypeInContext(ofile.context);
+ pub fn getLlvmConst(self: *Bool, ofile: *ObjectFile) !?*llvm.Value {
+ const llvm_type = llvm.Int1TypeInContext(ofile.context) orelse return error.OutOfMemory;
if (self.x) {
return llvm.ConstAllOnes(llvm_type);
} else {
@@ -381,7 +381,7 @@ pub const Value = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *Ptr, ofile: *ObjectFile) !?*llvm.Value {
const llvm_type = self.base.typ.getLlvmType(ofile.arena, ofile.context);
// TODO carefully port the logic from codegen.cpp:gen_const_val_ptr
switch (self.special) {
@@ -391,7 +391,7 @@ pub const Value = struct {
const array_llvm_value = (try base_array.val.getLlvmConst(ofile)).?;
const ptr_bit_count = ofile.comp.target_ptr_bits;
const usize_llvm_type = llvm.IntTypeInContext(ofile.context, ptr_bit_count) orelse return error.OutOfMemory;
- const indices = []llvm.ValueRef{
+ const indices = []*llvm.Value{
llvm.ConstNull(usize_llvm_type) orelse return error.OutOfMemory,
llvm.ConstInt(usize_llvm_type, base_array.elem_index, 0) orelse return error.OutOfMemory,
};
@@ -459,7 +459,7 @@ pub const Value = struct {
comp.gpa().destroy(self);
}
- pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *Array, ofile: *ObjectFile) !?*llvm.Value {
switch (self.special) {
Special.Undefined => {
const llvm_type = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
@@ -534,7 +534,7 @@ pub const Value = struct {
return self;
}
- pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?llvm.ValueRef {
+ pub fn getLlvmConst(self: *Int, ofile: *ObjectFile) !?*llvm.Value {
switch (self.base.typ.id) {
Type.Id.Int => {
const type_ref = try self.base.typ.getLlvmType(ofile.arena, ofile.context);
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 908c0e327c..902c6e13c2 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -18,6 +18,7 @@
#include "bigfloat.hpp"
#include "target.hpp"
#include "tokenizer.hpp"
+#include "libc_installation.hpp"
struct AstNode;
struct ImportTableEntry;
@@ -630,24 +631,12 @@ struct AstNodeUnwrapOptional {
AstNode *expr;
};
-enum CastOp {
- CastOpNoCast, // signifies the function call expression is not a cast
- CastOpNoop, // fn call expr is a cast, but does nothing
- CastOpIntToFloat,
- CastOpFloatToInt,
- CastOpBoolToInt,
- CastOpResizeSlice,
- CastOpNumLitToConcrete,
- CastOpErrSet,
- CastOpBitCast,
- CastOpPtrOfArrayToSlice,
-};
-
struct AstNodeFnCallExpr {
AstNode *fn_ref_expr;
ZigList params;
bool is_builtin;
bool is_async;
+ bool seen; // used by @compileLog
AstNode *async_allocator;
};
@@ -691,15 +680,17 @@ struct AstNodePointerType {
AstNode *align_expr;
BigInt *bit_offset_start;
BigInt *host_int_bytes;
+ AstNode *op_expr;
+ Token *allow_zero_token;
bool is_const;
bool is_volatile;
- AstNode *op_expr;
};
struct AstNodeArrayType {
AstNode *size;
AstNode *child_type;
AstNode *align_expr;
+ Token *allow_zero_token;
bool is_const;
bool is_volatile;
};
@@ -1038,6 +1029,7 @@ bool fn_type_id_eql(FnTypeId *a, FnTypeId *b);
enum PtrLen {
PtrLenUnknown,
PtrLenSingle,
+ PtrLenC,
};
struct ZigTypePointer {
@@ -1049,6 +1041,7 @@ struct ZigTypePointer {
uint32_t host_int_bytes; // size of host integer. 0 means no host integer; this field is aligned
bool is_const;
bool is_volatile;
+ bool allow_zero;
};
struct ZigTypeInt {
@@ -1247,6 +1240,12 @@ enum ZigTypeId {
ZigTypeIdVector,
};
+enum OnePossibleValue {
+ OnePossibleValueInvalid,
+ OnePossibleValueNo,
+ OnePossibleValueYes,
+};
+
struct ZigType {
ZigTypeId id;
Buf name;
@@ -1254,9 +1253,6 @@ struct ZigType {
LLVMTypeRef type_ref;
ZigLLVMDIType *di_type;
- bool zero_bits; // this is denormalized data
- bool gen_h_loop_flag;
-
union {
ZigTypePointer pointer;
ZigTypeInt integral;
@@ -1282,6 +1278,11 @@ struct ZigType {
// If we generate a constant name value for this type, we memoize it here.
// The type of this is array
ConstExprValue *cached_const_name_val;
+
+ OnePossibleValue one_possible_value;
+
+ bool zero_bits; // this is denormalized data
+ bool gen_h_loop_flag;
};
struct PackageTableEntry {
@@ -1340,15 +1341,11 @@ struct ZigFn {
// in the case of async functions this is the implicit return type according to the
// zig source code, not according to zig ir
ZigType *src_implicit_return_type;
- bool is_test;
- FnInline fn_inline;
- FnAnalState anal_state;
IrExecutable ir_executable;
IrExecutable analyzed_executable;
size_t prealloc_bbc;
AstNode **param_source_nodes;
Buf **param_names;
- uint32_t align_bytes;
AstNode *fn_no_inline_set_node;
AstNode *fn_static_eval_set_node;
@@ -1358,13 +1355,22 @@ struct ZigFn {
Buf *section_name;
AstNode *set_alignstack_node;
- uint32_t alignstack_value;
AstNode *set_cold_node;
- bool is_cold;
ZigList export_list;
+
+ LLVMValueRef valgrind_client_request_array;
+
+ FnInline fn_inline;
+ FnAnalState anal_state;
+
+ uint32_t align_bytes;
+ uint32_t alignstack_value;
+
bool calls_or_awaits_errorable_fn;
+ bool is_cold;
+ bool is_test;
};
uint32_t fn_table_entry_hash(ZigFn*);
@@ -1484,6 +1490,7 @@ enum PanicMsgId {
PanicMsgIdBadUnionField,
PanicMsgIdBadEnumValue,
PanicMsgIdFloatToInt,
+ PanicMsgIdPtrCastNull,
PanicMsgIdCount,
};
@@ -1498,11 +1505,12 @@ struct TypeId {
struct {
ZigType *child_type;
PtrLen ptr_len;
- bool is_const;
- bool is_volatile;
uint32_t alignment;
uint32_t bit_offset_in_host;
uint32_t host_int_bytes;
+ bool is_const;
+ bool is_volatile;
+ bool allow_zero;
} pointer;
struct {
ZigType *child_type;
@@ -1605,6 +1613,17 @@ struct LinkLib {
bool provided_explicitly;
};
+enum ValgrindSupport {
+ ValgrindSupportAuto,
+ ValgrindSupportDisabled,
+ ValgrindSupportEnabled,
+};
+
+struct CFile {
+ ZigList args;
+ const char *source_path;
+};
+
// When adding fields, check if they should be added to the hash computation in build_with_cache
struct CodeGen {
//////////////////////////// Runtime State
@@ -1660,7 +1679,7 @@ struct CodeGen {
HashMap generic_table;
HashMap memoized_fn_eval_table;
HashMap llvm_fn_table;
- HashMap exported_symbol_names;
+ HashMap exported_symbol_names;
HashMap external_prototypes;
HashMap string_literals_table;
HashMap type_info_cache;
@@ -1732,12 +1751,16 @@ struct CodeGen {
Buf triple_str;
Buf global_asm;
Buf *out_h_path;
+ Buf *out_lib_path;
Buf artifact_dir;
Buf output_file_path;
Buf o_file_output_path;
Buf *wanted_output_file_path;
Buf cache_dir;
+ Buf *zig_c_headers_dir; // Cannot be overridden; derived from zig_lib_dir.
+ Buf *zig_std_special_dir; // Cannot be overridden; derived from zig_lib_dir.
+
IrInstruction *invalid_instruction;
IrInstruction *unreach_instruction;
@@ -1752,6 +1775,7 @@ struct CodeGen {
ZigFn *cur_fn;
ZigFn *main_fn;
ZigFn *panic_fn;
+ TldFn *panic_tld_fn;
AstNode *root_export_decl;
CacheHash cache_hash;
@@ -1760,7 +1784,8 @@ struct CodeGen {
unsigned pointer_size_bytes;
uint32_t target_os_index;
uint32_t target_arch_index;
- uint32_t target_environ_index;
+ uint32_t target_sub_arch_index;
+ uint32_t target_abi_index;
uint32_t target_oformat_index;
bool is_big_endian;
bool have_pub_main;
@@ -1778,13 +1803,17 @@ struct CodeGen {
bool verbose_ir;
bool verbose_llvm_ir;
bool verbose_cimport;
+ bool verbose_cc;
bool error_during_imports;
bool generate_error_name_table;
bool enable_cache;
bool enable_time_report;
bool system_linker_hack;
+ bool reported_bad_link_libc_error;
//////////////////////////// Participates in Input Parameter Cache Hash
+ /////// Note: there is a separate cache hash for builtin.zig, when adding fields,
+ /////// consider if they need to go into both.
ZigList link_libs_list;
// add -framework [name] args to linker
ZigList darwin_frameworks;
@@ -1793,8 +1822,11 @@ struct CodeGen {
ZigList forbidden_libs;
ZigList link_objects;
ZigList assembly_files;
+ ZigList c_source_files;
ZigList lib_dirs;
+ ZigLibCInstallation *libc;
+
size_t version_major;
size_t version_minor;
size_t version_patch;
@@ -1803,15 +1835,14 @@ struct CodeGen {
EmitFileType emit_file_type;
BuildMode build_mode;
OutType out_type;
- ZigTarget zig_target;
+ const ZigTarget *zig_target;
TargetSubsystem subsystem;
+ ValgrindSupport valgrind_support;
bool is_static;
bool strip_debug_symbols;
bool is_test_build;
bool is_single_threaded;
- bool is_native_target;
bool linker_rdynamic;
- bool no_rosegment_workaround;
bool each_lib_rpath;
bool disable_pic;
@@ -1821,31 +1852,21 @@ struct CodeGen {
Buf *test_filter;
Buf *test_name_prefix;
PackageTableEntry *root_package;
+ Buf *zig_lib_dir;
+ Buf *zig_std_dir;
const char **llvm_argv;
size_t llvm_argv_len;
const char **clang_argv;
size_t clang_argv_len;
-
- //////////////////////////// Unsorted
-
- Buf *libc_lib_dir;
- Buf *libc_static_lib_dir;
- Buf *libc_include_dir;
- Buf *msvc_lib_dir;
- Buf *kernel32_lib_dir;
- Buf *zig_lib_dir;
- Buf *zig_std_dir;
- Buf *zig_c_headers_dir;
- Buf *zig_std_special_dir;
- Buf *dynamic_linker;
- ZigWindowsSDK *win_sdk;
};
enum VarLinkage {
VarLinkageInternal,
- VarLinkageExport,
+ VarLinkageExportStrong,
+ VarLinkageExportWeak,
+ VarLinkageExportLinkOnce,
VarLinkageExternal,
};
@@ -2084,6 +2105,11 @@ struct IrBasicBlock {
IrInstruction *must_be_comptime_source_instr;
};
+enum LVal {
+ LValNone,
+ LValPtr,
+};
+
// These instructions are in transition to having "pass 1" instructions
// and "pass 2" instructions. The pass 1 instructions are suffixed with Src
// and pass 2 are suffixed with Gen.
@@ -2106,6 +2132,7 @@ enum IrInstructionId {
IrInstructionIdUnOp,
IrInstructionIdBinOp,
IrInstructionIdLoadPtr,
+ IrInstructionIdLoadPtrGen,
IrInstructionIdStorePtr,
IrInstructionIdFieldPtr,
IrInstructionIdStructFieldPtr,
@@ -2116,6 +2143,7 @@ enum IrInstructionId {
IrInstructionIdConst,
IrInstructionIdReturn,
IrInstructionIdCast,
+ IrInstructionIdResizeSlice,
IrInstructionIdContainerInitList,
IrInstructionIdContainerInitFields,
IrInstructionIdStructInit,
@@ -2183,6 +2211,7 @@ enum IrInstructionId {
IrInstructionIdPtrCastSrc,
IrInstructionIdPtrCastGen,
IrInstructionIdBitCast,
+ IrInstructionIdBitCastGen,
IrInstructionIdWidenOrShorten,
IrInstructionIdIntToPtr,
IrInstructionIdPtrToInt,
@@ -2347,6 +2376,7 @@ struct IrInstructionUnOp {
IrUnOp op_id;
IrInstruction *value;
+ LVal lval;
};
enum IrBinOp {
@@ -2399,6 +2429,13 @@ struct IrInstructionLoadPtr {
IrInstruction *ptr;
};
+struct IrInstructionLoadPtrGen {
+ IrInstruction base;
+
+ IrInstruction *ptr;
+ LLVMValueRef tmp_ptr;
+};
+
struct IrInstructionStorePtr {
IrInstruction base;
@@ -2476,6 +2513,18 @@ struct IrInstructionReturn {
IrInstruction *value;
};
+enum CastOp {
+ CastOpNoCast, // signifies the function call expression is not a cast
+ CastOpNoop, // fn call expr is a cast, but does nothing
+ CastOpIntToFloat,
+ CastOpFloatToInt,
+ CastOpBoolToInt,
+ CastOpNumLitToConcrete,
+ CastOpErrSet,
+ CastOpBitCast,
+ CastOpPtrOfArrayToSlice,
+};
+
// TODO get rid of this instruction, replace with instructions for each op code
struct IrInstructionCast {
IrInstruction base;
@@ -2486,6 +2535,13 @@ struct IrInstructionCast {
LLVMValueRef tmp_ptr;
};
+struct IrInstructionResizeSlice {
+ IrInstruction base;
+
+ IrInstruction *operand;
+ LLVMValueRef tmp_ptr;
+};
+
struct IrInstructionContainerInitList {
IrInstruction base;
@@ -2591,6 +2647,7 @@ struct IrInstructionPtrType {
PtrLen ptr_len;
bool is_const;
bool is_volatile;
+ bool allow_zero;
};
struct IrInstructionPromiseType {
@@ -2606,6 +2663,7 @@ struct IrInstructionSliceType {
IrInstruction *child_type;
bool is_const;
bool is_volatile;
+ bool allow_zero;
};
struct IrInstructionAsm {
@@ -2994,12 +3052,14 @@ struct IrInstructionPtrCastSrc {
IrInstruction *dest_type;
IrInstruction *ptr;
+ bool safety_check_on;
};
struct IrInstructionPtrCastGen {
IrInstruction base;
IrInstruction *ptr;
+ bool safety_check_on;
};
struct IrInstructionBitCast {
@@ -3009,6 +3069,13 @@ struct IrInstructionBitCast {
IrInstruction *value;
};
+struct IrInstructionBitCastGen {
+ IrInstruction base;
+
+ IrInstruction *operand;
+ LLVMValueRef tmp_ptr;
+};
+
struct IrInstructionWidenOrShorten {
IrInstruction base;
@@ -3079,11 +3146,6 @@ struct IrInstructionTypeName {
IrInstruction *type_value;
};
-enum LVal {
- LValNone,
- LValPtr,
-};
-
struct IrInstructionDeclRef {
IrInstruction base;
diff --git a/src/analyze.cpp b/src/analyze.cpp
index 970d1cc382..3ceda41934 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -356,7 +356,7 @@ uint64_t type_size(CodeGen *g, ZigType *type_entry) {
}
}
- return LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
+ return LLVMABISizeOfType(g->target_data_ref, type_entry->type_ref);
}
uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
@@ -365,19 +365,19 @@ uint64_t type_size_bits(CodeGen *g, ZigType *type_entry) {
if (!type_has_bits(type_entry))
return 0;
- if (type_entry->id == ZigTypeIdStruct && type_entry->data.structure.layout == ContainerLayoutPacked) {
- uint64_t result = 0;
- for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
- result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry);
+ if (type_entry->id == ZigTypeIdStruct) {
+ if (type_entry->data.structure.layout == ContainerLayoutPacked) {
+ uint64_t result = 0;
+ for (size_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) {
+ result += type_size_bits(g, type_entry->data.structure.fields[i].type_entry);
+ }
+ return result;
+ } else if (type_entry->data.structure.layout == ContainerLayoutExtern) {
+ return type_size(g, type_entry) * 8;
}
- return result;
} else if (type_entry->id == ZigTypeIdArray) {
ZigType *child_type = type_entry->data.array.child_type;
- if (child_type->id == ZigTypeIdStruct &&
- child_type->data.structure.layout == ContainerLayoutPacked)
- {
- return type_entry->data.array.len * type_size_bits(g, child_type);
- }
+ return type_entry->data.array.len * type_size_bits(g, child_type);
}
return LLVMSizeOfTypeInBits(g->target_data_ref, type_entry->type_ref);
@@ -417,10 +417,25 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type) {
return entry;
}
+static const char *ptr_len_to_star_str(PtrLen ptr_len) {
+ switch (ptr_len) {
+ case PtrLenSingle:
+ return "*";
+ case PtrLenUnknown:
+ return "[*]";
+ case PtrLenC:
+ return "[*c]";
+ }
+ zig_unreachable();
+}
+
ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_const,
bool is_volatile, PtrLen ptr_len, uint32_t byte_alignment,
uint32_t bit_offset_in_host, uint32_t host_int_bytes)
{
+ // TODO when implementing https://github.com/ziglang/zig/issues/1953
+ // move this to a parameter
+ bool allow_zero = (ptr_len == PtrLenC);
assert(!type_is_invalid(child_type));
assert(ptr_len == PtrLenSingle || child_type->id != ZigTypeIdOpaque);
@@ -440,7 +455,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
TypeId type_id = {};
ZigType **parent_pointer = nullptr;
- if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle) {
+ if (host_int_bytes != 0 || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || allow_zero) {
type_id.id = ZigTypeIdPointer;
type_id.data.pointer.child_type = child_type;
type_id.data.pointer.is_const = is_const;
@@ -449,6 +464,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
type_id.data.pointer.bit_offset_in_host = bit_offset_in_host;
type_id.data.pointer.host_int_bytes = host_int_bytes;
type_id.data.pointer.ptr_len = ptr_len;
+ type_id.data.pointer.allow_zero = allow_zero;
auto existing_entry = g->type_table.maybe_get(type_id);
if (existing_entry)
@@ -466,21 +482,31 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
ZigType *entry = new_type_table_entry(ZigTypeIdPointer);
- const char *star_str = ptr_len == PtrLenSingle ? "*" : "[*]";
+ const char *star_str = ptr_len_to_star_str(ptr_len);
const char *const_str = is_const ? "const " : "";
const char *volatile_str = is_volatile ? "volatile " : "";
+ const char *allow_zero_str;
+ if (ptr_len == PtrLenC) {
+ assert(allow_zero);
+ allow_zero_str = "";
+ } else {
+ allow_zero_str = allow_zero ? "allowzero " : "";
+ }
buf_resize(&entry->name, 0);
if (host_int_bytes == 0 && byte_alignment == 0) {
- buf_appendf(&entry->name, "%s%s%s%s", star_str, const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%s%s%s%s%s",
+ star_str, const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
} else if (host_int_bytes == 0) {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s", star_str, byte_alignment,
- const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%salign(%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
+ const_str, volatile_str, allow_zero_str, buf_ptr(&child_type->name));
} else if (byte_alignment == 0) {
- buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str,
- bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%salign(:%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str,
+ bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
+ buf_ptr(&child_type->name));
} else {
- buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s", star_str, byte_alignment,
- bit_offset_in_host, host_int_bytes, const_str, volatile_str, buf_ptr(&child_type->name));
+ buf_appendf(&entry->name, "%salign(%" PRIu32 ":%" PRIu32 ":%" PRIu32 ") %s%s%s%s", star_str, byte_alignment,
+ bit_offset_in_host, host_int_bytes, const_str, volatile_str, allow_zero_str,
+ buf_ptr(&child_type->name));
}
assert(child_type->id != ZigTypeIdInvalid);
@@ -488,7 +514,9 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->zero_bits = !type_has_bits(child_type);
if (!entry->zero_bits) {
- if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle || bit_offset_in_host != 0) {
+ if (is_const || is_volatile || byte_alignment != 0 || ptr_len != PtrLenSingle ||
+ bit_offset_in_host != 0 || allow_zero)
+ {
ZigType *peer_type = get_pointer_to_type_extra(g, child_type, false, false,
PtrLenSingle, 0, 0, host_int_bytes);
entry->type_ref = peer_type->type_ref;
@@ -522,6 +550,7 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
entry->data.pointer.explicit_alignment = byte_alignment;
entry->data.pointer.bit_offset_in_host = bit_offset_in_host;
entry->data.pointer.host_int_bytes = host_int_bytes;
+ entry->data.pointer.allow_zero = allow_zero;
if (parent_pointer) {
*parent_pointer = entry;
@@ -838,7 +867,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
ZigType *child_type = ptr_type->data.pointer.child_type;
if (ptr_type->data.pointer.is_const || ptr_type->data.pointer.is_volatile ||
- ptr_type->data.pointer.explicit_alignment != 0)
+ ptr_type->data.pointer.explicit_alignment != 0 || ptr_type->data.pointer.allow_zero)
{
ZigType *peer_ptr_type = get_pointer_to_type_extra(g, child_type, false, false,
PtrLenUnknown, 0, 0, 0);
@@ -861,7 +890,7 @@ ZigType *get_slice_type(CodeGen *g, ZigType *ptr_type) {
ZigType *child_ptr_type = child_type->data.structure.fields[slice_ptr_index].type_entry;
assert(child_ptr_type->id == ZigTypeIdPointer);
if (child_ptr_type->data.pointer.is_const || child_ptr_type->data.pointer.is_volatile ||
- child_ptr_type->data.pointer.explicit_alignment != 0)
+ child_ptr_type->data.pointer.explicit_alignment != 0 || child_ptr_type->data.pointer.allow_zero)
{
ZigType *grand_child_type = child_ptr_type->data.pointer.child_type;
ZigType *bland_child_ptr_type = get_pointer_to_type_extra(g, grand_child_type, false, false,
@@ -1073,10 +1102,10 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
if (type_is_c_abi_int(g, fn_type_id->return_type)) {
return false;
}
- if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
+ if (g->zig_target->arch == ZigLLVM_x86_64) {
X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
return abi_class == X64CABIClass_MEMORY;
- } else if (target_is_arm(&g->zig_target)) {
+ } else if (target_is_arm(g->zig_target)) {
return type_size(g, fn_type_id->return_type) > 16;
}
zig_panic("TODO implement C ABI for this architecture. See https://github.com/ziglang/zig/issues/1481");
@@ -1300,7 +1329,7 @@ static ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *no
size_t backward_branch_count = 0;
return ir_eval_const_value(g, scope, node, type_entry,
&backward_branch_count, default_backward_branch_quota,
- nullptr, nullptr, node, type_name, nullptr);
+ nullptr, nullptr, node, type_name, nullptr, nullptr);
}
ZigType *analyze_type_expr(CodeGen *g, Scope *scope, AstNode *node) {
@@ -1415,7 +1444,10 @@ static bool analyze_const_string(CodeGen *g, Scope *scope, AstNode *node, Buf **
return true;
}
-static bool type_allowed_in_packed_struct(ZigType *type_entry) {
+static Error emit_error_unless_type_allowed_in_packed_struct(CodeGen *g, ZigType *type_entry,
+ AstNode *source_node)
+{
+ Error err;
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
@@ -1432,32 +1464,79 @@ static bool type_allowed_in_packed_struct(ZigType *type_entry) {
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
case ZigTypeIdPromise:
- return false;
+ add_node_error(g, source_node,
+ buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name)));
+ return ErrorSemanticAnalyzeFail;
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
- case ZigTypeIdArray:
case ZigTypeIdFn:
case ZigTypeIdVector:
- return true;
+ return ErrorNone;
+ case ZigTypeIdArray: {
+ ZigType *elem_type = type_entry->data.array.child_type;
+ if ((err = emit_error_unless_type_allowed_in_packed_struct(g, elem_type, source_node)))
+ return err;
+ if (type_size(g, type_entry) * 8 == type_size_bits(g, type_entry))
+ return ErrorNone;
+ add_node_error(g, source_node,
+ buf_sprintf("array of '%s' not allowed in packed struct due to padding bits",
+ buf_ptr(&elem_type->name)));
+ return ErrorSemanticAnalyzeFail;
+ }
case ZigTypeIdStruct:
- return type_entry->data.structure.layout == ContainerLayoutPacked;
- case ZigTypeIdUnion:
- return type_entry->data.unionation.layout == ContainerLayoutPacked;
- case ZigTypeIdOptional:
- {
- ZigType *child_type = type_entry->data.maybe.child_type;
- return type_is_codegen_pointer(child_type);
+ switch (type_entry->data.structure.layout) {
+ case ContainerLayoutPacked:
+ case ContainerLayoutExtern:
+ return ErrorNone;
+ case ContainerLayoutAuto:
+ add_node_error(g, source_node,
+ buf_sprintf("non-packed, non-extern struct '%s' not allowed in packed struct; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name)));
+ return ErrorSemanticAnalyzeFail;
}
- case ZigTypeIdEnum:
- return type_entry->data.enumeration.decl_node->data.container_decl.init_arg_expr != nullptr;
+ zig_unreachable();
+ case ZigTypeIdUnion:
+ switch (type_entry->data.unionation.layout) {
+ case ContainerLayoutPacked:
+ case ContainerLayoutExtern:
+ return ErrorNone;
+ case ContainerLayoutAuto:
+ add_node_error(g, source_node,
+ buf_sprintf("non-packed, non-extern union '%s' not allowed in packed struct; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name)));
+ return ErrorSemanticAnalyzeFail;
+ }
+ zig_unreachable();
+ case ZigTypeIdOptional:
+ if (get_codegen_ptr_type(type_entry) != nullptr) {
+ return ErrorNone;
+ } else {
+ add_node_error(g, source_node,
+ buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name)));
+ return ErrorSemanticAnalyzeFail;
+ }
+ case ZigTypeIdEnum: {
+ AstNode *decl_node = type_entry->data.enumeration.decl_node;
+ if (decl_node->data.container_decl.init_arg_expr != nullptr) {
+ return ErrorNone;
+ }
+ ErrorMsg *msg = add_node_error(g, source_node,
+ buf_sprintf("type '%s' not allowed in packed struct; no guaranteed in-memory representation",
+ buf_ptr(&type_entry->name)));
+ add_error_note(g, msg, decl_node,
+ buf_sprintf("enum declaration does not specify an integer tag type"));
+ return ErrorSemanticAnalyzeFail;
+ }
}
zig_unreachable();
}
-static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
+bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
@@ -1583,7 +1662,7 @@ static ZigType *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *child_sc
}
} else if (param_node->data.param_decl.var_token != nullptr) {
if (!calling_convention_allows_zig_types(fn_type_id.cc)) {
- add_node_error(g, param_node->data.param_decl.type,
+ add_node_error(g, param_node,
buf_sprintf("parameter of type 'var' not allowed in function with calling convention '%s'",
calling_convention_name(fn_type_id.cc)));
return g->builtin_types.entry_invalid;
@@ -2022,11 +2101,8 @@ static Error resolve_struct_type(CodeGen *g, ZigType *struct_type) {
type_struct_field->gen_index = gen_field_index;
if (packed) {
- if (!type_allowed_in_packed_struct(field_type)) {
- AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
- add_node_error(g, field_source_node,
- buf_sprintf("packed structs cannot contain fields of type '%s'",
- buf_ptr(&field_type->name)));
+ AstNode *field_source_node = decl_node->data.container_decl.fields.at(i);
+ if ((err = emit_error_unless_type_allowed_in_packed_struct(g, field_type, field_source_node))) {
struct_type->data.structure.resolve_status = ResolveStatusInvalid;
break;
}
@@ -2650,6 +2726,13 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
buf_sprintf("enums, not structs, support field assignment"));
}
+ if (field_type->id == ZigTypeIdOpaque) {
+ add_node_error(g, field_node->data.struct_field.type,
+ buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in structs"));
+ struct_type->data.structure.resolve_status = ResolveStatusInvalid;
+ continue;
+ }
+
switch (type_requires_comptime(g, field_type)) {
case ReqCompTimeYes:
struct_type->data.structure.requires_comptime = true;
@@ -2828,7 +2911,7 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
union_type->data.unionation.have_explicit_tag_type = decl_node->data.container_decl.auto_enum ||
enum_type_node != nullptr;
bool auto_layout = (union_type->data.unionation.layout == ContainerLayoutAuto);
- bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr);
+ bool want_safety = (field_count >= 2) && (auto_layout || enum_type_node != nullptr) && !(g->build_mode == BuildModeFastRelease || g->build_mode == BuildModeSmallRelease);
ZigType *tag_type;
bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
bool *covered_enum_fields;
@@ -2934,6 +3017,13 @@ static Error resolve_union_zero_bits(CodeGen *g, ZigType *union_type) {
}
union_field->type_entry = field_type;
+ if (field_type->id == ZigTypeIdOpaque) {
+ add_node_error(g, field_node->data.struct_field.type,
+ buf_sprintf("opaque types have unknown size and therefore cannot be directly embedded in unions"));
+ union_type->data.unionation.is_invalid = true;
+ continue;
+ }
+
switch (type_requires_comptime(g, field_type)) {
case ReqCompTimeInvalid:
union_type->data.unionation.is_invalid = true;
@@ -3182,36 +3272,19 @@ static bool scope_is_root_decls(Scope *scope) {
zig_unreachable();
}
-static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, ZigType *fn_type) {
- add_node_error(g, proto_node,
- buf_sprintf("expected 'fn([]const u8, ?*builtin.StackTrace) noreturn', found '%s'",
- buf_ptr(&fn_type->name)));
-}
+void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn) {
+ ConstExprValue *panic_fn_type_val = get_builtin_value(g, "PanicFn");
+ assert(panic_fn_type_val != nullptr);
+ assert(panic_fn_type_val->type->id == ZigTypeIdMetaType);
+ ZigType *panic_fn_type = panic_fn_type_val->data.x_type;
-static void typecheck_panic_fn(CodeGen *g, ZigFn *panic_fn) {
- AstNode *proto_node = panic_fn->proto_node;
- assert(proto_node->type == NodeTypeFnProto);
- ZigType *fn_type = panic_fn->type_entry;
- FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
- if (fn_type_id->param_count != 2) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
- ZigType *const_u8_ptr = get_pointer_to_type_extra(g, g->builtin_types.entry_u8, true, false,
- PtrLenUnknown, 0, 0, 0);
- ZigType *const_u8_slice = get_slice_type(g, const_u8_ptr);
- if (fn_type_id->param_info[0].type != const_u8_slice) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
+ AstNode *fake_decl = allocate(1);
+ *fake_decl = *panic_fn->proto_node;
+ fake_decl->type = NodeTypeSymbol;
+ fake_decl->data.symbol_expr.symbol = &panic_fn->symbol_name;
- ZigType *optional_ptr_to_stack_trace_type = get_optional_type(g, get_ptr_to_stack_trace_type(g));
- if (fn_type_id->param_info[1].type != optional_ptr_to_stack_trace_type) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
-
- ZigType *actual_return_type = fn_type_id->return_type;
- if (actual_return_type != g->builtin_types.entry_unreachable) {
- return wrong_panic_prototype(g, proto_node, fn_type);
- }
+ // call this for the side effects of casting to panic_fn_type
+ analyze_const_value(g, tld_fn->base.parent_scope, fake_decl, panic_fn_type, nullptr);
}
ZigType *get_test_fn_type(CodeGen *g) {
@@ -3231,16 +3304,16 @@ void add_fn_export(CodeGen *g, ZigFn *fn_table_entry, Buf *symbol_name, GlobalLi
g->have_c_main = true;
g->subsystem = TargetSubsystemConsole;
} else if (buf_eql_str(symbol_name, "WinMain") &&
- g->zig_target.os == OsWindows)
+ g->zig_target->os == OsWindows)
{
g->have_winmain = true;
g->subsystem = TargetSubsystemWindows;
} else if (buf_eql_str(symbol_name, "WinMainCRTStartup") &&
- g->zig_target.os == OsWindows)
+ g->zig_target->os == OsWindows)
{
g->have_winmain_crt_startup = true;
} else if (buf_eql_str(symbol_name, "DllMainCRTStartup") &&
- g->zig_target.os == OsWindows)
+ g->zig_target->os == OsWindows)
{
g->have_dllmain_crt_startup = true;
}
@@ -3306,18 +3379,18 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
if (!fn_table_entry->type_entry->data.fn.is_generic) {
if (fn_def_node)
g->fn_defs.append(fn_table_entry);
+ }
- if (scope_is_root_decls(tld_fn->base.parent_scope) &&
- (import == g->root_import || import->package == g->panic_package))
+ if (scope_is_root_decls(tld_fn->base.parent_scope) &&
+ (import == g->root_import || import->package == g->panic_package))
+ {
+ if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
+ g->main_fn = fn_table_entry;
+ } else if ((import->package == g->panic_package || g->have_pub_panic) &&
+ buf_eql_str(&fn_table_entry->symbol_name, "panic"))
{
- if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
- g->main_fn = fn_table_entry;
- } else if ((import->package == g->panic_package || g->have_pub_panic) &&
- buf_eql_str(&fn_table_entry->symbol_name, "panic"))
- {
- g->panic_fn = fn_table_entry;
- typecheck_panic_fn(g, fn_table_entry);
- }
+ g->panic_fn = fn_table_entry;
+ g->panic_tld_fn = tld_fn;
}
}
} else if (source_node->type == NodeTypeTestDecl) {
@@ -3366,9 +3439,9 @@ static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
if (is_export) {
g->resolve_queue.append(tld);
- auto entry = g->exported_symbol_names.put_unique(tld->name, tld->source_node);
+ auto entry = g->exported_symbol_names.put_unique(tld->name, tld);
if (entry) {
- AstNode *other_source_node = entry->value;
+ AstNode *other_source_node = entry->value->source_node;
ErrorMsg *msg = add_node_error(g, tld->source_node,
buf_sprintf("exported symbol collision: '%s'", buf_ptr(tld->name)));
add_error_note(g, msg, other_source_node, buf_sprintf("other symbol here"));
@@ -3698,7 +3771,7 @@ static void resolve_decl_var(CodeGen *g, TldVar *tld_var) {
VarLinkage linkage;
if (is_export) {
- linkage = VarLinkageExport;
+ linkage = VarLinkageExportStrong;
} else if (is_extern) {
linkage = VarLinkageExternal;
} else {
@@ -4041,7 +4114,9 @@ ZigType *get_src_ptr_type(ZigType *type) {
if (type->id == ZigTypeIdFn) return type;
if (type->id == ZigTypeIdPromise) return type;
if (type->id == ZigTypeIdOptional) {
- if (type->data.maybe.child_type->id == ZigTypeIdPointer) return type->data.maybe.child_type;
+ if (type->data.maybe.child_type->id == ZigTypeIdPointer) {
+ return type->data.maybe.child_type->data.pointer.allow_zero ? nullptr : type->data.maybe.child_type;
+ }
if (type->data.maybe.child_type->id == ZigTypeIdFn) return type->data.maybe.child_type;
if (type->data.maybe.child_type->id == ZigTypeIdPromise) return type->data.maybe.child_type;
}
@@ -4055,6 +4130,10 @@ ZigType *get_codegen_ptr_type(ZigType *type) {
return ty;
}
+bool type_is_nonnull_ptr(ZigType *type) {
+ return type_is_codegen_pointer(type) && !ptr_allows_addr_zero(type);
+}
+
bool type_is_codegen_pointer(ZigType *type) {
return get_codegen_ptr_type(type) == type;
}
@@ -4572,185 +4651,6 @@ bool handle_is_ptr(ZigType *type_entry) {
zig_unreachable();
}
-static ZigWindowsSDK *get_windows_sdk(CodeGen *g) {
- if (g->win_sdk == nullptr) {
- if (zig_find_windows_sdk(&g->win_sdk)) {
- fprintf(stderr, "unable to determine windows sdk path\n");
- exit(1);
- }
- }
- assert(g->win_sdk != nullptr);
- return g->win_sdk;
-}
-
-
-static Buf *get_linux_libc_lib_path(const char *o_file) {
- const char *cc_exe = getenv("CC");
- cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
- ZigList args = {};
- args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
- Termination term;
- Buf *out_stderr = buf_alloc();
- Buf *out_stdout = buf_alloc();
- Error err;
- if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
- zig_panic("unable to determine libc lib path: executing C compiler: %s", err_str(err));
- }
- if (term.how != TerminationIdClean || term.code != 0) {
- zig_panic("unable to determine libc lib path: executing C compiler command failed");
- }
- if (buf_ends_with_str(out_stdout, "\n")) {
- buf_resize(out_stdout, buf_len(out_stdout) - 1);
- }
- if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) {
- zig_panic("unable to determine libc lib path: C compiler could not find %s", o_file);
- }
- Buf *result = buf_alloc();
- os_path_dirname(out_stdout, result);
- return result;
-}
-
-static Buf *get_posix_libc_include_path(void) {
- const char *cc_exe = getenv("CC");
- cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
- ZigList args = {};
- args.append("-E");
- args.append("-Wp,-v");
- args.append("-xc");
- args.append("/dev/null");
- Termination term;
- Buf *out_stderr = buf_alloc();
- Buf *out_stdout = buf_alloc();
- Error err;
- if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
- zig_panic("unable to determine libc include path: executing C compiler: %s", err_str(err));
- }
- if (term.how != TerminationIdClean || term.code != 0) {
- zig_panic("unable to determine libc include path: executing C compiler command failed");
- }
- char *prev_newline = buf_ptr(out_stderr);
- ZigList search_paths = {};
- for (;;) {
- char *newline = strchr(prev_newline, '\n');
- if (newline == nullptr) {
- break;
- }
- *newline = 0;
- if (prev_newline[0] == ' ') {
- search_paths.append(prev_newline);
- }
- prev_newline = newline + 1;
- }
- if (search_paths.length == 0) {
- zig_panic("unable to determine libc include path: even C compiler does not know where libc headers are");
- }
- for (size_t i = 0; i < search_paths.length; i += 1) {
- // search in reverse order
- const char *search_path = search_paths.items[search_paths.length - i - 1];
- // cut off spaces
- while (*search_path == ' ') {
- search_path += 1;
- }
- Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path);
- bool exists;
- if ((err = os_file_exists(stdlib_path, &exists))) {
- exists = false;
- }
- if (exists) {
- return buf_create_from_str(search_path);
- }
- }
- zig_panic("unable to determine libc include path: stdlib.h not found in C compiler search paths");
-}
-
-void find_libc_include_path(CodeGen *g) {
- if (g->libc_include_dir == nullptr) {
- if (!g->is_native_target) {
- return;
- }
-
- if (g->zig_target.os == OsWindows) {
- ZigWindowsSDK *sdk = get_windows_sdk(g);
- g->libc_include_dir = buf_alloc();
- if (os_get_win32_ucrt_include_path(sdk, g->libc_include_dir)) {
- fprintf(stderr, "Unable to determine libc include path. --libc-include-dir");
- exit(1);
- }
- } else if (g->zig_target.os == OsLinux ||
- g->zig_target.os == OsMacOSX ||
- g->zig_target.os == OsFreeBSD)
- {
- g->libc_include_dir = get_posix_libc_include_path();
- } else {
- fprintf(stderr, "Unable to determine libc include path.\n"
- "TODO: implement finding libc at runtime for other operating systems.\n"
- "in the meantime, you can use as a workaround: --libc-include-dir\n");
- exit(1);
- }
- }
- assert(buf_len(g->libc_include_dir) != 0);
-}
-
-void find_libc_lib_path(CodeGen *g) {
- // later we can handle this better by reporting an error via the normal mechanism
- if (g->libc_lib_dir == nullptr ||
- (g->zig_target.os == OsWindows && (g->msvc_lib_dir == nullptr || g->kernel32_lib_dir == nullptr)))
- {
- if (g->zig_target.os == OsWindows) {
- ZigWindowsSDK *sdk = get_windows_sdk(g);
-
- if (g->msvc_lib_dir == nullptr) {
- if (sdk->msvc_lib_dir_ptr == nullptr) {
- fprintf(stderr, "Unable to determine vcruntime path. --msvc-lib-dir");
- exit(1);
- }
- g->msvc_lib_dir = buf_create_from_mem(sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
- }
-
- if (g->libc_lib_dir == nullptr) {
- Buf* ucrt_lib_path = buf_alloc();
- if (os_get_win32_ucrt_lib_path(sdk, ucrt_lib_path, g->zig_target.arch.arch)) {
- fprintf(stderr, "Unable to determine ucrt path. --libc-lib-dir");
- exit(1);
- }
- g->libc_lib_dir = ucrt_lib_path;
- }
-
- if (g->kernel32_lib_dir == nullptr) {
- Buf* kern_lib_path = buf_alloc();
- if (os_get_win32_kern32_path(sdk, kern_lib_path, g->zig_target.arch.arch)) {
- fprintf(stderr, "Unable to determine kernel32 path. --kernel32-lib-dir");
- exit(1);
- }
- g->kernel32_lib_dir = kern_lib_path;
- }
-
- } else if (g->zig_target.os == OsLinux) {
- g->libc_lib_dir = get_linux_libc_lib_path("crt1.o");
- } else if (g->zig_target.os == OsFreeBSD) {
- g->libc_lib_dir = buf_create_from_str("/usr/lib");
- } else {
- zig_panic("Unable to determine libc lib path.");
- }
- } else {
- assert(buf_len(g->libc_lib_dir) != 0);
- }
-
- if (g->libc_static_lib_dir == nullptr) {
- if ((g->zig_target.os == OsWindows) && (g->msvc_lib_dir != NULL)) {
- return;
- } else if (g->zig_target.os == OsLinux) {
- g->libc_static_lib_dir = get_linux_libc_lib_path("crtbegin.o");
- } else if (g->zig_target.os == OsFreeBSD) {
- g->libc_static_lib_dir = buf_create_from_str("/usr/lib");
- } else {
- zig_panic("Unable to determine libc static lib path.");
- }
- } else {
- assert(buf_len(g->libc_static_lib_dir) != 0);
- }
-}
-
static uint32_t hash_ptr(void *ptr) {
return (uint32_t)(((uintptr_t)ptr) % UINT32_MAX);
}
@@ -5229,6 +5129,10 @@ bool type_has_bits(ZigType *type_entry) {
// Whether you can infer the value based solely on the type.
OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
assert(type_entry != nullptr);
+
+ if (type_entry->one_possible_value != OnePossibleValueInvalid)
+ return type_entry->one_possible_value;
+
Error err;
if ((err = type_resolve(g, type_entry, ResolveStatusZeroBitsKnown)))
return OnePossibleValueInvalid;
@@ -5276,8 +5180,14 @@ OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry) {
case ZigTypeIdInt:
case ZigTypeIdVector:
return type_has_bits(type_entry) ? OnePossibleValueNo : OnePossibleValueYes;
- case ZigTypeIdPointer:
- return type_has_one_possible_value(g, type_entry->data.pointer.child_type);
+ case ZigTypeIdPointer: {
+ ZigType *elem_type = type_entry->data.pointer.child_type;
+ // If the recursive function call asks, then we are not one possible value.
+ type_entry->one_possible_value = OnePossibleValueNo;
+ // Now update it to be the value of the recursive call.
+ type_entry->one_possible_value = type_has_one_possible_value(g, elem_type);
+ return type_entry->one_possible_value;
+ }
case ZigTypeIdUnion:
if (type_entry->data.unionation.src_field_count > 1)
return OnePossibleValueNo;
@@ -6010,16 +5920,20 @@ static void render_const_val_err_set(CodeGen *g, Buf *buf, ConstExprValue *const
}
}
-static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_val, size_t len) {
- switch (const_val->data.x_array.special) {
+static void render_const_val_array(CodeGen *g, Buf *buf, Buf *type_name, ConstExprValue *const_val, uint64_t start, uint64_t len) {
+ ConstArrayValue *array = &const_val->data.x_array;
+ switch (array->special) {
case ConstArraySpecialUndef:
buf_append_str(buf, "undefined");
return;
case ConstArraySpecialBuf: {
- Buf *array_buf = const_val->data.x_array.data.s_buf;
+ Buf *array_buf = array->data.s_buf;
+ const char *base = &buf_ptr(array_buf)[start];
+ assert(start + len <= buf_len(array_buf));
+
buf_append_char(buf, '"');
- for (size_t i = 0; i < buf_len(array_buf); i += 1) {
- uint8_t c = buf_ptr(array_buf)[i];
+ for (size_t i = 0; i < len; i += 1) {
+ uint8_t c = base[i];
if (c == '"') {
buf_append_str(buf, "\\\"");
} else {
@@ -6030,12 +5944,13 @@ static void render_const_val_array(CodeGen *g, Buf *buf, ConstExprValue *const_v
return;
}
case ConstArraySpecialNone: {
- buf_appendf(buf, "%s{", buf_ptr(&const_val->type->name));
+ ConstExprValue *base = &array->data.s_none.elements[start];
+ assert(start + len <= const_val->type->data.array.len);
+
+ buf_appendf(buf, "%s{", buf_ptr(type_name));
for (uint64_t i = 0; i < len; i += 1) {
- if (i != 0)
- buf_appendf(buf, ",");
- ConstExprValue *child_value = &const_val->data.x_array.data.s_none.elements[i];
- render_const_value(g, buf, child_value);
+ if (i != 0) buf_appendf(buf, ",");
+ render_const_value(g, buf, &base[i]);
}
buf_appendf(buf, "}");
return;
@@ -6124,10 +6039,16 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
}
case ZigTypeIdPointer:
return render_const_val_ptr(g, buf, const_val, type_entry);
- case ZigTypeIdVector:
- return render_const_val_array(g, buf, const_val, type_entry->data.vector.len);
- case ZigTypeIdArray:
- return render_const_val_array(g, buf, const_val, type_entry->data.array.len);
+ case ZigTypeIdArray: {
+ uint64_t len = type_entry->data.array.len;
+ render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
+ return;
+ }
+ case ZigTypeIdVector: {
+ uint32_t len = type_entry->data.vector.len;
+ render_const_val_array(g, buf, &type_entry->name, const_val, 0, len);
+ return;
+ }
case ZigTypeIdNull:
{
buf_appendf(buf, "null");
@@ -6169,7 +6090,24 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
}
case ZigTypeIdStruct:
{
- buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
+ if (is_slice(type_entry)) {
+ ConstExprValue *len_val = &const_val->data.x_struct.fields[slice_len_index];
+ size_t len = bigint_as_unsigned(&len_val->data.x_bigint);
+
+ ConstExprValue *ptr_val = &const_val->data.x_struct.fields[slice_ptr_index];
+ if (ptr_val->special == ConstValSpecialUndef) {
+ assert(len == 0);
+ buf_appendf(buf, "((%s)(undefined))[0..0]", buf_ptr(&type_entry->name));
+ return;
+ }
+ assert(ptr_val->data.x_ptr.special == ConstPtrSpecialBaseArray);
+ ConstExprValue *array = ptr_val->data.x_ptr.data.base_array.array_val;
+ size_t start = ptr_val->data.x_ptr.data.base_array.elem_index;
+
+ render_const_val_array(g, buf, &type_entry->name, array, start, len);
+ } else {
+ buf_appendf(buf, "(struct %s constant)", buf_ptr(&type_entry->name));
+ }
return;
}
case ZigTypeIdEnum:
@@ -6193,8 +6131,8 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
}
case ZigTypeIdUnion:
{
- uint64_t tag = bigint_as_unsigned(&const_val->data.x_union.tag);
- TypeUnionField *field = &type_entry->data.unionation.fields[tag];
+ const BigInt *tag = &const_val->data.x_union.tag;
+ TypeUnionField *field = find_union_field_by_tag(type_entry, tag);
buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name));
render_const_value(g, buf, const_val->data.x_union.payload);
buf_append_str(buf, "}");
@@ -6277,6 +6215,7 @@ uint32_t type_id_hash(TypeId x) {
((x.data.pointer.ptr_len == PtrLenSingle) ? (uint32_t)1120226602 : (uint32_t)3200913342) +
(x.data.pointer.is_const ? (uint32_t)2749109194 : (uint32_t)4047371087) +
(x.data.pointer.is_volatile ? (uint32_t)536730450 : (uint32_t)1685612214) +
+ (x.data.pointer.allow_zero ? (uint32_t)3324284834 : (uint32_t)3584904923) +
(((uint32_t)x.data.pointer.alignment) ^ (uint32_t)0x777fbe0e) +
(((uint32_t)x.data.pointer.bit_offset_in_host) ^ (uint32_t)2639019452) +
(((uint32_t)x.data.pointer.host_int_bytes) ^ (uint32_t)529908881);
@@ -6327,6 +6266,7 @@ bool type_id_eql(TypeId a, TypeId b) {
a.data.pointer.ptr_len == b.data.pointer.ptr_len &&
a.data.pointer.is_const == b.data.pointer.is_const &&
a.data.pointer.is_volatile == b.data.pointer.is_volatile &&
+ a.data.pointer.allow_zero == b.data.pointer.allow_zero &&
a.data.pointer.alignment == b.data.pointer.alignment &&
a.data.pointer.bit_offset_in_host == b.data.pointer.bit_offset_in_host &&
a.data.pointer.host_int_bytes == b.data.pointer.host_int_bytes;
@@ -6626,12 +6566,6 @@ LinkLib *add_link_lib(CodeGen *g, Buf *name) {
if (is_libc && g->libc_link_lib != nullptr)
return g->libc_link_lib;
- if (g->enable_cache && is_libc && g->zig_target.os != OsMacOSX && g->zig_target.os != OsIOS && g->zig_target.os != OsFreeBSD) {
- fprintf(stderr, "TODO linking against libc is currently incompatible with `--cache on`.\n"
- "Zig is not yet capable of determining whether the libc installation has changed on subsequent builds.\n");
- exit(1);
- }
-
for (size_t i = 0; i < g->link_libs_list.length; i += 1) {
LinkLib *existing_lib = g->link_libs_list.at(i);
if (buf_eql_buf(existing_lib->name, name)) {
@@ -6860,3 +6794,21 @@ Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_no
return ErrorNone;
}
+
+const char *container_string(ContainerKind kind) {
+ switch (kind) {
+ case ContainerKindEnum: return "enum";
+ case ContainerKindStruct: return "struct";
+ case ContainerKindUnion: return "union";
+ }
+ zig_unreachable();
+}
+
+bool ptr_allows_addr_zero(ZigType *ptr_type) {
+ if (ptr_type->id == ZigTypeIdPointer) {
+ return ptr_type->data.pointer.allow_zero;
+ } else if (ptr_type->id == ZigTypeIdOptional) {
+ return true;
+ }
+ return false;
+}
diff --git a/src/analyze.hpp b/src/analyze.hpp
index 9773782510..e8838ae57e 100644
--- a/src/analyze.hpp
+++ b/src/analyze.hpp
@@ -40,11 +40,11 @@ ZigType *get_promise_type(CodeGen *g, ZigType *result_type);
ZigType *get_promise_frame_type(CodeGen *g, ZigType *return_type);
ZigType *get_test_fn_type(CodeGen *g);
bool handle_is_ptr(ZigType *type_entry);
-void find_libc_include_path(CodeGen *g);
-void find_libc_lib_path(CodeGen *g);
bool type_has_bits(ZigType *type_entry);
-
+bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry);
+bool ptr_allows_addr_zero(ZigType *ptr_type);
+bool type_is_nonnull_ptr(ZigType *type);
ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package, Buf *abs_full_path, Buf *source_code);
@@ -215,6 +215,7 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk);
X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty);
bool type_is_c_abi_int(CodeGen *g, ZigType *ty);
bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id);
+const char *container_string(ContainerKind kind);
uint32_t get_host_int_bytes(CodeGen *g, ZigType *struct_type, TypeStructField *field);
@@ -225,14 +226,10 @@ enum ReqCompTime {
};
ReqCompTime type_requires_comptime(CodeGen *g, ZigType *type_entry);
-enum OnePossibleValue {
- OnePossibleValueInvalid,
- OnePossibleValueNo,
- OnePossibleValueYes,
-};
OnePossibleValue type_has_one_possible_value(CodeGen *g, ZigType *type_entry);
Error ensure_const_val_repr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
ConstExprValue *const_val, ZigType *wanted_type);
+void typecheck_panic_fn(CodeGen *g, TldFn *tld_fn, ZigFn *panic_fn);
#endif
diff --git a/src/ast_render.cpp b/src/ast_render.cpp
index 34a7faa2a5..7b57841205 100644
--- a/src/ast_render.cpp
+++ b/src/ast_render.cpp
@@ -136,13 +136,19 @@ static const char *thread_local_string(Token *tok) {
return (tok == nullptr) ? "" : "threadlocal ";
}
-const char *container_string(ContainerKind kind) {
- switch (kind) {
- case ContainerKindEnum: return "enum";
- case ContainerKindStruct: return "struct";
- case ContainerKindUnion: return "union";
+static const char *token_to_ptr_len_str(Token *tok) {
+ assert(tok != nullptr);
+ switch (tok->id) {
+ case TokenIdStar:
+ case TokenIdStarStar:
+ return "*";
+ case TokenIdBracketStarBracket:
+ return "[*]";
+ case TokenIdBracketStarCBracket:
+ return "[*c]";
+ default:
+ zig_unreachable();
}
- zig_unreachable();
}
static const char *node_type_str(NodeType node_type) {
@@ -644,13 +650,8 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
case NodeTypePointerType:
{
if (!grouped) fprintf(ar->f, "(");
- const char *star = "[*]";
- if (node->data.pointer_type.star_token != nullptr &&
- (node->data.pointer_type.star_token->id == TokenIdStar || node->data.pointer_type.star_token->id == TokenIdStarStar))
- {
- star = "*";
- }
- fprintf(ar->f, "%s", star);
+ const char *ptr_len_str = token_to_ptr_len_str(node->data.pointer_type.star_token);
+ fprintf(ar->f, "%s", ptr_len_str);
if (node->data.pointer_type.align_expr != nullptr) {
fprintf(ar->f, "align(");
render_node_grouped(ar, node->data.pointer_type.align_expr);
diff --git a/src/ast_render.hpp b/src/ast_render.hpp
index d37002d8c7..1652156eee 100644
--- a/src/ast_render.hpp
+++ b/src/ast_render.hpp
@@ -17,7 +17,4 @@ void ast_print(FILE *f, AstNode *node, int indent);
void ast_render(CodeGen *codegen, FILE *f, AstNode *node, int indent_size);
-const char *container_string(ContainerKind kind);
-
#endif
-
diff --git a/src/bigint.cpp b/src/bigint.cpp
index 7299f2379c..4c103adce3 100644
--- a/src/bigint.cpp
+++ b/src/bigint.cpp
@@ -1665,7 +1665,6 @@ int64_t bigint_as_signed(const BigInt *bigint) {
return 0;
} else if (bigint->digit_count == 1) {
if (bigint->is_negative) {
- // TODO this code path is untested
if (bigint->data.digit <= 9223372036854775808ULL) {
return (-((int64_t)(bigint->data.digit - 1))) - 1;
} else {
diff --git a/src/buffer.hpp b/src/buffer.hpp
index afe9fd8a91..e286f7dc63 100644
--- a/src/buffer.hpp
+++ b/src/buffer.hpp
@@ -132,9 +132,7 @@ void buf_appendf(Buf *buf, const char *format, ...)
static inline bool buf_eql_mem(Buf *buf, const char *mem, size_t mem_len) {
assert(buf->list.length);
- if (buf_len(buf) != mem_len)
- return false;
- return memcmp(buf_ptr(buf), mem, mem_len) == 0;
+ return mem_eql_mem(buf_ptr(buf), buf_len(buf), mem, mem_len);
}
static inline bool buf_eql_str(Buf *buf, const char *str) {
diff --git a/src/cache_hash.cpp b/src/cache_hash.cpp
index 4526a83c27..85bad3dd2d 100644
--- a/src/cache_hash.cpp
+++ b/src/cache_hash.cpp
@@ -414,6 +414,39 @@ Error cache_add_file(CacheHash *ch, Buf *path) {
return cache_add_file_fetch(ch, resolved_path, nullptr);
}
+Error cache_add_dep_file(CacheHash *ch, Buf *dep_file_path, bool verbose) {
+ Error err;
+ Buf *contents = buf_alloc();
+ if ((err = os_fetch_file_path(dep_file_path, contents, false))) {
+ if (verbose) {
+ fprintf(stderr, "unable to read .d file: %s\n", err_str(err));
+ }
+ return ErrorReadingDepFile;
+ }
+ SplitIterator it = memSplit(buf_to_slice(contents), str("\n"));
+ // skip first line
+ SplitIterator_next(&it);
+ for (;;) {
+ Optional> opt_line = SplitIterator_next(&it);
+ if (!opt_line.is_some)
+ break;
+ if (opt_line.value.len == 0)
+ continue;
+ SplitIterator line_it = memSplit(opt_line.value, str(" \t"));
+ Slice filename;
+ if (!SplitIterator_next(&line_it).unwrap(&filename))
+ continue;
+ Buf *filename_buf = buf_create_from_slice(filename);
+ if ((err = cache_add_file(ch, filename_buf))) {
+ if (verbose) {
+ fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(filename_buf), err_str(err));
+ }
+ return err;
+ }
+ }
+ return ErrorNone;
+}
+
static Error write_manifest_file(CacheHash *ch) {
Error err;
Buf contents = BUF_INIT;
@@ -464,3 +497,4 @@ void cache_release(CacheHash *ch) {
os_file_close(ch->manifest_file);
}
+
diff --git a/src/cache_hash.hpp b/src/cache_hash.hpp
index db1c42ec03..d74c8623ce 100644
--- a/src/cache_hash.hpp
+++ b/src/cache_hash.hpp
@@ -56,6 +56,8 @@ Error ATTRIBUTE_MUST_USE cache_hit(CacheHash *ch, Buf *out_b64_digest);
// If you did not get a cache hit, call this function for every file
// that is depended on, and then finish with cache_final.
Error ATTRIBUTE_MUST_USE cache_add_file(CacheHash *ch, Buf *path);
+// This opens a file created by -MD -MF args to Clang
+Error ATTRIBUTE_MUST_USE cache_add_dep_file(CacheHash *ch, Buf *path, bool verbose);
// This variant of cache_add_file returns the file contents.
// Also the file path argument must be already resolved.
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 9a81a5a1c9..ee63318eb8 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -29,9 +29,9 @@ static void init_darwin_native(CodeGen *g) {
// Allow conflicts among OSX and iOS, but choose the default platform.
if (osx_target && ios_target) {
- if (g->zig_target.arch.arch == ZigLLVM_arm ||
- g->zig_target.arch.arch == ZigLLVM_aarch64 ||
- g->zig_target.arch.arch == ZigLLVM_thumb)
+ if (g->zig_target->arch == ZigLLVM_arm ||
+ g->zig_target->arch == ZigLLVM_aarch64 ||
+ g->zig_target->arch == ZigLLVM_thumb)
{
osx_target = nullptr;
} else {
@@ -43,7 +43,7 @@ static void init_darwin_native(CodeGen *g) {
g->mmacosx_version_min = buf_create_from_str(osx_target);
} else if (ios_target) {
g->mios_version_min = buf_create_from_str(ios_target);
- } else if (g->zig_target.os != OsIOS) {
+ } else if (g->zig_target->os != OsIOS) {
g->mmacosx_version_min = buf_create_from_str("10.10");
}
}
@@ -88,13 +88,15 @@ static const char *symbols_that_llvm_depends_on[] = {
};
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
- Buf *zig_lib_dir, Buf *override_std_dir)
+ Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc)
{
CodeGen *g = allocate(1);
codegen_add_time_event(g, "Initialize");
+ g->libc = libc;
g->zig_lib_dir = zig_lib_dir;
+ g->zig_target = target;
if (override_std_dir == nullptr) {
g->zig_std_dir = buf_alloc();
@@ -149,43 +151,19 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
g->zig_std_special_dir = buf_alloc();
os_path_join(g->zig_std_dir, buf_sprintf("special"), g->zig_std_special_dir);
- if (target) {
- // cross compiling, so we can't rely on all the configured stuff since
- // that's for native compilation
- g->zig_target = *target;
- resolve_target_object_format(&g->zig_target);
- g->dynamic_linker = nullptr;
- g->libc_lib_dir = nullptr;
- g->libc_static_lib_dir = nullptr;
- g->libc_include_dir = nullptr;
- g->msvc_lib_dir = nullptr;
- g->kernel32_lib_dir = nullptr;
+ assert(target != nullptr);
+ if (!target->is_native) {
g->each_lib_rpath = false;
} else {
- // native compilation, we can rely on the configuration stuff
- g->is_native_target = true;
- get_native_target(&g->zig_target);
- g->dynamic_linker = nullptr; // find it at runtime
- g->libc_lib_dir = nullptr; // find it at runtime
- g->libc_static_lib_dir = nullptr; // find it at runtime
- g->libc_include_dir = nullptr; // find it at runtime
- g->msvc_lib_dir = nullptr; // find it at runtime
- g->kernel32_lib_dir = nullptr; // find it at runtime
g->each_lib_rpath = true;
- if (g->zig_target.os == OsMacOSX ||
- g->zig_target.os == OsIOS)
- {
+ if (target_is_darwin(g->zig_target)) {
init_darwin_native(g);
}
}
- // On Darwin/MacOS/iOS, we always link libSystem which contains libc.
- if (g->zig_target.os == OsMacOSX ||
- g->zig_target.os == OsIOS ||
- g->zig_target.os == OsFreeBSD)
- {
+ if (target_requires_libc(g->zig_target)) {
g->libc_link_lib = create_link_lib(buf_create_from_str("c"));
g->link_libs_list.append(g->libc_link_lib);
}
@@ -197,6 +175,10 @@ void codegen_set_output_h_path(CodeGen *g, Buf *h_path) {
g->out_h_path = h_path;
}
+void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path) {
+ g->out_lib_path = lib_path;
+}
+
void codegen_set_output_path(CodeGen *g, Buf *path) {
g->wanted_output_file_path = path;
}
@@ -253,30 +235,6 @@ void codegen_set_out_name(CodeGen *g, Buf *out_name) {
g->root_out_name = out_name;
}
-void codegen_set_libc_lib_dir(CodeGen *g, Buf *libc_lib_dir) {
- g->libc_lib_dir = libc_lib_dir;
-}
-
-void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir) {
- g->libc_static_lib_dir = libc_static_lib_dir;
-}
-
-void codegen_set_libc_include_dir(CodeGen *g, Buf *libc_include_dir) {
- g->libc_include_dir = libc_include_dir;
-}
-
-void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir) {
- g->msvc_lib_dir = msvc_lib_dir;
-}
-
-void codegen_set_kernel32_lib_dir(CodeGen *g, Buf *kernel32_lib_dir) {
- g->kernel32_lib_dir = kernel32_lib_dir;
-}
-
-void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker) {
- g->dynamic_linker = dynamic_linker;
-}
-
void codegen_add_lib_dir(CodeGen *g, const char *dir) {
g->lib_dirs.append(dir);
}
@@ -389,11 +347,11 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
case CallingConventionC: return LLVMCCallConv;
case CallingConventionCold:
// cold calling convention only works on x86.
- if (g->zig_target.arch.arch == ZigLLVM_x86 ||
- g->zig_target.arch.arch == ZigLLVM_x86_64)
+ if (g->zig_target->arch == ZigLLVM_x86 ||
+ g->zig_target->arch == ZigLLVM_x86_64)
{
// cold calling convention is not supported on windows
- if (g->zig_target.os == OsWindows) {
+ if (g->zig_target->os == OsWindows) {
return LLVMCCallConv;
} else {
return LLVMColdCallConv;
@@ -406,7 +364,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
zig_unreachable();
case CallingConventionStdcall:
// stdcall calling convention only works on x86.
- if (g->zig_target.arch.arch == ZigLLVM_x86) {
+ if (g->zig_target->arch == ZigLLVM_x86) {
return LLVMX86StdcallCallConv;
} else {
return LLVMCCallConv;
@@ -418,7 +376,7 @@ static LLVMCallConv get_llvm_cc(CodeGen *g, CallingConvention cc) {
}
static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) {
- if (g->zig_target.os == OsWindows) {
+ if (g->zig_target->os == OsWindows) {
addLLVMFnAttr(fn_val, "uwtable");
}
}
@@ -454,13 +412,13 @@ static uint32_t get_err_ret_trace_arg_index(CodeGen *g, ZigFn *fn_table_entry) {
}
static void maybe_export_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
- if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) {
+ if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) {
LLVMSetDLLStorageClass(global_value, LLVMDLLExportStorageClass);
}
}
static void maybe_import_dll(CodeGen *g, LLVMValueRef global_value, GlobalLinkageId linkage) {
- if (linkage != GlobalLinkageIdInternal && g->zig_target.os == OsWindows) {
+ if (linkage != GlobalLinkageIdInternal && g->zig_target->os == OsWindows) {
// TODO come up with a good explanation/understanding for why we never do
// DLLImportStorageClass. Empirically it only causes problems. But let's have
// this documented and then clean up the code accordingly.
@@ -505,7 +463,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
bool external_linkage = linkage != GlobalLinkageIdInternal;
CallingConvention cc = fn_table_entry->type_entry->data.fn.fn_type_id.cc;
if (cc == CallingConventionStdcall && external_linkage &&
- g->zig_target.arch.arch == ZigLLVM_x86)
+ g->zig_target->arch == ZigLLVM_x86)
{
// prevent llvm name mangling
symbol_name = buf_sprintf("\x01_%s", buf_ptr(symbol_name));
@@ -520,10 +478,23 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
fn_table_entry->llvm_value = LLVMConstBitCast(existing_llvm_fn, LLVMPointerType(fn_llvm_type, 0));
return fn_table_entry->llvm_value;
} else {
- fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
+ auto entry = g->exported_symbol_names.maybe_get(symbol_name);
+ if (entry == nullptr) {
+ fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
+ } else {
+ assert(entry->value->id == TldIdFn);
+ TldFn *tld_fn = reinterpret_cast(entry->value);
+ tld_fn->fn_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name),
+ tld_fn->fn_entry->type_entry->data.fn.raw_type_ref);
+ fn_table_entry->llvm_value = LLVMConstBitCast(tld_fn->fn_entry->llvm_value,
+ LLVMPointerType(fn_llvm_type, 0));
+ return fn_table_entry->llvm_value;
+ }
}
} else {
- fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
+ if (fn_table_entry->llvm_value == nullptr) {
+ fn_table_entry->llvm_value = LLVMAddFunction(g->module, buf_ptr(symbol_name), fn_llvm_type);
+ }
for (size_t i = 1; i < fn_table_entry->export_list.length; i += 1) {
FnExport *fn_export = &fn_table_entry->export_list.items[i];
@@ -617,9 +588,10 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
unsigned init_gen_i = 0;
if (!type_has_bits(return_type)) {
// nothing to do
- } else if (type_is_codegen_pointer(return_type)) {
+ } else if (type_is_nonnull_ptr(return_type)) {
addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull");
} else if (want_first_arg_sret(g, &fn_type->data.fn.fn_type_id)) {
+ // Sret pointers must not be address 0
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "nonnull");
addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret");
if (cc_want_sret_attr(cc)) {
@@ -637,6 +609,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, ZigFn *fn_table_entry) {
uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
if (err_ret_trace_arg_index != UINT32_MAX) {
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
}
@@ -950,6 +924,8 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) {
return buf_create_from_str("invalid enum value");
case PanicMsgIdFloatToInt:
return buf_create_from_str("integer part of floating point value out of bounds");
+ case PanicMsgIdPtrCastNull:
+ return buf_create_from_str("cast causes pointer to be null");
}
zig_unreachable();
}
@@ -1244,6 +1220,8 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) {
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
addLLVMFnAttr(fn_val, "nounwind");
add_uwtable_attr(g, fn_val);
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
if (g->build_mode == BuildModeDebug) {
ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
@@ -1318,9 +1296,13 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) {
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
addLLVMFnAttr(fn_val, "nounwind");
add_uwtable_attr(g, fn_val);
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
addLLVMArgAttr(fn_val, (unsigned)0, "noalias");
addLLVMArgAttr(fn_val, (unsigned)0, "writeonly");
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_val, (unsigned)1, "nonnull");
addLLVMArgAttr(fn_val, (unsigned)1, "noalias");
addLLVMArgAttr(fn_val, (unsigned)1, "readonly");
@@ -1448,6 +1430,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) {
LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified));
addLLVMFnAttr(fn_val, "nounwind");
add_uwtable_attr(g, fn_val);
+ // Error return trace memory is in the stack, which is impossible to be at address 0
+ // on any architecture.
addLLVMArgAttr(fn_val, (unsigned)0, "nonnull");
if (g->build_mode == BuildModeDebug) {
ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
@@ -2049,7 +2033,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
case FnWalkIdAttrs: {
ZigType *ptr_type = get_codegen_ptr_type(ty);
if (ptr_type != nullptr) {
- if (ty->id != ZigTypeIdOptional) {
+ if (type_is_nonnull_ptr(ty)) {
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
}
if (ptr_type->data.pointer.is_const) {
@@ -2093,6 +2077,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
assert(handle_is_ptr(ty));
switch (fn_walk->id) {
case FnWalkIdAttrs:
+ // arrays passed to C ABI functions may not be at address 0
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
fn_walk->data.attrs.gen_i += 1;
@@ -2123,7 +2108,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
return true;
}
- if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
+ if (g->zig_target->arch == ZigLLVM_x86_64) {
X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);
size_t ty_size = type_size(g, ty);
if (abi_class == X64CABIClass_MEMORY) {
@@ -2132,6 +2117,7 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
case FnWalkIdAttrs:
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval");
addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
+ // Byvalue parameters must not have address 0
addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
fn_walk->data.attrs.gen_i += 1;
break;
@@ -2264,7 +2250,10 @@ void walk_function_params(CodeGen *g, ZigType *fn_type, FnWalk *fn_walk) {
if ((param_type->id == ZigTypeIdPointer && param_type->data.pointer.is_const) || is_byval) {
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "readonly");
}
- if (param_type->id == ZigTypeIdPointer) {
+ if (get_codegen_ptr_type(param_type) != nullptr) {
+ addLLVMArgAttrInt(llvm_fn, (unsigned)gen_index, "align", get_ptr_align(g, param_type));
+ }
+ if (type_is_nonnull_ptr(param_type)) {
addLLVMArgAttr(llvm_fn, (unsigned)gen_index, "nonnull");
}
break;
@@ -2657,7 +2646,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
(op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) ||
(op1->value.type->id == ZigTypeIdPointer &&
(op_id == IrBinOpAdd || op_id == IrBinOpSub) &&
- op1->value.type->data.pointer.ptr_len == PtrLenUnknown)
+ op1->value.type->data.pointer.ptr_len != PtrLenSingle)
);
ZigType *operand_type = op1->value.type;
ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
@@ -2716,7 +2705,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
AddSubMulMul;
if (scalar_type->id == ZigTypeIdPointer) {
- assert(scalar_type->data.pointer.ptr_len == PtrLenUnknown);
+ assert(scalar_type->data.pointer.ptr_len != PtrLenSingle);
LLVMValueRef subscript_value;
if (operand_type->id == ZigTypeIdVector)
zig_panic("TODO: Implement vector operations on pointers.");
@@ -2863,6 +2852,76 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in
}
}
+static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutable *executable,
+ IrInstructionResizeSlice *instruction)
+{
+ ZigType *actual_type = instruction->operand->value.type;
+ ZigType *wanted_type = instruction->base.value.type;
+ LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand);
+ assert(expr_val);
+
+ assert(instruction->tmp_ptr);
+ assert(wanted_type->id == ZigTypeIdStruct);
+ assert(wanted_type->data.structure.is_slice);
+ assert(actual_type->id == ZigTypeIdStruct);
+ assert(actual_type->data.structure.is_slice);
+
+ ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
+ ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type;
+ ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
+ ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
+
+
+ size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index;
+ size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index;
+ size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index;
+ size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index;
+
+ LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, "");
+ LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, "");
+ LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
+ wanted_type->data.structure.fields[0].type_entry->type_ref, "");
+ LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
+ (unsigned)wanted_ptr_index, "");
+ gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
+
+ LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, "");
+ LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, "");
+ uint64_t src_size = type_size(g, actual_child_type);
+ uint64_t dest_size = type_size(g, wanted_child_type);
+
+ LLVMValueRef new_len;
+ if (dest_size == 1) {
+ LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false);
+ new_len = LLVMBuildMul(g->builder, src_len, src_size_val, "");
+ } else if (src_size == 1) {
+ LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false);
+ if (ir_want_runtime_safety(g, &instruction->base)) {
+ LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, "");
+ LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref);
+ LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk");
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail");
+ LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, fail_block);
+ gen_safety_crash(g, PanicMsgIdSliceWidenRemainder);
+
+ LLVMPositionBuilderAtEnd(g->builder, ok_block);
+ }
+ new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, "");
+ } else {
+ zig_unreachable();
+ }
+
+ LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, instruction->tmp_ptr,
+ (unsigned)wanted_len_index, "");
+ gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
+
+
+ return instruction->tmp_ptr;
+}
+
static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
IrInstructionCast *cast_instruction)
{
@@ -2877,69 +2936,6 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
zig_unreachable();
case CastOpNoop:
return expr_val;
- case CastOpResizeSlice:
- {
- assert(cast_instruction->tmp_ptr);
- assert(wanted_type->id == ZigTypeIdStruct);
- assert(wanted_type->data.structure.is_slice);
- assert(actual_type->id == ZigTypeIdStruct);
- assert(actual_type->data.structure.is_slice);
-
- ZigType *actual_pointer_type = actual_type->data.structure.fields[0].type_entry;
- ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type;
- ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0].type_entry;
- ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type;
-
-
- size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index].gen_index;
- size_t actual_len_index = actual_type->data.structure.fields[slice_len_index].gen_index;
- size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index].gen_index;
- size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index].gen_index;
-
- LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, "");
- LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, "");
- LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr,
- wanted_type->data.structure.fields[0].type_entry->type_ref, "");
- LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
- (unsigned)wanted_ptr_index, "");
- gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false);
-
- LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, "");
- LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, "");
- uint64_t src_size = type_size(g, actual_child_type);
- uint64_t dest_size = type_size(g, wanted_child_type);
-
- LLVMValueRef new_len;
- if (dest_size == 1) {
- LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, src_size, false);
- new_len = LLVMBuildMul(g->builder, src_len, src_size_val, "");
- } else if (src_size == 1) {
- LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->type_ref, dest_size, false);
- if (ir_want_runtime_safety(g, &cast_instruction->base)) {
- LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, "");
- LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->type_ref);
- LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, "");
- LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk");
- LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail");
- LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
-
- LLVMPositionBuilderAtEnd(g->builder, fail_block);
- gen_safety_crash(g, PanicMsgIdSliceWidenRemainder);
-
- LLVMPositionBuilderAtEnd(g->builder, ok_block);
- }
- new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, "");
- } else {
- zig_unreachable();
- }
-
- LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, cast_instruction->tmp_ptr,
- (unsigned)wanted_len_index, "");
- gen_store_untyped(g, new_len, dest_len_ptr, 0, false);
-
-
- return cast_instruction->tmp_ptr;
- }
case CastOpIntToFloat:
assert(actual_type->id == ZigTypeIdInt);
if (actual_type->data.integral.is_signed) {
@@ -3028,15 +3024,51 @@ static LLVMValueRef ir_render_ptr_cast(CodeGen *g, IrExecutable *executable,
return nullptr;
}
LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr);
- return LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
+ LLVMValueRef result_ptr = LLVMBuildBitCast(g->builder, ptr, wanted_type->type_ref, "");
+ bool want_safety_check = instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base);
+ if (!want_safety_check || ptr_allows_addr_zero(wanted_type))
+ return result_ptr;
+
+ LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(result_ptr));
+ LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntNE, result_ptr, zero, "");
+ LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastFail");
+ LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "PtrCastOk");
+ LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
+
+ LLVMPositionBuilderAtEnd(g->builder, fail_block);
+ gen_safety_crash(g, PanicMsgIdPtrCastNull);
+
+ LLVMPositionBuilderAtEnd(g->builder, ok_block);
+ return result_ptr;
}
static LLVMValueRef ir_render_bit_cast(CodeGen *g, IrExecutable *executable,
- IrInstructionBitCast *instruction)
+ IrInstructionBitCastGen *instruction)
{
ZigType *wanted_type = instruction->base.value.type;
- LLVMValueRef value = ir_llvm_value(g, instruction->value);
- return LLVMBuildBitCast(g->builder, value, wanted_type->type_ref, "");
+ ZigType *actual_type = instruction->operand->value.type;
+ LLVMValueRef value = ir_llvm_value(g, instruction->operand);
+
+ bool wanted_is_ptr = handle_is_ptr(wanted_type);
+ bool actual_is_ptr = handle_is_ptr(actual_type);
+ if (wanted_is_ptr == actual_is_ptr) {
+ // We either bitcast the value directly or bitcast the pointer which does a pointer cast
+ LLVMTypeRef wanted_type_ref = wanted_is_ptr ?
+ LLVMPointerType(wanted_type->type_ref, 0) : wanted_type->type_ref;
+ return LLVMBuildBitCast(g->builder, value, wanted_type_ref, "");
+ } else if (actual_is_ptr) {
+ LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(wanted_type->type_ref, 0);
+ LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, "");
+ uint32_t alignment = get_abi_alignment(g, actual_type);
+ return gen_load_untyped(g, bitcasted_ptr, alignment, false, "");
+ } else {
+ assert(instruction->tmp_ptr != nullptr);
+ LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(actual_type->type_ref, 0);
+ LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr, wanted_ptr_type_ref, "");
+ uint32_t alignment = get_abi_alignment(g, wanted_type);
+ gen_store_untyped(g, value, bitcasted_ptr, alignment, false);
+ return instruction->tmp_ptr;
+ }
}
static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutable *executable,
@@ -3167,7 +3199,8 @@ static LLVMValueRef ir_render_br(CodeGen *g, IrExecutable *executable, IrInstruc
static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInstructionUnOp *un_op_instruction) {
IrUnOp op_id = un_op_instruction->op_id;
LLVMValueRef expr = ir_llvm_value(g, un_op_instruction->value);
- ZigType *expr_type = un_op_instruction->value->value.type;
+ ZigType *operand_type = un_op_instruction->value->value.type;
+ ZigType *scalar_type = (operand_type->id == ZigTypeIdVector) ? operand_type->data.vector.elem_type : operand_type;
switch (op_id) {
case IrUnOpInvalid:
@@ -3177,16 +3210,16 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
case IrUnOpNegation:
case IrUnOpNegationWrap:
{
- if (expr_type->id == ZigTypeIdFloat) {
+ if (scalar_type->id == ZigTypeIdFloat) {
ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &un_op_instruction->base));
return LLVMBuildFNeg(g->builder, expr, "");
- } else if (expr_type->id == ZigTypeIdInt) {
+ } else if (scalar_type->id == ZigTypeIdInt) {
if (op_id == IrUnOpNegationWrap) {
return LLVMBuildNeg(g->builder, expr, "");
} else if (ir_want_runtime_safety(g, &un_op_instruction->base)) {
LLVMValueRef zero = LLVMConstNull(LLVMTypeOf(expr));
- return gen_overflow_op(g, expr_type, AddSubMulSub, zero, expr);
- } else if (expr_type->data.integral.is_signed) {
+ return gen_overflow_op(g, operand_type, AddSubMulSub, zero, expr);
+ } else if (scalar_type->data.integral.is_signed) {
return LLVMBuildNSWNeg(g->builder, expr, "");
} else {
return LLVMBuildNUWNeg(g->builder, expr, "");
@@ -3237,7 +3270,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
return nullptr;
}
-static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtr *instruction) {
+static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrInstructionLoadPtrGen *instruction) {
ZigType *child_type = instruction->base.value.type;
if (!type_has_bits(child_type))
return nullptr;
@@ -3252,7 +3285,6 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
bool big_endian = g->is_big_endian;
- assert(!handle_is_ptr(child_type));
LLVMValueRef containing_int = gen_load(g, ptr, ptr_type, "");
uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int));
assert(host_bit_count == host_int_bytes * 8);
@@ -3264,7 +3296,16 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI
LLVMValueRef shift_amt_val = LLVMConstInt(LLVMTypeOf(containing_int), shift_amt, false);
LLVMValueRef shifted_value = LLVMBuildLShr(g->builder, containing_int, shift_amt_val, "");
- return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
+ if (!handle_is_ptr(child_type))
+ return LLVMBuildTrunc(g->builder, shifted_value, child_type->type_ref, "");
+
+ assert(instruction->tmp_ptr != nullptr);
+ LLVMTypeRef same_size_int = LLVMIntType(size_in_bits);
+ LLVMValueRef truncated_int = LLVMBuildTrunc(g->builder, shifted_value, same_size_int, "");
+ LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, instruction->tmp_ptr,
+ LLVMPointerType(same_size_int, 0), "");
+ LLVMBuildStore(g->builder, truncated_int, bitcasted_ptr);
+ return instruction->tmp_ptr;
}
static bool value_is_all_undef_array(ConstExprValue *const_val, size_t len) {
@@ -3307,6 +3348,77 @@ static bool value_is_all_undef(ConstExprValue *const_val) {
zig_unreachable();
}
+static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default_value, LLVMValueRef request,
+ LLVMValueRef a1, LLVMValueRef a2, LLVMValueRef a3, LLVMValueRef a4, LLVMValueRef a5)
+{
+ if (!target_has_valgrind_support(g->zig_target)) {
+ return default_value;
+ }
+ LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref;
+ bool asm_has_side_effects = true;
+ bool asm_is_alignstack = false;
+ if (g->zig_target->arch == ZigLLVM_x86_64) {
+ if (g->zig_target->os == OsLinux || target_is_darwin(g->zig_target) || g->zig_target->os == OsSolaris ||
+ (g->zig_target->os == OsWindows && g->zig_target->abi != ZigLLVM_MSVC))
+ {
+ if (g->cur_fn->valgrind_client_request_array == nullptr) {
+ LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder);
+ LLVMBasicBlockRef entry_block = LLVMGetEntryBasicBlock(g->cur_fn->llvm_value);
+ LLVMValueRef first_inst = LLVMGetFirstInstruction(entry_block);
+ LLVMPositionBuilderBefore(g->builder, first_inst);
+ LLVMTypeRef array_type_ref = LLVMArrayType(usize_type_ref, 6);
+ g->cur_fn->valgrind_client_request_array = LLVMBuildAlloca(g->builder, array_type_ref, "");
+ LLVMPositionBuilderAtEnd(g->builder, prev_block);
+ }
+ LLVMValueRef array_ptr = g->cur_fn->valgrind_client_request_array;
+ LLVMValueRef array_elements[] = {request, a1, a2, a3, a4, a5};
+ LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false);
+ for (unsigned i = 0; i < 6; i += 1) {
+ LLVMValueRef indexes[] = {
+ zero,
+ LLVMConstInt(usize_type_ref, i, false),
+ };
+ LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, "");
+ LLVMBuildStore(g->builder, array_elements[i], elem_ptr);
+ }
+
+ Buf *asm_template = buf_create_from_str(
+ "rolq $$3, %rdi ; rolq $$13, %rdi\n"
+ "rolq $$61, %rdi ; rolq $$51, %rdi\n"
+ "xchgq %rbx,%rbx\n"
+ );
+ Buf *asm_constraints = buf_create_from_str(
+ "={rdx},{rax},0,~{cc},~{memory}"
+ );
+ unsigned input_and_output_count = 2;
+ LLVMValueRef array_ptr_as_usize = LLVMBuildPtrToInt(g->builder, array_ptr, usize_type_ref, "");
+ LLVMValueRef param_values[] = { array_ptr_as_usize, default_value };
+ LLVMTypeRef param_types[] = {usize_type_ref, usize_type_ref};
+ LLVMTypeRef function_type = LLVMFunctionType(usize_type_ref, param_types,
+ input_and_output_count, false);
+ LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(asm_template), buf_len(asm_template),
+ buf_ptr(asm_constraints), buf_len(asm_constraints), asm_has_side_effects, asm_is_alignstack,
+ LLVMInlineAsmDialectATT);
+ return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, "");
+ }
+ }
+ zig_unreachable();
+}
+
+static bool want_valgrind_support(CodeGen *g) {
+ if (!target_has_valgrind_support(g->zig_target))
+ return false;
+ switch (g->valgrind_support) {
+ case ValgrindSupportDisabled:
+ return false;
+ case ValgrindSupportEnabled:
+ return true;
+ case ValgrindSupportAuto:
+ return g->build_mode == BuildModeDebug;
+ }
+ zig_unreachable();
+}
+
static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_type, LLVMValueRef ptr) {
assert(type_has_bits(value_type));
uint64_t size_bytes = LLVMStoreSizeOfType(g->target_data_ref, value_type->type_ref);
@@ -3319,6 +3431,14 @@ static void gen_undef_init(CodeGen *g, uint32_t ptr_align_bytes, ZigType *value_
ZigType *usize = g->builtin_types.entry_usize;
LLVMValueRef byte_count = LLVMConstInt(usize->type_ref, size_bytes, false);
ZigLLVMBuildMemSet(g->builder, dest_ptr, fill_char, byte_count, ptr_align_bytes, false);
+ // then tell valgrind that the memory is undefined even though we just memset it
+ if (want_valgrind_support(g)) {
+ static const uint32_t VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545;
+ LLVMValueRef zero = LLVMConstInt(usize->type_ref, 0, false);
+ LLVMValueRef req = LLVMConstInt(usize->type_ref, VG_USERREQ__MAKE_MEM_UNDEFINED, false);
+ LLVMValueRef ptr_as_usize = LLVMBuildPtrToInt(g->builder, dest_ptr, usize->type_ref, "");
+ gen_valgrind_client_request(g, zero, req, ptr_as_usize, byte_count, zero, zero, zero);
+ }
}
static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) {
@@ -3479,7 +3599,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) {
LLVMValueRef write_register_fn_val = get_write_register_fn_val(g);
if (g->sp_md_node == nullptr) {
- Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(&g->zig_target.arch));
+ Buf *sp_reg_name = buf_create_from_str(arch_stack_pointer_register_name(g->zig_target->arch));
LLVMValueRef str_node = LLVMMDString(buf_ptr(sp_reg_name), buf_len(sp_reg_name) + 1);
g->sp_md_node = LLVMMDNode(&str_node, 1);
}
@@ -5337,6 +5457,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
case IrInstructionIdDeclVarSrc:
case IrInstructionIdPtrCastSrc:
case IrInstructionIdCmpxchgSrc:
+ case IrInstructionIdLoadPtr:
+ case IrInstructionIdBitCast:
zig_unreachable();
case IrInstructionIdDeclVarGen:
@@ -5355,8 +5477,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_br(g, executable, (IrInstructionBr *)instruction);
case IrInstructionIdUnOp:
return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction);
- case IrInstructionIdLoadPtr:
- return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction);
+ case IrInstructionIdLoadPtrGen:
+ return ir_render_load_ptr(g, executable, (IrInstructionLoadPtrGen *)instruction);
case IrInstructionIdStorePtr:
return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction);
case IrInstructionIdVarPtr:
@@ -5433,8 +5555,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_union_init(g, executable, (IrInstructionUnionInit *)instruction);
case IrInstructionIdPtrCastGen:
return ir_render_ptr_cast(g, executable, (IrInstructionPtrCastGen *)instruction);
- case IrInstructionIdBitCast:
- return ir_render_bit_cast(g, executable, (IrInstructionBitCast *)instruction);
+ case IrInstructionIdBitCastGen:
+ return ir_render_bit_cast(g, executable, (IrInstructionBitCastGen *)instruction);
case IrInstructionIdWidenOrShorten:
return ir_render_widen_or_shorten(g, executable, (IrInstructionWidenOrShorten *)instruction);
case IrInstructionIdPtrToInt:
@@ -5509,6 +5631,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
return ir_render_vector_to_array(g, executable, (IrInstructionVectorToArray *)instruction);
case IrInstructionIdAssertZero:
return ir_render_assert_zero(g, executable, (IrInstructionAssertZero *)instruction);
+ case IrInstructionIdResizeSlice:
+ return ir_render_resize_slice(g, executable, (IrInstructionResizeSlice *)instruction);
}
zig_unreachable();
}
@@ -5711,8 +5835,32 @@ static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, Con
LLVMValueRef ptr_size_int_val = LLVMConstPtrToInt(ptr_val, g->builtin_types.entry_usize->type_ref);
return LLVMConstZExt(ptr_size_int_val, big_int_type_ref);
}
- case ZigTypeIdArray:
- zig_panic("TODO bit pack an array");
+ case ZigTypeIdArray: {
+ LLVMValueRef val = LLVMConstInt(big_int_type_ref, 0, false);
+ if (const_val->data.x_array.special == ConstArraySpecialUndef) {
+ return val;
+ }
+ expand_undef_array(g, const_val);
+ bool is_big_endian = g->is_big_endian; // TODO get endianness from struct type
+ uint32_t packed_bits_size = type_size_bits(g, type_entry->data.array.child_type);
+ size_t used_bits = 0;
+ for (size_t i = 0; i < type_entry->data.array.len; i += 1) {
+ ConstExprValue *elem_val = &const_val->data.x_array.data.s_none.elements[i];
+ LLVMValueRef child_val = pack_const_int(g, big_int_type_ref, elem_val);
+
+ if (is_big_endian) {
+ LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, packed_bits_size, false);
+ val = LLVMConstShl(val, shift_amt);
+ val = LLVMConstOr(val, child_val);
+ } else {
+ LLVMValueRef shift_amt = LLVMConstInt(big_int_type_ref, used_bits, false);
+ LLVMValueRef child_val_shifted = LLVMConstShl(child_val, shift_amt);
+ val = LLVMConstOr(val, child_val_shifted);
+ used_bits += packed_bits_size;
+ }
+ }
+ return val;
+ }
case ZigTypeIdVector:
zig_panic("TODO bit pack a vector");
case ZigTypeIdUnion:
@@ -6387,6 +6535,22 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
}
}
+static LLVMLinkage var_linkage_to_llvm(VarLinkage var_linkage) {
+ switch (var_linkage) {
+ case VarLinkageInternal:
+ return LLVMInternalLinkage;
+ case VarLinkageExportStrong:
+ return LLVMExternalLinkage;
+ case VarLinkageExportWeak:
+ return LLVMWeakODRLinkage;
+ case VarLinkageExportLinkOnce:
+ return LLVMLinkOnceODRLinkage;
+ case VarLinkageExternal:
+ return LLVMExternalLinkage;
+ }
+ zig_unreachable();
+}
+
static void do_code_gen(CodeGen *g) {
assert(!g->errors.length);
@@ -6467,21 +6631,21 @@ static void do_code_gen(CodeGen *g) {
global_value = LLVMAddGlobal(g->module, var->var_type->type_ref, buf_ptr(&var->name));
// TODO debug info for the extern variable
- LLVMSetLinkage(global_value, LLVMExternalLinkage);
+ LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
maybe_import_dll(g, global_value, GlobalLinkageIdStrong);
LLVMSetAlignment(global_value, var->align_bytes);
LLVMSetGlobalConstant(global_value, var->gen_is_const);
set_global_tls(g, var, global_value);
}
} else {
- bool exported = (var->linkage == VarLinkageExport);
+ bool exported = (var->linkage != VarLinkageInternal);
const char *mangled_name = buf_ptr(get_mangled_name(g, &var->name, exported));
render_const_val(g, var->const_value, mangled_name);
render_const_val_global(g, var->const_value, mangled_name);
global_value = var->const_value->global_refs->llvm_global;
if (exported) {
- LLVMSetLinkage(global_value, LLVMExternalLinkage);
+ LLVMSetLinkage(global_value, var_linkage_to_llvm(var->linkage));
maybe_export_dll(g, global_value, GlobalLinkageIdStrong);
}
if (tld_var->section_name) {
@@ -6584,6 +6748,15 @@ static void do_code_gen(CodeGen *g) {
} else if (instruction->id == IrInstructionIdCmpxchgGen) {
IrInstructionCmpxchgGen *cmpxchg_instruction = (IrInstructionCmpxchgGen *)instruction;
slot = &cmpxchg_instruction->tmp_ptr;
+ } else if (instruction->id == IrInstructionIdResizeSlice) {
+ IrInstructionResizeSlice *resize_slice_instruction = (IrInstructionResizeSlice *)instruction;
+ slot = &resize_slice_instruction->tmp_ptr;
+ } else if (instruction->id == IrInstructionIdLoadPtrGen) {
+ IrInstructionLoadPtrGen *load_ptr_inst = (IrInstructionLoadPtrGen *)instruction;
+ slot = &load_ptr_inst->tmp_ptr;
+ } else if (instruction->id == IrInstructionIdBitCastGen) {
+ IrInstructionBitCastGen *bit_cast_inst = (IrInstructionBitCastGen *)instruction;
+ slot = &bit_cast_inst->tmp_ptr;
} else if (instruction->id == IrInstructionIdVectorToArray) {
IrInstructionVectorToArray *vector_to_array_instruction = (IrInstructionVectorToArray *)instruction;
alignment_bytes = get_abi_alignment(g, vector_to_array_instruction->vector->value.type);
@@ -6839,7 +7012,7 @@ static void define_builtin_types(CodeGen *g) {
for (size_t i = 0; i < array_length(c_int_type_infos); i += 1) {
const CIntTypeInfo *info = &c_int_type_infos[i];
- uint32_t size_in_bits = target_c_type_size_in_bits(&g->zig_target, info->id);
+ uint32_t size_in_bits = target_c_type_size_in_bits(g->zig_target, info->id);
bool is_signed = info->is_signed;
ZigType *entry = new_type_table_entry(ZigTypeIdInt);
@@ -7106,6 +7279,9 @@ static const char *build_mode_to_str(BuildMode build_mode) {
Buf *codegen_generate_builtin_source(CodeGen *g) {
Buf *contents = buf_alloc();
+ // NOTE: when editing this file, you may need to make modifications to the
+ // cache input parameters in define_builtin_compile_vars
+
// Modifications to this struct must be coordinated with code that does anything with
// g->stack_trace_type. There are hard-coded references to the field indexes.
buf_append_str(contents,
@@ -7114,16 +7290,18 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" instruction_addresses: []usize,\n"
"};\n\n");
+ buf_append_str(contents, "pub const PanicFn = fn([]const u8, ?*StackTrace) noreturn;\n\n");
+
const char *cur_os = nullptr;
{
buf_appendf(contents, "pub const Os = enum {\n");
uint32_t field_count = (uint32_t)target_os_count();
for (uint32_t i = 0; i < field_count; i += 1) {
- Os os_type = get_target_os(i);
- const char *name = get_target_os_name(os_type);
+ Os os_type = target_os_enum(i);
+ const char *name = target_os_name(os_type);
buf_appendf(contents, " %s,\n", name);
- if (os_type == g->zig_target.os) {
+ if (os_type == g->zig_target->os) {
g->target_os_index = i;
cur_os = name;
}
@@ -7134,56 +7312,81 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
const char *cur_arch = nullptr;
{
- buf_appendf(contents, "pub const Arch = enum {\n");
+ buf_appendf(contents, "pub const Arch = union(enum) {\n");
uint32_t field_count = (uint32_t)target_arch_count();
- for (uint32_t i = 0; i < field_count; i += 1) {
- const ArchType *arch_type = get_target_arch(i);
- Buf *arch_name = buf_alloc();
- buf_resize(arch_name, 50);
- get_arch_name(buf_ptr(arch_name), arch_type);
- buf_resize(arch_name, strlen(buf_ptr(arch_name)));
-
- buf_appendf(contents, " %s,\n", buf_ptr(arch_name));
-
- if (arch_type->arch == g->zig_target.arch.arch &&
- arch_type->sub_arch == g->zig_target.arch.sub_arch)
- {
- g->target_arch_index = i;
- cur_arch = buf_ptr(arch_name);
+ for (uint32_t arch_i = 0; arch_i < field_count; arch_i += 1) {
+ ZigLLVM_ArchType arch = target_arch_enum(arch_i);
+ const char *arch_name = target_arch_name(arch);
+ SubArchList sub_arch_list = target_subarch_list(arch);
+ if (sub_arch_list == SubArchListNone) {
+ buf_appendf(contents, " %s,\n", arch_name);
+ if (arch == g->zig_target->arch) {
+ g->target_arch_index = arch_i;
+ cur_arch = buf_ptr(buf_sprintf("Arch.%s", arch_name));
+ }
+ } else {
+ const char *sub_arch_list_name = target_subarch_list_name(sub_arch_list);
+ buf_appendf(contents, " %s: %s,\n", arch_name, sub_arch_list_name);
+ if (arch == g->zig_target->arch) {
+ size_t sub_count = target_subarch_count(sub_arch_list);
+ for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
+ ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
+ if (sub == g->zig_target->sub_arch) {
+ g->target_sub_arch_index = sub_i;
+ cur_arch = buf_ptr(buf_sprintf("Arch{ .%s = Arch.%s.%s }",
+ arch_name, sub_arch_list_name, target_subarch_name(sub)));
+ }
+ }
+ }
}
}
+
+ uint32_t list_count = target_subarch_list_count();
+ // start at index 1 to skip None
+ for (uint32_t list_i = 1; list_i < list_count; list_i += 1) {
+ SubArchList sub_arch_list = target_subarch_list_enum(list_i);
+ const char *subarch_list_name = target_subarch_list_name(sub_arch_list);
+ buf_appendf(contents, " pub const %s = enum {\n", subarch_list_name);
+ size_t sub_count = target_subarch_count(sub_arch_list);
+ for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
+ ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
+ buf_appendf(contents, " %s,\n", target_subarch_name(sub));
+ }
+ buf_appendf(contents, " };\n");
+ }
buf_appendf(contents, "};\n\n");
}
assert(cur_arch != nullptr);
- const char *cur_environ = nullptr;
+ const char *cur_abi = nullptr;
{
- buf_appendf(contents, "pub const Environ = enum {\n");
- uint32_t field_count = (uint32_t)target_environ_count();
+ buf_appendf(contents, "pub const Abi = enum {\n");
+ uint32_t field_count = (uint32_t)target_abi_count();
for (uint32_t i = 0; i < field_count; i += 1) {
- ZigLLVM_EnvironmentType environ_type = get_target_environ(i);
- const char *name = ZigLLVMGetEnvironmentTypeName(environ_type);
+ ZigLLVM_EnvironmentType abi = target_abi_enum(i);
+ const char *name = target_abi_name(abi);
buf_appendf(contents, " %s,\n", name);
- if (environ_type == g->zig_target.env_type) {
- g->target_environ_index = i;
- cur_environ = name;
+ if (abi == g->zig_target->abi) {
+ g->target_abi_index = i;
+ cur_abi = name;
}
}
buf_appendf(contents, "};\n\n");
}
- assert(cur_environ != nullptr);
+ assert(cur_abi != nullptr);
const char *cur_obj_fmt = nullptr;
{
buf_appendf(contents, "pub const ObjectFormat = enum {\n");
uint32_t field_count = (uint32_t)target_oformat_count();
for (uint32_t i = 0; i < field_count; i += 1) {
- ZigLLVM_ObjectFormatType oformat = get_target_oformat(i);
- const char *name = get_target_oformat_name(oformat);
+ ZigLLVM_ObjectFormatType oformat = target_oformat_enum(i);
+ const char *name = target_oformat_name(oformat);
buf_appendf(contents, " %s,\n", name);
- if (oformat == g->zig_target.oformat) {
+ ZigLLVM_ObjectFormatType target_oformat = target_object_format(g->zig_target);
+ if (oformat == target_oformat) {
g->target_oformat_index = i;
cur_obj_fmt = name;
}
@@ -7294,6 +7497,7 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
" One,\n"
" Many,\n"
" Slice,\n"
+ " C,\n"
" };\n"
" };\n"
"\n"
@@ -7466,12 +7670,13 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
buf_appendf(contents, "pub const single_threaded = %s;\n", bool_to_str(g->is_single_threaded));
buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
- buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
- buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
+ buf_appendf(contents, "pub const arch = %s;\n", cur_arch);
+ buf_appendf(contents, "pub const abi = Abi.%s;\n", cur_abi);
buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr));
buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing));
+ buf_appendf(contents, "pub const valgrind_support = %s;\n", bool_to_str(want_valgrind_support(g)));
buf_appendf(contents, "pub const __zig_test_fn_slice = {}; // overwritten later\n");
@@ -7500,14 +7705,15 @@ static Error define_builtin_compile_vars(CodeGen *g) {
cache_int(&cache_hash, g->build_mode);
cache_bool(&cache_hash, g->is_test_build);
cache_bool(&cache_hash, g->is_single_threaded);
- cache_int(&cache_hash, g->zig_target.arch.arch);
- cache_int(&cache_hash, g->zig_target.arch.sub_arch);
- cache_int(&cache_hash, g->zig_target.vendor);
- cache_int(&cache_hash, g->zig_target.os);
- cache_int(&cache_hash, g->zig_target.env_type);
- cache_int(&cache_hash, g->zig_target.oformat);
+ cache_int(&cache_hash, g->zig_target->is_native);
+ cache_int(&cache_hash, g->zig_target->arch);
+ cache_int(&cache_hash, g->zig_target->sub_arch);
+ cache_int(&cache_hash, g->zig_target->vendor);
+ cache_int(&cache_hash, g->zig_target->os);
+ cache_int(&cache_hash, g->zig_target->abi);
cache_bool(&cache_hash, g->have_err_ret_tracing);
cache_bool(&cache_hash, g->libc_link_lib != nullptr);
+ cache_bool(&cache_hash, g->valgrind_support);
Buf digest = BUF_INIT;
buf_resize(&digest, 0);
@@ -7576,11 +7782,11 @@ static void init(CodeGen *g) {
assert(g->root_out_name);
g->module = LLVMModuleCreateWithName(buf_ptr(g->root_out_name));
- get_target_triple(&g->triple_str, &g->zig_target);
+ get_target_triple(&g->triple_str, g->zig_target);
LLVMSetTarget(g->module, buf_ptr(&g->triple_str));
- if (g->zig_target.oformat == ZigLLVM_COFF) {
+ if (target_object_format(g->zig_target) == ZigLLVM_COFF) {
ZigLLVMAddModuleCodeViewFlag(g->module);
} else {
ZigLLVMAddModuleDebugInfoFlag(g->module);
@@ -7608,11 +7814,11 @@ static void init(CodeGen *g) {
const char *target_specific_cpu_args;
const char *target_specific_features;
- if (g->is_native_target) {
+ if (g->zig_target->is_native) {
// LLVM creates invalid binaries on Windows sometimes.
// See https://github.com/ziglang/zig/issues/508
// As a workaround we do not use target native features on Windows.
- if (g->zig_target.os == OsWindows || g->zig_target.os == OsUefi) {
+ if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
target_specific_cpu_args = "";
target_specific_features = "";
} else {
@@ -7685,9 +7891,59 @@ static void init(CodeGen *g) {
}
}
-void codegen_translate_c(CodeGen *g, Buf *full_path) {
- find_libc_include_path(g);
+static void detect_libc(CodeGen *g) {
+ Error err;
+ if (g->libc != nullptr || g->libc_link_lib == nullptr)
+ return;
+
+ if (g->zig_target->is_native) {
+ g->libc = allocate(1);
+
+ // Look for zig-cache/native_libc.txt
+ Buf *native_libc_txt = buf_alloc();
+ os_path_join(&g->cache_dir, buf_create_from_str("native_libc.txt"), native_libc_txt);
+ if ((err = zig_libc_parse(g->libc, native_libc_txt, g->zig_target, false))) {
+ if ((err = zig_libc_find_native(g->libc, true))) {
+ fprintf(stderr,
+ "Unable to link against libc: Unable to find libc installation: %s\n"
+ "See `zig libc --help` for more details.\n", err_str(err));
+ exit(1);
+ }
+ if ((err = os_make_path(&g->cache_dir))) {
+ fprintf(stderr, "Unable to create %s directory: %s\n",
+ buf_ptr(&g->cache_dir), err_str(err));
+ exit(1);
+ }
+ Buf *native_libc_tmp = buf_sprintf("%s.tmp", buf_ptr(native_libc_txt));
+ FILE *file = fopen(buf_ptr(native_libc_tmp), "wb");
+ if (file == nullptr) {
+ fprintf(stderr, "Unable to open %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno));
+ exit(1);
+ }
+ zig_libc_render(g->libc, file);
+ if (fclose(file) != 0) {
+ fprintf(stderr, "Unable to save %s: %s\n", buf_ptr(native_libc_tmp), strerror(errno));
+ exit(1);
+ }
+ if ((err = os_rename(native_libc_tmp, native_libc_txt))) {
+ fprintf(stderr, "Unable to create %s: %s\n", buf_ptr(native_libc_txt), err_str(err));
+ exit(1);
+ }
+ }
+ } else if ((g->out_type == OutTypeExe || (g->out_type == OutTypeLib && !g->is_static)) &&
+ !target_is_darwin(g->zig_target))
+ {
+ // Currently darwin is the only platform that we can link libc on when not compiling natively,
+ // without a cross compiling libc kit.
+ fprintf(stderr,
+ "Cannot link against libc for non-native OS '%s' without providing a libc installation file.\n"
+ "See `zig libc --help` for more details.\n", target_os_name(g->zig_target->os));
+ exit(1);
+ }
+}
+
+void codegen_translate_c(CodeGen *g, Buf *full_path) {
Buf *src_basename = buf_alloc();
Buf *src_dirname = buf_alloc();
os_path_split(full_path, src_dirname, src_basename);
@@ -7698,6 +7954,8 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
g->root_import = import;
import->decls_scope = create_decls_scope(g, nullptr, nullptr, nullptr, import);
+ detect_libc(g);
+
init(g);
import->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
@@ -7857,14 +8115,14 @@ static void gen_root_source(CodeGen *g) {
}
report_errors_and_maybe_exit(g);
- if (!g->is_test_build && g->zig_target.os != OsFreestanding &&
- g->zig_target.os != OsUefi &&
+ if (!g->is_test_build && g->zig_target->os != OsFreestanding &&
+ g->zig_target->os != OsUefi &&
!g->have_c_main && !g->have_winmain && !g->have_winmain_crt_startup &&
((g->have_pub_main && g->out_type == OutTypeObj) || g->out_type == OutTypeExe))
{
g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap.zig");
}
- if (g->zig_target.os == OsWindows && !g->have_dllmain_crt_startup &&
+ if (g->zig_target->os == OsWindows && !g->have_dllmain_crt_startup &&
g->out_type == OutTypeLib && !g->is_static)
{
g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g, g->root_package), "bootstrap_lib.zig");
@@ -7882,6 +8140,8 @@ static void gen_root_source(CodeGen *g) {
}
}
+ typecheck_panic_fn(g, g->panic_tld_fn, g->panic_fn);
+
report_errors_and_maybe_exit(g);
}
@@ -7904,6 +8164,168 @@ static void gen_global_asm(CodeGen *g) {
}
}
+static void print_zig_cc_cmd(const char *zig_exe, ZigList *args) {
+ fprintf(stderr, "%s", zig_exe);
+ for (size_t arg_i = 0; arg_i < args->length; arg_i += 1) {
+ fprintf(stderr, " %s", args->at(arg_i));
+ }
+ fprintf(stderr, "\n");
+}
+
+static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
+ Error err;
+
+ Buf *c_source_file = buf_create_from_str(c_file->source_path);
+ Buf *c_source_basename = buf_alloc();
+ os_path_split(c_source_file, nullptr, c_source_basename);
+ Buf *out_obj_name = buf_sprintf("%s%s", buf_ptr(c_source_basename), target_o_file_ext(g->zig_target));
+ Buf *out_obj_path = buf_alloc();
+ os_path_join(&g->cache_dir, out_obj_name, out_obj_path);
+ Buf *out_dep_name = buf_sprintf("%s.d", buf_ptr(c_source_file));
+ Buf *out_dep_path = buf_alloc();
+ os_path_join(&g->cache_dir, out_dep_name, out_dep_path);
+
+ Termination term;
+ ZigList args = {};
+ args.append("cc");
+
+ if (g->enable_cache) {
+ args.append("-MD");
+ args.append("-MF");
+ args.append(buf_ptr(out_dep_path));
+ }
+
+ args.append("-nostdinc");
+ args.append("-fno-spell-checking");
+
+ switch (g->err_color) {
+ case ErrColorAuto:
+ break;
+ case ErrColorOff:
+ args.append("-fno-color-diagnostics");
+ args.append("-fno-caret-diagnostics");
+ break;
+ case ErrColorOn:
+ args.append("-fcolor-diagnostics");
+ args.append("-fcaret-diagnostics");
+ break;
+ }
+
+ args.append("-isystem");
+ args.append(buf_ptr(g->zig_c_headers_dir));
+
+ if (g->libc != nullptr) {
+ args.append("-isystem");
+ args.append(buf_ptr(&g->libc->include_dir));
+
+ if (!buf_eql_buf(&g->libc->include_dir, &g->libc->sys_include_dir)) {
+ args.append("-isystem");
+ args.append(buf_ptr(&g->libc->sys_include_dir));
+ }
+ }
+
+ if (g->zig_target->is_native) {
+ args.append("-march=native");
+ } else {
+ args.append("-target");
+ args.append(buf_ptr(&g->triple_str));
+ }
+
+ if (!g->strip_debug_symbols) {
+ args.append("-g");
+ }
+ switch (g->build_mode) {
+ case BuildModeDebug:
+ if (g->libc_link_lib != nullptr) {
+ args.append("-fstack-protector-strong");
+ args.append("--param");
+ args.append("ssp-buffer-size=4");
+ } else {
+ args.append("-fno-stack-protector");
+ }
+ break;
+ case BuildModeSafeRelease:
+ args.append("-O2");
+ if (g->libc_link_lib != nullptr) {
+ args.append("-D_FORTIFY_SOURCE=2");
+ args.append("-fstack-protector-strong");
+ args.append("--param");
+ args.append("ssp-buffer-size=4");
+ } else {
+ args.append("-fno-stack-protector");
+ }
+ break;
+ case BuildModeFastRelease:
+ args.append("-O2");
+ args.append("-fno-stack-protector");
+ break;
+ case BuildModeSmallRelease:
+ args.append("-Os");
+ args.append("-fno-stack-protector");
+ break;
+ }
+
+ args.append("-o");
+ args.append(buf_ptr(out_obj_path));
+
+ args.append("-c");
+ args.append(buf_ptr(c_source_file));
+
+ if (!g->disable_pic && target_supports_fpic(g->zig_target)) {
+ args.append("-fPIC");
+ }
+
+ for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
+ args.append(g->clang_argv[arg_i]);
+ }
+
+ for (size_t arg_i = 0; arg_i < c_file->args.length; arg_i += 1) {
+ args.append(c_file->args.at(arg_i));
+ }
+
+ if (g->verbose_cc) {
+ print_zig_cc_cmd("zig", &args);
+ }
+ os_spawn_process(buf_ptr(self_exe_path), args, &term);
+ if (term.how != TerminationIdClean || term.code != 0) {
+ fprintf(stderr, "\nThe following command failed:\n");
+ print_zig_cc_cmd(buf_ptr(self_exe_path), &args);
+ exit(1);
+ }
+
+ g->link_objects.append(out_obj_path);
+
+ if (g->enable_cache) {
+ // add the files depended on to the cache system
+ if ((err = cache_add_file(&g->cache_hash, c_source_file))) {
+ fprintf(stderr, "unable to add %s to cache: %s\n", buf_ptr(c_source_file), err_str(err));
+ exit(1);
+ }
+ if ((err = cache_add_dep_file(&g->cache_hash, out_dep_path, true))) {
+ fprintf(stderr, "failed to add C source dependencies to cache: %s\n", err_str(err));
+ exit(1);
+ }
+ }
+}
+
+static void gen_c_objects(CodeGen *g) {
+ Error err;
+
+ if (g->c_source_files.length == 0)
+ return;
+
+ Buf *self_exe_path = buf_alloc();
+ if ((err = os_self_exe_path(self_exe_path))) {
+ fprintf(stderr, "Unable to get self exe path: %s\n", err_str(err));
+ exit(1);
+ }
+
+ for (size_t c_file_i = 0; c_file_i < g->c_source_files.length; c_file_i += 1) {
+ CFile *c_file = g->c_source_files.at(c_file_i);
+ gen_c_object(g, self_exe_path, c_file);
+ }
+}
+
void codegen_add_object(CodeGen *g, Buf *object_path) {
g->link_objects.append(object_path);
}
@@ -8410,31 +8832,39 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
}
cache_buf(ch, compiler_id);
cache_buf(ch, g->root_out_name);
+ cache_buf(ch, g->zig_lib_dir);
+ cache_buf(ch, g->zig_std_dir);
cache_list_of_link_lib(ch, g->link_libs_list.items, g->link_libs_list.length);
cache_list_of_buf(ch, g->darwin_frameworks.items, g->darwin_frameworks.length);
cache_list_of_buf(ch, g->rpath_list.items, g->rpath_list.length);
cache_list_of_buf(ch, g->forbidden_libs.items, g->forbidden_libs.length);
cache_list_of_file(ch, g->link_objects.items, g->link_objects.length);
cache_list_of_file(ch, g->assembly_files.items, g->assembly_files.length);
+ for (size_t c_file_i = 0; c_file_i < g->c_source_files.length; c_file_i += 1) {
+ CFile *c_file = g->c_source_files.at(c_file_i);
+ cache_file(ch, buf_create_from_str(c_file->source_path));
+ for (size_t opt_i = 0; opt_i < c_file->args.length; opt_i += 1) {
+ cache_buf(ch, buf_create_from_str(c_file->args.at(opt_i)));
+ }
+ }
cache_int(ch, g->emit_file_type);
cache_int(ch, g->build_mode);
cache_int(ch, g->out_type);
- cache_int(ch, g->zig_target.arch.arch);
- cache_int(ch, g->zig_target.arch.sub_arch);
- cache_int(ch, g->zig_target.vendor);
- cache_int(ch, g->zig_target.os);
- cache_int(ch, g->zig_target.env_type);
- cache_int(ch, g->zig_target.oformat);
+ cache_bool(ch, g->zig_target->is_native);
+ cache_int(ch, g->zig_target->arch);
+ cache_int(ch, g->zig_target->sub_arch);
+ cache_int(ch, g->zig_target->vendor);
+ cache_int(ch, g->zig_target->os);
+ cache_int(ch, g->zig_target->abi);
cache_int(ch, g->subsystem);
cache_bool(ch, g->is_static);
cache_bool(ch, g->strip_debug_symbols);
cache_bool(ch, g->is_test_build);
cache_bool(ch, g->is_single_threaded);
- cache_bool(ch, g->is_native_target);
cache_bool(ch, g->linker_rdynamic);
- cache_bool(ch, g->no_rosegment_workaround);
cache_bool(ch, g->each_lib_rpath);
cache_bool(ch, g->disable_pic);
+ cache_bool(ch, g->valgrind_support);
cache_buf_opt(ch, g->mmacosx_version_min);
cache_buf_opt(ch, g->mios_version_min);
cache_usize(ch, g->version_major);
@@ -8445,6 +8875,16 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);
cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);
cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);
+ if (g->libc) {
+ cache_buf(ch, &g->libc->include_dir);
+ cache_buf(ch, &g->libc->sys_include_dir);
+ cache_buf(ch, &g->libc->crt_dir);
+ cache_buf(ch, &g->libc->lib_dir);
+ cache_buf(ch, &g->libc->static_lib_dir);
+ cache_buf(ch, &g->libc->msvc_lib_dir);
+ cache_buf(ch, &g->libc->kernel32_lib_dir);
+ cache_buf(ch, &g->libc->dynamic_linker_path);
+ }
buf_resize(digest, 0);
if ((err = cache_hit(ch, digest)))
@@ -8459,19 +8899,19 @@ static void resolve_out_paths(CodeGen *g) {
switch (g->emit_file_type) {
case EmitFileTypeBinary:
{
- const char *o_ext = target_o_file_ext(&g->zig_target);
+ const char *o_ext = target_o_file_ext(g->zig_target);
buf_append_str(o_basename, o_ext);
break;
}
case EmitFileTypeAssembly:
{
- const char *asm_ext = target_asm_file_ext(&g->zig_target);
+ const char *asm_ext = target_asm_file_ext(g->zig_target);
buf_append_str(o_basename, asm_ext);
break;
}
case EmitFileTypeLLVMIr:
{
- const char *llvm_ir_ext = target_llvm_ir_file_ext(&g->zig_target);
+ const char *llvm_ir_ext = target_llvm_ir_file_ext(g->zig_target);
buf_append_str(o_basename, llvm_ir_ext);
break;
}
@@ -8497,7 +8937,7 @@ static void resolve_out_paths(CodeGen *g) {
Buf basename = BUF_INIT;
buf_init_from_buf(&basename, g->root_out_name);
- buf_append_str(&basename, target_exe_file_ext(&g->zig_target));
+ buf_append_str(&basename, target_exe_file_ext(g->zig_target));
if (g->enable_cache || g->is_test_build) {
os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
} else {
@@ -8510,7 +8950,7 @@ static void resolve_out_paths(CodeGen *g) {
} else {
Buf basename = BUF_INIT;
buf_init_from_buf(&basename, g->root_out_name);
- buf_append_str(&basename, target_lib_file_ext(&g->zig_target, g->is_static,
+ buf_append_str(&basename, target_lib_file_ext(g->zig_target, g->is_static,
g->version_major, g->version_minor, g->version_patch));
if (g->enable_cache) {
os_path_join(&g->artifact_dir, &basename, &g->output_file_path);
@@ -8523,11 +8963,12 @@ static void resolve_out_paths(CodeGen *g) {
}
}
-
void codegen_build_and_link(CodeGen *g) {
Error err;
assert(g->out_type != OutTypeUnknown);
+ detect_libc(g);
+
Buf *stage1_dir = get_stage1_cache_path();
Buf *artifact_dir = buf_alloc();
Buf digest = BUF_INIT;
@@ -8559,6 +9000,7 @@ void codegen_build_and_link(CodeGen *g) {
gen_global_asm(g);
gen_root_source(g);
+ gen_c_objects(g);
if (g->enable_cache) {
if ((err = cache_final(&g->cache_hash, &digest))) {
@@ -8576,16 +9018,25 @@ void codegen_build_and_link(CodeGen *g) {
resolve_out_paths(g);
codegen_add_time_event(g, "Code Generation");
- do_code_gen(g);
- codegen_add_time_event(g, "LLVM Emit Output");
- zig_llvm_emit_output(g);
+ if (g->out_type == OutTypeObj && g->c_source_files.length == 1) {
+ assert(g->link_objects.length == 1);
+ if ((err = os_rename(g->link_objects.pop(), &g->o_file_output_path))) {
+ fprintf(stderr, "unable to move object to '%s': %s\n",
+ buf_ptr(&g->o_file_output_path), err_str(err));
+ exit(1);
+ }
+ } else {
+ do_code_gen(g);
+ codegen_add_time_event(g, "LLVM Emit Output");
+ zig_llvm_emit_output(g);
- if (g->out_h_path != nullptr) {
- codegen_add_time_event(g, "Generate .h");
- gen_h_file(g);
- }
- if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {
- codegen_link(g);
+ if (g->out_h_path != nullptr) {
+ codegen_add_time_event(g, "Generate .h");
+ gen_h_file(g);
+ }
+ if (g->out_type != OutTypeObj && g->emit_file_type == EmitFileTypeBinary) {
+ codegen_link(g);
+ }
}
}
diff --git a/src/codegen.hpp b/src/codegen.hpp
index 4bd8f2dcca..4f62cc4cbc 100644
--- a/src/codegen.hpp
+++ b/src/codegen.hpp
@@ -11,11 +11,12 @@
#include "parser.hpp"
#include "errmsg.hpp"
#include "target.hpp"
+#include "libc_installation.hpp"
#include
CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode,
- Buf *zig_lib_dir, Buf *override_std_dir);
+ Buf *zig_lib_dir, Buf *override_std_dir, ZigLibCInstallation *libc);
void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
void codegen_set_llvm_argv(CodeGen *codegen, const char **args, size_t len);
@@ -27,12 +28,6 @@ void codegen_set_is_static(CodeGen *codegen, bool is_static);
void codegen_set_strip(CodeGen *codegen, bool strip);
void codegen_set_errmsg_color(CodeGen *codegen, ErrColor err_color);
void codegen_set_out_name(CodeGen *codegen, Buf *out_name);
-void codegen_set_libc_lib_dir(CodeGen *codegen, Buf *libc_lib_dir);
-void codegen_set_libc_static_lib_dir(CodeGen *g, Buf *libc_static_lib_dir);
-void codegen_set_libc_include_dir(CodeGen *codegen, Buf *libc_include_dir);
-void codegen_set_msvc_lib_dir(CodeGen *g, Buf *msvc_lib_dir);
-void codegen_set_kernel32_lib_dir(CodeGen *codegen, Buf *kernel32_lib_dir);
-void codegen_set_dynamic_linker(CodeGen *g, Buf *dynamic_linker);
void codegen_add_lib_dir(CodeGen *codegen, const char *dir);
void codegen_add_forbidden_lib(CodeGen *codegen, Buf *lib);
LinkLib *codegen_add_link_lib(CodeGen *codegen, Buf *lib);
@@ -46,6 +41,7 @@ void codegen_set_test_filter(CodeGen *g, Buf *filter);
void codegen_set_test_name_prefix(CodeGen *g, Buf *prefix);
void codegen_set_lib_version(CodeGen *g, size_t major, size_t minor, size_t patch);
void codegen_set_output_h_path(CodeGen *g, Buf *h_path);
+void codegen_set_output_lib_path(CodeGen *g, Buf *lib_path);
void codegen_set_output_path(CodeGen *g, Buf *path);
void codegen_add_time_event(CodeGen *g, const char *name);
void codegen_print_timing_report(CodeGen *g, FILE *f);
diff --git a/src/error.cpp b/src/error.cpp
index 10186fbde5..17d44bffed 100644
--- a/src/error.cpp
+++ b/src/error.cpp
@@ -34,6 +34,15 @@ const char *err_str(Error err) {
case ErrorPipeBusy: return "pipe busy";
case ErrorPrimitiveTypeNotFound: return "primitive type not found";
case ErrorCacheUnavailable: return "cache unavailable";
+ case ErrorPathTooLong: return "path too long";
+ case ErrorCCompilerCannotFindFile: return "C compiler cannot find file";
+ case ErrorReadingDepFile: return "failed to read .d file";
+ case ErrorMissingArchitecture: return "missing architecture";
+ case ErrorMissingOperatingSystem: return "missing operating system";
+ case ErrorUnknownArchitecture: return "unrecognized architecture";
+ case ErrorUnknownOperatingSystem: return "unrecognized operating system";
+ case ErrorUnknownABI: return "unrecognized C ABI";
+ case ErrorInvalidFilename: return "invalid filename";
}
return "(invalid error)";
}
diff --git a/src/error.hpp b/src/error.hpp
index b60cb8517e..6d9727a217 100644
--- a/src/error.hpp
+++ b/src/error.hpp
@@ -36,6 +36,15 @@ enum Error {
ErrorPipeBusy,
ErrorPrimitiveTypeNotFound,
ErrorCacheUnavailable,
+ ErrorPathTooLong,
+ ErrorCCompilerCannotFindFile,
+ ErrorReadingDepFile,
+ ErrorMissingArchitecture,
+ ErrorMissingOperatingSystem,
+ ErrorUnknownArchitecture,
+ ErrorUnknownOperatingSystem,
+ ErrorUnknownABI,
+ ErrorInvalidFilename,
};
const char *err_str(Error err);
diff --git a/src/ir.cpp b/src/ir.cpp
index 5d4013b4b9..87e03ea519 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -61,7 +61,7 @@ enum ConstCastResultId {
ConstCastResultIdType,
ConstCastResultIdUnresolvedInferredErrSet,
ConstCastResultIdAsyncAllocatorType,
- ConstCastResultIdNullWrapPtr
+ ConstCastResultIdBadAllowsZero,
};
struct ConstCastOnly;
@@ -83,6 +83,7 @@ struct ConstCastErrUnionErrSetMismatch;
struct ConstCastErrUnionPayloadMismatch;
struct ConstCastErrSetMismatch;
struct ConstCastTypeMismatch;
+struct ConstCastBadAllowsZero;
struct ConstCastOnly {
ConstCastResultId id;
@@ -99,6 +100,7 @@ struct ConstCastOnly {
ConstCastOnly *null_wrap_ptr_child;
ConstCastArg fn_arg;
ConstCastArgNoAlias arg_no_alias;
+ ConstCastBadAllowsZero *bad_allows_zero;
} data;
};
@@ -141,6 +143,12 @@ struct ConstCastErrSetMismatch {
ZigList missing_errors;
};
+struct ConstCastBadAllowsZero {
+ ZigType *wanted_type;
+ ZigType *actual_type;
+};
+
+
enum UndefAllowed {
UndefOk,
UndefBad,
@@ -164,11 +172,15 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source_node,
ConstExprValue *out_val, ConstExprValue *ptr_val);
static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
- ZigType *dest_type, IrInstruction *dest_type_src);
+ ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on);
static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, UndefAllowed undef_allowed);
static void copy_const_val(ConstExprValue *dest, ConstExprValue *src, bool same_global_refs);
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align);
static void ir_add_alloca(IrAnalyze *ira, IrInstruction *instruction, ZigType *type_entry);
+static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
+ ZigType *ptr_type);
+static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
+ ZigType *dest_type);
static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *const_val) {
assert(get_src_ptr_type(const_val->type) != nullptr);
@@ -186,10 +198,11 @@ static ConstExprValue *const_ptr_pointee_unchecked(CodeGen *g, ConstExprValue *c
result = &array_val->data.x_array.data.s_none.elements[const_val->data.x_ptr.data.base_array.elem_index];
break;
}
- case ConstPtrSpecialBaseStruct:
- result = &const_val->data.x_ptr.data.base_struct.struct_val->data.x_struct.fields[
- const_val->data.x_ptr.data.base_struct.field_index];
+ case ConstPtrSpecialBaseStruct: {
+ ConstExprValue *struct_val = const_val->data.x_ptr.data.base_struct.struct_val;
+ result = &struct_val->data.x_struct.fields[const_val->data.x_ptr.data.base_struct.field_index];
break;
+ }
case ConstPtrSpecialBaseErrorUnionCode:
result = const_val->data.x_ptr.data.base_err_union_code.err_union_val->data.x_err_union.error_set;
break;
@@ -218,20 +231,55 @@ static bool is_opt_err_set(ZigType *ty) {
(ty->id == ZigTypeIdOptional && ty->data.maybe.child_type->id == ZigTypeIdErrorSet);
}
+// This function returns true when you can change the type of a ConstExprValue and the
+// value remains meaningful.
static bool types_have_same_zig_comptime_repr(ZigType *a, ZigType *b) {
if (a == b)
return true;
- if (a->id == b->id)
- return true;
-
if (get_codegen_ptr_type(a) != nullptr && get_codegen_ptr_type(b) != nullptr)
return true;
if (is_opt_err_set(a) && is_opt_err_set(b))
return true;
- return false;
+ if (a->id != b->id)
+ return false;
+
+ switch (a->id) {
+ case ZigTypeIdInvalid:
+ case ZigTypeIdUnreachable:
+ zig_unreachable();
+ case ZigTypeIdMetaType:
+ case ZigTypeIdVoid:
+ case ZigTypeIdBool:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdPointer:
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdNamespace:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdErrorSet:
+ case ZigTypeIdOpaque:
+ return true;
+ case ZigTypeIdFloat:
+ return a->data.floating.bit_count == b->data.floating.bit_count;
+ case ZigTypeIdInt:
+ return a->data.integral.is_signed == b->data.integral.is_signed;
+ case ZigTypeIdArray:
+ case ZigTypeIdStruct:
+ case ZigTypeIdOptional:
+ case ZigTypeIdErrorUnion:
+ case ZigTypeIdEnum:
+ case ZigTypeIdUnion:
+ case ZigTypeIdFn:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdPromise:
+ case ZigTypeIdVector:
+ return false;
+ }
+ zig_unreachable();
}
static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
@@ -368,6 +416,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtr *) {
return IrInstructionIdLoadPtr;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionLoadPtrGen *) {
+ return IrInstructionIdLoadPtrGen;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionStorePtr *) {
return IrInstructionIdStorePtr;
}
@@ -408,6 +460,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionCast *) {
return IrInstructionIdCast;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionResizeSlice *) {
+ return IrInstructionIdResizeSlice;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionContainerInitList *) {
return IrInstructionIdContainerInitList;
}
@@ -688,6 +744,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCast *) {
return IrInstructionIdBitCast;
}
+static constexpr IrInstructionId ir_instruction_id(IrInstructionBitCastGen *) {
+ return IrInstructionIdBitCastGen;
+}
+
static constexpr IrInstructionId ir_instruction_id(IrInstructionWidenOrShorten *) {
return IrInstructionIdWidenOrShorten;
}
@@ -1291,14 +1351,23 @@ static IrInstruction *ir_build_ptr_type(IrBuilder *irb, Scope *scope, AstNode *s
return &ptr_type_of_instruction->base;
}
-static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id, IrInstruction *value) {
- IrInstructionUnOp *br_instruction = ir_build_instruction(irb, scope, source_node);
- br_instruction->op_id = op_id;
- br_instruction->value = value;
+static IrInstruction *ir_build_un_op_lval(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
+ IrInstruction *value, LVal lval)
+{
+ IrInstructionUnOp *instruction = ir_build_instruction(irb, scope, source_node);
+ instruction->op_id = op_id;
+ instruction->value = value;
+ instruction->lval = lval;
ir_ref_instruction(value, irb->current_basic_block);
- return &br_instruction->base;
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *source_node, IrUnOp op_id,
+ IrInstruction *value)
+{
+ return ir_build_un_op_lval(irb, scope, source_node, op_id, value, LValNone);
}
static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
@@ -1418,6 +1487,19 @@ static IrInstruction *ir_build_var_decl_gen(IrAnalyze *ira, IrInstruction *sourc
return &decl_var_instruction->base;
}
+static IrInstruction *ir_build_resize_slice(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *operand, ZigType *ty)
+{
+ IrInstructionResizeSlice *instruction = ir_build_instruction(&ira->new_irb,
+ source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ty;
+ instruction->operand = operand;
+
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_export(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *name, IrInstruction *target, IrInstruction *linkage)
{
@@ -2190,12 +2272,13 @@ static IrInstruction *ir_build_test_comptime(IrBuilder *irb, Scope *scope, AstNo
}
static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNode *source_node,
- IrInstruction *dest_type, IrInstruction *ptr)
+ IrInstruction *dest_type, IrInstruction *ptr, bool safety_check_on)
{
IrInstructionPtrCastSrc *instruction = ir_build_instruction(
irb, scope, source_node);
instruction->dest_type = dest_type;
instruction->ptr = ptr;
+ instruction->safety_check_on = safety_check_on;
ir_ref_instruction(dest_type, irb->current_basic_block);
ir_ref_instruction(ptr, irb->current_basic_block);
@@ -2204,12 +2287,26 @@ static IrInstruction *ir_build_ptr_cast_src(IrBuilder *irb, Scope *scope, AstNod
}
static IrInstruction *ir_build_ptr_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
- ZigType *ptr_type, IrInstruction *ptr)
+ ZigType *ptr_type, IrInstruction *ptr, bool safety_check_on)
{
IrInstructionPtrCastGen *instruction = ir_build_instruction(
&ira->new_irb, source_instruction->scope, source_instruction->source_node);
instruction->base.value.type = ptr_type;
instruction->ptr = ptr;
+ instruction->safety_check_on = safety_check_on;
+
+ ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
+static IrInstruction *ir_build_load_ptr_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *ptr, ZigType *ty)
+{
+ IrInstructionLoadPtrGen *instruction = ir_build_instruction(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ty;
+ instruction->ptr = ptr;
ir_ref_instruction(ptr, ira->new_irb.current_basic_block);
@@ -2224,12 +2321,25 @@ static IrInstruction *ir_build_bit_cast(IrBuilder *irb, Scope *scope, AstNode *s
instruction->dest_type = dest_type;
instruction->value = value;
- if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);
+ ir_ref_instruction(dest_type, irb->current_basic_block);
ir_ref_instruction(value, irb->current_basic_block);
return &instruction->base;
}
+static IrInstruction *ir_build_bit_cast_gen(IrAnalyze *ira, IrInstruction *source_instruction,
+ IrInstruction *operand, ZigType *ty)
+{
+ IrInstructionBitCastGen *instruction = ir_build_instruction(
+ &ira->new_irb, source_instruction->scope, source_instruction->source_node);
+ instruction->base.value.type = ty;
+ instruction->operand = operand;
+
+ ir_ref_instruction(operand, ira->new_irb.current_basic_block);
+
+ return &instruction->base;
+}
+
static IrInstruction *ir_build_widen_or_shorten(IrBuilder *irb, Scope *scope, AstNode *source_node,
IrInstruction *target)
{
@@ -2458,7 +2568,7 @@ static IrInstruction *ir_build_type_info(IrBuilder *irb, Scope *scope, AstNode *
ir_ref_instruction(type_value, irb->current_basic_block);
- return &instruction->base;
+ return &instruction->base;
}
static IrInstruction *ir_build_type_id(IrBuilder *irb, Scope *scope, AstNode *source_node,
@@ -3651,6 +3761,22 @@ static IrInstruction *ir_gen_null_literal(IrBuilder *irb, Scope *scope, AstNode
return ir_build_const_null(irb, scope, node);
}
+static void populate_invalid_variable_in_scope(CodeGen *g, Scope *scope, AstNode *node, Buf *var_name) {
+ ScopeDecls *scope_decls = nullptr;
+ while (scope != nullptr) {
+ if (scope->id == ScopeIdDecls) {
+ scope_decls = reinterpret_cast(scope);
+ }
+ scope = scope->parent;
+ }
+ TldVar *tld_var = allocate(1);
+ init_tld(&tld_var->base, TldIdVar, var_name, VisibModPub, node, &scope_decls->base);
+ tld_var->base.resolution = TldResolutionInvalid;
+ tld_var->var = add_variable(g, node, &scope_decls->base, var_name, false,
+ &g->invalid_instruction->value, &tld_var->base, g->builtin_types.entry_invalid);
+ scope_decls->decl_table.put(var_name, &tld_var->base);
+}
+
static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
Error err;
assert(node->type == NodeTypeSymbol);
@@ -3704,8 +3830,9 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
return irb->codegen->invalid_instruction;
}
- // TODO put a variable of same name with invalid type in global scope
+ // put a variable of same name with invalid type in global scope
// so that future references to this same name will find a variable with an invalid type
+ populate_invalid_variable_in_scope(irb->codegen, scope, node, variable_name);
add_node_error(irb->codegen, node, buf_sprintf("use of undeclared identifier '%s'", buf_ptr(variable_name)));
return irb->codegen->invalid_instruction;
}
@@ -4493,7 +4620,7 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
if (arg1_value == irb->codegen->invalid_instruction)
return arg1_value;
- IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value);
+ IrInstruction *ptr_cast = ir_build_ptr_cast_src(irb, scope, node, arg0_value, arg1_value, true);
return ir_lval_wrap(irb, scope, ptr_cast, lval);
}
case BuiltinFnIdBitCast:
@@ -5019,10 +5146,23 @@ static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *
return ir_build_ref(irb, scope, value->source_node, value, false, false);
}
+static PtrLen star_token_to_ptr_len(TokenId token_id) {
+ switch (token_id) {
+ case TokenIdStar:
+ case TokenIdStarStar:
+ return PtrLenSingle;
+ case TokenIdBracketStarBracket:
+ return PtrLenUnknown;
+ case TokenIdBracketStarCBracket:
+ return PtrLenC;
+ default:
+ zig_unreachable();
+ }
+}
+
static IrInstruction *ir_gen_pointer_type(IrBuilder *irb, Scope *scope, AstNode *node) {
assert(node->type == NodeTypePointerType);
- PtrLen ptr_len = (node->data.pointer_type.star_token->id == TokenIdStar ||
- node->data.pointer_type.star_token->id == TokenIdStarStar) ? PtrLenSingle : PtrLenUnknown;
+ PtrLen ptr_len = star_token_to_ptr_len(node->data.pointer_type.star_token->id);
bool is_const = node->data.pointer_type.is_const;
bool is_volatile = node->data.pointer_type.is_volatile;
AstNode *expr_node = node->data.pointer_type.op_expr;
@@ -6715,14 +6855,15 @@ static IrInstruction *ir_gen_cancel_target(IrBuilder *irb, Scope *scope, AstNode
IrInstruction *is_suspended_mask = ir_build_const_usize(irb, scope, node, 0x2); // 0b010
// TODO relies on Zig not re-ordering fields
- IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
+ IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
+ false);
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
atomic_state_field_name);
// set the is_canceled bit
- IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, atomic_state_ptr, nullptr, is_canceled_mask, nullptr,
AtomicRmwOp_or, AtomicOrderSeqCst);
@@ -6793,14 +6934,15 @@ static IrInstruction *ir_gen_resume_target(IrBuilder *irb, Scope *scope, AstNode
get_promise_type(irb->codegen, irb->codegen->builtin_types.entry_void));
// TODO relies on Zig not re-ordering fields
- IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst);
+ IrInstruction *casted_target_inst = ir_build_ptr_cast_src(irb, scope, node, promise_T_type_val, target_inst,
+ false);
IrInstruction *coro_promise_ptr = ir_build_coro_promise(irb, scope, node, casted_target_inst);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
IrInstruction *atomic_state_ptr = ir_build_field_ptr(irb, scope, node, coro_promise_ptr,
atomic_state_field_name);
// clear the is_suspended bit
- IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, atomic_state_ptr, nullptr, and_mask, nullptr,
AtomicRmwOp_and, AtomicOrderSeqCst);
@@ -6916,7 +7058,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
IrInstruction *coro_handle_addr = ir_build_ptr_to_int(irb, scope, node, irb->exec->coro_handle);
IrInstruction *mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, coro_handle_addr, await_mask, false);
- IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, atomic_state_ptr, nullptr, mask_bits, nullptr,
AtomicRmwOp_or, AtomicOrderSeqCst);
@@ -6959,7 +7101,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
ir_set_cursor_at_end_and_append_block(irb, yes_suspend_block);
- IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, is_suspended_mask, nullptr,
AtomicRmwOp_or, AtomicOrderSeqCst);
IrInstruction *my_is_suspended_value = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, my_prev_atomic_value, is_suspended_mask, false);
@@ -6991,7 +7133,7 @@ static IrInstruction *ir_gen_await_expr(IrBuilder *irb, Scope *scope, AstNode *n
ir_set_cursor_at_end_and_append_block(irb, cleanup_block);
IrInstruction *my_mask_bits = ir_build_bin_op(irb, scope, node, IrBinOpBinOr, ptr_mask, is_canceled_mask, false);
- IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
+ IrInstruction *b_my_prev_atomic_value = ir_build_atomic_rmw(irb, scope, node,
usize_type_val, irb->exec->atomic_state_field_ptr, nullptr, my_mask_bits, nullptr,
AtomicRmwOp_or, AtomicOrderSeqCst);
IrInstruction *my_await_handle_addr = ir_build_bin_op(irb, scope, node, IrBinOpBinAnd, b_my_prev_atomic_value, ptr_mask, false);
@@ -7194,7 +7336,10 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
if (value == irb->codegen->invalid_instruction)
return value;
- return ir_build_un_op(irb, scope, node, IrUnOpDereference, value);
+ // We essentially just converted any lvalue from &(x.*) to (&x).*;
+ // this inhibits checking that x is a pointer later, so we directly
+ // record whether the pointer check is needed
+ return ir_build_un_op_lval(irb, scope, node, IrUnOpDereference, value, lval);
}
case NodeTypeUnwrapOptional: {
AstNode *expr_node = node->data.unwrap_optional.expr;
@@ -7338,7 +7483,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
u8_ptr_type = ir_build_const_type(irb, coro_scope, node,
get_pointer_to_type(irb->codegen, irb->codegen->builtin_types.entry_u8, false));
- IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, coro_promise_ptr);
+ IrInstruction *promise_as_u8_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type,
+ coro_promise_ptr, false);
coro_id = ir_build_coro_id(irb, coro_scope, node, promise_as_u8_ptr);
coro_size_var = ir_create_var(irb, node, coro_scope, nullptr, false, false, true, const_bool_false);
IrInstruction *coro_size = ir_build_coro_size(irb, coro_scope, node);
@@ -7362,7 +7508,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
ir_build_return(irb, coro_scope, node, undef);
ir_set_cursor_at_end_and_append_block(irb, alloc_ok_block);
- IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr);
+ IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, coro_scope, node, u8_ptr_type, maybe_coro_mem_ptr,
+ false);
irb->exec->coro_handle = ir_build_coro_begin(irb, coro_scope, node, coro_id, coro_mem_ptr);
Buf *atomic_state_field_name = buf_create_from_str(ATOMIC_STATE_FIELD_NAME);
@@ -7440,9 +7587,10 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
false, false, PtrLenUnknown, 0, 0, 0));
IrInstruction *result_ptr = ir_build_load_ptr(irb, scope, node, irb->exec->coro_result_ptr_field_ptr);
- IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, result_ptr);
- IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
- irb->exec->coro_result_field_ptr);
+ IrInstruction *result_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
+ result_ptr, false);
+ IrInstruction *return_value_ptr_as_u8_ptr = ir_build_ptr_cast_src(irb, scope, node,
+ u8_ptr_type_unknown_len, irb->exec->coro_result_field_ptr, false);
IrInstruction *return_type_inst = ir_build_const_type(irb, scope, node,
fn_entry->type_entry->data.fn.fn_type_id.return_type);
IrInstruction *size_of_ret_val = ir_build_size_of(irb, scope, node, return_type_inst);
@@ -7492,7 +7640,8 @@ bool ir_gen(CodeGen *codegen, AstNode *node, Scope *scope, IrExecutable *ir_exec
IrInstruction *u8_ptr_type_unknown_len = ir_build_const_type(irb, scope, node,
get_pointer_to_type_extra(irb->codegen, irb->codegen->builtin_types.entry_u8,
false, false, PtrLenUnknown, 0, 0, 0));
- IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len, coro_mem_ptr_maybe);
+ IrInstruction *coro_mem_ptr = ir_build_ptr_cast_src(irb, scope, node, u8_ptr_type_unknown_len,
+ coro_mem_ptr_maybe, false);
IrInstruction *coro_mem_ptr_ref = ir_build_ref(irb, scope, node, coro_mem_ptr, true, false);
IrInstruction *coro_size_ptr = ir_build_var_ptr(irb, scope, node, coro_size_var);
IrInstruction *coro_size = ir_build_load_ptr(irb, scope, node, coro_size_ptr);
@@ -8619,7 +8768,6 @@ static ZigType *get_error_set_intersection(IrAnalyze *ira, ZigType *set1, ZigTyp
return err_set_type;
}
-
static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted_type,
ZigType *actual_type, AstNode *source_node, bool wanted_is_mutable)
{
@@ -8632,53 +8780,63 @@ static ConstCastOnly types_match_const_cast_only(IrAnalyze *ira, ZigType *wanted
if (wanted_type == actual_type)
return result;
- // *T and [*]T may const-cast-only to ?*U and ?[*]U, respectively
- // but not if we want a mutable pointer
- // and not if the actual pointer has zero bits
- if (!wanted_is_mutable && wanted_type->id == ZigTypeIdOptional &&
- wanted_type->data.maybe.child_type->id == ZigTypeIdPointer &&
- actual_type->id == ZigTypeIdPointer && type_has_bits(actual_type))
- {
- ConstCastOnly child = types_match_const_cast_only(ira,
- wanted_type->data.maybe.child_type, actual_type, source_node, wanted_is_mutable);
- if (child.id == ConstCastResultIdInvalid)
- return child;
- if (child.id != ConstCastResultIdOk) {
- result.id = ConstCastResultIdNullWrapPtr;
- result.data.null_wrap_ptr_child = allocate_nonzero(1);
- *result.data.null_wrap_ptr_child = child;
- }
- return result;
- }
-
- // pointer const
- if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer) {
- ConstCastOnly child = types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
- actual_type->data.pointer.child_type, source_node, !wanted_type->data.pointer.is_const);
+ // If pointers have the same representation in memory, they can be "const-casted".
+ // `const` attribute can be gained
+ // `volatile` attribute can be gained
+ // `allowzero` attribute can be gained (whether from explicit attribute, C pointer, or optional pointer)
+ // but only if !wanted_is_mutable
+ // alignment can be decreased
+ // bit offset attributes must match exactly
+ // PtrLenSingle/PtrLenUnknown must match exactly, but PtrLenC matches either one
+ ZigType *wanted_ptr_type = get_src_ptr_type(wanted_type);
+ ZigType *actual_ptr_type = get_src_ptr_type(actual_type);
+ bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
+ bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
+ bool wanted_is_c_ptr = wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC;
+ bool actual_is_c_ptr = actual_type->id == ZigTypeIdPointer && actual_type->data.pointer.ptr_len == PtrLenC;
+ bool wanted_opt_or_ptr = wanted_ptr_type != nullptr &&
+ (wanted_type->id == ZigTypeIdPointer || wanted_type->id == ZigTypeIdOptional);
+ bool actual_opt_or_ptr = actual_ptr_type != nullptr &&
+ (actual_type->id == ZigTypeIdPointer || actual_type->id == ZigTypeIdOptional);
+ if (wanted_opt_or_ptr && actual_opt_or_ptr) {
+ ConstCastOnly child = types_match_const_cast_only(ira, wanted_ptr_type->data.pointer.child_type,
+ actual_ptr_type->data.pointer.child_type, source_node, !wanted_ptr_type->data.pointer.is_const);
if (child.id == ConstCastResultIdInvalid)
return child;
if (child.id != ConstCastResultIdOk) {
result.id = ConstCastResultIdPointerChild;
result.data.pointer_mismatch = allocate_nonzero(1);
result.data.pointer_mismatch->child = child;
- result.data.pointer_mismatch->wanted_child = wanted_type->data.pointer.child_type;
- result.data.pointer_mismatch->actual_child = actual_type->data.pointer.child_type;
+ result.data.pointer_mismatch->wanted_child = wanted_ptr_type->data.pointer.child_type;
+ result.data.pointer_mismatch->actual_child = actual_ptr_type->data.pointer.child_type;
return result;
}
- if ((err = type_resolve(g, actual_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
+ bool ok_allows_zero = (wanted_allows_zero &&
+ (actual_allows_zero || !wanted_is_mutable)) ||
+ (!wanted_allows_zero && !actual_allows_zero);
+ if (!ok_allows_zero) {
+ result.id = ConstCastResultIdBadAllowsZero;
+ result.data.bad_allows_zero = allocate_nonzero(1);
+ result.data.bad_allows_zero->wanted_type = wanted_type;
+ result.data.bad_allows_zero->actual_type = actual_type;
+ return result;
+ }
+ if ((err = type_resolve(g, actual_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
result.id = ConstCastResultIdInvalid;
return result;
}
- if ((err = type_resolve(g, wanted_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
+ if ((err = type_resolve(g, wanted_ptr_type->data.pointer.child_type, ResolveStatusAlignmentKnown))) {
result.id = ConstCastResultIdInvalid;
return result;
}
- if ((actual_type->data.pointer.ptr_len == wanted_type->data.pointer.ptr_len) &&
- (!actual_type->data.pointer.is_const || wanted_type->data.pointer.is_const) &&
- (!actual_type->data.pointer.is_volatile || wanted_type->data.pointer.is_volatile) &&
- actual_type->data.pointer.bit_offset_in_host == wanted_type->data.pointer.bit_offset_in_host &&
- actual_type->data.pointer.host_int_bytes == wanted_type->data.pointer.host_int_bytes &&
- get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, wanted_type))
+ bool ptr_lens_equal = actual_ptr_type->data.pointer.ptr_len == wanted_ptr_type->data.pointer.ptr_len;
+ if ((ptr_lens_equal || wanted_is_c_ptr || actual_is_c_ptr) &&
+ type_has_bits(wanted_type) == type_has_bits(actual_type) &&
+ (!actual_ptr_type->data.pointer.is_const || wanted_ptr_type->data.pointer.is_const) &&
+ (!actual_ptr_type->data.pointer.is_volatile || wanted_ptr_type->data.pointer.is_volatile) &&
+ actual_ptr_type->data.pointer.bit_offset_in_host == wanted_ptr_type->data.pointer.bit_offset_in_host &&
+ actual_ptr_type->data.pointer.host_int_bytes == wanted_ptr_type->data.pointer.host_int_bytes &&
+ get_ptr_align(ira->codegen, actual_ptr_type) >= get_ptr_align(ira->codegen, wanted_ptr_type))
{
return result;
}
@@ -8912,7 +9070,9 @@ static void update_errors_helper(CodeGen *g, ErrorTableEntry ***errors, size_t *
*errors = reallocate(*errors, old_errors_count, *errors_count);
}
-static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type, IrInstruction **instructions, size_t instruction_count) {
+static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigType *expected_type,
+ IrInstruction **instructions, size_t instruction_count)
+{
Error err;
assert(instruction_count >= 1);
IrInstruction *prev_inst = instructions[0];
@@ -9229,6 +9389,37 @@ static ZigType *ir_resolve_peer_types(IrAnalyze *ira, AstNode *source_node, ZigT
continue;
}
+ if (prev_type->id == ZigTypeIdPointer && prev_type->data.pointer.ptr_len == PtrLenC &&
+ (cur_type->id == ZigTypeIdComptimeInt || cur_type->id == ZigTypeIdInt))
+ {
+ continue;
+ }
+
+ if (cur_type->id == ZigTypeIdPointer && cur_type->data.pointer.ptr_len == PtrLenC &&
+ (prev_type->id == ZigTypeIdComptimeInt || prev_type->id == ZigTypeIdInt))
+ {
+ prev_inst = cur_inst;
+ continue;
+ }
+
+ if (prev_type->id == ZigTypeIdPointer && cur_type->id == ZigTypeIdPointer) {
+ if (prev_type->data.pointer.ptr_len == PtrLenC &&
+ types_match_const_cast_only(ira, prev_type->data.pointer.child_type,
+ cur_type->data.pointer.child_type, source_node,
+ !prev_type->data.pointer.is_const).id == ConstCastResultIdOk)
+ {
+ continue;
+ }
+ if (cur_type->data.pointer.ptr_len == PtrLenC &&
+ types_match_const_cast_only(ira, cur_type->data.pointer.child_type,
+ prev_type->data.pointer.child_type, source_node,
+ !cur_type->data.pointer.is_const).id == ConstCastResultIdOk)
+ {
+ prev_inst = cur_inst;
+ continue;
+ }
+ }
+
if (types_match_const_cast_only(ira, prev_type, cur_type, source_node, false).id == ConstCastResultIdOk) {
continue;
}
@@ -9534,9 +9725,6 @@ static bool eval_const_expr_implicit_cast(IrAnalyze *ira, IrInstruction *source_
}
const_val->type = new_type;
break;
- case CastOpResizeSlice:
- // can't do it
- zig_unreachable();
case CastOpIntToFloat:
{
assert(new_type->id == ZigTypeIdFloat);
@@ -9600,9 +9788,7 @@ static IrInstruction *ir_const(IrAnalyze *ira, IrInstruction *old_instruction, Z
static IrInstruction *ir_resolve_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
ZigType *wanted_type, CastOp cast_op, bool need_alloca)
{
- if ((instr_is_comptime(value) || !type_has_bits(wanted_type)) &&
- cast_op != CastOpResizeSlice)
- {
+ if (instr_is_comptime(value) || !type_has_bits(wanted_type)) {
IrInstruction *result = ir_const(ira, source_instr, wanted_type);
if (!eval_const_expr_implicit_cast(ira, source_instr, cast_op, &value->value, value->value.type,
&result->value, wanted_type))
@@ -9864,7 +10050,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
if (undef_allowed == UndefOk) {
return &value->value;
} else {
- ir_add_error(ira, value, buf_sprintf("use of undefined value"));
+ ir_add_error(ira, value, buf_sprintf("use of undefined value here causes undefined behavior"));
return nullptr;
}
}
@@ -9874,7 +10060,7 @@ static ConstExprValue *ir_resolve_const(IrAnalyze *ira, IrInstruction *value, Un
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
- IrExecutable *parent_exec)
+ IrExecutable *parent_exec, AstNode *expected_type_source_node)
{
if (expected_type != nullptr && type_is_invalid(expected_type))
return &codegen->invalid_instruction->value;
@@ -9910,7 +10096,7 @@ ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *nod
analyzed_executable->backward_branch_count = backward_branch_count;
analyzed_executable->backward_branch_quota = backward_branch_quota;
analyzed_executable->begin_scope = scope;
- ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, node);
+ ZigType *result_type = ir_analyze(codegen, ir_executable, analyzed_executable, expected_type, expected_type_source_node);
if (type_is_invalid(result_type))
return &codegen->invalid_instruction->value;
@@ -10230,49 +10416,75 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
return result;
}
-static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr,
- IrInstruction *target, ZigType *wanted_type)
-{
+static ZigType *ir_resolve_union_tag_type(IrAnalyze *ira, IrInstruction *source_instr, ZigType *union_type) {
+ assert(union_type->id == ZigTypeIdUnion);
+
Error err;
- assert(wanted_type->id == ZigTypeIdInt || wanted_type->id == ZigTypeIdComptimeInt);
+ if ((err = type_resolve(ira->codegen, union_type, ResolveStatusSizeKnown)))
+ return ira->codegen->builtin_types.entry_invalid;
- ZigType *actual_type = target->value.type;
- if ((err = ensure_complete_type(ira->codegen, actual_type)))
- return ira->codegen->invalid_instruction;
+ AstNode *decl_node = union_type->data.unionation.decl_node;
+ if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {
+ assert(union_type->data.unionation.tag_type != nullptr);
+ return union_type->data.unionation.tag_type;
+ } else {
+ ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("union '%s' has no tag",
+ buf_ptr(&union_type->name)));
+ add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here"));
+ return ira->codegen->builtin_types.entry_invalid;
+ }
+}
- if (wanted_type != actual_type->data.enumeration.tag_int_type) {
- ir_add_error(ira, source_instr,
- buf_sprintf("enum to integer cast to '%s' instead of its tag type, '%s'",
- buf_ptr(&wanted_type->name),
- buf_ptr(&actual_type->data.enumeration.tag_int_type->name)));
+static IrInstruction *ir_analyze_enum_to_int(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target) {
+ Error err;
+
+ IrInstruction *enum_target;
+ ZigType *enum_type;
+ if (target->value.type->id == ZigTypeIdUnion) {
+ enum_type = ir_resolve_union_tag_type(ira, target, target->value.type);
+ if (type_is_invalid(enum_type))
+ return ira->codegen->invalid_instruction;
+ enum_target = ir_implicit_cast(ira, target, enum_type);
+ if (type_is_invalid(enum_target->value.type))
+ return ira->codegen->invalid_instruction;
+ } else if (target->value.type->id == ZigTypeIdEnum) {
+ enum_target = target;
+ enum_type = target->value.type;
+ } else {
+ ir_add_error(ira, target,
+ buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name)));
return ira->codegen->invalid_instruction;
}
- assert(actual_type->id == ZigTypeIdEnum);
+ if ((err = type_resolve(ira->codegen, enum_type, ResolveStatusSizeKnown)))
+ return ira->codegen->invalid_instruction;
- if (instr_is_comptime(target)) {
- ConstExprValue *val = ir_resolve_const(ira, target, UndefBad);
+ ZigType *tag_type = enum_type->data.enumeration.tag_int_type;
+ assert(tag_type->id == ZigTypeIdInt || tag_type->id == ZigTypeIdComptimeInt);
+
+ if (instr_is_comptime(enum_target)) {
+ ConstExprValue *val = ir_resolve_const(ira, enum_target, UndefBad);
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_const(ira, source_instr, wanted_type);
- init_const_bigint(&result->value, wanted_type, &val->data.x_enum_tag);
+ IrInstruction *result = ir_const(ira, source_instr, tag_type);
+ init_const_bigint(&result->value, tag_type, &val->data.x_enum_tag);
return result;
}
// If there is only one possible tag, then we know at comptime what it is.
- if (actual_type->data.enumeration.layout == ContainerLayoutAuto &&
- actual_type->data.enumeration.src_field_count == 1)
+ if (enum_type->data.enumeration.layout == ContainerLayoutAuto &&
+ enum_type->data.enumeration.src_field_count == 1)
{
- assert(wanted_type== ira->codegen->builtin_types.entry_num_lit_int);
- IrInstruction *result = ir_const(ira, source_instr, wanted_type);
- init_const_bigint(&result->value, wanted_type,
- &actual_type->data.enumeration.fields[0].value);
+ assert(tag_type == ira->codegen->builtin_types.entry_num_lit_int);
+ IrInstruction *result = ir_const(ira, source_instr, tag_type);
+ init_const_bigint(&result->value, tag_type,
+ &enum_type->data.enumeration.fields[0].value);
return result;
}
IrInstruction *result = ir_build_widen_or_shorten(&ira->new_irb, source_instr->scope,
- source_instr->source_node, target);
- result->value.type = wanted_type;
+ source_instr->source_node, enum_target);
+ result->value.type = tag_type;
return result;
}
@@ -10770,17 +10982,37 @@ static void report_recursive_error(IrAnalyze *ira, AstNode *source_node, ConstCa
report_recursive_error(ira, source_node, cast_result->data.fn_arg.child, msg);
break;
}
+ case ConstCastResultIdBadAllowsZero: {
+ ZigType *wanted_type = cast_result->data.bad_allows_zero->wanted_type;
+ ZigType *actual_type = cast_result->data.bad_allows_zero->actual_type;
+ bool wanted_allows_zero = ptr_allows_addr_zero(wanted_type);
+ bool actual_allows_zero = ptr_allows_addr_zero(actual_type);
+ if (actual_allows_zero && !wanted_allows_zero) {
+ add_error_note(ira->codegen, parent_msg, source_node,
+ buf_sprintf("'%s' could have null values which are illegal in type '%s'",
+ buf_ptr(&actual_type->name),
+ buf_ptr(&wanted_type->name)));
+ } else {
+ add_error_note(ira->codegen, parent_msg, source_node,
+ buf_sprintf("mutable '%s' allows illegal null values stored to type '%s'",
+ buf_ptr(&wanted_type->name),
+ buf_ptr(&actual_type->name)));
+ }
+ break;
+ }
+ case ConstCastResultIdFnIsGeneric:
+ add_error_note(ira->codegen, parent_msg, source_node,
+ buf_sprintf("only one of the functions is generic"));
+ break;
case ConstCastResultIdFnAlign: // TODO
case ConstCastResultIdFnCC: // TODO
case ConstCastResultIdFnVarArgs: // TODO
- case ConstCastResultIdFnIsGeneric: // TODO
case ConstCastResultIdFnReturnType: // TODO
case ConstCastResultIdFnArgCount: // TODO
case ConstCastResultIdFnGenericArgCount: // TODO
case ConstCastResultIdFnArgNoAlias: // TODO
case ConstCastResultIdUnresolvedInferredErrSet: // TODO
case ConstCastResultIdAsyncAllocatorType: // TODO
- case ConstCastResultIdNullWrapPtr: // TODO
break;
}
}
@@ -10811,6 +11043,39 @@ static IrInstruction *ir_analyze_vector_to_array(IrAnalyze *ira, IrInstruction *
return ir_build_vector_to_array(ira, source_instr, vector, array_type);
}
+static IrInstruction *ir_analyze_int_to_c_ptr(IrAnalyze *ira, IrInstruction *source_instr,
+ IrInstruction *integer, ZigType *dest_type)
+{
+ IrInstruction *unsigned_integer;
+ if (instr_is_comptime(integer)) {
+ unsigned_integer = integer;
+ } else {
+ assert(integer->value.type->id == ZigTypeIdInt);
+
+ if (integer->value.type->data.integral.bit_count >
+ ira->codegen->builtin_types.entry_usize->data.integral.bit_count)
+ {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("integer type '%s' too big for implicit @intToPtr to type '%s'",
+ buf_ptr(&integer->value.type->name),
+ buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (integer->value.type->data.integral.is_signed) {
+ ZigType *unsigned_int_type = get_int_type(ira->codegen, false,
+ integer->value.type->data.integral.bit_count);
+ unsigned_integer = ir_analyze_bit_cast(ira, source_instr, integer, unsigned_int_type);
+ if (type_is_invalid(unsigned_integer->value.type))
+ return ira->codegen->invalid_instruction;
+ } else {
+ unsigned_integer = integer;
+ }
+ }
+
+ return ir_analyze_int_to_ptr(ira, source_instr, unsigned_integer, dest_type);
+}
+
static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr,
ZigType *wanted_type, IrInstruction *value)
{
@@ -11182,7 +11447,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
actual_type->data.pointer.host_int_bytes == dest_ptr_type->data.pointer.host_int_bytes &&
get_ptr_align(ira->codegen, actual_type) >= get_ptr_align(ira->codegen, dest_ptr_type))
{
- return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr);
+ return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
}
}
@@ -11217,6 +11482,23 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
return ir_analyze_array_to_vector(ira, source_instr, value, wanted_type);
}
+ // casting between C pointers and normal pointers
+ if (wanted_type->id == ZigTypeIdPointer && actual_type->id == ZigTypeIdPointer &&
+ (wanted_type->data.pointer.ptr_len == PtrLenC || actual_type->data.pointer.ptr_len == PtrLenC) &&
+ types_match_const_cast_only(ira, wanted_type->data.pointer.child_type,
+ actual_type->data.pointer.child_type, source_node,
+ !wanted_type->data.pointer.is_const).id == ConstCastResultIdOk)
+ {
+ return ir_analyze_ptr_cast(ira, source_instr, value, wanted_type, source_instr, true);
+ }
+
+ // cast from integer to C pointer
+ if (wanted_type->id == ZigTypeIdPointer && wanted_type->data.pointer.ptr_len == PtrLenC &&
+ (actual_type->id == ZigTypeIdInt || actual_type->id == ZigTypeIdComptimeInt))
+ {
+ return ir_analyze_int_to_c_ptr(ira, source_instr, value, wanted_type);
+ }
+
// cast from undefined to anything
if (actual_type->id == ZigTypeIdUndefined) {
return ir_analyze_undefined_to_anything(ira, source_instr, value, wanted_type);
@@ -11286,13 +11568,14 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
IrInstructionRef *ref_inst = reinterpret_cast(ptr);
return ref_inst->value;
}
- IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
- source_instruction->source_node, ptr);
- load_ptr_instruction->value.type = child_type;
- return load_ptr_instruction;
+ IrInstruction *result = ir_build_load_ptr_gen(ira, source_instruction, ptr, child_type);
+ if (type_entry->data.pointer.host_int_bytes != 0 && handle_is_ptr(child_type)) {
+ ir_add_alloca(ira, result, child_type);
+ }
+ return result;
} else {
ir_add_error_node(ira, source_instruction->source_node,
- buf_sprintf("attempt to dereference non pointer type '%s'",
+ buf_sprintf("attempt to dereference non-pointer type '%s'",
buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
}
@@ -11588,28 +11871,34 @@ static IrInstruction *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp
}
static bool resolve_cmp_op_id(IrBinOp op_id, Cmp cmp) {
- if (op_id == IrBinOpCmpEq) {
- return cmp == CmpEQ;
- } else if (op_id == IrBinOpCmpNotEq) {
- return cmp != CmpEQ;
- } else if (op_id == IrBinOpCmpLessThan) {
- return cmp == CmpLT;
- } else if (op_id == IrBinOpCmpGreaterThan) {
- return cmp == CmpGT;
- } else if (op_id == IrBinOpCmpLessOrEq) {
- return cmp != CmpGT;
- } else if (op_id == IrBinOpCmpGreaterOrEq) {
- return cmp != CmpLT;
- } else {
- zig_unreachable();
+ switch (op_id) {
+ case IrBinOpCmpEq:
+ return cmp == CmpEQ;
+ case IrBinOpCmpNotEq:
+ return cmp != CmpEQ;
+ case IrBinOpCmpLessThan:
+ return cmp == CmpLT;
+ case IrBinOpCmpGreaterThan:
+ return cmp == CmpGT;
+ case IrBinOpCmpLessOrEq:
+ return cmp != CmpGT;
+ case IrBinOpCmpGreaterOrEq:
+ return cmp != CmpLT;
+ default:
+ zig_unreachable();
}
}
static bool optional_value_is_null(ConstExprValue *val) {
assert(val->special == ConstValSpecialStatic);
if (get_codegen_ptr_type(val->type) != nullptr) {
- return val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
- val->data.x_ptr.data.hard_coded_addr.addr == 0;
+ if (val->data.x_ptr.special == ConstPtrSpecialNull) {
+ return true;
+ } else if (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr) {
+ return val->data.x_ptr.data.hard_coded_addr.addr == 0;
+ } else {
+ return false;
+ }
} else if (is_opt_err_set(val->type)) {
return val->data.x_err_set == nullptr;
} else {
@@ -11773,7 +12062,6 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
case ZigTypeIdBool:
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
- case ZigTypeIdPointer:
case ZigTypeIdErrorSet:
case ZigTypeIdFn:
case ZigTypeIdOpaque:
@@ -11785,6 +12073,10 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
operator_allowed = is_equality_cmp;
break;
+ case ZigTypeIdPointer:
+ operator_allowed = is_equality_cmp || (resolved_type->data.pointer.ptr_len == PtrLenC);
+ break;
+
case ZigTypeIdUnreachable:
case ZigTypeIdArray:
case ZigTypeIdStruct:
@@ -11832,15 +12124,38 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
if (op2_val == nullptr)
return ira->codegen->invalid_instruction;
- bool answer;
if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
Cmp cmp_result = float_cmp(op1_val, op2_val);
- answer = resolve_cmp_op_id(op_id, cmp_result);
+ bool answer = resolve_cmp_op_id(op_id, cmp_result);
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
} else if (resolved_type->id == ZigTypeIdComptimeInt || resolved_type->id == ZigTypeIdInt) {
Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
- answer = resolve_cmp_op_id(op_id, cmp_result);
+ bool answer = resolve_cmp_op_id(op_id, cmp_result);
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
+ } else if (resolved_type->id == ZigTypeIdPointer && op_id != IrBinOpCmpEq && op_id != IrBinOpCmpNotEq) {
+ if ((op1_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
+ op1_val->data.x_ptr.special == ConstPtrSpecialNull) &&
+ (op2_val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
+ op2_val->data.x_ptr.special == ConstPtrSpecialNull))
+ {
+ uint64_t op1_addr = op1_val->data.x_ptr.special == ConstPtrSpecialNull ?
+ 0 : op1_val->data.x_ptr.data.hard_coded_addr.addr;
+ uint64_t op2_addr = op2_val->data.x_ptr.special == ConstPtrSpecialNull ?
+ 0 : op2_val->data.x_ptr.data.hard_coded_addr.addr;
+ Cmp cmp_result;
+ if (op1_addr > op2_addr) {
+ cmp_result = CmpGT;
+ } else if (op1_addr < op2_addr) {
+ cmp_result = CmpLT;
+ } else {
+ cmp_result = CmpEQ;
+ }
+ bool answer = resolve_cmp_op_id(op_id, cmp_result);
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
+ }
} else {
bool are_equal = one_possible_value || const_values_equal(ira->codegen, op1_val, op2_val);
+ bool answer;
if (op_id == IrBinOpCmpEq) {
answer = are_equal;
} else if (op_id == IrBinOpCmpNotEq) {
@@ -11848,9 +12163,8 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
} else {
zig_unreachable();
}
+ return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
-
- return ir_const_bool(ira, &bin_op_instruction->base, answer);
}
// some comparisons with unsigned numbers can be evaluated
@@ -12245,7 +12559,29 @@ static bool ok_float_op(IrBinOp op) {
zig_unreachable();
}
+static bool is_pointer_arithmetic_allowed(ZigType *lhs_type, IrBinOp op) {
+ if (lhs_type->id != ZigTypeIdPointer)
+ return false;
+ switch (op) {
+ case IrBinOpAdd:
+ case IrBinOpSub:
+ break;
+ default:
+ return false;
+ }
+ switch (lhs_type->data.pointer.ptr_len) {
+ case PtrLenSingle:
+ return false;
+ case PtrLenUnknown:
+ case PtrLenC:
+ break;
+ }
+ return true;
+}
+
static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp *instruction) {
+ Error err;
+
IrInstruction *op1 = instruction->op1->child;
if (type_is_invalid(op1->value.type))
return ira->codegen->invalid_instruction;
@@ -12257,13 +12593,44 @@ static IrInstruction *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp
IrBinOp op_id = instruction->op_id;
// look for pointer math
- if (op1->value.type->id == ZigTypeIdPointer && op1->value.type->data.pointer.ptr_len == PtrLenUnknown &&
- (op_id == IrBinOpAdd || op_id == IrBinOpSub))
- {
+ if (is_pointer_arithmetic_allowed(op1->value.type, op_id)) {
IrInstruction *casted_op2 = ir_implicit_cast(ira, op2, ira->codegen->builtin_types.entry_usize);
- if (casted_op2 == ira->codegen->invalid_instruction)
+ if (type_is_invalid(casted_op2->value.type))
return ira->codegen->invalid_instruction;
+ if (op1->value.special == ConstValSpecialUndef || casted_op2->value.special == ConstValSpecialUndef) {
+ IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
+ result->value.special = ConstValSpecialUndef;
+ return result;
+ }
+ if (casted_op2->value.special == ConstValSpecialStatic && op1->value.special == ConstValSpecialStatic &&
+ (op1->value.data.x_ptr.special == ConstPtrSpecialHardCodedAddr ||
+ op1->value.data.x_ptr.special == ConstPtrSpecialNull))
+ {
+ uint64_t start_addr = (op1->value.data.x_ptr.special == ConstPtrSpecialNull) ?
+ 0 : op1->value.data.x_ptr.data.hard_coded_addr.addr;
+ uint64_t elem_offset;
+ if (!ir_resolve_usize(ira, casted_op2, &elem_offset))
+ return ira->codegen->invalid_instruction;
+ ZigType *elem_type = op1->value.type->data.pointer.child_type;
+ if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
+ return ira->codegen->invalid_instruction;
+ uint64_t byte_offset = type_size(ira->codegen, elem_type) * elem_offset;
+ uint64_t new_addr;
+ if (op_id == IrBinOpAdd) {
+ new_addr = start_addr + byte_offset;
+ } else if (op_id == IrBinOpSub) {
+ new_addr = start_addr - byte_offset;
+ } else {
+ zig_unreachable();
+ }
+ IrInstruction *result = ir_const(ira, &instruction->base, op1->value.type);
+ result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+ result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
+ result->value.data.x_ptr.data.hard_coded_addr.addr = new_addr;
+ return result;
+ }
+
IrInstruction *result = ir_build_bin_op(&ira->new_irb, instruction->base.scope,
instruction->base.source_node, op_id, op1, casted_op2, true);
result->value.type = op1->value.type;
@@ -12878,6 +13245,20 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira,
return ir_build_var_decl_gen(ira, &decl_var_instruction->base, var, casted_init_value);
}
+static VarLinkage global_linkage_to_var_linkage(GlobalLinkageId id) {
+ switch (id) {
+ case GlobalLinkageIdStrong:
+ return VarLinkageExportStrong;
+ case GlobalLinkageIdWeak:
+ return VarLinkageExportWeak;
+ case GlobalLinkageIdLinkOnce:
+ return VarLinkageExportLinkOnce;
+ case GlobalLinkageIdInternal:
+ return VarLinkageInternal;
+ }
+ zig_unreachable();
+}
+
static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructionExport *instruction) {
IrInstruction *name = instruction->name->child;
Buf *symbol_name = ir_resolve_str(ira, name);
@@ -12898,14 +13279,24 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
}
}
- auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, instruction->base.source_node);
+ // TODO: This function needs to be audited.
+ // It's not clear how all the different types are supposed to be handled.
+ // Need comprehensive tests for exporting one thing in one file and declaring an extern var
+ // in another file.
+ TldFn *tld_fn = allocate(1);
+ tld_fn->base.id = TldIdFn;
+ tld_fn->base.source_node = instruction->base.source_node;
+
+ auto entry = ira->codegen->exported_symbol_names.put_unique(symbol_name, &tld_fn->base);
if (entry) {
- AstNode *other_export_node = entry->value;
+ AstNode *other_export_node = entry->value->source_node;
ErrorMsg *msg = ir_add_error(ira, &instruction->base,
buf_sprintf("exported symbol collision: '%s'", buf_ptr(symbol_name)));
add_error_note(ira->codegen, msg, other_export_node, buf_sprintf("other symbol is here"));
+ return ira->codegen->invalid_instruction;
}
+ bool want_var_export = false;
switch (target->value.type->id) {
case ZigTypeIdInvalid:
case ZigTypeIdUnreachable:
@@ -12913,6 +13304,7 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
case ZigTypeIdFn: {
assert(target->value.data.x_ptr.special == ConstPtrSpecialFunction);
ZigFn *fn_entry = target->value.data.x_ptr.data.fn.fn_entry;
+ tld_fn->fn_entry = fn_entry;
CallingConvention cc = fn_entry->type_entry->data.fn.fn_type_id.cc;
switch (cc) {
case CallingConventionUnspecified: {
@@ -12941,6 +13333,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
ErrorMsg *msg = ir_add_error(ira, target,
buf_sprintf("exported struct value must be declared extern"));
add_error_note(ira->codegen, msg, target->value.type->data.structure.decl_node, buf_sprintf("declared here"));
+ } else {
+ want_var_export = true;
}
break;
case ZigTypeIdUnion:
@@ -12948,6 +13342,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
ErrorMsg *msg = ir_add_error(ira, target,
buf_sprintf("exported union value must be declared extern"));
add_error_note(ira->codegen, msg, target->value.type->data.unionation.decl_node, buf_sprintf("declared here"));
+ } else {
+ want_var_export = true;
}
break;
case ZigTypeIdEnum:
@@ -12955,6 +13351,8 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
ErrorMsg *msg = ir_add_error(ira, target,
buf_sprintf("exported enum value must be declared extern"));
add_error_note(ira->codegen, msg, target->value.type->data.enumeration.decl_node, buf_sprintf("declared here"));
+ } else {
+ want_var_export = true;
}
break;
case ZigTypeIdMetaType: {
@@ -13044,6 +13442,16 @@ static IrInstruction *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructio
break;
}
+ // TODO audit the various ways to use @export
+ if (want_var_export && target->id == IrInstructionIdLoadPtrGen) {
+ IrInstructionLoadPtrGen *load_ptr = reinterpret_cast(target);
+ if (load_ptr->ptr->id == IrInstructionIdVarPtr) {
+ IrInstructionVarPtr *var_ptr = reinterpret_cast(load_ptr->ptr);
+ ZigVar *var = var_ptr->var;
+ var->linkage = global_linkage_to_var_linkage(global_linkage_id);
+ }
+ }
+
return ir_const_void(ira, &instruction->base);
}
@@ -13331,9 +13739,16 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
if (var->var_type == nullptr || type_is_invalid(var->var_type))
return ira->codegen->invalid_instruction;
- bool comptime_var_mem = ir_get_var_is_comptime(var);
-
ConstExprValue *mem_slot = nullptr;
+
+ bool comptime_var_mem = ir_get_var_is_comptime(var);
+ bool linkage_makes_it_runtime = var->linkage == VarLinkageExternal;
+ bool is_const = var->src_is_const;
+ bool is_volatile = false;
+
+ if (linkage_makes_it_runtime)
+ goto no_mem_slot;
+
if (var->const_value->special == ConstValSpecialStatic) {
mem_slot = var->const_value;
} else {
@@ -13347,8 +13762,6 @@ static IrInstruction *ir_get_var_ptr(IrAnalyze *ira, IrInstruction *instruction,
}
}
- bool is_const = var->src_is_const;
- bool is_volatile = false;
if (mem_slot != nullptr) {
switch (mem_slot->special) {
case ConstValSpecialRuntime:
@@ -13387,26 +13800,32 @@ no_mem_slot:
static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source_instr,
IrInstruction *ptr, IrInstruction *uncasted_value)
{
- if (ptr->value.type->id != ZigTypeIdPointer) {
- ir_add_error(ira, ptr,
- buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr->value.type->name)));
- return ira->codegen->invalid_instruction;
- }
+ assert(ptr->value.type->id == ZigTypeIdPointer);
if (ptr->value.data.x_ptr.special == ConstPtrSpecialDiscard) {
return ir_const_void(ira, source_instr);
}
+ ZigType *child_type = ptr->value.type->data.pointer.child_type;
+
if (ptr->value.type->data.pointer.is_const && !source_instr->is_gen) {
ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
return ira->codegen->invalid_instruction;
}
- ZigType *child_type = ptr->value.type->data.pointer.child_type;
IrInstruction *value = ir_implicit_cast(ira, uncasted_value, child_type);
if (value == ira->codegen->invalid_instruction)
return ira->codegen->invalid_instruction;
+ switch (type_has_one_possible_value(ira->codegen, child_type)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes:
+ return ir_const_void(ira, source_instr);
+ case OnePossibleValueNo:
+ break;
+ }
+
if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) {
if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst) {
ir_add_error(ira, source_instr, buf_sprintf("cannot assign to constant"));
@@ -13427,15 +13846,7 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
bool same_global_refs = ptr->value.data.x_ptr.mut != ConstPtrMutComptimeVar;
copy_const_val(dest_val, &value->value, same_global_refs);
if (!ira->new_irb.current_basic_block->must_be_comptime_source_instr) {
- switch (type_has_one_possible_value(ira->codegen, child_type)) {
- case OnePossibleValueInvalid:
- return ira->codegen->invalid_instruction;
- case OnePossibleValueNo:
- ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
- break;
- case OnePossibleValueYes:
- break;
- }
+ ira->new_irb.current_basic_block->must_be_comptime_source_instr = source_instr;
}
return ir_const_void(ira, source_instr);
}
@@ -13630,7 +14041,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
AstNode *body_node = fn_entry->body_node;
result = ir_eval_const_value(ira->codegen, exec_scope, body_node, return_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, fn_entry,
- nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec);
+ nullptr, call_instruction->base.source_node, nullptr, ira->new_irb.exec, return_type_node);
if (inferred_err_set_type != nullptr) {
inferred_err_set_type->data.error_set.infer_fn = nullptr;
@@ -13826,7 +14237,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *call
ConstExprValue *align_result = ir_eval_const_value(ira->codegen, impl_fn->child_scope,
fn_proto_node->data.fn_proto.align_expr, get_align_amt_type(ira->codegen),
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota,
- nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec);
+ nullptr, nullptr, fn_proto_node->data.fn_proto.align_expr, nullptr, ira->new_irb.exec, nullptr);
IrInstructionConst *const_instruction = ir_create_instruction(&ira->new_irb,
impl_fn->child_scope, fn_proto_node->data.fn_proto.align_expr);
const_instruction->base.value = *align_result;
@@ -14108,12 +14519,11 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
size_t src_size = type_size(codegen, pointee->type);
size_t dst_size = type_size(codegen, out_val->type);
- if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
- copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
- return ErrorNone;
- }
-
if (dst_size <= src_size) {
+ if (src_size == dst_size && types_have_same_zig_comptime_repr(pointee->type, out_val->type)) {
+ copy_const_val(out_val, pointee, ptr_val->data.x_ptr.mut == ConstPtrMutComptimeConst);
+ return ErrorNone;
+ }
Buf buf = BUF_INIT;
buf_resize(&buf, src_size);
buf_write_value_bytes(codegen, (uint8_t*)buf_ptr(&buf), pointee);
@@ -14129,12 +14539,12 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
if (dst_size == 0)
return ErrorNone;
opt_ir_add_error_node(ira, codegen, source_node,
- buf_sprintf("attempt to read %zu bytes from null pointer",
+ buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from null pointer",
dst_size));
return ErrorSemanticAnalyzeFail;
case ConstPtrSpecialRef: {
opt_ir_add_error_node(ira, codegen, source_node,
- buf_sprintf("attempt to read %zu bytes from pointer to %s which is %zu bytes",
+ buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from pointer to %s which is %" ZIG_PRI_usize " bytes",
dst_size, buf_ptr(&pointee->type->name), src_size));
return ErrorSemanticAnalyzeFail;
}
@@ -14148,7 +14558,7 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
src_size = elem_size * (array_val->type->data.array.len - elem_index);
if (dst_size > src_size) {
opt_ir_add_error_node(ira, codegen, source_node,
- buf_sprintf("attempt to read %zu bytes from %s at index %" ZIG_PRI_usize " which is %zu bytes",
+ buf_sprintf("attempt to read %" ZIG_PRI_usize " bytes from %s at index %" ZIG_PRI_usize " which is %" ZIG_PRI_usize " bytes",
dst_size, buf_ptr(&array_val->type->name), elem_index, src_size));
return ErrorSemanticAnalyzeFail;
}
@@ -14220,6 +14630,41 @@ static IrInstruction *ir_analyze_maybe(IrAnalyze *ira, IrInstructionUnOp *un_op_
zig_unreachable();
}
+static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *scalar_type,
+ ConstExprValue *operand_val, ConstExprValue *scalar_out_val, bool is_wrap_op)
+{
+ bool is_float = (scalar_type->id == ZigTypeIdFloat || scalar_type->id == ZigTypeIdComptimeFloat);
+
+ bool ok_type = ((scalar_type->id == ZigTypeIdInt && scalar_type->data.integral.is_signed) ||
+ scalar_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op));
+
+ if (!ok_type) {
+ const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
+ return ir_add_error(ira, source_instr, buf_sprintf(fmt, buf_ptr(&scalar_type->name)));
+ }
+
+ if (is_float) {
+ float_negate(scalar_out_val, operand_val);
+ } else if (is_wrap_op) {
+ bigint_negate_wrap(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint,
+ scalar_type->data.integral.bit_count);
+ } else {
+ bigint_negate(&scalar_out_val->data.x_bigint, &operand_val->data.x_bigint);
+ }
+
+ scalar_out_val->type = scalar_type;
+ scalar_out_val->special = ConstValSpecialStatic;
+
+ if (is_wrap_op || is_float || scalar_type->id == ZigTypeIdComptimeInt) {
+ return nullptr;
+ }
+
+ if (!bigint_fits_in_bits(&scalar_out_val->data.x_bigint, scalar_type->data.integral.bit_count, true)) {
+ return ir_add_error(ira, source_instr, buf_sprintf("negation caused overflow"));
+ }
+ return nullptr;
+}
+
static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *instruction) {
IrInstruction *value = instruction->value->child;
ZigType *expr_type = value->value.type;
@@ -14228,47 +14673,50 @@ static IrInstruction *ir_analyze_negation(IrAnalyze *ira, IrInstructionUnOp *ins
bool is_wrap_op = (instruction->op_id == IrUnOpNegationWrap);
- bool is_float = (expr_type->id == ZigTypeIdFloat || expr_type->id == ZigTypeIdComptimeFloat);
+ ZigType *scalar_type = (expr_type->id == ZigTypeIdVector) ? expr_type->data.vector.elem_type : expr_type;
- if ((expr_type->id == ZigTypeIdInt && expr_type->data.integral.is_signed) ||
- expr_type->id == ZigTypeIdComptimeInt || (is_float && !is_wrap_op))
- {
- if (instr_is_comptime(value)) {
- ConstExprValue *target_const_val = ir_resolve_const(ira, value, UndefBad);
- if (!target_const_val)
- return ira->codegen->invalid_instruction;
+ if (instr_is_comptime(value)) {
+ ConstExprValue *operand_val = ir_resolve_const(ira, value, UndefBad);
+ if (!operand_val)
+ return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_const(ira, &instruction->base, expr_type);
- ConstExprValue *out_val = &result->value;
- if (is_float) {
- float_negate(out_val, target_const_val);
- } else if (is_wrap_op) {
- bigint_negate_wrap(&out_val->data.x_bigint, &target_const_val->data.x_bigint,
- expr_type->data.integral.bit_count);
- } else {
- bigint_negate(&out_val->data.x_bigint, &target_const_val->data.x_bigint);
+ IrInstruction *result_instruction = ir_const(ira, &instruction->base, expr_type);
+ ConstExprValue *out_val = &result_instruction->value;
+ if (expr_type->id == ZigTypeIdVector) {
+ expand_undef_array(ira->codegen, operand_val);
+ out_val->special = ConstValSpecialUndef;
+ expand_undef_array(ira->codegen, out_val);
+ size_t len = expr_type->data.vector.len;
+ for (size_t i = 0; i < len; i += 1) {
+ ConstExprValue *scalar_operand_val = &operand_val->data.x_array.data.s_none.elements[i];
+ ConstExprValue *scalar_out_val = &out_val->data.x_array.data.s_none.elements[i];
+ assert(scalar_operand_val->type == scalar_type);
+ assert(scalar_out_val->type == scalar_type);
+ ErrorMsg *msg = ir_eval_negation_scalar(ira, &instruction->base, scalar_type,
+ scalar_operand_val, scalar_out_val, is_wrap_op);
+ if (msg != nullptr) {
+ add_error_note(ira->codegen, msg, instruction->base.source_node,
+ buf_sprintf("when computing vector element at index %" ZIG_PRI_usize, i));
+ return ira->codegen->invalid_instruction;
+ }
}
- if (is_wrap_op || is_float || expr_type->id == ZigTypeIdComptimeInt) {
- return result;
- }
-
- if (!bigint_fits_in_bits(&out_val->data.x_bigint, expr_type->data.integral.bit_count, true)) {
- ir_add_error(ira, &instruction->base, buf_sprintf("negation caused overflow"));
+ out_val->type = expr_type;
+ out_val->special = ConstValSpecialStatic;
+ } else {
+ if (ir_eval_negation_scalar(ira, &instruction->base, scalar_type, operand_val, out_val,
+ is_wrap_op) != nullptr)
+ {
return ira->codegen->invalid_instruction;
}
- return result;
}
-
- IrInstruction *result = ir_build_un_op(&ira->new_irb,
- instruction->base.scope, instruction->base.source_node,
- instruction->op_id, value);
- result->value.type = expr_type;
- return result;
+ return result_instruction;
}
- const char *fmt = is_wrap_op ? "invalid wrapping negation type: '%s'" : "invalid negation type: '%s'";
- ir_add_error(ira, &instruction->base, buf_sprintf(fmt, buf_ptr(&expr_type->name)));
- return ira->codegen->invalid_instruction;
+ IrInstruction *result = ir_build_un_op(&ira->new_irb,
+ instruction->base.scope, instruction->base.source_node,
+ instruction->op_id, value);
+ result->value.type = expr_type;
+ return result;
}
static IrInstruction *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *instruction) {
@@ -14321,11 +14769,18 @@ static IrInstruction *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstruction
buf_ptr(&ptr_type->name)));
return ira->codegen->invalid_instruction;
}
- // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
- // one of the ptr instructions
+
IrInstruction *result = ir_get_deref(ira, &instruction->base, ptr);
if (result == ira->codegen->invalid_instruction)
return ira->codegen->invalid_instruction;
+
+ // If the result needs to be an lvalue, type check it
+ if (instruction->lval == LValPtr && result->value.type->id != ZigTypeIdPointer) {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("attempt to dereference non-pointer type '%s'", buf_ptr(&result->value.type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
return result;
}
case IrUnOpOptional:
@@ -14958,6 +15413,16 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
if (bare_type->id == ZigTypeIdStruct) {
TypeStructField *field = find_struct_type_field(bare_type, field_name);
if (field) {
+ switch (type_has_one_possible_value(ira->codegen, field->type_entry)) {
+ case OnePossibleValueInvalid:
+ return ira->codegen->invalid_instruction;
+ case OnePossibleValueYes: {
+ IrInstruction *elem = ir_const(ira, source_instr, field->type_entry);
+ return ir_get_ref(ira, source_instr, elem, false, false);
+ }
+ case OnePossibleValueNo:
+ break;
+ }
bool is_packed = (bare_type->data.structure.layout == ContainerLayoutPacked);
uint32_t align_bytes = is_packed ? 1 : get_abi_alignment(ira->codegen, field->type_entry);
uint32_t ptr_bit_offset = container_ptr->value.type->data.pointer.bit_offset_in_host;
@@ -15065,6 +15530,14 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
}
static void add_link_lib_symbol(IrAnalyze *ira, Buf *lib_name, Buf *symbol_name, AstNode *source_node) {
+ if (buf_eql_str(lib_name, "c") && ira->codegen->libc_link_lib == nullptr &&
+ !ira->codegen->reported_bad_link_libc_error)
+ {
+ ir_add_error_node(ira, source_node,
+ buf_sprintf("dependency on library c must be explicitly specified in the build command"));
+ ira->codegen->reported_bad_link_libc_error = true;
+ }
+
LinkLib *link_lib = add_link_lib(ira->codegen, lib_name);
for (size_t i = 0; i < link_lib->symbols.length; i += 1) {
Buf *existing_symbol_name = link_lib->symbols.at(i);
@@ -15151,12 +15624,6 @@ static IrInstruction *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstruc
if (type_is_invalid(container_ptr->value.type))
return ira->codegen->invalid_instruction;
- if (container_ptr->value.type->id != ZigTypeIdPointer) {
- ir_add_error_node(ira, field_ptr_instruction->base.source_node,
- buf_sprintf("attempt to dereference non-pointer type '%s'",
- buf_ptr(&container_ptr->value.type->name)));
- return ira->codegen->invalid_instruction;
- }
ZigType *container_type = container_ptr->value.type->data.pointer.child_type;
Buf *field_name = field_ptr_instruction->field_name_buffer;
@@ -15572,6 +16039,8 @@ static IrInstruction *ir_analyze_instruction_typeof(IrAnalyze *ira, IrInstructio
static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
IrInstructionToPtrType *to_ptr_type_instruction)
{
+ Error err;
+
IrInstruction *value = to_ptr_type_instruction->value->child;
ZigType *type_entry = value->value.type;
if (type_is_invalid(type_entry))
@@ -15587,7 +16056,17 @@ static IrInstruction *ir_analyze_instruction_to_ptr_type(IrAnalyze *ira,
ptr_type = get_pointer_to_type(ira->codegen,
type_entry->data.pointer.child_type->data.array.child_type, type_entry->data.pointer.is_const);
} else if (is_slice(type_entry)) {
- ptr_type = adjust_ptr_len(ira->codegen, type_entry->data.structure.fields[0].type_entry, PtrLenSingle);
+ ZigType *slice_ptr_type = type_entry->data.structure.fields[0].type_entry;
+ ptr_type = adjust_ptr_len(ira->codegen, slice_ptr_type, PtrLenSingle);
+ // If the pointer is over-aligned, we may have to reduce it based on the alignment of the element type.
+ if (slice_ptr_type->data.pointer.explicit_alignment != 0) {
+ ZigType *elem_type = slice_ptr_type->data.pointer.child_type;
+ if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusAlignmentKnown)))
+ return ira->codegen->invalid_instruction;
+ uint32_t elem_align = get_abi_alignment(ira->codegen, elem_type);
+ uint32_t reduced_align = min(elem_align, slice_ptr_type->data.pointer.explicit_alignment);
+ ptr_type = adjust_ptr_align(ira->codegen, ptr_type, reduced_align);
+ }
} else if (type_entry->id == ZigTypeIdArgTuple) {
ConstExprValue *arg_tuple_val = ir_resolve_const(ira, value, UndefBad);
if (!arg_tuple_val)
@@ -16355,18 +16834,13 @@ static IrInstruction *ir_analyze_instruction_switch_target(IrAnalyze *ira,
return ir_const_type(ira, &switch_target_instruction->base, ptr_type->data.pointer.child_type);
}
- if (target_value_ptr->value.type->id != ZigTypeIdPointer) {
- ir_add_error(ira, target_value_ptr, buf_sprintf("invalid deref on switch target"));
- return ira->codegen->invalid_instruction;
- }
-
ZigType *target_type = target_value_ptr->value.type->data.pointer.child_type;
ConstExprValue *pointee_val = nullptr;
if (instr_is_comptime(target_value_ptr)) {
pointee_val = const_ptr_pointee(ira, ira->codegen, &target_value_ptr->value, target_value_ptr->source_node);
if (pointee_val == nullptr)
return ira->codegen->invalid_instruction;
-
+
if (pointee_val->special == ConstValSpecialRuntime)
pointee_val = nullptr;
}
@@ -16953,9 +17427,13 @@ static IrInstruction *ir_analyze_instruction_compile_log(IrAnalyze *ira, IrInstr
}
fprintf(stderr, "\n");
- // Here we bypass higher level functions such as ir_add_error because we do not want
- // invalidate_exec to be called.
- add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement"));
+ auto *expr = &instruction->base.source_node->data.fn_call_expr;
+ if (!expr->seen) {
+ // Here we bypass higher level functions such as ir_add_error because we do not want
+ // invalidate_exec to be called.
+ add_node_error(ira->codegen, instruction->base.source_node, buf_sprintf("found compile log statement"));
+ }
+ expr->seen = true;
return ir_const_void(ira, &instruction->base);
}
@@ -17116,7 +17594,7 @@ static IrInstruction *ir_analyze_instruction_field_parent_ptr(IrAnalyze *ira,
static TypeStructField *validate_byte_offset(IrAnalyze *ira,
IrInstruction *type_value,
IrInstruction *field_name_value,
- size_t *byte_offset)
+ size_t *byte_offset)
{
ZigType *container_type = ir_resolve_type(ira, type_value);
if (type_is_invalid(container_type))
@@ -17290,7 +17768,7 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
// Loop through the definitions and generate info.
decl_it = decls_scope->decl_table.entry_iterator();
- curr_entry = nullptr;
+ curr_entry = nullptr;
int definition_index = 0;
while ((curr_entry = decl_it.next()) != nullptr) {
// Skip comptime blocks and test functions.
@@ -17469,6 +17947,18 @@ static Error ir_make_type_info_defs(IrAnalyze *ira, ConstExprValue *out_val, Sco
return ErrorNone;
}
+static uint32_t ptr_len_to_size_enum_index(PtrLen ptr_len) {
+ switch (ptr_len) {
+ case PtrLenSingle:
+ return 0;
+ case PtrLenUnknown:
+ return 1;
+ case PtrLenC:
+ return 3;
+ }
+ zig_unreachable();
+}
+
static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_type_entry) {
Error err;
ZigType *attrs_type;
@@ -17478,7 +17968,7 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
size_enum_index = 2;
} else if (ptr_type_entry->id == ZigTypeIdPointer) {
attrs_type = ptr_type_entry;
- size_enum_index = (ptr_type_entry->data.pointer.ptr_len == PtrLenSingle) ? 0 : 1;
+ size_enum_index = ptr_len_to_size_enum_index(ptr_type_entry->data.pointer.ptr_len);
} else {
zig_unreachable();
}
@@ -18172,12 +18662,6 @@ static IrInstruction *ir_analyze_instruction_type_id(IrAnalyze *ira,
static IrInstruction *ir_analyze_instruction_set_eval_branch_quota(IrAnalyze *ira,
IrInstructionSetEvalBranchQuota *instruction)
{
- if (ira->new_irb.exec->parent_exec != nullptr && !ira->new_irb.exec->is_generic_instantiation) {
- ir_add_error(ira, &instruction->base,
- buf_sprintf("@setEvalBranchQuota must be called from the top of the comptime stack"));
- return ira->codegen->invalid_instruction;
- }
-
uint64_t new_quota;
if (!ir_resolve_usize(ira, instruction->new_quota->child, &new_quota))
return ira->codegen->invalid_instruction;
@@ -18204,12 +18688,6 @@ static IrInstruction *ir_analyze_instruction_type_name(IrAnalyze *ira, IrInstruc
}
static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstructionCImport *instruction) {
- if (ira->codegen->enable_cache) {
- ir_add_error(ira, &instruction->base,
- buf_sprintf("TODO @cImport is incompatible with --cache on. The cache system currently is unable to detect subsequent changes in .h files."));
- return ira->codegen->invalid_instruction;
- }
-
AstNode *node = instruction->base.source_node;
assert(node->type == NodeTypeFnCallExpr);
AstNode *block_node = node->data.fn_call_expr.params.at(0);
@@ -18220,12 +18698,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
ZigType *void_type = ira->codegen->builtin_types.entry_void;
ConstExprValue *cimport_result = ir_eval_const_value(ira->codegen, &cimport_scope->base, block_node, void_type,
ira->new_irb.exec->backward_branch_count, ira->new_irb.exec->backward_branch_quota, nullptr,
- &cimport_scope->buf, block_node, nullptr, nullptr);
+ &cimport_scope->buf, block_node, nullptr, nullptr, nullptr);
if (type_is_invalid(cimport_result->type))
return ira->codegen->invalid_instruction;
- find_libc_include_path(ira->codegen);
-
ImportTableEntry *child_import = allocate(1);
child_import->decls_scope = create_decls_scope(ira->codegen, node, nullptr, nullptr, child_import);
child_import->c_import_node = node;
@@ -18247,6 +18723,10 @@ static IrInstruction *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstruct
if (errors.length > 0) {
ErrorMsg *parent_err_msg = ir_add_error_node(ira, node, buf_sprintf("C import failed"));
+ if (ira->codegen->libc_link_lib == nullptr) {
+ add_error_note(ira->codegen, parent_err_msg, node,
+ buf_sprintf("libc headers not available; compilation does not link against libc"));
+ }
for (size_t i = 0; i < errors.length; i += 1) {
ErrorMsg *err_msg = errors.at(i);
err_msg_add_note(parent_err_msg, err_msg);
@@ -18713,7 +19193,9 @@ static IrInstruction *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstru
}
}
- return ir_resolve_cast(ira, &instruction->base, casted_value, dest_slice_type, CastOpResizeSlice, true);
+ IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, casted_value, dest_slice_type);
+ ir_add_alloca(ira, result, dest_slice_type);
+ return result;
}
static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
@@ -18740,7 +19222,34 @@ static IrInstruction *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstruct
alignment, 0, 0);
ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
- return ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
+ if (instr_is_comptime(target)) {
+ ConstExprValue *target_val = ir_resolve_const(ira, target, UndefBad);
+ if (target_val == nullptr)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, &instruction->base, dest_slice_type);
+ result->value.data.x_struct.fields = create_const_vals(2);
+
+ ConstExprValue *ptr_val = &result->value.data.x_struct.fields[slice_ptr_index];
+ ConstExprValue *target_ptr_val = &target_val->data.x_struct.fields[slice_ptr_index];
+ copy_const_val(ptr_val, target_ptr_val, false);
+ ptr_val->type = dest_ptr_type;
+
+ ConstExprValue *len_val = &result->value.data.x_struct.fields[slice_len_index];
+ len_val->special = ConstValSpecialStatic;
+ len_val->type = ira->codegen->builtin_types.entry_usize;
+ ConstExprValue *target_len_val = &target_val->data.x_struct.fields[slice_len_index];
+ ZigType *elem_type = src_ptr_type->data.pointer.child_type;
+ BigInt elem_size_bigint;
+ bigint_init_unsigned(&elem_size_bigint, type_size(ira->codegen, elem_type));
+ bigint_mul(&len_val->data.x_bigint, &target_len_val->data.x_bigint, &elem_size_bigint);
+
+ return result;
+ }
+
+ IrInstruction *result = ir_build_resize_slice(ira, &instruction->base, target, dest_slice_type);
+ ir_add_alloca(ira, result, dest_slice_type);
+ return result;
}
static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) {
@@ -18952,10 +19461,12 @@ static IrInstruction *ir_analyze_instruction_memset(IrAnalyze *ira, IrInstructio
if (type_is_invalid(casted_count->value.type))
return ira->codegen->invalid_instruction;
+ // TODO test this at comptime with u8 and non-u8 types
if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
casted_byte->value.special == ConstValSpecialStatic &&
casted_count->value.special == ConstValSpecialStatic &&
- casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr)
+ casted_dest_ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr &&
+ casted_dest_ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar)
{
ConstExprValue *dest_ptr_val = &casted_dest_ptr->value;
@@ -19074,6 +19585,8 @@ static IrInstruction *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructio
if (type_is_invalid(casted_count->value.type))
return ira->codegen->invalid_instruction;
+ // TODO test this at comptime with u8 and non-u8 types
+ // TODO test with dest ptr being a global runtime variable
if (casted_dest_ptr->value.special == ConstValSpecialStatic &&
casted_src_ptr->value.special == ConstValSpecialStatic &&
casted_count->value.special == ConstValSpecialStatic &&
@@ -20242,7 +20755,7 @@ static IrInstruction *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira,
} else {
seenFalse += 1;
}
-
+
if ((seenTrue > 1) || (seenFalse > 1)) {
ir_add_error(ira, value, buf_sprintf("duplicate switch value"));
return ira->codegen->invalid_instruction;
@@ -20375,7 +20888,7 @@ static IrInstruction *ir_align_cast(IrAnalyze *ira, IrInstruction *target, uint3
}
static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *ptr,
- ZigType *dest_type, IrInstruction *dest_type_src)
+ ZigType *dest_type, IrInstruction *dest_type_src, bool safety_check_on)
{
Error err;
@@ -20385,12 +20898,14 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
// We have a check for zero bits later so we use get_src_ptr_type to
// validate src_type and dest_type.
- if (get_src_ptr_type(src_type) == nullptr) {
+ ZigType *src_ptr_type = get_src_ptr_type(src_type);
+ if (src_ptr_type == nullptr) {
ir_add_error(ira, ptr, buf_sprintf("expected pointer, found '%s'", buf_ptr(&src_type->name)));
return ira->codegen->invalid_instruction;
}
- if (get_src_ptr_type(dest_type) == nullptr) {
+ ZigType *dest_ptr_type = get_src_ptr_type(dest_type);
+ if (dest_ptr_type == nullptr) {
ir_add_error(ira, dest_type_src,
buf_sprintf("expected pointer, found '%s'", buf_ptr(&dest_type->name)));
return ira->codegen->invalid_instruction;
@@ -20400,18 +20915,6 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
ir_add_error(ira, source_instr, buf_sprintf("cast discards const qualifier"));
return ira->codegen->invalid_instruction;
}
-
- if (instr_is_comptime(ptr)) {
- ConstExprValue *val = ir_resolve_const(ira, ptr, UndefOk);
- if (!val)
- return ira->codegen->invalid_instruction;
-
- IrInstruction *result = ir_const(ira, source_instr, dest_type);
- copy_const_val(&result->value, val, false);
- result->value.type = dest_type;
- return result;
- }
-
uint32_t src_align_bytes;
if ((err = resolve_ptr_align(ira, src_type, &src_align_bytes)))
return ira->codegen->invalid_instruction;
@@ -20420,6 +20923,37 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
if ((err = resolve_ptr_align(ira, dest_type, &dest_align_bytes)))
return ira->codegen->invalid_instruction;
+ if (instr_is_comptime(ptr)) {
+ bool dest_allows_addr_zero = ptr_allows_addr_zero(dest_type);
+ UndefAllowed is_undef_allowed = dest_allows_addr_zero ? UndefOk : UndefBad;
+ ConstExprValue *val = ir_resolve_const(ira, ptr, is_undef_allowed);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ if (val->special == ConstValSpecialStatic) {
+ bool is_addr_zero = val->data.x_ptr.special == ConstPtrSpecialNull ||
+ (val->data.x_ptr.special == ConstPtrSpecialHardCodedAddr &&
+ val->data.x_ptr.data.hard_coded_addr.addr == 0);
+ if (is_addr_zero && !dest_allows_addr_zero) {
+ ir_add_error(ira, source_instr,
+ buf_sprintf("null pointer casted to type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+ }
+
+ IrInstruction *result = ir_const(ira, source_instr, dest_type);
+ copy_const_val(&result->value, val, false);
+ result->value.type = dest_type;
+
+ // Keep the bigger alignment, it can only help-
+ // unless the target is zero bits.
+ if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
+ result = ir_align_cast(ira, result, src_align_bytes, false);
+ }
+
+ return result;
+ }
+
if (dest_align_bytes > src_align_bytes) {
ErrorMsg *msg = ir_add_error(ira, source_instr, buf_sprintf("cast increases pointer alignment"));
add_error_note(ira->codegen, msg, ptr->source_node,
@@ -20429,7 +20963,7 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
return ira->codegen->invalid_instruction;
}
- IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr);
+ IrInstruction *casted_ptr = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
if (type_has_bits(dest_type) && !type_has_bits(src_type)) {
ErrorMsg *msg = ir_add_error(ira, source_instr,
@@ -20466,7 +21000,8 @@ static IrInstruction *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstruct
if (type_is_invalid(src_type))
return ira->codegen->invalid_instruction;
- return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value);
+ return ir_analyze_ptr_cast(ira, &instruction->base, ptr, dest_type, dest_type_value,
+ instruction->safety_check_on);
}
static void buf_write_value_bytes_array(CodeGen *codegen, uint8_t *buf, ConstExprValue *val, size_t len) {
@@ -20529,7 +21064,79 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
case ZigTypeIdVector:
return buf_write_value_bytes_array(codegen, buf, val, val->type->data.vector.len);
case ZigTypeIdStruct:
- zig_panic("TODO buf_write_value_bytes struct type");
+ switch (val->type->data.structure.layout) {
+ case ContainerLayoutAuto:
+ zig_unreachable();
+ case ContainerLayoutExtern: {
+ size_t src_field_count = val->type->data.structure.src_field_count;
+ for (size_t field_i = 0; field_i < src_field_count; field_i += 1) {
+ TypeStructField *type_field = &val->type->data.structure.fields[field_i];
+ if (type_field->gen_index == SIZE_MAX)
+ continue;
+ ConstExprValue *field_val = &val->data.x_struct.fields[field_i];
+ size_t offset = LLVMOffsetOfElement(codegen->target_data_ref, val->type->type_ref,
+ type_field->gen_index);
+ buf_write_value_bytes(codegen, buf + offset, field_val);
+ }
+ return;
+ }
+ case ContainerLayoutPacked: {
+ size_t src_field_count = val->type->data.structure.src_field_count;
+ size_t gen_field_count = val->type->data.structure.gen_field_count;
+ size_t gen_i = 0;
+ size_t src_i = 0;
+ size_t offset = 0;
+ bool is_big_endian = codegen->is_big_endian;
+ uint8_t child_buf_prealloc[16];
+ size_t child_buf_len = 16;
+ uint8_t *child_buf = child_buf_prealloc;
+ while (gen_i < gen_field_count) {
+ LLVMTypeRef gen_llvm_int_type = LLVMStructGetTypeAtIndex(val->type->type_ref,
+ (unsigned)gen_i);
+ size_t big_int_bit_count = LLVMGetIntTypeWidth(gen_llvm_int_type);
+ size_t big_int_byte_count = big_int_bit_count / 8;
+ if (big_int_byte_count > child_buf_len) {
+ child_buf = allocate_nonzero(big_int_byte_count);
+ child_buf_len = big_int_byte_count;
+ }
+ BigInt big_int;
+ bigint_init_unsigned(&big_int, 0);
+ size_t used_bits = 0;
+ while (src_i < src_field_count) {
+ TypeStructField *field = &val->type->data.structure.fields[src_i];
+ assert(field->gen_index != SIZE_MAX);
+ if (field->gen_index != gen_i)
+ break;
+ uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry);
+ buf_write_value_bytes(codegen, child_buf, &val->data.x_struct.fields[src_i]);
+ BigInt child_val;
+ bigint_read_twos_complement(&child_val, child_buf, packed_bits_size, is_big_endian,
+ false);
+ if (is_big_endian) {
+ BigInt shift_amt;
+ bigint_init_unsigned(&shift_amt, packed_bits_size);
+ BigInt shifted;
+ bigint_shl(&shifted, &big_int, &shift_amt);
+ bigint_or(&big_int, &shifted, &child_val);
+ } else {
+ BigInt shift_amt;
+ bigint_init_unsigned(&shift_amt, used_bits);
+ BigInt child_val_shifted;
+ bigint_shl(&child_val_shifted, &child_val, &shift_amt);
+ BigInt tmp;
+ bigint_or(&tmp, &big_int, &child_val_shifted);
+ big_int = tmp;
+ used_bits += packed_bits_size;
+ }
+ src_i += 1;
+ }
+ bigint_write_twos_complement(&big_int, buf + offset, big_int_bit_count, is_big_endian);
+ offset += big_int_byte_count;
+ gen_i += 1;
+ }
+ return;
+ }
+ }
case ZigTypeIdOptional:
zig_panic("TODO buf_write_value_bytes maybe type");
case ZigTypeIdErrorUnion:
@@ -20656,8 +21263,62 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
}
return ErrorNone;
}
- case ContainerLayoutPacked:
- zig_panic("TODO buf_read_value_bytes packed struct");
+ case ContainerLayoutPacked: {
+ size_t src_field_count = val->type->data.structure.src_field_count;
+ val->data.x_struct.fields = create_const_vals(src_field_count);
+ size_t gen_field_count = val->type->data.structure.gen_field_count;
+ size_t gen_i = 0;
+ size_t src_i = 0;
+ size_t offset = 0;
+ bool is_big_endian = codegen->is_big_endian;
+ uint8_t child_buf_prealloc[16];
+ size_t child_buf_len = 16;
+ uint8_t *child_buf = child_buf_prealloc;
+ while (gen_i < gen_field_count) {
+ LLVMTypeRef gen_llvm_int_type = LLVMStructGetTypeAtIndex(val->type->type_ref,
+ (unsigned)gen_i);
+ size_t big_int_bit_count = LLVMGetIntTypeWidth(gen_llvm_int_type);
+ size_t big_int_byte_count = big_int_bit_count / 8;
+ if (big_int_byte_count > child_buf_len) {
+ child_buf = allocate_nonzero(big_int_byte_count);
+ child_buf_len = big_int_byte_count;
+ }
+ BigInt big_int;
+ bigint_read_twos_complement(&big_int, buf + offset, big_int_bit_count, is_big_endian, false);
+ while (src_i < src_field_count) {
+ TypeStructField *field = &val->type->data.structure.fields[src_i];
+ assert(field->gen_index != SIZE_MAX);
+ if (field->gen_index != gen_i)
+ break;
+ ConstExprValue *field_val = &val->data.x_struct.fields[src_i];
+ field_val->special = ConstValSpecialStatic;
+ field_val->type = field->type_entry;
+ uint32_t packed_bits_size = type_size_bits(codegen, field->type_entry);
+
+ BigInt child_val;
+ if (is_big_endian) {
+ zig_panic("TODO buf_read_value_bytes packed struct big endian");
+ } else {
+ BigInt packed_bits_size_bi;
+ bigint_init_unsigned(&packed_bits_size_bi, packed_bits_size);
+ bigint_truncate(&child_val, &big_int, packed_bits_size, false);
+ BigInt tmp;
+ bigint_shr(&tmp, &big_int, &packed_bits_size_bi);
+ big_int = tmp;
+ }
+
+ bigint_write_twos_complement(&child_val, child_buf, big_int_bit_count, is_big_endian);
+ if ((err = buf_read_value_bytes(ira, codegen, source_node, child_buf, field_val))) {
+ return err;
+ }
+
+ src_i += 1;
+ }
+ offset += big_int_byte_count;
+ gen_i += 1;
+ }
+ return ErrorNone;
+ }
}
zig_unreachable();
case ZigTypeIdOptional:
@@ -20674,17 +21335,38 @@ static Error buf_read_value_bytes(IrAnalyze *ira, CodeGen *codegen, AstNode *sou
zig_unreachable();
}
-static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
- Error err;
- IrInstruction *dest_type_value = instruction->dest_type->child;
- ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
- if (type_is_invalid(dest_type))
- return ira->codegen->invalid_instruction;
+static bool type_can_bit_cast(ZigType *t) {
+ switch (t->id) {
+ case ZigTypeIdInvalid:
+ zig_unreachable();
+ case ZigTypeIdMetaType:
+ case ZigTypeIdOpaque:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdNamespace:
+ case ZigTypeIdUnreachable:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdPointer:
+ return false;
+ default:
+ // TODO list these types out explicitly, there are probably some other invalid ones here
+ return true;
+ }
+}
+
+static IrInstruction *ir_analyze_bit_cast(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value,
+ ZigType *dest_type)
+{
+ Error err;
- IrInstruction *value = instruction->value->child;
ZigType *src_type = value->value.type;
- if (type_is_invalid(src_type))
- return ira->codegen->invalid_instruction;
+ assert(get_codegen_ptr_type(src_type) == nullptr);
+ assert(type_can_bit_cast(src_type));
+ assert(get_codegen_ptr_type(dest_type) == nullptr);
+ assert(type_can_bit_cast(dest_type));
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction;
@@ -20692,60 +21374,11 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
if ((err = type_resolve(ira->codegen, src_type, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction;
- if (get_codegen_ptr_type(src_type) != nullptr) {
- ir_add_error(ira, value,
- buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- switch (src_type->id) {
- case ZigTypeIdInvalid:
- case ZigTypeIdMetaType:
- case ZigTypeIdOpaque:
- case ZigTypeIdBoundFn:
- case ZigTypeIdArgTuple:
- case ZigTypeIdNamespace:
- case ZigTypeIdUnreachable:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
- return ira->codegen->invalid_instruction;
- default:
- break;
- }
-
- if (get_codegen_ptr_type(dest_type) != nullptr) {
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- switch (dest_type->id) {
- case ZigTypeIdInvalid:
- case ZigTypeIdMetaType:
- case ZigTypeIdOpaque:
- case ZigTypeIdBoundFn:
- case ZigTypeIdArgTuple:
- case ZigTypeIdNamespace:
- case ZigTypeIdUnreachable:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- ir_add_error(ira, dest_type_value,
- buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
- return ira->codegen->invalid_instruction;
- default:
- break;
- }
uint64_t dest_size_bytes = type_size(ira->codegen, dest_type);
uint64_t src_size_bytes = type_size(ira->codegen, src_type);
if (dest_size_bytes != src_size_bytes) {
- ir_add_error(ira, &instruction->base,
+ ir_add_error(ira, source_instr,
buf_sprintf("destination type '%s' has size %" ZIG_PRI_u64 " but source type '%s' has size %" ZIG_PRI_u64,
buf_ptr(&dest_type->name), dest_size_bytes,
buf_ptr(&src_type->name), src_size_bytes));
@@ -20755,7 +21388,7 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
uint64_t dest_size_bits = type_size_bits(ira->codegen, dest_type);
uint64_t src_size_bits = type_size_bits(ira->codegen, src_type);
if (dest_size_bits != src_size_bits) {
- ir_add_error(ira, &instruction->base,
+ ir_add_error(ira, source_instr,
buf_sprintf("destination type '%s' has %" ZIG_PRI_u64 " bits but source type '%s' has %" ZIG_PRI_u64 " bits",
buf_ptr(&dest_type->name), dest_size_bits,
buf_ptr(&src_type->name), src_size_bits));
@@ -20767,17 +21400,84 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct
if (!val)
return ira->codegen->invalid_instruction;
- IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
+ IrInstruction *result = ir_const(ira, source_instr, dest_type);
uint8_t *buf = allocate_nonzero(src_size_bytes);
buf_write_value_bytes(ira->codegen, buf, val);
- if ((err = buf_read_value_bytes(ira, ira->codegen, instruction->base.source_node, buf, &result->value)))
+ if ((err = buf_read_value_bytes(ira, ira->codegen, source_instr->source_node, buf, &result->value)))
return ira->codegen->invalid_instruction;
return result;
}
- IrInstruction *result = ir_build_bit_cast(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, nullptr, value);
- result->value.type = dest_type;
+ IrInstruction *result = ir_build_bit_cast_gen(ira, source_instr, value, dest_type);
+ if (handle_is_ptr(dest_type) && !handle_is_ptr(src_type)) {
+ ir_add_alloca(ira, result, dest_type);
+ }
+ return result;
+}
+
+static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstructionBitCast *instruction) {
+ IrInstruction *dest_type_value = instruction->dest_type->child;
+ ZigType *dest_type = ir_resolve_type(ira, dest_type_value);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *value = instruction->value->child;
+ ZigType *src_type = value->value.type;
+ if (type_is_invalid(src_type))
+ return ira->codegen->invalid_instruction;
+
+ if (get_codegen_ptr_type(src_type) != nullptr) {
+ ir_add_error(ira, value,
+ buf_sprintf("unable to @bitCast from pointer type '%s'", buf_ptr(&src_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (!type_can_bit_cast(src_type)) {
+ ir_add_error(ira, dest_type_value,
+ buf_sprintf("unable to @bitCast from type '%s'", buf_ptr(&src_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (get_codegen_ptr_type(dest_type) != nullptr) {
+ ir_add_error(ira, dest_type_value,
+ buf_sprintf("unable to @bitCast to pointer type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ if (!type_can_bit_cast(dest_type)) {
+ ir_add_error(ira, dest_type_value,
+ buf_sprintf("unable to @bitCast to type '%s'", buf_ptr(&dest_type->name)));
+ return ira->codegen->invalid_instruction;
+ }
+
+ return ir_analyze_bit_cast(ira, &instruction->base, value, dest_type);
+}
+
+static IrInstruction *ir_analyze_int_to_ptr(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *target,
+ ZigType *ptr_type)
+{
+ assert(get_src_ptr_type(ptr_type) != nullptr);
+ assert(type_has_bits(ptr_type));
+
+ IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
+ if (type_is_invalid(casted_int->value.type))
+ return ira->codegen->invalid_instruction;
+
+ if (instr_is_comptime(casted_int)) {
+ ConstExprValue *val = ir_resolve_const(ira, casted_int, UndefBad);
+ if (!val)
+ return ira->codegen->invalid_instruction;
+
+ IrInstruction *result = ir_const(ira, source_instr, ptr_type);
+ result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
+ result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
+ result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
+ return result;
+ }
+
+ IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, source_instr->scope,
+ source_instr->source_node, nullptr, casted_int);
+ result->value.type = ptr_type;
return result;
}
@@ -20802,30 +21502,12 @@ static IrInstruction *ir_analyze_instruction_int_to_ptr(IrAnalyze *ira, IrInstru
return ira->codegen->invalid_instruction;
}
+
IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
return ira->codegen->invalid_instruction;
- IrInstruction *casted_int = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_usize);
- if (type_is_invalid(casted_int->value.type))
- return ira->codegen->invalid_instruction;
-
- if (instr_is_comptime(casted_int)) {
- ConstExprValue *val = ir_resolve_const(ira, casted_int, UndefBad);
- if (!val)
- return ira->codegen->invalid_instruction;
-
- IrInstruction *result = ir_const(ira, &instruction->base, dest_type);
- result->value.data.x_ptr.special = ConstPtrSpecialHardCodedAddr;
- result->value.data.x_ptr.mut = ConstPtrMutRuntimeVar;
- result->value.data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&val->data.x_bigint);
- return result;
- }
-
- IrInstruction *result = ir_build_int_to_ptr(&ira->new_irb, instruction->base.scope,
- instruction->base.source_node, nullptr, casted_int);
- result->value.type = dest_type;
- return result;
+ return ir_analyze_int_to_ptr(ira, &instruction->base, target, dest_type);
}
static IrInstruction *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
@@ -20931,6 +21613,15 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct
} else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) {
ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque"));
return ira->codegen->invalid_instruction;
+ } else if (instruction->ptr_len == PtrLenC) {
+ if (!type_allowed_in_extern(ira->codegen, child_type)) {
+ ir_add_error(ira, &instruction->base,
+ buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name)));
+ return ira->codegen->invalid_instruction;
+ } else if (child_type->id == ZigTypeIdOpaque) {
+ ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types"));
+ return ira->codegen->invalid_instruction;
+ }
}
uint32_t align_bytes;
@@ -21068,20 +21759,10 @@ static IrInstruction *ir_analyze_instruction_tag_type(IrAnalyze *ira, IrInstruct
return ir_const_type(ira, &instruction->base, enum_type->data.enumeration.tag_int_type);
} else if (enum_type->id == ZigTypeIdUnion) {
- if ((err = ensure_complete_type(ira->codegen, enum_type)))
+ ZigType *tag_type = ir_resolve_union_tag_type(ira, instruction->target, enum_type);
+ if (type_is_invalid(tag_type))
return ira->codegen->invalid_instruction;
-
- AstNode *decl_node = enum_type->data.unionation.decl_node;
- if (decl_node->data.container_decl.auto_enum || decl_node->data.container_decl.init_arg_expr != nullptr) {
- assert(enum_type->data.unionation.tag_type != nullptr);
-
- return ir_const_type(ira, &instruction->base, enum_type->data.unionation.tag_type);
- } else {
- ErrorMsg *msg = ir_add_error(ira, target_inst, buf_sprintf("union '%s' has no tag",
- buf_ptr(&enum_type->name)));
- add_error_note(ira->codegen, msg, decl_node, buf_sprintf("consider 'union(enum)' here"));
- return ira->codegen->invalid_instruction;
- }
+ return ir_const_type(ira, &instruction->base, tag_type);
} else {
ir_add_error(ira, target_inst, buf_sprintf("expected enum or union, found '%s'",
buf_ptr(&enum_type->name)));
@@ -21662,23 +22343,11 @@ static IrInstruction *ir_analyze_instruction_bit_reverse(IrAnalyze *ira, IrInstr
static IrInstruction *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
- Error err;
IrInstruction *target = instruction->target->child;
if (type_is_invalid(target->value.type))
return ira->codegen->invalid_instruction;
- if (target->value.type->id != ZigTypeIdEnum) {
- ir_add_error(ira, instruction->target,
- buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name)));
- return ira->codegen->invalid_instruction;
- }
-
- if ((err = type_resolve(ira->codegen, target->value.type, ResolveStatusZeroBitsKnown)))
- return ira->codegen->invalid_instruction;
-
- ZigType *tag_type = target->value.type->data.enumeration.tag_int_type;
-
- return ir_analyze_enum_to_int(ira, &instruction->base, target, tag_type);
+ return ir_analyze_enum_to_int(ira, &instruction->base, target);
}
static IrInstruction *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {
@@ -21750,6 +22419,9 @@ static IrInstruction *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructio
case IrInstructionIdArrayToVector:
case IrInstructionIdVectorToArray:
case IrInstructionIdAssertZero:
+ case IrInstructionIdResizeSlice:
+ case IrInstructionIdLoadPtrGen:
+ case IrInstructionIdBitCastGen:
zig_unreachable();
case IrInstructionIdReturn:
@@ -22149,12 +22821,14 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdCmpxchgGen:
case IrInstructionIdCmpxchgSrc:
case IrInstructionIdAssertZero:
+ case IrInstructionIdResizeSlice:
return true;
case IrInstructionIdPhi:
case IrInstructionIdUnOp:
case IrInstructionIdBinOp:
case IrInstructionIdLoadPtr:
+ case IrInstructionIdLoadPtrGen:
case IrInstructionIdConst:
case IrInstructionIdCast:
case IrInstructionIdContainerInitList:
@@ -22205,6 +22879,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
case IrInstructionIdPtrCastSrc:
case IrInstructionIdPtrCastGen:
case IrInstructionIdBitCast:
+ case IrInstructionIdBitCastGen:
case IrInstructionIdWidenOrShorten:
case IrInstructionIdPtrToInt:
case IrInstructionIdIntToPtr:
diff --git a/src/ir.hpp b/src/ir.hpp
index 0a7c614812..0b85ad2c55 100644
--- a/src/ir.hpp
+++ b/src/ir.hpp
@@ -16,7 +16,7 @@ bool ir_gen_fn(CodeGen *g, ZigFn *fn_entry);
ConstExprValue *ir_eval_const_value(CodeGen *codegen, Scope *scope, AstNode *node,
ZigType *expected_type, size_t *backward_branch_count, size_t backward_branch_quota,
ZigFn *fn_entry, Buf *c_import_buf, AstNode *source_node, Buf *exec_name,
- IrExecutable *parent_exec);
+ IrExecutable *parent_exec, AstNode *expected_type_source_node);
ZigType *ir_analyze(CodeGen *g, IrExecutable *old_executable, IrExecutable *new_executable,
ZigType *expected_type, AstNode *expected_type_source_node);
diff --git a/src/ir_print.cpp b/src/ir_print.cpp
index 75da24d1a9..4572b30ded 100644
--- a/src/ir_print.cpp
+++ b/src/ir_print.cpp
@@ -336,6 +336,11 @@ static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) {
fprintf(irp->f, ".*");
}
+static void ir_print_load_ptr_gen(IrPrint *irp, IrInstructionLoadPtrGen *instruction) {
+ ir_print_other_instruction(irp, instruction->ptr);
+ fprintf(irp->f, ".*");
+}
+
static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) {
fprintf(irp->f, "*");
ir_print_var_instruction(irp, instruction->ptr);
@@ -915,14 +920,18 @@ static void ir_print_ptr_cast_gen(IrPrint *irp, IrInstructionPtrCastGen *instruc
static void ir_print_bit_cast(IrPrint *irp, IrInstructionBitCast *instruction) {
fprintf(irp->f, "@bitCast(");
- if (instruction->dest_type) {
- ir_print_other_instruction(irp, instruction->dest_type);
- }
+ ir_print_other_instruction(irp, instruction->dest_type);
fprintf(irp->f, ",");
ir_print_other_instruction(irp, instruction->value);
fprintf(irp->f, ")");
}
+static void ir_print_bit_cast_gen(IrPrint *irp, IrInstructionBitCastGen *instruction) {
+ fprintf(irp->f, "@bitCast(");
+ ir_print_other_instruction(irp, instruction->operand);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_widen_or_shorten(IrPrint *irp, IrInstructionWidenOrShorten *instruction) {
fprintf(irp->f, "WidenOrShorten(");
ir_print_other_instruction(irp, instruction->target);
@@ -990,6 +999,12 @@ static void ir_print_assert_zero(IrPrint *irp, IrInstructionAssertZero *instruct
fprintf(irp->f, ")");
}
+static void ir_print_resize_slice(IrPrint *irp, IrInstructionResizeSlice *instruction) {
+ fprintf(irp->f, "@resizeSlice(");
+ ir_print_other_instruction(irp, instruction->operand);
+ fprintf(irp->f, ")");
+}
+
static void ir_print_int_to_err(IrPrint *irp, IrInstructionIntToErr *instruction) {
fprintf(irp->f, "inttoerr ");
ir_print_other_instruction(irp, instruction->target);
@@ -1462,6 +1477,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdLoadPtr:
ir_print_load_ptr(irp, (IrInstructionLoadPtr *)instruction);
break;
+ case IrInstructionIdLoadPtrGen:
+ ir_print_load_ptr_gen(irp, (IrInstructionLoadPtrGen *)instruction);
+ break;
case IrInstructionIdStorePtr:
ir_print_store_ptr(irp, (IrInstructionStorePtr *)instruction);
break;
@@ -1678,6 +1696,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdBitCast:
ir_print_bit_cast(irp, (IrInstructionBitCast *)instruction);
break;
+ case IrInstructionIdBitCastGen:
+ ir_print_bit_cast_gen(irp, (IrInstructionBitCastGen *)instruction);
+ break;
case IrInstructionIdWidenOrShorten:
ir_print_widen_or_shorten(irp, (IrInstructionWidenOrShorten *)instruction);
break;
@@ -1852,6 +1873,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
case IrInstructionIdAssertZero:
ir_print_assert_zero(irp, (IrInstructionAssertZero *)instruction);
break;
+ case IrInstructionIdResizeSlice:
+ ir_print_resize_slice(irp, (IrInstructionResizeSlice *)instruction);
+ break;
}
fprintf(irp->f, "\n");
}
diff --git a/src/libc_installation.cpp b/src/libc_installation.cpp
new file mode 100644
index 0000000000..8be704887a
--- /dev/null
+++ b/src/libc_installation.cpp
@@ -0,0 +1,498 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#include "libc_installation.hpp"
+#include "os.hpp"
+#include "windows_sdk.h"
+#include "target.hpp"
+
+static const char *zig_libc_keys[] = {
+ "include_dir",
+ "sys_include_dir",
+ "crt_dir",
+ "lib_dir",
+ "static_lib_dir",
+ "msvc_lib_dir",
+ "kernel32_lib_dir",
+ "dynamic_linker_path",
+};
+
+static const size_t zig_libc_keys_len = array_length(zig_libc_keys);
+
+static bool zig_libc_match_key(Slice name, Slice value, bool *found_keys,
+ size_t index, Buf *field_ptr)
+{
+ if (!memEql(name, str(zig_libc_keys[index]))) return false;
+ buf_init_from_mem(field_ptr, (const char*)value.ptr, value.len);
+ found_keys[index] = true;
+ return true;
+}
+
+static void zig_libc_init_empty(ZigLibCInstallation *libc) {
+ *libc = {};
+ buf_init_from_str(&libc->include_dir, "");
+ buf_init_from_str(&libc->sys_include_dir, "");
+ buf_init_from_str(&libc->crt_dir, "");
+ buf_init_from_str(&libc->lib_dir, "");
+ buf_init_from_str(&libc->static_lib_dir, "");
+ buf_init_from_str(&libc->msvc_lib_dir, "");
+ buf_init_from_str(&libc->kernel32_lib_dir, "");
+ buf_init_from_str(&libc->dynamic_linker_path, "");
+}
+
+Error zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file, const ZigTarget *target, bool verbose) {
+ Error err;
+ zig_libc_init_empty(libc);
+
+ bool found_keys[array_length(zig_libc_keys)] = {};
+
+ Buf *contents = buf_alloc();
+ if ((err = os_fetch_file_path(libc_file, contents, false))) {
+ if (err != ErrorFileNotFound && verbose) {
+ fprintf(stderr, "Unable to read '%s': %s\n", buf_ptr(libc_file), err_str(err));
+ }
+ return err;
+ }
+
+ SplitIterator it = memSplit(buf_to_slice(contents), str("\n"));
+ for (;;) {
+ Optional> opt_line = SplitIterator_next(&it);
+ if (!opt_line.is_some)
+ break;
+
+ if (opt_line.value.len == 0 || opt_line.value.ptr[0] == '#')
+ continue;
+
+ SplitIterator line_it = memSplit(opt_line.value, str("="));
+ Slice name;
+ if (!SplitIterator_next(&line_it).unwrap(&name)) {
+ if (verbose) {
+ fprintf(stderr, "missing equal sign after field name\n");
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ Slice value = SplitIterator_rest(&line_it);
+ bool match = false;
+ match = match || zig_libc_match_key(name, value, found_keys, 0, &libc->include_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 1, &libc->sys_include_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 2, &libc->crt_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 3, &libc->lib_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 4, &libc->static_lib_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 5, &libc->msvc_lib_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 6, &libc->kernel32_lib_dir);
+ match = match || zig_libc_match_key(name, value, found_keys, 7, &libc->dynamic_linker_path);
+ }
+
+ for (size_t i = 0; i < zig_libc_keys_len; i += 1) {
+ if (!found_keys[i]) {
+ if (verbose) {
+ fprintf(stderr, "missing field: %s\n", zig_libc_keys[i]);
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
+ if (buf_len(&libc->include_dir) == 0) {
+ if (verbose) {
+ fprintf(stderr, "include_dir may not be empty\n");
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+
+ if (buf_len(&libc->sys_include_dir) == 0) {
+ if (verbose) {
+ fprintf(stderr, "sys_include_dir may not be empty\n");
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+
+ if (buf_len(&libc->crt_dir) == 0) {
+ if (!target_is_darwin(target)) {
+ if (verbose) {
+ fprintf(stderr, "crt_dir may not be empty for %s\n", target_os_name(target->os));
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
+ if (buf_len(&libc->lib_dir) == 0) {
+ if (!target_is_darwin(target) && target->os != OsWindows) {
+ if (verbose) {
+ fprintf(stderr, "lib_dir may not be empty for %s\n", target_os_name(target->os));
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
+ if (buf_len(&libc->static_lib_dir) == 0) {
+ if (!target_is_darwin(target) && target->os != OsWindows) {
+ if (verbose) {
+ fprintf(stderr, "static_lib_dir may not be empty for %s\n", target_os_name(target->os));
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
+ if (buf_len(&libc->msvc_lib_dir) == 0) {
+ if (target->os == OsWindows) {
+ if (verbose) {
+ fprintf(stderr, "msvc_lib_dir may not be empty for %s\n", target_os_name(target->os));
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
+ if (buf_len(&libc->kernel32_lib_dir) == 0) {
+ if (target->os == OsWindows) {
+ if (verbose) {
+ fprintf(stderr, "kernel32_lib_dir may not be empty for %s\n", target_os_name(target->os));
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
+ if (buf_len(&libc->dynamic_linker_path) == 0) {
+ if (!target_is_darwin(target) && target->os != OsWindows) {
+ if (verbose) {
+ fprintf(stderr, "dynamic_linker_path may not be empty for %s\n", target_os_name(target->os));
+ }
+ return ErrorSemanticAnalyzeFail;
+ }
+ }
+
+ return ErrorNone;
+}
+
+#if defined(ZIG_OS_WINDOWS)
+static Error zig_libc_find_native_include_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
+ Error err;
+ if ((err = os_get_win32_ucrt_include_path(sdk, &self->include_dir))) {
+ if (verbose) {
+ fprintf(stderr, "Unable to determine libc include path: %s\n", err_str(err));
+ }
+ return err;
+ }
+ return ErrorNone;
+}
+static Error zig_libc_find_crt_dir_windows(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
+ bool verbose)
+{
+ Error err;
+ if ((err = os_get_win32_ucrt_lib_path(sdk, &self->crt_dir, target->arch))) {
+ if (verbose) {
+ fprintf(stderr, "Unable to determine ucrt path: %s\n", err_str(err));
+ }
+ return err;
+ }
+ return ErrorNone;
+}
+static Error zig_libc_find_kernel32_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, ZigTarget *target,
+ bool verbose)
+{
+ Error err;
+ if ((err = os_get_win32_kern32_path(sdk, &self->kernel32_lib_dir, target->arch))) {
+ if (verbose) {
+ fprintf(stderr, "Unable to determine kernel32 path: %s\n", err_str(err));
+ }
+ return err;
+ }
+ return ErrorNone;
+}
+static Error zig_libc_find_native_msvc_lib_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
+ if (sdk->msvc_lib_dir_ptr == nullptr) {
+ if (verbose) {
+ fprintf(stderr, "Unable to determine vcruntime.lib path\n");
+ }
+ return ErrorFileNotFound;
+ }
+ buf_init_from_mem(&self->msvc_lib_dir, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
+ return ErrorNone;
+}
+static Error zig_libc_find_native_msvc_include_dir(ZigLibCInstallation *self, ZigWindowsSDK *sdk, bool verbose) {
+ Error err;
+ if (sdk->msvc_lib_dir_ptr == nullptr) {
+ if (verbose) {
+ fprintf(stderr, "Unable to determine vcruntime.h path\n");
+ }
+ return ErrorFileNotFound;
+ }
+ Buf search_path = BUF_INIT;
+ buf_init_from_mem(&search_path, sdk->msvc_lib_dir_ptr, sdk->msvc_lib_dir_len);
+ buf_append_str(&search_path, "\\..\\..\\include");
+
+ Buf *vcruntime_path = buf_sprintf("%s\\vcruntime.h", buf_ptr(&search_path));
+ bool exists;
+ if ((err = os_file_exists(vcruntime_path, &exists))) {
+ exists = false;
+ }
+ if (exists) {
+ self->sys_include_dir = search_path;
+ return ErrorNone;
+ }
+
+ if (verbose) {
+ fprintf(stderr, "Unable to determine vcruntime.h path\n");
+ }
+ return ErrorFileNotFound;
+}
+#else
+static Error zig_libc_find_native_include_dir_posix(ZigLibCInstallation *self, bool verbose) {
+ const char *cc_exe = getenv("CC");
+ cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
+ ZigList args = {};
+ args.append("-E");
+ args.append("-Wp,-v");
+ args.append("-xc");
+ args.append("/dev/null");
+ Termination term;
+ Buf *out_stderr = buf_alloc();
+ Buf *out_stdout = buf_alloc();
+ Error err;
+ if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
+ if (verbose) {
+ fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err));
+ }
+ return err;
+ }
+ if (term.how != TerminationIdClean || term.code != 0) {
+ if (verbose) {
+ fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe);
+ }
+ return ErrorCCompileErrors;
+ }
+ char *prev_newline = buf_ptr(out_stderr);
+ ZigList search_paths = {};
+ for (;;) {
+ char *newline = strchr(prev_newline, '\n');
+ if (newline == nullptr) {
+ break;
+ }
+ *newline = 0;
+ if (prev_newline[0] == ' ') {
+ search_paths.append(prev_newline);
+ }
+ prev_newline = newline + 1;
+ }
+ if (search_paths.length == 0) {
+ if (verbose) {
+ fprintf(stderr, "unable to determine libc include path: '%s' cannot find libc headers\n", cc_exe);
+ }
+ return ErrorCCompileErrors;
+ }
+ for (size_t i = 0; i < search_paths.length; i += 1) {
+ // search in reverse order
+ const char *search_path = search_paths.items[search_paths.length - i - 1];
+ // cut off spaces
+ while (*search_path == ' ') {
+ search_path += 1;
+ }
+
+ if (buf_len(&self->include_dir) == 0) {
+ Buf *stdlib_path = buf_sprintf("%s/stdlib.h", search_path);
+ bool exists;
+ if ((err = os_file_exists(stdlib_path, &exists))) {
+ exists = false;
+ }
+ if (exists) {
+ buf_init_from_str(&self->include_dir, search_path);
+ }
+ }
+ if (buf_len(&self->sys_include_dir) == 0) {
+ Buf *stdlib_path = buf_sprintf("%s/sys/errno.h", search_path);
+ bool exists;
+ if ((err = os_file_exists(stdlib_path, &exists))) {
+ exists = false;
+ }
+ if (exists) {
+ buf_init_from_str(&self->sys_include_dir, search_path);
+ }
+ }
+ if (buf_len(&self->include_dir) != 0 && buf_len(&self->sys_include_dir) != 0) {
+ return ErrorNone;
+ }
+ }
+ if (verbose) {
+ if (buf_len(&self->include_dir) == 0) {
+ fprintf(stderr, "unable to determine libc include path: stdlib.h not found in '%s' search paths\n", cc_exe);
+ }
+ if (buf_len(&self->sys_include_dir) == 0) {
+ fprintf(stderr, "unable to determine libc include path: sys/errno.h not found in '%s' search paths\n", cc_exe);
+ }
+ }
+ return ErrorFileNotFound;
+}
+#if !defined(ZIG_OS_DARWIN) && !defined(ZIG_OS_FREEBSD) && !defined(ZIG_OS_NETBSD)
+static Error zig_libc_cc_print_file_name(const char *o_file, Buf *out, bool want_dirname, bool verbose) {
+ const char *cc_exe = getenv("CC");
+ cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
+ ZigList args = {};
+ args.append(buf_ptr(buf_sprintf("-print-file-name=%s", o_file)));
+ Termination term;
+ Buf *out_stderr = buf_alloc();
+ Buf *out_stdout = buf_alloc();
+ Error err;
+ if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
+ if (verbose) {
+ fprintf(stderr, "unable to determine libc include path: executing '%s': %s\n", cc_exe, err_str(err));
+ }
+ return err;
+ }
+ if (term.how != TerminationIdClean || term.code != 0) {
+ if (verbose) {
+ fprintf(stderr, "unable to determine libc include path: executing '%s' failed\n", cc_exe);
+ }
+ return ErrorCCompileErrors;
+ }
+ if (buf_ends_with_str(out_stdout, "\n")) {
+ buf_resize(out_stdout, buf_len(out_stdout) - 1);
+ }
+ if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, o_file)) {
+ return ErrorCCompilerCannotFindFile;
+ }
+ if (want_dirname) {
+ os_path_dirname(out_stdout, out);
+ } else {
+ buf_init_from_buf(out, out_stdout);
+ }
+ return ErrorNone;
+}
+static Error zig_libc_find_native_crt_dir_posix(ZigLibCInstallation *self, bool verbose) {
+ return zig_libc_cc_print_file_name("crt1.o", &self->crt_dir, true, verbose);
+}
+static Error zig_libc_find_native_lib_dir_posix(ZigLibCInstallation *self, bool verbose) {
+ return zig_libc_cc_print_file_name("libgcc_s.so", &self->lib_dir, true, verbose);
+}
+
+static Error zig_libc_find_native_static_lib_dir_posix(ZigLibCInstallation *self, bool verbose) {
+ return zig_libc_cc_print_file_name("crtbegin.o", &self->static_lib_dir, true, verbose);
+}
+#endif
+
+static Error zig_libc_find_native_dynamic_linker_posix(ZigLibCInstallation *self, bool verbose) {
+#if defined(ZIG_OS_LINUX)
+ Error err;
+ static const char *dyn_tests[] = {
+ "ld-linux-x86-64.so.2",
+ "ld-musl-x86_64.so.1",
+ };
+ for (size_t i = 0; i < array_length(dyn_tests); i += 1) {
+ const char *lib_name = dyn_tests[i];
+ if ((err = zig_libc_cc_print_file_name(lib_name, &self->dynamic_linker_path, false, true))) {
+ if (err != ErrorCCompilerCannotFindFile)
+ return err;
+ continue;
+ }
+ return ErrorNone;
+ }
+#endif
+ ZigTarget native_target;
+ get_native_target(&native_target);
+ const char *dynamic_linker_path = target_dynamic_linker(&native_target);
+ if (dynamic_linker_path != nullptr) {
+ buf_init_from_str(&self->dynamic_linker_path, dynamic_linker_path);
+ }
+ return ErrorNone;
+}
+#endif
+
+void zig_libc_render(ZigLibCInstallation *self, FILE *file) {
+ fprintf(file,
+ "# The directory that contains `stdlib.h`.\n"
+ "# On POSIX, include directories be found with: `cc -E -Wp,-v -xc /dev/null`\n"
+ "include_dir=%s\n"
+ "# The system-specific include directory. May be the same as `include_dir`.\n"
+ "# On Windows it's the directory that includes `vcruntime.h`.\n"
+ "# On POSIX it's the directory that includes `sys/errno.h`.\n"
+ "sys_include_dir=%s\n"
+ "\n"
+ "# The directory that contains `crt1.o`.\n"
+ "# On POSIX, can be found with `cc -print-file-name=crt1.o`.\n"
+ "# Not needed when targeting MacOS.\n"
+ "crt_dir=%s\n"
+ "\n"
+ "# The directory that contains `libgcc_s.so`.\n"
+ "# On POSIX, can be found with `cc -print-file-name=libgcc_s.so`.\n"
+ "# Not needed when targeting MacOS or Windows.\n"
+ "lib_dir=%s\n"
+ "\n"
+ "# The directory that contains `crtbegin.o`.\n"
+ "# On POSIX, can be found with `cc -print-file-name=crtbegin.o`.\n"
+ "# Not needed when targeting MacOS or Windows.\n"
+ "static_lib_dir=%s\n"
+ "\n"
+ "# The directory that contains `vcruntime.lib`.\n"
+ "# Only needed when targeting Windows.\n"
+ "msvc_lib_dir=%s\n"
+ "\n"
+ "# The directory that contains `kernel32.lib`.\n"
+ "# Only needed when targeting Windows.\n"
+ "kernel32_lib_dir=%s\n"
+ "\n"
+ "# The full path to the dynamic linker, on the target system.\n"
+ "# Not needed when targeting MacOS or Windows.\n"
+ "dynamic_linker_path=%s\n"
+ "\n"
+ ,
+ buf_ptr(&self->include_dir),
+ buf_ptr(&self->sys_include_dir),
+ buf_ptr(&self->crt_dir),
+ buf_ptr(&self->lib_dir),
+ buf_ptr(&self->static_lib_dir),
+ buf_ptr(&self->msvc_lib_dir),
+ buf_ptr(&self->kernel32_lib_dir),
+ buf_ptr(&self->dynamic_linker_path)
+ );
+}
+
+Error zig_libc_find_native(ZigLibCInstallation *self, bool verbose) {
+ Error err;
+ zig_libc_init_empty(self);
+#if defined(ZIG_OS_WINDOWS)
+ ZigTarget native_target;
+ get_native_target(&native_target);
+ ZigWindowsSDK *sdk;
+ switch (zig_find_windows_sdk(&sdk)) {
+ case ZigFindWindowsSdkErrorNone:
+ if ((err = zig_libc_find_native_msvc_include_dir(self, sdk, verbose)))
+ return err;
+ if ((err = zig_libc_find_native_msvc_lib_dir(self, sdk, verbose)))
+ return err;
+ if ((err = zig_libc_find_kernel32_lib_dir(self, sdk, &native_target, verbose)))
+ return err;
+ if ((err = zig_libc_find_native_include_dir_windows(self, sdk, verbose)))
+ return err;
+ if ((err = zig_libc_find_crt_dir_windows(self, sdk, &native_target, verbose)))
+ return err;
+ return ErrorNone;
+ case ZigFindWindowsSdkErrorOutOfMemory:
+ return ErrorNoMem;
+ case ZigFindWindowsSdkErrorNotFound:
+ return ErrorFileNotFound;
+ case ZigFindWindowsSdkErrorPathTooLong:
+ return ErrorPathTooLong;
+ }
+ zig_unreachable();
+#else
+ if ((err = zig_libc_find_native_include_dir_posix(self, verbose)))
+ return err;
+#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
+ buf_init_from_str(&self->crt_dir, "/usr/lib");
+ buf_init_from_str(&self->lib_dir, "/usr/lib");
+ buf_init_from_str(&self->static_lib_dir, "/usr/lib");
+#elif !defined(ZIG_OS_DARWIN)
+ if ((err = zig_libc_find_native_crt_dir_posix(self, verbose)))
+ return err;
+ if ((err = zig_libc_find_native_lib_dir_posix(self, verbose)))
+ return err;
+ if ((err = zig_libc_find_native_static_lib_dir_posix(self, verbose)))
+ return err;
+#endif
+ if ((err = zig_libc_find_native_dynamic_linker_posix(self, verbose)))
+ return err;
+ return ErrorNone;
+#endif
+}
diff --git a/src/libc_installation.hpp b/src/libc_installation.hpp
new file mode 100644
index 0000000000..167f9ee834
--- /dev/null
+++ b/src/libc_installation.hpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#ifndef ZIG_LIBC_INSTALLATION_HPP
+#define ZIG_LIBC_INSTALLATION_HPP
+
+#include
+
+#include "buffer.hpp"
+#include "error.hpp"
+#include "target.hpp"
+
+// Must be synchronized with zig_libc_keys
+struct ZigLibCInstallation {
+ Buf include_dir;
+ Buf sys_include_dir;
+ Buf crt_dir;
+ Buf lib_dir;
+ Buf static_lib_dir;
+ Buf msvc_lib_dir;
+ Buf kernel32_lib_dir;
+ Buf dynamic_linker_path;
+};
+
+Error ATTRIBUTE_MUST_USE zig_libc_parse(ZigLibCInstallation *libc, Buf *libc_file,
+ const ZigTarget *target, bool verbose);
+void zig_libc_render(ZigLibCInstallation *self, FILE *file);
+
+Error ATTRIBUTE_MUST_USE zig_libc_find_native(ZigLibCInstallation *self, bool verbose);
+
+#endif
diff --git a/src/link.cpp b/src/link.cpp
index 58221a99ea..7eb8cb111f 100644
--- a/src/link.cpp
+++ b/src/link.cpp
@@ -17,32 +17,33 @@ struct LinkJob {
HashMap rpath_table;
};
-static const char *get_libc_file(CodeGen *g, const char *file) {
+static const char *get_libc_crt_file(CodeGen *g, const char *file) {
+ assert(g->libc != nullptr);
Buf *out_buf = buf_alloc();
- os_path_join(g->libc_lib_dir, buf_create_from_str(file), out_buf);
+ os_path_join(&g->libc->crt_dir, buf_create_from_str(file), out_buf);
return buf_ptr(out_buf);
}
static const char *get_libc_static_file(CodeGen *g, const char *file) {
+ assert(g->libc != nullptr);
Buf *out_buf = buf_alloc();
- os_path_join(g->libc_static_lib_dir, buf_create_from_str(file), out_buf);
+ os_path_join(&g->libc->static_lib_dir, buf_create_from_str(file), out_buf);
return buf_ptr(out_buf);
}
static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path) {
- ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
-
// The Mach-O LLD code is not well maintained, and trips an assertion
// when we link compiler_rt and builtin as libraries rather than objects.
// Here we workaround this by having compiler_rt and builtin be objects.
// TODO write our own linker. https://github.com/ziglang/zig/issues/1535
OutType child_out_type = OutTypeLib;
- if (parent_gen->zig_target.os == OsMacOSX) {
+ if (parent_gen->zig_target->os == OsMacOSX) {
child_out_type = OutTypeObj;
}
- CodeGen *child_gen = codegen_create(full_path, child_target, child_out_type,
- parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir);
+ CodeGen *child_gen = codegen_create(full_path, parent_gen->zig_target, child_out_type,
+ parent_gen->build_mode, parent_gen->zig_lib_dir, parent_gen->zig_std_dir,
+ parent_gen->libc);
child_gen->out_h_path = nullptr;
child_gen->verbose_tokenize = parent_gen->verbose_tokenize;
@@ -55,6 +56,7 @@ static Buf *build_a_raw(CodeGen *parent_gen, const char *aname, Buf *full_path)
codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
codegen_set_is_static(child_gen, true);
child_gen->disable_pic = parent_gen->disable_pic;
+ child_gen->valgrind_support = ValgrindSupportDisabled;
codegen_set_out_name(child_gen, buf_create_from_str(aname));
@@ -94,7 +96,7 @@ static Buf *build_compiler_rt(CodeGen *parent_gen) {
}
static const char *get_darwin_arch_string(const ZigTarget *t) {
- switch (t->arch.arch) {
+ switch (t->arch) {
case ZigLLVM_aarch64:
return "arm64";
case ZigLLVM_thumb:
@@ -107,13 +109,13 @@ static const char *get_darwin_arch_string(const ZigTarget *t) {
case ZigLLVM_ppc64le:
return "ppc64le";
default:
- return ZigLLVMGetArchTypeName(t->arch.arch);
+ return ZigLLVMGetArchTypeName(t->arch);
}
}
static const char *getLDMOption(const ZigTarget *t) {
- switch (t->arch.arch) {
+ switch (t->arch) {
case ZigLLVM_x86:
return "elf_i386";
case ZigLLVM_aarch64:
@@ -147,7 +149,7 @@ static const char *getLDMOption(const ZigTarget *t) {
case ZigLLVM_systemz:
return "elf64_s390";
case ZigLLVM_x86_64:
- if (t->env_type == ZigLLVM_GNUX32) {
+ if (t->abi == ZigLLVM_GNUX32) {
return "elf32_x86_64";
}
// Any target elf will use the freebsd osabi if suffixed with "_fbsd".
@@ -170,78 +172,27 @@ static void add_rpath(LinkJob *lj, Buf *rpath) {
lj->rpath_table.put(rpath, true);
}
-static Buf *try_dynamic_linker_path(const char *ld_name) {
- const char *cc_exe = getenv("CC");
- cc_exe = (cc_exe == nullptr) ? "cc" : cc_exe;
- ZigList args = {};
- args.append(buf_ptr(buf_sprintf("-print-file-name=%s", ld_name)));
- Termination term;
- Buf *out_stderr = buf_alloc();
- Buf *out_stdout = buf_alloc();
- int err;
- if ((err = os_exec_process(cc_exe, args, &term, out_stderr, out_stdout))) {
- return nullptr;
- }
- if (term.how != TerminationIdClean || term.code != 0) {
- return nullptr;
- }
- if (buf_ends_with_str(out_stdout, "\n")) {
- buf_resize(out_stdout, buf_len(out_stdout) - 1);
- }
- if (buf_len(out_stdout) == 0 || buf_eql_str(out_stdout, ld_name)) {
- return nullptr;
- }
- return out_stdout;
-}
-
-static Buf *get_dynamic_linker_path(CodeGen *g) {
- if (g->zig_target.os == OsFreeBSD) {
- return buf_create_from_str("/libexec/ld-elf.so.1");
- }
- if (g->is_native_target && g->zig_target.arch.arch == ZigLLVM_x86_64) {
- static const char *ld_names[] = {
- "ld-linux-x86-64.so.2",
- "ld-musl-x86_64.so.1",
- };
- for (size_t i = 0; i < array_length(ld_names); i += 1) {
- const char *ld_name = ld_names[i];
- Buf *result = try_dynamic_linker_path(ld_name);
- if (result != nullptr) {
- return result;
- }
- }
- }
- return target_dynamic_linker(&g->zig_target);
-}
-
static void construct_linker_job_elf(LinkJob *lj) {
CodeGen *g = lj->codegen;
lj->args.append("-error-limit=0");
- if (g->libc_link_lib != nullptr) {
- find_libc_lib_path(g);
- }
-
if (g->linker_script) {
lj->args.append("-T");
lj->args.append(g->linker_script);
}
- if (g->no_rosegment_workaround) {
- lj->args.append("--no-rosegment");
- }
lj->args.append("--gc-sections");
lj->args.append("-m");
- lj->args.append(getLDMOption(&g->zig_target));
+ lj->args.append(getLDMOption(g->zig_target));
bool is_lib = g->out_type == OutTypeLib;
bool shared = !g->is_static && is_lib;
Buf *soname = nullptr;
if (g->is_static) {
- if (g->zig_target.arch.arch == ZigLLVM_arm || g->zig_target.arch.arch == ZigLLVM_armeb ||
- g->zig_target.arch.arch == ZigLLVM_thumb || g->zig_target.arch.arch == ZigLLVM_thumbeb)
+ if (g->zig_target->arch == ZigLLVM_arm || g->zig_target->arch == ZigLLVM_armeb ||
+ g->zig_target->arch == ZigLLVM_thumb || g->zig_target->arch == ZigLLVM_thumbeb)
{
lj->args.append("-Bstatic");
} else {
@@ -263,15 +214,18 @@ static void construct_linker_job_elf(LinkJob *lj) {
if (lj->link_in_crt) {
const char *crt1o;
const char *crtbegino;
- if (g->is_static) {
+ if (g->zig_target->os == OsNetBSD) {
+ crt1o = "crt0.o";
+ crtbegino = "crtbegin.o";
+ } else if (g->is_static) {
crt1o = "crt1.o";
crtbegino = "crtbeginT.o";
} else {
crt1o = "Scrt1.o";
crtbegino = "crtbegin.o";
}
- lj->args.append(get_libc_file(g, crt1o));
- lj->args.append(get_libc_file(g, "crti.o"));
+ lj->args.append(get_libc_crt_file(g, crt1o));
+ lj->args.append(get_libc_crt_file(g, "crti.o"));
lj->args.append(get_libc_static_file(g, crtbegino));
}
@@ -307,23 +261,24 @@ static void construct_linker_job_elf(LinkJob *lj) {
}
if (g->libc_link_lib != nullptr) {
+ assert(g->libc != nullptr);
lj->args.append("-L");
- lj->args.append(buf_ptr(g->libc_lib_dir));
+ lj->args.append(buf_ptr(&g->libc->crt_dir));
- lj->args.append("-L");
- lj->args.append(buf_ptr(g->libc_static_lib_dir));
- }
-
- if (!g->is_static) {
- if (g->dynamic_linker != nullptr) {
- assert(buf_len(g->dynamic_linker) != 0);
- lj->args.append("-dynamic-linker");
- lj->args.append(buf_ptr(g->dynamic_linker));
- } else {
- Buf *resolved_dynamic_linker = get_dynamic_linker_path(g);
- lj->args.append("-dynamic-linker");
- lj->args.append(buf_ptr(resolved_dynamic_linker));
+ if (!buf_eql_buf(&g->libc->crt_dir, &g->libc->lib_dir)) {
+ lj->args.append("-L");
+ lj->args.append(buf_ptr(&g->libc->lib_dir));
}
+
+ lj->args.append("-L");
+ lj->args.append(buf_ptr(&g->libc->static_lib_dir));
+
+ if (!g->is_static) {
+ assert(buf_len(&g->libc->dynamic_linker_path) != 0);
+ lj->args.append("-dynamic-linker");
+ lj->args.append(buf_ptr(&g->libc->dynamic_linker_path));
+ }
+
}
if (shared) {
@@ -390,14 +345,14 @@ static void construct_linker_job_elf(LinkJob *lj) {
// crt end
if (lj->link_in_crt) {
lj->args.append(get_libc_static_file(g, "crtend.o"));
- lj->args.append(get_libc_file(g, "crtn.o"));
+ lj->args.append(get_libc_crt_file(g, "crtn.o"));
}
- if (!g->is_native_target) {
+ if (!g->zig_target->is_native) {
lj->args.append("--allow-shlib-undefined");
}
- if (g->zig_target.os == OsZen) {
+ if (g->zig_target->os == OsZen) {
lj->args.append("-e");
lj->args.append("_start");
@@ -420,16 +375,16 @@ static void construct_linker_job_wasm(LinkJob *lj) {
}
//static bool is_target_cyg_mingw(const ZigTarget *target) {
-// return (target->os == ZigLLVM_Win32 && target->env_type == ZigLLVM_Cygnus) ||
-// (target->os == ZigLLVM_Win32 && target->env_type == ZigLLVM_GNU);
+// return (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_Cygnus) ||
+// (target->os == ZigLLVM_Win32 && target->abi == ZigLLVM_GNU);
//}
static void coff_append_machine_arg(CodeGen *g, ZigList *list) {
- if (g->zig_target.arch.arch == ZigLLVM_x86) {
+ if (g->zig_target->arch == ZigLLVM_x86) {
list->append("-MACHINE:X86");
- } else if (g->zig_target.arch.arch == ZigLLVM_x86_64) {
+ } else if (g->zig_target->arch == ZigLLVM_x86_64) {
list->append("-MACHINE:X64");
- } else if (g->zig_target.arch.arch == ZigLLVM_arm) {
+ } else if (g->zig_target->arch == ZigLLVM_arm) {
list->append("-MACHINE:ARM");
}
}
@@ -515,7 +470,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {
// lj->args.append("-Bdynamic");
// if (dll || shared) {
// lj->args.append("-e");
-// if (g->zig_target.arch.arch == ZigLLVM_x86) {
+// if (g->zig_target.arch == ZigLLVM_x86) {
// lj->args.append("_DllMainCRTStartup@12");
// } else {
// lj->args.append("DllMainCRTStartup");
@@ -541,7 +496,7 @@ static void add_nt_link_args(LinkJob *lj, bool is_library) {
//lj->args.append("-lmingw32");
//lj->args.append("-lgcc");
-//bool is_android = (g->zig_target.env_type == ZigLLVM_Android);
+//bool is_android = (g->zig_target.abi == ZigLLVM_Android);
//bool is_cyg_ming = is_target_cyg_mingw(&g->zig_target);
//if (!g->is_static && !is_android) {
// if (!is_cyg_ming) {
@@ -588,10 +543,6 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append("/ERRORLIMIT:0");
- if (g->libc_link_lib != nullptr) {
- find_libc_lib_path(g);
- }
-
lj->args.append("/NOLOGO");
if (!g->strip_debug_symbols) {
@@ -608,6 +559,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
bool is_library = g->out_type == OutTypeLib;
switch (g->subsystem) {
case TargetSubsystemAuto:
+ if (g->zig_target->os == OsUefi) {
+ add_uefi_link_args(lj);
+ } else {
+ add_nt_link_args(lj, is_library);
+ }
break;
case TargetSubsystemConsole:
lj->args.append("/SUBSYSTEM:console");
@@ -646,13 +602,11 @@ static void construct_linker_job_coff(LinkJob *lj) {
lj->args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(&g->output_file_path))));
if (g->libc_link_lib != nullptr) {
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->msvc_lib_dir))));
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->kernel32_lib_dir))));
+ assert(g->libc != nullptr);
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_lib_dir))));
- if (g->libc_static_lib_dir != nullptr) {
- lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(g->libc_static_lib_dir))));
- }
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->msvc_lib_dir))));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->kernel32_lib_dir))));
+ lj->args.append(buf_ptr(buf_sprintf("-LIBPATH:%s", buf_ptr(&g->libc->crt_dir))));
}
if (is_library && !g->is_static) {
@@ -687,7 +641,7 @@ static void construct_linker_job_coff(LinkJob *lj) {
continue;
}
if (link_lib->provided_explicitly) {
- if (lj->codegen->zig_target.env_type == ZigLLVM_GNU) {
+ if (lj->codegen->zig_target->abi == ZigLLVM_GNU) {
Buf *arg = buf_sprintf("-l%s", buf_ptr(link_lib->name));
lj->args.append(buf_ptr(arg));
}
@@ -717,7 +671,8 @@ static void construct_linker_job_coff(LinkJob *lj) {
gen_lib_args.append(buf_ptr(buf_sprintf("-DEF:%s", buf_ptr(def_path))));
gen_lib_args.append(buf_ptr(buf_sprintf("-OUT:%s", buf_ptr(generated_lib_path))));
Buf diag = BUF_INIT;
- if (!zig_lld_link(g->zig_target.oformat, gen_lib_args.items, gen_lib_args.length, &diag)) {
+ ZigLLVM_ObjectFormatType target_ofmt = target_object_format(g->zig_target);
+ if (!zig_lld_link(target_ofmt, gen_lib_args.items, gen_lib_args.length, &diag)) {
fprintf(stderr, "%s\n", buf_ptr(&diag));
exit(1);
}
@@ -786,7 +741,7 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
platform->kind = MacOS;
} else if (g->mios_version_min) {
platform->kind = IPhoneOS;
- } else if (g->zig_target.os == OsMacOSX) {
+ } else if (g->zig_target->os == OsMacOSX) {
platform->kind = MacOS;
g->mmacosx_version_min = buf_create_from_str("10.10");
} else {
@@ -813,8 +768,8 @@ static void get_darwin_platform(LinkJob *lj, DarwinPlatform *platform) {
}
if (platform->kind == IPhoneOS &&
- (g->zig_target.arch.arch == ZigLLVM_x86 ||
- g->zig_target.arch.arch == ZigLLVM_x86_64))
+ (g->zig_target->arch == ZigLLVM_x86 ||
+ g->zig_target->arch == ZigLLVM_x86_64))
{
platform->kind = IPhoneOSSimulator;
}
@@ -878,7 +833,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
}
lj->args.append("-arch");
- lj->args.append(get_darwin_arch_string(&g->zig_target));
+ lj->args.append(get_darwin_arch_string(g->zig_target));
DarwinPlatform platform;
get_darwin_platform(lj, &platform);
@@ -893,7 +848,11 @@ static void construct_linker_job_macho(LinkJob *lj) {
lj->args.append("-ios_simulator_version_min");
break;
}
- lj->args.append(buf_ptr(buf_sprintf("%d.%d.%d", platform.major, platform.minor, platform.micro)));
+ Buf *version_string = buf_sprintf("%d.%d.%d", platform.major, platform.minor, platform.micro);
+ lj->args.append(buf_ptr(version_string));
+
+ lj->args.append("-sdk_version");
+ lj->args.append(buf_ptr(version_string));
if (g->out_type == OutTypeExe) {
@@ -914,7 +873,9 @@ static void construct_linker_job_macho(LinkJob *lj) {
add_rpath(lj, &g->output_file_path);
if (shared) {
- lj->args.append("-headerpad_max_install_names");
+ if (g->system_linker_hack) {
+ lj->args.append("-headerpad_max_install_names");
+ }
} else if (g->is_static) {
lj->args.append("-lcrt0.o");
} else {
@@ -929,7 +890,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
}
break;
case IPhoneOS:
- if (g->zig_target.arch.arch == ZigLLVM_aarch64) {
+ if (g->zig_target->arch == ZigLLVM_aarch64) {
// iOS does not need any crt1 files for arm64
} else if (darwin_version_lt(&platform, 3, 1)) {
lj->args.append("-lcrt1.o");
@@ -959,7 +920,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
lj->args.append(buf_ptr(compiler_rt_o_path));
}
- if (g->is_native_target) {
+ if (g->zig_target->is_native) {
for (size_t lib_i = 0; lib_i < g->link_libs_list.length; lib_i += 1) {
LinkLib *link_lib = g->link_libs_list.at(lib_i);
if (buf_eql_str(link_lib->name, "c")) {
@@ -1000,7 +961,7 @@ static void construct_linker_job_macho(LinkJob *lj) {
}
static void construct_linker_job(LinkJob *lj) {
- switch (lj->codegen->zig_target.oformat) {
+ switch (target_object_format(lj->codegen->zig_target)) {
case ZigLLVM_UnknownObjectFormat:
zig_unreachable();
@@ -1040,7 +1001,7 @@ void codegen_link(CodeGen *g) {
for (size_t i = 0; i < g->link_objects.length; i += 1) {
file_names.append((const char *)buf_ptr(g->link_objects.at(i)));
}
- ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target.os);
+ ZigLLVM_OSType os_type = get_llvm_os_type(g->zig_target->os);
codegen_add_time_event(g, "LLVM Link");
if (ZigLLVMWriteArchive(buf_ptr(&g->output_file_path), file_names.items, file_names.length, os_type)) {
fprintf(stderr, "Unable to write archive '%s'\n", buf_ptr(&g->output_file_path));
@@ -1065,7 +1026,7 @@ void codegen_link(CodeGen *g) {
Buf diag = BUF_INIT;
codegen_add_time_event(g, "LLVM Link");
- if (g->system_linker_hack && g->zig_target.os == OsMacOSX) {
+ if (g->system_linker_hack && g->zig_target->os == OsMacOSX) {
Termination term;
ZigList args = {};
for (size_t i = 1; i < lj.args.length; i += 1) {
@@ -1075,7 +1036,7 @@ void codegen_link(CodeGen *g) {
if (term.how != TerminationIdClean || term.code != 0) {
exit(1);
}
- } else if (!zig_lld_link(g->zig_target.oformat, lj.args.items, lj.args.length, &diag)) {
+ } else if (!zig_lld_link(target_object_format(g->zig_target), lj.args.items, lj.args.length, &diag)) {
fprintf(stderr, "%s\n", buf_ptr(&diag));
exit(1);
}
diff --git a/src/main.cpp b/src/main.cpp
index 73a1d75d42..d2099a9f80 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -13,16 +13,17 @@
#include "error.hpp"
#include "os.hpp"
#include "target.hpp"
+#include "libc_installation.hpp"
#include
static int print_error_usage(const char *arg0) {
- fprintf(stderr, "See `%s help` for detailed usage information\n", arg0);
+ fprintf(stderr, "See `%s --help` for detailed usage information\n", arg0);
return EXIT_FAILURE;
}
-static int print_full_usage(const char *arg0) {
- fprintf(stdout,
+static int print_full_usage(const char *arg0, FILE *file, int return_code) {
+ fprintf(file,
"Usage: %s [command] [options]\n"
"\n"
"Commands:\n"
@@ -31,10 +32,12 @@ static int print_full_usage(const char *arg0) {
" build-lib [source] create library from source or object files\n"
" build-obj [source] create object from source or assembly\n"
" builtin show the source code of that @import(\"builtin\")\n"
- " help show this usage information\n"
+ " cc C compiler\n"
+ " fmt parse files and render in canonical zig format\n"
" id print the base64-encoded compiler id\n"
" init-exe initialize a `zig build` application in the cwd\n"
" init-lib initialize a `zig build` library in the cwd\n"
+ " libc [paths_file] Display native libc paths file or validate one\n"
" run [source] create executable and run immediately\n"
" translate-c [source] convert c code to zig code\n"
" targets list available compilation targets\n"
@@ -44,16 +47,20 @@ static int print_full_usage(const char *arg0) {
"\n"
"Compile Options:\n"
" --assembly [source] add assembly file to build\n"
+ " --c-source [options] [file] compile C source code\n"
" --cache-dir [path] override the cache directory\n"
" --cache [auto|off|on] build in global cache, print out paths to stdout\n"
" --color [auto|off|on] enable or disable colored error messages\n"
" --disable-pic disable Position Independent Code for libraries\n"
+ " --disable-valgrind omit valgrind client requests in debug builds\n"
+ " --enable-valgrind include valgrind client requests release builds\n"
" --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
" -ftime-report print timing diagnostics\n"
- " --libc-include-dir [path] directory where libc stdlib.h resides\n"
+ " --libc [file] Provide a file which specifies libc paths\n"
" --name [name] override output name\n"
" --output [file] override destination path\n"
" --output-h [file] generate header file\n"
+ " --output-lib [file] override import library path\n"
" --pkg-begin [name] [path] make pkg available to import and push current pkg\n"
" --pkg-end pop current pkg\n"
" --release-fast build with optimizations on and safety off\n"
@@ -62,15 +69,14 @@ static int print_full_usage(const char *arg0) {
" --single-threaded source may assume it is only used single-threaded\n"
" --static output will be statically linked\n"
" --strip exclude debug symbols\n"
- " --target-arch [name] specify target architecture\n"
- " --target-environ [name] specify target environment\n"
- " --target-os [name] specify target operating system\n"
+ " -target [name] -- see the targets command\n"
" --verbose-tokenize enable compiler debug output for tokenization\n"
" --verbose-ast enable compiler debug output for AST parsing\n"
" --verbose-link enable compiler debug output for linking\n"
" --verbose-ir enable compiler debug output for Zig IR\n"
" --verbose-llvm-ir enable compiler debug output for LLVM IR\n"
" --verbose-cimport enable compiler debug output for C imports\n"
+ " --verbose-cc enable compiler debug output for C compilation\n"
" -dirafter [dir] same as -isystem but do it last\n"
" -isystem [dir] add additional search path for other .h files\n"
" -mllvm [arg] forward an arg to LLVM's option processing\n"
@@ -79,10 +85,6 @@ static int print_full_usage(const char *arg0) {
"Link Options:\n"
" --dynamic-linker [path] set the path to ld.so\n"
" --each-lib-rpath add rpath for each used dynamic library\n"
- " --libc-lib-dir [path] directory where libc crt1.o resides\n"
- " --libc-static-lib-dir [path] directory where libc crtbegin.o resides\n"
- " --msvc-lib-dir [path] (windows) directory where vcruntime.lib resides\n"
- " --kernel32-lib-dir [path] (windows) directory where kernel32.lib resides\n"
" --library [lib] link against lib\n"
" --forbid-library [lib] make it an error to link against lib\n"
" --library-path [dir] add a directory to the library search path\n"
@@ -91,7 +93,6 @@ static int print_full_usage(const char *arg0) {
" -L[dir] alias for --library-path\n"
" -rdynamic add all symbols to the dynamic symbol table\n"
" -rpath [path] add directory to the runtime library search path\n"
- " --no-rosegment compromise security to workaround valgrind bug\n"
" --subsystem [subsystem] (windows) /SUBSYSTEM: to the linker\n"
" -framework [name] (darwin) link against framework\n"
" -mios-version-min [ver] (darwin) set iOS deployment target\n"
@@ -106,7 +107,27 @@ static int print_full_usage(const char *arg0) {
" --test-cmd [arg] specify test execution command one arg at a time\n"
" --test-cmd-bin appends test binary path to test cmd args\n"
, arg0);
- return EXIT_SUCCESS;
+ return return_code;
+}
+
+static int print_libc_usage(const char *arg0, FILE *file, int return_code) {
+ fprintf(file,
+ "Usage: %s libc\n"
+ "\n"
+ "Detect the native libc installation and print the resulting paths to stdout.\n"
+ "You can save this into a file and then edit the paths to create a cross\n"
+ "compilation libc kit. Then you can pass `--libc [file]` for Zig to use it.\n"
+ "\n"
+ "When compiling natively and no `--libc` argument provided, Zig automatically\n"
+ "creates zig-cache/native_libc.txt so that it does not have to detect libc\n"
+ "on every invocation. You can remove this file to have Zig re-detect the\n"
+ "native libc.\n"
+ "\n\n"
+ "Usage: %s libc [file]\n"
+ "\n"
+ "Parse a libc installation text file and validate it.\n"
+ , arg0, arg0);
+ return return_code;
}
static const char *ZIG_ZEN = "\n"
@@ -122,6 +143,14 @@ static const char *ZIG_ZEN = "\n"
" * Minimize energy spent on coding style.\n"
" * Together we serve end users.\n";
+static bool arch_available_in_llvm(ZigLLVM_ArchType arch) {
+ LLVMTargetRef target_ref;
+ char *err_msg = nullptr;
+ char triple_string[128];
+ sprintf(triple_string, "%s-unknown-unknown-unknown", ZigLLVMGetArchTypeName(arch));
+ return !LLVMGetTargetFromTriple(triple_string, &target_ref, &err_msg);
+}
+
static int print_target_list(FILE *f) {
ZigTarget native;
get_native_target(&native);
@@ -129,28 +158,36 @@ static int print_target_list(FILE *f) {
fprintf(f, "Architectures:\n");
size_t arch_count = target_arch_count();
for (size_t arch_i = 0; arch_i < arch_count; arch_i += 1) {
- const ArchType *arch = get_target_arch(arch_i);
- char arch_name[50];
- get_arch_name(arch_name, arch);
- const char *native_str = (native.arch.arch == arch->arch && native.arch.sub_arch == arch->sub_arch) ?
- " (native)" : "";
- fprintf(f, " %s%s\n", arch_name, native_str);
+ ZigLLVM_ArchType arch = target_arch_enum(arch_i);
+ if (!arch_available_in_llvm(arch))
+ continue;
+ const char *arch_name = target_arch_name(arch);
+ SubArchList sub_arch_list = target_subarch_list(arch);
+ size_t sub_count = target_subarch_count(sub_arch_list);
+ const char *arch_native_str = (native.arch == arch) ? " (native)" : "";
+ fprintf(stderr, " %s%s\n", arch_name, arch_native_str);
+ for (size_t sub_i = 0; sub_i < sub_count; sub_i += 1) {
+ ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
+ const char *sub_name = target_subarch_name(sub);
+ const char *sub_native_str = (native.arch == arch && native.sub_arch == sub) ? " (native)" : "";
+ fprintf(f, " %s%s\n", sub_name, sub_native_str);
+ }
}
fprintf(f, "\nOperating Systems:\n");
size_t os_count = target_os_count();
for (size_t i = 0; i < os_count; i += 1) {
- Os os_type = get_target_os(i);
+ Os os_type = target_os_enum(i);
const char *native_str = (native.os == os_type) ? " (native)" : "";
- fprintf(f, " %s%s\n", get_target_os_name(os_type), native_str);
+ fprintf(f, " %s%s\n", target_os_name(os_type), native_str);
}
- fprintf(f, "\nEnvironments:\n");
- size_t environ_count = target_environ_count();
- for (size_t i = 0; i < environ_count; i += 1) {
- ZigLLVM_EnvironmentType environ_type = get_target_environ(i);
- const char *native_str = (native.env_type == environ_type) ? " (native)" : "";
- fprintf(f, " %s%s\n", ZigLLVMGetEnvironmentTypeName(environ_type), native_str);
+ fprintf(f, "\nC ABIs:\n");
+ size_t abi_count = target_abi_count();
+ for (size_t i = 0; i < abi_count; i += 1) {
+ ZigLLVM_EnvironmentType abi = target_abi_enum(i);
+ const char *native_str = (native.abi == abi) ? " (native)" : "";
+ fprintf(f, " %s%s\n", target_abi_name(abi), native_str);
}
return EXIT_SUCCESS;
@@ -160,13 +197,13 @@ enum Cmd {
CmdNone,
CmdBuild,
CmdBuiltin,
- CmdHelp,
CmdRun,
CmdTargets,
CmdTest,
CmdTranslateC,
CmdVersion,
CmdZen,
+ CmdLibC,
};
static const char *default_zig_cache_name = "zig-cache";
@@ -219,6 +256,8 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {
zig_unreachable();
}
+extern "C" int ZigClang_main(int argc, char **argv);
+
int main(int argc, char **argv) {
char *arg0 = argv[0];
Error err;
@@ -236,6 +275,12 @@ int main(int argc, char **argv) {
return 0;
}
+ if (argc >= 2 && (strcmp(argv[1], "cc") == 0 ||
+ strcmp(argv[1], "-cc1") == 0 || strcmp(argv[1], "-cc1as") == 0))
+ {
+ return ZigClang_main(argc, argv);
+ }
+
// Must be before all os.hpp function calls.
os_init();
@@ -345,6 +390,7 @@ int main(int argc, char **argv) {
const char *in_file = nullptr;
const char *out_file = nullptr;
const char *out_file_h = nullptr;
+ const char *out_file_lib = nullptr;
bool strip = false;
bool is_static = false;
OutType out_type = OutTypeUnknown;
@@ -355,23 +401,17 @@ int main(int argc, char **argv) {
bool verbose_ir = false;
bool verbose_llvm_ir = false;
bool verbose_cimport = false;
+ bool verbose_cc = false;
ErrColor color = ErrColorAuto;
CacheOpt enable_cache = CacheOptAuto;
- const char *libc_lib_dir = nullptr;
- const char *libc_static_lib_dir = nullptr;
- const char *libc_include_dir = nullptr;
- const char *msvc_lib_dir = nullptr;
- const char *kernel32_lib_dir = nullptr;
- const char *dynamic_linker = nullptr;
+ const char *libc_txt = nullptr;
ZigList clang_argv = {0};
ZigList llvm_argv = {0};
ZigList lib_dirs = {0};
ZigList link_libs = {0};
ZigList forbidden_link_libs = {0};
ZigList frameworks = {0};
- const char *target_arch = nullptr;
- const char *target_os = nullptr;
- const char *target_environ = nullptr;
+ const char *target_string = nullptr;
bool rdynamic = false;
const char *mmacosx_version_min = nullptr;
const char *mios_version_min = nullptr;
@@ -379,6 +419,7 @@ int main(int argc, char **argv) {
ZigList rpath_list = {0};
bool each_lib_rpath = false;
ZigList objects = {0};
+ ZigList c_source_files = {0};
ZigList asm_files = {0};
const char *test_filter = nullptr;
const char *test_name_prefix = nullptr;
@@ -392,11 +433,11 @@ int main(int argc, char **argv) {
BuildMode build_mode = BuildModeDebug;
ZigList test_exec_args = {0};
int runtime_args_start = -1;
- bool no_rosegment_workaround = false;
bool system_linker_hack = false;
TargetSubsystem subsystem = TargetSubsystemAuto;
bool is_single_threaded = false;
Buf *override_std_dir = nullptr;
+ ValgrindSupport valgrind_support = ValgrindSupportAuto;
if (argc >= 2 && strcmp(argv[1], "build") == 0) {
Buf zig_exe_path_buf = BUF_INIT;
@@ -432,8 +473,11 @@ int main(int argc, char **argv) {
Buf *build_runner_path = buf_alloc();
os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path);
- CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
- override_std_dir);
+ ZigTarget target;
+ get_native_target(&target);
+ CodeGen *g = codegen_create(build_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
+ override_std_dir, nullptr);
+ g->valgrind_support = valgrind_support;
g->enable_time_report = timing_info;
buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
codegen_set_out_name(g, buf_create_from_str("build"));
@@ -484,6 +528,7 @@ int main(int argc, char **argv) {
" --verbose-ir Enable compiler debug output for Zig IR\n"
" --verbose-llvm-ir Enable compiler debug output for LLVM IR\n"
" --verbose-cimport Enable compiler debug output for C imports\n"
+ " --verbose-cc Enable compiler debug output for C compilation\n"
"\n"
, zig_exe_path);
return EXIT_SUCCESS;
@@ -493,7 +538,7 @@ int main(int argc, char **argv) {
"No 'build.zig' file found.\n"
"Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n"
"or build an executable directly with `zig build-exe $FILENAME.zig`.\n"
- "See: `zig build --help` or `zig help` for more options.\n"
+ "See: `zig build --help` or `zig --help` for more options.\n"
);
return EXIT_FAILURE;
}
@@ -515,6 +560,37 @@ int main(int argc, char **argv) {
fprintf(stderr, "\n");
}
return (term.how == TerminationIdClean) ? term.code : -1;
+ } else if (argc >= 2 && strcmp(argv[1], "fmt") == 0) {
+ init_all_targets();
+ ZigTarget target;
+ get_native_target(&target);
+ Buf *fmt_runner_path = buf_alloc();
+ os_path_join(get_zig_special_dir(), buf_create_from_str("fmt_runner.zig"), fmt_runner_path);
+ CodeGen *g = codegen_create(fmt_runner_path, &target, OutTypeExe, BuildModeDebug, get_zig_lib_dir(),
+ nullptr, nullptr);
+ buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
+ g->valgrind_support = valgrind_support;
+ g->is_single_threaded = true;
+ codegen_set_out_name(g, buf_create_from_str("fmt"));
+ g->enable_cache = true;
+
+ codegen_build_and_link(g);
+
+ // TODO standardize os.cpp so that the args are supposed to have the exe
+ ZigList args_with_exe = {0};
+ ZigList args_without_exe = {0};
+ const char *exec_path = buf_ptr(&g->output_file_path);
+ args_with_exe.append(exec_path);
+ for (int i = 2; i < argc; i += 1) {
+ args_with_exe.append(argv[i]);
+ args_without_exe.append(argv[i]);
+ }
+ args_with_exe.append(nullptr);
+ os_execv(exec_path, args_with_exe.items);
+
+ Termination term;
+ os_spawn_process(exec_path, args_without_exe, &term);
+ return term.code;
}
for (int i = 1; i < argc; i += 1) {
@@ -527,6 +603,12 @@ int main(int argc, char **argv) {
build_mode = BuildModeSafeRelease;
} else if (strcmp(arg, "--release-small") == 0) {
build_mode = BuildModeSmallRelease;
+ } else if (strcmp(arg, "--help") == 0) {
+ if (cmd == CmdLibC) {
+ return print_libc_usage(arg0, stdout, EXIT_SUCCESS);
+ } else {
+ return print_full_usage(arg0, stdout, EXIT_SUCCESS);
+ }
} else if (strcmp(arg, "--strip") == 0) {
strip = true;
} else if (strcmp(arg, "--static") == 0) {
@@ -543,16 +625,20 @@ int main(int argc, char **argv) {
verbose_llvm_ir = true;
} else if (strcmp(arg, "--verbose-cimport") == 0) {
verbose_cimport = true;
+ } else if (strcmp(arg, "--verbose-cc") == 0) {
+ verbose_cc = true;
} else if (strcmp(arg, "-rdynamic") == 0) {
rdynamic = true;
- } else if (strcmp(arg, "--no-rosegment") == 0) {
- no_rosegment_workaround = true;
} else if (strcmp(arg, "--each-lib-rpath") == 0) {
each_lib_rpath = true;
} else if (strcmp(arg, "-ftime-report") == 0) {
timing_info = true;
} else if (strcmp(arg, "--disable-pic") == 0) {
disable_pic = true;
+ } else if (strcmp(arg, "--enable-valgrind") == 0) {
+ valgrind_support = ValgrindSupportEnabled;
+ } else if (strcmp(arg, "--disable-valgrind") == 0) {
+ valgrind_support = ValgrindSupportDisabled;
} else if (strcmp(arg, "--system-linker-hack") == 0) {
system_linker_hack = true;
} else if (strcmp(arg, "--single-threaded") == 0) {
@@ -590,6 +676,8 @@ int main(int argc, char **argv) {
out_file = argv[i];
} else if (strcmp(arg, "--output-h") == 0) {
out_file_h = argv[i];
+ } else if (strcmp(arg, "--output-lib") == 0) {
+ out_file_lib = argv[i];
} else if (strcmp(arg, "--color") == 0) {
if (strcmp(argv[i], "auto") == 0) {
color = ErrColorAuto;
@@ -625,18 +713,8 @@ int main(int argc, char **argv) {
}
} else if (strcmp(arg, "--name") == 0) {
out_name = argv[i];
- } else if (strcmp(arg, "--libc-lib-dir") == 0) {
- libc_lib_dir = argv[i];
- } else if (strcmp(arg, "--libc-static-lib-dir") == 0) {
- libc_static_lib_dir = argv[i];
- } else if (strcmp(arg, "--libc-include-dir") == 0) {
- libc_include_dir = argv[i];
- } else if (strcmp(arg, "--msvc-lib-dir") == 0) {
- msvc_lib_dir = argv[i];
- } else if (strcmp(arg, "--kernel32-lib-dir") == 0) {
- kernel32_lib_dir = argv[i];
- } else if (strcmp(arg, "--dynamic-linker") == 0) {
- dynamic_linker = argv[i];
+ } else if (strcmp(arg, "--libc") == 0) {
+ libc_txt = argv[i];
} else if (strcmp(arg, "-isystem") == 0) {
clang_argv.append("-isystem");
clang_argv.append(argv[i]);
@@ -658,16 +736,25 @@ int main(int argc, char **argv) {
forbidden_link_libs.append(argv[i]);
} else if (strcmp(arg, "--object") == 0) {
objects.append(argv[i]);
+ } else if (strcmp(arg, "--c-source") == 0) {
+ CFile *c_file = allocate(1);
+ for (;;) {
+ if (argv[i][0] == '-') {
+ c_file->args.append(argv[i]);
+ i += 1;
+ continue;
+ } else {
+ c_file->source_path = argv[i];
+ c_source_files.append(c_file);
+ break;
+ }
+ }
} else if (strcmp(arg, "--assembly") == 0) {
asm_files.append(argv[i]);
} else if (strcmp(arg, "--cache-dir") == 0) {
cache_dir = argv[i];
- } else if (strcmp(arg, "--target-arch") == 0) {
- target_arch = argv[i];
- } else if (strcmp(arg, "--target-os") == 0) {
- target_os = argv[i];
- } else if (strcmp(arg, "--target-environ") == 0) {
- target_environ = argv[i];
+ } else if (strcmp(arg, "-target") == 0) {
+ target_string = argv[i];
} else if (strcmp(arg, "-mmacosx-version-min") == 0) {
mmacosx_version_min = argv[i];
} else if (strcmp(arg, "-mios-version-min") == 0) {
@@ -736,8 +823,6 @@ int main(int argc, char **argv) {
} else if (strcmp(arg, "build-lib") == 0) {
cmd = CmdBuild;
out_type = OutTypeLib;
- } else if (strcmp(arg, "help") == 0) {
- cmd = CmdHelp;
} else if (strcmp(arg, "run") == 0) {
cmd = CmdRun;
out_type = OutTypeExe;
@@ -745,6 +830,8 @@ int main(int argc, char **argv) {
cmd = CmdVersion;
} else if (strcmp(arg, "zen") == 0) {
cmd = CmdZen;
+ } else if (strcmp(arg, "libc") == 0) {
+ cmd = CmdLibC;
} else if (strcmp(arg, "translate-c") == 0) {
cmd = CmdTranslateC;
} else if (strcmp(arg, "test") == 0) {
@@ -764,6 +851,7 @@ int main(int argc, char **argv) {
case CmdRun:
case CmdTranslateC:
case CmdTest:
+ case CmdLibC:
if (!in_file) {
in_file = arg;
if (cmd == CmdRun) {
@@ -776,7 +864,6 @@ int main(int argc, char **argv) {
}
break;
case CmdBuiltin:
- case CmdHelp:
case CmdVersion:
case CmdZen:
case CmdTargets:
@@ -795,36 +882,34 @@ int main(int argc, char **argv) {
init_all_targets();
- ZigTarget alloc_target;
- ZigTarget *target;
- if (!target_arch && !target_os && !target_environ) {
- target = nullptr;
+ ZigTarget target;
+ if (target_string == nullptr) {
+ get_native_target(&target);
} else {
- target = &alloc_target;
- get_unknown_target(target);
- if (target_arch) {
- if (parse_target_arch(target_arch, &target->arch)) {
- fprintf(stderr, "invalid --target-arch argument\n");
- return print_error_usage(arg0);
- }
- }
- if (target_os) {
- if (parse_target_os(target_os, &target->os)) {
- fprintf(stderr, "invalid --target-os argument\n");
- return print_error_usage(arg0);
- }
- }
- if (target_environ) {
- if (parse_target_environ(target_environ, &target->env_type)) {
- fprintf(stderr, "invalid --target-environ argument\n");
- return print_error_usage(arg0);
- }
+ if ((err = target_parse_triple(&target, target_string))) {
+ fprintf(stderr, "invalid target: %s\n", err_str(err));
+ return print_error_usage(arg0);
}
}
switch (cmd) {
+ case CmdLibC: {
+ if (in_file) {
+ ZigLibCInstallation libc;
+ if ((err = zig_libc_parse(&libc, buf_create_from_str(in_file), &target, true)))
+ return EXIT_FAILURE;
+ return EXIT_SUCCESS;
+ }
+ ZigLibCInstallation libc;
+ if ((err = zig_libc_find_native(&libc, true)))
+ return EXIT_FAILURE;
+ zig_libc_render(&libc, stdout);
+ return EXIT_SUCCESS;
+ }
case CmdBuiltin: {
- CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir(), override_std_dir);
+ CodeGen *g = codegen_create(nullptr, &target, out_type, build_mode, get_zig_lib_dir(), override_std_dir,
+ nullptr);
+ g->valgrind_support = valgrind_support;
g->is_single_threaded = is_single_threaded;
Buf *builtin_source = codegen_generate_builtin_source(g);
if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
@@ -838,15 +923,43 @@ int main(int argc, char **argv) {
case CmdTranslateC:
case CmdTest:
{
- if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0) {
- fprintf(stderr, "Expected source file argument or at least one --object or --assembly argument.\n");
+ if (cmd == CmdBuild && !in_file && objects.length == 0 && asm_files.length == 0 &&
+ c_source_files.length == 0)
+ {
+ fprintf(stderr,
+ "Expected at least one of these things:\n"
+ " * Zig root source file argument\n"
+ " * --object argument\n"
+ " * --assembly argument\n"
+ " * --c-source argument\n");
return print_error_usage(arg0);
} else if ((cmd == CmdTranslateC || cmd == CmdTest || cmd == CmdRun) && !in_file) {
fprintf(stderr, "Expected source file argument.\n");
return print_error_usage(arg0);
- } else if (cmd == CmdBuild && out_type == OutTypeObj && objects.length != 0) {
- fprintf(stderr, "When building an object file, --object arguments are invalid.\n");
- return print_error_usage(arg0);
+ } else if (cmd == CmdBuild && out_type == OutTypeObj) {
+ if (objects.length != 0) {
+ fprintf(stderr,
+ "When building an object file, --object arguments are invalid.\n"
+ "Consider building a static library instead.\n");
+ return print_error_usage(arg0);
+ }
+ size_t zig_root_src_count = in_file ? 1 : 0;
+ if (zig_root_src_count + c_source_files.length > 1) {
+ fprintf(stderr,
+ "When building an object file, only one of these allowed:\n"
+ " * Zig root source file argument\n"
+ " * --c-source argument\n"
+ "Consider building a static library instead.\n");
+ return print_error_usage(arg0);
+ }
+ if (c_source_files.length != 0 && asm_files.length != 0) {
+ fprintf(stderr,
+ "When building an object file, only one of these allowed:\n"
+ " * --assembly argument\n"
+ " * --c-source argument\n"
+ "Consider building a static library instead.\n");
+ return print_error_usage(arg0);
+ }
}
assert(cmd != CmdBuild || out_type != OutTypeUnknown);
@@ -873,6 +986,13 @@ int main(int argc, char **argv) {
}
}
+ if (need_name && buf_out_name == nullptr && c_source_files.length == 1) {
+ Buf basename = BUF_INIT;
+ os_path_split(buf_create_from_str(c_source_files.at(0)->source_path), nullptr, &basename);
+ buf_out_name = buf_alloc();
+ os_path_extname(&basename, buf_out_name, nullptr);
+ }
+
if (need_name && buf_out_name == nullptr) {
fprintf(stderr, "--name [name] not provided and unable to infer\n\n");
return print_error_usage(arg0);
@@ -883,8 +1003,17 @@ int main(int argc, char **argv) {
if (cmd == CmdRun && buf_out_name == nullptr) {
buf_out_name = buf_create_from_str("run");
}
- CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir(),
- override_std_dir);
+ ZigLibCInstallation *libc = nullptr;
+ if (libc_txt != nullptr) {
+ libc = allocate(1);
+ if ((err = zig_libc_parse(libc, buf_create_from_str(libc_txt), &target, true))) {
+ fprintf(stderr, "Unable to parse --libc text file: %s\n", err_str(err));
+ return EXIT_FAILURE;
+ }
+ }
+ CodeGen *g = codegen_create(zig_root_source_file, &target, out_type, build_mode, get_zig_lib_dir(),
+ override_std_dir, libc);
+ g->valgrind_support = valgrind_support;
g->subsystem = subsystem;
if (disable_pic) {
@@ -909,24 +1038,13 @@ int main(int argc, char **argv) {
codegen_set_llvm_argv(g, llvm_argv.items, llvm_argv.length);
codegen_set_strip(g, strip);
codegen_set_is_static(g, is_static);
- if (libc_lib_dir)
- codegen_set_libc_lib_dir(g, buf_create_from_str(libc_lib_dir));
- if (libc_static_lib_dir)
- codegen_set_libc_static_lib_dir(g, buf_create_from_str(libc_static_lib_dir));
- if (libc_include_dir)
- codegen_set_libc_include_dir(g, buf_create_from_str(libc_include_dir));
- if (msvc_lib_dir)
- codegen_set_msvc_lib_dir(g, buf_create_from_str(msvc_lib_dir));
- if (kernel32_lib_dir)
- codegen_set_kernel32_lib_dir(g, buf_create_from_str(kernel32_lib_dir));
- if (dynamic_linker)
- codegen_set_dynamic_linker(g, buf_create_from_str(dynamic_linker));
g->verbose_tokenize = verbose_tokenize;
g->verbose_ast = verbose_ast;
g->verbose_link = verbose_link;
g->verbose_ir = verbose_ir;
g->verbose_llvm_ir = verbose_llvm_ir;
g->verbose_cimport = verbose_cimport;
+ g->verbose_cc = verbose_cc;
codegen_set_errmsg_color(g, color);
g->system_linker_hack = system_linker_hack;
@@ -949,7 +1067,6 @@ int main(int argc, char **argv) {
}
codegen_set_rdynamic(g, rdynamic);
- g->no_rosegment_workaround = no_rosegment_workaround;
if (mmacosx_version_min && mios_version_min) {
fprintf(stderr, "-mmacosx-version-min and -mios-version-min options not allowed together\n");
return EXIT_FAILURE;
@@ -975,11 +1092,14 @@ int main(int argc, char **argv) {
codegen_set_output_path(g, buf_create_from_str(out_file));
if (out_file_h != nullptr && (out_type == OutTypeObj || out_type == OutTypeLib))
codegen_set_output_h_path(g, buf_create_from_str(out_file_h));
+ if (out_file_lib != nullptr && out_type == OutTypeLib && !is_static)
+ codegen_set_output_lib_path(g, buf_create_from_str(out_file_lib));
add_package(g, cur_pkg, g->root_package);
if (cmd == CmdBuild || cmd == CmdRun || cmd == CmdTest) {
+ g->c_source_files = c_source_files;
for (size_t i = 0; i < objects.length; i += 1) {
codegen_add_object(g, buf_create_from_str(objects.at(i)));
}
@@ -1052,7 +1172,7 @@ int main(int argc, char **argv) {
}
}
- if (!target_can_exec(&native, target)) {
+ if (!target_can_exec(&native, &target)) {
fprintf(stderr, "Created %s but skipping execution because it is non-native.\n",
buf_ptr(test_exe_path));
return 0;
@@ -1079,8 +1199,6 @@ int main(int argc, char **argv) {
zig_unreachable();
}
}
- case CmdHelp:
- return print_full_usage(arg0);
case CmdVersion:
printf("%s\n", ZIG_VERSION_STRING);
return EXIT_SUCCESS;
@@ -1090,7 +1208,6 @@ int main(int argc, char **argv) {
case CmdTargets:
return print_target_list(stdout);
case CmdNone:
- fprintf(stderr, "Zig programming language\n");
- return print_error_usage(arg0);
+ return print_full_usage(arg0, stderr, EXIT_FAILURE);
}
}
diff --git a/src/os.cpp b/src/os.cpp
index 8eb6b34654..732baea359 100644
--- a/src/os.cpp
+++ b/src/os.cpp
@@ -50,11 +50,11 @@ typedef SSIZE_T ssize_t;
#endif
-#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
+#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
#include
#endif
-#if defined(ZIG_OS_FREEBSD)
+#if defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
#include
#endif
@@ -78,7 +78,7 @@ static clock_serv_t cclock;
#if defined(__APPLE__) && !defined(environ)
#include
#define environ (*_NSGetEnviron())
-#elif defined(ZIG_OS_FREEBSD)
+#elif defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
extern char **environ;
#endif
@@ -1099,7 +1099,7 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
case EINTR:
return ErrorInterrupted;
case EINVAL:
- zig_unreachable();
+ return ErrorInvalidFilename;
case ENFILE:
case ENOMEM:
return ErrorSystemResources;
@@ -1232,6 +1232,18 @@ static Error os_buf_to_tmp_file_posix(Buf *contents, Buf *suffix, Buf *out_tmp_p
}
#endif
+Buf *os_tmp_filename(Buf *prefix, Buf *suffix) {
+ Buf *result = buf_create_from_buf(prefix);
+
+ const char base64[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
+ assert(array_length(base64) == 64 + 1);
+ for (size_t i = 0; i < 12; i += 1) {
+ buf_append_char(result, base64[rand() % 64]);
+ }
+ buf_append_buf(result, suffix);
+ return result;
+}
+
#if defined(ZIG_OS_WINDOWS)
static Error os_buf_to_tmp_file_windows(Buf *contents, Buf *suffix, Buf *out_tmp_path) {
char tmp_dir[MAX_PATH + 1];
@@ -1458,6 +1470,15 @@ Error os_self_exe_path(Buf *out_path) {
}
buf_resize(out_path, cb - 1);
return ErrorNone;
+#elif defined(ZIG_OS_NETBSD)
+ buf_resize(out_path, PATH_MAX);
+ int mib[4] = { CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME };
+ size_t cb = PATH_MAX;
+ if (sysctl(mib, 4, buf_ptr(out_path), &cb, nullptr, 0) != 0) {
+ return ErrorUnexpected;
+ }
+ buf_resize(out_path, cb - 1);
+ return ErrorNone;
#endif
return ErrorFileNotFound;
}
@@ -1541,7 +1562,7 @@ void os_stderr_set_color(TermColor color) {
#endif
}
-int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
+Error os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
#if defined(ZIG_OS_WINDOWS)
buf_resize(output_buf, 0);
buf_appendf(output_buf, "%s\\Lib\\%s\\ucrt\\", sdk->path10_ptr, sdk->version10_ptr);
@@ -1562,7 +1583,7 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch
buf_init_from_buf(tmp_buf, output_buf);
buf_append_str(tmp_buf, "ucrt.lib");
if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
- return 0;
+ return ErrorNone;
}
else {
buf_resize(output_buf, 0);
@@ -1573,12 +1594,12 @@ int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_Arch
#endif
}
-int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
+Error os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
#if defined(ZIG_OS_WINDOWS)
buf_resize(output_buf, 0);
buf_appendf(output_buf, "%s\\Include\\%s\\ucrt", sdk->path10_ptr, sdk->version10_ptr);
if (GetFileAttributesA(buf_ptr(output_buf)) != INVALID_FILE_ATTRIBUTES) {
- return 0;
+ return ErrorNone;
}
else {
buf_resize(output_buf, 0);
@@ -1589,7 +1610,7 @@ int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf* output_buf) {
#endif
}
-int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
+Error os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchType platform_type) {
#if defined(ZIG_OS_WINDOWS)
{
buf_resize(output_buf, 0);
@@ -1611,7 +1632,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
buf_init_from_buf(tmp_buf, output_buf);
buf_append_str(tmp_buf, "kernel32.lib");
if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
- return 0;
+ return ErrorNone;
}
}
{
@@ -1634,7 +1655,7 @@ int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf* output_buf, ZigLLVM_ArchTy
buf_init_from_buf(tmp_buf, output_buf);
buf_append_str(tmp_buf, "kernel32.lib");
if (GetFileAttributesA(buf_ptr(tmp_buf)) != INVALID_FILE_ATTRIBUTES) {
- return 0;
+ return ErrorNone;
}
}
return ErrorFileNotFound;
@@ -1776,7 +1797,7 @@ Error os_get_app_data_dir(Buf *out_path, const char *appname) {
}
-#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
+#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size, void *data) {
ZigList *libs = reinterpret_cast< ZigList *>(data);
if (info->dlpi_name[0] == '/') {
@@ -1787,7 +1808,7 @@ static int self_exe_shared_libs_callback(struct dl_phdr_info *info, size_t size,
#endif
Error os_self_exe_shared_libs(ZigList &paths) {
-#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD)
+#if defined(ZIG_OS_LINUX) || defined(ZIG_OS_FREEBSD) || defined(ZIG_OS_NETBSD)
paths.resize(0);
dl_iterate_phdr(self_exe_shared_libs_callback, &paths);
return ErrorNone;
diff --git a/src/os.hpp b/src/os.hpp
index 68ac6e0171..c4fae1d62b 100644
--- a/src/os.hpp
+++ b/src/os.hpp
@@ -25,6 +25,8 @@
#define ZIG_OS_LINUX
#elif defined(__FreeBSD__)
#define ZIG_OS_FREEBSD
+#elif defined(__NetBSD__)
+#define ZIG_OS_NETBSD
#else
#define ZIG_OS_UNKNOWN
#endif
@@ -119,6 +121,7 @@ Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
bool os_stderr_tty(void);
void os_stderr_set_color(TermColor color);
+Buf *os_tmp_filename(Buf *prefix, Buf *suffix);
Error os_buf_to_tmp_file(Buf *contents, Buf *suffix, Buf *out_tmp_path);
Error os_delete_file(Buf *path);
@@ -133,9 +136,9 @@ Error ATTRIBUTE_MUST_USE os_self_exe_path(Buf *out_path);
Error ATTRIBUTE_MUST_USE os_get_app_data_dir(Buf *out_path, const char *appname);
-int os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
-int os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
-int os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
+Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_include_path(ZigWindowsSDK *sdk, Buf *output_buf);
+Error ATTRIBUTE_MUST_USE os_get_win32_ucrt_lib_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
+Error ATTRIBUTE_MUST_USE os_get_win32_kern32_path(ZigWindowsSDK *sdk, Buf *output_buf, ZigLLVM_ArchType platform_type);
Error ATTRIBUTE_MUST_USE os_self_exe_shared_libs(ZigList &paths);
diff --git a/src/parser.cpp b/src/parser.cpp
index 1c1af87c51..6fe78c14c3 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -2739,6 +2739,7 @@ static AstNode *ast_parse_async_prefix(ParseContext *pc) {
AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, async);
res->data.fn_call_expr.is_async = true;
+ res->data.fn_call_expr.seen = false;
if (eat_token_if(pc, TokenIdCmpLessThan) != nullptr) {
AstNode *prefix_expr = ast_expect(pc, ast_parse_prefix_expr);
expect_token(pc, TokenIdCmpGreaterThan);
@@ -2759,6 +2760,7 @@ static AstNode *ast_parse_fn_call_argumnets(ParseContext *pc) {
AstNode *res = ast_create_node(pc, NodeTypeFnCallExpr, paren);
res->data.fn_call_expr.params = params;
+ res->data.fn_call_expr.seen = false;
return res;
}
@@ -2778,7 +2780,8 @@ static AstNode *ast_parse_array_type_start(ParseContext *pc) {
// PtrTypeStart
// <- ASTERISK
// / ASTERISK2
-// / LBRACKET ASTERISK RBRACKET
+// / PTRUNKNOWN
+// / PTRC
static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
Token *asterisk = eat_token_if(pc, TokenIdStar);
if (asterisk != nullptr) {
@@ -2804,6 +2807,13 @@ static AstNode *ast_parse_ptr_type_start(ParseContext *pc) {
return res;
}
+ Token *cptr = eat_token_if(pc, TokenIdBracketStarCBracket);
+ if (cptr != nullptr) {
+ AstNode *res = ast_create_node(pc, NodeTypePointerType, cptr);
+ res->data.pointer_type.star_token = cptr;
+ return res;
+ }
+
return nullptr;
}
diff --git a/src/target.cpp b/src/target.cpp
index 577710eb4b..b5f49b70d5 100644
--- a/src/target.cpp
+++ b/src/target.cpp
@@ -9,127 +9,116 @@
#include "error.hpp"
#include "target.hpp"
#include "util.hpp"
+#include "os.hpp"
#include
-static const ArchType arch_list[] = {
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_5a},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_4a},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_3a},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_2a},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8_1a},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8r},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8m_baseline},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v8m_mainline},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7em},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7m},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7s},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7k},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v7ve},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6m},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6k},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v6t2},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v5},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v5te},
- {ZigLLVM_arm, ZigLLVM_ARMSubArch_v4t},
+static const SubArchList subarch_list_list[] = {
+ SubArchListNone,
+ SubArchListArm32,
+ SubArchListArm64,
+ SubArchListKalimba,
+ SubArchListMips,
+};
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_5a},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_4a},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_3a},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_2a},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8_1a},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8r},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8m_baseline},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v8m_mainline},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7em},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7m},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7s},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7k},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v7ve},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6m},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6k},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v6t2},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v5te},
- {ZigLLVM_armeb, ZigLLVM_ARMSubArch_v4t},
+static const ZigLLVM_SubArchType subarch_list_arm32[] = {
+ ZigLLVM_ARMSubArch_v8_5a,
+ ZigLLVM_ARMSubArch_v8_4a,
+ ZigLLVM_ARMSubArch_v8_3a,
+ ZigLLVM_ARMSubArch_v8_2a,
+ ZigLLVM_ARMSubArch_v8_1a,
+ ZigLLVM_ARMSubArch_v8,
+ ZigLLVM_ARMSubArch_v8r,
+ ZigLLVM_ARMSubArch_v8m_baseline,
+ ZigLLVM_ARMSubArch_v8m_mainline,
+ ZigLLVM_ARMSubArch_v7,
+ ZigLLVM_ARMSubArch_v7em,
+ ZigLLVM_ARMSubArch_v7m,
+ ZigLLVM_ARMSubArch_v7s,
+ ZigLLVM_ARMSubArch_v7k,
+ ZigLLVM_ARMSubArch_v7ve,
+ ZigLLVM_ARMSubArch_v6,
+ ZigLLVM_ARMSubArch_v6m,
+ ZigLLVM_ARMSubArch_v6k,
+ ZigLLVM_ARMSubArch_v6t2,
+ ZigLLVM_ARMSubArch_v5,
+ ZigLLVM_ARMSubArch_v5te,
+ ZigLLVM_ARMSubArch_v4t,
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_5a},
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_4a},
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_3a},
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_2a},
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8_1a},
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8},
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8r},
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_baseline},
- {ZigLLVM_aarch64, ZigLLVM_ARMSubArch_v8m_mainline},
+};
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_5a},
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_4a},
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_3a},
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_2a},
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8_1a},
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8},
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8r},
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_baseline},
- {ZigLLVM_aarch64_be, ZigLLVM_ARMSubArch_v8m_mainline},
+static const ZigLLVM_SubArchType subarch_list_arm64[] = {
+ ZigLLVM_ARMSubArch_v8_5a,
+ ZigLLVM_ARMSubArch_v8_4a,
+ ZigLLVM_ARMSubArch_v8_3a,
+ ZigLLVM_ARMSubArch_v8_2a,
+ ZigLLVM_ARMSubArch_v8_1a,
+ ZigLLVM_ARMSubArch_v8,
+ ZigLLVM_ARMSubArch_v8r,
+ ZigLLVM_ARMSubArch_v8m_baseline,
+ ZigLLVM_ARMSubArch_v8m_mainline,
+};
- {ZigLLVM_arc, ZigLLVM_NoSubArch},
- {ZigLLVM_avr, ZigLLVM_NoSubArch},
- {ZigLLVM_bpfel, ZigLLVM_NoSubArch},
- {ZigLLVM_bpfeb, ZigLLVM_NoSubArch},
- {ZigLLVM_hexagon, ZigLLVM_NoSubArch},
+static const ZigLLVM_SubArchType subarch_list_kalimba[] = {
+ ZigLLVM_KalimbaSubArch_v5,
+ ZigLLVM_KalimbaSubArch_v4,
+ ZigLLVM_KalimbaSubArch_v3,
+};
- {ZigLLVM_mips, ZigLLVM_MipsSubArch_r6},
- {ZigLLVM_mipsel, ZigLLVM_MipsSubArch_r6},
- {ZigLLVM_mips64, ZigLLVM_MipsSubArch_r6},
- {ZigLLVM_mips64el, ZigLLVM_MipsSubArch_r6},
+static const ZigLLVM_SubArchType subarch_list_mips[] = {
+ ZigLLVM_MipsSubArch_r6,
+};
- {ZigLLVM_msp430, ZigLLVM_NoSubArch},
- {ZigLLVM_ppc, ZigLLVM_NoSubArch},
- {ZigLLVM_ppc64, ZigLLVM_NoSubArch},
- {ZigLLVM_ppc64le, ZigLLVM_NoSubArch},
- {ZigLLVM_r600, ZigLLVM_NoSubArch},
- {ZigLLVM_amdgcn, ZigLLVM_NoSubArch},
- {ZigLLVM_riscv32, ZigLLVM_NoSubArch},
- {ZigLLVM_riscv64, ZigLLVM_NoSubArch},
- {ZigLLVM_sparc, ZigLLVM_NoSubArch},
- {ZigLLVM_sparcv9, ZigLLVM_NoSubArch},
- {ZigLLVM_sparcel, ZigLLVM_NoSubArch},
- {ZigLLVM_systemz, ZigLLVM_NoSubArch},
- {ZigLLVM_tce, ZigLLVM_NoSubArch},
- {ZigLLVM_tcele, ZigLLVM_NoSubArch},
- {ZigLLVM_thumb, ZigLLVM_NoSubArch},
- {ZigLLVM_thumbeb, ZigLLVM_NoSubArch},
- {ZigLLVM_x86, ZigLLVM_NoSubArch},
- {ZigLLVM_x86_64, ZigLLVM_NoSubArch},
- {ZigLLVM_xcore, ZigLLVM_NoSubArch},
- {ZigLLVM_nvptx, ZigLLVM_NoSubArch},
- {ZigLLVM_nvptx64, ZigLLVM_NoSubArch},
- {ZigLLVM_le32, ZigLLVM_NoSubArch},
- {ZigLLVM_le64, ZigLLVM_NoSubArch},
- {ZigLLVM_amdil, ZigLLVM_NoSubArch},
- {ZigLLVM_amdil64, ZigLLVM_NoSubArch},
- {ZigLLVM_hsail, ZigLLVM_NoSubArch},
- {ZigLLVM_hsail64, ZigLLVM_NoSubArch},
- {ZigLLVM_spir, ZigLLVM_NoSubArch},
- {ZigLLVM_spir64, ZigLLVM_NoSubArch},
-
- {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v3},
- {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v4},
- {ZigLLVM_kalimba, ZigLLVM_KalimbaSubArch_v5},
-
- {ZigLLVM_shave, ZigLLVM_NoSubArch},
- {ZigLLVM_lanai, ZigLLVM_NoSubArch},
- {ZigLLVM_wasm32, ZigLLVM_NoSubArch},
- {ZigLLVM_wasm64, ZigLLVM_NoSubArch},
- {ZigLLVM_renderscript32, ZigLLVM_NoSubArch},
- {ZigLLVM_renderscript64, ZigLLVM_NoSubArch},
+static const ZigLLVM_ArchType arch_list[] = {
+ ZigLLVM_arm, // ARM (little endian): arm, armv.*, xscale
+ ZigLLVM_armeb, // ARM (big endian): armeb
+ ZigLLVM_aarch64, // AArch64 (little endian): aarch64
+ ZigLLVM_aarch64_be, // AArch64 (big endian): aarch64_be
+ ZigLLVM_arc, // ARC: Synopsys ARC
+ ZigLLVM_avr, // AVR: Atmel AVR microcontroller
+ ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian)
+ ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian)
+ ZigLLVM_hexagon, // Hexagon: hexagon
+ ZigLLVM_mips, // MIPS: mips, mipsallegrex, mipsr6
+ ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el
+ ZigLLVM_mips64, // MIPS64: mips64, mips64r6, mipsn32, mipsn32r6
+ ZigLLVM_mips64el, // MIPS64EL: mips64el, mips64r6el, mipsn32el, mipsn32r6el
+ ZigLLVM_msp430, // MSP430: msp430
+ ZigLLVM_ppc, // PPC: powerpc
+ ZigLLVM_ppc64, // PPC64: powerpc64, ppu
+ ZigLLVM_ppc64le, // PPC64LE: powerpc64le
+ ZigLLVM_r600, // R600: AMD GPUs HD2XXX - HD6XXX
+ ZigLLVM_amdgcn, // AMDGCN: AMD GCN GPUs
+ ZigLLVM_riscv32, // RISC-V (32-bit): riscv32
+ ZigLLVM_riscv64, // RISC-V (64-bit): riscv64
+ ZigLLVM_sparc, // Sparc: sparc
+ ZigLLVM_sparcv9, // Sparcv9: Sparcv9
+ ZigLLVM_sparcel, // Sparc: (endianness = little). NB: 'Sparcle' is a CPU variant
+ ZigLLVM_systemz, // SystemZ: s390x
+ ZigLLVM_tce, // TCE (http://tce.cs.tut.fi/): tce
+ ZigLLVM_tcele, // TCE little endian (http://tce.cs.tut.fi/): tcele
+ ZigLLVM_thumb, // Thumb (little endian): thumb, thumbv.*
+ ZigLLVM_thumbeb, // Thumb (big endian): thumbeb
+ ZigLLVM_x86, // X86: i[3-9]86
+ ZigLLVM_x86_64, // X86-64: amd64, x86_64
+ ZigLLVM_xcore, // XCore: xcore
+ ZigLLVM_nvptx, // NVPTX: 32-bit
+ ZigLLVM_nvptx64, // NVPTX: 64-bit
+ ZigLLVM_le32, // le32: generic little-endian 32-bit CPU (PNaCl)
+ ZigLLVM_le64, // le64: generic little-endian 64-bit CPU (PNaCl)
+ ZigLLVM_amdil, // AMDIL
+ ZigLLVM_amdil64, // AMDIL with 64-bit pointers
+ ZigLLVM_hsail, // AMD HSAIL
+ ZigLLVM_hsail64, // AMD HSAIL with 64-bit pointers
+ ZigLLVM_spir, // SPIR: standard portable IR for OpenCL 32-bit version
+ ZigLLVM_spir64, // SPIR: standard portable IR for OpenCL 64-bit version
+ ZigLLVM_kalimba, // Kalimba: generic kalimba
+ ZigLLVM_shave, // SHAVE: Movidius vector VLIW processors
+ ZigLLVM_lanai, // Lanai: Lanai 32-bit
+ ZigLLVM_wasm32, // WebAssembly with 32-bit pointers
+ ZigLLVM_wasm64, // WebAssembly with 64-bit pointers
+ ZigLLVM_renderscript32, // 32-bit RenderScript
+ ZigLLVM_renderscript64, // 64-bit RenderScript
};
static const ZigLLVM_VendorType vendor_list[] = {
@@ -190,7 +179,7 @@ static const Os os_list[] = {
};
// Coordinate with zig_llvm.h
-static const ZigLLVM_EnvironmentType environ_list[] = {
+static const ZigLLVM_EnvironmentType abi_list[] = {
ZigLLVM_UnknownEnvironment,
ZigLLVM_GNU,
@@ -225,11 +214,12 @@ size_t target_oformat_count(void) {
return array_length(oformat_list);
}
-const ZigLLVM_ObjectFormatType get_target_oformat(size_t index) {
+ZigLLVM_ObjectFormatType target_oformat_enum(size_t index) {
+ assert(index < array_length(oformat_list));
return oformat_list[index];
}
-const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat) {
+const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat) {
switch (oformat) {
case ZigLLVM_UnknownObjectFormat: return "unknown";
case ZigLLVM_COFF: return "coff";
@@ -244,22 +234,25 @@ size_t target_arch_count(void) {
return array_length(arch_list);
}
-const ArchType *get_target_arch(size_t index) {
- return &arch_list[index];
+ZigLLVM_ArchType target_arch_enum(size_t index) {
+ assert(index < array_length(arch_list));
+ return arch_list[index];
}
size_t target_vendor_count(void) {
return array_length(vendor_list);
}
-ZigLLVM_VendorType get_target_vendor(size_t index) {
+ZigLLVM_VendorType target_vendor_enum(size_t index) {
+ assert(index < array_length(vendor_list));
return vendor_list[index];
}
size_t target_os_count(void) {
return array_length(os_list);
}
-Os get_target_os(size_t index) {
+Os target_os_enum(size_t index) {
+ assert(index < array_length(os_list));
return os_list[index];
}
@@ -414,7 +407,7 @@ static Os get_zig_os_type(ZigLLVM_OSType os_type) {
zig_unreachable();
}
-const char *get_target_os_name(Os os_type) {
+const char *target_os_name(Os os_type) {
switch (os_type) {
case OsFreestanding:
return "freestanding";
@@ -460,78 +453,257 @@ const char *get_target_os_name(Os os_type) {
zig_unreachable();
}
-size_t target_environ_count(void) {
- return array_length(environ_list);
+size_t target_abi_count(void) {
+ return array_length(abi_list);
}
-ZigLLVM_EnvironmentType get_target_environ(size_t index) {
- return environ_list[index];
+ZigLLVM_EnvironmentType target_abi_enum(size_t index) {
+ assert(index < array_length(abi_list));
+ return abi_list[index];
+}
+const char *target_abi_name(ZigLLVM_EnvironmentType abi) {
+ if (abi == ZigLLVM_UnknownEnvironment)
+ return "none";
+ return ZigLLVMGetEnvironmentTypeName(abi);
}
void get_native_target(ZigTarget *target) {
ZigLLVM_OSType os_type;
+ ZigLLVM_ObjectFormatType oformat; // ignored; based on arch/os
ZigLLVMGetNativeTarget(
- &target->arch.arch,
- &target->arch.sub_arch,
+ &target->arch,
+ &target->sub_arch,
&target->vendor,
&os_type,
- &target->env_type,
- &target->oformat);
+ &target->abi,
+ &oformat);
target->os = get_zig_os_type(os_type);
+ target->is_native = true;
+ if (target->abi == ZigLLVM_UnknownEnvironment) {
+ target->abi = target_default_abi(target->arch, target->os);
+ }
}
-void get_unknown_target(ZigTarget *target) {
- target->arch.arch = ZigLLVM_UnknownArch;
- target->arch.sub_arch = ZigLLVM_NoSubArch;
- target->vendor = ZigLLVM_UnknownVendor;
- target->os = OsFreestanding;
- target->env_type = ZigLLVM_UnknownEnvironment;
- target->oformat = ZigLLVM_UnknownObjectFormat;
-}
-
-static void get_arch_name_raw(char *out_str, ZigLLVM_ArchType arch, ZigLLVM_SubArchType sub_arch) {
- const char *sub_str = (sub_arch == ZigLLVM_NoSubArch) ? "" : ZigLLVMGetSubArchTypeName(sub_arch);
- sprintf(out_str, "%s%s", ZigLLVMGetArchTypeName(arch), sub_str);
-}
-
-void get_arch_name(char *out_str, const ArchType *arch) {
- return get_arch_name_raw(out_str, arch->arch, arch->sub_arch);
-}
-
-int parse_target_arch(const char *str, ArchType *out_arch) {
- for (size_t i = 0; i < array_length(arch_list); i += 1) {
- const ArchType *arch = &arch_list[i];
- char arch_name[50];
- get_arch_name_raw(arch_name, arch->arch, arch->sub_arch);
- if (strcmp(arch_name, str) == 0) {
- *out_arch = *arch;
- return 0;
+Error target_parse_archsub(ZigLLVM_ArchType *out_arch, ZigLLVM_SubArchType *out_sub,
+ const char *archsub_ptr, size_t archsub_len)
+{
+ for (size_t arch_i = 0; arch_i < array_length(arch_list); arch_i += 1) {
+ ZigLLVM_ArchType arch = arch_list[arch_i];
+ SubArchList sub_arch_list = target_subarch_list(arch);
+ size_t subarch_count = target_subarch_count(sub_arch_list);
+ if (subarch_count == 0) {
+ if (mem_eql_str(archsub_ptr, archsub_len, target_arch_name(arch))) {
+ *out_arch = arch;
+ *out_sub = ZigLLVM_NoSubArch;
+ return ErrorNone;
+ }
+ continue;
+ }
+ for (size_t sub_i = 0; sub_i < subarch_count; sub_i += 1) {
+ ZigLLVM_SubArchType sub = target_subarch_enum(sub_arch_list, sub_i);
+ char arch_name[64];
+ int n = sprintf(arch_name, "%s%s", target_arch_name(arch), target_subarch_name(sub));
+ if (mem_eql_mem(arch_name, n, archsub_ptr, archsub_len)) {
+ *out_arch = arch;
+ *out_sub = sub;
+ return ErrorNone;
+ }
}
}
- return ErrorFileNotFound;
+ return ErrorUnknownArchitecture;
}
-int parse_target_os(const char *str, Os *out_os) {
+SubArchList target_subarch_list(ZigLLVM_ArchType arch) {
+ switch (arch) {
+ case ZigLLVM_UnknownArch:
+ zig_unreachable();
+ case ZigLLVM_arm:
+ case ZigLLVM_armeb:
+ case ZigLLVM_thumb:
+ case ZigLLVM_thumbeb:
+ return SubArchListArm32;
+
+ case ZigLLVM_aarch64:
+ case ZigLLVM_aarch64_be:
+ return SubArchListArm64;
+
+ case ZigLLVM_kalimba:
+ return SubArchListKalimba;
+
+ case ZigLLVM_arc:
+ case ZigLLVM_avr:
+ case ZigLLVM_bpfel:
+ case ZigLLVM_bpfeb:
+ case ZigLLVM_hexagon:
+ case ZigLLVM_mips:
+ case ZigLLVM_mipsel:
+ case ZigLLVM_mips64:
+ case ZigLLVM_mips64el:
+ case ZigLLVM_msp430:
+ case ZigLLVM_ppc:
+ case ZigLLVM_ppc64:
+ case ZigLLVM_ppc64le:
+ case ZigLLVM_r600:
+ case ZigLLVM_amdgcn:
+ case ZigLLVM_riscv32:
+ case ZigLLVM_riscv64:
+ case ZigLLVM_sparc:
+ case ZigLLVM_sparcv9:
+ case ZigLLVM_sparcel:
+ case ZigLLVM_systemz:
+ case ZigLLVM_tce:
+ case ZigLLVM_tcele:
+ case ZigLLVM_x86:
+ case ZigLLVM_x86_64:
+ case ZigLLVM_xcore:
+ case ZigLLVM_nvptx:
+ case ZigLLVM_nvptx64:
+ case ZigLLVM_le32:
+ case ZigLLVM_le64:
+ case ZigLLVM_amdil:
+ case ZigLLVM_amdil64:
+ case ZigLLVM_hsail:
+ case ZigLLVM_hsail64:
+ case ZigLLVM_spir:
+ case ZigLLVM_spir64:
+ case ZigLLVM_shave:
+ case ZigLLVM_lanai:
+ case ZigLLVM_wasm32:
+ case ZigLLVM_wasm64:
+ case ZigLLVM_renderscript32:
+ case ZigLLVM_renderscript64:
+ return SubArchListNone;
+ }
+ zig_unreachable();
+}
+
+size_t target_subarch_count(SubArchList sub_arch_list) {
+ switch (sub_arch_list) {
+ case SubArchListNone:
+ return 0;
+ case SubArchListArm32:
+ return array_length(subarch_list_arm32);
+ case SubArchListArm64:
+ return array_length(subarch_list_arm64);
+ case SubArchListKalimba:
+ return array_length(subarch_list_kalimba);
+ case SubArchListMips:
+ return array_length(subarch_list_mips);
+ }
+ zig_unreachable();
+}
+
+ZigLLVM_SubArchType target_subarch_enum(SubArchList sub_arch_list, size_t i) {
+ switch (sub_arch_list) {
+ case SubArchListNone:
+ zig_unreachable();
+ case SubArchListArm32:
+ assert(i < array_length(subarch_list_arm32));
+ return subarch_list_arm32[i];
+ case SubArchListArm64:
+ assert(i < array_length(subarch_list_arm64));
+ return subarch_list_arm64[i];
+ case SubArchListKalimba:
+ assert(i < array_length(subarch_list_kalimba));
+ return subarch_list_kalimba[i];
+ case SubArchListMips:
+ assert(i < array_length(subarch_list_mips));
+ return subarch_list_mips[i];
+ }
+ zig_unreachable();
+}
+
+const char *target_subarch_name(ZigLLVM_SubArchType subarch) {
+ return ZigLLVMGetSubArchTypeName(subarch);
+}
+
+size_t target_subarch_list_count(void) {
+ return array_length(subarch_list_list);
+}
+
+SubArchList target_subarch_list_enum(size_t index) {
+ assert(index < array_length(subarch_list_list));
+ return subarch_list_list[index];
+}
+
+const char *target_subarch_list_name(SubArchList sub_arch_list) {
+ switch (sub_arch_list) {
+ case SubArchListNone:
+ return "None";
+ case SubArchListArm32:
+ return "Arm32";
+ case SubArchListArm64:
+ return "Arm64";
+ case SubArchListKalimba:
+ return "Kalimba";
+ case SubArchListMips:
+ return "Mips";
+ }
+ zig_unreachable();
+}
+
+Error target_parse_os(Os *out_os, const char *os_ptr, size_t os_len) {
for (size_t i = 0; i < array_length(os_list); i += 1) {
Os os = os_list[i];
- const char *os_name = get_target_os_name(os);
- if (strcmp(os_name, str) == 0) {
+ const char *os_name = target_os_name(os);
+ if (mem_eql_str(os_ptr, os_len, os_name)) {
*out_os = os;
- return 0;
+ return ErrorNone;
}
}
- return ErrorFileNotFound;
+ return ErrorUnknownOperatingSystem;
}
-int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *out_environ) {
- for (size_t i = 0; i < array_length(environ_list); i += 1) {
- ZigLLVM_EnvironmentType env_type = environ_list[i];
- const char *environ_name = ZigLLVMGetEnvironmentTypeName(env_type);
- if (strcmp(environ_name, str) == 0) {
- *out_environ = env_type;
- return 0;
+Error target_parse_abi(ZigLLVM_EnvironmentType *out_abi, const char *abi_ptr, size_t abi_len) {
+ for (size_t i = 0; i < array_length(abi_list); i += 1) {
+ ZigLLVM_EnvironmentType abi = abi_list[i];
+ const char *abi_name = target_abi_name(abi);
+ if (mem_eql_str(abi_ptr, abi_len, abi_name)) {
+ *out_abi = abi;
+ return ErrorNone;
}
}
- return ErrorFileNotFound;
+ return ErrorUnknownABI;
+}
+
+Error target_parse_triple(ZigTarget *target, const char *triple) {
+ Error err;
+ SplitIterator it = memSplit(str(triple), str("-"));
+
+ Optional> opt_archsub = SplitIterator_next(&it);
+ Optional> opt_os = SplitIterator_next(&it);
+ Optional> opt_abi = SplitIterator_next(&it);
+
+ if (!opt_archsub.is_some)
+ return ErrorMissingArchitecture;
+
+ if (!opt_os.is_some)
+ return ErrorMissingOperatingSystem;
+
+ if ((err = target_parse_archsub(&target->arch, &target->sub_arch,
+ (char*)opt_archsub.value.ptr, opt_archsub.value.len)))
+ {
+ return err;
+ }
+
+ if ((err = target_parse_os(&target->os, (char*)opt_os.value.ptr, opt_os.value.len))) {
+ return err;
+ }
+
+ if (opt_abi.is_some) {
+ if ((err = target_parse_abi(&target->abi, (char*)opt_abi.value.ptr, opt_abi.value.len))) {
+ return err;
+ }
+ } else {
+ target->abi = target_default_abi(target->arch, target->os);
+ }
+
+ target->vendor = ZigLLVM_UnknownVendor;
+ target->is_native = false;
+ return ErrorNone;
+}
+
+const char *target_arch_name(ZigLLVM_ArchType arch) {
+ return ZigLLVMGetArchTypeName(arch);
}
void init_all_targets(void) {
@@ -543,121 +715,39 @@ void init_all_targets(void) {
}
void get_target_triple(Buf *triple, const ZigTarget *target) {
- char arch_name[50];
- get_arch_name(arch_name, &target->arch);
-
buf_resize(triple, 0);
-
- // LLVM WebAssembly output support requires the target to be activated at
- // build type with -DCMAKE_LLVM_EXPIERMENTAL_TARGETS_TO_BUILD=WebAssembly.
- //
- // LLVM determines the output format based on the environment suffix,
- // defaulting to an object based on the architecture. The default format in
- // LLVM 6 sets the wasm arch output incorrectly to ELF. We need to
- // explicitly set this ourself in order for it to work.
- //
- // This is fixed in LLVM 7 and you will be able to get wasm output by
- // using the target triple `wasm32-unknown-unknown-unknown`.
- if (!strncmp(arch_name, "wasm", 4)) {
- buf_appendf(triple, "%s-%s-%s-wasm", arch_name,
- ZigLLVMGetVendorTypeName(target->vendor),
- ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)));
- } else {
- buf_appendf(triple, "%s-%s-%s-%s", arch_name,
- ZigLLVMGetVendorTypeName(target->vendor),
- ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
- ZigLLVMGetEnvironmentTypeName(target->env_type));
- }
+ buf_appendf(triple, "%s%s-%s-%s-%s",
+ ZigLLVMGetArchTypeName(target->arch),
+ ZigLLVMGetSubArchTypeName(target->sub_arch),
+ ZigLLVMGetVendorTypeName(target->vendor),
+ ZigLLVMGetOSTypeName(get_llvm_os_type(target->os)),
+ ZigLLVMGetEnvironmentTypeName(target->abi));
}
-static bool is_os_darwin(ZigTarget *target) {
+bool target_is_darwin(const ZigTarget *target) {
switch (target->os) {
case OsMacOSX:
case OsIOS:
+ case OsWatchOS:
+ case OsTvOS:
return true;
default:
return false;
}
}
-void resolve_target_object_format(ZigTarget *target) {
- if (target->oformat != ZigLLVM_UnknownObjectFormat) {
- return;
+ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target) {
+ if (target->os == OsUefi || target->os == OsWindows) {
+ return ZigLLVM_COFF;
+ } else if (target_is_darwin(target)) {
+ return ZigLLVM_MachO;
}
-
- switch (target->arch.arch) {
- case ZigLLVM_UnknownArch:
- case ZigLLVM_aarch64:
- case ZigLLVM_arm:
- case ZigLLVM_thumb:
- case ZigLLVM_x86:
- case ZigLLVM_x86_64:
- if (is_os_darwin(target)) {
- target->oformat = ZigLLVM_MachO;
- } else if (target->os == OsWindows) {
- target->oformat = ZigLLVM_COFF;
- } else {
- target->oformat = ZigLLVM_ELF;
- }
- return;
-
- case ZigLLVM_aarch64_be:
- case ZigLLVM_amdgcn:
- case ZigLLVM_amdil:
- case ZigLLVM_amdil64:
- case ZigLLVM_armeb:
- case ZigLLVM_arc:
- case ZigLLVM_avr:
- case ZigLLVM_bpfeb:
- case ZigLLVM_bpfel:
- case ZigLLVM_hexagon:
- case ZigLLVM_lanai:
- case ZigLLVM_hsail:
- case ZigLLVM_hsail64:
- case ZigLLVM_kalimba:
- case ZigLLVM_le32:
- case ZigLLVM_le64:
- case ZigLLVM_mips:
- case ZigLLVM_mips64:
- case ZigLLVM_mips64el:
- case ZigLLVM_mipsel:
- case ZigLLVM_msp430:
- case ZigLLVM_nvptx:
- case ZigLLVM_nvptx64:
- case ZigLLVM_ppc64le:
- case ZigLLVM_r600:
- case ZigLLVM_renderscript32:
- case ZigLLVM_renderscript64:
- case ZigLLVM_riscv32:
- case ZigLLVM_riscv64:
- case ZigLLVM_shave:
- case ZigLLVM_sparc:
- case ZigLLVM_sparcel:
- case ZigLLVM_sparcv9:
- case ZigLLVM_spir:
- case ZigLLVM_spir64:
- case ZigLLVM_systemz:
- case ZigLLVM_tce:
- case ZigLLVM_tcele:
- case ZigLLVM_thumbeb:
- case ZigLLVM_xcore:
- target->oformat= ZigLLVM_ELF;
- return;
-
- case ZigLLVM_wasm32:
- case ZigLLVM_wasm64:
- target->oformat = ZigLLVM_Wasm;
- return;
-
- case ZigLLVM_ppc:
- case ZigLLVM_ppc64:
- if (is_os_darwin(target)) {
- target->oformat = ZigLLVM_MachO;
- } else {
- target->oformat= ZigLLVM_ELF;
- }
- return;
+ if (target->arch == ZigLLVM_wasm32 ||
+ target->arch == ZigLLVM_wasm64)
+ {
+ return ZigLLVM_Wasm;
}
+ return ZigLLVM_ELF;
}
// See lib/Support/Triple.cpp in LLVM for the source of this data.
@@ -728,7 +818,7 @@ static int get_arch_pointer_bit_width(ZigLLVM_ArchType arch) {
uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
switch (target->os) {
case OsFreestanding:
- switch (target->arch.arch) {
+ switch (target->arch) {
case ZigLLVM_msp430:
switch (id) {
case CIntTypeShort:
@@ -756,7 +846,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
return 32;
case CIntTypeLong:
case CIntTypeULong:
- return get_arch_pointer_bit_width(target->arch.arch);
+ return get_arch_pointer_bit_width(target->arch);
case CIntTypeLongLong:
case CIntTypeULongLong:
return 64;
@@ -768,6 +858,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case OsMacOSX:
case OsZen:
case OsFreeBSD:
+ case OsNetBSD:
case OsOpenBSD:
switch (id) {
case CIntTypeShort:
@@ -778,7 +869,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
return 32;
case CIntTypeLong:
case CIntTypeULong:
- return get_arch_pointer_bit_width(target->arch.arch);
+ return get_arch_pointer_bit_width(target->arch);
case CIntTypeLongLong:
case CIntTypeULongLong:
return 64;
@@ -808,7 +899,6 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
case OsIOS:
case OsKFreeBSD:
case OsLv2:
- case OsNetBSD:
case OsSolaris:
case OsHaiku:
case OsMinix:
@@ -835,23 +925,27 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) {
zig_unreachable();
}
-const char *target_o_file_ext(ZigTarget *target) {
- if (target->env_type == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
+bool target_allows_addr_zero(const ZigTarget *target) {
+ return target->os == OsFreestanding;
+}
+
+const char *target_o_file_ext(const ZigTarget *target) {
+ if (target->abi == ZigLLVM_MSVC || target->os == OsWindows || target->os == OsUefi) {
return ".obj";
} else {
return ".o";
}
}
-const char *target_asm_file_ext(ZigTarget *target) {
+const char *target_asm_file_ext(const ZigTarget *target) {
return ".s";
}
-const char *target_llvm_ir_file_ext(ZigTarget *target) {
+const char *target_llvm_ir_file_ext(const ZigTarget *target) {
return ".ll";
}
-const char *target_exe_file_ext(ZigTarget *target) {
+const char *target_exe_file_ext(const ZigTarget *target) {
if (target->os == OsWindows) {
return ".exe";
} else if (target->os == OsUefi) {
@@ -861,7 +955,9 @@ const char *target_exe_file_ext(ZigTarget *target) {
}
}
-const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch) {
+const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
+ size_t version_major, size_t version_minor, size_t version_patch)
+{
if (target->os == OsWindows || target->os == OsUefi) {
if (is_static) {
return ".lib";
@@ -872,7 +968,7 @@ const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t versio
if (is_static) {
return ".a";
} else {
- return buf_ptr(buf_sprintf(".so.%zu", version_major));
+ return buf_ptr(buf_sprintf(".so.%" ZIG_PRI_usize, version_major));
}
}
}
@@ -883,8 +979,8 @@ enum FloatAbi {
FloatAbiSoftFp,
};
-static FloatAbi get_float_abi(ZigTarget *target) {
- const ZigLLVM_EnvironmentType env = target->env_type;
+static FloatAbi get_float_abi(const ZigTarget *target) {
+ const ZigLLVM_EnvironmentType env = target->abi;
if (env == ZigLLVM_GNUEABIHF ||
env == ZigLLVM_EABIHF ||
env == ZigLLVM_MuslEABIHF)
@@ -899,64 +995,153 @@ static bool is_64_bit(ZigLLVM_ArchType arch) {
return get_arch_pointer_bit_width(arch) == 64;
}
-Buf *target_dynamic_linker(ZigTarget *target) {
- const ZigLLVM_ArchType arch = target->arch.arch;
- const ZigLLVM_EnvironmentType env = target->env_type;
+const char *target_dynamic_linker(const ZigTarget *target) {
+ switch (target->os) {
+ case OsFreeBSD:
+ return "/libexec/ld-elf.so.1";
+ case OsNetBSD:
+ return "/libexec/ld.elf_so";
+ case OsLinux: {
+ const ZigLLVM_EnvironmentType abi = target->abi;
+ if (abi == ZigLLVM_Android) {
+ if (is_64_bit(target->arch)) {
+ return "/system/bin/linker64";
+ } else {
+ return "/system/bin/linker";
+ }
+ }
- if (env == ZigLLVM_Android) {
- if (is_64_bit(arch)) {
- return buf_create_from_str("/system/bin/linker64");
- } else {
- return buf_create_from_str("/system/bin/linker");
+ switch (target->arch) {
+ case ZigLLVM_UnknownArch:
+ zig_unreachable();
+ case ZigLLVM_x86:
+ case ZigLLVM_sparc:
+ case ZigLLVM_sparcel:
+ return "/lib/ld-linux.so.2";
+
+ case ZigLLVM_aarch64:
+ return "/lib/ld-linux-aarch64.so.1";
+
+ case ZigLLVM_aarch64_be:
+ return "/lib/ld-linux-aarch64_be.so.1";
+
+ case ZigLLVM_arm:
+ case ZigLLVM_thumb:
+ if (get_float_abi(target) == FloatAbiHard) {
+ return "/lib/ld-linux-armhf.so.3";
+ } else {
+ return "/lib/ld-linux.so.3";
+ }
+
+ case ZigLLVM_armeb:
+ case ZigLLVM_thumbeb:
+ if (get_float_abi(target) == FloatAbiHard) {
+ return "/lib/ld-linux-armhf.so.3";
+ } else {
+ return "/lib/ld-linux.so.3";
+ }
+
+ case ZigLLVM_mips:
+ case ZigLLVM_mipsel:
+ case ZigLLVM_mips64:
+ case ZigLLVM_mips64el:
+ zig_panic("TODO implement target_dynamic_linker for mips");
+
+ case ZigLLVM_ppc:
+ return "/lib/ld.so.1";
+
+ case ZigLLVM_ppc64:
+ return "/lib64/ld64.so.2";
+
+ case ZigLLVM_ppc64le:
+ return "/lib64/ld64.so.2";
+
+ case ZigLLVM_systemz:
+ return "/lib64/ld64.so.1";
+
+ case ZigLLVM_sparcv9:
+ return "/lib64/ld-linux.so.2";
+
+ case ZigLLVM_x86_64:
+ if (abi == ZigLLVM_GNUX32) {
+ return "/libx32/ld-linux-x32.so.2";
+ }
+ if (abi == ZigLLVM_Musl || abi == ZigLLVM_MuslEABI || abi == ZigLLVM_MuslEABIHF) {
+ return "/lib/ld-musl-x86_64.so.1";
+ }
+ return "/lib64/ld-linux-x86-64.so.2";
+
+ case ZigLLVM_wasm32:
+ case ZigLLVM_wasm64:
+ return nullptr;
+
+ case ZigLLVM_arc:
+ case ZigLLVM_avr:
+ case ZigLLVM_bpfel:
+ case ZigLLVM_bpfeb:
+ case ZigLLVM_hexagon:
+ case ZigLLVM_msp430:
+ case ZigLLVM_r600:
+ case ZigLLVM_amdgcn:
+ case ZigLLVM_riscv32:
+ case ZigLLVM_riscv64:
+ case ZigLLVM_tce:
+ case ZigLLVM_tcele:
+ case ZigLLVM_xcore:
+ case ZigLLVM_nvptx:
+ case ZigLLVM_nvptx64:
+ case ZigLLVM_le32:
+ case ZigLLVM_le64:
+ case ZigLLVM_amdil:
+ case ZigLLVM_amdil64:
+ case ZigLLVM_hsail:
+ case ZigLLVM_hsail64:
+ case ZigLLVM_spir:
+ case ZigLLVM_spir64:
+ case ZigLLVM_kalimba:
+ case ZigLLVM_shave:
+ case ZigLLVM_lanai:
+ case ZigLLVM_renderscript32:
+ case ZigLLVM_renderscript64:
+ zig_panic("TODO implement target_dynamic_linker for this arch");
+ }
+ zig_unreachable();
}
- } else if (arch == ZigLLVM_x86 ||
- arch == ZigLLVM_sparc ||
- arch == ZigLLVM_sparcel)
- {
- return buf_create_from_str("/lib/ld-linux.so.2");
- } else if (arch == ZigLLVM_aarch64) {
- return buf_create_from_str("/lib/ld-linux-aarch64.so.1");
- } else if (arch == ZigLLVM_aarch64_be) {
- return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1");
- } else if (arch == ZigLLVM_arm || arch == ZigLLVM_thumb) {
- if (get_float_abi(target) == FloatAbiHard) {
- return buf_create_from_str("/lib/ld-linux-armhf.so.3");
- } else {
- return buf_create_from_str("/lib/ld-linux.so.3");
- }
- } else if (arch == ZigLLVM_armeb || arch == ZigLLVM_thumbeb) {
- if (get_float_abi(target) == FloatAbiHard) {
- return buf_create_from_str("/lib/ld-linux-armhf.so.3");
- } else {
- return buf_create_from_str("/lib/ld-linux.so.3");
- }
- } else if (arch == ZigLLVM_mips || arch == ZigLLVM_mipsel ||
- arch == ZigLLVM_mips64 || arch == ZigLLVM_mips64el)
- {
- // when you want to solve this TODO, grep clang codebase for
- // getLinuxDynamicLinker
- zig_panic("TODO figure out MIPS dynamic linker name");
- } else if (arch == ZigLLVM_ppc) {
- return buf_create_from_str("/lib/ld.so.1");
- } else if (arch == ZigLLVM_ppc64) {
- return buf_create_from_str("/lib64/ld64.so.2");
- } else if (arch == ZigLLVM_ppc64le) {
- return buf_create_from_str("/lib64/ld64.so.2");
- } else if (arch == ZigLLVM_systemz) {
- return buf_create_from_str("/lib64/ld64.so.1");
- } else if (arch == ZigLLVM_sparcv9) {
- return buf_create_from_str("/lib64/ld-linux.so.2");
- } else if (arch == ZigLLVM_x86_64 &&
- env == ZigLLVM_GNUX32)
- {
- return buf_create_from_str("/libx32/ld-linux-x32.so.2");
- } else if (arch == ZigLLVM_x86_64 &&
- (env == ZigLLVM_Musl || env == ZigLLVM_MuslEABI || env == ZigLLVM_MuslEABIHF))
- {
- return buf_create_from_str("/lib/ld-musl-x86_64.so.1");
- } else {
- return buf_create_from_str("/lib64/ld-linux-x86-64.so.2");
+ case OsFreestanding:
+ case OsIOS:
+ case OsTvOS:
+ case OsWatchOS:
+ case OsMacOSX:
+ return nullptr;
+
+ case OsAnanas:
+ case OsCloudABI:
+ case OsDragonFly:
+ case OsFuchsia:
+ case OsKFreeBSD:
+ case OsLv2:
+ case OsOpenBSD:
+ case OsSolaris:
+ case OsWindows:
+ case OsHaiku:
+ case OsMinix:
+ case OsRTEMS:
+ case OsNaCl:
+ case OsCNK:
+ case OsAIX:
+ case OsCUDA:
+ case OsNVCL:
+ case OsAMDHSA:
+ case OsPS4:
+ case OsELFIAMCU:
+ case OsMesa3D:
+ case OsContiki:
+ case OsAMDPAL:
+ case OsZen:
+ case OsUefi:
+ zig_panic("TODO implement target_dynamic_linker for this OS");
}
+ zig_unreachable();
}
bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target) {
@@ -967,15 +1152,15 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
return true;
}
- if (guest_target->os == host_target->os && guest_target->arch.arch == host_target->arch.arch &&
- guest_target->arch.sub_arch == host_target->arch.sub_arch)
+ if (guest_target->os == host_target->os && guest_target->arch == host_target->arch &&
+ guest_target->sub_arch == host_target->sub_arch)
{
// OS, arch, and sub-arch match
return true;
}
if (guest_target->os == OsWindows && host_target->os == OsWindows &&
- host_target->arch.arch == ZigLLVM_x86_64 && guest_target->arch.arch == ZigLLVM_x86)
+ host_target->arch == ZigLLVM_x86_64 && guest_target->arch == ZigLLVM_x86)
{
// 64-bit windows can run 32-bit programs
return true;
@@ -984,8 +1169,8 @@ bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target
return false;
}
-const char *arch_stack_pointer_register_name(const ArchType *arch) {
- switch (arch->arch) {
+const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) {
+ switch (arch) {
case ZigLLVM_UnknownArch:
zig_unreachable();
case ZigLLVM_x86:
@@ -1047,7 +1232,7 @@ const char *arch_stack_pointer_register_name(const ArchType *arch) {
}
bool target_is_arm(const ZigTarget *target) {
- switch (target->arch.arch) {
+ switch (target->arch) {
case ZigLLVM_UnknownArch:
zig_unreachable();
case ZigLLVM_aarch64:
@@ -1105,3 +1290,73 @@ bool target_is_arm(const ZigTarget *target) {
}
zig_unreachable();
}
+
+// Valgrind supports more, but Zig does not support them yet.
+bool target_has_valgrind_support(const ZigTarget *target) {
+ switch (target->arch) {
+ case ZigLLVM_UnknownArch:
+ zig_unreachable();
+ case ZigLLVM_x86_64:
+ return (target->os == OsLinux || target_is_darwin(target) || target->os == OsSolaris ||
+ (target->os == OsWindows && target->abi != ZigLLVM_MSVC));
+ default:
+ return false;
+ }
+ zig_unreachable();
+}
+
+bool target_requires_libc(const ZigTarget *target) {
+ // On Darwin, we always link libSystem which contains libc.
+ // Similarly on FreeBSD and NetBSD we always link system libc
+ // since this is the stable syscall interface.
+ return (target_is_darwin(target) || target->os == OsFreeBSD || target->os == OsNetBSD);
+}
+
+bool target_supports_fpic(const ZigTarget *target) {
+ // This is not whether the target supports Position Independent Code, but whether the -fPIC
+ // C compiler argument is valid.
+ return target->os != OsWindows;
+}
+
+ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) {
+ switch (os) {
+ case OsFreestanding:
+ case OsAnanas:
+ case OsCloudABI:
+ case OsDragonFly:
+ case OsLv2:
+ case OsSolaris:
+ case OsHaiku:
+ case OsMinix:
+ case OsRTEMS:
+ case OsNaCl:
+ case OsCNK:
+ case OsAIX:
+ case OsCUDA:
+ case OsNVCL:
+ case OsAMDHSA:
+ case OsPS4:
+ case OsELFIAMCU:
+ case OsMesa3D:
+ case OsContiki:
+ case OsAMDPAL:
+ case OsZen:
+ return ZigLLVM_EABI;
+ case OsOpenBSD:
+ case OsMacOSX:
+ case OsFreeBSD:
+ case OsIOS:
+ case OsTvOS:
+ case OsWatchOS:
+ case OsFuchsia:
+ case OsKFreeBSD:
+ case OsNetBSD:
+ return ZigLLVM_GNU;
+ case OsWindows:
+ case OsUefi:
+ return ZigLLVM_MSVC;
+ case OsLinux:
+ return ZigLLVM_Musl;
+ }
+ zig_unreachable();
+}
diff --git a/src/target.hpp b/src/target.hpp
index ec4547b7f6..8166f7f952 100644
--- a/src/target.hpp
+++ b/src/target.hpp
@@ -12,11 +12,6 @@
struct Buf;
-struct ArchType {
- ZigLLVM_ArchType arch;
- ZigLLVM_SubArchType sub_arch;
-};
-
// Synchronize with target.cpp::os_list
enum Os {
OsFreestanding,
@@ -57,6 +52,15 @@ enum Os {
OsUefi,
};
+// Synchronize with target.cpp::subarch_list_list
+enum SubArchList {
+ SubArchListNone,
+ SubArchListArm32,
+ SubArchListArm64,
+ SubArchListKalimba,
+ SubArchListMips,
+};
+
enum TargetSubsystem {
TargetSubsystemAuto, // Zig should infer the subsystem
TargetSubsystemConsole,
@@ -70,11 +74,12 @@ enum TargetSubsystem {
};
struct ZigTarget {
- ArchType arch;
+ ZigLLVM_ArchType arch;
+ ZigLLVM_SubArchType sub_arch;
ZigLLVM_VendorType vendor;
Os os;
- ZigLLVM_EnvironmentType env_type;
- ZigLLVM_ObjectFormatType oformat;
+ ZigLLVM_EnvironmentType abi;
+ bool is_native;
};
enum CIntType {
@@ -90,53 +95,71 @@ enum CIntType {
CIntTypeCount,
};
-size_t target_arch_count(void);
-const ArchType *get_target_arch(size_t index);
-void get_arch_name(char *out_str, const ArchType *arch);
+Error target_parse_triple(ZigTarget *target, const char *triple);
+Error target_parse_archsub(ZigLLVM_ArchType *arch, ZigLLVM_SubArchType *sub,
+ const char *archsub_ptr, size_t archsub_len);
+Error target_parse_os(Os *os, const char *os_ptr, size_t os_len);
+Error target_parse_abi(ZigLLVM_EnvironmentType *abi, const char *abi_ptr, size_t abi_len);
-const char *arch_stack_pointer_register_name(const ArchType *arch);
+size_t target_arch_count(void);
+ZigLLVM_ArchType target_arch_enum(size_t index);
+const char *target_arch_name(ZigLLVM_ArchType arch);
+
+SubArchList target_subarch_list(ZigLLVM_ArchType arch);
+size_t target_subarch_count(SubArchList sub_arch_list);
+ZigLLVM_SubArchType target_subarch_enum(SubArchList subarch_list, size_t index);
+const char *target_subarch_name(ZigLLVM_SubArchType subarch);
+
+size_t target_subarch_list_count(void);
+SubArchList target_subarch_list_enum(size_t index);
+const char *target_subarch_list_name(SubArchList sub_arch_list);
+
+const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch);
size_t target_vendor_count(void);
-ZigLLVM_VendorType get_target_vendor(size_t index);
+ZigLLVM_VendorType target_vendor_enum(size_t index);
size_t target_os_count(void);
-Os get_target_os(size_t index);
-const char *get_target_os_name(Os os_type);
+Os target_os_enum(size_t index);
+const char *target_os_name(Os os_type);
-size_t target_environ_count(void);
-ZigLLVM_EnvironmentType get_target_environ(size_t index);
+size_t target_abi_count(void);
+ZigLLVM_EnvironmentType target_abi_enum(size_t index);
+const char *target_abi_name(ZigLLVM_EnvironmentType abi);
+ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os);
size_t target_oformat_count(void);
-const ZigLLVM_ObjectFormatType get_target_oformat(size_t index);
-const char *get_target_oformat_name(ZigLLVM_ObjectFormatType oformat);
+ZigLLVM_ObjectFormatType target_oformat_enum(size_t index);
+const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat);
+ZigLLVM_ObjectFormatType target_object_format(const ZigTarget *target);
void get_native_target(ZigTarget *target);
-void get_unknown_target(ZigTarget *target);
-
-int parse_target_arch(const char *str, ArchType *arch);
-int parse_target_os(const char *str, Os *os);
-int parse_target_environ(const char *str, ZigLLVM_EnvironmentType *env_type);
+void get_target_triple(Buf *triple, const ZigTarget *target);
void init_all_targets(void);
-void get_target_triple(Buf *triple, const ZigTarget *target);
-
void resolve_target_object_format(ZigTarget *target);
uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id);
-const char *target_o_file_ext(ZigTarget *target);
-const char *target_asm_file_ext(ZigTarget *target);
-const char *target_llvm_ir_file_ext(ZigTarget *target);
-const char *target_exe_file_ext(ZigTarget *target);
-const char *target_lib_file_ext(ZigTarget *target, bool is_static, size_t version_major, size_t version_minor, size_t version_patch);
+const char *target_o_file_ext(const ZigTarget *target);
+const char *target_asm_file_ext(const ZigTarget *target);
+const char *target_llvm_ir_file_ext(const ZigTarget *target);
+const char *target_exe_file_ext(const ZigTarget *target);
+const char *target_lib_file_ext(const ZigTarget *target, bool is_static,
+ size_t version_major, size_t version_minor, size_t version_patch);
-Buf *target_dynamic_linker(ZigTarget *target);
+const char *target_dynamic_linker(const ZigTarget *target);
bool target_can_exec(const ZigTarget *host_target, const ZigTarget *guest_target);
ZigLLVM_OSType get_llvm_os_type(Os os_type);
bool target_is_arm(const ZigTarget *target);
+bool target_allows_addr_zero(const ZigTarget *target);
+bool target_has_valgrind_support(const ZigTarget *target);
+bool target_is_darwin(const ZigTarget *target);
+bool target_requires_libc(const ZigTarget *target);
+bool target_supports_fpic(const ZigTarget *target);
#endif
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp
index 3acd605748..9ff6ed3bbe 100644
--- a/src/tokenizer.cpp
+++ b/src/tokenizer.cpp
@@ -221,6 +221,7 @@ enum TokenizeState {
TokenizeStateError,
TokenizeStateLBracket,
TokenizeStateLBracketStar,
+ TokenizeStateLBracketStarC,
};
@@ -846,7 +847,6 @@ void tokenize(Buf *buf, Tokenization *out) {
switch (c) {
case '*':
t.state = TokenizeStateLBracketStar;
- set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
break;
default:
// reinterpret as just an lbracket
@@ -857,6 +857,21 @@ void tokenize(Buf *buf, Tokenization *out) {
}
break;
case TokenizeStateLBracketStar:
+ switch (c) {
+ case 'c':
+ t.state = TokenizeStateLBracketStarC;
+ set_token_id(&t, t.cur_tok, TokenIdBracketStarCBracket);
+ break;
+ case ']':
+ set_token_id(&t, t.cur_tok, TokenIdBracketStarBracket);
+ end_token(&t);
+ t.state = TokenizeStateStart;
+ break;
+ default:
+ invalid_char_error(&t, c);
+ }
+ break;
+ case TokenizeStateLBracketStarC:
switch (c) {
case ']':
end_token(&t);
@@ -1491,6 +1506,7 @@ void tokenize(Buf *buf, Tokenization *out) {
case TokenizeStateLineStringContinue:
case TokenizeStateLineStringContinueC:
case TokenizeStateLBracketStar:
+ case TokenizeStateLBracketStarC:
tokenize_error(&t, "unexpected EOF");
break;
case TokenizeStateLineComment:
@@ -1528,6 +1544,7 @@ const char * token_name(TokenId id) {
case TokenIdBitShiftRightEq: return ">>=";
case TokenIdBitXorEq: return "^=";
case TokenIdBracketStarBracket: return "[*]";
+ case TokenIdBracketStarCBracket: return "[*c]";
case TokenIdCharLiteral: return "CharLiteral";
case TokenIdCmpEq: return "==";
case TokenIdCmpGreaterOrEq: return ">=";
diff --git a/src/tokenizer.hpp b/src/tokenizer.hpp
index 17f36699b3..62117b5779 100644
--- a/src/tokenizer.hpp
+++ b/src/tokenizer.hpp
@@ -29,6 +29,7 @@ enum TokenId {
TokenIdBitShiftRightEq,
TokenIdBitXorEq,
TokenIdBracketStarBracket,
+ TokenIdBracketStarCBracket,
TokenIdCharLiteral,
TokenIdCmpEq,
TokenIdCmpGreaterOrEq,
diff --git a/src/translate_c.cpp b/src/translate_c.cpp
index 69a88f1204..84f8f2c681 100644
--- a/src/translate_c.cpp
+++ b/src/translate_c.cpp
@@ -4,7 +4,6 @@
* This file is part of zig, which is MIT licensed.
* See http://opensource.org/licenses/MIT
*/
-
#include "all_types.hpp"
#include "analyze.hpp"
#include "c_tokenizer.hpp"
@@ -13,7 +12,7 @@
#include "os.hpp"
#include "translate_c.hpp"
#include "parser.hpp"
-
+#include "zig_clang.h"
#if __GNUC__ >= 8
#pragma GCC diagnostic push
@@ -30,8 +29,6 @@
#include
-using namespace clang;
-
struct Alias {
Buf *new_name;
Buf *canon_name;
@@ -87,13 +84,13 @@ struct Context {
HashMap decl_table;
HashMap macro_table;
HashMap global_table;
- SourceManager *source_manager;
+ ZigClangSourceManager *source_manager;
ZigList aliases;
AstNode *source_node;
bool warnings_on;
CodeGen *codegen;
- ASTContext *ctx;
+ ZigClangASTContext *ctx;
TransScopeRoot *global_scope;
HashMap ptr_params;
@@ -117,22 +114,38 @@ static TransScopeSwitch *trans_scope_switch_create(Context *c, TransScope *paren
static TransScopeBlock *trans_scope_block_find(TransScope *scope);
-static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl);
-static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl);
-static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl);
+static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl);
+static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl);
+static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl);
-static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
+static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
ResultUsed result_used, TransLRValue lrval,
AstNode **out_node, TransScope **out_child_scope,
TransScope **out_node_scope);
-static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node);
-static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
-static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
-static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval);
-static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc);
+static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node);
+static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
+static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc);
+static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval);
+static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc);
+
+static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
+ ZigClangSourceLocation dest;
+ memcpy(&dest, static_cast(&src), sizeof(ZigClangSourceLocation));
+ return dest;
+}
+static ZigClangQualType bitcast(clang::QualType src) {
+ ZigClangQualType dest;
+ memcpy(&dest, static_cast(&src), sizeof(ZigClangQualType));
+ return dest;
+}
+static clang::QualType bitcast(ZigClangQualType src) {
+ clang::QualType dest;
+ memcpy(&dest, static_cast(&src), sizeof(ZigClangQualType));
+ return dest;
+}
ATTRIBUTE_PRINTF(3, 4)
-static void emit_warning(Context *c, const SourceLocation &sl, const char *format, ...) {
+static void emit_warning(Context *c, const clang::SourceLocation &clang_sl, const char *format, ...) {
if (!c->warnings_on) {
return;
}
@@ -142,16 +155,17 @@ static void emit_warning(Context *c, const SourceLocation &sl, const char *forma
Buf *msg = buf_vprintf(format, ap);
va_end(ap);
- StringRef filename = c->source_manager->getFilename(c->source_manager->getSpellingLoc(sl));
- const char *filename_bytes = (const char *)filename.bytes_begin();
+ ZigClangSourceLocation sl = bitcast(clang_sl);
+ const char *filename_bytes = ZigClangSourceManager_getFilename(c->source_manager,
+ ZigClangSourceManager_getSpellingLoc(c->source_manager, sl));
Buf *path;
if (filename_bytes) {
path = buf_create_from_str(filename_bytes);
} else {
path = buf_sprintf("(no file)");
}
- unsigned line = c->source_manager->getSpellingLineNumber(sl);
- unsigned column = c->source_manager->getSpellingColumnNumber(sl);
+ unsigned line = ZigClangSourceManager_getSpellingLineNumber(c->source_manager, sl);
+ unsigned column = ZigClangSourceManager_getSpellingColumnNumber(c->source_manager, sl);
fprintf(stderr, "%s:%u:%u: warning: %s\n", buf_ptr(path), line, column, buf_ptr(msg));
}
@@ -292,11 +306,22 @@ static AstNode *maybe_suppress_result(Context *c, ResultUsed result_used, AstNod
node);
}
+static TokenId ptr_len_to_token_id(PtrLen ptr_len) {
+ switch (ptr_len) {
+ case PtrLenSingle:
+ return TokenIdStar;
+ case PtrLenUnknown:
+ return TokenIdBracketStarBracket;
+ case PtrLenC:
+ return TokenIdBracketStarCBracket;
+ }
+ zig_unreachable();
+}
+
static AstNode *trans_create_node_ptr_type(Context *c, bool is_const, bool is_volatile, AstNode *child_node, PtrLen ptr_len) {
AstNode *node = trans_create_node(c, NodeTypePointerType);
node->data.pointer_type.star_token = allocate(1);
- node->data.pointer_type.star_token->id = (ptr_len == PtrLenSingle) ? TokenIdStar: TokenIdBracketStarBracket;
- node->data.pointer_type.is_const = is_const;
+ node->data.pointer_type.star_token->id = ptr_len_to_token_id(ptr_len);
node->data.pointer_type.is_const = is_const;
node->data.pointer_type.is_volatile = is_volatile;
node->data.pointer_type.op_expr = child_node;
@@ -461,15 +486,15 @@ static Buf *string_ref_to_buf(StringRef string_ref) {
return buf_create_from_mem((const char *)string_ref.bytes_begin(), string_ref.size());
}
-static const char *decl_name(const Decl *decl) {
- const NamedDecl *named_decl = static_cast(decl);
+static const char *decl_name(const clang::Decl *decl) {
+ const clang::NamedDecl *named_decl = static_cast(decl);
return (const char *)named_decl->getName().bytes_begin();
}
static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int) {
AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
node->data.int_literal.bigint = allocate(1);
- bool is_negative = aps_int.isNegative();
+ bool is_negative = aps_int.isSigned() && aps_int.isNegative();
if (!is_negative) {
bigint_init_data(node->data.int_literal.bigint, aps_int.getRawData(), aps_int.getNumWords(), false);
return node;
@@ -480,41 +505,41 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
}
-static const Type *qual_type_canon(QualType qt) {
+static const clang::Type *qual_type_canon(clang::QualType qt) {
return qt.getCanonicalType().getTypePtr();
}
-static QualType get_expr_qual_type(Context *c, const Expr *expr) {
+static clang::QualType get_expr_qual_type(Context *c, const clang::Expr *expr) {
// String literals in C are `char *` but they should really be `const char *`.
- if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
- const ImplicitCastExpr *cast_expr = static_cast(expr);
- if (cast_expr->getCastKind() == CK_ArrayToPointerDecay) {
- const Expr *sub_expr = cast_expr->getSubExpr();
- if (sub_expr->getStmtClass() == Stmt::StringLiteralClass) {
- QualType array_qt = sub_expr->getType();
- const ArrayType *array_type = static_cast(array_qt.getTypePtr());
- QualType pointee_qt = array_type->getElementType();
+ if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
+ const clang::ImplicitCastExpr *cast_expr = static_cast(expr);
+ if (cast_expr->getCastKind() == clang::CK_ArrayToPointerDecay) {
+ const clang::Expr *sub_expr = cast_expr->getSubExpr();
+ if (sub_expr->getStmtClass() == clang::Stmt::StringLiteralClass) {
+ clang::QualType array_qt = sub_expr->getType();
+ const clang::ArrayType *array_type = static_cast(array_qt.getTypePtr());
+ clang::QualType pointee_qt = array_type->getElementType();
pointee_qt.addConst();
- return c->ctx->getPointerType(pointee_qt);
+ return bitcast(ZigClangASTContext_getPointerType(c->ctx, bitcast(pointee_qt)));
}
}
}
return expr->getType();
}
-static QualType get_expr_qual_type_before_implicit_cast(Context *c, const Expr *expr) {
- if (expr->getStmtClass() == Stmt::ImplicitCastExprClass) {
- const ImplicitCastExpr *cast_expr = static_cast(expr);
+static clang::QualType get_expr_qual_type_before_implicit_cast(Context *c, const clang::Expr *expr) {
+ if (expr->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
+ const clang::ImplicitCastExpr *cast_expr = static_cast(expr);
return get_expr_qual_type(c, cast_expr->getSubExpr());
}
return expr->getType();
}
-static AstNode *get_expr_type(Context *c, const Expr *expr) {
+static AstNode *get_expr_type(Context *c, const clang::Expr *expr) {
return trans_qual_type(c, get_expr_qual_type(c, expr), expr->getBeginLoc());
}
-static bool qual_types_equal(QualType t1, QualType t2) {
+static bool qual_types_equal(clang::QualType t1, clang::QualType t2) {
if (t1.isConstQualified() != t2.isConstQualified()) {
return false;
}
@@ -531,37 +556,37 @@ static bool is_c_void_type(AstNode *node) {
return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
}
-static bool expr_types_equal(Context *c, const Expr *expr1, const Expr *expr2) {
- QualType t1 = get_expr_qual_type(c, expr1);
- QualType t2 = get_expr_qual_type(c, expr2);
+static bool expr_types_equal(Context *c, const clang::Expr *expr1, const clang::Expr *expr2) {
+ clang::QualType t1 = get_expr_qual_type(c, expr1);
+ clang::QualType t2 = get_expr_qual_type(c, expr2);
return qual_types_equal(t1, t2);
}
-static bool qual_type_is_ptr(QualType qt) {
- const Type *ty = qual_type_canon(qt);
- return ty->getTypeClass() == Type::Pointer;
+static bool qual_type_is_ptr(clang::QualType qt) {
+ const clang::Type *ty = qual_type_canon(qt);
+ return ty->getTypeClass() == clang::Type::Pointer;
}
-static const FunctionProtoType *qual_type_get_fn_proto(QualType qt, bool *is_ptr) {
- const Type *ty = qual_type_canon(qt);
+static const clang::FunctionProtoType *qual_type_get_fn_proto(clang::QualType qt, bool *is_ptr) {
+ const clang::Type *ty = qual_type_canon(qt);
*is_ptr = false;
- if (ty->getTypeClass() == Type::Pointer) {
+ if (ty->getTypeClass() == clang::Type::Pointer) {
*is_ptr = true;
- const PointerType *pointer_ty = static_cast(ty);
- QualType child_qt = pointer_ty->getPointeeType();
+ const clang::PointerType *pointer_ty = static_cast(ty);
+ clang::QualType child_qt = pointer_ty->getPointeeType();
ty = child_qt.getTypePtr();
}
- if (ty->getTypeClass() == Type::FunctionProto) {
- return static_cast(ty);
+ if (ty->getTypeClass() == clang::Type::FunctionProto) {
+ return static_cast(ty);
}
return nullptr;
}
-static bool qual_type_is_fn_ptr(QualType qt) {
+static bool qual_type_is_fn_ptr(clang::QualType qt) {
bool is_ptr;
if (qual_type_get_fn_proto(qt, &is_ptr)) {
return is_ptr;
@@ -570,30 +595,30 @@ static bool qual_type_is_fn_ptr(QualType qt) {
return false;
}
-static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const SourceLocation &source_loc) {
- const Type *ty = qt.getTypePtr();
+static uint32_t qual_type_int_bit_width(Context *c, const clang::QualType &qt, const clang::SourceLocation &source_loc) {
+ const clang::Type *ty = qt.getTypePtr();
switch (ty->getTypeClass()) {
- case Type::Builtin:
+ case clang::Type::Builtin:
{
- const BuiltinType *builtin_ty = static_cast(ty);
+ const clang::BuiltinType *builtin_ty = static_cast(ty);
switch (builtin_ty->getKind()) {
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
return 8;
- case BuiltinType::UInt128:
- case BuiltinType::Int128:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Int128:
return 128;
default:
return 0;
}
zig_unreachable();
}
- case Type::Typedef:
+ case clang::Type::Typedef:
{
- const TypedefType *typedef_ty = static_cast(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ const clang::TypedefType *typedef_ty = static_cast(ty);
+ const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
const char *type_name = decl_name(typedef_decl);
if (strcmp(type_name, "uint8_t") == 0 || strcmp(type_name, "int8_t") == 0) {
return 8;
@@ -614,8 +639,8 @@ static uint32_t qual_type_int_bit_width(Context *c, const QualType &qt, const So
}
-static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
- const SourceLocation &source_loc)
+static AstNode *qual_type_to_log2_int_ref(Context *c, const clang::QualType &qt,
+ const clang::SourceLocation &source_loc)
{
uint32_t int_bit_width = qual_type_int_bit_width(c, qt, source_loc);
if (int_bit_width != 0) {
@@ -633,7 +658,7 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
// FieldAccess
// FnCall (.builtin = true)
// Symbol "import"
-// StringLiteral "std"
+// clang::StringLiteral "std"
// Symbol "math"
// Symbol "Log2Int"
// zig_type_node
@@ -647,21 +672,21 @@ static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
return log2int_fn_call;
}
-static bool qual_type_child_is_fn_proto(const QualType &qt) {
- if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
- const ParenType *paren_type = static_cast(qt.getTypePtr());
- if (paren_type->getInnerType()->getTypeClass() == Type::FunctionProto) {
+static bool qual_type_child_is_fn_proto(const clang::QualType &qt) {
+ if (qt.getTypePtr()->getTypeClass() == clang::Type::Paren) {
+ const clang::ParenType *paren_type = static_cast(qt.getTypePtr());
+ if (paren_type->getInnerType()->getTypeClass() == clang::Type::FunctionProto) {
return true;
}
- } else if (qt.getTypePtr()->getTypeClass() == Type::Attributed) {
- const AttributedType *attr_type = static_cast(qt.getTypePtr());
+ } else if (qt.getTypePtr()->getTypeClass() == clang::Type::Attributed) {
+ const clang::AttributedType *attr_type = static_cast(qt.getTypePtr());
return qual_type_child_is_fn_proto(attr_type->getEquivalentType());
}
return false;
}
-static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, QualType dest_type,
- QualType src_type, AstNode *expr)
+static AstNode* trans_c_cast(Context *c, const clang::SourceLocation &source_location, clang::QualType dest_type,
+ clang::QualType src_type, AstNode *expr)
{
if (qual_types_equal(dest_type, src_type)) {
return expr;
@@ -678,72 +703,72 @@ static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location,
return trans_create_node_fn_call_1(c, trans_qual_type(c, dest_type, source_location), expr);
}
-static bool c_is_signed_integer(Context *c, QualType qt) {
- const Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != Type::Builtin)
+static bool c_is_signed_integer(Context *c, clang::QualType qt) {
+ const clang::Type *c_type = qual_type_canon(qt);
+ if (c_type->getTypeClass() != clang::Type::Builtin)
return false;
- const BuiltinType *builtin_ty = static_cast(c_type);
+ const clang::BuiltinType *builtin_ty = static_cast(c_type);
switch (builtin_ty->getKind()) {
- case BuiltinType::SChar:
- case BuiltinType::Short:
- case BuiltinType::Int:
- case BuiltinType::Long:
- case BuiltinType::LongLong:
- case BuiltinType::Int128:
- case BuiltinType::WChar_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::WChar_S:
return true;
default:
return false;
}
}
-static bool c_is_unsigned_integer(Context *c, QualType qt) {
- const Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != Type::Builtin)
+static bool c_is_unsigned_integer(Context *c, clang::QualType qt) {
+ const clang::Type *c_type = qual_type_canon(qt);
+ if (c_type->getTypeClass() != clang::Type::Builtin)
return false;
- const BuiltinType *builtin_ty = static_cast(c_type);
+ const clang::BuiltinType *builtin_ty = static_cast(c_type);
switch (builtin_ty->getKind()) {
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::ULong:
- case BuiltinType::ULongLong:
- case BuiltinType::UInt128:
- case BuiltinType::WChar_U:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::WChar_U:
return true;
default:
return false;
}
}
-static bool c_is_builtin_type(Context *c, QualType qt, BuiltinType::Kind kind) {
- const Type *c_type = qual_type_canon(qt);
- if (c_type->getTypeClass() != Type::Builtin)
+static bool c_is_builtin_type(Context *c, clang::QualType qt, clang::BuiltinType::Kind kind) {
+ const clang::Type *c_type = qual_type_canon(qt);
+ if (c_type->getTypeClass() != clang::Type::Builtin)
return false;
- const BuiltinType *builtin_ty = static_cast(c_type);
+ const clang::BuiltinType *builtin_ty = static_cast(c_type);
return builtin_ty->getKind() == kind;
}
-static bool c_is_float(Context *c, QualType qt) {
- const Type *c_type = qt.getTypePtr();
- if (c_type->getTypeClass() != Type::Builtin)
+static bool c_is_float(Context *c, clang::QualType qt) {
+ const clang::Type *c_type = qt.getTypePtr();
+ if (c_type->getTypeClass() != clang::Type::Builtin)
return false;
- const BuiltinType *builtin_ty = static_cast(c_type);
+ const clang::BuiltinType *builtin_ty = static_cast(c_type);
switch (builtin_ty->getKind()) {
- case BuiltinType::Half:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::Float128:
- case BuiltinType::LongDouble:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::Float128:
+ case clang::BuiltinType::LongDouble:
return true;
default:
return false;
}
}
-static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
+static bool qual_type_has_wrapping_overflow(Context *c, clang::QualType qt) {
if (c_is_signed_integer(c, qt) || c_is_float(c, qt)) {
// float and signed integer overflow is undefined behavior.
return false;
@@ -753,23 +778,23 @@ static bool qual_type_has_wrapping_overflow(Context *c, QualType qt) {
}
}
-static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &source_loc) {
+static bool type_is_opaque(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
switch (ty->getTypeClass()) {
- case Type::Builtin: {
- const BuiltinType *builtin_ty = static_cast(ty);
- return builtin_ty->getKind() == BuiltinType::Void;
+ case clang::Type::Builtin: {
+ const clang::BuiltinType *builtin_ty = static_cast(ty);
+ return builtin_ty->getKind() == clang::BuiltinType::Void;
}
- case Type::Record: {
- const RecordType *record_ty = static_cast(ty);
+ case clang::Type::Record: {
+ const clang::RecordType *record_ty = static_cast(ty);
return record_ty->getDecl()->getDefinition() == nullptr;
}
- case Type::Elaborated: {
- const ElaboratedType *elaborated_ty = static_cast(ty);
+ case clang::Type::Elaborated: {
+ const clang::ElaboratedType *elaborated_ty = static_cast(ty);
return type_is_opaque(c, elaborated_ty->getNamedType().getTypePtr(), source_loc);
}
- case Type::Typedef: {
- const TypedefType *typedef_ty = static_cast(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ case clang::Type::Typedef: {
+ const clang::TypedefType *typedef_ty = static_cast(ty);
+ const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
return type_is_opaque(c, typedef_decl->getUnderlyingType().getTypePtr(), source_loc);
}
default:
@@ -777,136 +802,136 @@ static bool type_is_opaque(Context *c, const Type *ty, const SourceLocation &sou
}
}
-static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &source_loc) {
+static AstNode *trans_type(Context *c, const clang::Type *ty, const clang::SourceLocation &source_loc) {
switch (ty->getTypeClass()) {
- case Type::Builtin:
+ case clang::Type::Builtin:
{
- const BuiltinType *builtin_ty = static_cast(ty);
+ const clang::BuiltinType *builtin_ty = static_cast(ty);
switch (builtin_ty->getKind()) {
- case BuiltinType::Void:
+ case clang::BuiltinType::Void:
return trans_create_node_symbol_str(c, "c_void");
- case BuiltinType::Bool:
+ case clang::BuiltinType::Bool:
return trans_create_node_symbol_str(c, "bool");
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::Char8:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::Char8:
return trans_create_node_symbol_str(c, "u8");
- case BuiltinType::SChar:
+ case clang::BuiltinType::SChar:
return trans_create_node_symbol_str(c, "i8");
- case BuiltinType::UShort:
+ case clang::BuiltinType::UShort:
return trans_create_node_symbol_str(c, "c_ushort");
- case BuiltinType::UInt:
+ case clang::BuiltinType::UInt:
return trans_create_node_symbol_str(c, "c_uint");
- case BuiltinType::ULong:
+ case clang::BuiltinType::ULong:
return trans_create_node_symbol_str(c, "c_ulong");
- case BuiltinType::ULongLong:
+ case clang::BuiltinType::ULongLong:
return trans_create_node_symbol_str(c, "c_ulonglong");
- case BuiltinType::Short:
+ case clang::BuiltinType::Short:
return trans_create_node_symbol_str(c, "c_short");
- case BuiltinType::Int:
+ case clang::BuiltinType::Int:
return trans_create_node_symbol_str(c, "c_int");
- case BuiltinType::Long:
+ case clang::BuiltinType::Long:
return trans_create_node_symbol_str(c, "c_long");
- case BuiltinType::LongLong:
+ case clang::BuiltinType::LongLong:
return trans_create_node_symbol_str(c, "c_longlong");
- case BuiltinType::UInt128:
+ case clang::BuiltinType::UInt128:
return trans_create_node_symbol_str(c, "u128");
- case BuiltinType::Int128:
+ case clang::BuiltinType::Int128:
return trans_create_node_symbol_str(c, "i128");
- case BuiltinType::Float:
+ case clang::BuiltinType::Float:
return trans_create_node_symbol_str(c, "f32");
- case BuiltinType::Double:
+ case clang::BuiltinType::Double:
return trans_create_node_symbol_str(c, "f64");
- case BuiltinType::Float128:
+ case clang::BuiltinType::Float128:
return trans_create_node_symbol_str(c, "f128");
- case BuiltinType::Float16:
+ case clang::BuiltinType::Float16:
return trans_create_node_symbol_str(c, "f16");
- case BuiltinType::LongDouble:
+ case clang::BuiltinType::LongDouble:
return trans_create_node_symbol_str(c, "c_longdouble");
- case BuiltinType::WChar_U:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::WChar_S:
- case BuiltinType::Half:
- case BuiltinType::NullPtr:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- case BuiltinType::OMPArraySection:
- case BuiltinType::Dependent:
- case BuiltinType::Overload:
- case BuiltinType::BoundMember:
- case BuiltinType::PseudoObject:
- case BuiltinType::UnknownAny:
- case BuiltinType::BuiltinFn:
- case BuiltinType::ARCUnbridgedCast:
- case BuiltinType::ShortAccum:
- case BuiltinType::Accum:
- case BuiltinType::LongAccum:
- case BuiltinType::UShortAccum:
- case BuiltinType::UAccum:
- case BuiltinType::ULongAccum:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::NullPtr:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ case clang::BuiltinType::OMPArraySection:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::PseudoObject:
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::BuiltinFn:
+ case clang::BuiltinType::ARCUnbridgedCast:
+ case clang::BuiltinType::ShortAccum:
+ case clang::BuiltinType::Accum:
+ case clang::BuiltinType::LongAccum:
+ case clang::BuiltinType::UShortAccum:
+ case clang::BuiltinType::UAccum:
+ case clang::BuiltinType::ULongAccum:
- case BuiltinType::OCLImage1dRO:
- case BuiltinType::OCLImage1dArrayRO:
- case BuiltinType::OCLImage1dBufferRO:
- case BuiltinType::OCLImage2dRO:
- case BuiltinType::OCLImage2dArrayRO:
- case BuiltinType::OCLImage2dDepthRO:
- case BuiltinType::OCLImage2dArrayDepthRO:
- case BuiltinType::OCLImage2dMSAARO:
- case BuiltinType::OCLImage2dArrayMSAARO:
- case BuiltinType::OCLImage2dMSAADepthRO:
- case BuiltinType::OCLImage2dArrayMSAADepthRO:
- case BuiltinType::OCLImage3dRO:
- case BuiltinType::OCLImage1dWO:
- case BuiltinType::OCLImage1dArrayWO:
- case BuiltinType::OCLImage1dBufferWO:
- case BuiltinType::OCLImage2dWO:
- case BuiltinType::OCLImage2dArrayWO:
- case BuiltinType::OCLImage2dDepthWO:
- case BuiltinType::OCLImage2dArrayDepthWO:
- case BuiltinType::OCLImage2dMSAAWO:
- case BuiltinType::OCLImage2dArrayMSAAWO:
- case BuiltinType::OCLImage2dMSAADepthWO:
- case BuiltinType::OCLImage2dArrayMSAADepthWO:
- case BuiltinType::OCLImage3dWO:
- case BuiltinType::OCLImage1dRW:
- case BuiltinType::OCLImage1dArrayRW:
- case BuiltinType::OCLImage1dBufferRW:
- case BuiltinType::OCLImage2dRW:
- case BuiltinType::OCLImage2dArrayRW:
- case BuiltinType::OCLImage2dDepthRW:
- case BuiltinType::OCLImage2dArrayDepthRW:
- case BuiltinType::OCLImage2dMSAARW:
- case BuiltinType::OCLImage2dArrayMSAARW:
- case BuiltinType::OCLImage2dMSAADepthRW:
- case BuiltinType::OCLImage2dArrayMSAADepthRW:
- case BuiltinType::OCLImage3dRW:
- case BuiltinType::OCLSampler:
- case BuiltinType::OCLEvent:
- case BuiltinType::OCLClkEvent:
- case BuiltinType::OCLQueue:
- case BuiltinType::OCLReserveID:
- case BuiltinType::ShortFract:
- case BuiltinType::Fract:
- case BuiltinType::LongFract:
- case BuiltinType::UShortFract:
- case BuiltinType::UFract:
- case BuiltinType::ULongFract:
- case BuiltinType::SatShortAccum:
- case BuiltinType::SatAccum:
- case BuiltinType::SatLongAccum:
- case BuiltinType::SatUShortAccum:
- case BuiltinType::SatUAccum:
- case BuiltinType::SatULongAccum:
- case BuiltinType::SatShortFract:
- case BuiltinType::SatFract:
- case BuiltinType::SatLongFract:
- case BuiltinType::SatUShortFract:
- case BuiltinType::SatUFract:
- case BuiltinType::SatULongFract:
+ case clang::BuiltinType::OCLImage1dRO:
+ case clang::BuiltinType::OCLImage1dArrayRO:
+ case clang::BuiltinType::OCLImage1dBufferRO:
+ case clang::BuiltinType::OCLImage2dRO:
+ case clang::BuiltinType::OCLImage2dArrayRO:
+ case clang::BuiltinType::OCLImage2dDepthRO:
+ case clang::BuiltinType::OCLImage2dArrayDepthRO:
+ case clang::BuiltinType::OCLImage2dMSAARO:
+ case clang::BuiltinType::OCLImage2dArrayMSAARO:
+ case clang::BuiltinType::OCLImage2dMSAADepthRO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
+ case clang::BuiltinType::OCLImage3dRO:
+ case clang::BuiltinType::OCLImage1dWO:
+ case clang::BuiltinType::OCLImage1dArrayWO:
+ case clang::BuiltinType::OCLImage1dBufferWO:
+ case clang::BuiltinType::OCLImage2dWO:
+ case clang::BuiltinType::OCLImage2dArrayWO:
+ case clang::BuiltinType::OCLImage2dDepthWO:
+ case clang::BuiltinType::OCLImage2dArrayDepthWO:
+ case clang::BuiltinType::OCLImage2dMSAAWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAAWO:
+ case clang::BuiltinType::OCLImage2dMSAADepthWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
+ case clang::BuiltinType::OCLImage3dWO:
+ case clang::BuiltinType::OCLImage1dRW:
+ case clang::BuiltinType::OCLImage1dArrayRW:
+ case clang::BuiltinType::OCLImage1dBufferRW:
+ case clang::BuiltinType::OCLImage2dRW:
+ case clang::BuiltinType::OCLImage2dArrayRW:
+ case clang::BuiltinType::OCLImage2dDepthRW:
+ case clang::BuiltinType::OCLImage2dArrayDepthRW:
+ case clang::BuiltinType::OCLImage2dMSAARW:
+ case clang::BuiltinType::OCLImage2dArrayMSAARW:
+ case clang::BuiltinType::OCLImage2dMSAADepthRW:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
+ case clang::BuiltinType::OCLImage3dRW:
+ case clang::BuiltinType::OCLSampler:
+ case clang::BuiltinType::OCLEvent:
+ case clang::BuiltinType::OCLClkEvent:
+ case clang::BuiltinType::OCLQueue:
+ case clang::BuiltinType::OCLReserveID:
+ case clang::BuiltinType::ShortFract:
+ case clang::BuiltinType::Fract:
+ case clang::BuiltinType::LongFract:
+ case clang::BuiltinType::UShortFract:
+ case clang::BuiltinType::UFract:
+ case clang::BuiltinType::ULongFract:
+ case clang::BuiltinType::SatShortAccum:
+ case clang::BuiltinType::SatAccum:
+ case clang::BuiltinType::SatLongAccum:
+ case clang::BuiltinType::SatUShortAccum:
+ case clang::BuiltinType::SatUAccum:
+ case clang::BuiltinType::SatULongAccum:
+ case clang::BuiltinType::SatShortFract:
+ case clang::BuiltinType::SatFract:
+ case clang::BuiltinType::SatLongFract:
+ case clang::BuiltinType::SatUShortFract:
+ case clang::BuiltinType::SatUFract:
+ case clang::BuiltinType::SatULongFract:
case BuiltinType::OCLIntelSubgroupAVCMcePayload:
case BuiltinType::OCLIntelSubgroupAVCImePayload:
case BuiltinType::OCLIntelSubgroupAVCRefPayload:
@@ -924,10 +949,10 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
}
break;
}
- case Type::Pointer:
+ case clang::Type::Pointer:
{
- const PointerType *pointer_ty = static_cast(ty);
- QualType child_qt = pointer_ty->getPointeeType();
+ const clang::PointerType *pointer_ty = static_cast(ty);
+ clang::QualType child_qt = pointer_ty->getPointeeType();
AstNode *child_node = trans_qual_type(c, child_qt, source_loc);
if (child_node == nullptr) {
emit_warning(c, source_loc, "pointer to unsupported type");
@@ -938,90 +963,94 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
return trans_create_node_prefix_op(c, PrefixOpOptional, child_node);
}
- PtrLen ptr_len = type_is_opaque(c, child_qt.getTypePtr(), source_loc) ? PtrLenSingle : PtrLenUnknown;
-
- AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
- child_qt.isVolatileQualified(), child_node, ptr_len);
- return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
+ if (type_is_opaque(c, child_qt.getTypePtr(), source_loc)) {
+ AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
+ child_qt.isVolatileQualified(), child_node, PtrLenSingle);
+ return trans_create_node_prefix_op(c, PrefixOpOptional, pointer_node);
+ } else {
+ return trans_create_node_ptr_type(c, child_qt.isConstQualified(),
+ child_qt.isVolatileQualified(), child_node, PtrLenC);
+ }
}
- case Type::Typedef:
+ case clang::Type::Typedef:
{
- const TypedefType *typedef_ty = static_cast(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ const clang::TypedefType *typedef_ty = static_cast(ty);
+ const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
return resolve_typedef_decl(c, typedef_decl);
}
- case Type::Elaborated:
+ case clang::Type::Elaborated:
{
- const ElaboratedType *elaborated_ty = static_cast(ty);
+ const clang::ElaboratedType *elaborated_ty = static_cast(ty);
switch (elaborated_ty->getKeyword()) {
- case ETK_Struct:
- case ETK_Enum:
- case ETK_Union:
+ case clang::ETK_Struct:
+ case clang::ETK_Enum:
+ case clang::ETK_Union:
return trans_qual_type(c, elaborated_ty->getNamedType(), source_loc);
- case ETK_Interface:
- case ETK_Class:
- case ETK_Typename:
- case ETK_None:
+ case clang::ETK_Interface:
+ case clang::ETK_Class:
+ case clang::ETK_Typename:
+ case clang::ETK_None:
emit_warning(c, source_loc, "unsupported elaborated type");
return nullptr;
}
}
- case Type::FunctionProto:
+ case clang::Type::FunctionProto:
+ case clang::Type::FunctionNoProto:
{
- const FunctionProtoType *fn_proto_ty = static_cast(ty);
+ const clang::FunctionType *fn_ty = static_cast(ty);
AstNode *proto_node = trans_create_node(c, NodeTypeFnProto);
- switch (fn_proto_ty->getCallConv()) {
- case CC_C: // __attribute__((cdecl))
+ switch (fn_ty->getCallConv()) {
+ case clang::CC_C: // __attribute__((cdecl))
proto_node->data.fn_proto.cc = CallingConventionC;
proto_node->data.fn_proto.is_extern = true;
break;
- case CC_X86StdCall: // __attribute__((stdcall))
+ case clang::CC_X86StdCall: // __attribute__((stdcall))
proto_node->data.fn_proto.cc = CallingConventionStdcall;
break;
- case CC_X86FastCall: // __attribute__((fastcall))
+ case clang::CC_X86FastCall: // __attribute__((fastcall))
emit_warning(c, source_loc, "unsupported calling convention: x86 fastcall");
return nullptr;
- case CC_X86ThisCall: // __attribute__((thiscall))
+ case clang::CC_X86ThisCall: // __attribute__((thiscall))
emit_warning(c, source_loc, "unsupported calling convention: x86 thiscall");
return nullptr;
- case CC_X86VectorCall: // __attribute__((vectorcall))
+ case clang::CC_X86VectorCall: // __attribute__((vectorcall))
emit_warning(c, source_loc, "unsupported calling convention: x86 vectorcall");
return nullptr;
- case CC_X86Pascal: // __attribute__((pascal))
+ case clang::CC_X86Pascal: // __attribute__((pascal))
emit_warning(c, source_loc, "unsupported calling convention: x86 pascal");
return nullptr;
- case CC_Win64: // __attribute__((ms_abi))
+ case clang::CC_Win64: // __attribute__((ms_abi))
emit_warning(c, source_loc, "unsupported calling convention: win64");
return nullptr;
- case CC_X86_64SysV: // __attribute__((sysv_abi))
+ case clang::CC_X86_64SysV: // __attribute__((sysv_abi))
emit_warning(c, source_loc, "unsupported calling convention: x86 64sysv");
return nullptr;
- case CC_X86RegCall:
+ case clang::CC_X86RegCall:
emit_warning(c, source_loc, "unsupported calling convention: x86 reg");
return nullptr;
- case CC_AAPCS: // __attribute__((pcs("aapcs")))
+ case clang::CC_AAPCS: // __attribute__((pcs("aapcs")))
emit_warning(c, source_loc, "unsupported calling convention: aapcs");
return nullptr;
- case CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
+ case clang::CC_AAPCS_VFP: // __attribute__((pcs("aapcs-vfp")))
emit_warning(c, source_loc, "unsupported calling convention: aapcs-vfp");
return nullptr;
- case CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
+ case clang::CC_IntelOclBicc: // __attribute__((intel_ocl_bicc))
emit_warning(c, source_loc, "unsupported calling convention: intel_ocl_bicc");
return nullptr;
- case CC_SpirFunction: // default for OpenCL functions on SPIR target
+ case clang::CC_SpirFunction: // default for OpenCL functions on SPIR target
emit_warning(c, source_loc, "unsupported calling convention: SPIR function");
return nullptr;
- case CC_OpenCLKernel:
+ case clang::CC_OpenCLKernel:
emit_warning(c, source_loc, "unsupported calling convention: OpenCLKernel");
return nullptr;
- case CC_Swift:
+ case clang::CC_Swift:
emit_warning(c, source_loc, "unsupported calling convention: Swift");
return nullptr;
- case CC_PreserveMost:
+ case clang::CC_PreserveMost:
emit_warning(c, source_loc, "unsupported calling convention: PreserveMost");
return nullptr;
- case CC_PreserveAll:
+ case clang::CC_PreserveAll:
emit_warning(c, source_loc, "unsupported calling convention: PreserveAll");
return nullptr;
case CC_AArch64VectorCall:
@@ -1029,20 +1058,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
return nullptr;
}
- proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
- size_t param_count = fn_proto_ty->getNumParams();
-
- if (fn_proto_ty->getNoReturnAttr()) {
+ if (fn_ty->getNoReturnAttr()) {
proto_node->data.fn_proto.return_type = trans_create_node_symbol_str(c, "noreturn");
} else {
- proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_proto_ty->getReturnType(),
+ proto_node->data.fn_proto.return_type = trans_qual_type(c, fn_ty->getReturnType(),
source_loc);
if (proto_node->data.fn_proto.return_type == nullptr) {
emit_warning(c, source_loc, "unsupported function proto return type");
return nullptr;
}
// convert c_void to actual void (only for return type)
- // we do want to look at the AstNode instead of QualType, because
+ // we do want to look at the AstNode instead of clang::QualType, because
// if they do something like:
// typedef Foo void;
// void foo(void) -> Foo;
@@ -1058,8 +1084,17 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
proto_node->data.fn_proto.name = buf_create_from_str(fn_name);
}
+ if (ty->getTypeClass() == clang::Type::FunctionNoProto) {
+ return proto_node;
+ }
+
+ const clang::FunctionProtoType *fn_proto_ty = static_cast(ty);
+
+ proto_node->data.fn_proto.is_var_args = fn_proto_ty->isVariadic();
+ size_t param_count = fn_proto_ty->getNumParams();
+
for (size_t i = 0; i < param_count; i += 1) {
- QualType qt = fn_proto_ty->getParamType(i);
+ clang::QualType qt = fn_proto_ty->getParamType(i);
AstNode *param_type_node = trans_qual_type(c, qt, source_loc);
if (param_type_node == nullptr) {
@@ -1082,19 +1117,19 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
return proto_node;
}
- case Type::Record:
+ case clang::Type::Record:
{
- const RecordType *record_ty = static_cast(ty);
+ const clang::RecordType *record_ty = static_cast(ty);
return resolve_record_decl(c, record_ty->getDecl());
}
- case Type::Enum:
+ case clang::Type::Enum:
{
- const EnumType *enum_ty = static_cast(ty);
+ const clang::EnumType *enum_ty = static_cast(ty);
return resolve_enum_decl(c, enum_ty->getDecl());
}
- case Type::ConstantArray:
+ case clang::Type::ConstantArray:
{
- const ConstantArrayType *const_arr_ty = static_cast(ty);
+ const clang::ConstantArrayType *const_arr_ty = static_cast(ty);
AstNode *child_type_node = trans_qual_type(c, const_arr_ty->getElementType(), source_loc);
if (child_type_node == nullptr) {
emit_warning(c, source_loc, "unresolved array element type");
@@ -1104,84 +1139,83 @@ static AstNode *trans_type(Context *c, const Type *ty, const SourceLocation &sou
AstNode *size_node = trans_create_node_unsigned(c, size);
return trans_create_node_array_type(c, size_node, child_type_node);
}
- case Type::Paren:
+ case clang::Type::Paren:
{
- const ParenType *paren_ty = static_cast(ty);
+ const clang::ParenType *paren_ty = static_cast(ty);
return trans_qual_type(c, paren_ty->getInnerType(), source_loc);
}
- case Type::Decayed:
+ case clang::Type::Decayed:
{
- const DecayedType *decayed_ty = static_cast(ty);
+ const clang::DecayedType *decayed_ty = static_cast(ty);
return trans_qual_type(c, decayed_ty->getDecayedType(), source_loc);
}
- case Type::Attributed:
+ case clang::Type::Attributed:
{
- const AttributedType *attributed_ty = static_cast(ty);
+ const clang::AttributedType *attributed_ty = static_cast(ty);
return trans_qual_type(c, attributed_ty->getEquivalentType(), source_loc);
}
- case Type::IncompleteArray:
+ case clang::Type::IncompleteArray:
{
- const IncompleteArrayType *incomplete_array_ty = static_cast(ty);
- QualType child_qt = incomplete_array_ty->getElementType();
+ const clang::IncompleteArrayType *incomplete_array_ty = static_cast(ty);
+ clang::QualType child_qt = incomplete_array_ty->getElementType();
AstNode *child_type_node = trans_qual_type(c, child_qt, source_loc);
if (child_type_node == nullptr) {
emit_warning(c, source_loc, "unresolved array element type");
return nullptr;
}
AstNode *pointer_node = trans_create_node_ptr_type(c, child_qt.isConstQualified(),
- child_qt.isVolatileQualified(), child_type_node, PtrLenUnknown);
+ child_qt.isVolatileQualified(), child_type_node, PtrLenC);
return pointer_node;
}
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionNoProto:
- case Type::UnresolvedUsing:
- case Type::Adjusted:
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::UnaryTransform:
- case Type::TemplateTypeParm:
- case Type::SubstTemplateTypeParm:
- case Type::SubstTemplateTypeParmPack:
- case Type::TemplateSpecialization:
- case Type::Auto:
- case Type::InjectedClassName:
- case Type::DependentName:
- case Type::DependentTemplateSpecialization:
- case Type::PackExpansion:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::Complex:
- case Type::ObjCObjectPointer:
- case Type::Atomic:
- case Type::Pipe:
- case Type::ObjCTypeParam:
- case Type::DeducedTemplateSpecialization:
- case Type::DependentAddressSpace:
- case Type::DependentVector:
+ case clang::Type::BlockPointer:
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ case clang::Type::MemberPointer:
+ case clang::Type::VariableArray:
+ case clang::Type::DependentSizedArray:
+ case clang::Type::DependentSizedExtVector:
+ case clang::Type::Vector:
+ case clang::Type::ExtVector:
+ case clang::Type::UnresolvedUsing:
+ case clang::Type::Adjusted:
+ case clang::Type::TypeOfExpr:
+ case clang::Type::TypeOf:
+ case clang::Type::Decltype:
+ case clang::Type::UnaryTransform:
+ case clang::Type::TemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParmPack:
+ case clang::Type::TemplateSpecialization:
+ case clang::Type::Auto:
+ case clang::Type::InjectedClassName:
+ case clang::Type::DependentName:
+ case clang::Type::DependentTemplateSpecialization:
+ case clang::Type::PackExpansion:
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ case clang::Type::Complex:
+ case clang::Type::ObjCObjectPointer:
+ case clang::Type::Atomic:
+ case clang::Type::Pipe:
+ case clang::Type::ObjCTypeParam:
+ case clang::Type::DeducedTemplateSpecialization:
+ case clang::Type::DependentAddressSpace:
+ case clang::Type::DependentVector:
emit_warning(c, source_loc, "unsupported type: '%s'", ty->getTypeClassName());
return nullptr;
}
zig_unreachable();
}
-static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc) {
+static AstNode *trans_qual_type(Context *c, clang::QualType qt, const clang::SourceLocation &source_loc) {
return trans_type(c, qt.getTypePtr(), source_loc);
}
-static int trans_compound_stmt_inline(Context *c, TransScope *scope, const CompoundStmt *stmt,
+static int trans_compound_stmt_inline(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
AstNode *block_node, TransScope **out_node_scope)
{
assert(block_node->type == NodeTypeBlock);
- for (CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
+ for (clang::CompoundStmt::const_body_iterator it = stmt->body_begin(), end_it = stmt->body_end(); it != end_it; ++it) {
AstNode *child_node;
scope = trans_stmt(c, scope, *it, &child_node);
if (scope == nullptr)
@@ -1195,7 +1229,7 @@ static int trans_compound_stmt_inline(Context *c, TransScope *scope, const Compo
return ErrorNone;
}
-static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const CompoundStmt *stmt,
+static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const clang::CompoundStmt *stmt,
TransScope **out_node_scope)
{
TransScopeBlock *child_scope_block = trans_scope_block_create(c, scope);
@@ -1204,8 +1238,8 @@ static AstNode *trans_compound_stmt(Context *c, TransScope *scope, const Compoun
return child_scope_block->node;
}
-static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStmt *stmt) {
- const Expr *value_expr = stmt->getRetValue();
+static AstNode *trans_return_stmt(Context *c, TransScope *scope, const clang::ReturnStmt *stmt) {
+ const clang::Expr *value_expr = stmt->getRetValue();
if (value_expr == nullptr) {
return trans_create_node(c, NodeTypeReturnExpr);
} else {
@@ -1217,18 +1251,18 @@ static AstNode *trans_return_stmt(Context *c, TransScope *scope, const ReturnStm
}
}
-static AstNode *trans_integer_literal(Context *c, const IntegerLiteral *stmt) {
+static AstNode *trans_integer_literal(Context *c, const clang::IntegerLiteral *stmt) {
Expr::EvalResult result;
- if (!stmt->EvaluateAsInt(result, *c->ctx)) {
+ if (!stmt->EvaluateAsInt(result, *reinterpret_cast(c->ctx))) {
emit_warning(c, stmt->getBeginLoc(), "invalid integer literal");
return nullptr;
}
return trans_create_node_apint(c, result.Val.getInt());
}
-static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) {
+static AstNode *trans_constant_expr(Context *c, const clang::ConstantExpr *expr) {
Expr::EvalResult result;
- if (!expr->EvaluateAsConstantExpr(result, Expr::EvaluateForCodeGen, *c->ctx)) {
+ if (!expr->EvaluateAsConstantExpr(result, clang::Expr::EvaluateForCodeGen, *c->ctx)) {
emit_warning(c, expr->getBeginLoc(), "invalid constant expression");
return nullptr;
}
@@ -1236,13 +1270,13 @@ static AstNode *trans_constant_expr(Context *c, const ConstantExpr *expr) {
}
static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, TransScope *scope,
- const ConditionalOperator *stmt)
+ const clang::ConditionalOperator *stmt)
{
AstNode *node = trans_create_node(c, NodeTypeIfBoolExpr);
- Expr *cond_expr = stmt->getCond();
- Expr *true_expr = stmt->getTrueExpr();
- Expr *false_expr = stmt->getFalseExpr();
+ clang::Expr *cond_expr = stmt->getCond();
+ clang::Expr *true_expr = stmt->getTrueExpr();
+ clang::Expr *false_expr = stmt->getFalseExpr();
node->data.if_bool_expr.condition = trans_expr(c, ResultUsedYes, scope, cond_expr, TransRValue);
if (node->data.if_bool_expr.condition == nullptr)
@@ -1259,7 +1293,7 @@ static AstNode *trans_conditional_operator(Context *c, ResultUsed result_used, T
return maybe_suppress_result(c, result_used, node);
}
-static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {
+static AstNode *trans_create_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
node->data.bin_op_expr.bin_op = bin_op;
@@ -1274,7 +1308,7 @@ static AstNode *trans_create_bin_op(Context *c, TransScope *scope, Expr *lhs, Bi
return node;
}
-static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lhs, BinOpType bin_op, Expr *rhs) {
+static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, clang::Expr *lhs, BinOpType bin_op, clang::Expr *rhs) {
assert(bin_op == BinOpTypeBoolAnd || bin_op == BinOpTypeBoolOr);
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
node->data.bin_op_expr.bin_op = bin_op;
@@ -1290,7 +1324,7 @@ static AstNode *trans_create_bool_bin_op(Context *c, TransScope *scope, Expr *lh
return node;
}
-static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, Expr *lhs, Expr *rhs) {
+static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransScope *scope, clang::Expr *lhs, clang::Expr *rhs) {
if (result_used == ResultUsedNo) {
// common case
AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
@@ -1341,10 +1375,10 @@ static AstNode *trans_create_assign(Context *c, ResultUsed result_used, TransSco
}
}
-static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType result_type,
- Expr *lhs_expr, BinOpType bin_op, Expr *rhs_expr)
+static AstNode *trans_create_shift_op(Context *c, TransScope *scope, clang::QualType result_type,
+ clang::Expr *lhs_expr, BinOpType bin_op, clang::Expr *rhs_expr)
{
- const SourceLocation &rhs_location = rhs_expr->getBeginLoc();
+ const clang::SourceLocation &rhs_location = rhs_expr->getBeginLoc();
AstNode *rhs_type = qual_type_to_log2_int_ref(c, result_type, rhs_location);
// lhs >> u5(rh)
@@ -1358,22 +1392,22 @@ static AstNode *trans_create_shift_op(Context *c, TransScope *scope, QualType re
return trans_create_node_bin_op(c, lhs, bin_op, coerced_rhs);
}
-static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const BinaryOperator *stmt) {
+static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::BinaryOperator *stmt) {
switch (stmt->getOpcode()) {
- case BO_PtrMemD:
+ case clang::BO_PtrMemD:
emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemD");
return nullptr;
- case BO_PtrMemI:
+ case clang::BO_PtrMemI:
emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_PtrMemI");
return nullptr;
- case BO_Cmp:
+ case clang::BO_Cmp:
emit_warning(c, stmt->getBeginLoc(), "TODO handle more C binary operators: BO_Cmp");
return nullptr;
- case BO_Mul:
+ case clang::BO_Mul:
return trans_create_bin_op(c, scope, stmt->getLHS(),
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeMultWrap : BinOpTypeMult,
stmt->getRHS());
- case BO_Div:
+ case clang::BO_Div:
if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
// unsigned/float division uses the operator
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeDiv, stmt->getRHS());
@@ -1388,7 +1422,7 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
fn_call->data.fn_call_expr.params.append(rhs);
return fn_call;
}
- case BO_Rem:
+ case clang::BO_Rem:
if (qual_type_has_wrapping_overflow(c, stmt->getType())) {
// unsigned/float division uses the operator
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeMod, stmt->getRHS());
@@ -1403,43 +1437,43 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
fn_call->data.fn_call_expr.params.append(rhs);
return fn_call;
}
- case BO_Add:
+ case clang::BO_Add:
return trans_create_bin_op(c, scope, stmt->getLHS(),
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeAddWrap : BinOpTypeAdd,
stmt->getRHS());
- case BO_Sub:
+ case clang::BO_Sub:
return trans_create_bin_op(c, scope, stmt->getLHS(),
qual_type_has_wrapping_overflow(c, stmt->getType()) ? BinOpTypeSubWrap : BinOpTypeSub,
stmt->getRHS());
- case BO_Shl:
+ case clang::BO_Shl:
return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftLeft, stmt->getRHS());
- case BO_Shr:
+ case clang::BO_Shr:
return trans_create_shift_op(c, scope, stmt->getType(), stmt->getLHS(), BinOpTypeBitShiftRight, stmt->getRHS());
- case BO_LT:
+ case clang::BO_LT:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessThan, stmt->getRHS());
- case BO_GT:
+ case clang::BO_GT:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterThan, stmt->getRHS());
- case BO_LE:
+ case clang::BO_LE:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpLessOrEq, stmt->getRHS());
- case BO_GE:
+ case clang::BO_GE:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpGreaterOrEq, stmt->getRHS());
- case BO_EQ:
+ case clang::BO_EQ:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpEq, stmt->getRHS());
- case BO_NE:
+ case clang::BO_NE:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeCmpNotEq, stmt->getRHS());
- case BO_And:
+ case clang::BO_And:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinAnd, stmt->getRHS());
- case BO_Xor:
+ case clang::BO_Xor:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinXor, stmt->getRHS());
- case BO_Or:
+ case clang::BO_Or:
return trans_create_bin_op(c, scope, stmt->getLHS(), BinOpTypeBinOr, stmt->getRHS());
- case BO_LAnd:
+ case clang::BO_LAnd:
return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolAnd, stmt->getRHS());
- case BO_LOr:
+ case clang::BO_LOr:
return trans_create_bool_bin_op(c, scope, stmt->getLHS(), BinOpTypeBoolOr, stmt->getRHS());
- case BO_Assign:
+ case clang::BO_Assign:
return trans_create_assign(c, result_used, scope, stmt->getLHS(), stmt->getRHS());
- case BO_Comma:
+ case clang::BO_Comma:
{
TransScopeBlock *scope_block = trans_scope_block_create(c, scope);
Buf *label_name = buf_create_from_str("x");
@@ -1456,16 +1490,16 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
scope_block->node->data.block.statements.append(trans_create_node_break(c, label_name, maybe_suppress_result(c, result_used, rhs)));
return scope_block->node;
}
- case BO_MulAssign:
- case BO_DivAssign:
- case BO_RemAssign:
- case BO_AddAssign:
- case BO_SubAssign:
- case BO_ShlAssign:
- case BO_ShrAssign:
- case BO_AndAssign:
- case BO_XorAssign:
- case BO_OrAssign:
+ case clang::BO_MulAssign:
+ case clang::BO_DivAssign:
+ case clang::BO_RemAssign:
+ case clang::BO_AddAssign:
+ case clang::BO_SubAssign:
+ case clang::BO_ShlAssign:
+ case clang::BO_ShrAssign:
+ case clang::BO_AndAssign:
+ case clang::BO_XorAssign:
+ case clang::BO_OrAssign:
zig_unreachable();
}
@@ -1473,9 +1507,9 @@ static AstNode *trans_binary_operator(Context *c, ResultUsed result_used, TransS
}
static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result_used, TransScope *scope,
- const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
+ const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
{
- const SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc();
+ const clang::SourceLocation &rhs_location = stmt->getRHS()->getBeginLoc();
AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
bool use_intermediate_casts = stmt->getComputationLHSType().getTypePtr() != stmt->getComputationResultType().getTypePtr();
@@ -1555,7 +1589,7 @@ static AstNode *trans_create_compound_assign_shift(Context *c, ResultUsed result
}
static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used, TransScope *scope,
- const CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
+ const clang::CompoundAssignOperator *stmt, BinOpType assign_op, BinOpType bin_op)
{
if (result_used == ResultUsedNo) {
// simple common case, where the C and Zig are identical:
@@ -1615,76 +1649,76 @@ static AstNode *trans_create_compound_assign(Context *c, ResultUsed result_used,
static AstNode *trans_compound_assign_operator(Context *c, ResultUsed result_used, TransScope *scope,
- const CompoundAssignOperator *stmt)
+ const clang::CompoundAssignOperator *stmt)
{
switch (stmt->getOpcode()) {
- case BO_MulAssign:
+ case clang::BO_MulAssign:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimesWrap, BinOpTypeMultWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignTimes, BinOpTypeMult);
- case BO_DivAssign:
+ case clang::BO_DivAssign:
emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_DivAssign");
return nullptr;
- case BO_RemAssign:
+ case clang::BO_RemAssign:
emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_RemAssign");
return nullptr;
- case BO_Cmp:
+ case clang::BO_Cmp:
emit_warning(c, stmt->getBeginLoc(), "TODO handle more C compound assign operators: BO_Cmp");
return nullptr;
- case BO_AddAssign:
+ case clang::BO_AddAssign:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap, BinOpTypeAddWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignPlus, BinOpTypeAdd);
- case BO_SubAssign:
+ case clang::BO_SubAssign:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap, BinOpTypeSubWrap);
else
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignMinus, BinOpTypeSub);
- case BO_ShlAssign:
+ case clang::BO_ShlAssign:
return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftLeft, BinOpTypeBitShiftLeft);
- case BO_ShrAssign:
+ case clang::BO_ShrAssign:
return trans_create_compound_assign_shift(c, result_used, scope, stmt, BinOpTypeAssignBitShiftRight, BinOpTypeBitShiftRight);
- case BO_AndAssign:
+ case clang::BO_AndAssign:
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitAnd, BinOpTypeBinAnd);
- case BO_XorAssign:
+ case clang::BO_XorAssign:
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitXor, BinOpTypeBinXor);
- case BO_OrAssign:
+ case clang::BO_OrAssign:
return trans_create_compound_assign(c, result_used, scope, stmt, BinOpTypeAssignBitOr, BinOpTypeBinOr);
- case BO_PtrMemD:
- case BO_PtrMemI:
- case BO_Assign:
- case BO_Mul:
- case BO_Div:
- case BO_Rem:
- case BO_Add:
- case BO_Sub:
- case BO_Shl:
- case BO_Shr:
- case BO_LT:
- case BO_GT:
- case BO_LE:
- case BO_GE:
- case BO_EQ:
- case BO_NE:
- case BO_And:
- case BO_Xor:
- case BO_Or:
- case BO_LAnd:
- case BO_LOr:
- case BO_Comma:
+ case clang::BO_PtrMemD:
+ case clang::BO_PtrMemI:
+ case clang::BO_Assign:
+ case clang::BO_Mul:
+ case clang::BO_Div:
+ case clang::BO_Rem:
+ case clang::BO_Add:
+ case clang::BO_Sub:
+ case clang::BO_Shl:
+ case clang::BO_Shr:
+ case clang::BO_LT:
+ case clang::BO_GT:
+ case clang::BO_LE:
+ case clang::BO_GE:
+ case clang::BO_EQ:
+ case clang::BO_NE:
+ case clang::BO_And:
+ case clang::BO_Xor:
+ case clang::BO_Or:
+ case clang::BO_LAnd:
+ case clang::BO_LOr:
+ case clang::BO_Comma:
zig_unreachable();
}
zig_unreachable();
}
-static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const ImplicitCastExpr *stmt) {
+static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const clang::ImplicitCastExpr *stmt) {
switch (stmt->getCastKind()) {
- case CK_LValueToRValue:
+ case clang::CK_LValueToRValue:
return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
- case CK_IntegralCast:
+ case clang::CK_IntegralCast:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
if (target_node == nullptr)
@@ -1692,15 +1726,15 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(),
stmt->getSubExpr()->getType(), target_node);
}
- case CK_FunctionToPointerDecay:
- case CK_ArrayToPointerDecay:
+ case clang::CK_FunctionToPointerDecay:
+ case clang::CK_ArrayToPointerDecay:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
if (target_node == nullptr)
return nullptr;
return target_node;
}
- case CK_BitCast:
+ case clang::CK_BitCast:
{
AstNode *target_node = trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
if (target_node == nullptr)
@@ -1717,172 +1751,55 @@ static AstNode *trans_implicit_cast_expr(Context *c, TransScope *scope, const Im
node->data.fn_call_expr.params.append(target_node);
return node;
}
- case CK_NullToPointer:
- return trans_create_node(c, NodeTypeNullLiteral);
- case CK_Dependent:
+ case clang::CK_NullToPointer:
+ return trans_create_node_unsigned(c, 0);
+ case clang::CK_NoOp:
+ return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
+ case clang::CK_Dependent:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dependent");
return nullptr;
- case CK_LValueBitCast:
+ case clang::CK_LValueBitCast:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_LValueBitCast");
return nullptr;
- case CK_NoOp:
- return trans_expr(c, ResultUsedYes, scope, stmt->getSubExpr(), TransRValue);
- case CK_BaseToDerived:
+ case clang::CK_BaseToDerived:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerived");
return nullptr;
- case CK_DerivedToBase:
+ case clang::CK_DerivedToBase:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBase");
return nullptr;
- case CK_UncheckedDerivedToBase:
+ case clang::CK_UncheckedDerivedToBase:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UncheckedDerivedToBase");
return nullptr;
- case CK_Dynamic:
+ case clang::CK_Dynamic:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_Dynamic");
return nullptr;
- case CK_ToUnion:
+ case clang::CK_ToUnion:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToUnion");
return nullptr;
- case CK_NullToMemberPointer:
+ case clang::CK_NullToMemberPointer:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NullToMemberPointer");
return nullptr;
- case CK_BaseToDerivedMemberPointer:
+ case clang::CK_BaseToDerivedMemberPointer:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BaseToDerivedMemberPointer");
return nullptr;
- case CK_DerivedToBaseMemberPointer:
+ case clang::CK_DerivedToBaseMemberPointer:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_DerivedToBaseMemberPointer");
return nullptr;
- case CK_MemberPointerToBoolean:
+ case clang::CK_MemberPointerToBoolean:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_MemberPointerToBoolean");
return nullptr;
- case CK_ReinterpretMemberPointer:
+ case clang::CK_ReinterpretMemberPointer:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ReinterpretMemberPointer");
return nullptr;
- case CK_UserDefinedConversion:
+ case clang::CK_UserDefinedConversion:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_UserDefinedConversion");
return nullptr;
- case CK_ConstructorConversion:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ConstructorConversion");
- return nullptr;
- case CK_IntegralToPointer:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralToPointer");
- return nullptr;
- case CK_PointerToIntegral:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_PointerToIntegral");
- return nullptr;
- case CK_PointerToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_PointerToBoolean");
- return nullptr;
- case CK_ToVoid:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ToVoid");
- return nullptr;
- case CK_VectorSplat:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_VectorSplat");
- return nullptr;
- case CK_IntegralToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralToBoolean");
- return nullptr;
- case CK_IntegralToFloating:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralToFloating");
- return nullptr;
- case CK_FloatingToIntegral:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingToIntegral");
- return nullptr;
- case CK_FloatingToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingToBoolean");
- return nullptr;
- case CK_BooleanToSignedIntegral:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BooleanToSignedIntegral");
- return nullptr;
- case CK_FloatingCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingCast");
- return nullptr;
- case CK_CPointerToObjCPointerCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_CPointerToObjCPointerCast");
- return nullptr;
- case CK_BlockPointerToObjCPointerCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BlockPointerToObjCPointerCast");
- return nullptr;
- case CK_AnyPointerToBlockPointerCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_AnyPointerToBlockPointerCast");
- return nullptr;
- case CK_ObjCObjectLValueCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ObjCObjectLValueCast");
- return nullptr;
- case CK_FloatingRealToComplex:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingRealToComplex");
- return nullptr;
- case CK_FloatingComplexToReal:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingComplexToReal");
- return nullptr;
- case CK_FloatingComplexToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingComplexToBoolean");
- return nullptr;
- case CK_FloatingComplexCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingComplexCast");
- return nullptr;
- case CK_FloatingComplexToIntegralComplex:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FloatingComplexToIntegralComplex");
- return nullptr;
- case CK_IntegralRealToComplex:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralRealToComplex");
- return nullptr;
- case CK_IntegralComplexToReal:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralComplexToReal");
- return nullptr;
- case CK_IntegralComplexToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralComplexToBoolean");
- return nullptr;
- case CK_IntegralComplexCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralComplexCast");
- return nullptr;
- case CK_IntegralComplexToFloatingComplex:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntegralComplexToFloatingComplex");
- return nullptr;
- case CK_ARCProduceObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ARCProduceObject");
- return nullptr;
- case CK_ARCConsumeObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ARCConsumeObject");
- return nullptr;
- case CK_ARCReclaimReturnedObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ARCReclaimReturnedObject");
- return nullptr;
- case CK_ARCExtendBlockObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ARCExtendBlockObject");
- return nullptr;
- case CK_AtomicToNonAtomic:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_AtomicToNonAtomic");
- return nullptr;
- case CK_NonAtomicToAtomic:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_NonAtomicToAtomic");
- return nullptr;
- case CK_CopyAndAutoreleaseBlockObject:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_CopyAndAutoreleaseBlockObject");
- return nullptr;
- case CK_BuiltinFnToFnPtr:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_BuiltinFnToFnPtr");
- return nullptr;
- case CK_AddressSpaceConversion:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_AddressSpaceConversion");
- return nullptr;
- case CK_IntToOCLSampler:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_IntToOCLSampler");
- return nullptr;
- case CK_FixedPointCast:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FixedPointCast");
- return nullptr;
- case CK_FixedPointToBoolean:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_FixedPointToBoolean");
- return nullptr;
- case CK_ZeroToOCLOpaqueType:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation cast CK_ZeroToOCLOpaqueType");
- return nullptr;
}
zig_unreachable();
}
-static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRefExpr *stmt, TransLRValue lrval) {
- const ValueDecl *value_decl = stmt->getDecl();
+static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const clang::DeclRefExpr *stmt, TransLRValue lrval) {
+ const clang::ValueDecl *value_decl = stmt->getDecl();
Buf *c_symbol_name = buf_create_from_str(decl_name(value_decl));
Buf *zig_symbol_name = trans_lookup_zig_symbol(c, scope, c_symbol_name);
if (lrval == TransLValue) {
@@ -1892,9 +1809,9 @@ static AstNode *trans_decl_ref_expr(Context *c, TransScope *scope, const DeclRef
}
static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, TransScope *scope,
- const UnaryOperator *stmt, BinOpType assign_op)
+ const clang::UnaryOperator *stmt, BinOpType assign_op)
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
if (result_used == ResultUsedNo) {
// common case
@@ -1948,9 +1865,9 @@ static AstNode *trans_create_post_crement(Context *c, ResultUsed result_used, Tr
}
static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, TransScope *scope,
- const UnaryOperator *stmt, BinOpType assign_op)
+ const clang::UnaryOperator *stmt, BinOpType assign_op)
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
if (result_used == ResultUsedNo) {
// common case
@@ -1997,36 +1914,36 @@ static AstNode *trans_create_pre_crement(Context *c, ResultUsed result_used, Tra
return child_scope->node;
}
-static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const UnaryOperator *stmt) {
+static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransScope *scope, const clang::UnaryOperator *stmt) {
switch (stmt->getOpcode()) {
- case UO_PostInc:
+ case clang::UO_PostInc:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
else
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
- case UO_PostDec:
+ case clang::UO_PostDec:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
else
return trans_create_post_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
- case UO_PreInc:
+ case clang::UO_PreInc:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlusWrap);
else
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignPlus);
- case UO_PreDec:
+ case clang::UO_PreDec:
if (qual_type_has_wrapping_overflow(c, stmt->getType()))
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinusWrap);
else
return trans_create_pre_crement(c, result_used, scope, stmt, BinOpTypeAssignMinus);
- case UO_AddrOf:
+ case clang::UO_AddrOf:
{
AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransLValue);
if (value_node == nullptr)
return value_node;
return trans_create_node_addr_of(c, value_node);
}
- case UO_Deref:
+ case clang::UO_Deref:
{
AstNode *value_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), TransRValue);
if (value_node == nullptr)
@@ -2037,12 +1954,12 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
AstNode *unwrapped = trans_create_node_unwrap_null(c, value_node);
return trans_create_node_ptr_deref(c, unwrapped);
}
- case UO_Plus:
+ case clang::UO_Plus:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Plus");
return nullptr;
- case UO_Minus:
+ case clang::UO_Minus:
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
if (!qual_type_has_wrapping_overflow(c, op_expr->getType())) {
AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
node->data.prefix_op_expr.prefix_op = PrefixOpNegation;
@@ -2068,41 +1985,41 @@ static AstNode *trans_unary_operator(Context *c, ResultUsed result_used, TransSc
return nullptr;
}
}
- case UO_Not:
+ case clang::UO_Not:
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
AstNode *sub_node = trans_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
if (sub_node == nullptr)
return nullptr;
return trans_create_node_prefix_op(c, PrefixOpBinNot, sub_node);
}
- case UO_LNot:
+ case clang::UO_LNot:
{
- Expr *op_expr = stmt->getSubExpr();
+ clang::Expr *op_expr = stmt->getSubExpr();
AstNode *sub_node = trans_bool_expr(c, ResultUsedYes, scope, op_expr, TransRValue);
if (sub_node == nullptr)
return nullptr;
return trans_create_node_prefix_op(c, PrefixOpBoolNot, sub_node);
}
- case UO_Real:
+ case clang::UO_Real:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Real");
return nullptr;
- case UO_Imag:
+ case clang::UO_Imag:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Imag");
return nullptr;
- case UO_Extension:
+ case clang::UO_Extension:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Extension");
return nullptr;
- case UO_Coawait:
+ case clang::UO_Coawait:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C translation UO_Coawait");
return nullptr;
}
zig_unreachable();
}
-static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt *stmt,
+static int trans_local_declaration(Context *c, TransScope *scope, const clang::DeclStmt *stmt,
AstNode **out_node, TransScope **out_scope)
{
// declarations are added via the scope
@@ -2112,11 +2029,11 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
assert(scope_block != nullptr);
for (auto iter = stmt->decl_begin(); iter != stmt->decl_end(); iter++) {
- Decl *decl = *iter;
+ clang::Decl *decl = *iter;
switch (decl->getKind()) {
- case Decl::Var: {
- VarDecl *var_decl = (VarDecl *)decl;
- QualType qual_type = var_decl->getTypeSourceInfo()->getType();
+ case clang::Decl::Var: {
+ clang::VarDecl *var_decl = (clang::VarDecl *)decl;
+ clang::QualType qual_type = var_decl->getTypeSourceInfo()->getType();
AstNode *init_node = nullptr;
if (var_decl->hasInit()) {
init_node = trans_expr(c, ResultUsedYes, scope, var_decl->getInit(), TransRValue);
@@ -2141,225 +2058,9 @@ static int trans_local_declaration(Context *c, TransScope *scope, const DeclStmt
scope_block->node->data.block.statements.append(node);
continue;
}
- case Decl::AccessSpec:
+ case clang::Decl::AccessSpec:
emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind AccessSpec");
return ErrorUnexpected;
- case Decl::Block:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Block");
- return ErrorUnexpected;
- case Decl::Captured:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Captured");
- return ErrorUnexpected;
- case Decl::ClassScopeFunctionSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ClassScopeFunctionSpecialization");
- return ErrorUnexpected;
- case Decl::Empty:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Empty");
- return ErrorUnexpected;
- case Decl::Export:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Export");
- return ErrorUnexpected;
- case Decl::ExternCContext:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ExternCContext");
- return ErrorUnexpected;
- case Decl::FileScopeAsm:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind FileScopeAsm");
- return ErrorUnexpected;
- case Decl::Friend:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Friend");
- return ErrorUnexpected;
- case Decl::FriendTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind FriendTemplate");
- return ErrorUnexpected;
- case Decl::Import:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Import");
- return ErrorUnexpected;
- case Decl::LinkageSpec:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind LinkageSpec");
- return ErrorUnexpected;
- case Decl::Label:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Label");
- return ErrorUnexpected;
- case Decl::Namespace:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Namespace");
- return ErrorUnexpected;
- case Decl::NamespaceAlias:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind NamespaceAlias");
- return ErrorUnexpected;
- case Decl::ObjCCompatibleAlias:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCCompatibleAlias");
- return ErrorUnexpected;
- case Decl::ObjCCategory:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCCategory");
- return ErrorUnexpected;
- case Decl::ObjCCategoryImpl:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCCategoryImpl");
- return ErrorUnexpected;
- case Decl::ObjCImplementation:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCImplementation");
- return ErrorUnexpected;
- case Decl::ObjCInterface:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCInterface");
- return ErrorUnexpected;
- case Decl::ObjCProtocol:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCProtocol");
- return ErrorUnexpected;
- case Decl::ObjCMethod:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCMethod");
- return ErrorUnexpected;
- case Decl::ObjCProperty:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCProperty");
- return ErrorUnexpected;
- case Decl::BuiltinTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind BuiltinTemplate");
- return ErrorUnexpected;
- case Decl::ClassTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ClassTemplate");
- return ErrorUnexpected;
- case Decl::FunctionTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind FunctionTemplate");
- return ErrorUnexpected;
- case Decl::TypeAliasTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TypeAliasTemplate");
- return ErrorUnexpected;
- case Decl::VarTemplate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind VarTemplate");
- return ErrorUnexpected;
- case Decl::TemplateTemplateParm:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TemplateTemplateParm");
- return ErrorUnexpected;
- case Decl::Enum:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Enum");
- return ErrorUnexpected;
- case Decl::Record:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Record");
- return ErrorUnexpected;
- case Decl::CXXRecord:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXRecord");
- return ErrorUnexpected;
- case Decl::ClassTemplateSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ClassTemplateSpecialization");
- return ErrorUnexpected;
- case Decl::ClassTemplatePartialSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ClassTemplatePartialSpecialization");
- return ErrorUnexpected;
- case Decl::TemplateTypeParm:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TemplateTypeParm");
- return ErrorUnexpected;
- case Decl::ObjCTypeParam:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCTypeParam");
- return ErrorUnexpected;
- case Decl::TypeAlias:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TypeAlias");
- return ErrorUnexpected;
- case Decl::Typedef:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Typedef");
- return ErrorUnexpected;
- case Decl::UnresolvedUsingTypename:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UnresolvedUsingTypename");
- return ErrorUnexpected;
- case Decl::Using:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Using");
- return ErrorUnexpected;
- case Decl::UsingDirective:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UsingDirective");
- return ErrorUnexpected;
- case Decl::UsingPack:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UsingPack");
- return ErrorUnexpected;
- case Decl::UsingShadow:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UsingShadow");
- return ErrorUnexpected;
- case Decl::ConstructorUsingShadow:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ConstructorUsingShadow");
- return ErrorUnexpected;
- case Decl::Binding:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Binding");
- return ErrorUnexpected;
- case Decl::Field:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Field");
- return ErrorUnexpected;
- case Decl::ObjCAtDefsField:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCAtDefsField");
- return ErrorUnexpected;
- case Decl::ObjCIvar:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCIvar");
- return ErrorUnexpected;
- case Decl::Function:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Function");
- return ErrorUnexpected;
- case Decl::CXXDeductionGuide:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXDeductionGuide");
- return ErrorUnexpected;
- case Decl::CXXMethod:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXMethod");
- return ErrorUnexpected;
- case Decl::CXXConstructor:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXConstructor");
- return ErrorUnexpected;
- case Decl::CXXConversion:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXConversion");
- return ErrorUnexpected;
- case Decl::CXXDestructor:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind CXXDestructor");
- return ErrorUnexpected;
- case Decl::MSProperty:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind MSProperty");
- return ErrorUnexpected;
- case Decl::NonTypeTemplateParm:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind NonTypeTemplateParm");
- return ErrorUnexpected;
- case Decl::Decomposition:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind Decomposition");
- return ErrorUnexpected;
- case Decl::ImplicitParam:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ImplicitParam");
- return ErrorUnexpected;
- case Decl::OMPCapturedExpr:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind OMPCapturedExpr");
- return ErrorUnexpected;
- case Decl::ParmVar:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ParmVar");
- return ErrorUnexpected;
- case Decl::VarTemplateSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind VarTemplateSpecialization");
- return ErrorUnexpected;
- case Decl::VarTemplatePartialSpecialization:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind VarTemplatePartialSpecialization");
- return ErrorUnexpected;
- case Decl::EnumConstant:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind EnumConstant");
- return ErrorUnexpected;
- case Decl::IndirectField:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind IndirectField");
- return ErrorUnexpected;
- case Decl::OMPDeclareReduction:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind OMPDeclareReduction");
- return ErrorUnexpected;
- case Decl::UnresolvedUsingValue:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind UnresolvedUsingValue");
- return ErrorUnexpected;
- case Decl::OMPThreadPrivate:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind OMPThreadPrivate");
- return ErrorUnexpected;
- case Decl::ObjCPropertyImpl:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind ObjCPropertyImpl");
- return ErrorUnexpected;
- case Decl::PragmaComment:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind PragmaComment");
- return ErrorUnexpected;
- case Decl::PragmaDetectMismatch:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind PragmaDetectMismatch");
- return ErrorUnexpected;
- case Decl::StaticAssert:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind StaticAssert");
- return ErrorUnexpected;
- case Decl::TranslationUnit:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind TranslationUnit");
- return ErrorUnexpected;
- case Decl::OMPRequires:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle decl kind OMPRequires");
- return ErrorUnexpected;
}
zig_unreachable();
}
@@ -2384,7 +2085,7 @@ static AstNode *to_enum_zero_cmp(Context *c, AstNode *expr, AstNode *enum_type)
return trans_create_node_bin_op(c, expr, BinOpTypeCmpNotEq, bitcast);
}
-static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr, TransLRValue lrval) {
+static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr, TransLRValue lrval) {
AstNode *res = trans_expr(c, result_used, scope, expr, lrval);
if (res == nullptr)
return nullptr;
@@ -2421,143 +2122,145 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
}
- const Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
+ const clang::Type *ty = get_expr_qual_type_before_implicit_cast(c, expr).getTypePtr();
auto classs = ty->getTypeClass();
switch (classs) {
- case Type::Builtin:
+ case clang::Type::Builtin:
{
- const BuiltinType *builtin_ty = static_cast(ty);
+ const clang::BuiltinType *builtin_ty = static_cast(ty);
switch (builtin_ty->getKind()) {
- case BuiltinType::Bool:
- case BuiltinType::Char_U:
- case BuiltinType::UChar:
- case BuiltinType::Char_S:
- case BuiltinType::SChar:
- case BuiltinType::UShort:
- case BuiltinType::UInt:
- case BuiltinType::ULong:
- case BuiltinType::ULongLong:
- case BuiltinType::Short:
- case BuiltinType::Int:
- case BuiltinType::Long:
- case BuiltinType::LongLong:
- case BuiltinType::UInt128:
- case BuiltinType::Int128:
- case BuiltinType::Float:
- case BuiltinType::Double:
- case BuiltinType::Float128:
- case BuiltinType::LongDouble:
- case BuiltinType::WChar_U:
- case BuiltinType::Char8:
- case BuiltinType::Char16:
- case BuiltinType::Char32:
- case BuiltinType::WChar_S:
- case BuiltinType::Float16:
+ case clang::BuiltinType::Bool:
+ case clang::BuiltinType::Char_U:
+ case clang::BuiltinType::UChar:
+ case clang::BuiltinType::Char_S:
+ case clang::BuiltinType::SChar:
+ case clang::BuiltinType::UShort:
+ case clang::BuiltinType::UInt:
+ case clang::BuiltinType::ULong:
+ case clang::BuiltinType::ULongLong:
+ case clang::BuiltinType::Short:
+ case clang::BuiltinType::Int:
+ case clang::BuiltinType::Long:
+ case clang::BuiltinType::LongLong:
+ case clang::BuiltinType::UInt128:
+ case clang::BuiltinType::Int128:
+ case clang::BuiltinType::Float:
+ case clang::BuiltinType::Double:
+ case clang::BuiltinType::Float128:
+ case clang::BuiltinType::LongDouble:
+ case clang::BuiltinType::WChar_U:
+ case clang::BuiltinType::Char8:
+ case clang::BuiltinType::Char16:
+ case clang::BuiltinType::Char32:
+ case clang::BuiltinType::WChar_S:
+ case clang::BuiltinType::Float16:
return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node_unsigned_negative(c, 0, false));
- case BuiltinType::NullPtr:
- return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
+ case clang::BuiltinType::NullPtr:
+ return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
+ trans_create_node_unsigned(c, 0));
- case BuiltinType::Void:
- case BuiltinType::Half:
- case BuiltinType::ObjCId:
- case BuiltinType::ObjCClass:
- case BuiltinType::ObjCSel:
- case BuiltinType::OMPArraySection:
- case BuiltinType::Dependent:
- case BuiltinType::Overload:
- case BuiltinType::BoundMember:
- case BuiltinType::PseudoObject:
- case BuiltinType::UnknownAny:
- case BuiltinType::BuiltinFn:
- case BuiltinType::ARCUnbridgedCast:
- case BuiltinType::OCLImage1dRO:
- case BuiltinType::OCLImage1dArrayRO:
- case BuiltinType::OCLImage1dBufferRO:
- case BuiltinType::OCLImage2dRO:
- case BuiltinType::OCLImage2dArrayRO:
- case BuiltinType::OCLImage2dDepthRO:
- case BuiltinType::OCLImage2dArrayDepthRO:
- case BuiltinType::OCLImage2dMSAARO:
- case BuiltinType::OCLImage2dArrayMSAARO:
- case BuiltinType::OCLImage2dMSAADepthRO:
- case BuiltinType::OCLImage2dArrayMSAADepthRO:
- case BuiltinType::OCLImage3dRO:
- case BuiltinType::OCLImage1dWO:
- case BuiltinType::OCLImage1dArrayWO:
- case BuiltinType::OCLImage1dBufferWO:
- case BuiltinType::OCLImage2dWO:
- case BuiltinType::OCLImage2dArrayWO:
- case BuiltinType::OCLImage2dDepthWO:
- case BuiltinType::OCLImage2dArrayDepthWO:
- case BuiltinType::OCLImage2dMSAAWO:
- case BuiltinType::OCLImage2dArrayMSAAWO:
- case BuiltinType::OCLImage2dMSAADepthWO:
- case BuiltinType::OCLImage2dArrayMSAADepthWO:
- case BuiltinType::OCLImage3dWO:
- case BuiltinType::OCLImage1dRW:
- case BuiltinType::OCLImage1dArrayRW:
- case BuiltinType::OCLImage1dBufferRW:
- case BuiltinType::OCLImage2dRW:
- case BuiltinType::OCLImage2dArrayRW:
- case BuiltinType::OCLImage2dDepthRW:
- case BuiltinType::OCLImage2dArrayDepthRW:
- case BuiltinType::OCLImage2dMSAARW:
- case BuiltinType::OCLImage2dArrayMSAARW:
- case BuiltinType::OCLImage2dMSAADepthRW:
- case BuiltinType::OCLImage2dArrayMSAADepthRW:
- case BuiltinType::OCLImage3dRW:
- case BuiltinType::OCLSampler:
- case BuiltinType::OCLEvent:
- case BuiltinType::OCLClkEvent:
- case BuiltinType::OCLQueue:
- case BuiltinType::OCLReserveID:
- case BuiltinType::ShortAccum:
- case BuiltinType::Accum:
- case BuiltinType::LongAccum:
- case BuiltinType::UShortAccum:
- case BuiltinType::UAccum:
- case BuiltinType::ULongAccum:
- case BuiltinType::ShortFract:
- case BuiltinType::Fract:
- case BuiltinType::LongFract:
- case BuiltinType::UShortFract:
- case BuiltinType::UFract:
- case BuiltinType::ULongFract:
- case BuiltinType::SatShortAccum:
- case BuiltinType::SatAccum:
- case BuiltinType::SatLongAccum:
- case BuiltinType::SatUShortAccum:
- case BuiltinType::SatUAccum:
- case BuiltinType::SatULongAccum:
- case BuiltinType::SatShortFract:
- case BuiltinType::SatFract:
- case BuiltinType::SatLongFract:
- case BuiltinType::SatUShortFract:
- case BuiltinType::SatUFract:
- case BuiltinType::SatULongFract:
- case BuiltinType::OCLIntelSubgroupAVCMcePayload:
- case BuiltinType::OCLIntelSubgroupAVCImePayload:
- case BuiltinType::OCLIntelSubgroupAVCRefPayload:
- case BuiltinType::OCLIntelSubgroupAVCSicPayload:
- case BuiltinType::OCLIntelSubgroupAVCMceResult:
- case BuiltinType::OCLIntelSubgroupAVCImeResult:
- case BuiltinType::OCLIntelSubgroupAVCRefResult:
- case BuiltinType::OCLIntelSubgroupAVCSicResult:
- case BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
- case BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
- case BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
- case BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
+ case clang::BuiltinType::Void:
+ case clang::BuiltinType::Half:
+ case clang::BuiltinType::ObjCId:
+ case clang::BuiltinType::ObjCClass:
+ case clang::BuiltinType::ObjCSel:
+ case clang::BuiltinType::OMPArraySection:
+ case clang::BuiltinType::Dependent:
+ case clang::BuiltinType::Overload:
+ case clang::BuiltinType::BoundMember:
+ case clang::BuiltinType::PseudoObject:
+ case clang::BuiltinType::UnknownAny:
+ case clang::BuiltinType::BuiltinFn:
+ case clang::BuiltinType::ARCUnbridgedCast:
+ case clang::BuiltinType::OCLImage1dRO:
+ case clang::BuiltinType::OCLImage1dArrayRO:
+ case clang::BuiltinType::OCLImage1dBufferRO:
+ case clang::BuiltinType::OCLImage2dRO:
+ case clang::BuiltinType::OCLImage2dArrayRO:
+ case clang::BuiltinType::OCLImage2dDepthRO:
+ case clang::BuiltinType::OCLImage2dArrayDepthRO:
+ case clang::BuiltinType::OCLImage2dMSAARO:
+ case clang::BuiltinType::OCLImage2dArrayMSAARO:
+ case clang::BuiltinType::OCLImage2dMSAADepthRO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRO:
+ case clang::BuiltinType::OCLImage3dRO:
+ case clang::BuiltinType::OCLImage1dWO:
+ case clang::BuiltinType::OCLImage1dArrayWO:
+ case clang::BuiltinType::OCLImage1dBufferWO:
+ case clang::BuiltinType::OCLImage2dWO:
+ case clang::BuiltinType::OCLImage2dArrayWO:
+ case clang::BuiltinType::OCLImage2dDepthWO:
+ case clang::BuiltinType::OCLImage2dArrayDepthWO:
+ case clang::BuiltinType::OCLImage2dMSAAWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAAWO:
+ case clang::BuiltinType::OCLImage2dMSAADepthWO:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthWO:
+ case clang::BuiltinType::OCLImage3dWO:
+ case clang::BuiltinType::OCLImage1dRW:
+ case clang::BuiltinType::OCLImage1dArrayRW:
+ case clang::BuiltinType::OCLImage1dBufferRW:
+ case clang::BuiltinType::OCLImage2dRW:
+ case clang::BuiltinType::OCLImage2dArrayRW:
+ case clang::BuiltinType::OCLImage2dDepthRW:
+ case clang::BuiltinType::OCLImage2dArrayDepthRW:
+ case clang::BuiltinType::OCLImage2dMSAARW:
+ case clang::BuiltinType::OCLImage2dArrayMSAARW:
+ case clang::BuiltinType::OCLImage2dMSAADepthRW:
+ case clang::BuiltinType::OCLImage2dArrayMSAADepthRW:
+ case clang::BuiltinType::OCLImage3dRW:
+ case clang::BuiltinType::OCLSampler:
+ case clang::BuiltinType::OCLEvent:
+ case clang::BuiltinType::OCLClkEvent:
+ case clang::BuiltinType::OCLQueue:
+ case clang::BuiltinType::OCLReserveID:
+ case clang::BuiltinType::ShortAccum:
+ case clang::BuiltinType::Accum:
+ case clang::BuiltinType::LongAccum:
+ case clang::BuiltinType::UShortAccum:
+ case clang::BuiltinType::UAccum:
+ case clang::BuiltinType::ULongAccum:
+ case clang::BuiltinType::ShortFract:
+ case clang::BuiltinType::Fract:
+ case clang::BuiltinType::LongFract:
+ case clang::BuiltinType::UShortFract:
+ case clang::BuiltinType::UFract:
+ case clang::BuiltinType::ULongFract:
+ case clang::BuiltinType::SatShortAccum:
+ case clang::BuiltinType::SatAccum:
+ case clang::BuiltinType::SatLongAccum:
+ case clang::BuiltinType::SatUShortAccum:
+ case clang::BuiltinType::SatUAccum:
+ case clang::BuiltinType::SatULongAccum:
+ case clang::BuiltinType::SatShortFract:
+ case clang::BuiltinType::SatFract:
+ case clang::BuiltinType::SatLongFract:
+ case clang::BuiltinType::SatUShortFract:
+ case clang::BuiltinType::SatUFract:
+ case clang::BuiltinType::SatULongFract:
+ case clang::BuiltinType::OCLIntelSubgroupAVCMcePayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImePayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCRefPayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCSicPayload:
+ case clang::BuiltinType::OCLIntelSubgroupAVCMceResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCRefResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCSicResult:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResultSingleRefStreamout:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeResultDualRefStreamout:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeSingleRefStreamin:
+ case clang::BuiltinType::OCLIntelSubgroupAVCImeDualRefStreamin:
return res;
}
break;
}
- case Type::Pointer:
- return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq, trans_create_node(c, NodeTypeNullLiteral));
+ case clang::Type::Pointer:
+ return trans_create_node_bin_op(c, res, BinOpTypeCmpNotEq,
+ trans_create_node_unsigned(c, 0));
- case Type::Typedef:
+ case clang::Type::Typedef:
{
- const TypedefType *typedef_ty = static_cast(ty);
- const TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
+ const clang::TypedefType *typedef_ty = static_cast(ty);
+ const clang::TypedefNameDecl *typedef_decl = typedef_ty->getDecl();
auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
if (existing_entry) {
return existing_entry->value;
@@ -2566,79 +2269,79 @@ static AstNode *trans_bool_expr(Context *c, ResultUsed result_used, TransScope *
return res;
}
- case Type::Enum:
+ case clang::Type::Enum:
{
- const EnumType *enum_ty = static_cast(ty);
+ const clang::EnumType *enum_ty = static_cast(ty);
AstNode *enum_type = resolve_enum_decl(c, enum_ty->getDecl());
return to_enum_zero_cmp(c, res, enum_type);
}
- case Type::Elaborated:
+ case clang::Type::Elaborated:
{
- const ElaboratedType *elaborated_ty = static_cast(ty);
+ const clang::ElaboratedType *elaborated_ty = static_cast(ty);
switch (elaborated_ty->getKeyword()) {
- case ETK_Enum: {
- AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginLoc());
+ case clang::ETK_Enum: {
+ AstNode *enum_type = trans_qual_type(c, elaborated_ty->getNamedType(), expr->getBeginloc());
return to_enum_zero_cmp(c, res, enum_type);
}
- case ETK_Struct:
- case ETK_Union:
- case ETK_Interface:
- case ETK_Class:
- case ETK_Typename:
- case ETK_None:
+ case clang::ETK_Struct:
+ case clang::ETK_Union:
+ case clang::ETK_Interface:
+ case clang::ETK_Class:
+ case clang::ETK_Typename:
+ case clang::ETK_None:
return res;
}
}
- case Type::FunctionProto:
- case Type::Record:
- case Type::ConstantArray:
- case Type::Paren:
- case Type::Decayed:
- case Type::Attributed:
- case Type::IncompleteArray:
- case Type::BlockPointer:
- case Type::LValueReference:
- case Type::RValueReference:
- case Type::MemberPointer:
- case Type::VariableArray:
- case Type::DependentSizedArray:
- case Type::DependentSizedExtVector:
- case Type::Vector:
- case Type::ExtVector:
- case Type::FunctionNoProto:
- case Type::UnresolvedUsing:
- case Type::Adjusted:
- case Type::TypeOfExpr:
- case Type::TypeOf:
- case Type::Decltype:
- case Type::UnaryTransform:
- case Type::TemplateTypeParm:
- case Type::SubstTemplateTypeParm:
- case Type::SubstTemplateTypeParmPack:
- case Type::TemplateSpecialization:
- case Type::Auto:
- case Type::InjectedClassName:
- case Type::DependentName:
- case Type::DependentTemplateSpecialization:
- case Type::PackExpansion:
- case Type::ObjCObject:
- case Type::ObjCInterface:
- case Type::Complex:
- case Type::ObjCObjectPointer:
- case Type::Atomic:
- case Type::Pipe:
- case Type::ObjCTypeParam:
- case Type::DeducedTemplateSpecialization:
- case Type::DependentAddressSpace:
- case Type::DependentVector:
+ case clang::Type::FunctionProto:
+ case clang::Type::Record:
+ case clang::Type::ConstantArray:
+ case clang::Type::Paren:
+ case clang::Type::Decayed:
+ case clang::Type::Attributed:
+ case clang::Type::IncompleteArray:
+ case clang::Type::BlockPointer:
+ case clang::Type::LValueReference:
+ case clang::Type::RValueReference:
+ case clang::Type::MemberPointer:
+ case clang::Type::VariableArray:
+ case clang::Type::DependentSizedArray:
+ case clang::Type::DependentSizedExtVector:
+ case clang::Type::Vector:
+ case clang::Type::ExtVector:
+ case clang::Type::FunctionNoProto:
+ case clang::Type::UnresolvedUsing:
+ case clang::Type::Adjusted:
+ case clang::Type::TypeOfExpr:
+ case clang::Type::TypeOf:
+ case clang::Type::Decltype:
+ case clang::Type::UnaryTransform:
+ case clang::Type::TemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParm:
+ case clang::Type::SubstTemplateTypeParmPack:
+ case clang::Type::TemplateSpecialization:
+ case clang::Type::Auto:
+ case clang::Type::InjectedClassName:
+ case clang::Type::DependentName:
+ case clang::Type::DependentTemplateSpecialization:
+ case clang::Type::PackExpansion:
+ case clang::Type::ObjCObject:
+ case clang::Type::ObjCInterface:
+ case clang::Type::Complex:
+ case clang::Type::ObjCObjectPointer:
+ case clang::Type::Atomic:
+ case clang::Type::Pipe:
+ case clang::Type::ObjCTypeParam:
+ case clang::Type::DeducedTemplateSpecialization:
+ case clang::Type::DependentAddressSpace:
+ case clang::Type::DependentVector:
return res;
}
zig_unreachable();
}
-static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt *stmt) {
+static AstNode *trans_while_loop(Context *c, TransScope *scope, const clang::WhileStmt *stmt) {
TransScopeWhile *while_scope = trans_scope_while_create(c, scope);
while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, scope, stmt->getCond(), TransRValue);
@@ -2653,7 +2356,7 @@ static AstNode *trans_while_loop(Context *c, TransScope *scope, const WhileStmt
return while_scope->node;
}
-static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *stmt) {
+static AstNode *trans_if_statement(Context *c, TransScope *scope, const clang::IfStmt *stmt) {
// if (c) t
// if (c) t else e
AstNode *if_node = trans_create_node(c, NodeTypeIfBoolExpr);
@@ -2675,7 +2378,7 @@ static AstNode *trans_if_statement(Context *c, TransScope *scope, const IfStmt *
return if_node;
}
-static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const CallExpr *stmt) {
+static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::CallExpr *stmt) {
AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
AstNode *callee_raw_node = trans_expr(c, ResultUsedYes, scope, stmt->getCallee(), TransRValue);
@@ -2683,16 +2386,16 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
return nullptr;
bool is_ptr = false;
- const FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);
+ const clang::FunctionProtoType *fn_ty = qual_type_get_fn_proto(stmt->getCallee()->getType(), &is_ptr);
AstNode *callee_node = nullptr;
if (is_ptr && fn_ty) {
- if (stmt->getCallee()->getStmtClass() == Stmt::ImplicitCastExprClass) {
- const ImplicitCastExpr *implicit_cast = static_cast(stmt->getCallee());
- if (implicit_cast->getCastKind() == CK_FunctionToPointerDecay) {
- if (implicit_cast->getSubExpr()->getStmtClass() == Stmt::DeclRefExprClass) {
- const DeclRefExpr *decl_ref = static_cast(implicit_cast->getSubExpr());
- const Decl *decl = decl_ref->getFoundDecl();
- if (decl->getKind() == Decl::Function) {
+ if (stmt->getCallee()->getStmtClass() == clang::Stmt::ImplicitCastExprClass) {
+ const clang::ImplicitCastExpr *implicit_cast = static_cast(stmt->getCallee());
+ if (implicit_cast->getCastKind() == clang::CK_FunctionToPointerDecay) {
+ if (implicit_cast->getSubExpr()->getStmtClass() == clang::Stmt::DeclRefExprClass) {
+ const clang::DeclRefExpr *decl_ref = static_cast(implicit_cast->getSubExpr());
+ const clang::Decl *decl = decl_ref->getFoundDecl();
+ if (decl->getKind() == clang::Decl::Function) {
callee_node = callee_raw_node;
}
}
@@ -2708,7 +2411,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
node->data.fn_call_expr.fn_ref_expr = callee_node;
unsigned num_args = stmt->getNumArgs();
- const Expr * const* args = stmt->getArgs();
+ const clang::Expr * const* args = stmt->getArgs();
for (unsigned i = 0; i < num_args; i += 1) {
AstNode *arg_node = trans_expr(c, ResultUsedYes, scope, args[i], TransRValue);
if (arg_node == nullptr)
@@ -2724,7 +2427,7 @@ static AstNode *trans_call_expr(Context *c, ResultUsed result_used, TransScope *
return node;
}
-static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExpr *stmt) {
+static AstNode *trans_member_expr(Context *c, TransScope *scope, const clang::MemberExpr *stmt) {
AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
if (container_node == nullptr)
return nullptr;
@@ -2739,7 +2442,7 @@ static AstNode *trans_member_expr(Context *c, TransScope *scope, const MemberExp
return node;
}
-static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const ArraySubscriptExpr *stmt) {
+static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const clang::ArraySubscriptExpr *stmt) {
AstNode *container_node = trans_expr(c, ResultUsedYes, scope, stmt->getBase(), TransRValue);
if (container_node == nullptr)
return nullptr;
@@ -2756,7 +2459,7 @@ static AstNode *trans_array_subscript_expr(Context *c, TransScope *scope, const
}
static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, TransScope *scope,
- const CStyleCastExpr *stmt, TransLRValue lrvalue)
+ const clang::CStyleCastExpr *stmt, TransLRValue lrvalue)
{
AstNode *sub_expr_node = trans_expr(c, result_used, scope, stmt->getSubExpr(), lrvalue);
if (sub_expr_node == nullptr)
@@ -2766,7 +2469,7 @@ static AstNode *trans_c_style_cast_expr(Context *c, ResultUsed result_used, Tran
}
static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scope,
- const UnaryExprOrTypeTraitExpr *stmt)
+ const clang::UnaryExprOrTypeTraitExpr *stmt)
{
AstNode *type_node = trans_qual_type(c, stmt->getTypeOfArgument(), stmt->getBeginLoc());
if (type_node == nullptr)
@@ -2777,14 +2480,14 @@ static AstNode *trans_unary_expr_or_type_trait_expr(Context *c, TransScope *scop
return node;
}
-static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt *stmt) {
+static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const clang::DoStmt *stmt) {
TransScopeWhile *while_scope = trans_scope_while_create(c, parent_scope);
while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
AstNode *body_node;
TransScope *child_scope;
- if (stmt->getBody()->getStmtClass() == Stmt::CompoundStmtClass) {
+ if (stmt->getBody()->getStmtClass() == clang::Stmt::CompoundStmtClass) {
// there's already a block in C, so we'll append our condition to it.
// c: do {
// c: a;
@@ -2837,11 +2540,11 @@ static AstNode *trans_do_loop(Context *c, TransScope *parent_scope, const DoStmt
return while_scope->node;
}
-static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForStmt *stmt) {
+static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const clang::ForStmt *stmt) {
AstNode *loop_block_node;
TransScopeWhile *while_scope;
TransScope *cond_scope;
- const Stmt *init_stmt = stmt->getInit();
+ const clang::Stmt *init_stmt = stmt->getInit();
if (init_stmt == nullptr) {
while_scope = trans_scope_while_create(c, parent_scope);
loop_block_node = while_scope->node;
@@ -2862,12 +2565,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
child_scope->node->data.block.statements.append(while_scope->node);
}
- const Stmt *cond_stmt = stmt->getCond();
+ const clang::Stmt *cond_stmt = stmt->getCond();
if (cond_stmt == nullptr) {
while_scope->node->data.while_expr.condition = trans_create_node_bool(c, true);
} else {
- if (Expr::classof(cond_stmt)) {
- const Expr *cond_expr = static_cast(cond_stmt);
+ if (clang::Expr::classof(cond_stmt)) {
+ const clang::Expr *cond_expr = static_cast(cond_stmt);
while_scope->node->data.while_expr.condition = trans_bool_expr(c, ResultUsedYes, cond_scope, cond_expr, TransRValue);
if (while_scope->node->data.while_expr.condition == nullptr)
@@ -2880,7 +2583,7 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
}
}
- const Stmt *inc_stmt = stmt->getInc();
+ const clang::Stmt *inc_stmt = stmt->getInc();
if (inc_stmt != nullptr) {
AstNode *inc_node;
TransScope *inc_scope = trans_stmt(c, cond_scope, inc_stmt, &inc_node);
@@ -2903,12 +2606,12 @@ static AstNode *trans_for_loop(Context *c, TransScope *parent_scope, const ForSt
return loop_block_node;
}
-static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const SwitchStmt *stmt) {
+static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const clang::SwitchStmt *stmt) {
TransScopeBlock *block_scope = trans_scope_block_create(c, parent_scope);
TransScopeSwitch *switch_scope;
- const DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
+ const clang::DeclStmt *var_decl_stmt = stmt->getConditionVariableDeclStmt();
if (var_decl_stmt == nullptr) {
switch_scope = trans_scope_switch_create(c, &block_scope->base);
} else {
@@ -2927,7 +2630,7 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
switch_scope->end_label_name = end_label_name;
block_scope->node->data.block.name = end_label_name;
- const Expr *cond_expr = stmt->getCond();
+ const clang::Expr *cond_expr = stmt->getCond();
assert(cond_expr != nullptr);
AstNode *expr_node = trans_expr(c, ResultUsedYes, &block_scope->base, cond_expr, TransRValue);
@@ -2936,9 +2639,9 @@ static AstNode *trans_switch_stmt(Context *c, TransScope *parent_scope, const Sw
switch_scope->switch_node->data.switch_expr.expr = expr_node;
AstNode *body_node;
- const Stmt *body_stmt = stmt->getBody();
- if (body_stmt->getStmtClass() == Stmt::CompoundStmtClass) {
- if (trans_compound_stmt_inline(c, &switch_scope->base, (const CompoundStmt *)body_stmt,
+ const clang::Stmt *body_stmt = stmt->getBody();
+ if (body_stmt->getStmtClass() == clang::Stmt::CompoundStmtClass) {
+ if (trans_compound_stmt_inline(c, &switch_scope->base, (const clang::CompoundStmt *)body_stmt,
block_scope->node, nullptr))
{
return nullptr;
@@ -2970,7 +2673,7 @@ static TransScopeSwitch *trans_scope_switch_find(TransScope *scope) {
return nullptr;
}
-static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStmt *stmt, AstNode **out_node,
+static int trans_switch_case(Context *c, TransScope *parent_scope, const clang::CaseStmt *stmt, AstNode **out_node,
TransScope **out_scope) {
*out_node = nullptr;
@@ -3015,7 +2718,7 @@ static int trans_switch_case(Context *c, TransScope *parent_scope, const CaseStm
return ErrorNone;
}
-static int trans_switch_default(Context *c, TransScope *parent_scope, const DefaultStmt *stmt, AstNode **out_node,
+static int trans_switch_default(Context *c, TransScope *parent_scope, const clang::DefaultStmt *stmt, AstNode **out_node,
TransScope **out_scope)
{
*out_node = nullptr;
@@ -3052,25 +2755,27 @@ static int trans_switch_default(Context *c, TransScope *parent_scope, const Defa
return ErrorNone;
}
-static AstNode *trans_string_literal(Context *c, TransScope *scope, const StringLiteral *stmt) {
+static AstNode *trans_string_literal(Context *c, TransScope *scope, const clang::StringLiteral *stmt) {
switch (stmt->getKind()) {
- case StringLiteral::Ascii:
- case StringLiteral::UTF8:
+ case clang::StringLiteral::Ascii:
+ case clang::StringLiteral::UTF8:
return trans_create_node_str_lit_c(c, string_ref_to_buf(stmt->getString()));
- case StringLiteral::UTF16:
+ case clang::StringLiteral::UTF16:
emit_warning(c, stmt->getBeginLoc(), "TODO support UTF16 string literals");
return nullptr;
- case StringLiteral::UTF32:
+ case clang::StringLiteral::UTF32:
emit_warning(c, stmt->getBeginLoc(), "TODO support UTF32 string literals");
+ case clang::StringLiteral::UTF32:
+ emit_warning(c, stmt->getLocStart(), "TODO support UTF32 string literals");
return nullptr;
- case StringLiteral::Wide:
+ case clang::StringLiteral::Wide:
emit_warning(c, stmt->getBeginLoc(), "TODO support wide string literals");
return nullptr;
}
zig_unreachable();
}
-static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt *stmt) {
+static AstNode *trans_break_stmt(Context *c, TransScope *scope, const clang::BreakStmt *stmt) {
TransScope *cur_scope = scope;
while (cur_scope != nullptr) {
if (cur_scope->id == TransScopeIdWhile) {
@@ -3084,7 +2789,7 @@ static AstNode *trans_break_stmt(Context *c, TransScope *scope, const BreakStmt
zig_unreachable();
}
-static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const ContinueStmt *stmt) {
+static AstNode *trans_continue_stmt(Context *c, TransScope *scope, const clang::ContinueStmt *stmt) {
return trans_create_node(c, NodeTypeContinue);
}
@@ -3097,47 +2802,47 @@ static int wrap_stmt(AstNode **out_node, TransScope **out_scope, TransScope *in_
return ErrorNone;
}
-static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
+static int trans_stmt_extra(Context *c, TransScope *scope, const clang::Stmt *stmt,
ResultUsed result_used, TransLRValue lrvalue,
AstNode **out_node, TransScope **out_child_scope,
TransScope **out_node_scope)
{
- Stmt::StmtClass sc = stmt->getStmtClass();
+ clang::Stmt::StmtClass sc = stmt->getStmtClass();
switch (sc) {
- case Stmt::ReturnStmtClass:
+ case clang::Stmt::ReturnStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_return_stmt(c, scope, (const ReturnStmt *)stmt));
- case Stmt::CompoundStmtClass:
+ trans_return_stmt(c, scope, (const clang::ReturnStmt *)stmt));
+ case clang::Stmt::CompoundStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_compound_stmt(c, scope, (const CompoundStmt *)stmt, out_node_scope));
- case Stmt::IntegerLiteralClass:
+ trans_compound_stmt(c, scope, (const clang::CompoundStmt *)stmt, out_node_scope));
+ case clang::Stmt::IntegerLiteralClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_integer_literal(c, (const IntegerLiteral *)stmt));
- case Stmt::ConditionalOperatorClass:
+ trans_integer_literal(c, (const clang::IntegerLiteral *)stmt));
+ case clang::Stmt::ConditionalOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_conditional_operator(c, result_used, scope, (const ConditionalOperator *)stmt));
- case Stmt::BinaryOperatorClass:
+ trans_conditional_operator(c, result_used, scope, (const clang::ConditionalOperator *)stmt));
+ case clang::Stmt::BinaryOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_binary_operator(c, result_used, scope, (const BinaryOperator *)stmt));
- case Stmt::CompoundAssignOperatorClass:
+ trans_binary_operator(c, result_used, scope, (const clang::BinaryOperator *)stmt));
+ case clang::Stmt::CompoundAssignOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_compound_assign_operator(c, result_used, scope, (const CompoundAssignOperator *)stmt));
- case Stmt::ImplicitCastExprClass:
+ trans_compound_assign_operator(c, result_used, scope, (const clang::CompoundAssignOperator *)stmt));
+ case clang::Stmt::ImplicitCastExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_implicit_cast_expr(c, scope, (const ImplicitCastExpr *)stmt));
- case Stmt::DeclRefExprClass:
+ trans_implicit_cast_expr(c, scope, (const clang::ImplicitCastExpr *)stmt));
+ case clang::Stmt::DeclRefExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_decl_ref_expr(c, scope, (const DeclRefExpr *)stmt, lrvalue));
- case Stmt::UnaryOperatorClass:
+ trans_decl_ref_expr(c, scope, (const clang::DeclRefExpr *)stmt, lrvalue));
+ case clang::Stmt::UnaryOperatorClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_unary_operator(c, result_used, scope, (const UnaryOperator *)stmt));
- case Stmt::DeclStmtClass:
- return trans_local_declaration(c, scope, (const DeclStmt *)stmt, out_node, out_child_scope);
- case Stmt::DoStmtClass:
- case Stmt::WhileStmtClass: {
- AstNode *while_node = sc == Stmt::DoStmtClass
- ? trans_do_loop(c, scope, (const DoStmt *)stmt)
- : trans_while_loop(c, scope, (const WhileStmt *)stmt);
+ trans_unary_operator(c, result_used, scope, (const clang::UnaryOperator *)stmt));
+ case clang::Stmt::DeclStmtClass:
+ return trans_local_declaration(c, scope, (const clang::DeclStmt *)stmt, out_node, out_child_scope);
+ case clang::Stmt::DoStmtClass:
+ case clang::Stmt::WhileStmtClass: {
+ AstNode *while_node = sc == clang::Stmt::DoStmtClass
+ ? trans_do_loop(c, scope, (const clang::DoStmt *)stmt)
+ : trans_while_loop(c, scope, (const clang::WhileStmt *)stmt);
if (while_node == nullptr)
return ErrorUnexpected;
@@ -3148,567 +2853,63 @@ static int trans_stmt_extra(Context *c, TransScope *scope, const Stmt *stmt,
return wrap_stmt(out_node, out_child_scope, scope, while_node);
}
- case Stmt::IfStmtClass:
+ case clang::Stmt::IfStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_if_statement(c, scope, (const IfStmt *)stmt));
- case Stmt::CallExprClass:
+ trans_if_statement(c, scope, (const clang::IfStmt *)stmt));
+ case clang::Stmt::CallExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_call_expr(c, result_used, scope, (const CallExpr *)stmt));
- case Stmt::NullStmtClass:
+ trans_call_expr(c, result_used, scope, (const clang::CallExpr *)stmt));
+ case clang::Stmt::NullStmtClass:
*out_node = nullptr;
*out_child_scope = scope;
return ErrorNone;
- case Stmt::MemberExprClass:
+ case clang::Stmt::MemberExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_member_expr(c, scope, (const MemberExpr *)stmt));
- case Stmt::ArraySubscriptExprClass:
+ trans_member_expr(c, scope, (const clang::MemberExpr *)stmt));
+ case clang::Stmt::ArraySubscriptExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_array_subscript_expr(c, scope, (const ArraySubscriptExpr *)stmt));
- case Stmt::CStyleCastExprClass:
+ trans_array_subscript_expr(c, scope, (const clang::ArraySubscriptExpr *)stmt));
+ case clang::Stmt::CStyleCastExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_c_style_cast_expr(c, result_used, scope, (const CStyleCastExpr *)stmt, lrvalue));
- case Stmt::UnaryExprOrTypeTraitExprClass:
+ trans_c_style_cast_expr(c, result_used, scope, (const clang::CStyleCastExpr *)stmt, lrvalue));
+ case clang::Stmt::UnaryExprOrTypeTraitExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_unary_expr_or_type_trait_expr(c, scope, (const UnaryExprOrTypeTraitExpr *)stmt));
- case Stmt::ForStmtClass: {
- AstNode *node = trans_for_loop(c, scope, (const ForStmt *)stmt);
+ trans_unary_expr_or_type_trait_expr(c, scope, (const clang::UnaryExprOrTypeTraitExpr *)stmt));
+ case clang::Stmt::ForStmtClass: {
+ AstNode *node = trans_for_loop(c, scope, (const clang::ForStmt *)stmt);
return wrap_stmt(out_node, out_child_scope, scope, node);
}
- case Stmt::StringLiteralClass:
+ case clang::Stmt::StringLiteralClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_string_literal(c, scope, (const StringLiteral *)stmt));
- case Stmt::BreakStmtClass:
+ trans_string_literal(c, scope, (const clang::StringLiteral *)stmt));
+ case clang::Stmt::BreakStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_break_stmt(c, scope, (const BreakStmt *)stmt));
- case Stmt::ContinueStmtClass:
+ trans_break_stmt(c, scope, (const clang::BreakStmt *)stmt));
+ case clang::Stmt::ContinueStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_continue_stmt(c, scope, (const ContinueStmt *)stmt));
- case Stmt::ParenExprClass:
+ trans_continue_stmt(c, scope, (const clang::ContinueStmt *)stmt));
+ case clang::Stmt::ParenExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_expr(c, result_used, scope, ((const ParenExpr*)stmt)->getSubExpr(), lrvalue));
- case Stmt::SwitchStmtClass:
+ trans_expr(c, result_used, scope, ((const clang::ParenExpr*)stmt)->getSubExpr(), lrvalue));
+ case clang::Stmt::SwitchStmtClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_switch_stmt(c, scope, (const SwitchStmt *)stmt));
- case Stmt::CaseStmtClass:
- return trans_switch_case(c, scope, (const CaseStmt *)stmt, out_node, out_child_scope);
- case Stmt::DefaultStmtClass:
- return trans_switch_default(c, scope, (const DefaultStmt *)stmt, out_node, out_child_scope);
- case Stmt::ConstantExprClass:
+ trans_switch_stmt(c, scope, (const clang::SwitchStmt *)stmt));
+ case clang::Stmt::CaseStmtClass:
+ return trans_switch_case(c, scope, (const clang::CaseStmt *)stmt, out_node, out_child_scope);
+ case clang::Stmt::DefaultStmtClass:
+ return trans_switch_default(c, scope, (const clang::DefaultStmt *)stmt, out_node, out_child_scope);
+ case clang::Stmt::ConstantExprClass:
return wrap_stmt(out_node, out_child_scope, scope,
- trans_constant_expr(c, (const ConstantExpr *)stmt));
- case Stmt::NoStmtClass:
+ trans_constant_expr(c, (const clang::ConstantExpr *)stmt));
+ case clang::Stmt::NoStmtClass:
emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoStmtClass");
return ErrorUnexpected;
- case Stmt::GCCAsmStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C GCCAsmStmtClass");
- return ErrorUnexpected;
- case Stmt::MSAsmStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSAsmStmtClass");
- return ErrorUnexpected;
- case Stmt::AttributedStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C AttributedStmtClass");
- return ErrorUnexpected;
- case Stmt::CXXCatchStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXCatchStmtClass");
- return ErrorUnexpected;
- case Stmt::CXXForRangeStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXForRangeStmtClass");
- return ErrorUnexpected;
- case Stmt::CXXTryStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTryStmtClass");
- return ErrorUnexpected;
- case Stmt::CapturedStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CapturedStmtClass");
- return ErrorUnexpected;
- case Stmt::CoreturnStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoreturnStmtClass");
- return ErrorUnexpected;
- case Stmt::CoroutineBodyStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoroutineBodyStmtClass");
- return ErrorUnexpected;
- case Stmt::BinaryConditionalOperatorClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C BinaryConditionalOperatorClass");
- return ErrorUnexpected;
- case Stmt::AddrLabelExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C AddrLabelExprClass");
- return ErrorUnexpected;
- case Stmt::ArrayInitIndexExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitIndexExprClass");
- return ErrorUnexpected;
- case Stmt::ArrayInitLoopExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayInitLoopExprClass");
- return ErrorUnexpected;
- case Stmt::ArrayTypeTraitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ArrayTypeTraitExprClass");
- return ErrorUnexpected;
- case Stmt::AsTypeExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C AsTypeExprClass");
- return ErrorUnexpected;
- case Stmt::AtomicExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C AtomicExprClass");
- return ErrorUnexpected;
- case Stmt::BlockExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C BlockExprClass");
- return ErrorUnexpected;
- case Stmt::CXXBindTemporaryExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBindTemporaryExprClass");
- return ErrorUnexpected;
- case Stmt::CXXBoolLiteralExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXBoolLiteralExprClass");
- return ErrorUnexpected;
- case Stmt::CXXConstructExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstructExprClass");
- return ErrorUnexpected;
- case Stmt::CXXTemporaryObjectExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTemporaryObjectExprClass");
- return ErrorUnexpected;
- case Stmt::CXXDefaultArgExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultArgExprClass");
- return ErrorUnexpected;
- case Stmt::CXXDefaultInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDefaultInitExprClass");
- return ErrorUnexpected;
- case Stmt::CXXDeleteExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDeleteExprClass");
- return ErrorUnexpected;
- case Stmt::CXXDependentScopeMemberExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDependentScopeMemberExprClass");
- return ErrorUnexpected;
- case Stmt::CXXFoldExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFoldExprClass");
- return ErrorUnexpected;
- case Stmt::CXXInheritedCtorInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXInheritedCtorInitExprClass");
- return ErrorUnexpected;
- case Stmt::CXXNewExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNewExprClass");
- return ErrorUnexpected;
- case Stmt::CXXNoexceptExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNoexceptExprClass");
- return ErrorUnexpected;
- case Stmt::CXXNullPtrLiteralExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXNullPtrLiteralExprClass");
- return ErrorUnexpected;
- case Stmt::CXXPseudoDestructorExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXPseudoDestructorExprClass");
- return ErrorUnexpected;
- case Stmt::CXXScalarValueInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXScalarValueInitExprClass");
- return ErrorUnexpected;
- case Stmt::CXXStdInitializerListExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStdInitializerListExprClass");
- return ErrorUnexpected;
- case Stmt::CXXThisExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThisExprClass");
- return ErrorUnexpected;
- case Stmt::CXXThrowExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXThrowExprClass");
- return ErrorUnexpected;
- case Stmt::CXXTypeidExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXTypeidExprClass");
- return ErrorUnexpected;
- case Stmt::CXXUnresolvedConstructExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUnresolvedConstructExprClass");
- return ErrorUnexpected;
- case Stmt::CXXUuidofExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXUuidofExprClass");
- return ErrorUnexpected;
- case Stmt::CUDAKernelCallExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CUDAKernelCallExprClass");
- return ErrorUnexpected;
- case Stmt::CXXMemberCallExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXMemberCallExprClass");
- return ErrorUnexpected;
- case Stmt::CXXOperatorCallExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXOperatorCallExprClass");
- return ErrorUnexpected;
- case Stmt::UserDefinedLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UserDefinedLiteralClass");
- return ErrorUnexpected;
- case Stmt::CXXFunctionalCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXFunctionalCastExprClass");
- return ErrorUnexpected;
- case Stmt::CXXConstCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXConstCastExprClass");
- return ErrorUnexpected;
- case Stmt::CXXDynamicCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXDynamicCastExprClass");
- return ErrorUnexpected;
- case Stmt::CXXReinterpretCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXReinterpretCastExprClass");
- return ErrorUnexpected;
- case Stmt::CXXStaticCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CXXStaticCastExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCBridgedCastExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBridgedCastExprClass");
- return ErrorUnexpected;
- case Stmt::CharacterLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CharacterLiteralClass");
- return ErrorUnexpected;
- case Stmt::ChooseExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ChooseExprClass");
- return ErrorUnexpected;
- case Stmt::CompoundLiteralExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CompoundLiteralExprClass");
- return ErrorUnexpected;
- case Stmt::ConvertVectorExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ConvertVectorExprClass");
- return ErrorUnexpected;
- case Stmt::CoawaitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoawaitExprClass");
- return ErrorUnexpected;
- case Stmt::CoyieldExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C CoyieldExprClass");
- return ErrorUnexpected;
- case Stmt::DependentCoawaitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentCoawaitExprClass");
- return ErrorUnexpected;
- case Stmt::DependentScopeDeclRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C DependentScopeDeclRefExprClass");
- return ErrorUnexpected;
- case Stmt::DesignatedInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitExprClass");
- return ErrorUnexpected;
- case Stmt::DesignatedInitUpdateExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C DesignatedInitUpdateExprClass");
- return ErrorUnexpected;
- case Stmt::ExprWithCleanupsClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExprWithCleanupsClass");
- return ErrorUnexpected;
- case Stmt::ExpressionTraitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExpressionTraitExprClass");
- return ErrorUnexpected;
- case Stmt::ExtVectorElementExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ExtVectorElementExprClass");
- return ErrorUnexpected;
- case Stmt::FloatingLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FloatingLiteralClass");
- return ErrorUnexpected;
- case Stmt::FunctionParmPackExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FunctionParmPackExprClass");
- return ErrorUnexpected;
- case Stmt::GNUNullExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C GNUNullExprClass");
- return ErrorUnexpected;
- case Stmt::GenericSelectionExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C GenericSelectionExprClass");
- return ErrorUnexpected;
- case Stmt::ImaginaryLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImaginaryLiteralClass");
- return ErrorUnexpected;
- case Stmt::ImplicitValueInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ImplicitValueInitExprClass");
- return ErrorUnexpected;
- case Stmt::InitListExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C InitListExprClass");
- return ErrorUnexpected;
- case Stmt::LambdaExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C LambdaExprClass");
- return ErrorUnexpected;
- case Stmt::MSPropertyRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertyRefExprClass");
- return ErrorUnexpected;
- case Stmt::MSPropertySubscriptExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSPropertySubscriptExprClass");
- return ErrorUnexpected;
- case Stmt::MaterializeTemporaryExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MaterializeTemporaryExprClass");
- return ErrorUnexpected;
- case Stmt::NoInitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C NoInitExprClass");
- return ErrorUnexpected;
- case Stmt::OMPArraySectionExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPArraySectionExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCArrayLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCArrayLiteralClass");
- return ErrorUnexpected;
- case Stmt::ObjCAvailabilityCheckExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAvailabilityCheckExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCBoolLiteralExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoolLiteralExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCBoxedExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCBoxedExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCDictionaryLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCDictionaryLiteralClass");
- return ErrorUnexpected;
- case Stmt::ObjCEncodeExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCEncodeExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCIndirectCopyRestoreExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIndirectCopyRestoreExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCIsaExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIsaExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCIvarRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCIvarRefExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCMessageExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCMessageExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCPropertyRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCPropertyRefExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCProtocolExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCProtocolExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCSelectorExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSelectorExprClass");
- return ErrorUnexpected;
- case Stmt::ObjCStringLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCStringLiteralClass");
- return ErrorUnexpected;
- case Stmt::ObjCSubscriptRefExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCSubscriptRefExprClass");
- return ErrorUnexpected;
- case Stmt::OffsetOfExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OffsetOfExprClass");
- return ErrorUnexpected;
- case Stmt::OpaqueValueExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OpaqueValueExprClass");
- return ErrorUnexpected;
- case Stmt::UnresolvedLookupExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedLookupExprClass");
- return ErrorUnexpected;
- case Stmt::UnresolvedMemberExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C UnresolvedMemberExprClass");
- return ErrorUnexpected;
- case Stmt::PackExpansionExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C PackExpansionExprClass");
- return ErrorUnexpected;
- case Stmt::ParenListExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ParenListExprClass");
- return ErrorUnexpected;
- case Stmt::PredefinedExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C PredefinedExprClass");
- return ErrorUnexpected;
- case Stmt::PseudoObjectExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C PseudoObjectExprClass");
- return ErrorUnexpected;
- case Stmt::ShuffleVectorExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ShuffleVectorExprClass");
- return ErrorUnexpected;
- case Stmt::SizeOfPackExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SizeOfPackExprClass");
- return ErrorUnexpected;
- case Stmt::StmtExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C StmtExprClass");
- return ErrorUnexpected;
- case Stmt::SubstNonTypeTemplateParmExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmExprClass");
- return ErrorUnexpected;
- case Stmt::SubstNonTypeTemplateParmPackExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SubstNonTypeTemplateParmPackExprClass");
- return ErrorUnexpected;
- case Stmt::TypeTraitExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypeTraitExprClass");
- return ErrorUnexpected;
- case Stmt::TypoExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C TypoExprClass");
- return ErrorUnexpected;
- case Stmt::VAArgExprClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C VAArgExprClass");
- return ErrorUnexpected;
- case Stmt::GotoStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C GotoStmtClass");
- return ErrorUnexpected;
- case Stmt::IndirectGotoStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C IndirectGotoStmtClass");
- return ErrorUnexpected;
- case Stmt::LabelStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C LabelStmtClass");
- return ErrorUnexpected;
- case Stmt::MSDependentExistsStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C MSDependentExistsStmtClass");
- return ErrorUnexpected;
- case Stmt::OMPAtomicDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPAtomicDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPBarrierDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPBarrierDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPCancelDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancelDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPCancellationPointDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCancellationPointDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPCriticalDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPCriticalDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPFlushDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPFlushDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPDistributeDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPDistributeParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPDistributeParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeParallelForSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPDistributeSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPDistributeSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPForSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelForSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDistributeDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeParallelForSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDistributeSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDistributeSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTaskLoopDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTaskLoopSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskLoopSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTeamsDistributeDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTeamsDistributeParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeParallelForSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTeamsDistributeSimdDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDistributeSimdDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPMasterDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPMasterDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPOrderedDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPOrderedDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPParallelDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPParallelSectionsDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPParallelSectionsDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPSectionDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPSectionsDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSectionsDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPSingleDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPSingleDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetDataDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDataDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetEnterDataDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetEnterDataDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetExitDataDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetExitDataDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetParallelDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetParallelForDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetParallelForDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetTeamsDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetTeamsDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTargetUpdateDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTargetUpdateDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTaskDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTaskgroupDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskgroupDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTaskwaitDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskwaitDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTaskyieldDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTaskyieldDirectiveClass");
- return ErrorUnexpected;
- case Stmt::OMPTeamsDirectiveClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C OMPTeamsDirectiveClass");
- return ErrorUnexpected;
- case Stmt::ObjCAtCatchStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtCatchStmtClass");
- return ErrorUnexpected;
- case Stmt::ObjCAtFinallyStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtFinallyStmtClass");
- return ErrorUnexpected;
- case Stmt::ObjCAtSynchronizedStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtSynchronizedStmtClass");
- return ErrorUnexpected;
- case Stmt::ObjCAtThrowStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtThrowStmtClass");
- return ErrorUnexpected;
- case Stmt::ObjCAtTryStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAtTryStmtClass");
- return ErrorUnexpected;
- case Stmt::ObjCAutoreleasePoolStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCAutoreleasePoolStmtClass");
- return ErrorUnexpected;
- case Stmt::ObjCForCollectionStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C ObjCForCollectionStmtClass");
- return ErrorUnexpected;
- case Stmt::SEHExceptStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHExceptStmtClass");
- return ErrorUnexpected;
- case Stmt::SEHFinallyStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHFinallyStmtClass");
- return ErrorUnexpected;
- case Stmt::SEHLeaveStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHLeaveStmtClass");
- return ErrorUnexpected;
- case Stmt::SEHTryStmtClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C SEHTryStmtClass");
- return ErrorUnexpected;
- case Stmt::FixedPointLiteralClass:
- emit_warning(c, stmt->getBeginLoc(), "TODO handle C FixedPointLiteralClass");
- return ErrorUnexpected;
}
zig_unreachable();
}
// Returns null if there was an error
-static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const Expr *expr,
+static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope, const clang::Expr *expr,
TransLRValue lrval)
{
AstNode *result_node;
@@ -3721,7 +2922,7 @@ static AstNode *trans_expr(Context *c, ResultUsed result_used, TransScope *scope
// Statements have no result and no concept of L or R value.
// Returns child scope, or null if there was an error
-static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, AstNode **out_node) {
+static TransScope *trans_stmt(Context *c, TransScope *scope, const clang::Stmt *stmt, AstNode **out_node) {
TransScope *child_scope;
if (trans_stmt_extra(c, scope, stmt, ResultUsedNo, TransRValue, out_node, &child_scope, nullptr)) {
return nullptr;
@@ -3729,7 +2930,7 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const Stmt *stmt, A
return child_scope;
}
-static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
+static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
Buf *fn_name = buf_create_from_str(decl_name(fn_decl));
if (get_global(c, fn_name)) {
@@ -3746,13 +2947,13 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
proto_node->data.fn_proto.name = fn_name;
proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
- StorageClass sc = fn_decl->getStorageClass();
- if (sc == SC_None) {
+ clang::StorageClass sc = fn_decl->getStorageClass();
+ if (sc == clang::SC_None) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false;
- } else if (sc == SC_Extern || sc == SC_Static) {
+ } else if (sc == clang::SC_Extern || sc == clang::SC_Static) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
- } else if (sc == SC_PrivateExtern) {
+ } else if (sc == clang::SC_PrivateExtern) {
emit_warning(c, fn_decl->getLocation(), "unsupported storage class: private extern");
return;
} else {
@@ -3764,7 +2965,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
AstNode *param_node = proto_node->data.fn_proto.params.at(i);
- const ParmVarDecl *param = fn_decl->getParamDecl(i);
+ const clang::ParmVarDecl *param = fn_decl->getParamDecl(i);
const char *name = decl_name(param);
Buf *proto_param_name;
@@ -3791,7 +2992,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
// actual function definition with body
c->ptr_params.clear();
- Stmt *body = fn_decl->getBody();
+ clang::Stmt *body = fn_decl->getBody();
AstNode *actual_body_node;
TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
if (result_scope == nullptr) {
@@ -3833,19 +3034,19 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
add_top_level_decl(c, fn_def_node->data.fn_def.fn_proto->data.fn_proto.name, fn_def_node);
}
-static AstNode *resolve_typdef_as_builtin(Context *c, const TypedefNameDecl *typedef_decl, const char *primitive_name) {
+static AstNode *resolve_typdef_as_builtin(Context *c, const clang::TypedefNameDecl *typedef_decl, const char *primitive_name) {
AstNode *node = trans_create_node_symbol_str(c, primitive_name);
c->decl_table.put(typedef_decl, node);
return node;
}
-static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_decl) {
+static AstNode *resolve_typedef_decl(Context *c, const clang::TypedefNameDecl *typedef_decl) {
auto existing_entry = c->decl_table.maybe_get((void*)typedef_decl->getCanonicalDecl());
if (existing_entry) {
return existing_entry->value;
}
- QualType child_qt = typedef_decl->getUnderlyingType();
+ clang::QualType child_qt = typedef_decl->getUnderlyingType();
Buf *type_name = buf_create_from_str(decl_name(typedef_decl));
if (buf_eql_str(type_name, "uint8_t")) {
@@ -3894,7 +3095,7 @@ static AstNode *resolve_typedef_decl(Context *c, const TypedefNameDecl *typedef_
return symbol_node;
}
-struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
+struct AstNode *demote_enum_to_opaque(Context *c, const clang::EnumDecl *enum_decl,
Buf *full_type_name, Buf *bare_name)
{
AstNode *opaque_node = trans_create_node_opaque(c);
@@ -3909,7 +3110,7 @@ struct AstNode *demote_enum_to_opaque(Context *c, const EnumDecl *enum_decl,
return symbol_node;
}
-static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
+static AstNode *resolve_enum_decl(Context *c, const clang::EnumDecl *enum_decl) {
auto existing_entry = c->decl_table.maybe_get((void*)enum_decl->getCanonicalDecl());
if (existing_entry) {
return existing_entry->value;
@@ -3920,7 +3121,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
Buf *bare_name = is_anonymous ? nullptr : buf_create_from_str(raw_name);
Buf *full_type_name = is_anonymous ? nullptr : buf_sprintf("enum_%s", buf_ptr(bare_name));
- const EnumDecl *enum_def = enum_decl->getDefinition();
+ const clang::EnumDecl *enum_def = enum_decl->getDefinition();
if (!enum_def) {
return demote_enum_to_opaque(c, enum_decl, full_type_name, bare_name);
}
@@ -3932,7 +3133,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
it_end = enum_def->enumerator_end();
it != it_end; ++it, field_count += 1)
{
- const EnumConstantDecl *enum_const = *it;
+ const clang::EnumConstantDecl *enum_const = *it;
if (enum_const->getInitExpr()) {
pure_enum = false;
}
@@ -3946,8 +3147,8 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
// TODO only emit this tag type if the enum tag type is not the default.
// I don't know what the default is, need to figure out how clang is deciding.
// it appears to at least be different across gcc/msvc
- if (!c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::UInt) &&
- !c_is_builtin_type(c, enum_decl->getIntegerType(), BuiltinType::Int))
+ if (!c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::UInt) &&
+ !c_is_builtin_type(c, enum_decl->getIntegerType(), clang::BuiltinType::Int))
{
enum_node->data.container_decl.init_arg_expr = tag_int_type;
}
@@ -3957,7 +3158,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
it_end = enum_def->enumerator_end();
it != it_end; ++it, i += 1)
{
- const EnumConstantDecl *enum_const = *it;
+ const clang::EnumConstantDecl *enum_const = *it;
Buf *enum_val_name = buf_create_from_str(decl_name(enum_const));
Buf *field_name;
@@ -3998,7 +3199,7 @@ static AstNode *resolve_enum_decl(Context *c, const EnumDecl *enum_decl) {
}
}
-static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_decl,
+static AstNode *demote_struct_to_opaque(Context *c, const clang::RecordDecl *record_decl,
Buf *full_type_name, Buf *bare_name)
{
AstNode *opaque_node = trans_create_node_opaque(c);
@@ -4013,7 +3214,7 @@ static AstNode *demote_struct_to_opaque(Context *c, const RecordDecl *record_dec
return symbol_node;
}
-static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
+static AstNode *resolve_record_decl(Context *c, const clang::RecordDecl *record_decl) {
auto existing_entry = c->decl_table.maybe_get((void*)record_decl->getCanonicalDecl());
if (existing_entry) {
return existing_entry->value;
@@ -4039,7 +3240,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
Buf *full_type_name = (bare_name == nullptr) ?
nullptr : buf_sprintf("%s_%s", container_kind_name, buf_ptr(bare_name));
- RecordDecl *record_def = record_decl->getDefinition();
+ clang::RecordDecl *record_def = record_decl->getDefinition();
if (record_def == nullptr) {
return demote_struct_to_opaque(c, record_decl, full_type_name, bare_name);
}
@@ -4050,7 +3251,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
it_end = record_def->field_end();
it != it_end; ++it, field_count += 1)
{
- const FieldDecl *field_decl = *it;
+ const clang::FieldDecl *field_decl = *it;
if (field_decl->isBitField()) {
emit_warning(c, field_decl->getLocation(), "%s %s demoted to opaque type - has bitfield",
@@ -4080,7 +3281,7 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
it_end = record_def->field_end();
it != it_end; ++it, i += 1)
{
- const FieldDecl *field_decl = *it;
+ const clang::FieldDecl *field_decl = *it;
AstNode *field_node = trans_create_node(c, NodeTypeStructField);
field_node->data.struct_field.name = buf_create_from_str(decl_name(field_decl));
@@ -4107,13 +3308,13 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
}
}
-static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc) {
+static AstNode *trans_ap_value(Context *c, clang::APValue *ap_value, clang::QualType qt, const clang::SourceLocation &source_loc) {
switch (ap_value->getKind()) {
- case APValue::Int:
+ case clang::APValue::Int:
return trans_create_node_apint(c, ap_value->getInt());
- case APValue::Uninitialized:
+ case clang::APValue::Uninitialized:
return trans_create_node(c, NodeTypeUndefinedLiteral);
- case APValue::Array: {
+ case clang::APValue::Array: {
emit_warning(c, source_loc, "TODO add a test case for this code");
unsigned init_count = ap_value->getArrayInitializedElts();
@@ -4121,13 +3322,16 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
unsigned leftover_count = all_count - init_count;
AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);
+ if (leftover_count != 0) { // We can't use the size of the final array for a partial initializer.
+ bigint_init_unsigned(arr_type_node->data.array_type.size->data.int_literal.bigint, init_count);
+ }
init_node->data.container_init_expr.type = arr_type_node;
init_node->data.container_init_expr.kind = ContainerInitKindArray;
- QualType child_qt = qt.getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType();
+ clang::QualType child_qt = qt.getTypePtr()->getAsArrayTypeUnsafe()->getElementType();
for (size_t i = 0; i < init_count; i += 1) {
- APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);
+ clang::APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);
AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);
if (elem_node == nullptr)
return nullptr;
@@ -4137,15 +3341,19 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
return init_node;
}
- APValue &filler_ap_val = ap_value->getArrayFiller();
+ clang::APValue &filler_ap_val = ap_value->getArrayFiller();
AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);
if (filler_node == nullptr)
return nullptr;
+ AstNode* filler_arr_type = trans_create_node(c, NodeTypeArrayType);
+ *filler_arr_type = *arr_type_node;
+ filler_arr_type->data.array_type.size = trans_create_node_unsigned(c, 1);
+
AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);
- init_node->data.container_init_expr.type = arr_type_node;
- init_node->data.container_init_expr.kind = ContainerInitKindArray;
- init_node->data.container_init_expr.entries.append(filler_node);
+ filler_arr_1->data.container_init_expr.type = filler_arr_type;
+ filler_arr_1->data.container_init_expr.kind = ContainerInitKindArray;
+ filler_arr_1->data.container_init_expr.entries.append(filler_node);
AstNode *rhs_node;
if (leftover_count == 1) {
@@ -4155,62 +3363,66 @@ static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const
rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);
}
+ if (init_count == 0) {
+ return rhs_node;
+ }
+
return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
}
- case APValue::LValue: {
- const APValue::LValueBase lval_base = ap_value->getLValueBase();
- if (const Expr *expr = lval_base.dyn_cast()) {
+ case clang::APValue::LValue: {
+ const clang::APValue::LValueBase lval_base = ap_value->getLValueBase();
+ if (const clang::Expr *expr = lval_base.dyn_cast()) {
return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
}
- //const ValueDecl *value_decl = lval_base.get();
- emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl");
+ //const clang::ValueDecl *value_decl = lval_base.get();
+ emit_warning(c, source_loc, "TODO handle initializer LValue clang::ValueDecl");
return nullptr;
}
- case APValue::Float:
+ case clang::APValue::Float:
emit_warning(c, source_loc, "unsupported initializer value kind: Float");
return nullptr;
- case APValue::ComplexInt:
+ case clang::APValue::ComplexInt:
emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
return nullptr;
- case APValue::ComplexFloat:
+ case clang::APValue::ComplexFloat:
emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
return nullptr;
- case APValue::Vector:
+ case clang::APValue::Vector:
emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
return nullptr;
- case APValue::Struct:
+ case clang::APValue::Struct:
emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
return nullptr;
- case APValue::Union:
+ case clang::APValue::Union:
emit_warning(c, source_loc, "unsupported initializer value kind: Union");
return nullptr;
- case APValue::MemberPointer:
+ case clang::APValue::MemberPointer:
emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
return nullptr;
- case APValue::AddrLabelDiff:
+ case clang::APValue::AddrLabelDiff:
emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
return nullptr;
}
zig_unreachable();
}
-static void visit_var_decl(Context *c, const VarDecl *var_decl) {
+static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
Buf *name = buf_create_from_str(decl_name(var_decl));
switch (var_decl->getTLSKind()) {
- case VarDecl::TLS_None:
+ case clang::VarDecl::TLS_None:
break;
- case VarDecl::TLS_Static:
+ case clang::VarDecl::TLS_Static:
emit_warning(c, var_decl->getLocation(),
"ignoring variable '%s' - static thread local storage", buf_ptr(name));
return;
- case VarDecl::TLS_Dynamic:
+ case clang::VarDecl::TLS_Dynamic:
emit_warning(c, var_decl->getLocation(),
"ignoring variable '%s' - dynamic thread local storage", buf_ptr(name));
return;
}
- QualType qt = var_decl->getType();
+ clang::QualType qt = var_decl->getType();
AstNode *var_type = trans_qual_type(c, qt, var_decl->getLocation());
if (var_type == nullptr) {
emit_warning(c, var_decl->getLocation(), "ignoring variable '%s' - unresolved type", buf_ptr(name));
@@ -4224,7 +3436,7 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
if (is_static && !is_extern) {
AstNode *init_node;
if (var_decl->hasInit()) {
- APValue *ap_value = var_decl->evaluateValue();
+ clang::APValue *ap_value = var_decl->evaluateValue();
if (ap_value == nullptr) {
emit_warning(c, var_decl->getLocation(),
"ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
@@ -4254,24 +3466,25 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
return;
}
-static bool decl_visitor(void *context, const Decl *decl) {
+static bool decl_visitor(void *context, const ZigClangDecl *zdecl) {
+ const clang::Decl *decl = reinterpret_cast(zdecl);
Context *c = (Context*)context;
switch (decl->getKind()) {
- case Decl::Function:
- visit_fn_decl(c, static_cast(decl));
+ case clang::Decl::Function:
+ visit_fn_decl(c, static_cast(decl));
break;
- case Decl::Typedef:
- resolve_typedef_decl(c, static_cast(decl));
+ case clang::Decl::Typedef:
+ resolve_typedef_decl(c, static_cast(decl));
break;
- case Decl::Enum:
- resolve_enum_decl(c, static_cast(decl));
+ case clang::Decl::Enum:
+ resolve_enum_decl(c, static_cast(decl));
break;
- case Decl::Record:
- resolve_record_decl(c, static_cast(decl));
+ case clang::Decl::Record:
+ resolve_record_decl(c, static_cast(decl));
break;
- case Decl::Var:
- visit_var_decl(c, static_cast(decl));
+ case clang::Decl::Var:
+ visit_var_decl(c, static_cast(decl));
break;
default:
emit_warning(c, decl->getLocation(), "ignoring %s decl", decl->getDeclKindName());
@@ -4613,7 +3826,7 @@ static AstNode *parse_ctok_suffix_op_expr(Context *c, CTokenize *ctok, size_t *t
} else if (first_tok->id == CTokIdAsterisk) {
*tok_i += 1;
- node = trans_create_node_ptr_type(c, false, false, node, PtrLenUnknown);
+ node = trans_create_node_ptr_type(c, false, false, node, PtrLenC);
} else {
return node;
}
@@ -4692,24 +3905,25 @@ static void process_macro(Context *c, CTokenize *ctok, Buf *name, const char *ch
c->macro_table.put(name, result_node);
}
-static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
+static void process_preprocessor_entities(Context *c, ZigClangASTUnit *zunit) {
+ clang::ASTUnit *unit = reinterpret_cast(zunit);
CTokenize ctok = {{0}};
// TODO if we see #undef, delete it from the table
- for (PreprocessedEntity *entity : unit.getLocalPreprocessingEntities()) {
+ for (clang::PreprocessedEntity *entity : unit->getLocalPreprocessingEntities()) {
switch (entity->getKind()) {
- case PreprocessedEntity::InvalidKind:
- case PreprocessedEntity::InclusionDirectiveKind:
- case PreprocessedEntity::MacroExpansionKind:
+ case clang::PreprocessedEntity::InvalidKind:
+ case clang::PreprocessedEntity::InclusionDirectiveKind:
+ case clang::PreprocessedEntity::MacroExpansionKind:
continue;
- case PreprocessedEntity::MacroDefinitionKind:
+ case clang::PreprocessedEntity::MacroDefinitionKind:
{
- MacroDefinitionRecord *macro = static_cast(entity);
+ clang::MacroDefinitionRecord *macro = static_cast(entity);
const char *raw_name = macro->getName()->getNameStart();
- SourceRange range = macro->getSourceRange();
- SourceLocation begin_loc = range.getBegin();
- SourceLocation end_loc = range.getEnd();
+ clang::SourceRange range = macro->getSourceRange();
+ clang::SourceLocation begin_loc = range.getBegin();
+ clang::SourceLocation end_loc = range.getEnd();
if (begin_loc == end_loc) {
// this means it is a macro without a value
@@ -4721,7 +3935,7 @@ static void process_preprocessor_entities(Context *c, ASTUnit &unit) {
continue;
}
- const char *begin_c = c->source_manager->getCharacterData(begin_loc);
+ const char *begin_c = ZigClangSourceManager_getCharacterData(c->source_manager, bitcast(begin_loc));
process_macro(c, &ctok, name, begin_c);
}
}
@@ -4772,7 +3986,16 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
clang_argv.append("-x");
clang_argv.append("c");
- if (c->codegen->is_native_target) {
+ Buf *out_dep_path = nullptr;
+ if (codegen->enable_cache) {
+ Buf *prefix = buf_sprintf("%s" OS_SEP, buf_ptr(&codegen->cache_dir));
+ out_dep_path = os_tmp_filename(prefix, buf_create_from_str(".d"));
+ clang_argv.append("-MD");
+ clang_argv.append("-MF");
+ clang_argv.append(buf_ptr(out_dep_path));
+ }
+
+ if (c->codegen->zig_target->is_native) {
char *ZIG_PARSEC_CFLAGS = getenv("ZIG_NATIVE_PARSEC_CFLAGS");
if (ZIG_PARSEC_CFLAGS) {
Buf tmp_buf = BUF_INIT;
@@ -4791,12 +4014,24 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
}
}
+ clang_argv.append("-nobuiltininc");
+ clang_argv.append("-nostdinc");
+ clang_argv.append("-nostdinc++");
+ if (codegen->libc_link_lib == nullptr) {
+ clang_argv.append("-nolibc");
+ }
+
clang_argv.append("-isystem");
clang_argv.append(buf_ptr(codegen->zig_c_headers_dir));
- if (codegen->libc_include_dir != nullptr) {
+ if (codegen->libc != nullptr) {
clang_argv.append("-isystem");
- clang_argv.append(buf_ptr(codegen->libc_include_dir));
+ clang_argv.append(buf_ptr(&codegen->libc->include_dir));
+
+ if (!buf_eql_buf(&codegen->libc->include_dir, &codegen->libc->sys_include_dir)) {
+ clang_argv.append("-isystem");
+ clang_argv.append(buf_ptr(&codegen->libc->sys_include_dir));
+ }
}
// windows c runtime requires -D_DEBUG if using debug libraries
@@ -4816,7 +4051,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
clang_argv.append("-Xclang");
clang_argv.append("-detailed-preprocessing-record");
- if (!c->codegen->is_native_target) {
+ if (c->codegen->zig_target->is_native) {
+ clang_argv.append("-march=native");
+ } else {
clang_argv.append("-target");
clang_argv.append(buf_ptr(&c->codegen->triple_str));
}
@@ -4834,9 +4071,9 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
// to make the [start...end] argument work
clang_argv.append(nullptr);
- IntrusiveRefCntPtr diags(CompilerInstance::createDiagnostics(new DiagnosticOptions));
+ clang::IntrusiveRefCntPtr diags(clang::CompilerInstance::createDiagnostics(new clang::DiagnosticOptions));
- std::shared_ptr pch_container_ops = std::make_shared();
+ std::shared_ptr pch_container_ops = std::make_shared();
bool only_local_decls = true;
bool capture_diagnostics = true;
@@ -4845,13 +4082,13 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
bool single_file_parse = false;
bool for_serialization = false;
const char *resources_path = buf_ptr(codegen->zig_c_headers_dir);
- std::unique_ptr err_unit;
- std::unique_ptr ast_unit(ASTUnit::LoadFromCommandLine(
+ std::unique_ptr err_unit;
+ ZigClangASTUnit *ast_unit = reinterpret_cast(clang::ASTUnit::LoadFromCommandLine(
&clang_argv.at(0), &clang_argv.last(),
pch_container_ops, diags, resources_path,
- only_local_decls, capture_diagnostics, None, true, 0, TU_Complete,
- false, false, allow_pch_with_compiler_errors, SkipFunctionBodiesScope::None,
- single_file_parse, user_files_are_volatile, for_serialization, None, &err_unit,
+ only_local_decls, capture_diagnostics, clang::None, true, 0, clang::TU_Complete,
+ false, false, allow_pch_with_compiler_errors, clang::SkipFunctionBodiesScope::None,
+ single_file_parse, user_files_are_volatile, for_serialization, clang::None, &err_unit,
nullptr));
// Early failures in LoadFromCommandLine may return with ErrUnit unset.
@@ -4861,29 +4098,29 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
if (diags->getClient()->getNumErrors() > 0) {
if (ast_unit) {
- err_unit = std::move(ast_unit);
+ err_unit = std::unique_ptr(reinterpret_cast(ast_unit));
}
- for (ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
+ for (clang::ASTUnit::stored_diag_iterator it = err_unit->stored_diag_begin(),
it_end = err_unit->stored_diag_end();
it != it_end; ++it)
{
switch (it->getLevel()) {
- case DiagnosticsEngine::Ignored:
- case DiagnosticsEngine::Note:
- case DiagnosticsEngine::Remark:
- case DiagnosticsEngine::Warning:
+ case clang::DiagnosticsEngine::Ignored:
+ case clang::DiagnosticsEngine::Note:
+ case clang::DiagnosticsEngine::Remark:
+ case clang::DiagnosticsEngine::Warning:
continue;
- case DiagnosticsEngine::Error:
- case DiagnosticsEngine::Fatal:
+ case clang::DiagnosticsEngine::Error:
+ case clang::DiagnosticsEngine::Fatal:
break;
}
StringRef msg_str_ref = it->getMessage();
Buf *msg = string_ref_to_buf(msg_str_ref);
- FullSourceLoc fsl = it->getLocation();
+ clang::FullSourceLoc fsl = it->getLocation();
if (fsl.hasManager()) {
- FileID file_id = fsl.getFileID();
- StringRef filename = fsl.getManager().getFilename(fsl);
+ clang::FileID file_id = fsl.getFileID();
+ clang::StringRef filename = fsl.getManager().getFilename(fsl);
unsigned line = fsl.getSpellingLineNumber() - 1;
unsigned column = fsl.getSpellingColumnNumber() - 1;
unsigned offset = fsl.getManager().getFileOffset(fsl);
@@ -4908,14 +4145,25 @@ Error parse_h_file(ImportTableEntry *import, ZigList *errors, const
return ErrorCCompileErrors;
}
- c->ctx = &ast_unit->getASTContext();
- c->source_manager = &ast_unit->getSourceManager();
+ if (codegen->enable_cache) {
+ Error err;
+ assert(out_dep_path != nullptr);
+ if ((err = cache_add_dep_file(&codegen->cache_hash, out_dep_path, codegen->verbose_cimport))) {
+ if (codegen->verbose_cimport) {
+ fprintf(stderr, "translate-c: aborting due to failed cache operation: %s\n", err_str(err));
+ }
+ return err;
+ }
+ }
+
+ c->ctx = ZigClangASTUnit_getASTContext(ast_unit);
+ c->source_manager = ZigClangASTUnit_getSourceManager(ast_unit);
c->root = trans_create_node(c, NodeTypeContainerDecl);
c->root->data.container_decl.is_root = true;
- ast_unit->visitLocalTopLevelDecls(c, decl_visitor);
+ ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, c, decl_visitor);
- process_preprocessor_entities(c, *ast_unit);
+ process_preprocessor_entities(c, ast_unit);
render_macros(c);
render_aliases(c);
diff --git a/src/util.hpp b/src/util.hpp
index cc83022328..a0e759567e 100644
--- a/src/util.hpp
+++ b/src/util.hpp
@@ -147,11 +147,14 @@ static inline T clamp(T min_value, T value, T max_value) {
return max(min(value, max_value), min_value);
}
-static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) {
- size_t str_len = strlen(str);
- if (str_len != mem_len)
+static inline bool mem_eql_mem(const char *a_ptr, size_t a_len, const char *b_ptr, size_t b_len) {
+ if (a_len != b_len)
return false;
- return memcmp(mem, str, mem_len) == 0;
+ return memcmp(a_ptr, b_ptr, a_len) == 0;
+}
+
+static inline bool mem_eql_str(const char *mem, size_t mem_len, const char *str) {
+ return mem_eql_mem(mem, mem_len, str, strlen(str));
}
static inline bool is_power_of_2(uint64_t x) {
diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp
new file mode 100644
index 0000000000..95d74d4536
--- /dev/null
+++ b/src/zig_clang.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+
+/*
+ * The point of this file is to contain all the Clang C++ API interaction so that:
+ * 1. The compile time of other files is kept under control.
+ * 2. Provide a C interface to the Clang functions we need for self-hosting purposes.
+ * 3. Prevent C++ from infecting the rest of the project.
+ */
+#include "zig_clang.h"
+
+#if __GNUC__ >= 8
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wclass-memaccess"
+#endif
+
+#include
+#include
+#include
+
+#if __GNUC__ >= 8
+#pragma GCC diagnostic pop
+#endif
+
+// Detect additions to the enum
+void zig2clang_BO(ZigClangBO op) {
+ switch (op) {
+ case ZigClangBO_PtrMemD:
+ case ZigClangBO_PtrMemI:
+ case ZigClangBO_Cmp:
+ case ZigClangBO_Mul:
+ case ZigClangBO_Div:
+ case ZigClangBO_Rem:
+ case ZigClangBO_Add:
+ case ZigClangBO_Sub:
+ case ZigClangBO_Shl:
+ case ZigClangBO_Shr:
+ case ZigClangBO_LT:
+ case ZigClangBO_GT:
+ case ZigClangBO_LE:
+ case ZigClangBO_GE:
+ case ZigClangBO_EQ:
+ case ZigClangBO_NE:
+ case ZigClangBO_And:
+ case ZigClangBO_Xor:
+ case ZigClangBO_Or:
+ case ZigClangBO_LAnd:
+ case ZigClangBO_LOr:
+ case ZigClangBO_Assign:
+ case ZigClangBO_Comma:
+ case ZigClangBO_MulAssign:
+ case ZigClangBO_DivAssign:
+ case ZigClangBO_RemAssign:
+ case ZigClangBO_AddAssign:
+ case ZigClangBO_SubAssign:
+ case ZigClangBO_ShlAssign:
+ case ZigClangBO_ShrAssign:
+ case ZigClangBO_AndAssign:
+ case ZigClangBO_XorAssign:
+ case ZigClangBO_OrAssign:
+ break;
+ }
+}
+
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Add == clang::BO_Add, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_AddAssign == clang::BO_AddAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_And == clang::BO_And, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_AndAssign == clang::BO_AndAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Assign == clang::BO_Assign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Cmp == clang::BO_Cmp, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Comma == clang::BO_Comma, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Div == clang::BO_Div, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_DivAssign == clang::BO_DivAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_EQ == clang::BO_EQ, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_GE == clang::BO_GE, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_GT == clang::BO_GT, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_LAnd == clang::BO_LAnd, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_LE == clang::BO_LE, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_LOr == clang::BO_LOr, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_LT == clang::BO_LT, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Mul == clang::BO_Mul, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_MulAssign == clang::BO_MulAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_NE == clang::BO_NE, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Or == clang::BO_Or, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_OrAssign == clang::BO_OrAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemD == clang::BO_PtrMemD, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_PtrMemI == clang::BO_PtrMemI, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Rem == clang::BO_Rem, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_RemAssign == clang::BO_RemAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Shl == clang::BO_Shl, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_ShlAssign == clang::BO_ShlAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Shr == clang::BO_Shr, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_ShrAssign == clang::BO_ShrAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Sub == clang::BO_Sub, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_SubAssign == clang::BO_SubAssign, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_Xor == clang::BO_Xor, "");
+static_assert((clang::BinaryOperatorKind)ZigClangBO_XorAssign == clang::BO_XorAssign, "");
+
+// This function detects additions to the enum
+void zig2clang_UO(ZigClangUO op) {
+ switch (op) {
+ case ZigClangUO_AddrOf:
+ case ZigClangUO_Coawait:
+ case ZigClangUO_Deref:
+ case ZigClangUO_Extension:
+ case ZigClangUO_Imag:
+ case ZigClangUO_LNot:
+ case ZigClangUO_Minus:
+ case ZigClangUO_Not:
+ case ZigClangUO_Plus:
+ case ZigClangUO_PostDec:
+ case ZigClangUO_PostInc:
+ case ZigClangUO_PreDec:
+ case ZigClangUO_PreInc:
+ case ZigClangUO_Real:
+ break;
+ }
+}
+
+static_assert((clang::UnaryOperatorKind)ZigClangUO_AddrOf == clang::UO_AddrOf, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Coawait == clang::UO_Coawait, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Deref == clang::UO_Deref, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Extension == clang::UO_Extension, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Imag == clang::UO_Imag, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_LNot == clang::UO_LNot, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Minus == clang::UO_Minus, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Not == clang::UO_Not, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Plus == clang::UO_Plus, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_PostDec == clang::UO_PostDec, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_PostInc == clang::UO_PostInc, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_PreDec == clang::UO_PreDec, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_PreInc == clang::UO_PreInc, "");
+static_assert((clang::UnaryOperatorKind)ZigClangUO_Real == clang::UO_Real, "");
+
+static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
+static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
+ ZigClangSourceLocation dest;
+ memcpy(&dest, static_cast(&src), sizeof(ZigClangSourceLocation));
+ return dest;
+}
+static clang::SourceLocation bitcast(ZigClangSourceLocation src) {
+ clang::SourceLocation dest;
+ memcpy(&dest, static_cast(&src), sizeof(ZigClangSourceLocation));
+ return dest;
+}
+
+static_assert(sizeof(ZigClangQualType) == sizeof(clang::QualType), "");
+static ZigClangQualType bitcast(clang::QualType src) {
+ ZigClangQualType dest;
+ memcpy(&dest, static_cast(&src), sizeof(ZigClangQualType));
+ return dest;
+}
+static clang::QualType bitcast(ZigClangQualType src) {
+ clang::QualType dest;
+ memcpy(&dest, static_cast(&src), sizeof(ZigClangQualType));
+ return dest;
+}
+
+ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *self,
+ ZigClangSourceLocation Loc)
+{
+ return bitcast(reinterpret_cast(self)->getSpellingLoc(bitcast(Loc)));
+}
+
+const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *self,
+ ZigClangSourceLocation SpellingLoc)
+{
+ StringRef s = reinterpret_cast(self)->getFilename(bitcast(SpellingLoc));
+ return (const char *)s.bytes_begin();
+}
+
+unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *self,
+ ZigClangSourceLocation Loc)
+{
+ return reinterpret_cast(self)->getSpellingLineNumber(bitcast(Loc));
+}
+
+unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *self,
+ ZigClangSourceLocation Loc)
+{
+ return reinterpret_cast(self)->getSpellingColumnNumber(bitcast(Loc));
+}
+
+const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *self,
+ ZigClangSourceLocation SL)
+{
+ return reinterpret_cast(self)->getCharacterData(bitcast(SL));
+}
+
+ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext* self, ZigClangQualType T) {
+ return bitcast(reinterpret_cast(self)->getPointerType(bitcast(T)));
+}
+
+ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *self) {
+ clang::ASTContext *result = &reinterpret_cast(self)->getASTContext();
+ return reinterpret_cast(result);
+}
+
+ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *self) {
+ clang::SourceManager *result = &reinterpret_cast(self)->getSourceManager();
+ return reinterpret_cast(result);
+}
+
+bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *self, void *context,
+ bool (*Fn)(void *context, const ZigClangDecl *decl))
+{
+ return reinterpret_cast(self)->visitLocalTopLevelDecls(context,
+ reinterpret_cast(Fn));
+}
diff --git a/src/zig_clang.h b/src/zig_clang.h
new file mode 100644
index 0000000000..c7d749cbd9
--- /dev/null
+++ b/src/zig_clang.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2019 Andrew Kelley
+ *
+ * This file is part of zig, which is MIT licensed.
+ * See http://opensource.org/licenses/MIT
+ */
+
+#ifndef ZIG_ZIG_CLANG_H
+#define ZIG_ZIG_CLANG_H
+
+#ifdef __cplusplus
+#define ZIG_EXTERN_C extern "C"
+#else
+#define ZIG_EXTERN_C
+#endif
+
+// ATTENTION: If you modify this file, be sure to update the corresponding
+// extern function declarations in the self-hosted compiler.
+
+struct ZigClangSourceLocation {
+ unsigned ID;
+};
+
+struct ZigClangQualType {
+ void *ptr;
+};
+
+struct ZigClangAPValue;
+struct ZigClangASTContext;
+struct ZigClangASTUnit;
+struct ZigClangArraySubscriptExpr;
+struct ZigClangArrayType;
+struct ZigClangAttributedType;
+struct ZigClangBinaryOperator;
+struct ZigClangBreakStmt;
+struct ZigClangBuiltinType;
+struct ZigClangCStyleCastExpr;
+struct ZigClangCallExpr;
+struct ZigClangCaseStmt;
+struct ZigClangCompoundAssignOperator;
+struct ZigClangCompoundStmt;
+struct ZigClangConditionalOperator;
+struct ZigClangConstantArrayType;
+struct ZigClangContinueStmt;
+struct ZigClangDecayedType;
+struct ZigClangDecl;
+struct ZigClangDeclRefExpr;
+struct ZigClangDeclStmt;
+struct ZigClangDefaultStmt;
+struct ZigClangDiagnosticOptions;
+struct ZigClangDiagnosticsEngine;
+struct ZigClangDoStmt;
+struct ZigClangElaboratedType;
+struct ZigClangEnumConstantDecl;
+struct ZigClangEnumDecl;
+struct ZigClangEnumType;
+struct ZigClangExpr;
+struct ZigClangFieldDecl;
+struct ZigClangFileID;
+struct ZigClangForStmt;
+struct ZigClangFullSourceLoc;
+struct ZigClangFunctionDecl;
+struct ZigClangFunctionProtoType;
+struct ZigClangIfStmt;
+struct ZigClangImplicitCastExpr;
+struct ZigClangIncompleteArrayType;
+struct ZigClangIntegerLiteral;
+struct ZigClangMacroDefinitionRecord;
+struct ZigClangMemberExpr;
+struct ZigClangNamedDecl;
+struct ZigClangNone;
+struct ZigClangPCHContainerOperations;
+struct ZigClangParenExpr;
+struct ZigClangParenType;
+struct ZigClangParmVarDecl;
+struct ZigClangPointerType;
+struct ZigClangPreprocessedEntity;
+struct ZigClangRecordDecl;
+struct ZigClangRecordType;
+struct ZigClangReturnStmt;
+struct ZigClangSkipFunctionBodiesScope;
+struct ZigClangSourceManager;
+struct ZigClangSourceRange;
+struct ZigClangStmt;
+struct ZigClangStorageClass;
+struct ZigClangStringLiteral;
+struct ZigClangStringRef;
+struct ZigClangSwitchStmt;
+struct ZigClangType;
+struct ZigClangTypedefNameDecl;
+struct ZigClangTypedefType;
+struct ZigClangUnaryExprOrTypeTraitExpr;
+struct ZigClangUnaryOperator;
+struct ZigClangValueDecl;
+struct ZigClangVarDecl;
+struct ZigClangWhileStmt;
+
+enum ZigClangBO {
+ ZigClangBO_PtrMemD,
+ ZigClangBO_PtrMemI,
+ ZigClangBO_Mul,
+ ZigClangBO_Div,
+ ZigClangBO_Rem,
+ ZigClangBO_Add,
+ ZigClangBO_Sub,
+ ZigClangBO_Shl,
+ ZigClangBO_Shr,
+ ZigClangBO_Cmp,
+ ZigClangBO_LT,
+ ZigClangBO_GT,
+ ZigClangBO_LE,
+ ZigClangBO_GE,
+ ZigClangBO_EQ,
+ ZigClangBO_NE,
+ ZigClangBO_And,
+ ZigClangBO_Xor,
+ ZigClangBO_Or,
+ ZigClangBO_LAnd,
+ ZigClangBO_LOr,
+ ZigClangBO_Assign,
+ ZigClangBO_MulAssign,
+ ZigClangBO_DivAssign,
+ ZigClangBO_RemAssign,
+ ZigClangBO_AddAssign,
+ ZigClangBO_SubAssign,
+ ZigClangBO_ShlAssign,
+ ZigClangBO_ShrAssign,
+ ZigClangBO_AndAssign,
+ ZigClangBO_XorAssign,
+ ZigClangBO_OrAssign,
+ ZigClangBO_Comma,
+};
+
+enum ZigClangUO {
+ ZigClangUO_PostInc,
+ ZigClangUO_PostDec,
+ ZigClangUO_PreInc,
+ ZigClangUO_PreDec,
+ ZigClangUO_AddrOf,
+ ZigClangUO_Deref,
+ ZigClangUO_Plus,
+ ZigClangUO_Minus,
+ ZigClangUO_Not,
+ ZigClangUO_LNot,
+ ZigClangUO_Real,
+ ZigClangUO_Imag,
+ ZigClangUO_Extension,
+ ZigClangUO_Coawait,
+};
+
+//struct ZigClangCC_AAPCS;
+//struct ZigClangCC_AAPCS_VFP;
+//struct ZigClangCC_C;
+//struct ZigClangCC_IntelOclBicc;
+//struct ZigClangCC_OpenCLKernel;
+//struct ZigClangCC_PreserveAll;
+//struct ZigClangCC_PreserveMost;
+//struct ZigClangCC_SpirFunction;
+//struct ZigClangCC_Swift;
+//struct ZigClangCC_Win64;
+//struct ZigClangCC_X86FastCall;
+//struct ZigClangCC_X86Pascal;
+//struct ZigClangCC_X86RegCall;
+//struct ZigClangCC_X86StdCall;
+//struct ZigClangCC_X86ThisCall;
+//struct ZigClangCC_X86VectorCall;
+//struct ZigClangCC_X86_64SysV;
+
+//struct ZigClangCK_ARCConsumeObject;
+//struct ZigClangCK_ARCExtendBlockObject;
+//struct ZigClangCK_ARCProduceObject;
+//struct ZigClangCK_ARCReclaimReturnedObject;
+//struct ZigClangCK_AddressSpaceConversion;
+//struct ZigClangCK_AnyPointerToBlockPointerCast;
+//struct ZigClangCK_ArrayToPointerDecay;
+//struct ZigClangCK_AtomicToNonAtomic;
+//struct ZigClangCK_BaseToDerived;
+//struct ZigClangCK_BaseToDerivedMemberPointer;
+//struct ZigClangCK_BitCast;
+//struct ZigClangCK_BlockPointerToObjCPointerCast;
+//struct ZigClangCK_BooleanToSignedIntegral;
+//struct ZigClangCK_BuiltinFnToFnPtr;
+//struct ZigClangCK_CPointerToObjCPointerCast;
+//struct ZigClangCK_ConstructorConversion;
+//struct ZigClangCK_CopyAndAutoreleaseBlockObject;
+//struct ZigClangCK_Dependent;
+//struct ZigClangCK_DerivedToBase;
+//struct ZigClangCK_DerivedToBaseMemberPointer;
+//struct ZigClangCK_Dynamic;
+//struct ZigClangCK_FloatingCast;
+//struct ZigClangCK_FloatingComplexCast;
+//struct ZigClangCK_FloatingComplexToBoolean;
+//struct ZigClangCK_FloatingComplexToIntegralComplex;
+//struct ZigClangCK_FloatingComplexToReal;
+//struct ZigClangCK_FloatingRealToComplex;
+//struct ZigClangCK_FloatingToBoolean;
+//struct ZigClangCK_FloatingToIntegral;
+//struct ZigClangCK_FunctionToPointerDecay;
+//struct ZigClangCK_IntToOCLSampler;
+//struct ZigClangCK_IntegralCast;
+//struct ZigClangCK_IntegralComplexCast;
+//struct ZigClangCK_IntegralComplexToBoolean;
+//struct ZigClangCK_IntegralComplexToFloatingComplex;
+//struct ZigClangCK_IntegralComplexToReal;
+//struct ZigClangCK_IntegralRealToComplex;
+//struct ZigClangCK_IntegralToBoolean;
+//struct ZigClangCK_IntegralToFloating;
+//struct ZigClangCK_IntegralToPointer;
+//struct ZigClangCK_LValueBitCast;
+//struct ZigClangCK_LValueToRValue;
+//struct ZigClangCK_MemberPointerToBoolean;
+//struct ZigClangCK_NoOp;
+//struct ZigClangCK_NonAtomicToAtomic;
+//struct ZigClangCK_NullToMemberPointer;
+//struct ZigClangCK_NullToPointer;
+//struct ZigClangCK_ObjCObjectLValueCast;
+//struct ZigClangCK_PointerToBoolean;
+//struct ZigClangCK_PointerToIntegral;
+//struct ZigClangCK_ReinterpretMemberPointer;
+//struct ZigClangCK_ToUnion;
+//struct ZigClangCK_ToVoid;
+//struct ZigClangCK_UncheckedDerivedToBase;
+//struct ZigClangCK_UserDefinedConversion;
+//struct ZigClangCK_VectorSplat;
+//struct ZigClangCK_ZeroToOCLEvent;
+//struct ZigClangCK_ZeroToOCLQueue;
+
+//struct ZigClangETK_Class;
+//struct ZigClangETK_Enum;
+//struct ZigClangETK_Interface;
+//struct ZigClangETK_None;
+//struct ZigClangETK_Struct;
+//struct ZigClangETK_Typename;
+//struct ZigClangETK_Union;
+
+//struct ZigClangSC_None;
+//struct ZigClangSC_PrivateExtern;
+//struct ZigClangSC_Static;
+
+//struct ZigClangTU_Complete;
+
+ZIG_EXTERN_C ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const ZigClangSourceManager *,
+ ZigClangSourceLocation Loc);
+ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const ZigClangSourceManager *,
+ ZigClangSourceLocation SpellingLoc);
+ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingLineNumber(const ZigClangSourceManager *,
+ ZigClangSourceLocation Loc);
+ZIG_EXTERN_C unsigned ZigClangSourceManager_getSpellingColumnNumber(const ZigClangSourceManager *,
+ ZigClangSourceLocation Loc);
+ZIG_EXTERN_C const char* ZigClangSourceManager_getCharacterData(const ZigClangSourceManager *,
+ ZigClangSourceLocation SL);
+
+ZIG_EXTERN_C ZigClangQualType ZigClangASTContext_getPointerType(const ZigClangASTContext*, ZigClangQualType T);
+
+ZIG_EXTERN_C ZigClangASTContext *ZigClangASTUnit_getASTContext(ZigClangASTUnit *);
+ZIG_EXTERN_C ZigClangSourceManager *ZigClangASTUnit_getSourceManager(ZigClangASTUnit *);
+ZIG_EXTERN_C bool ZigClangASTUnit_visitLocalTopLevelDecls(ZigClangASTUnit *, void *context,
+ bool (*Fn)(void *context, const ZigClangDecl *decl));
+#endif
diff --git a/src/zig_clang_cc1_main.cpp b/src/zig_clang_cc1_main.cpp
new file mode 100644
index 0000000000..ee0f212ff3
--- /dev/null
+++ b/src/zig_clang_cc1_main.cpp
@@ -0,0 +1,226 @@
+//===-- cc1_main.cpp - Clang CC1 Compiler Frontend ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the entry point to the clang -cc1 functionality, which implements the
+// core compiler functionality along with a number of additional tools for
+// demonstration and testing purposes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Option/Arg.h"
+#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
+#include "clang/Config/config.h"
+#include "clang/Basic/Stack.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/CompilerInvocation.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Frontend/TextDiagnosticBuffer.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
+#include "clang/Frontend/Utils.h"
+#include "clang/FrontendTool/Utils.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/Config/llvm-config.h"
+#include "llvm/LinkAllPasses.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include
+
+#ifdef CLANG_HAVE_RLIMITS
+#include
+#endif
+
+using namespace clang;
+using namespace llvm::opt;
+
+//===----------------------------------------------------------------------===//
+// Main driver
+//===----------------------------------------------------------------------===//
+
+static void LLVMErrorHandler(void *UserData, const std::string &Message,
+ bool GenCrashDiag) {
+ DiagnosticsEngine &Diags = *static_cast(UserData);
+
+ Diags.Report(diag::err_fe_error_backend) << Message;
+
+ // Run the interrupt handlers to make sure any special cleanups get done, in
+ // particular that we remove files registered with RemoveFileOnSignal.
+ llvm::sys::RunInterruptHandlers();
+
+ // We cannot recover from llvm errors. When reporting a fatal error, exit
+ // with status 70 to generate crash diagnostics. For BSD systems this is
+ // defined as an internal software error. Otherwise, exit with status 1.
+ exit(GenCrashDiag ? 70 : 1);
+}
+
+#ifdef CLANG_HAVE_RLIMITS
+#if defined(__linux__) && defined(__PIE__)
+static size_t getCurrentStackAllocation() {
+ // If we can't compute the current stack usage, allow for 512K of command
+ // line arguments and environment.
+ size_t Usage = 512 * 1024;
+ if (FILE *StatFile = fopen("/proc/self/stat", "r")) {
+ // We assume that the stack extends from its current address to the end of
+ // the environment space. In reality, there is another string literal (the
+ // program name) after the environment, but this is close enough (we only
+ // need to be within 100K or so).
+ unsigned long StackPtr, EnvEnd;
+ // Disable silly GCC -Wformat warning that complains about length
+ // modifiers on ignored format specifiers. We want to retain these
+ // for documentation purposes even though they have no effect.
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+#endif
+ if (fscanf(StatFile,
+ "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*lu %*lu %*lu %*lu %*lu "
+ "%*lu %*ld %*ld %*ld %*ld %*ld %*ld %*llu %*lu %*ld %*lu %*lu "
+ "%*lu %*lu %lu %*lu %*lu %*lu %*lu %*lu %*llu %*lu %*lu %*d %*d "
+ "%*u %*u %*llu %*lu %*ld %*lu %*lu %*lu %*lu %*lu %*lu %lu %*d",
+ &StackPtr, &EnvEnd) == 2) {
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif
+ Usage = StackPtr < EnvEnd ? EnvEnd - StackPtr : StackPtr - EnvEnd;
+ }
+ fclose(StatFile);
+ }
+ return Usage;
+}
+
+#include
+
+LLVM_ATTRIBUTE_NOINLINE
+static void ensureStackAddressSpace() {
+ // Linux kernels prior to 4.1 will sometimes locate the heap of a PIE binary
+ // relatively close to the stack (they are only guaranteed to be 128MiB
+ // apart). This results in crashes if we happen to heap-allocate more than
+ // 128MiB before we reach our stack high-water mark.
+ //
+ // To avoid these crashes, ensure that we have sufficient virtual memory
+ // pages allocated before we start running.
+ size_t Curr = getCurrentStackAllocation();
+ const int kTargetStack = DesiredStackSize - 256 * 1024;
+ if (Curr < kTargetStack) {
+ volatile char *volatile Alloc =
+ static_cast(alloca(kTargetStack - Curr));
+ Alloc[0] = 0;
+ Alloc[kTargetStack - Curr - 1] = 0;
+ }
+}
+#else
+static void ensureStackAddressSpace() {}
+#endif
+
+/// Attempt to ensure that we have at least 8MiB of usable stack space.
+static void ensureSufficientStack() {
+ struct rlimit rlim;
+ if (getrlimit(RLIMIT_STACK, &rlim) != 0)
+ return;
+
+ // Increase the soft stack limit to our desired level, if necessary and
+ // possible.
+ if (rlim.rlim_cur != RLIM_INFINITY &&
+ rlim.rlim_cur < rlim_t(DesiredStackSize)) {
+ // Try to allocate sufficient stack.
+ if (rlim.rlim_max == RLIM_INFINITY ||
+ rlim.rlim_max >= rlim_t(DesiredStackSize))
+ rlim.rlim_cur = DesiredStackSize;
+ else if (rlim.rlim_cur == rlim.rlim_max)
+ return;
+ else
+ rlim.rlim_cur = rlim.rlim_max;
+
+ if (setrlimit(RLIMIT_STACK, &rlim) != 0 ||
+ rlim.rlim_cur != DesiredStackSize)
+ return;
+ }
+
+ // We should now have a stack of size at least DesiredStackSize. Ensure
+ // that we can actually use that much, if necessary.
+ ensureStackAddressSpace();
+}
+#else
+static void ensureSufficientStack() {}
+#endif
+
+int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) {
+ ensureSufficientStack();
+
+ std::unique_ptr Clang(new CompilerInstance());
+ IntrusiveRefCntPtr DiagID(new DiagnosticIDs());
+
+ // Register the support for object-file-wrapped Clang modules.
+ auto PCHOps = Clang->getPCHContainerOperations();
+ PCHOps->registerWriter(llvm::make_unique