authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-24 19:13:21-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-10-24 19:13:21-04:00
logf8bd1cd3b11802d3566d287167d79d3cfc3ef41d
tree076226342d7d97280d02d364f8cc7311b3d98d86
parent32c89531b1475ce8e3b8efdf7a07745da7bc854a
signaturelock-open Commit is signed but in an unrecognized format.

implement partial C ABI support for aarch64


3 files changed, 62 insertions(+), 44 deletions(-)

src/all_types.hpp+1
...@@ -74,6 +74,7 @@ enum UndefAllowed {...@@ -74,6 +74,7 @@ enum UndefAllowed {
74enum X64CABIClass {74enum X64CABIClass {
75 X64CABIClass_Unknown,75 X64CABIClass_Unknown,
76 X64CABIClass_MEMORY,76 X64CABIClass_MEMORY,
77 X64CABIClass_MEMORY_nobyval,
77 X64CABIClass_INTEGER,78 X64CABIClass_INTEGER,
78 X64CABIClass_SSE,79 X64CABIClass_SSE,
79};80};
src/analyze.cpp+11-7
...@@ -919,14 +919,13 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {...@@ -919,14 +919,13 @@ bool want_first_arg_sret(CodeGen *g, FnTypeId *fn_type_id) {
919 if (type_is_c_abi_int(g, fn_type_id->return_type)) {919 if (type_is_c_abi_int(g, fn_type_id->return_type)) {
920 return false;920 return false;
921 }921 }
922 if (g->zig_target->arch == ZigLLVM_x86) {922 if (g->zig_target->arch == ZigLLVM_x86 ||
923 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);923 g->zig_target->arch == ZigLLVM_x86_64 ||
924 return abi_class == X64CABIClass_MEMORY;924 target_is_arm(g->zig_target) ||
925 } else if (g->zig_target->arch == ZigLLVM_x86_64) {925 target_is_riscv(g->zig_target))
926 {
926 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);927 X64CABIClass abi_class = type_c_abi_x86_64_class(g, fn_type_id->return_type);
927 return abi_class == X64CABIClass_MEMORY;928 return abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval;
928 } else if (target_is_arm(g->zig_target) || target_is_riscv(g->zig_target)) {
929 return type_size(g, fn_type_id->return_type) > 16;
930 } else if (g->zig_target->arch == ZigLLVM_mipsel) {929 } else if (g->zig_target->arch == ZigLLVM_mipsel) {
931 return false;930 return false;
932 }931 }
...@@ -7509,6 +7508,11 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {...@@ -7509,6 +7508,11 @@ X64CABIClass type_c_abi_x86_64_class(CodeGen *g, ZigType *ty) {
75097508
7510 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {7509 if (g->zig_target->os == OsWindows || g->zig_target->os == OsUefi) {
7511 return type_windows_abi_x86_64_class(g, ty, ty_size);7510 return type_windows_abi_x86_64_class(g, ty, ty_size);
7511 } else if (g->zig_target->arch == ZigLLVM_aarch64 ||
7512 g->zig_target->arch == ZigLLVM_aarch64_be)
7513 {
7514 X64CABIClass result = type_system_V_abi_x86_64_class(g, ty, ty_size);
7515 return (result == X64CABIClass_MEMORY) ? X64CABIClass_MEMORY_nobyval : result;
7512 } else {7516 } else {
7513 return type_system_V_abi_x86_64_class(g, ty, ty_size);7517 return type_system_V_abi_x86_64_class(g, ty, ty_size);
7514 }7518 }
src/codegen.cpp+50-37
...@@ -1847,51 +1847,64 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_...@@ -1847,51 +1847,64 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_
1847 return true;1847 return true;
1848 }1848 }
18491849
1850 // Arrays are just pointers1850 {
1851 if (ty->id == ZigTypeIdArray) {1851 // Arrays are just pointers
1852 assert(handle_is_ptr(ty));1852 if (ty->id == ZigTypeIdArray) {
1853 switch (fn_walk->id) {1853 assert(handle_is_ptr(ty));
1854 case FnWalkIdAttrs:1854 switch (fn_walk->id) {
1855 // arrays passed to C ABI functions may not be at address 01855 case FnWalkIdAttrs:
1856 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");1856 // arrays passed to C ABI functions may not be at address 0
1857 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));1857 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
1858 fn_walk->data.attrs.gen_i += 1;1858 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
1859 break;1859 fn_walk->data.attrs.gen_i += 1;
1860 case FnWalkIdCall:1860 break;
1861 fn_walk->data.call.gen_param_values->append(val);1861 case FnWalkIdCall:
1862 break;1862 fn_walk->data.call.gen_param_values->append(val);
1863 case FnWalkIdTypes: {1863 break;
1864 ZigType *gen_type = get_pointer_to_type(g, ty, true);1864 case FnWalkIdTypes: {
1865 fn_walk->data.types.gen_param_types->append(get_llvm_type(g, gen_type));1865 ZigType *gen_type = get_pointer_to_type(g, ty, true);
1866 fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, gen_type));1866 fn_walk->data.types.gen_param_types->append(get_llvm_type(g, gen_type));
1867 break;1867 fn_walk->data.types.param_di_types->append(get_llvm_di_type(g, gen_type));
1868 }1868 break;
1869 case FnWalkIdVars: {
1870 var->value_ref = LLVMGetParam(llvm_fn, fn_walk->data.vars.gen_i);
1871 di_arg_index = fn_walk->data.vars.gen_i;
1872 dest_ty = get_pointer_to_type(g, ty, false);
1873 fn_walk->data.vars.gen_i += 1;
1874 goto var_ok;
1875 }
1876 case FnWalkIdInits:
1877 if (var->decl_node) {
1878 gen_var_debug_decl(g, var);
1879 }1869 }
1880 fn_walk->data.inits.gen_i += 1;1870 case FnWalkIdVars: {
1881 break;1871 var->value_ref = LLVMGetParam(llvm_fn, fn_walk->data.vars.gen_i);
1872 di_arg_index = fn_walk->data.vars.gen_i;
1873 dest_ty = get_pointer_to_type(g, ty, false);
1874 fn_walk->data.vars.gen_i += 1;
1875 goto var_ok;
1876 }
1877 case FnWalkIdInits:
1878 if (var->decl_node) {
1879 gen_var_debug_decl(g, var);
1880 }
1881 fn_walk->data.inits.gen_i += 1;
1882 break;
1883 }
1884 return true;
1882 }1885 }
1883 return true;
1884 }
18851886
1886 if (g->zig_target->arch == ZigLLVM_x86_64) {
1887 X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);1887 X64CABIClass abi_class = type_c_abi_x86_64_class(g, ty);
1888 size_t ty_size = type_size(g, ty);1888 size_t ty_size = type_size(g, ty);
1889 if (abi_class == X64CABIClass_MEMORY) {1889 if (abi_class == X64CABIClass_MEMORY || abi_class == X64CABIClass_MEMORY_nobyval) {
1890 assert(handle_is_ptr(ty));1890 assert(handle_is_ptr(ty));
1891 switch (fn_walk->id) {1891 switch (fn_walk->id) {
1892 case FnWalkIdAttrs:1892 case FnWalkIdAttrs:
1893 ZigLLVMAddByValAttr(llvm_fn, fn_walk->data.attrs.gen_i + 1, get_llvm_type(g, ty));1893 if (abi_class != X64CABIClass_MEMORY_nobyval) {
1894 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));1894 ZigLLVMAddByValAttr(llvm_fn, fn_walk->data.attrs.gen_i + 1, get_llvm_type(g, ty));
1895 addLLVMArgAttrInt(llvm_fn, fn_walk->data.attrs.gen_i, "align", get_abi_alignment(g, ty));
1896 } else if (g->zig_target->arch == ZigLLVM_aarch64 ||
1897 g->zig_target->arch == ZigLLVM_aarch64_be)
1898 {
1899 // no attrs needed
1900 } else {
1901 if (source_node != nullptr) {
1902 give_up_with_c_abi_error(g, source_node);
1903 }
1904 // otherwise allow codegen code to report a compile error
1905 return false;
1906 }
1907
1895 // Byvalue parameters must not have address 01908 // Byvalue parameters must not have address 0
1896 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");1909 addLLVMArgAttr(llvm_fn, fn_walk->data.attrs.gen_i, "nonnull");
1897 fn_walk->data.attrs.gen_i += 1;1910 fn_walk->data.attrs.gen_i += 1;