| ... | @@ -17,6 +17,8 @@ | ... | @@ -17,6 +17,8 @@ |
| 17 | #include <llvm/IR/DIBuilder.h> | 17 | #include <llvm/IR/DIBuilder.h> |
| 18 | #include <llvm/IR/DiagnosticInfo.h> | 18 | #include <llvm/IR/DiagnosticInfo.h> |
| 19 | #include <llvm/IR/DiagnosticPrinter.h> | 19 | #include <llvm/IR/DiagnosticPrinter.h> |
| | 20 | #include <llvm/Target/TargetMachine.h> |
| | 21 | #include <llvm/Support/TargetParser.h> |
| 20 | | 22 | |
| 21 | struct FnTableEntry { | 23 | struct FnTableEntry { |
| 22 | LLVMValueRef fn_value; | 24 | LLVMValueRef fn_value; |
| ... | @@ -66,6 +68,7 @@ struct CodeGen { | ... | @@ -66,6 +68,7 @@ struct CodeGen { |
| 66 | bool strip_debug_symbols; | 68 | bool strip_debug_symbols; |
| 67 | CodeGenBuildType build_type; | 69 | CodeGenBuildType build_type; |
| 68 | LLVMTargetMachineRef target_machine; | 70 | LLVMTargetMachineRef target_machine; |
| | 71 | bool is_native_target; |
| 69 | Buf in_file; | 72 | Buf in_file; |
| 70 | Buf in_dir; | 73 | Buf in_dir; |
| 71 | ZigList<llvm::DIScope *> block_scopes; | 74 | ZigList<llvm::DIScope *> block_scopes; |
| ... | @@ -423,6 +426,7 @@ void semantic_analyze(CodeGen *g) { | ... | @@ -423,6 +426,7 @@ void semantic_analyze(CodeGen *g) { |
| 423 | LLVMInitializeAllAsmParsers(); | 426 | LLVMInitializeAllAsmParsers(); |
| 424 | LLVMInitializeNativeTarget(); | 427 | LLVMInitializeNativeTarget(); |
| 425 | | 428 | |
| | 429 | g->is_native_target = true; |
| 426 | char *native_triple = LLVMGetDefaultTargetTriple(); | 430 | char *native_triple = LLVMGetDefaultTargetTriple(); |
| 427 | | 431 | |
| 428 | LLVMTargetRef target_ref; | 432 | LLVMTargetRef target_ref; |
| ... | @@ -699,6 +703,121 @@ ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) { | ... | @@ -699,6 +703,121 @@ ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) { |
| 699 | return &g->errors; | 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 | void code_gen_link(CodeGen *g, const char *out_file) { | 822 | void code_gen_link(CodeGen *g, const char *out_file) { |
| 704 | LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry(); | 823 | LLVMPassRegistryRef registry = LLVMGetGlobalPassRegistry(); |
| ... | @@ -721,13 +840,21 @@ void code_gen_link(CodeGen *g, const char *out_file) { | ... | @@ -721,13 +840,21 @@ void code_gen_link(CodeGen *g, const char *out_file) { |
| 721 | if (g->is_static) { | 840 | if (g->is_static) { |
| 722 | args.append("-static"); | 841 | args.append("-static"); |
| 723 | } | 842 | } |
| 724 | if (getenv("ZIG_DEBIAN_HACK") != nullptr) { | 843 | |
| 725 | // XXX: hack. see https://github.com/andrewrk/zig/issues/1 | 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 | args.append("-dynamic-linker"); | 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 | args.append("-o"); | 855 | args.append("-o"); |
| 730 | args.append(out_file); | 856 | args.append(out_file); |
| | 857 | |
| 731 | args.append((const char *)buf_ptr(&out_file_o)); | 858 | args.append((const char *)buf_ptr(&out_file_o)); |
| 732 | | 859 | |
| 733 | auto it = g->link_table.entry_iterator(); | 860 | auto it = g->link_table.entry_iterator(); |
| ... | @@ -742,3 +869,5 @@ void code_gen_link(CodeGen *g, const char *out_file) { | ... | @@ -742,3 +869,5 @@ void code_gen_link(CodeGen *g, const char *out_file) { |
| 742 | | 869 | |
| 743 | os_spawn_process("ld", args, false); | 870 | os_spawn_process("ld", args, false); |
| 744 | } | 871 | } |
| | 872 | |
| | 873 | |