From ab483281d31c852e77fe0afc6a623fedd1574546 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 7 Aug 2020 11:50:15 -0700 Subject: stage1: elide `@intToPtr` alignment safety check for 1-byte alignment --- src/codegen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 3f3d80d51d..023c94f245 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -3480,8 +3480,9 @@ static LLVMValueRef ir_render_widen_or_shorten(CodeGen *g, IrExecutableGen *exec static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutableGen *executable, IrInstGenIntToPtr *instruction) { ZigType *wanted_type = instruction->base.value->type; LLVMValueRef target_val = ir_llvm_value(g, instruction->target); + const uint32_t align_bytes = get_ptr_align(g, wanted_type); - if (ir_want_runtime_safety(g, &instruction->base)) { + if (ir_want_runtime_safety(g, &instruction->base) && align_bytes > 1) { ZigType *usize = g->builtin_types.entry_usize; LLVMValueRef zero = LLVMConstNull(usize->llvm_type); @@ -3498,7 +3499,6 @@ static LLVMValueRef ir_render_int_to_ptr(CodeGen *g, IrExecutableGen *executable } { - const uint32_t align_bytes = get_ptr_align(g, wanted_type); LLVMValueRef alignment_minus_1 = LLVMConstInt(usize->llvm_type, align_bytes - 1, false); LLVMValueRef anded_val = LLVMBuildAnd(g->builder, target_val, alignment_minus_1, ""); LLVMValueRef is_ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, anded_val, zero, ""); -- cgit v1.2.3 From 1b1921f0e26b9cb8ac78003c9061acac2da5e7ab Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 8 Aug 2020 01:00:29 -0700 Subject: stage1: deal with WebAssembly not supporting @returnAddress() This makes `@returnAddress()` return 0 for WebAssembly (when not using the Emscripten OS) and avoids trying to capture stack traces for the general purpose allocator on that target. --- lib/std/heap.zig | 11 +++++++++-- lib/std/heap/general_purpose_allocator.zig | 5 ++++- src/codegen.cpp | 6 ++++++ 3 files changed, 19 insertions(+), 3 deletions(-) (limited to 'src/codegen.cpp') diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 88f27fad49..0c9dbca369 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -37,7 +37,7 @@ var c_allocator_state = Allocator{ .resizeFn = cResize, }; -fn cAlloc(self: *Allocator, len: usize, ptr_align: u29, len_align: u29) Allocator.Error![]u8 { +fn cAlloc(self: *Allocator, len: usize, ptr_align: u29, len_align: u29, ret_addr: usize) Allocator.Error![]u8 { assert(ptr_align <= @alignOf(c_longdouble)); const ptr = @ptrCast([*]u8, c.malloc(len) orelse return error.OutOfMemory); if (len_align == 0) { @@ -54,7 +54,14 @@ fn cAlloc(self: *Allocator, len: usize, ptr_align: u29, len_align: u29) Allocato return ptr[0..mem.alignBackwardAnyAlign(full_len, len_align)]; } -fn cResize(self: *Allocator, buf: []u8, old_align: u29, new_len: usize, len_align: u29) Allocator.Error!usize { +fn cResize( + self: *Allocator, + buf: []u8, + old_align: u29, + new_len: usize, + len_align: u29, + ret_addr: usize, +) Allocator.Error!usize { if (new_len == 0) { c.free(buf.ptr); return 0; diff --git a/lib/std/heap/general_purpose_allocator.zig b/lib/std/heap/general_purpose_allocator.zig index 98f029579c..5369560356 100644 --- a/lib/std/heap/general_purpose_allocator.zig +++ b/lib/std/heap/general_purpose_allocator.zig @@ -102,9 +102,12 @@ const StackTrace = std.builtin.StackTrace; /// Integer type for pointing to slots in a small allocation const SlotIndex = std.meta.Int(false, math.log2(page_size) + 1); +// WebAssembly doesn't support stack tracing yet. +const default_stack_trace_frames: usize = if (std.Target.current.cpu.arch.isWasm()) 0 else 4; + pub const Config = struct { /// Number of stack frames to capture. - stack_trace_frames: usize = if (std.debug.runtime_safety) @as(usize, 4) else @as(usize, 0), + stack_trace_frames: usize = if (std.debug.runtime_safety) default_stack_trace_frames else @as(usize, 0), /// If true, the allocator will have two fields: /// * `total_requested_bytes` which tracks the total allocated bytes of memory requested. diff --git a/src/codegen.cpp b/src/codegen.cpp index 023c94f245..6941eae466 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -5886,6 +5886,12 @@ static LLVMValueRef ir_render_breakpoint(CodeGen *g, IrExecutableGen *executable static LLVMValueRef ir_render_return_address(CodeGen *g, IrExecutableGen *executable, IrInstGenReturnAddress *instruction) { + if (target_is_wasm(g->zig_target) && g->zig_target->os != OsEmscripten) { + // I got this error from LLVM 10: + // "Non-Emscripten WebAssembly hasn't implemented __builtin_return_address" + return LLVMConstNull(get_llvm_type(g, instruction->base.value->type)); + } + LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); -- cgit v1.2.3 From 2cd19c05d0f615071102a5f18bb4cc800e86c07f Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 15 Aug 2020 09:53:39 -0700 Subject: stage1: remove buggy "unable to inline function" compile error We still want this compile error but I'm giving up on implementing it correctly in stage1. It's been buggy and has false positives sometimes. I left the test cases there, but commented out, so that when we go through the stage1 compile error cases and get coverage for them in stage2 we can reactivate the test cases. closes #2154 --- src/codegen.cpp | 13 ------------ test/compile_errors.zig | 53 +++++++++++++++++++++++++------------------------ 2 files changed, 27 insertions(+), 39 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 6941eae466..1bd8d5b7bc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7871,17 +7871,6 @@ static void gen_global_var(CodeGen *g, ZigVar *var, LLVMValueRef init_val, // TODO ^^ make an actual global variable } -static void validate_inline_fns(CodeGen *g) { - for (size_t i = 0; i < g->inline_fns.length; i += 1) { - ZigFn *fn_entry = g->inline_fns.at(i); - LLVMValueRef fn_val = LLVMGetNamedFunction(g->module, fn_entry->llvm_name); - if (fn_val != nullptr) { - add_node_error(g, fn_entry->proto_node, buf_sprintf("unable to inline function")); - } - } - report_errors_and_maybe_exit(g); -} - static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) { bool is_extern = var->decl_node->data.variable_declaration.is_extern; bool is_export = var->decl_node->data.variable_declaration.is_export; @@ -8359,8 +8348,6 @@ static void zig_llvm_emit_output(CodeGen *g) { exit(1); } - validate_inline_fns(g); - if (g->emit_bin) { g->link_objects.append(&g->o_file_output_path); if (g->bundle_compiler_rt && (g->out_type == OutTypeObj || (g->out_type == OutTypeLib && !g->is_dynamic))) { diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 4adc538602..70a9c47998 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -6151,32 +6151,33 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:2:15: error: expected error union type, found '?i32'", }); - cases.add("inline fn calls itself indirectly", - \\export fn foo() void { - \\ bar(); - \\} - \\inline fn bar() void { - \\ baz(); - \\ quux(); - \\} - \\inline fn baz() void { - \\ bar(); - \\ quux(); - \\} - \\extern fn quux() void; - , &[_][]const u8{ - "tmp.zig:4:1: error: unable to inline function", - }); - - cases.add("save reference to inline function", - \\export fn foo() void { - \\ quux(@ptrToInt(bar)); - \\} - \\inline fn bar() void { } - \\extern fn quux(usize) void; - , &[_][]const u8{ - "tmp.zig:4:1: error: unable to inline function", - }); + // TODO test this in stage2, but we won't even try in stage1 + //cases.add("inline fn calls itself indirectly", + // \\export fn foo() void { + // \\ bar(); + // \\} + // \\inline fn bar() void { + // \\ baz(); + // \\ quux(); + // \\} + // \\inline fn baz() void { + // \\ bar(); + // \\ quux(); + // \\} + // \\extern fn quux() void; + //, &[_][]const u8{ + // "tmp.zig:4:1: error: unable to inline function", + //}); + + //cases.add("save reference to inline function", + // \\export fn foo() void { + // \\ quux(@ptrToInt(bar)); + // \\} + // \\inline fn bar() void { } + // \\extern fn quux(usize) void; + //, &[_][]const u8{ + // "tmp.zig:4:1: error: unable to inline function", + //}); cases.add("signed integer division", \\export fn foo(a: i32, b: i32) i32 { -- cgit v1.2.3 From 60ea87340e7a7157bedbb43d60804ff0fb191ef9 Mon Sep 17 00:00:00 2001 From: Soren Date: Sun, 16 Aug 2020 12:08:34 -0700 Subject: Fix opaque structs and C++ mangling --- src/codegen.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 1bd8d5b7bc..36ed520069 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -10252,9 +10252,11 @@ static void prepend_c_type_to_decl_list(CodeGen *g, GenH *gen_h, ZigType *type_e gen_h->types_to_declare.append(type_entry); return; case ZigTypeIdStruct: - for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { - TypeStructField *field = type_entry->data.structure.fields[i]; - prepend_c_type_to_decl_list(g, gen_h, field->type_entry); + if(type_entry->data.structure.layout == ContainerLayoutExtern) { + for (uint32_t i = 0; i < type_entry->data.structure.src_field_count; i += 1) { + TypeStructField *field = type_entry->data.structure.fields[i]; + prepend_c_type_to_decl_list(g, gen_h, field->type_entry); + } } gen_h->types_to_declare.append(type_entry); return; @@ -10687,21 +10689,19 @@ static void gen_h_file(CodeGen *g) { fprintf(out_h, "\n"); } - fprintf(out_h, "%s", buf_ptr(&types_buf)); - fprintf(out_h, "#ifdef __cplusplus\n"); fprintf(out_h, "extern \"C\" {\n"); fprintf(out_h, "#endif\n"); fprintf(out_h, "\n"); + fprintf(out_h, "%s", buf_ptr(&types_buf)); fprintf(out_h, "%s\n", buf_ptr(&fns_buf)); + fprintf(out_h, "%s\n", buf_ptr(&vars_buf)); fprintf(out_h, "#ifdef __cplusplus\n"); fprintf(out_h, "} // extern \"C\"\n"); fprintf(out_h, "#endif\n\n"); - fprintf(out_h, "%s\n", buf_ptr(&vars_buf)); - fprintf(out_h, "#endif // %s\n", buf_ptr(ifdef_dance_name)); if (fclose(out_h)) -- cgit v1.2.3