| ... | ... | @@ -17,6 +17,8 @@ |
| 17 | 17 | #include <llvm/IR/DIBuilder.h> |
| 18 | 18 | #include <llvm/IR/DiagnosticInfo.h> |
| 19 | 19 | #include <llvm/IR/DiagnosticPrinter.h> |
| 20 | #include <llvm/Target/TargetMachine.h> |
| 21 | #include <llvm/Support/TargetParser.h> |
| 20 | 22 | |
| 21 | 23 | struct FnTableEntry { |
| 22 | 24 | LLVMValueRef fn_value; |
| ... | ... | @@ -66,6 +68,7 @@ struct CodeGen { |
| 66 | 68 | bool strip_debug_symbols; |
| 67 | 69 | CodeGenBuildType build_type; |
| 68 | 70 | LLVMTargetMachineRef target_machine; |
| 71 | bool is_native_target; |
| 69 | 72 | Buf in_file; |
| 70 | 73 | Buf in_dir; |
| 71 | 74 | ZigList<llvm::DIScope *> block_scopes; |
| ... | ... | @@ -423,6 +426,7 @@ void semantic_analyze(CodeGen *g) { |
| 423 | 426 | LLVMInitializeAllAsmParsers(); |
| 424 | 427 | LLVMInitializeNativeTarget(); |
| 425 | 428 | |
| 429 | g->is_native_target = true; |
| 426 | 430 | char *native_triple = LLVMGetDefaultTargetTriple(); |
| 427 | 431 | |
| 428 | 432 | LLVMTargetRef target_ref; |
| ... | ... | @@ -699,6 +703,121 @@ ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) { |
| 699 | 703 | return &g->errors; |
| 700 | 704 | } |
| 701 | 705 | |
| 706 | enum FloatAbi { |
| 707 | FloatAbiHard, |
| 708 | FloatAbiSoft, |
| 709 | FloatAbiSoftFp, |
| 710 | }; |
| 711 | |
| 712 | |
| 713 | static int get_arm_sub_arch_version(const llvm::Triple &triple) { |
| 714 | return llvm::ARMTargetParser::parseArchVersion(triple.getArchName()); |
| 715 | } |
| 716 | |
| 717 | static FloatAbi get_float_abi(const llvm::Triple &triple) { |
| 718 | switch (triple.getOS()) { |
| 719 | case llvm::Triple::Darwin: |
| 720 | case llvm::Triple::MacOSX: |
| 721 | case llvm::Triple::IOS: |
| 722 | if (get_arm_sub_arch_version(triple) == 6 || |
| 723 | get_arm_sub_arch_version(triple) == 7) |
| 724 | { |
| 725 | return FloatAbiSoftFp; |
| 726 | } else { |
| 727 | return FloatAbiSoft; |
| 728 | } |
| 729 | case llvm::Triple::Win32: |
| 730 | return FloatAbiHard; |
| 731 | case llvm::Triple::FreeBSD: |
| 732 | switch (triple.getEnvironment()) { |
| 733 | case llvm::Triple::GNUEABIHF: |
| 734 | return FloatAbiHard; |
| 735 | default: |
| 736 | return FloatAbiSoft; |
| 737 | } |
| 738 | default: |
| 739 | switch (triple.getEnvironment()) { |
| 740 | case llvm::Triple::GNUEABIHF: |
| 741 | return FloatAbiHard; |
| 742 | case llvm::Triple::GNUEABI: |
| 743 | return FloatAbiSoftFp; |
| 744 | case llvm::Triple::EABIHF: |
| 745 | return FloatAbiHard; |
| 746 | case llvm::Triple::EABI: |
| 747 | return FloatAbiSoftFp; |
| 748 | case llvm::Triple::Android: |
| 749 | if (get_arm_sub_arch_version(triple) == 7) { |
| 750 | return FloatAbiSoftFp; |
| 751 | } else { |
| 752 | return FloatAbiSoft; |
| 753 | } |
| 754 | default: |
| 755 | return FloatAbiSoft; |
| 756 | } |
| 757 | } |
| 758 | } |
| 759 | |
| 760 | static Buf *get_dynamic_linker(CodeGen *g) { |
| 761 | llvm::TargetMachine *target_machine = reinterpret_cast<llvm::TargetMachine*>(g->target_machine); |
| 762 | const llvm::Triple &triple = target_machine->getTargetTriple(); |
| 763 | |
| 764 | const llvm::Triple::ArchType arch = triple.getArch(); |
| 765 | |
| 766 | if (triple.getEnvironment() == llvm::Triple::Android) { |
| 767 | if (triple.isArch64Bit()) { |
| 768 | return buf_create_from_str("/system/bin/linker64"); |
| 769 | } else { |
| 770 | return buf_create_from_str("/system/bin/linker"); |
| 771 | } |
| 772 | } else if (arch == llvm::Triple::x86 || |
| 773 | arch == llvm::Triple::sparc || |
| 774 | arch == llvm::Triple::sparcel) |
| 775 | { |
| 776 | return buf_create_from_str("/lib/ld-linux.so.2"); |
| 777 | } else if (arch == llvm::Triple::aarch64) { |
| 778 | return buf_create_from_str("/lib/ld-linux-aarch64.so.1"); |
| 779 | } else if (arch == llvm::Triple::aarch64_be) { |
| 780 | return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1"); |
| 781 | } else if (arch == llvm::Triple::arm || arch == llvm::Triple::thumb) { |
| 782 | if (triple.getEnvironment() == llvm::Triple::GNUEABIHF || |
| 783 | get_float_abi(triple) == FloatAbiHard) |
| 784 | { |
| 785 | return buf_create_from_str("/lib/ld-linux-armhf.so.3"); |
| 786 | } else { |
| 787 | return buf_create_from_str("/lib/ld-linux.so.3"); |
| 788 | } |
| 789 | } else if (arch == llvm::Triple::armeb || arch == llvm::Triple::thumbeb) { |
| 790 | if (triple.getEnvironment() == llvm::Triple::GNUEABIHF || |
| 791 | get_float_abi(triple) == FloatAbiHard) |
| 792 | { |
| 793 | return buf_create_from_str("/lib/ld-linux-armhf.so.3"); |
| 794 | } else { |
| 795 | return buf_create_from_str("/lib/ld-linux.so.3"); |
| 796 | } |
| 797 | } else if (arch == llvm::Triple::mips || arch == llvm::Triple::mipsel || |
| 798 | arch == llvm::Triple::mips64 || arch == llvm::Triple::mips64el) |
| 799 | { |
| 800 | // when you want to solve this TODO, grep clang codebase for |
| 801 | // getLinuxDynamicLinker |
| 802 | zig_panic("TODO figure out MIPS dynamic linker name"); |
| 803 | } else if (arch == llvm::Triple::ppc) { |
| 804 | return buf_create_from_str("/lib/ld.so.1"); |
| 805 | } else if (arch == llvm::Triple::ppc64) { |
| 806 | return buf_create_from_str("/lib64/ld64.so.2"); |
| 807 | } else if (arch == llvm::Triple::ppc64le) { |
| 808 | return buf_create_from_str("/lib64/ld64.so.2"); |
| 809 | } else if (arch == llvm::Triple::systemz) { |
| 810 | return buf_create_from_str("/lib64/ld64.so.1"); |
| 811 | } else if (arch == llvm::Triple::sparcv9) { |
| 812 | return buf_create_from_str("/lib64/ld-linux.so.2"); |
| 813 | } else if (arch == llvm::Triple::x86_64 && |
| 814 | triple.getEnvironment() == llvm::Triple::GNUX32) |
| 815 | { |
| 816 | return buf_create_from_str("/libx32/ld-linux-x32.so.2"); |
| 817 | } else { |
| 818 | return buf_create_from_str("/lib64/ld-linux-x86-64.so.2"); |
| 819 | } |
| 820 | } |
| 702 | 821 | |
| 703 | 822 | void code_gen_link(CodeGen *g, const char *out_file) { |
| 704 | 823 | LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry(); |
| ... | ... | @@ -721,13 +840,21 @@ void code_gen_link(CodeGen *g, const char *out_file) { |
| 721 | 840 | if (g->is_static) { |
| 722 | 841 | args.append("-static"); |
| 723 | 842 | } |
| 724 | | if (getenv("ZIG_DEBIAN_HACK") != nullptr) { |
| 725 | | // XXX: hack. see https://github.com/andrewrk/zig/issues/1 |
| 843 | |
| 844 | char *ZIG_NATIVE_DYNAMIC_LINKER = getenv("ZIG_NATIVE_DYNAMIC_LINKER"); |
| 845 | if (g->is_native_target && ZIG_NATIVE_DYNAMIC_LINKER) { |
| 846 | if (ZIG_NATIVE_DYNAMIC_LINKER[0] != 0) { |
| 847 | args.append("-dynamic-linker"); |
| 848 | args.append(ZIG_NATIVE_DYNAMIC_LINKER); |
| 849 | } |
| 850 | } else { |
| 726 | 851 | args.append("-dynamic-linker"); |
| 727 | | args.append("/lib64/ld-linux-x86-64.so.2"); |
| 852 | args.append(buf_ptr(get_dynamic_linker(g))); |
| 728 | 853 | } |
| 854 | |
| 729 | 855 | args.append("-o"); |
| 730 | 856 | args.append(out_file); |
| 857 | |
| 731 | 858 | args.append((const char *)buf_ptr(&out_file_o)); |
| 732 | 859 | |
| 733 | 860 | auto it = g->link_table.entry_iterator(); |
| ... | ... | @@ -742,3 +869,5 @@ void code_gen_link(CodeGen *g, const char *out_file) { |
| 742 | 869 | |
| 743 | 870 | os_spawn_process("ld", args, false); |
| 744 | 871 | } |
| 872 | |
| 873 | |