| author | |
| committer | |
| log | b77c423f773cdf05c95b293f44852ec5a39fc4ed |
| tree | e37dcaa0a6f8f48b67736800dc00b73f773cb86e |
| parent | f36255b670f2bcec368a9ce4622af194b5b71d70 |
3 files changed, 155 insertions(+), 141 deletions(-)
src/codegen.cpp+8-138| ... | ... | @@ -15,13 +15,7 @@ |
| 15 | 15 | #include "semantic_info.hpp" |
| 16 | 16 | |
| 17 | 17 | #include <stdio.h> |
| 18 | ||
| 19 | #include <llvm/IR/IRBuilder.h> | |
| 20 | #include <llvm/IR/DIBuilder.h> | |
| 21 | #include <llvm/IR/DiagnosticInfo.h> | |
| 22 | #include <llvm/IR/DiagnosticPrinter.h> | |
| 23 | #include <llvm/Target/TargetMachine.h> | |
| 24 | #include <llvm/Support/TargetParser.h> | |
| 18 | #include <errno.h> | |
| 25 | 19 | |
| 26 | 20 | CodeGen *create_codegen(AstNode *root, Buf *in_full_path) { |
| 27 | 21 | CodeGen *g = allocate<CodeGen>(1); |
| ... | ... | @@ -460,24 +454,16 @@ static void gen_block(CodeGen *g, AstNode *block_node, bool add_implicit_return) |
| 460 | 454 | static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProto *fn_proto, |
| 461 | 455 | LLVMZigDIFile *di_file) |
| 462 | 456 | { |
| 463 | llvm::SmallVector<llvm::Metadata *, 8> types; | |
| 464 | ||
| 465 | llvm::DIType *return_type = reinterpret_cast<llvm::DIType*>(to_llvm_debug_type(fn_proto->return_type)); | |
| 466 | types.push_back(return_type); | |
| 467 | ||
| 457 | LLVMZigDIType **types = allocate<LLVMZigDIType*>(1 + fn_proto->params.length); | |
| 458 | types[0] = to_llvm_debug_type(fn_proto->return_type); | |
| 459 | int types_len = fn_proto->params.length + 1; | |
| 468 | 460 | for (int i = 0; i < fn_proto->params.length; i += 1) { |
| 469 | 461 | AstNode *param_node = fn_proto->params.at(i); |
| 470 | 462 | assert(param_node->type == NodeTypeParamDecl); |
| 471 | llvm::DIType *param_type = reinterpret_cast<llvm::DIType*>(to_llvm_debug_type(param_node->data.param_decl.type)); | |
| 472 | types.push_back(param_type); | |
| 463 | LLVMZigDIType *param_type = to_llvm_debug_type(param_node->data.param_decl.type); | |
| 464 | types[i + 1] = param_type; | |
| 473 | 465 | } |
| 474 | ||
| 475 | llvm::DIBuilder *dibuilder = reinterpret_cast<llvm::DIBuilder*>(g->dbuilder); | |
| 476 | ||
| 477 | llvm::DISubroutineType *result = dibuilder->createSubroutineType( | |
| 478 | reinterpret_cast<llvm::DIFile*>(di_file), | |
| 479 | dibuilder->getOrCreateTypeArray(types)); | |
| 480 | return reinterpret_cast<LLVMZigDISubroutineType*>(result); | |
| 466 | return LLVMZigCreateSubroutineType(g->dbuilder, di_file, types, types_len, 0); | |
| 481 | 467 | } |
| 482 | 468 | |
| 483 | 469 | void code_gen(CodeGen *g) { |
| ... | ... | @@ -596,122 +582,6 @@ ZigList<ErrorMsg> *codegen_error_messages(CodeGen *g) { |
| 596 | 582 | return &g->errors; |
| 597 | 583 | } |
| 598 | 584 | |
| 599 | enum FloatAbi { | |
| 600 | FloatAbiHard, | |
| 601 | FloatAbiSoft, | |
| 602 | FloatAbiSoftFp, | |
| 603 | }; | |
| 604 | ||
| 605 | ||
| 606 | static int get_arm_sub_arch_version(const llvm::Triple &triple) { | |
| 607 | return llvm::ARMTargetParser::parseArchVersion(triple.getArchName()); | |
| 608 | } | |
| 609 | ||
| 610 | static FloatAbi get_float_abi(const llvm::Triple &triple) { | |
| 611 | switch (triple.getOS()) { | |
| 612 | case llvm::Triple::Darwin: | |
| 613 | case llvm::Triple::MacOSX: | |
| 614 | case llvm::Triple::IOS: | |
| 615 | if (get_arm_sub_arch_version(triple) == 6 || | |
| 616 | get_arm_sub_arch_version(triple) == 7) | |
| 617 | { | |
| 618 | return FloatAbiSoftFp; | |
| 619 | } else { | |
| 620 | return FloatAbiSoft; | |
| 621 | } | |
| 622 | case llvm::Triple::Win32: | |
| 623 | return FloatAbiHard; | |
| 624 | case llvm::Triple::FreeBSD: | |
| 625 | switch (triple.getEnvironment()) { | |
| 626 | case llvm::Triple::GNUEABIHF: | |
| 627 | return FloatAbiHard; | |
| 628 | default: | |
| 629 | return FloatAbiSoft; | |
| 630 | } | |
| 631 | default: | |
| 632 | switch (triple.getEnvironment()) { | |
| 633 | case llvm::Triple::GNUEABIHF: | |
| 634 | return FloatAbiHard; | |
| 635 | case llvm::Triple::GNUEABI: | |
| 636 | return FloatAbiSoftFp; | |
| 637 | case llvm::Triple::EABIHF: | |
| 638 | return FloatAbiHard; | |
| 639 | case llvm::Triple::EABI: | |
| 640 | return FloatAbiSoftFp; | |
| 641 | case llvm::Triple::Android: | |
| 642 | if (get_arm_sub_arch_version(triple) == 7) { | |
| 643 | return FloatAbiSoftFp; | |
| 644 | } else { | |
| 645 | return FloatAbiSoft; | |
| 646 | } | |
| 647 | default: | |
| 648 | return FloatAbiSoft; | |
| 649 | } | |
| 650 | } | |
| 651 | } | |
| 652 | ||
| 653 | static Buf *get_dynamic_linker(CodeGen *g) { | |
| 654 | llvm::TargetMachine *target_machine = reinterpret_cast<llvm::TargetMachine*>(g->target_machine); | |
| 655 | const llvm::Triple &triple = target_machine->getTargetTriple(); | |
| 656 | ||
| 657 | const llvm::Triple::ArchType arch = triple.getArch(); | |
| 658 | ||
| 659 | if (triple.getEnvironment() == llvm::Triple::Android) { | |
| 660 | if (triple.isArch64Bit()) { | |
| 661 | return buf_create_from_str("/system/bin/linker64"); | |
| 662 | } else { | |
| 663 | return buf_create_from_str("/system/bin/linker"); | |
| 664 | } | |
| 665 | } else if (arch == llvm::Triple::x86 || | |
| 666 | arch == llvm::Triple::sparc || | |
| 667 | arch == llvm::Triple::sparcel) | |
| 668 | { | |
| 669 | return buf_create_from_str("/lib/ld-linux.so.2"); | |
| 670 | } else if (arch == llvm::Triple::aarch64) { | |
| 671 | return buf_create_from_str("/lib/ld-linux-aarch64.so.1"); | |
| 672 | } else if (arch == llvm::Triple::aarch64_be) { | |
| 673 | return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1"); | |
| 674 | } else if (arch == llvm::Triple::arm || arch == llvm::Triple::thumb) { | |
| 675 | if (triple.getEnvironment() == llvm::Triple::GNUEABIHF || | |
| 676 | get_float_abi(triple) == FloatAbiHard) | |
| 677 | { | |
| 678 | return buf_create_from_str("/lib/ld-linux-armhf.so.3"); | |
| 679 | } else { | |
| 680 | return buf_create_from_str("/lib/ld-linux.so.3"); | |
| 681 | } | |
| 682 | } else if (arch == llvm::Triple::armeb || arch == llvm::Triple::thumbeb) { | |
| 683 | if (triple.getEnvironment() == llvm::Triple::GNUEABIHF || | |
| 684 | get_float_abi(triple) == FloatAbiHard) | |
| 685 | { | |
| 686 | return buf_create_from_str("/lib/ld-linux-armhf.so.3"); | |
| 687 | } else { | |
| 688 | return buf_create_from_str("/lib/ld-linux.so.3"); | |
| 689 | } | |
| 690 | } else if (arch == llvm::Triple::mips || arch == llvm::Triple::mipsel || | |
| 691 | arch == llvm::Triple::mips64 || arch == llvm::Triple::mips64el) | |
| 692 | { | |
| 693 | // when you want to solve this TODO, grep clang codebase for | |
| 694 | // getLinuxDynamicLinker | |
| 695 | zig_panic("TODO figure out MIPS dynamic linker name"); | |
| 696 | } else if (arch == llvm::Triple::ppc) { | |
| 697 | return buf_create_from_str("/lib/ld.so.1"); | |
| 698 | } else if (arch == llvm::Triple::ppc64) { | |
| 699 | return buf_create_from_str("/lib64/ld64.so.2"); | |
| 700 | } else if (arch == llvm::Triple::ppc64le) { | |
| 701 | return buf_create_from_str("/lib64/ld64.so.2"); | |
| 702 | } else if (arch == llvm::Triple::systemz) { | |
| 703 | return buf_create_from_str("/lib64/ld64.so.1"); | |
| 704 | } else if (arch == llvm::Triple::sparcv9) { | |
| 705 | return buf_create_from_str("/lib64/ld-linux.so.2"); | |
| 706 | } else if (arch == llvm::Triple::x86_64 && | |
| 707 | triple.getEnvironment() == llvm::Triple::GNUX32) | |
| 708 | { | |
| 709 | return buf_create_from_str("/libx32/ld-linux-x32.so.2"); | |
| 710 | } else { | |
| 711 | return buf_create_from_str("/lib64/ld-linux-x86-64.so.2"); | |
| 712 | } | |
| 713 | } | |
| 714 | ||
| 715 | 585 | static Buf *to_c_type(CodeGen *g, AstNode *type_node) { |
| 716 | 586 | assert(type_node->type == NodeTypeType); |
| 717 | 587 | assert(type_node->codegen_node); |
| ... | ... | @@ -865,7 +735,7 @@ void code_gen_link(CodeGen *g, const char *out_file) { |
| 865 | 735 | } |
| 866 | 736 | } else { |
| 867 | 737 | args.append("-dynamic-linker"); |
| 868 | args.append(buf_ptr(get_dynamic_linker(g))); | |
| 738 | args.append(buf_ptr(get_dynamic_linker(g->target_machine))); | |
| 869 | 739 | } |
| 870 | 740 | |
| 871 | 741 | if (g->out_type == OutTypeLib) { |
src/zig_llvm.cpp+136-3| ... | ... | @@ -19,6 +19,7 @@ |
| 19 | 19 | #include <llvm/MC/SubtargetFeature.h> |
| 20 | 20 | #include <llvm/Support/raw_ostream.h> |
| 21 | 21 | #include <llvm/Support/FileSystem.h> |
| 22 | #include <llvm/Support/TargetParser.h> | |
| 22 | 23 | #include <llvm/Target/TargetMachine.h> |
| 23 | 24 | #include <llvm/IR/LegacyPassManager.h> |
| 24 | 25 | #include <llvm/IR/Module.h> |
| ... | ... | @@ -148,6 +149,22 @@ LLVMZigDIType *LLVMZigCreateDebugBasicType(LLVMZigDIBuilder *dibuilder, const ch |
| 148 | 149 | return reinterpret_cast<LLVMZigDIType*>(di_type); |
| 149 | 150 | } |
| 150 | 151 | |
| 152 | LLVMZigDISubroutineType *LLVMZigCreateSubroutineType(LLVMZigDIBuilder *dibuilder_wrapped, | |
| 153 | LLVMZigDIFile *file, LLVMZigDIType **types_array, int types_array_len, unsigned flags) | |
| 154 | { | |
| 155 | SmallVector<Metadata *, 8> types; | |
| 156 | for (int i = 0; i < types_array_len; i += 1) { | |
| 157 | DIType *ditype = reinterpret_cast<DIType*>(types_array[i]); | |
| 158 | types.push_back(ditype); | |
| 159 | } | |
| 160 | DIBuilder *dibuilder = reinterpret_cast<DIBuilder*>(dibuilder_wrapped); | |
| 161 | DISubroutineType *subroutine_type = dibuilder->createSubroutineType( | |
| 162 | reinterpret_cast<DIFile*>(file), | |
| 163 | dibuilder->getOrCreateTypeArray(types), | |
| 164 | flags); | |
| 165 | return reinterpret_cast<LLVMZigDISubroutineType*>(subroutine_type); | |
| 166 | } | |
| 167 | ||
| 151 | 168 | unsigned LLVMZigEncoding_DW_ATE_unsigned(void) { |
| 152 | 169 | return dwarf::DW_ATE_unsigned; |
| 153 | 170 | } |
| ... | ... | @@ -161,12 +178,12 @@ unsigned LLVMZigLang_DW_LANG_C99(void) { |
| 161 | 178 | } |
| 162 | 179 | |
| 163 | 180 | LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) { |
| 164 | DIBuilder *di_builder = new DIBuilder(*llvm::unwrap(module), allow_unresolved); | |
| 181 | DIBuilder *di_builder = new DIBuilder(*unwrap(module), allow_unresolved); | |
| 165 | 182 | return reinterpret_cast<LLVMZigDIBuilder *>(di_builder); |
| 166 | 183 | } |
| 167 | 184 | |
| 168 | 185 | void LLVMZigSetCurrentDebugLocation(LLVMBuilderRef builder, int line, int column, LLVMZigDIScope *scope) { |
| 169 | unwrap(builder)->SetCurrentDebugLocation(llvm::DebugLoc::get( | |
| 186 | unwrap(builder)->SetCurrentDebugLocation(DebugLoc::get( | |
| 170 | 187 | line, column, reinterpret_cast<DIScope*>(scope))); |
| 171 | 188 | } |
| 172 | 189 | |
| ... | ... | @@ -223,7 +240,7 @@ LLVMZigDISubprogram *LLVMZigCreateFunction(LLVMZigDIBuilder *dibuilder, LLVMZigD |
| 223 | 240 | LLVMZigDISubroutineType *ty, bool is_local_to_unit, bool is_definition, unsigned scope_line, |
| 224 | 241 | unsigned flags, bool is_optimized, LLVMValueRef function) |
| 225 | 242 | { |
| 226 | llvm::Function *unwrapped_function = reinterpret_cast<llvm::Function*>(unwrap(function)); | |
| 243 | Function *unwrapped_function = reinterpret_cast<Function*>(unwrap(function)); | |
| 227 | 244 | DISubprogram *result = reinterpret_cast<DIBuilder*>(dibuilder)->createFunction( |
| 228 | 245 | reinterpret_cast<DIScope*>(scope), |
| 229 | 246 | name, linkage_name, |
| ... | ... | @@ -237,3 +254,119 @@ LLVMZigDISubprogram *LLVMZigCreateFunction(LLVMZigDIBuilder *dibuilder, LLVMZigD |
| 237 | 254 | void LLVMZigDIBuilderFinalize(LLVMZigDIBuilder *dibuilder) { |
| 238 | 255 | reinterpret_cast<DIBuilder*>(dibuilder)->finalize(); |
| 239 | 256 | } |
| 257 | ||
| 258 | enum FloatAbi { | |
| 259 | FloatAbiHard, | |
| 260 | FloatAbiSoft, | |
| 261 | FloatAbiSoftFp, | |
| 262 | }; | |
| 263 | ||
| 264 | static int get_arm_sub_arch_version(const Triple &triple) { | |
| 265 | return ARMTargetParser::parseArchVersion(triple.getArchName()); | |
| 266 | } | |
| 267 | ||
| 268 | static FloatAbi get_float_abi(const Triple &triple) { | |
| 269 | switch (triple.getOS()) { | |
| 270 | case Triple::Darwin: | |
| 271 | case Triple::MacOSX: | |
| 272 | case Triple::IOS: | |
| 273 | if (get_arm_sub_arch_version(triple) == 6 || | |
| 274 | get_arm_sub_arch_version(triple) == 7) | |
| 275 | { | |
| 276 | return FloatAbiSoftFp; | |
| 277 | } else { | |
| 278 | return FloatAbiSoft; | |
| 279 | } | |
| 280 | case Triple::Win32: | |
| 281 | return FloatAbiHard; | |
| 282 | case Triple::FreeBSD: | |
| 283 | switch (triple.getEnvironment()) { | |
| 284 | case Triple::GNUEABIHF: | |
| 285 | return FloatAbiHard; | |
| 286 | default: | |
| 287 | return FloatAbiSoft; | |
| 288 | } | |
| 289 | default: | |
| 290 | switch (triple.getEnvironment()) { | |
| 291 | case Triple::GNUEABIHF: | |
| 292 | return FloatAbiHard; | |
| 293 | case Triple::GNUEABI: | |
| 294 | return FloatAbiSoftFp; | |
| 295 | case Triple::EABIHF: | |
| 296 | return FloatAbiHard; | |
| 297 | case Triple::EABI: | |
| 298 | return FloatAbiSoftFp; | |
| 299 | case Triple::Android: | |
| 300 | if (get_arm_sub_arch_version(triple) == 7) { | |
| 301 | return FloatAbiSoftFp; | |
| 302 | } else { | |
| 303 | return FloatAbiSoft; | |
| 304 | } | |
| 305 | default: | |
| 306 | return FloatAbiSoft; | |
| 307 | } | |
| 308 | } | |
| 309 | } | |
| 310 | ||
| 311 | Buf *get_dynamic_linker(LLVMTargetMachineRef target_machine_ref) { | |
| 312 | TargetMachine *target_machine = reinterpret_cast<TargetMachine*>(target_machine_ref); | |
| 313 | const Triple &triple = target_machine->getTargetTriple(); | |
| 314 | ||
| 315 | const Triple::ArchType arch = triple.getArch(); | |
| 316 | ||
| 317 | if (triple.getEnvironment() == Triple::Android) { | |
| 318 | if (triple.isArch64Bit()) { | |
| 319 | return buf_create_from_str("/system/bin/linker64"); | |
| 320 | } else { | |
| 321 | return buf_create_from_str("/system/bin/linker"); | |
| 322 | } | |
| 323 | } else if (arch == Triple::x86 || | |
| 324 | arch == Triple::sparc || | |
| 325 | arch == Triple::sparcel) | |
| 326 | { | |
| 327 | return buf_create_from_str("/lib/ld-linux.so.2"); | |
| 328 | } else if (arch == Triple::aarch64) { | |
| 329 | return buf_create_from_str("/lib/ld-linux-aarch64.so.1"); | |
| 330 | } else if (arch == Triple::aarch64_be) { | |
| 331 | return buf_create_from_str("/lib/ld-linux-aarch64_be.so.1"); | |
| 332 | } else if (arch == Triple::arm || arch == Triple::thumb) { | |
| 333 | if (triple.getEnvironment() == Triple::GNUEABIHF || | |
| 334 | get_float_abi(triple) == FloatAbiHard) | |
| 335 | { | |
| 336 | return buf_create_from_str("/lib/ld-linux-armhf.so.3"); | |
| 337 | } else { | |
| 338 | return buf_create_from_str("/lib/ld-linux.so.3"); | |
| 339 | } | |
| 340 | } else if (arch == Triple::armeb || arch == Triple::thumbeb) { | |
| 341 | if (triple.getEnvironment() == Triple::GNUEABIHF || | |
| 342 | get_float_abi(triple) == FloatAbiHard) | |
| 343 | { | |
| 344 | return buf_create_from_str("/lib/ld-linux-armhf.so.3"); | |
| 345 | } else { | |
| 346 | return buf_create_from_str("/lib/ld-linux.so.3"); | |
| 347 | } | |
| 348 | } else if (arch == Triple::mips || arch == Triple::mipsel || | |
| 349 | arch == Triple::mips64 || arch == Triple::mips64el) | |
| 350 | { | |
| 351 | // when you want to solve this TODO, grep clang codebase for | |
| 352 | // getLinuxDynamicLinker | |
| 353 | zig_panic("TODO figure out MIPS dynamic linker name"); | |
| 354 | } else if (arch == Triple::ppc) { | |
| 355 | return buf_create_from_str("/lib/ld.so.1"); | |
| 356 | } else if (arch == Triple::ppc64) { | |
| 357 | return buf_create_from_str("/lib64/ld64.so.2"); | |
| 358 | } else if (arch == Triple::ppc64le) { | |
| 359 | return buf_create_from_str("/lib64/ld64.so.2"); | |
| 360 | } else if (arch == Triple::systemz) { | |
| 361 | return buf_create_from_str("/lib64/ld64.so.1"); | |
| 362 | } else if (arch == Triple::sparcv9) { | |
| 363 | return buf_create_from_str("/lib64/ld-linux.so.2"); | |
| 364 | } else if (arch == Triple::x86_64 && | |
| 365 | triple.getEnvironment() == Triple::GNUX32) | |
| 366 | { | |
| 367 | return buf_create_from_str("/libx32/ld-linux-x32.so.2"); | |
| 368 | } else { | |
| 369 | return buf_create_from_str("/lib64/ld-linux-x86-64.so.2"); | |
| 370 | } | |
| 371 | } | |
| 372 |
src/zig_llvm.hpp+11| ... | ... | @@ -42,6 +42,9 @@ LLVMZigDIType *LLVMZigCreateDebugPointerType(LLVMZigDIBuilder *dibuilder, LLVMZi |
| 42 | 42 | LLVMZigDIType *LLVMZigCreateDebugBasicType(LLVMZigDIBuilder *dibuilder, const char *name, |
| 43 | 43 | uint64_t size_in_bits, uint64_t align_in_bits, unsigned encoding); |
| 44 | 44 | |
| 45 | LLVMZigDISubroutineType *LLVMZigCreateSubroutineType(LLVMZigDIBuilder *dibuilder_wrapped, | |
| 46 | LLVMZigDIFile *file, LLVMZigDIType **types_array, int types_array_len, unsigned flags); | |
| 47 | ||
| 45 | 48 | unsigned LLVMZigEncoding_DW_ATE_unsigned(void); |
| 46 | 49 | unsigned LLVMZigEncoding_DW_ATE_signed(void); |
| 47 | 50 | unsigned LLVMZigLang_DW_LANG_C99(void); |
| ... | ... | @@ -72,4 +75,12 @@ LLVMZigDISubprogram *LLVMZigCreateFunction(LLVMZigDIBuilder *dibuilder, LLVMZigD |
| 72 | 75 | |
| 73 | 76 | void LLVMZigDIBuilderFinalize(LLVMZigDIBuilder *dibuilder); |
| 74 | 77 | |
| 78 | ||
| 79 | /* | |
| 80 | * This stuff is not LLVM API but it depends on the LLVM C++ API so we put it here. | |
| 81 | */ | |
| 82 | #include "buffer.hpp" | |
| 83 | ||
| 84 | Buf *get_dynamic_linker(LLVMTargetMachineRef target_machine); | |
| 85 | ||
| 75 | 86 | #endif |