From d4ca337e6b8d0c268ebce5c4b5fbe9015f3d8ab6 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 18 Jul 2019 11:45:37 -0400 Subject: improvements to riscv support --- src/codegen.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 188c5ccc8d..7136429615 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8390,13 +8390,13 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa } } + // According to Rich Felker libc headers are supposed to go before C language headers. for (size_t i = 0; i < g->libc_include_dir_len; i += 1) { Buf *include_dir = g->libc_include_dir_list[i]; args.append("-isystem"); args.append(buf_ptr(include_dir)); } - // According to Rich Felker libc headers are supposed to go before C language headers. args.append("-isystem"); args.append(buf_ptr(g->zig_c_headers_dir)); @@ -8405,6 +8405,21 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa } else { args.append("-target"); args.append(buf_ptr(&g->llvm_triple_str)); + + if (target_is_musl(g->zig_target) && target_is_riscv(g->zig_target)) { + // Musl depends on atomic instructions, which are disabled by default in Clang/LLVM's + // cross compilation CPU info for RISCV. + switch (g->zig_target->arch) { + case ZigLLVM_riscv32: + args.append("-march=rv32ia"); + break; + case ZigLLVM_riscv64: + args.append("-march=rv64ia"); + break; + default: + zig_unreachable(); + } + } } if (g->zig_target->os == OsFreestanding) { args.append("-ffreestanding"); @@ -8474,6 +8489,7 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) { args.append(g->clang_argv[arg_i]); } + } void codegen_translate_c(CodeGen *g, Buf *full_path, FILE *out_file, bool use_userland_implementation) { -- cgit v1.2.3 From afbf99c84671992acb4129a6a7bc70d604c4d00d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 18 Jul 2019 12:28:24 -0400 Subject: riscv musl: only add the +a feature --- src/codegen.cpp | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 7136429615..2c5f2c96e5 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8409,16 +8409,11 @@ void add_cc_args(CodeGen *g, ZigList &args, const char *out_dep_pa if (target_is_musl(g->zig_target) && target_is_riscv(g->zig_target)) { // Musl depends on atomic instructions, which are disabled by default in Clang/LLVM's // cross compilation CPU info for RISCV. - switch (g->zig_target->arch) { - case ZigLLVM_riscv32: - args.append("-march=rv32ia"); - break; - case ZigLLVM_riscv64: - args.append("-march=rv64ia"); - break; - default: - zig_unreachable(); - } + // TODO: https://github.com/ziglang/zig/issues/2883 + args.append("-Xclang"); + args.append("-target-feature"); + args.append("-Xclang"); + args.append("+a"); } } if (g->zig_target->os == OsFreestanding) { -- cgit v1.2.3 From 03a3b1ca39e73c7edf615d26bb7647d7565a09f7 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 18 Jul 2019 15:20:58 -0400 Subject: riscv workarounds for llvm not having good asm integration --- src/codegen.cpp | 4 ++ std/os/linux/riscv64.zig | 132 ++++++++++++++++++++++++++++++++--------------- std/special/c.zig | 5 +- std/special/start.zig | 2 +- 4 files changed, 99 insertions(+), 44 deletions(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index 2c5f2c96e5..d664a21ecc 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8148,6 +8148,10 @@ static void init(CodeGen *g) { target_specific_cpu_args = ZigLLVMGetHostCPUName(); target_specific_features = ZigLLVMGetNativeFeatures(); } + } else if (target_is_riscv(g->zig_target)) { + // TODO https://github.com/ziglang/zig/issues/2883 + target_specific_cpu_args = ""; + target_specific_features = "+a"; } else { target_specific_cpu_args = ""; target_specific_features = ""; diff --git a/std/os/linux/riscv64.zig b/std/os/linux/riscv64.zig index b9264aa3db..5cda2afa0a 100644 --- a/std/os/linux/riscv64.zig +++ b/std/os/linux/riscv64.zig @@ -1,58 +1,96 @@ pub fn syscall0(number: usize) usize { - return asm volatile ("ecall" - : [ret] "={a0}" (-> usize) - : [number] "{a7}" (number) + return asm volatile ( + \\ mv a7, %[number] + \\ ecall + \\ mv %[ret], a0 + : [ret] "=r" (-> usize) + : [number] "r" (number) : "memory" ); } pub fn syscall1(number: usize, arg1: usize) usize { - return asm volatile ("ecall" - : [ret] "={a0}" (-> usize) - : [number] "{a7}" (number), - [arg1] "{a0}" (arg1) + return asm volatile ( + \\ mv a7, %[number] + \\ mv a0, %[arg1] + \\ ecall + \\ mv %[ret], a0 + : [ret] "=r" (-> usize) + : [number] "r" (number), + [arg1] "r" (arg1) + : "memory" ); } pub fn syscall2(number: usize, arg1: usize, arg2: usize) usize { - return asm volatile ("ecall" - : [ret] "={a0}" (-> usize) - : [number] "{a7}" (number), - [arg1] "{a0}" (arg1), - [arg2] "{a1}" (arg2) + return asm volatile ( + \\ mv a7, %[number] + \\ mv a0, %[arg1] + \\ mv a1, %[arg2] + \\ ecall + \\ mv %[ret], a0 + : [ret] "=r" (-> usize) + : [number] "r" (number), + [arg1] "r" (arg1), + [arg2] "r" (arg2) + : "memory" ); } pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize { - return asm volatile ("ecall" - : [ret] "={a0}" (-> usize) - : [number] "{a7}" (number), - [arg1] "{a0}" (arg1), - [arg2] "{a1}" (arg2), - [arg3] "{a2}" (arg3) + return asm volatile ( + \\ mv a7, %[number] + \\ mv a0, %[arg1] + \\ mv a1, %[arg2] + \\ mv a2, %[arg3] + \\ ecall + \\ mv %[ret], a0 + : [ret] "=r" (-> usize) + : [number] "r" (number), + [arg1] "r" (arg1), + [arg2] "r" (arg2), + [arg3] "r" (arg3) + : "memory" ); } pub fn syscall4(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize) usize { - return asm volatile ("ecall" - : [ret] "={a0}" (-> usize) - : [number] "{a7}" (number), - [arg1] "{a0}" (arg1), - [arg2] "{a1}" (arg2), - [arg3] "{a2}" (arg3), - [arg4] "{a3}" (arg4) + return asm volatile ( + \\ mv a7, %[number] + \\ mv a0, %[arg1] + \\ mv a1, %[arg2] + \\ mv a2, %[arg3] + \\ mv a3, %[arg4] + \\ ecall + \\ mv %[ret], a0 + : [ret] "=r" (-> usize) + : [number] "r" (number), + [arg1] "r" (arg1), + [arg2] "r" (arg2), + [arg3] "r" (arg3), + [arg4] "r" (arg4) + : "memory" ); } pub fn syscall5(number: usize, arg1: usize, arg2: usize, arg3: usize, arg4: usize, arg5: usize) usize { - return asm volatile ("ecall" - : [ret] "={a0}" (-> usize) - : [number] "{a7}" (number), - [arg1] "{a0}" (arg1), - [arg2] "{a1}" (arg2), - [arg3] "{a2}" (arg3), - [arg4] "{a3}" (arg4), - [arg5] "{a4}" (arg5) + return asm volatile ( + \\ mv a7, %[number] + \\ mv a0, %[arg1] + \\ mv a1, %[arg2] + \\ mv a2, %[arg3] + \\ mv a3, %[arg4] + \\ mv a4, %[arg5] + \\ ecall + \\ mv %[ret], a0 + : [ret] "=r" (-> usize) + : [number] "r" (number), + [arg1] "r" (arg1), + [arg2] "r" (arg2), + [arg3] "r" (arg3), + [arg4] "r" (arg4), + [arg5] "r" (arg5) + : "memory" ); } @@ -65,14 +103,24 @@ pub fn syscall6( arg5: usize, arg6: usize, ) usize { - return asm volatile ("ecall" - : [ret] "={a0}" (-> usize) - : [number] "{a7}" (number), - [arg1] "{a0}" (arg1), - [arg2] "{a1}" (arg2), - [arg3] "{a2}" (arg3), - [arg4] "{a3}" (arg4), - [arg5] "{a4}" (arg5), - [arg6] "{a5}" (arg6) + return asm volatile ( + \\ mv a7, %[number] + \\ mv a0, %[arg1] + \\ mv a1, %[arg2] + \\ mv a2, %[arg3] + \\ mv a3, %[arg4] + \\ mv a4, %[arg5] + \\ mv a5, %[arg6] + \\ ecall + \\ mv %[ret], a0 + : [ret] "=r" (-> usize) + : [number] "r" (number), + [arg1] "r" (arg1), + [arg2] "r" (arg2), + [arg3] "r" (arg3), + [arg4] "r" (arg4), + [arg5] "r" (arg5), + [arg6] "r" (arg6) + : "memory" ); } diff --git a/std/special/c.zig b/std/special/c.zig index 150127196b..fa039b3604 100644 --- a/std/special/c.zig +++ b/std/special/c.zig @@ -180,7 +180,10 @@ comptime { @export("__stack_chk_fail", __stack_chk_fail, builtin.GlobalLinkage.Strong); } if (builtin.os == builtin.Os.linux) { - @export("clone", clone, builtin.GlobalLinkage.Strong); + // TODO implement clone for riscv64 + if (builtin.arch != .riscv64) { + @export("clone", clone, builtin.GlobalLinkage.Strong); + } } } extern fn __stack_chk_fail() noreturn { diff --git a/std/special/start.zig b/std/special/start.zig index 42dda53121..0366e088d9 100644 --- a/std/special/start.zig +++ b/std/special/start.zig @@ -60,7 +60,7 @@ nakedcc fn _start() noreturn { ); }, .riscv64 => { - argc_ptr = asm ("mov %[argc], sp" + argc_ptr = asm ("mv %[argc], sp" : [argc] "=r" (-> [*]usize) ); }, -- cgit v1.2.3 From 2c1e955de7a8f31666c751ce4f69c47d4c1b822e Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 20 Jul 2019 13:32:50 -0400 Subject: always give the type to byval attribute --- src/codegen.cpp | 2 +- src/zig_llvm.cpp | 10 ++++++++++ src/zig_llvm.h | 1 + 3 files changed, 12 insertions(+), 1 deletion(-) (limited to 'src/codegen.cpp') diff --git a/src/codegen.cpp b/src/codegen.cpp index d664a21ecc..2170da10ac 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2216,7 +2216,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: - addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "byval"); + ZigLLVMAddByValAttr(llvm_fn, fn_walk->data.attrs.gen_i + 1, get_llvm_type(g, ty)); 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"); diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index c033d7af96..b82d0c51ba 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -723,6 +723,16 @@ void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state) { } } +void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val) { + Function *func = unwrap(fn_ref); + const AttributeList attr_set = func->getAttributes(); + AttrBuilder attr_builder; + Type *llvm_type = unwrap(type_val); + attr_builder.addByValAttr(llvm_type); + const AttributeList new_attr_set = attr_set.addAttributes(func->getContext(), ArgNo, attr_builder); + func->setAttributes(new_attr_set); +} + void ZigLLVMAddFunctionAttr(LLVMValueRef fn_ref, const char *attr_name, const char *attr_value) { Function *func = unwrap(fn_ref); const AttributeList attr_set = func->getAttributes(); diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 210f245efe..10b6d24364 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -213,6 +213,7 @@ ZIG_EXTERN_C struct ZigLLVMDILocation *ZigLLVMGetDebugLoc(unsigned line, unsigne ZIG_EXTERN_C void ZigLLVMSetFastMath(LLVMBuilderRef builder_wrapped, bool on_state); ZIG_EXTERN_C void ZigLLVMAddFunctionAttr(LLVMValueRef fn, const char *attr_name, const char *attr_value); +ZIG_EXTERN_C void ZigLLVMAddByValAttr(LLVMValueRef fn_ref, unsigned ArgNo, LLVMTypeRef type_val); ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv); -- cgit v1.2.3 From f7f86927304073a0e95a2932a77c8d4193099a29 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 29 Aug 2019 10:24:24 -0400 Subject: fix not fully resolving debug info for structs causing llvm error --- src/all_types.hpp | 2 ++ src/analyze.cpp | 15 ++++++++++++++- src/codegen.cpp | 6 ++++++ src/list.hpp | 11 +++++++++++ 4 files changed, 33 insertions(+), 1 deletion(-) (limited to 'src/codegen.cpp') diff --git a/src/all_types.hpp b/src/all_types.hpp index 48323e58ad..e55f10d5e2 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1214,6 +1214,7 @@ struct ZigTypeStruct { HashMap fields_by_name; RootStruct *root_struct; uint32_t *host_int_bytes; // available for packed structs, indexed by gen_index + size_t llvm_full_type_queue_index; uint32_t src_field_count; uint32_t gen_field_count; @@ -1861,6 +1862,7 @@ struct CodeGen { ZigList errors_by_index; ZigList caches_to_release; size_t largest_err_name_len; + ZigList type_resolve_stack; ZigPackage *std_package; ZigPackage *panic_package; diff --git a/src/analyze.cpp b/src/analyze.cpp index 9ae7e99547..2c934bcf69 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -7271,7 +7271,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS di_scope, di_file, line); struct_type->data.structure.resolve_status = ResolveStatusLLVMFwdDecl; - if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) return; + if (ResolveStatusLLVMFwdDecl >= wanted_resolve_status) { + struct_type->data.structure.llvm_full_type_queue_index = g->type_resolve_stack.length; + g->type_resolve_stack.append(struct_type); + return; + } else { + struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX; + } } size_t field_count = struct_type->data.structure.src_field_count; @@ -7475,6 +7481,13 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS ZigLLVMReplaceTemporary(g->dbuilder, struct_type->llvm_di_type, replacement_di_type); struct_type->llvm_di_type = replacement_di_type; struct_type->data.structure.resolve_status = ResolveStatusLLVMFull; + if (struct_type->data.structure.llvm_full_type_queue_index != SIZE_MAX) { + ZigType *last = g->type_resolve_stack.last(); + assert(last->id == ZigTypeIdStruct); + last->data.structure.llvm_full_type_queue_index = struct_type->data.structure.llvm_full_type_queue_index; + g->type_resolve_stack.swap_remove(struct_type->data.structure.llvm_full_type_queue_index); + struct_type->data.structure.llvm_full_type_queue_index = SIZE_MAX; + } } static void resolve_llvm_types_enum(CodeGen *g, ZigType *enum_type, ResolveStatus wanted_resolve_status) { diff --git a/src/codegen.cpp b/src/codegen.cpp index e869201294..7131087703 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -7208,6 +7208,12 @@ static void do_code_gen(CodeGen *g) { LLVMSetModuleInlineAsm(g->module, buf_ptr(&g->global_asm)); } + while (g->type_resolve_stack.length != 0) { + ZigType *ty = g->type_resolve_stack.last(); + if (type_resolve(g, ty, ResolveStatusLLVMFull)) + zig_unreachable(); + } + ZigLLVMDIBuilderFinalize(g->dbuilder); if (g->verbose_llvm_ir) { diff --git a/src/list.hpp b/src/list.hpp index f838e44a5b..8dce75f2b8 100644 --- a/src/list.hpp +++ b/src/list.hpp @@ -74,6 +74,17 @@ struct ZigList { capacity = better_capacity; } + T swap_remove(size_t index) { + if (length - 1 == index) return pop(); + + assert(index != SIZE_MAX); + assert(index < length); + + T old_item = items[index]; + items[index] = pop(); + return old_item; + } + T *items; size_t length; size_t capacity; -- cgit v1.2.3