diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2022-09-13 15:39:19 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-09-13 15:39:19 -0700 |
| commit | 716d9237cb757c15217b21964fde8e755aabe853 (patch) | |
| tree | 92760021e4d49af92db2d37701f4a303d32d69ac /src | |
| parent | fda6d44778f3faf53c66945a0db65be68113416f (diff) | |
| parent | 0a4cfb81bcca0ca514758049f8d7d99224537f93 (diff) | |
| download | zig-716d9237cb757c15217b21964fde8e755aabe853.tar.gz zig-716d9237cb757c15217b21964fde8e755aabe853.zip | |
Merge remote-tracking branch 'origin/llvm15'
Upgrade to LLVM 15
Diffstat (limited to 'src')
| -rw-r--r-- | src/Compilation.zig | 11 | ||||
| -rw-r--r-- | src/clang.zig | 23 | ||||
| -rw-r--r-- | src/clang_options_data.zig | 295 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 674 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 56 | ||||
| -rw-r--r-- | src/libcxx.zig | 31 | ||||
| -rw-r--r-- | src/libunwind.zig | 29 | ||||
| -rw-r--r-- | src/link.zig | 3 | ||||
| -rw-r--r-- | src/link/Elf.zig | 2 | ||||
| -rw-r--r-- | src/link/Wasm.zig | 2 | ||||
| -rw-r--r-- | src/stage1/all_types.hpp | 2 | ||||
| -rw-r--r-- | src/stage1/analyze.cpp | 4 | ||||
| -rw-r--r-- | src/stage1/codegen.cpp | 911 | ||||
| -rw-r--r-- | src/stage1/stage1.h | 3 | ||||
| -rw-r--r-- | src/stage1/target.cpp | 57 | ||||
| -rw-r--r-- | src/stage1/zig0.cpp | 6 | ||||
| -rw-r--r-- | src/target.zig | 24 | ||||
| -rw-r--r-- | src/type.zig | 8 | ||||
| -rw-r--r-- | src/zig_clang.cpp | 46 | ||||
| -rw-r--r-- | src/zig_clang.h | 55 | ||||
| -rw-r--r-- | src/zig_clang_cc1_main.cpp | 14 | ||||
| -rw-r--r-- | src/zig_clang_cc1as_main.cpp | 28 | ||||
| -rw-r--r-- | src/zig_clang_driver.cpp | 66 | ||||
| -rw-r--r-- | src/zig_llvm-ar.cpp | 327 | ||||
| -rw-r--r-- | src/zig_llvm.cpp | 17 | ||||
| -rw-r--r-- | src/zig_llvm.h | 47 |
26 files changed, 1902 insertions, 839 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index 5a1abcb52b..18dab183a5 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -154,6 +154,8 @@ owned_link_dir: ?std.fs.Dir, /// Don't use this for anything other than stage1 compatibility. color: Color = .auto, +libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default, + /// This mutex guards all `Compilation` mutable state. mutex: std.Thread.Mutex = .{}, @@ -950,6 +952,7 @@ pub const InitOptions = struct { headerpad_max_install_names: bool = false, /// (Darwin) remove dylibs that are unreachable by the entry point or exported symbols dead_strip_dylibs: bool = false, + libcxx_abi_version: libcxx.AbiVersion = libcxx.AbiVersion.default, }; fn addPackageTableToCacheHash( @@ -1843,6 +1846,7 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { .test_evented_io = options.test_evented_io, .debug_compiler_runtime_libs = options.debug_compiler_runtime_libs, .debug_compile_errors = options.debug_compile_errors, + .libcxx_abi_version = options.libcxx_abi_version, }; break :comp comp; }; @@ -4026,6 +4030,13 @@ pub fn addCCArgs( if (comp.bin_file.options.single_threaded) { try argv.append("-D_LIBCPP_HAS_NO_THREADS"); } + + try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_VERSION={d}", .{ + @enumToInt(comp.libcxx_abi_version), + })); + try argv.append(try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{ + @enumToInt(comp.libcxx_abi_version), + })); } if (comp.bin_file.options.link_libunwind) { diff --git a/src/clang.zig b/src/clang.zig index 40dacc5df8..205a3cccc6 100644 --- a/src/clang.zig +++ b/src/clang.zig @@ -859,7 +859,7 @@ pub const StmtExpr = opaque { pub const StringLiteral = opaque { pub const getKind = ZigClangStringLiteral_getKind; - extern fn ZigClangStringLiteral_getKind(*const StringLiteral) StringLiteral_StringKind; + extern fn ZigClangStringLiteral_getKind(*const StringLiteral) CharacterLiteral_CharacterKind; pub const getCodeUnit = ZigClangStringLiteral_getCodeUnit; extern fn ZigClangStringLiteral_getCodeUnit(*const StringLiteral, usize) u32; @@ -1117,6 +1117,7 @@ pub const TypeClass = enum(c_int) { VariableArray, Atomic, Attributed, + BTFTagAttributed, BitInt, BlockPointer, Builtin, @@ -1202,25 +1203,33 @@ const StmtClass = enum(c_int) { OMPForDirectiveClass, OMPForSimdDirectiveClass, OMPGenericLoopDirectiveClass, + OMPMaskedTaskLoopDirectiveClass, + OMPMaskedTaskLoopSimdDirectiveClass, OMPMasterTaskLoopDirectiveClass, OMPMasterTaskLoopSimdDirectiveClass, OMPParallelForDirectiveClass, OMPParallelForSimdDirectiveClass, + OMPParallelGenericLoopDirectiveClass, + OMPParallelMaskedTaskLoopDirectiveClass, + OMPParallelMaskedTaskLoopSimdDirectiveClass, OMPParallelMasterTaskLoopDirectiveClass, OMPParallelMasterTaskLoopSimdDirectiveClass, OMPSimdDirectiveClass, OMPTargetParallelForSimdDirectiveClass, + OMPTargetParallelGenericLoopDirectiveClass, OMPTargetSimdDirectiveClass, OMPTargetTeamsDistributeDirectiveClass, OMPTargetTeamsDistributeParallelForDirectiveClass, OMPTargetTeamsDistributeParallelForSimdDirectiveClass, OMPTargetTeamsDistributeSimdDirectiveClass, + OMPTargetTeamsGenericLoopDirectiveClass, OMPTaskLoopDirectiveClass, OMPTaskLoopSimdDirectiveClass, OMPTeamsDistributeDirectiveClass, OMPTeamsDistributeParallelForDirectiveClass, OMPTeamsDistributeParallelForSimdDirectiveClass, OMPTeamsDistributeSimdDirectiveClass, + OMPTeamsGenericLoopDirectiveClass, OMPTileDirectiveClass, OMPUnrollDirectiveClass, OMPMaskedDirectiveClass, @@ -1228,6 +1237,7 @@ const StmtClass = enum(c_int) { OMPMetaDirectiveClass, OMPOrderedDirectiveClass, OMPParallelDirectiveClass, + OMPParallelMaskedDirectiveClass, OMPParallelMasterDirectiveClass, OMPParallelSectionsDirectiveClass, OMPScanDirectiveClass, @@ -1532,6 +1542,7 @@ pub const DeclKind = enum(c_int) { OMPDeclareMapper, OMPDeclareReduction, TemplateParamObject, + UnnamedGlobalConstant, UnresolvedUsingValue, OMPAllocate, OMPRequires, @@ -1805,6 +1816,8 @@ pub const CallingConv = enum(c_int) { PreserveMost, PreserveAll, AArch64VectorCall, + AArch64SVEPCS, + AMDGPUKernelCall, }; pub const StorageClass = enum(c_int) { @@ -1826,14 +1839,6 @@ pub const APFloat_roundingMode = enum(i8) { Invalid = -1, }; -pub const StringLiteral_StringKind = enum(c_int) { - Ascii, - Wide, - UTF8, - UTF16, - UTF32, -}; - pub const CharacterLiteral_CharacterKind = enum(c_int) { Ascii, Wide, diff --git a/src/clang_options_data.zig b/src/clang_options_data.zig index 90ba377847..edabac2da6 100644 --- a/src/clang_options_data.zig +++ b/src/clang_options_data.zig @@ -144,7 +144,9 @@ flagpd1("Wframe-larger-than"), flagpd1("Wlarge-by-value-copy"), flagpd1("Wno-deprecated"), flagpd1("Wno-rewrite-macros"), +flagpd1("Wno-system-headers"), flagpd1("Wno-write-strings"), +flagpd1("Wsystem-headers"), flagpd1("Wwrite-strings"), flagpd1("X"), sepd1("Xanalyzer"), @@ -243,14 +245,6 @@ sepd1("Zlinker-input"), .psl = true, }, .{ - .name = "FA", - .syntax = .flag, - .zig_equivalent = .other, - .pd1 = true, - .pd2 = false, - .psl = true, -}, -.{ .name = "FC", .syntax = .flag, .zig_equivalent = .other, @@ -539,6 +533,14 @@ sepd1("Zlinker-input"), .psl = true, }, .{ + .name = "JMC-", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ .name = "LD", .syntax = .flag, .zig_equivalent = .other, @@ -1044,6 +1046,14 @@ flagpsl("MT"), .psl = true, }, .{ + .name = "Zc:wchar_t-", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ .name = "Ze", .syntax = .flag, .zig_equivalent = .other, @@ -1204,6 +1214,46 @@ flagpsl("MT"), .psl = true, }, .{ + .name = "external:W0", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ + .name = "external:W1", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ + .name = "external:W2", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ + .name = "external:W3", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ + .name = "external:W4", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ .name = "fp:except", .syntax = .flag, .zig_equivalent = .other, @@ -2213,6 +2263,8 @@ flagpd1("shared-libasan"), .pd2 = false, .psl = true, }, +flagpd1("fdiagnostics-color"), +flagpd1("fno-diagnostics-color"), flagpd1("frecord-gcc-switches"), flagpd1("fno-record-gcc-switches"), flagpd1("fident"), @@ -2385,6 +2437,8 @@ flagpd1("dD"), flagpd1("dI"), flagpd1("dM"), flagpd1("d"), +sepd1("darwin-target-variant"), +sepd1("darwin-target-variant-triple"), flagpd1("dead_strip"), flagpd1("debug-forward-template-params"), flagpd1("debug-info-macro"), @@ -2401,7 +2455,6 @@ flagpd1("disable-lifetime-markers"), flagpd1("disable-llvm-optzns"), flagpd1("disable-llvm-passes"), flagpd1("disable-llvm-verifier"), -flagpd1("disable-noundef-analysis"), flagpd1("disable-objc-default-synthesize-properties"), flagpd1("disable-pragma-debug-crash"), flagpd1("disable-red-zone"), @@ -2417,6 +2470,14 @@ sepd1("dwarf-debug-flags"), sepd1("dwarf-debug-producer"), flagpd1("dwarf-explicit-import"), flagpd1("dwarf-ext-refs"), +.{ + .name = "hlsl-no-stdinc", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, sepd1("dylib_file"), flagpd1("dylinker"), flagpd1("dynamic"), @@ -2431,7 +2492,9 @@ flagpd1("dynamic"), flagpd1("ehcontguard"), flagpd1("emit-ast"), flagpd1("emit-codegen-only"), +flagpd1("emit-fir"), flagpd1("emit-header-module"), +flagpd1("emit-header-unit"), flagpd1("emit-html"), flagpd1("emit-interface-stubs"), .{ @@ -2446,11 +2509,20 @@ flagpd1("emit-llvm-bc"), flagpd1("emit-llvm-only"), flagpd1("emit-llvm-uselists"), flagpd1("emit-merged-ifs"), +flagpd1("emit-mlir"), flagpd1("emit-module"), flagpd1("emit-module-interface"), flagpd1("emit-obj"), flagpd1("emit-pch"), .{ + .name = "emit-pristine-llvm", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ .name = "emit-static-lib", .syntax = .flag, .zig_equivalent = .other, @@ -2458,6 +2530,15 @@ flagpd1("emit-pch"), .pd2 = true, .psl = false, }, +.{ + .name = "enable-16bit-types", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +flagpd1("enable-noundef-analysis"), flagpd1("enable-trivial-auto-var-init-zero-knowing-it-will-be-removed-from-clang"), .{ .name = "end-no-unused-arguments", @@ -2508,6 +2589,7 @@ flagpd1("falternative-parameter-statement"), flagpd1("faltivec"), flagpd1("fanalyzed-objects-for-unparse"), flagpd1("fkeep-inline-functions"), +flagpd1("funit-at-a-time"), flagpd1("fansi-escape-codes"), flagpd1("fapple-kext"), flagpd1("fapple-link-rtlib"), @@ -2565,6 +2647,14 @@ flagpd1("fcaller-saves"), }, sepd1("fcaret-diagnostics-max-lines"), flagpd1("fcf-protection"), +.{ + .name = "fcgl", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, flagpd1("fchar8_t"), flagpd1("fcheck-array-temporaries"), .{ @@ -2608,6 +2698,7 @@ flagpd1("fdebug-dump-all"), flagpd1("fdebug-dump-parse-tree"), flagpd1("fdebug-dump-parse-tree-no-sema"), flagpd1("fdebug-dump-parsing-log"), +flagpd1("fdebug-dump-pft"), flagpd1("fdebug-dump-provenance"), flagpd1("fdebug-dump-symbols"), flagpd1("fdebug-info-for-profiling"), @@ -2638,7 +2729,6 @@ flagpd1("fdeprecated-macro"), flagpd1("fdevirtualize"), flagpd1("fdevirtualize-speculatively"), flagpd1("fdiagnostics-absolute-paths"), -flagpd1("fdiagnostics-color"), flagpd1("fdiagnostics-fixit-info"), sepd1("fdiagnostics-format"), flagpd1("fdiagnostics-parseable-fixits"), @@ -2650,11 +2740,13 @@ flagpd1("fdiagnostics-show-option"), flagpd1("fdiagnostics-show-template-tree"), flagpd1("fdigraphs"), flagpd1("fdirect-access-external-data"), +flagpd1("fdirectives-only"), flagpd1("fdisable-module-hash"), flagpd1("fdiscard-value-names"), flagpd1("fdollar-ok"), flagpd1("fdollars-in-identifiers"), flagpd1("fdouble-square-bracket-attributes"), +flagpd1("fdriver-only"), flagpd1("fdump-fortran-optimized"), flagpd1("fdump-fortran-original"), flagpd1("fdump-parse-tree"), @@ -2679,6 +2771,7 @@ sepd1("ferror-limit"), flagpd1("fescaping-block-tail-calls"), flagpd1("fexceptions"), flagpd1("fexperimental-isel"), +flagpd1("fexperimental-library"), flagpd1("fexperimental-new-constant-interpreter"), flagpd1("fexperimental-new-pass-manager"), flagpd1("fexperimental-relative-c++-abi-vtables"), @@ -2690,6 +2783,7 @@ flagpd1("ffake-address-space-map"), flagpd1("ffast-math"), flagpd1("ffat-lto-objects"), flagpd1("fcheck-new"), +flagpd1("ffile-reproducible"), flagpd1("fimplicit-modules-use-lock"), flagpd1("ffine-grained-bitfield-accesses"), flagpd1("ffinite-loops"), @@ -2793,6 +2887,7 @@ flagpd1("fhalf-no-semantic-interposition"), flagpd1("fheinous-gnu-extensions"), flagpd1("fhip-dump-offload-linker-script"), flagpd1("fhip-fp32-correctly-rounded-divide-sqrt"), +flagpd1("fhip-kernel-arg-name"), flagpd1("fhip-new-launch-api"), flagpd1("fhonor-infinities"), flagpd1("fhonor-nans"), @@ -2818,6 +2913,7 @@ flagpd1("finstrument-functions-after-inlining"), flagpd1("finteger-4-integer-8"), flagpd1("fintegrated-as"), flagpd1("fintegrated-cc1"), +flagpd1("fintegrated-objemitter"), sepd1("fintrinsic-modules-path"), flagpd1("fipa-cp"), flagpd1("fivopts"), @@ -2826,12 +2922,13 @@ flagpd1("fix-what-you-can"), flagpd1("fixit"), flagpd1("fixit-recompile"), flagpd1("fixit-to-temporary"), +flagpd1("fjmc"), flagpd1("fjump-tables"), flagpd1("fkeep-static-consts"), +flagpd1("flang-experimental-exec"), flagpd1("flarge-sizes"), flagpd1("flat_namespace"), flagpd1("flax-vector-conversions"), -flagpd1("flegacy-pass-manager"), flagpd1("flimit-debug-info"), flagpd1("flogical-abbreviations"), .{ @@ -2856,6 +2953,8 @@ flagpd1("fmerge-functions"), flagpd1("fminimize-whitespace"), sepd1("fmodule-feature"), flagpd1("fmodule-file-deps"), +flagpd1("fmodule-file-home-is-cwd"), +flagpd1("fmodule-header"), sepd1("fmodule-implementation-of"), flagpd1("fmodule-map-file-home-is-cwd"), flagpd1("fmodule-maps"), @@ -2880,6 +2979,7 @@ flagpd1("fmodulo-sched-allow-regmoves"), flagpd1("fms-compatibility"), flagpd1("fms-extensions"), flagpd1("fms-hotpatch"), +flagpd1("fms-kernel"), flagpd1("fms-volatile"), flagpd1("fmudflap"), flagpd1("fmudflapth"), @@ -2919,6 +3019,7 @@ flagpd1("fno-allow-editor-placeholders"), flagpd1("fno-altivec"), flagpd1("fno-analyzed-objects-for-unparse"), flagpd1("fno-keep-inline-functions"), +flagpd1("fno-unit-at-a-time"), flagpd1("fno-apple-pragma-pack"), flagpd1("fno-application-extension"), flagpd1("fno-approx-func"), @@ -2968,7 +3069,6 @@ flagpd1("fno-check-array-temporaries"), }, flagpd1("fno-common"), flagpd1("fno-complete-member-pointers"), -flagpd1("fno-concept-satisfaction-caching"), flagpd1("fno-const-strings"), flagpd1("fno-constant-cfstrings"), flagpd1("fno-coroutines-ts"), @@ -2997,7 +3097,6 @@ flagpd1("fno-delete-null-pointer-checks"), flagpd1("fno-deprecated-macro"), flagpd1("fno-devirtualize"), flagpd1("fno-devirtualize-speculatively"), -flagpd1("fno-diagnostics-color"), flagpd1("fno-diagnostics-fixit-info"), flagpd1("fno-diagnostics-show-hotness"), flagpd1("fno-diagnostics-show-note-include-stack"), @@ -3005,6 +3104,7 @@ flagpd1("fno-diagnostics-show-option"), flagpd1("fno-diagnostics-use-presumed-location"), flagpd1("fno-digraphs"), flagpd1("fno-direct-access-external-data"), +flagpd1("fno-directives-only"), flagpd1("fno-discard-value-names"), flagpd1("fno-dllexport-inlines"), flagpd1("fno-dollar-ok"), @@ -3023,13 +3123,14 @@ flagpd1("fno-emulated-tls"), flagpd1("fno-escaping-block-tail-calls"), flagpd1("fno-exceptions"), flagpd1("fno-experimental-isel"), -flagpd1("fno-experimental-new-pass-manager"), +flagpd1("fno-experimental-library"), flagpd1("fno-experimental-relative-c++-abi-vtables"), flagpd1("fno-external-blas"), flagpd1("fno-f2c"), flagpd1("fno-fast-math"), flagpd1("fno-fat-lto-objects"), flagpd1("fno-check-new"), +flagpd1("fno-file-reproducible"), flagpd1("fno-implicit-modules-use-lock"), flagpd1("fno-fine-grained-bitfield-accesses"), flagpd1("fno-finite-loops"), @@ -3068,6 +3169,7 @@ flagpd1("fno-gpu-flush-denormals-to-zero"), flagpd1("fno-gpu-rdc"), flagpd1("fno-gpu-sanitize"), flagpd1("fno-hip-fp32-correctly-rounded-divide-sqrt"), +flagpd1("fno-hip-kernel-arg-name"), flagpd1("fno-hip-new-launch-api"), flagpd1("fno-honor-infinities"), flagpd1("fno-honor-nans"), @@ -3084,10 +3186,13 @@ flagpd1("fno-inline-small-functions"), flagpd1("fno-integer-4-integer-8"), flagpd1("fno-integrated-as"), flagpd1("fno-integrated-cc1"), +flagpd1("fno-integrated-objemitter"), flagpd1("fno-ipa-cp"), flagpd1("fno-ivopts"), +flagpd1("fno-jmc"), flagpd1("fno-jump-tables"), flagpd1("fno-keep-static-consts"), +flagpd1("fno-knr-functions"), flagpd1("fno-lax-vector-conversions"), flagpd1("fno-legacy-pass-manager"), flagpd1("fno-limit-debug-info"), @@ -3152,6 +3257,7 @@ flagpd1("fno-openmp-cuda-force-full-runtime"), flagpd1("fno-openmp-cuda-mode"), flagpd1("fno-openmp-extensions"), flagpd1("fno-openmp-implicit-rpath"), +flagpd1("fno-openmp-new-driver"), flagpd1("fno-openmp-optimistic-collapse"), flagpd1("fno-openmp-simd"), flagpd1("fno-openmp-target-debug"), @@ -3234,6 +3340,7 @@ flagpd1("fno-rtlib-add-rpath"), flagpd1("fno-rtti"), flagpd1("fno-rtti-data"), flagpd1("fno-rwpi"), +flagpd1("fno-sanitize-address-globals-dead-stripping"), flagpd1("fno-sanitize-address-outline-instrumentation"), flagpd1("fno-sanitize-address-poison-custom-array-cookie"), flagpd1("fno-sanitize-address-use-after-scope"), @@ -3325,7 +3432,6 @@ flagpd1("fno-underscoring"), flagpd1("fno-unique-basic-block-section-names"), flagpd1("fno-unique-internal-linkage-names"), flagpd1("fno-unique-section-names"), -flagpd1("fno-unit-at-a-time"), flagpd1("fno-unroll-all-loops"), flagpd1("fno-unroll-loops"), flagpd1("fno-unsafe-loop-optimizations"), @@ -3406,6 +3512,7 @@ flagpd1("foffload-lto"), }, flagpd1("fopenacc"), flagpd1("fopenmp"), +flagpd1("fopenmp-assume-no-thread-state"), flagpd1("fopenmp-assume-teams-oversubscription"), flagpd1("fopenmp-assume-threads-oversubscription"), flagpd1("fopenmp-cuda-force-full-runtime"), @@ -3416,6 +3523,7 @@ sepd1("fopenmp-host-ir-file-path"), flagpd1("fopenmp-implicit-rpath"), flagpd1("fopenmp-is-device"), flagpd1("fopenmp-new-driver"), +flagpd1("fopenmp-offload-mandatory"), flagpd1("fopenmp-optimistic-collapse"), flagpd1("fopenmp-relocatable-target"), flagpd1("fopenmp-simd"), @@ -3659,7 +3767,6 @@ flagpd1("funderscoring"), flagpd1("funique-basic-block-section-names"), flagpd1("funique-internal-linkage-names"), flagpd1("funique-section-names"), -flagpd1("funit-at-a-time"), flagpd1("funknown-anytype"), flagpd1("funroll-all-loops"), flagpd1("funroll-loops"), @@ -3844,6 +3951,7 @@ flagpd1("m68060"), flagpd1("m80387"), m("mseses"), flagpd1("mabi=ieeelongdouble"), +flagpd1("mabi=quadword-atomics"), flagpd1("mabi=vec-default"), flagpd1("mabi=vec-extabi"), flagpd1("mabicalls"), @@ -3907,7 +4015,6 @@ m("mcumode"), m("mcx16"), sepd1("mdebug-pass"), m("mdirect-move"), -flagpd1("mdisable-tail-calls"), flagpd1("mdouble-float"), m("mdsp"), m("mdspr2"), @@ -3921,6 +4028,7 @@ flagpd1("menable-unsafe-fp-math"), m("menqcmd"), m("mexception-handling"), m("mexecute-only"), +flagpd1("mextended-const"), flagpd1("mextern-sdata"), m("mf16c"), flagpd1("mfancy-math-387"), @@ -3929,6 +4037,8 @@ flagpd1("mfix4300"), flagpd1("mfix-and-continue"), m("mfix-cmse-cve-2021-35465"), m("mfix-cortex-a53-835769"), +flagpd1("mfix-cortex-a57-aes-1742098"), +flagpd1("mfix-cortex-a72-aes-1655431"), m("mfloat128"), sepd1("mfloat-abi"), m("mfma"), @@ -4007,6 +4117,7 @@ m("mmemops"), flagpd1("mmfcrf"), m("mmfocrf"), m("mmicromips"), +sepd1("mmlir"), m("mmma"), m("mmmx"), m("mmovbe"), @@ -4077,10 +4188,13 @@ m("mno-enqcmd"), m("mno-exception-handling"), flagpd1("mnoexecstack"), m("mno-execute-only"), +flagpd1("mno-extended-const"), flagpd1("mno-extern-sdata"), m("mno-f16c"), m("mno-fix-cmse-cve-2021-35465"), m("mno-fix-cortex-a53-835769"), +flagpd1("mno-fix-cortex-a57-aes-1742098"), +flagpd1("mno-fix-cortex-a72-aes-1655431"), m("mno-float128"), m("mno-fma"), m("mno-fma4"), @@ -4158,6 +4272,7 @@ m("mno-prfchw"), m("mno-ptwrite"), flagpd1("mno-pure-code"), m("mno-rdpid"), +flagpd1("mno-rdpru"), m("mno-rdrnd"), m("mno-rdseed"), .{ @@ -4239,7 +4354,6 @@ m("mnvj"), m("mnvs"), flagpd1("modd-spreg"), sepd1("module-dependency-dir"), -sepd1("module-dir"), flagpd1("module-file-deps"), flagpd1("module-file-info"), sepd1("module-suffix"), @@ -4268,6 +4382,7 @@ m("mptwrite"), flagpd1("mpure-code"), flagpd1("mqdsp6-compat"), m("mrdpid"), +flagpd1("mrdpru"), m("mrdrnd"), m("mrdseed"), flagpd1("mreassociate"), @@ -4404,6 +4519,7 @@ flagpd1("no-cpp-precomp"), .psl = false, }, flagpd1("no-emit-llvm-uselists"), +flagpd1("no-enable-noundef-analysis"), .{ .name = "no-gpu-bundle-output", .syntax = .flag, @@ -4412,6 +4528,7 @@ flagpd1("no-emit-llvm-uselists"), .pd2 = true, .psl = false, }, +flagpd1("no-hip-rt"), flagpd1("no-implicit-float"), .{ .name = "no-integrated-cpp", @@ -4422,6 +4539,15 @@ flagpd1("no-implicit-float"), .psl = false, }, .{ + .name = "no-offload-new-driver", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, +flagpd1("no-opaque-pointers"), +.{ .name = "no-pedantic", .syntax = .flag, .zig_equivalent = .other, @@ -4443,6 +4569,7 @@ flagpd1("no-struct-path-tbaa"), flagpd1("nobuiltininc"), flagpd1("nocpp"), flagpd1("nodefaultlibs"), +flagpd1("nodriverkitlib"), flagpd1("nofixprebinding"), flagpd1("nogpuinc"), flagpd1("nogpulib"), @@ -4526,6 +4653,47 @@ flagpd1("objcmt-ns-nonatomic-iosonly"), flagpd1("objcmt-returns-innerpointer-property"), flagpd1("object"), sepd1("object-file-name"), +.{ + .name = "offload-device-only", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, +.{ + .name = "offload-host-device", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, +.{ + .name = "offload-host-only", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, +.{ + .name = "offload-link", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, +.{ + .name = "offload-new-driver", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, +flagpd1("opaque-pointers"), sepd1("opt-record-file"), sepd1("opt-record-format"), sepd1("opt-record-passes"), @@ -4582,6 +4750,14 @@ flagpd1("prebind_all_twolevel_modules"), flagpd1("preload"), flagpd1("print-dependency-directives-minimized-source"), .{ + .name = "print-diagnostic-options", + .syntax = .flag, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = true, + .psl = false, +}, +.{ .name = "print-effective-triple", .syntax = .flag, .zig_equivalent = .other, @@ -4982,6 +5158,7 @@ joinpd1("fsanitize-undefined-strip-path-components="), joinpd1("fopenmp-cuda-teams-reduction-recs-num="), joinpd1("fvisibility-externs-nodllstorageclass="), joinpd1("analyzer-config-compatibility-mode="), +joinpd1("mdefault-visibility-export-mapping="), joinpd1("fsanitize-address-use-after-return="), .{ .name = "fsanitize-address-use-after-return", @@ -4991,9 +5168,12 @@ joinpd1("fsanitize-address-use-after-return="), .pd2 = false, .psl = true, }, +joinpd1("darwin-target-variant-sdk-version="), joinpd1("ftrivial-auto-var-init-stop-after="), joinpd1("fverify-debuginfo-preserve-export="), +joinpd1("fdiagnostics-misexpect-tolerance="), joinpd1("fpatchable-function-entry-offset="), +joinpd1("fprofile-selected-function-group="), joinpd1("analyzer-inline-max-stack-depth="), joinpd1("fsanitize-address-field-padding="), .{ @@ -5005,6 +5185,7 @@ joinpd1("fsanitize-address-field-padding="), .psl = true, }, joinpd1("fdiagnostics-hotness-threshold="), +joinpd1("fexperimental-max-bitint-width="), joinpd1("fsanitize-memory-track-origins="), joinpd1("mwatchos-simulator-version-min="), joinpd1("fsanitize-coverage-ignorelist="), @@ -5013,6 +5194,7 @@ joinpd1("fvisibility-nodllstorageclass="), joinpd1("fxray-selected-function-group="), joinpd1("mappletvsimulator-version-min="), joinpd1("mstack-protector-guard-offset="), +joinpd1("mstack-protector-guard-symbol="), .{ .name = "sourceDependencies:directives", .syntax = .joined_or_separate, @@ -5021,16 +5203,17 @@ joinpd1("mstack-protector-guard-offset="), .pd2 = false, .psl = true, }, +joinpd1("miphonesimulator-version-min="), joinpd1("fsanitize-coverage-whitelist="), joinpd1("fsanitize-coverage-blacklist="), joinpd1("fobjc-nonfragile-abi-version="), joinpd1("fprofile-instrument-use-path="), joinpd1("fsanitize-coverage-allowlist="), jspd1("fxray-instrumentation-bundle="), -joinpd1("miphonesimulator-version-min="), joinpd1("fsanitize-address-destructor="), joinpd1("faddress-space-map-mangling="), joinpd1("foptimization-record-passes="), +joinpd1("frandomize-layout-seed-file="), joinpd1("fsanitize-system-ignorelist="), joinpd1("ftest-module-file-extension="), jspd1("fxray-instruction-threshold="), @@ -5042,6 +5225,14 @@ jspd1("fxray-instruction-threshold="), .pd2 = true, .psl = false, }, +.{ + .name = "libomptarget-amdgpu-bc-path=", + .syntax = .joined, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, joinpd1("mno-default-build-attributes"), joinpd1("mtvos-simulator-version-min="), joinpd1("mwatchsimulator-version-min="), @@ -5107,6 +5298,7 @@ joinpd1("objcmt-allowlist-dir-path="), joinpd1("Wno-nonportable-cfstrings"), joinpd1("analyzer-disable-checker="), joinpd1("fbuild-session-timestamp="), +joinpd1("fprofile-function-groups="), joinpd1("fprofile-instrument-path="), joinpd1("mdefault-build-attributes"), joinpd1("msign-return-address-key="), @@ -5178,6 +5370,7 @@ joinpd1("ffp-exception-behavior="), joinpd1("fmacro-backtrace-limit="), joinpd1("fmax-array-constructor="), joinpd1("fprofile-exclude-files="), +joinpd1("frandomize-layout-seed="), joinpd1("ftrivial-auto-var-init="), jspd1("fxray-never-instrument="), joinpd1("gsimple-template-names="), @@ -5186,6 +5379,7 @@ joinpd1("malign-branch-boundary="), joinpd1("mappletvos-version-min="), joinpd1("mstack-protector-guard="), joinpd1("Wnonportable-cfstrings"), +joinpd1("miphoneos-version-min="), joinpd1("fbasic-block-sections="), joinpd1("fdefault-calling-conv="), joinpd1("fdenormal-fp-math-f32="), @@ -5206,10 +5400,10 @@ joinpd1("fobjc-dispatch-method="), joinpd1("foperator-arrow-depth="), joinpd1("fprebuilt-module-path="), joinpd1("fprofile-filter-files="), +joinpd1("fsanitize-memtag-mode="), joinpd1("fspell-checking-limit="), joinpd1("fvisibility-dllexport="), joinpd1("fxray-function-groups="), -joinpd1("miphoneos-version-min="), joinpd1("msmall-data-threshold="), joinpd1("Wlarge-by-value-copy="), joinpd1("analyzer-constraints="), @@ -5229,6 +5423,7 @@ joinpd1("fmodules-prune-after="), }, joinpd1("fopenmp-target-debug="), joinpd1("fsanitize-ignorelist="), +joinpd1("fzero-call-used-regs="), jspd1("iframeworkwithsysroot"), joinpd1("mcode-object-version="), joinpd1("mpad-max-prefix-size="), @@ -5260,6 +5455,7 @@ joinpd1("mwatchos-version-min="), .psl = false, }, joinpd1("faltivec-src-compat="), +joinpd1("mmacosx-version-min="), joinpd1("fsanitize-blacklist="), .{ .name = "hip-device-lib-path=", @@ -5272,12 +5468,13 @@ joinpd1("fsanitize-blacklist="), joinpd1("coverage-notes-file="), joinpd1("fbuild-session-file="), joinpd1("fdiagnostics-format="), +joinpd1("fgpu-default-stream="), joinpd1("fmax-stack-var-size="), joinpd1("fmodules-cache-path="), joinpd1("fmodules-embed-file="), joinpd1("fprofile-instrument="), joinpd1("fprofile-sample-use="), -joinpd1("mmacosx-version-min="), +joinpd1("fstrict-flex-arrays="), .{ .name = "no-cuda-include-ptx=", .syntax = .joined, @@ -5291,6 +5488,7 @@ joinpd1("code-completion-at="), joinpd1("coverage-data-file="), joinpd1("fblas-matmul-limit="), joinpd1("fdiagnostics-color="), +joinpd1("femit-dwarf-unwind="), joinpd1("ffixed-line-length="), joinpd1("ffixed-line-length-"), joinpd1("ffuchsia-api-level="), @@ -5430,6 +5628,7 @@ joinpd1("fproc-stat-report"), joinpd1("fwarn-stack-size="), jspd1("iwithprefixbefore"), joinpd1("malign-functions="), +joinpd1("mfunction-return="), joinpd1("mios-version-min="), joinpd1("mstack-alignment="), joinpd1("msve-vector-bits="), @@ -5473,6 +5672,7 @@ joinpd1("debug-info-kind="), joinpd1("debugger-tuning="), joinpd1("exception-model="), joinpd1("fcf-runtime-abi="), +joinpd1("ffp-eval-method="), joinpd1("finit-character="), joinpd1("fmax-type-align="), joinpd1("fmemory-profile="), @@ -5521,6 +5721,14 @@ joinpd1("mlinker-version="), jspd1("stdlib++-isystem"), joinpd1("Rpass-analysis="), .{ + .name = "Xoffload-linker", + .syntax = .joined_and_separate, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = false, +}, +.{ .name = "Xopenmp-target=", .syntax = .joined_and_separate, .zig_equivalent = .other, @@ -5570,6 +5778,7 @@ joinpd1("fdepfile-entry="), joinpd1("fembed-bitcode="), joinpd1("finput-charset="), joinpd1("fmodule-format="), +joinpd1("fmodule-header="), joinpd1("fms-memptr-rep="), joinpd1("fnew-alignment="), joinpd1("frecord-marker="), @@ -5592,6 +5801,7 @@ joinpd1("ftrapv-handler="), .pd2 = false, .psl = false, }, +joinpd1("gen-reproducer="), .{ .name = "hip-device-lib=", .syntax = .joined, @@ -5725,6 +5935,14 @@ joinpd1("ast-dump-all="), .pd2 = true, .psl = false, }, +.{ + .name = "cuda-feature=", + .syntax = .joined, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, joinpd1("falign-jumps="), joinpd1("falign-loops="), joinpd1("faligned-new="), @@ -5752,6 +5970,7 @@ joinpd1("gsplit-dwarf="), jspd1("isystem-after"), joinpd1("malign-jumps="), joinpd1("malign-loops="), +joinpd1("mframe-chain="), joinpd1("mimplicit-it="), .{ .name = "offload-arch=", @@ -5762,6 +5981,14 @@ joinpd1("mimplicit-it="), .psl = false, }, jspd1("pagezero_size"), +.{ + .name = "product-name=", + .syntax = .joined, + .zig_equivalent = .other, + .pd1 = false, + .pd2 = true, + .psl = false, +}, joinpd1("resource-dir="), .{ .name = "dyld-prefix=", @@ -5783,6 +6010,7 @@ joinpd1("fmax-errors="), joinpd1("fmax-tokens="), joinpd1("fno-builtin-"), joinpd1("fplugin-arg-"), +joinpd1("ftime-trace="), joinpd1("fvisibility="), joinpd1("fwchar-type="), jspd1("fxray-modes="), @@ -5988,6 +6216,7 @@ joinpd1("flto-jobs="), }, joinpd1("fuse-cuid="), jspd1("iframework"), +jspd1("module-dir"), joinpd1("mtargetos="), joinpd1("mtls-size="), .{ @@ -6527,6 +6756,14 @@ joinpd1("mtp="), }, joinpd1("gz="), joinpd1("A-"), +.{ + .name = "Fo", + .syntax = .joined_or_separate, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, joinpd1("G="), .{ .name = "MF", @@ -6705,6 +6942,14 @@ joinpd1("G="), .psl = true, }, .{ + .name = "Wv", + .syntax = .joined, + .zig_equivalent = .other, + .pd1 = true, + .pd2 = false, + .psl = true, +}, +.{ .name = "Yc", .syntax = .joined, .zig_equivalent = .other, @@ -6903,6 +7148,14 @@ joinpd1("d"), .pd2 = false, .psl = false, }, +.{ + .name = "T", + .syntax = .joined_or_separate, + .zig_equivalent = .linker_script, + .pd1 = true, + .pd2 = false, + .psl = true, +}, jspd1("u"), jspd1("x"), joinpd1("y"), diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 3603713195..d20b6f2ab6 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -42,7 +42,10 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .bpfel => "bpfel", .bpfeb => "bpfeb", .csky => "csky", + .dxil => "dxil", .hexagon => "hexagon", + .loongarch32 => "loongarch32", + .loongarch64 => "loongarch64", .m68k => "m68k", .mips => "mips", .mipsel => "mipsel", @@ -117,6 +120,7 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .nvcl => "nvcl", .amdhsa => "amdhsa", .ps4 => "ps4", + .ps5 => "ps5", .elfiamcu => "elfiamcu", .mesa3d => "mesa3d", .contiki => "contiki", @@ -130,6 +134,8 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .ios => "ios", .tvos => "tvos", .watchos => "watchos", + .driverkit => "driverkit", + .shadermodel => "shadermodel", .opencl, .glsl450, .vulkan, @@ -172,6 +178,21 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![:0]u8 { .coreclr => "coreclr", .simulator => "simulator", .macabi => "macabi", + .pixel => "pixel", + .vertex => "vertex", + .geometry => "geometry", + .hull => "hull", + .domain => "domain", + .compute => "compute", + .library => "library", + .raygeneration => "raygeneration", + .intersection => "intersection", + .anyhit => "anyhit", + .closesthit => "closesthit", + .miss => "miss", + .callable => "callable", + .mesh => "mesh", + .amplification => "amplification", }; try llvm_triple.appendSlice(llvm_abi); @@ -205,6 +226,7 @@ pub fn targetOs(os_tag: std.Target.Os.Tag) llvm.OSType { .nvcl => .NVCL, .amdhsa => .AMDHSA, .ps4 => .PS4, + .ps5 => .PS5, .elfiamcu => .ELFIAMCU, .tvos => .TvOS, .watchos => .WatchOS, @@ -215,6 +237,8 @@ pub fn targetOs(os_tag: std.Target.Os.Tag) llvm.OSType { .hurd => .Hurd, .wasi => .WASI, .emscripten => .Emscripten, + .driverkit => .DriverKit, + .shadermodel => .ShaderModel, }; } @@ -230,7 +254,10 @@ pub fn targetArch(arch_tag: std.Target.Cpu.Arch) llvm.ArchType { .bpfel => .bpfel, .bpfeb => .bpfeb, .csky => .csky, + .dxil => .dxil, .hexagon => .hexagon, + .loongarch32 => .loongarch32, + .loongarch64 => .loongarch64, .m68k => .m68k, .mips => .mips, .mipsel => .mipsel, @@ -893,7 +920,9 @@ pub const Object = struct { while (it.next()) |lowering| switch (lowering) { .no_bits => continue, .byval => { - const param_ty = fn_info.param_types[it.zig_index - 1]; + assert(!it.byval_attr); + const param_index = it.zig_index - 1; + const param_ty = fn_info.param_types[param_index]; const param = llvm_func.getParam(llvm_arg_i); try args.ensureUnusedCapacity(1); @@ -908,43 +937,17 @@ pub const Object = struct { } else { args.appendAssumeCapacity(param); - if (param_ty.isPtrAtRuntime()) { - const ptr_info = param_ty.ptrInfo().data; - if (math.cast(u5, it.zig_index - 1)) |i| { - if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { - dg.addArgAttr(llvm_func, llvm_arg_i, "noalias"); - } - } - if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); - } - if (!ptr_info.mutable) { - dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); - } - if (ptr_info.@"align" != 0) { - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", ptr_info.@"align"); - } else { - const elem_align = @maximum( - ptr_info.pointee_type.abiAlignment(target), - 1, - ); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", elem_align); - } - } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { - .signed => dg.addArgAttr(llvm_func, llvm_arg_i, "signext"), - .unsigned => dg.addArgAttr(llvm_func, llvm_arg_i, "zeroext"), - }; + dg.addByValParamAttrs(llvm_func, param_ty, param_index, fn_info, llvm_arg_i); } llvm_arg_i += 1; }, .byref => { const param_ty = fn_info.param_types[it.zig_index - 1]; + const param_llvm_ty = try dg.lowerType(param_ty); const param = llvm_func.getParam(llvm_arg_i); + const alignment = param_ty.abiAlignment(target); - dg.addArgAttr(llvm_func, llvm_arg_i, "nonnull"); - dg.addArgAttr(llvm_func, llvm_arg_i, "readonly"); - dg.addArgAttrInt(llvm_func, llvm_arg_i, "align", param_ty.abiAlignment(target)); - + dg.addByRefParamAttrs(llvm_func, llvm_arg_i, alignment, it.byval_attr, param_llvm_ty); llvm_arg_i += 1; try args.ensureUnusedCapacity(1); @@ -952,13 +955,13 @@ pub const Object = struct { if (isByRef(param_ty)) { args.appendAssumeCapacity(param); } else { - const alignment = param_ty.abiAlignment(target); - const load_inst = builder.buildLoad(param, ""); + const load_inst = builder.buildLoad(param_llvm_ty, param, ""); load_inst.setAlignment(alignment); args.appendAssumeCapacity(load_inst); } }, .abi_sized_int => { + assert(!it.byval_attr); const param_ty = fn_info.param_types[it.zig_index - 1]; const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; @@ -982,12 +985,13 @@ pub const Object = struct { if (isByRef(param_ty)) { args.appendAssumeCapacity(arg_ptr); } else { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(alignment); args.appendAssumeCapacity(load_inst); } }, .slice => { + assert(!it.byval_attr); const param_ty = fn_info.param_types[it.zig_index - 1]; const ptr_info = param_ty.ptrInfo().data; @@ -1017,6 +1021,7 @@ pub const Object = struct { try args.append(aggregate); }, .multiple_llvm_ints => { + assert(!it.byval_attr); const llvm_ints = it.llvm_types_buffer[0..it.llvm_types_len]; const param_ty = fn_info.param_types[it.zig_index - 1]; const param_llvm_ty = try dg.lowerType(param_ty); @@ -1033,20 +1038,21 @@ pub const Object = struct { for (llvm_ints) |_, i_usize| { const i = @intCast(c_uint, i_usize); const param = llvm_func.getParam(i); - const field_ptr = builder.buildStructGEP(casted_ptr, i, ""); + const field_ptr = builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, ""); const store_inst = builder.buildStore(param, field_ptr); store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); } const is_by_ref = isByRef(param_ty); const loaded = if (is_by_ref) arg_ptr else l: { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(param_alignment); break :l load_inst; }; try args.append(loaded); }, .multiple_llvm_float => { + assert(!it.byval_attr); const llvm_floats = it.llvm_types_buffer[0..it.llvm_types_len]; const param_ty = fn_info.param_types[it.zig_index - 1]; const param_llvm_ty = try dg.lowerType(param_ty); @@ -1062,25 +1068,26 @@ pub const Object = struct { else => {}, } } - const ints_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); - const casted_ptr = builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), ""); + const floats_llvm_ty = dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); + const casted_ptr = builder.buildBitCast(arg_ptr, floats_llvm_ty.pointerType(0), ""); for (llvm_floats) |_, i_usize| { const i = @intCast(c_uint, i_usize); const param = llvm_func.getParam(i); - const field_ptr = builder.buildStructGEP(casted_ptr, i, ""); + const field_ptr = builder.buildStructGEP(floats_llvm_ty, casted_ptr, i, ""); const store_inst = builder.buildStore(param, field_ptr); store_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); } const is_by_ref = isByRef(param_ty); const loaded = if (is_by_ref) arg_ptr else l: { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(param_alignment); break :l load_inst; }; try args.append(loaded); }, .as_u16 => { + assert(!it.byval_attr); const param = llvm_func.getParam(llvm_arg_i); llvm_arg_i += 1; const casted = builder.buildBitCast(param, dg.context.halfType(), ""); @@ -1102,7 +1109,7 @@ pub const Object = struct { if (isByRef(param_ty)) { try args.append(arg_ptr); } else { - const load_inst = builder.buildLoad(arg_ptr, ""); + const load_inst = builder.buildLoad(param_llvm_ty, arg_ptr, ""); load_inst.setAlignment(alignment); try args.append(load_inst); } @@ -2515,12 +2522,38 @@ pub const DeclGen = struct { dg.addFnAttr(llvm_fn, "noreturn"); } - var llvm_arg_i = @as(c_uint, @boolToInt(sret)) + @boolToInt(err_return_tracing); - var it = iterateParamTypes(dg, fn_info); - while (it.next()) |_| : (llvm_arg_i += 1) { - if (!it.byval_attr) continue; - const param = llvm_fn.getParam(llvm_arg_i); - llvm_fn.addByValAttr(llvm_arg_i, param.typeOf().getElementType()); + // Add parameter attributes. We handle only the case of extern functions (no body) + // because functions with bodies are handled in `updateFunc`. + if (is_extern) { + var it = iterateParamTypes(dg, fn_info); + it.llvm_index += @boolToInt(sret); + it.llvm_index += @boolToInt(err_return_tracing); + while (it.next()) |lowering| switch (lowering) { + .byval => { + const param_index = it.zig_index - 1; + const param_ty = fn_info.param_types[param_index]; + if (!isByRef(param_ty)) { + dg.addByValParamAttrs(llvm_fn, param_ty, param_index, fn_info, it.llvm_index - 1); + } + }, + .byref => { + const param_ty = fn_info.param_types[it.zig_index - 1]; + const param_llvm_ty = try dg.lowerType(param_ty); + const alignment = param_ty.abiAlignment(target); + dg.addByRefParamAttrs(llvm_fn, it.llvm_index - 1, alignment, it.byval_attr, param_llvm_ty); + }, + // No attributes needed for these. + .no_bits, + .abi_sized_int, + .multiple_llvm_ints, + .multiple_llvm_float, + .as_u16, + .float_array, + => continue, + + .slice => unreachable, // extern functions do not support slice types. + + }; } return llvm_fn; @@ -2539,7 +2572,7 @@ pub const DeclGen = struct { } dg.addFnAttr(llvm_fn, "nounwind"); if (comp.unwind_tables) { - dg.addFnAttr(llvm_fn, "uwtable"); + dg.addFnAttrString(llvm_fn, "uwtable", "sync"); } if (comp.bin_file.options.skip_linker_dependencies or comp.bin_file.options.no_builtin) @@ -2697,16 +2730,7 @@ pub const DeclGen = struct { if (ptr_info.host_size != 0) { return dg.context.intType(ptr_info.host_size * 8).pointerType(llvm_addrspace); } - const elem_ty = ptr_info.pointee_type; - const lower_elem_ty = switch (elem_ty.zigTypeTag()) { - .Opaque, .Fn => true, - .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), - else => elem_ty.hasRuntimeBitsIgnoreComptime(), - }; - const llvm_elem_ty = if (lower_elem_ty) - try dg.lowerType(elem_ty) - else - dg.context.intType(8); + const llvm_elem_ty = try dg.lowerPtrElemTy(ptr_info.pointee_type); return llvm_elem_ty.pointerType(llvm_addrspace); }, .Opaque => switch (t.tag()) { @@ -3108,6 +3132,23 @@ pub const DeclGen = struct { ); } + /// Use this instead of lowerType when you want to handle correctly the case of elem_ty + /// being a zero bit type, but it should still be lowered as an i8 in such case. + /// There are other similar cases handled here as well. + fn lowerPtrElemTy(dg: *DeclGen, elem_ty: Type) Allocator.Error!*const llvm.Type { + const lower_elem_ty = switch (elem_ty.zigTypeTag()) { + .Opaque, .Fn => true, + .Array => elem_ty.childType().hasRuntimeBitsIgnoreComptime(), + else => elem_ty.hasRuntimeBitsIgnoreComptime(), + }; + const llvm_elem_ty = if (lower_elem_ty) + try dg.lowerType(elem_ty) + else + dg.context.intType(8); + + return llvm_elem_ty; + } + fn lowerValue(dg: *DeclGen, tv: TypedValue) Error!*const llvm.Value { if (tv.val.isUndef()) { const llvm_type = try dg.lowerType(tv.ty); @@ -3858,7 +3899,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(llvm_pl_index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const parent_llvm_ty = try dg.lowerType(parent_ty); + break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .Struct => { const field_ty = parent_ty.structFieldType(field_index); @@ -3888,7 +3930,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(llvm_field_index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const parent_llvm_ty = try dg.lowerType(parent_ty); + break :blk parent_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, else => unreachable, } @@ -3902,7 +3945,8 @@ pub const DeclGen = struct { const indices: [1]*const llvm.Value = .{ llvm_usize.constInt(elem_ptr.index, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const elem_llvm_ty = try dg.lowerType(elem_ptr.elem_ty); + break :blk elem_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .opt_payload_ptr => blk: { const opt_payload_ptr = ptr_val.castTag(.opt_payload_ptr).?.data; @@ -3925,7 +3969,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(0, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const opt_llvm_ty = try dg.lowerType(opt_payload_ptr.container_ty); + break :blk opt_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, .eu_payload_ptr => blk: { const eu_payload_ptr = ptr_val.castTag(.eu_payload_ptr).?.data; @@ -3946,7 +3991,8 @@ pub const DeclGen = struct { llvm_u32.constInt(0, .False), llvm_u32.constInt(payload_offset, .False), }; - break :blk parent_llvm_ptr.constInBoundsGEP(&indices, indices.len); + const eu_llvm_ty = try dg.lowerType(eu_payload_ptr.container_ty); + break :blk eu_llvm_ty.constInBoundsGEP(parent_llvm_ptr, &indices, indices.len); }, else => unreachable, }; @@ -4127,6 +4173,59 @@ pub const DeclGen = struct { return null; } } + + fn addByValParamAttrs( + dg: DeclGen, + llvm_fn: *const llvm.Value, + param_ty: Type, + param_index: u32, + fn_info: Type.Payload.Function.Data, + llvm_arg_i: u32, + ) void { + const target = dg.module.getTarget(); + if (param_ty.isPtrAtRuntime()) { + const ptr_info = param_ty.ptrInfo().data; + if (math.cast(u5, param_index)) |i| { + if (@truncate(u1, fn_info.noalias_bits >> i) != 0) { + dg.addArgAttr(llvm_fn, llvm_arg_i, "noalias"); + } + } + if (!param_ty.isPtrLikeOptional() and !ptr_info.@"allowzero") { + dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); + } + if (!ptr_info.mutable) { + dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); + } + if (ptr_info.@"align" != 0) { + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", ptr_info.@"align"); + } else { + const elem_align = @maximum( + ptr_info.pointee_type.abiAlignment(target), + 1, + ); + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", elem_align); + } + } else if (ccAbiPromoteInt(fn_info.cc, target, param_ty)) |s| switch (s) { + .signed => dg.addArgAttr(llvm_fn, llvm_arg_i, "signext"), + .unsigned => dg.addArgAttr(llvm_fn, llvm_arg_i, "zeroext"), + }; + } + + fn addByRefParamAttrs( + dg: DeclGen, + llvm_fn: *const llvm.Value, + llvm_arg_i: u32, + alignment: u32, + byval_attr: bool, + param_llvm_ty: *const llvm.Type, + ) void { + dg.addArgAttr(llvm_fn, llvm_arg_i, "nonnull"); + dg.addArgAttr(llvm_fn, llvm_arg_i, "readonly"); + dg.addArgAttrInt(llvm_fn, llvm_arg_i, "align", alignment); + if (byval_attr) { + llvm_fn.addByValAttr(llvm_arg_i, param_llvm_ty); + } + } }; pub const FuncGen = struct { @@ -4504,9 +4603,10 @@ pub const FuncGen = struct { const arg = args[it.zig_index - 1]; const param_ty = self.air.typeOf(arg); const llvm_arg = try self.resolveInst(arg); + const llvm_param_ty = try self.dg.lowerType(param_ty); if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); - const load_inst = self.builder.buildLoad(llvm_arg, ""); + const load_inst = self.builder.buildLoad(llvm_param_ty, llvm_arg, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } else { @@ -4516,7 +4616,6 @@ pub const FuncGen = struct { // which is always lowered to an LLVM type of `*i8`. // 2. The argument is a global which does act as a pointer, however // a bitcast is needed in order for the LLVM types to match. - const llvm_param_ty = try self.dg.lowerType(param_ty); const casted_ptr = self.builder.buildBitCast(llvm_arg, llvm_param_ty, ""); try llvm_args.append(casted_ptr); } else { @@ -4551,7 +4650,7 @@ pub const FuncGen = struct { if (isByRef(param_ty)) { const alignment = param_ty.abiAlignment(target); const casted_ptr = self.builder.buildBitCast(llvm_arg, int_ptr_llvm_ty, ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(int_llvm_ty, casted_ptr, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } else { @@ -4567,7 +4666,7 @@ pub const FuncGen = struct { const casted_ptr = self.builder.buildBitCast(int_ptr, param_llvm_ty.pointerType(0), ""); const store_inst = self.builder.buildStore(llvm_arg, casted_ptr); store_inst.setAlignment(alignment); - const load_inst = self.builder.buildLoad(int_ptr, ""); + const load_inst = self.builder.buildLoad(int_llvm_ty, int_ptr, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); } @@ -4604,8 +4703,8 @@ pub const FuncGen = struct { try llvm_args.ensureUnusedCapacity(it.llvm_types_len); for (llvm_ints) |_, i_usize| { const i = @intCast(c_uint, i_usize); - const field_ptr = self.builder.buildStructGEP(casted_ptr, i, ""); - const load_inst = self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(ints_llvm_ty, casted_ptr, i, ""); + const load_inst = self.builder.buildLoad(field_types[i], field_ptr, ""); load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); llvm_args.appendAssumeCapacity(load_inst); } @@ -4632,13 +4731,13 @@ pub const FuncGen = struct { else => {}, } } - const ints_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); - const casted_ptr = self.builder.buildBitCast(arg_ptr, ints_llvm_ty.pointerType(0), ""); + const floats_llvm_ty = self.dg.context.structType(field_types.ptr, @intCast(c_uint, field_types.len), .False); + const casted_ptr = self.builder.buildBitCast(arg_ptr, floats_llvm_ty.pointerType(0), ""); try llvm_args.ensureUnusedCapacity(it.llvm_types_len); for (llvm_floats) |_, i_usize| { const i = @intCast(c_uint, i_usize); - const field_ptr = self.builder.buildStructGEP(casted_ptr, i, ""); - const load_inst = self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(floats_llvm_ty, casted_ptr, i, ""); + const load_inst = self.builder.buildLoad(field_types[i], field_ptr, ""); load_inst.setAlignment(target.cpu.arch.ptrBitWidth() / 8); llvm_args.appendAssumeCapacity(load_inst); } @@ -4662,17 +4761,18 @@ pub const FuncGen = struct { const float_ty = try self.dg.lowerType(arg_ty.structFieldType(0)); const field_count = @intCast(u32, arg_ty.structFieldCount()); - const arr_ty = float_ty.arrayType(field_count); + const array_llvm_ty = float_ty.arrayType(field_count); - const casted = self.builder.buildBitCast(llvm_arg, arr_ty.pointerType(0), ""); + const casted = self.builder.buildBitCast(llvm_arg, array_llvm_ty.pointerType(0), ""); const alignment = arg_ty.abiAlignment(target); - const load_inst = self.builder.buildLoad(casted, ""); + const load_inst = self.builder.buildLoad(array_llvm_ty, casted, ""); load_inst.setAlignment(alignment); try llvm_args.append(load_inst); }, }; const call = self.builder.buildCall( + try self.dg.lowerType(zig_fn_ty), llvm_fn, llvm_args.items.ptr, @intCast(c_uint, llvm_args.items.len), @@ -4698,7 +4798,7 @@ pub const FuncGen = struct { return rp; } else { // our by-ref status disagrees with sret so we must load. - const loaded = self.builder.buildLoad(rp, ""); + const loaded = self.builder.buildLoad(llvm_ret_ty, rp, ""); loaded.setAlignment(return_type.abiAlignment(target)); return loaded; } @@ -4720,7 +4820,7 @@ pub const FuncGen = struct { if (isByRef(return_type)) { return rp; } else { - const load_inst = self.builder.buildLoad(rp, ""); + const load_inst = self.builder.buildLoad(llvm_ret_ty, rp, ""); load_inst.setAlignment(alignment); return load_inst; } @@ -4778,7 +4878,7 @@ pub const FuncGen = struct { // operand is a pointer however self.ret_ptr is null so that means // we need to return a value. const casted_ptr = self.builder.buildBitCast(operand, ptr_abi_ty, ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); load_inst.setAlignment(alignment); _ = self.builder.buildRet(load_inst); return null; @@ -4795,7 +4895,7 @@ pub const FuncGen = struct { const store_inst = self.builder.buildStore(operand, rp); store_inst.setAlignment(alignment); const casted_ptr = self.builder.buildBitCast(rp, ptr_abi_ty, ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); load_inst.setAlignment(alignment); _ = self.builder.buildRet(load_inst); return null; @@ -4830,7 +4930,7 @@ pub const FuncGen = struct { const ptr_abi_ty = abi_ret_ty.pointerType(0); break :p self.builder.buildBitCast(ptr, ptr_abi_ty, ""); }; - const loaded = self.builder.buildLoad(casted_ptr, ""); + const loaded = self.builder.buildLoad(abi_ret_ty, casted_ptr, ""); loaded.setAlignment(ret_ty.abiAlignment(target)); _ = self.builder.buildRet(loaded); return null; @@ -4870,7 +4970,7 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const llvm_fn = try self.getCmpLtErrorsLenFunction(); const args: [1]*const llvm.Value = .{operand}; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn cmp( @@ -4897,8 +4997,9 @@ pub const FuncGen = struct { // We need to emit instructions to check for equality/inequality // of optionals that are not pointers. const is_by_ref = isByRef(scalar_ty); - const lhs_non_null = self.optIsNonNull(lhs, is_by_ref); - const rhs_non_null = self.optIsNonNull(rhs, is_by_ref); + const opt_llvm_ty = try self.dg.lowerType(scalar_ty); + const lhs_non_null = self.optIsNonNull(opt_llvm_ty, lhs, is_by_ref); + const rhs_non_null = self.optIsNonNull(opt_llvm_ty, rhs, is_by_ref); const llvm_i2 = self.context.intType(2); const lhs_non_null_i2 = self.builder.buildZExt(lhs_non_null, llvm_i2, ""); const rhs_non_null_i2 = self.builder.buildZExt(rhs_non_null, llvm_i2, ""); @@ -4921,8 +5022,8 @@ pub const FuncGen = struct { _ = self.builder.buildBr(end_block); self.builder.positionBuilderAtEnd(both_pl_block); - const lhs_payload = self.optPayloadHandle(lhs, scalar_ty); - const rhs_payload = self.optPayloadHandle(rhs, scalar_ty); + const lhs_payload = try self.optPayloadHandle(opt_llvm_ty, lhs, scalar_ty); + const rhs_payload = try self.optPayloadHandle(opt_llvm_ty, rhs, scalar_ty); const payload_cmp = try self.cmp(lhs_payload, rhs_payload, payload_ty, op); _ = self.builder.buildBr(end_block); const both_pl_block_end = self.builder.getInsertBlock(); @@ -5087,10 +5188,18 @@ pub const FuncGen = struct { return lowerTry(self, err_union_ptr, body, err_union_ty, true, result_ty); } - fn lowerTry(fg: *FuncGen, err_union: *const llvm.Value, body: []const Air.Inst.Index, err_union_ty: Type, operand_is_ptr: bool, result_ty: Type) !?*const llvm.Value { + fn lowerTry( + fg: *FuncGen, + err_union: *const llvm.Value, + body: []const Air.Inst.Index, + err_union_ty: Type, + operand_is_ptr: bool, + result_ty: Type, + ) !?*const llvm.Value { const payload_ty = err_union_ty.errorUnionPayload(); const payload_has_bits = payload_ty.hasRuntimeBitsIgnoreComptime(); const target = fg.dg.module.getTarget(); + const err_union_llvm_ty = try fg.dg.lowerType(err_union_ty); if (!err_union_ty.errorUnionSet().errorSetIsEmpty()) { const is_err = err: { @@ -5098,14 +5207,17 @@ pub const FuncGen = struct { const zero = err_set_ty.constNull(); if (!payload_has_bits) { // TODO add alignment to this load - const loaded = if (operand_is_ptr) fg.builder.buildLoad(err_union, "") else err_union; + const loaded = if (operand_is_ptr) + fg.builder.buildLoad(err_set_ty, err_union, "") + else + err_union; break :err fg.builder.buildICmp(.NE, loaded, zero, ""); } const err_field_index = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = fg.builder.buildStructGEP(err_union, err_field_index, ""); + const err_field_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, err_field_index, ""); // TODO add alignment to this load - const loaded = fg.builder.buildLoad(err_field_ptr, ""); + const loaded = fg.builder.buildLoad(err_set_ty, err_field_ptr, ""); break :err fg.builder.buildICmp(.NE, loaded, zero, ""); } const loaded = fg.builder.buildExtractValue(err_union, err_field_index, ""); @@ -5131,13 +5243,13 @@ pub const FuncGen = struct { } const offset = errUnionPayloadOffset(payload_ty, target); if (operand_is_ptr or isByRef(payload_ty)) { - return fg.builder.buildStructGEP(err_union, offset, ""); + return fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); } else if (isByRef(err_union_ty)) { - const payload_ptr = fg.builder.buildStructGEP(err_union, offset, ""); + const payload_ptr = fg.builder.buildStructGEP(err_union_llvm_ty, err_union, offset, ""); if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = fg.builder.buildLoad(payload_ptr, ""); + const load_inst = fg.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -5232,7 +5344,8 @@ pub const FuncGen = struct { const indices: [2]*const llvm.Value = .{ llvm_usize.constNull(), llvm_usize.constNull(), }; - const ptr = self.builder.buildInBoundsGEP(operand, &indices, indices.len, ""); + const array_llvm_ty = try self.dg.lowerType(array_ty); + const ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indices, indices.len, ""); const partial = self.builder.buildInsertValue(slice_llvm_ty.getUndef(), ptr, 0, ""); return self.builder.buildInsertValue(partial, len, 1, ""); } @@ -5293,7 +5406,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, dest_llvm_ty); const params = [1]*const llvm.Value{extended}; - return self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + return self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); } fn airFloatToInt(self: *FuncGen, inst: Air.Inst.Index, want_fast_math: bool) !?*const llvm.Value { @@ -5348,7 +5461,7 @@ pub const FuncGen = struct { const libc_fn = self.getLibcFunction(fn_name, ¶m_types, libc_ret_ty); const params = [1]*const llvm.Value{operand}; - var result = self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + var result = self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); if (libc_ret_ty != ret_ty) result = self.builder.buildBitCast(result, ret_ty, ""); if (ret_ty != dest_llvm_ty) result = self.builder.buildTrunc(result, dest_llvm_ty, ""); @@ -5368,8 +5481,10 @@ pub const FuncGen = struct { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const slice_ptr = try self.resolveInst(ty_op.operand); + const slice_ptr_ty = self.air.typeOf(ty_op.operand); + const slice_llvm_ty = try self.dg.lowerPtrElemTy(slice_ptr_ty.childType()); - return self.builder.buildStructGEP(slice_ptr, index, ""); + return self.builder.buildStructGEP(slice_llvm_ty, slice_ptr, index, ""); } fn airSliceElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5379,7 +5494,10 @@ pub const FuncGen = struct { const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - const ptr = self.sliceElemPtr(slice, index); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType()); + const base_ptr = self.builder.buildExtractValue(slice, 0, ""); + const indices: [1]*const llvm.Value = .{index}; + const ptr = self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); return self.load(ptr, slice_ty); } @@ -5387,10 +5505,14 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; + const slice_ty = self.air.typeOf(bin_op.lhs); const slice = try self.resolveInst(bin_op.lhs); const index = try self.resolveInst(bin_op.rhs); - return self.sliceElemPtr(slice, index); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(slice_ty.childType()); + const base_ptr = self.builder.buildExtractValue(slice, 0, ""); + const indices: [1]*const llvm.Value = .{index}; + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } fn airArrayElemVal(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -5401,13 +5523,15 @@ pub const FuncGen = struct { const array_llvm_val = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); if (isByRef(array_ty)) { + const array_llvm_ty = try self.dg.lowerType(array_ty); const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_val, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, array_llvm_val, &indices, indices.len, ""); const elem_ty = array_ty.childType(); if (isByRef(elem_ty)) { return elem_ptr; } else { - return self.builder.buildLoad(elem_ptr, ""); + const elem_llvm_ty = try self.dg.lowerType(elem_ty); + return self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); } } @@ -5420,15 +5544,17 @@ pub const FuncGen = struct { const ptr_ty = self.air.typeOf(bin_op.lhs); if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) return null; + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); + // TODO: when we go fully opaque pointers in LLVM 16 we can remove this branch const ptr = if (ptr_ty.isSinglePointer()) ptr: { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - break :ptr self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else ptr: { const indices: [1]*const llvm.Value = .{rhs}; - break :ptr self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + break :ptr self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); }; return self.load(ptr, ptr_ty); } @@ -5444,13 +5570,14 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const rhs = try self.resolveInst(bin_op.rhs); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(elem_ty); if (ptr_ty.isSinglePointer()) { // If this is a single-item pointer to an array, we need another index in the GEP. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), rhs }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{rhs}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -5534,20 +5661,22 @@ pub const FuncGen = struct { assert(struct_ty.containerLayout() != .Packed); var ptr_ty_buf: Type.Payload.Pointer = undefined; const llvm_field_index = llvmFieldIndex(struct_ty, field_index, target, &ptr_ty_buf).?; - const field_ptr = self.builder.buildStructGEP(struct_llvm_val, llvm_field_index, ""); + const struct_llvm_ty = try self.dg.lowerType(struct_ty); + const field_ptr = self.builder.buildStructGEP(struct_llvm_ty, struct_llvm_val, llvm_field_index, ""); const field_ptr_ty = Type.initPayload(&ptr_ty_buf.base); return self.load(field_ptr, field_ptr_ty); }, .Union => { - const llvm_field_ty = try self.dg.lowerType(field_ty); + const union_llvm_ty = try self.dg.lowerType(struct_ty); const layout = struct_ty.unionGetLayout(target); const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); - const union_field_ptr = self.builder.buildStructGEP(struct_llvm_val, payload_index, ""); + const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, struct_llvm_val, payload_index, ""); + const llvm_field_ty = try self.dg.lowerType(field_ty); const field_ptr = self.builder.buildBitCast(union_field_ptr, llvm_field_ty.pointerType(0), ""); if (isByRef(field_ty)) { return field_ptr; } else { - return self.builder.buildLoad(field_ptr, ""); + return self.builder.buildLoad(llvm_field_ty, field_ptr, ""); } }, else => unreachable, @@ -5776,7 +5905,9 @@ pub const FuncGen = struct { const max_param_count = inputs.len + outputs.len; const llvm_param_types = try arena.alloc(*const llvm.Type, max_param_count); const llvm_param_values = try arena.alloc(*const llvm.Value, max_param_count); - const llvm_param_attrs = try arena.alloc(bool, max_param_count); + // This stores whether we need to add an elementtype attribute and + // if so, the element type itself. + const llvm_param_attrs = try arena.alloc(?*const llvm.Type, max_param_count); const target = self.dg.module.getTarget(); var llvm_ret_i: usize = 0; @@ -5794,7 +5925,7 @@ pub const FuncGen = struct { // for the string, we still use the next u32 for the null terminator. extra_i += (constraint.len + name.len + (2 + 3)) / 4; - try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 1); + try llvm_constraints.ensureUnusedCapacity(self.gpa, constraint.len + 3); if (total_i != 0) { llvm_constraints.appendAssumeCapacity(','); } @@ -5803,8 +5934,10 @@ pub const FuncGen = struct { // Pass any non-return outputs indirectly, if the constraint accepts a memory location llvm_ret_indirect[i] = (output != .none) and constraintAllowsMemory(constraint); if (output != .none) { - try llvm_constraints.ensureUnusedCapacity(self.gpa, llvm_constraints.capacity + 1); const output_inst = try self.resolveInst(output); + const output_ty = self.air.typeOf(output); + assert(output_ty.zigTypeTag() == .Pointer); + const elem_llvm_ty = try self.dg.lowerPtrElemTy(output_ty.childType()); if (llvm_ret_indirect[i]) { // Pass the result by reference as an indirect output (e.g. "=*m") @@ -5812,11 +5945,11 @@ pub const FuncGen = struct { llvm_param_values[llvm_param_i] = output_inst; llvm_param_types[llvm_param_i] = output_inst.typeOf(); - llvm_param_attrs[llvm_param_i] = true; + llvm_param_attrs[llvm_param_i] = elem_llvm_ty; llvm_param_i += 1; } else { // Pass the result directly (e.g. "=r") - llvm_ret_types[llvm_ret_i] = output_inst.typeOf().getElementType(); + llvm_ret_types[llvm_ret_i] = elem_llvm_ty; llvm_ret_i += 1; } } else { @@ -5854,16 +5987,19 @@ pub const FuncGen = struct { const arg_llvm_value = try self.resolveInst(input); const arg_ty = self.air.typeOf(input); + var llvm_elem_ty: ?*const llvm.Type = null; if (isByRef(arg_ty)) { + llvm_elem_ty = try self.dg.lowerPtrElemTy(arg_ty); if (constraintAllowsMemory(constraint)) { llvm_param_values[llvm_param_i] = arg_llvm_value; llvm_param_types[llvm_param_i] = arg_llvm_value.typeOf(); } else { const alignment = arg_ty.abiAlignment(target); - const load_inst = self.builder.buildLoad(arg_llvm_value, ""); + const arg_llvm_ty = try self.dg.lowerType(arg_ty); + const load_inst = self.builder.buildLoad(arg_llvm_ty, arg_llvm_value, ""); load_inst.setAlignment(alignment); llvm_param_values[llvm_param_i] = load_inst; - llvm_param_types[llvm_param_i] = load_inst.typeOf(); + llvm_param_types[llvm_param_i] = arg_llvm_ty; } } else { if (constraintAllowsRegister(constraint)) { @@ -5897,7 +6033,12 @@ pub const FuncGen = struct { // In the case of indirect inputs, LLVM requires the callsite to have // an elementtype(<ty>) attribute. - llvm_param_attrs[llvm_param_i] = constraint[0] == '*'; + if (constraint[0] == '*') { + llvm_param_attrs[llvm_param_i] = llvm_elem_ty orelse + try self.dg.lowerPtrElemTy(arg_ty.childType()); + } else { + llvm_param_attrs[llvm_param_i] = null; + } llvm_param_i += 1; total_i += 1; @@ -6024,6 +6165,7 @@ pub const FuncGen = struct { .False, ); const call = self.builder.buildCall( + llvm_fn_ty, asm_fn, llvm_param_values.ptr, @intCast(c_uint, param_count), @@ -6031,10 +6173,9 @@ pub const FuncGen = struct { .Auto, "", ); - for (llvm_param_attrs[0..param_count]) |need_elem_ty, i| { - if (need_elem_ty) { - const elem_ty = llvm_param_types[i].getElementType(); - llvm.setCallElemTypeAttr(call, i, elem_ty); + for (llvm_param_attrs[0..param_count]) |llvm_elem_ty, i| { + if (llvm_elem_ty) |llvm_ty| { + llvm.setCallElemTypeAttr(call, i, llvm_ty); } } @@ -6074,9 +6215,12 @@ pub const FuncGen = struct { const operand = try self.resolveInst(un_op); const operand_ty = self.air.typeOf(un_op); const optional_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; + const optional_llvm_ty = try self.dg.lowerType(optional_ty); if (optional_ty.optionalReprIsPayload()) { - const optional_llvm_ty = try self.dg.lowerType(optional_ty); - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(optional_llvm_ty, operand, "") + else + operand; return self.builder.buildICmp(pred, loaded, optional_llvm_ty.constNull(), ""); } @@ -6085,13 +6229,16 @@ pub const FuncGen = struct { var buf: Type.Payload.ElemType = undefined; const payload_ty = optional_ty.optionalChild(&buf); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(optional_llvm_ty, operand, "") + else + operand; const llvm_i8 = self.dg.context.intType(8); return self.builder.buildICmp(pred, loaded, llvm_i8.constNull(), ""); } const is_by_ref = operand_is_ptr or isByRef(optional_ty); - const non_null_bit = self.optIsNonNull(operand, is_by_ref); + const non_null_bit = self.optIsNonNull(optional_llvm_ty, operand, is_by_ref); if (pred == .EQ) { return self.builder.buildNot(non_null_bit, ""); } else { @@ -6112,7 +6259,7 @@ pub const FuncGen = struct { const operand_ty = self.air.typeOf(un_op); const err_union_ty = if (operand_is_ptr) operand_ty.childType() else operand_ty; const payload_ty = err_union_ty.errorUnionPayload(); - const err_set_ty = try self.dg.lowerType(Type.initTag(.anyerror)); + const err_set_ty = try self.dg.lowerType(Type.anyerror); const zero = err_set_ty.constNull(); if (err_union_ty.errorUnionSet().errorSetIsEmpty()) { @@ -6125,7 +6272,10 @@ pub const FuncGen = struct { } if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { - const loaded = if (operand_is_ptr) self.builder.buildLoad(operand, "") else operand; + const loaded = if (operand_is_ptr) + self.builder.buildLoad(try self.dg.lowerType(err_union_ty), operand, "") + else + operand; return self.builder.buildICmp(op, loaded, zero, ""); } @@ -6133,8 +6283,9 @@ pub const FuncGen = struct { const err_field_index = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = self.builder.buildStructGEP(operand, err_field_index, ""); - const loaded = self.builder.buildLoad(err_field_ptr, ""); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, err_field_index, ""); + const loaded = self.builder.buildLoad(err_set_ty, err_field_ptr, ""); return self.builder.buildICmp(op, loaded, zero, ""); } @@ -6155,7 +6306,7 @@ pub const FuncGen = struct { // We have a pointer to a zero-bit value and we need to return // a pointer to a zero-bit value. - // TODO once we update to LLVM 14 this bitcast won't be necessary. + // TODO once we update to LLVM 16 this bitcast won't be necessary. const res_ptr_ty = try self.dg.lowerType(result_ty); return self.builder.buildBitCast(operand, res_ptr_ty, ""); } @@ -6163,7 +6314,8 @@ pub const FuncGen = struct { // The payload and the optional are the same value. return operand; } - return self.builder.buildStructGEP(operand, 0, ""); + const optional_llvm_ty = try self.dg.lowerType(optional_ty); + return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); } fn airOptionalPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6180,7 +6332,7 @@ pub const FuncGen = struct { // We have a pointer to a i8. We need to set it to 1 and then return the same pointer. _ = self.builder.buildStore(non_null_bit, operand); - // TODO once we update to LLVM 14 this bitcast won't be necessary. + // TODO once we update to LLVM 16 this bitcast won't be necessary. const res_ptr_ty = try self.dg.lowerType(result_ty); return self.builder.buildBitCast(operand, res_ptr_ty, ""); } @@ -6191,7 +6343,8 @@ pub const FuncGen = struct { } // First set the non-null bit. - const non_null_ptr = self.builder.buildStructGEP(operand, 1, ""); + const optional_llvm_ty = try self.dg.lowerType(optional_ty); + const non_null_ptr = self.builder.buildStructGEP(optional_llvm_ty, operand, 1, ""); // TODO set alignment on this store _ = self.builder.buildStore(non_null_bit, non_null_ptr); @@ -6199,7 +6352,7 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; - return self.builder.buildStructGEP(operand, 0, ""); + return self.builder.buildStructGEP(optional_llvm_ty, operand, 0, ""); } fn airOptionalPayload(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6216,7 +6369,8 @@ pub const FuncGen = struct { return operand; } - return self.optPayloadHandle(operand, optional_ty); + const opt_llvm_ty = try self.dg.lowerType(optional_ty); + return self.optPayloadHandle(opt_llvm_ty, operand, optional_ty); } fn airErrUnionPayload( @@ -6242,14 +6396,15 @@ pub const FuncGen = struct { return self.builder.buildBitCast(operand, res_ptr_ty, ""); } const offset = errUnionPayloadOffset(payload_ty, target); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); if (operand_is_ptr or isByRef(payload_ty)) { - return self.builder.buildStructGEP(operand, offset, ""); + return self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); } else if (isByRef(err_union_ty)) { - const payload_ptr = self.builder.buildStructGEP(operand, offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); if (isByRef(payload_ty)) { return payload_ptr; } - const load_inst = self.builder.buildLoad(payload_ptr, ""); + const load_inst = self.builder.buildLoad(payload_ptr.getGEPResultElementType(), payload_ptr, ""); load_inst.setAlignment(payload_ty.abiAlignment(target)); return load_inst; } @@ -6277,18 +6432,21 @@ pub const FuncGen = struct { } } + const err_set_llvm_ty = try self.dg.lowerType(Type.anyerror); + const payload_ty = err_union_ty.errorUnionPayload(); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { if (!operand_is_ptr) return operand; - return self.builder.buildLoad(operand, ""); + return self.builder.buildLoad(err_set_llvm_ty, operand, ""); } const target = self.dg.module.getTarget(); const offset = errUnionErrorOffset(payload_ty, target); if (operand_is_ptr or isByRef(err_union_ty)) { - const err_field_ptr = self.builder.buildStructGEP(operand, offset, ""); - return self.builder.buildLoad(err_field_ptr, ""); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); + const err_field_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, offset, ""); + return self.builder.buildLoad(err_set_llvm_ty, err_field_ptr, ""); } return self.builder.buildExtractValue(operand, offset, ""); @@ -6297,19 +6455,20 @@ pub const FuncGen = struct { fn airErrUnionPayloadPtrSet(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { const ty_op = self.air.instructions.items(.data)[inst].ty_op; const operand = try self.resolveInst(ty_op.operand); - const error_union_ty = self.air.typeOf(ty_op.operand).childType(); + const err_union_ty = self.air.typeOf(ty_op.operand).childType(); - const payload_ty = error_union_ty.errorUnionPayload(); + const payload_ty = err_union_ty.errorUnionPayload(); const non_error_val = try self.dg.lowerValue(.{ .ty = Type.anyerror, .val = Value.zero }); if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { _ = self.builder.buildStore(non_error_val, operand); return operand; } const target = self.dg.module.getTarget(); + const err_union_llvm_ty = try self.dg.lowerType(err_union_ty); { const error_offset = errUnionErrorOffset(payload_ty, target); // First set the non-error value. - const non_null_ptr = self.builder.buildStructGEP(operand, error_offset, ""); + const non_null_ptr = self.builder.buildStructGEP(err_union_llvm_ty, operand, error_offset, ""); const store_inst = self.builder.buildStore(non_error_val, non_null_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); } @@ -6318,7 +6477,7 @@ pub const FuncGen = struct { return null; const payload_offset = errUnionPayloadOffset(payload_ty, target); - return self.builder.buildStructGEP(operand, payload_offset, ""); + return self.builder.buildStructGEP(err_union_llvm_ty, operand, payload_offset, ""); } fn airErrReturnTrace(self: *FuncGen, _: Air.Inst.Index) !?*const llvm.Value { @@ -6350,14 +6509,14 @@ pub const FuncGen = struct { const target = self.dg.module.getTarget(); const optional_ptr = self.buildAlloca(llvm_optional_ty); optional_ptr.setAlignment(optional_ty.abiAlignment(target)); - const payload_ptr = self.builder.buildStructGEP(optional_ptr, 0, ""); + const payload_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 0, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, }; const payload_ptr_ty = Type.initPayload(&ptr_ty_payload.base); self.store(payload_ptr, payload_ptr_ty, operand, .NotAtomic); - const non_null_ptr = self.builder.buildStructGEP(optional_ptr, 1, ""); + const non_null_ptr = self.builder.buildStructGEP(llvm_optional_ty, optional_ptr, 1, ""); _ = self.builder.buildStore(non_null_bit, non_null_ptr); return optional_ptr; } @@ -6384,10 +6543,10 @@ pub const FuncGen = struct { if (isByRef(err_un_ty)) { const result_ptr = self.buildAlloca(err_un_llvm_ty); result_ptr.setAlignment(err_un_ty.abiAlignment(target)); - const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); + const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); const store_inst = self.builder.buildStore(ok_err_code, err_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); - const payload_ptr = self.builder.buildStructGEP(result_ptr, payload_offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, @@ -6419,10 +6578,10 @@ pub const FuncGen = struct { if (isByRef(err_un_ty)) { const result_ptr = self.buildAlloca(err_un_llvm_ty); result_ptr.setAlignment(err_un_ty.abiAlignment(target)); - const err_ptr = self.builder.buildStructGEP(result_ptr, error_offset, ""); + const err_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, error_offset, ""); const store_inst = self.builder.buildStore(operand, err_ptr); store_inst.setAlignment(Type.anyerror.abiAlignment(target)); - const payload_ptr = self.builder.buildStructGEP(result_ptr, payload_offset, ""); + const payload_ptr = self.builder.buildStructGEP(err_un_llvm_ty, result_ptr, payload_offset, ""); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = payload_ty, @@ -6447,7 +6606,7 @@ pub const FuncGen = struct { const llvm_u32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.wasm.memory.size", &.{llvm_u32}); const args: [1]*const llvm.Value = .{llvm_u32.constInt(index, .False)}; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airWasmMemoryGrow(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6460,7 +6619,7 @@ pub const FuncGen = struct { llvm_u32.constInt(index, .False), operand, }; - return self.builder.buildCall(llvm_fn, &args, args.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .Fast, .Auto, ""); } fn airMin(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -6763,15 +6922,16 @@ pub const FuncGen = struct { const base_ptr = try self.resolveInst(bin_op.lhs); const offset = try self.resolveInst(bin_op.rhs); const ptr_ty = self.air.typeOf(bin_op.lhs); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), offset, }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{offset}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -6784,15 +6944,16 @@ pub const FuncGen = struct { const offset = try self.resolveInst(bin_op.rhs); const negative_offset = self.builder.buildNeg(offset, ""); const ptr_ty = self.air.typeOf(bin_op.lhs); + const llvm_elem_ty = try self.dg.lowerPtrElemTy(ptr_ty.childType()); if (ptr_ty.ptrSize() == .One) { // It's a pointer to an array, so according to LLVM we need an extra GEP index. const indices: [2]*const llvm.Value = .{ self.context.intType(32).constNull(), negative_offset, }; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } else { const indices: [1]*const llvm.Value = .{negative_offset}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(llvm_elem_ty, base_ptr, &indices, indices.len, ""); } } @@ -6823,7 +6984,7 @@ pub const FuncGen = struct { const tg = self.dg.module.getTarget(); const llvm_fn = self.getIntrinsic(intrinsic_name, &.{llvm_lhs_ty}); - const result_struct = self.builder.buildCall(llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); + const result_struct = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &[_]*const llvm.Value{ lhs, rhs }, 2, .Fast, .Auto, ""); const result = self.builder.buildExtractValue(result_struct, 0, ""); const overflow_bit = self.builder.buildExtractValue(result_struct, 1, ""); @@ -6838,12 +6999,12 @@ pub const FuncGen = struct { const result_alignment = dest_ty.abiAlignment(target); alloca_inst.setAlignment(result_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); const store_inst = self.builder.buildStore(result, field_ptr); store_inst.setAlignment(result_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, overflow_index, ""); const store_inst = self.builder.buildStore(overflow_bit, field_ptr); store_inst.setAlignment(1); } @@ -6875,7 +7036,7 @@ pub const FuncGen = struct { for (args_vectors) |arg_vector, k| { args[k] = self.builder.buildExtractElement(arg_vector, index_i32, ""); } - const result_elem = self.builder.buildCall(llvm_fn, &args, args_len, .C, .Auto, ""); + const result_elem = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args_len, .C, .Auto, ""); result = self.builder.buildInsertElement(result, result_elem, index_i32, ""); } return result; @@ -7002,7 +7163,7 @@ pub const FuncGen = struct { return self.builder.buildICmp(int_pred, result, zero_vector, ""); } - const result = self.builder.buildCall(libc_fn, ¶ms, params.len, .C, .Auto, ""); + const result = self.builder.buildCall(libc_fn.globalGetValueType(), libc_fn, ¶ms, params.len, .C, .Auto, ""); return self.builder.buildICmp(int_pred, result, zero, ""); } @@ -7130,7 +7291,7 @@ pub const FuncGen = struct { break :b libc_fn; }, }; - return self.builder.buildCall(llvm_fn, ¶ms, params_len, .C, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params_len, .C, .Auto, ""); } fn airMulAdd(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -7190,12 +7351,12 @@ pub const FuncGen = struct { const result_alignment = dest_ty.abiAlignment(target); alloca_inst.setAlignment(result_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, result_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, result_index, ""); const store_inst = self.builder.buildStore(result, field_ptr); store_inst.setAlignment(result_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, overflow_index, ""); + const field_ptr = self.builder.buildStructGEP(llvm_dest_ty, alloca_inst, overflow_index, ""); const store_inst = self.builder.buildStore(overflow_bit, field_ptr); store_inst.setAlignment(1); } @@ -7485,7 +7646,7 @@ pub const FuncGen = struct { const index_usize = llvm_usize.constInt(i, .False); const index_u32 = llvm_u32.constInt(i, .False); const indexes: [2]*const llvm.Value = .{ zero, index_usize }; - const elem_ptr = self.builder.buildInBoundsGEP(array_ptr, &indexes, indexes.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_dest_ty, array_ptr, &indexes, indexes.len, ""); const elem = self.builder.buildExtractElement(operand, index_u32, ""); _ = self.builder.buildStore(elem, elem_ptr); } @@ -7502,7 +7663,7 @@ pub const FuncGen = struct { if (bitcast_ok) { const llvm_vector_ptr_ty = llvm_vector_ty.pointerType(0); const casted_ptr = self.builder.buildBitCast(operand, llvm_vector_ptr_ty, ""); - const vector = self.builder.buildLoad(casted_ptr, ""); + const vector = self.builder.buildLoad(llvm_vector_ty, casted_ptr, ""); // The array is aligned to the element's alignment, while the vector might have a completely // different alignment. This means we need to enforce the alignment of this load. vector.setAlignment(elem_ty.abiAlignment(target)); @@ -7510,6 +7671,8 @@ pub const FuncGen = struct { } else { // If the ABI size of the element type is not evenly divisible by size in bits; // a simple bitcast will not work, and we fall back to extractelement. + const array_llvm_ty = try self.dg.lowerType(operand_ty); + const elem_llvm_ty = try self.dg.lowerType(elem_ty); const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_u32 = self.context.intType(32); const zero = llvm_usize.constNull(); @@ -7520,8 +7683,8 @@ pub const FuncGen = struct { const index_usize = llvm_usize.constInt(i, .False); const index_u32 = llvm_u32.constInt(i, .False); const indexes: [2]*const llvm.Value = .{ zero, index_usize }; - const elem_ptr = self.builder.buildInBoundsGEP(operand, &indexes, indexes.len, ""); - const elem = self.builder.buildLoad(elem_ptr, ""); + const elem_ptr = self.builder.buildInBoundsGEP(array_llvm_ty, operand, &indexes, indexes.len, ""); + const elem = self.builder.buildLoad(elem_llvm_ty, elem_ptr, ""); vector = self.builder.buildInsertElement(vector, elem, index_u32, ""); } @@ -7532,7 +7695,7 @@ pub const FuncGen = struct { if (operand_is_ref) { // Bitcast the operand pointer, then load. const casted_ptr = self.builder.buildBitCast(operand, llvm_dest_ty.pointerType(0), ""); - const load_inst = self.builder.buildLoad(casted_ptr, ""); + const load_inst = self.builder.buildLoad(llvm_dest_ty, casted_ptr, ""); load_inst.setAlignment(operand_ty.abiAlignment(target)); return load_inst; } @@ -7560,7 +7723,7 @@ pub const FuncGen = struct { const casted_ptr = self.builder.buildBitCast(result_ptr, operand_llvm_ty.pointerType(0), ""); const store_inst = self.builder.buildStore(operand, casted_ptr); store_inst.setAlignment(alignment); - const load_inst = self.builder.buildLoad(result_ptr, ""); + const load_inst = self.builder.buildLoad(llvm_dest_ty, result_ptr, ""); load_inst.setAlignment(alignment); return load_inst; } @@ -7739,7 +7902,7 @@ pub const FuncGen = struct { fn airBreakpoint(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { _ = inst; const llvm_fn = self.getIntrinsic("llvm.debugtrap", &.{}); - _ = self.builder.buildCall(llvm_fn, undefined, 0, .C, .Auto, ""); + _ = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, undefined, 0, .C, .Auto, ""); return null; } @@ -7756,7 +7919,7 @@ pub const FuncGen = struct { const llvm_i32 = self.context.intType(32); const llvm_fn = self.getIntrinsic("llvm.returnaddress", &.{}); const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7764,7 +7927,7 @@ pub const FuncGen = struct { if (self.liveness.isUnused(inst)) return null; const llvm_i32 = self.context.intType(32); - const llvm_fn_name = "llvm.frameaddress.p0i8"; + const llvm_fn_name = "llvm.frameaddress.p0"; const llvm_fn = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { const llvm_p0i8 = self.context.intType(8).pointerType(0); const param_types = [_]*const llvm.Type{llvm_i32}; @@ -7773,7 +7936,7 @@ pub const FuncGen = struct { }; const params = [_]*const llvm.Value{llvm_i32.constNull()}; - const ptr_val = self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + const ptr_val = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); const llvm_usize = try self.dg.lowerType(Type.usize); return self.builder.buildPtrToInt(ptr_val, llvm_usize, ""); } @@ -7894,20 +8057,31 @@ pub const FuncGen = struct { const atomic_load = self.air.instructions.items(.data)[inst].atomic_load; const ptr = try self.resolveInst(atomic_load.ptr); const ptr_ty = self.air.typeOf(atomic_load.ptr); - if (!ptr_ty.isVolatilePtr() and self.liveness.isUnused(inst)) + const ptr_info = ptr_ty.ptrInfo().data; + if (!ptr_info.@"volatile" and self.liveness.isUnused(inst)) + return null; + const elem_ty = ptr_info.pointee_type; + if (!elem_ty.hasRuntimeBitsIgnoreComptime()) return null; const ordering = toLlvmAtomicOrdering(atomic_load.order); - const operand_ty = ptr_ty.elemType(); - const opt_abi_ty = self.dg.getAtomicAbiType(operand_ty, false); + const opt_abi_llvm_ty = self.dg.getAtomicAbiType(elem_ty, false); + const target = self.dg.module.getTarget(); + const ptr_alignment = ptr_info.alignment(target); + const ptr_volatile = llvm.Bool.fromBool(ptr_info.@"volatile"); + const elem_llvm_ty = try self.dg.lowerType(elem_ty); - if (opt_abi_ty) |abi_ty| { + if (opt_abi_llvm_ty) |abi_llvm_ty| { // operand needs widening and truncating - const casted_ptr = self.builder.buildBitCast(ptr, abi_ty.pointerType(0), ""); - const load_inst = (try self.load(casted_ptr, ptr_ty)).?; + const casted_ptr = self.builder.buildBitCast(ptr, abi_llvm_ty.pointerType(0), ""); + const load_inst = self.builder.buildLoad(abi_llvm_ty, casted_ptr, ""); + load_inst.setAlignment(ptr_alignment); + load_inst.setVolatile(ptr_volatile); load_inst.setOrdering(ordering); - return self.builder.buildTrunc(load_inst, try self.dg.lowerType(operand_ty), ""); + return self.builder.buildTrunc(load_inst, elem_llvm_ty, ""); } - const load_inst = (try self.load(ptr, ptr_ty)).?; + const load_inst = self.builder.buildLoad(elem_llvm_ty, ptr, ""); + load_inst.setAlignment(ptr_alignment); + load_inst.setVolatile(ptr_volatile); load_inst.setOrdering(ordering); return load_inst; } @@ -7997,8 +8171,9 @@ pub const FuncGen = struct { _ = self.builder.buildStore(new_tag, union_ptr); return null; } + const un_llvm_ty = try self.dg.lowerType(un_ty); const tag_index = @boolToInt(layout.tag_align < layout.payload_align); - const tag_field_ptr = self.builder.buildStructGEP(union_ptr, tag_index, ""); + const tag_field_ptr = self.builder.buildStructGEP(un_llvm_ty, union_ptr, tag_index, ""); // TODO alignment on this store _ = self.builder.buildStore(new_tag, tag_field_ptr); return null; @@ -8014,12 +8189,13 @@ pub const FuncGen = struct { if (layout.tag_size == 0) return null; const union_handle = try self.resolveInst(ty_op.operand); if (isByRef(un_ty)) { + const llvm_un_ty = try self.dg.lowerType(un_ty); if (layout.payload_size == 0) { - return self.builder.buildLoad(union_handle, ""); + return self.builder.buildLoad(llvm_un_ty, union_handle, ""); } const tag_index = @boolToInt(layout.tag_align < layout.payload_align); - const tag_field_ptr = self.builder.buildStructGEP(union_handle, tag_index, ""); - return self.builder.buildLoad(tag_field_ptr, ""); + const tag_field_ptr = self.builder.buildStructGEP(llvm_un_ty, union_handle, tag_index, ""); + return self.builder.buildLoad(tag_field_ptr.getGEPResultElementType(), tag_field_ptr, ""); } else { if (layout.payload_size == 0) { return union_handle; @@ -8062,7 +8238,7 @@ pub const FuncGen = struct { const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); const params = [_]*const llvm.Value{ operand, llvm_i1.constNull() }; - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -8089,7 +8265,7 @@ pub const FuncGen = struct { const operand_llvm_ty = try self.dg.lowerType(operand_ty); const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -8146,7 +8322,7 @@ pub const FuncGen = struct { const params = [_]*const llvm.Value{operand}; const fn_val = self.getIntrinsic(llvm_fn_name, &.{operand_llvm_ty}); - const wrong_size_result = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + const wrong_size_result = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); const result_ty = self.air.typeOfIndex(inst); const result_llvm_ty = try self.dg.lowerType(result_ty); @@ -8216,7 +8392,7 @@ pub const FuncGen = struct { const llvm_fn = try self.getIsNamedEnumValueFunction(enum_ty); const params = [_]*const llvm.Value{operand}; - return self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); } fn getIsNamedEnumValueFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { @@ -8297,7 +8473,7 @@ pub const FuncGen = struct { const llvm_fn = try self.getEnumTagNameFunction(enum_ty); const params = [_]*const llvm.Value{operand}; - return self.builder.buildCall(llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); + return self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, ¶ms, params.len, .Fast, .Auto, ""); } fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value { @@ -8358,7 +8534,8 @@ pub const FuncGen = struct { for (fields.keys()) |name, field_index| { const str_init = self.dg.context.constString(name.ptr, @intCast(c_uint, name.len), .False); - const str_global = self.dg.object.llvm_module.addGlobal(str_init.typeOf(), ""); + const str_init_llvm_ty = str_init.typeOf(); + const str_global = self.dg.object.llvm_module.addGlobal(str_init_llvm_ty, ""); str_global.setInitializer(str_init); str_global.setLinkage(.Private); str_global.setGlobalConstant(.True); @@ -8366,7 +8543,7 @@ pub const FuncGen = struct { str_global.setAlignment(1); const slice_fields = [_]*const llvm.Value{ - str_global.constInBoundsGEP(&array_ptr_indices, array_ptr_indices.len), + str_init_llvm_ty.constInBoundsGEP(str_global, &array_ptr_indices, array_ptr_indices.len), usize_llvm_ty.constInt(name.len, .False), }; const slice_init = llvm_ret_ty.constNamedStruct(&slice_fields, slice_fields.len); @@ -8391,7 +8568,7 @@ pub const FuncGen = struct { switch_instr.addCase(this_tag_int_value, return_block); self.builder.positionBuilderAtEnd(return_block); - const loaded = self.builder.buildLoad(slice_global, ""); + const loaded = self.builder.buildLoad(llvm_ret_ty, slice_global, ""); loaded.setAlignment(slice_alignment); _ = self.builder.buildRet(loaded); } @@ -8425,12 +8602,15 @@ pub const FuncGen = struct { const un_op = self.air.instructions.items(.data)[inst].un_op; const operand = try self.resolveInst(un_op); + const slice_ty = self.air.typeOfIndex(inst); + const slice_llvm_ty = try self.dg.lowerType(slice_ty); const error_name_table_ptr = try self.getErrorNameTable(); - const error_name_table = self.builder.buildLoad(error_name_table_ptr, ""); + const ptr_slice_llvm_ty = slice_llvm_ty.pointerType(0); + const error_name_table = self.builder.buildLoad(ptr_slice_llvm_ty, error_name_table_ptr, ""); const indices = [_]*const llvm.Value{operand}; - const error_name_ptr = self.builder.buildInBoundsGEP(error_name_table, &indices, indices.len, ""); - return self.builder.buildLoad(error_name_ptr, ""); + const error_name_ptr = self.builder.buildInBoundsGEP(slice_llvm_ty, error_name_table, &indices, indices.len, ""); + return self.builder.buildLoad(slice_llvm_ty, error_name_ptr, ""); } fn airSplat(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value { @@ -8607,7 +8787,7 @@ pub const FuncGen = struct { const llvm_elem = try self.resolveInst(elem); const llvm_i = llvmFieldIndex(result_ty, i, target, &ptr_ty_buf).?; indices[1] = llvm_u32.constInt(llvm_i, .False); - const field_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); var field_ptr_payload: Type.Payload.Pointer = .{ .data = .{ .pointee_type = self.air.typeOf(elem), @@ -8653,7 +8833,7 @@ pub const FuncGen = struct { llvm_usize.constNull(), llvm_usize.constInt(@intCast(c_uint, i), .False), }; - const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); const llvm_elem = try self.resolveInst(elem); self.store(elem_ptr, elem_ptr_ty, llvm_elem, .NotAtomic); } @@ -8662,7 +8842,7 @@ pub const FuncGen = struct { llvm_usize.constNull(), llvm_usize.constInt(@intCast(c_uint, array_info.len), .False), }; - const elem_ptr = self.builder.buildInBoundsGEP(alloca_inst, &indices, indices.len, ""); + const elem_ptr = self.builder.buildInBoundsGEP(llvm_result_ty, alloca_inst, &indices, indices.len, ""); const llvm_elem = try self.dg.lowerValue(.{ .ty = array_info.elem_type, .val = sent_val, @@ -8775,7 +8955,7 @@ pub const FuncGen = struct { index_type.constNull(), }; const len: c_uint = if (field_size == layout.payload_size) 2 else 3; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, ""); self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); return result_ptr; } @@ -8787,7 +8967,7 @@ pub const FuncGen = struct { index_type.constNull(), }; const len: c_uint = if (field_size == layout.payload_size) 2 else 3; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, len, ""); self.store(field_ptr, field_ptr_ty, llvm_payload, .NotAtomic); } { @@ -8795,7 +8975,7 @@ pub const FuncGen = struct { index_type.constNull(), index_type.constInt(@boolToInt(layout.tag_align < layout.payload_align), .False), }; - const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, ""); + const field_ptr = self.builder.buildInBoundsGEP(llvm_union_ty, casted_ptr, &indices, indices.len, ""); const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); const llvm_tag = tag_llvm_ty.constInt(tag_int, .False); const store_inst = self.builder.buildStore(llvm_tag, field_ptr); @@ -8842,7 +9022,7 @@ pub const FuncGen = struct { const llvm_ptr_u8 = llvm_u8.pointerType(0); const llvm_u32 = self.context.intType(32); - const llvm_fn_name = "llvm.prefetch.p0i8"; + const llvm_fn_name = "llvm.prefetch.p0"; const fn_val = self.dg.object.llvm_module.getNamedFunction(llvm_fn_name) orelse blk: { // declare void @llvm.prefetch(i8*, i32, i32, i32) const llvm_void = self.context.voidType(); @@ -8862,7 +9042,7 @@ pub const FuncGen = struct { llvm_u32.constInt(prefetch.locality, .False), llvm_u32.constInt(@enumToInt(prefetch.cache), .False), }; - _ = self.builder.buildCall(fn_val, ¶ms, params.len, .C, .Auto, ""); + _ = self.builder.buildCall(fn_val.globalGetValueType(), fn_val, ¶ms, params.len, .C, .Auto, ""); return null; } @@ -8942,7 +9122,7 @@ pub const FuncGen = struct { }; var args: [1]*const llvm.Value = .{arg}; - const result = self.builder.buildCall(llvm_fn, &args, args.len, .C, .Auto, ""); + const result = self.builder.buildCall(llvm_fn.globalGetValueType(), llvm_fn, &args, args.len, .C, .Auto, ""); const final_cast_llvm_ty = final_cast orelse return result; return self.builder.buildBitCast(result, final_cast_llvm_ty, ""); } @@ -8969,38 +9149,46 @@ pub const FuncGen = struct { } /// Assumes the optional is not pointer-like and payload has bits. - fn optIsNonNull(self: *FuncGen, opt_handle: *const llvm.Value, is_by_ref: bool) *const llvm.Value { + fn optIsNonNull( + self: *FuncGen, + opt_llvm_ty: *const llvm.Type, + opt_handle: *const llvm.Value, + is_by_ref: bool, + ) *const llvm.Value { + const non_null_llvm_ty = self.context.intType(8); const field = b: { if (is_by_ref) { - const field_ptr = self.builder.buildStructGEP(opt_handle, 1, ""); - break :b self.builder.buildLoad(field_ptr, ""); + const field_ptr = self.builder.buildStructGEP(opt_llvm_ty, opt_handle, 1, ""); + break :b self.builder.buildLoad(non_null_llvm_ty, field_ptr, ""); } break :b self.builder.buildExtractValue(opt_handle, 1, ""); }; comptime assert(optional_layout_version == 3); - return self.builder.buildICmp(.NE, field, self.context.intType(8).constInt(0, .False), ""); + return self.builder.buildICmp(.NE, field, non_null_llvm_ty.constInt(0, .False), ""); } /// Assumes the optional is not pointer-like and payload has bits. fn optPayloadHandle( fg: *FuncGen, + opt_llvm_ty: *const llvm.Type, opt_handle: *const llvm.Value, opt_ty: Type, - ) *const llvm.Value { + ) !*const llvm.Value { var buf: Type.Payload.ElemType = undefined; const payload_ty = opt_ty.optionalChild(&buf); if (isByRef(opt_ty)) { // We have a pointer and we need to return a pointer to the first field. - const payload_ptr = fg.builder.buildStructGEP(opt_handle, 0, ""); + const payload_ptr = fg.builder.buildStructGEP(opt_llvm_ty, opt_handle, 0, ""); if (isByRef(payload_ty)) { return payload_ptr; } const target = fg.dg.module.getTarget(); const payload_alignment = payload_ty.abiAlignment(target); - const load_inst = fg.builder.buildLoad(payload_ptr, ""); + const payload_llvm_ty = try fg.dg.lowerType(payload_ty); + const load_inst = fg.builder.buildLoad(payload_llvm_ty, payload_ptr, ""); load_inst.setAlignment(payload_alignment); return load_inst; } @@ -9025,12 +9213,12 @@ pub const FuncGen = struct { alloca_inst.setAlignment(payload_alignment); { - const field_ptr = self.builder.buildStructGEP(alloca_inst, 0, ""); + const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 0, ""); const store_inst = self.builder.buildStore(payload, field_ptr); store_inst.setAlignment(payload_alignment); } { - const field_ptr = self.builder.buildStructGEP(alloca_inst, 1, ""); + const field_ptr = self.builder.buildStructGEP(optional_llvm_ty, alloca_inst, 1, ""); const store_inst = self.builder.buildStore(non_null_field, field_ptr); store_inst.setAlignment(1); } @@ -9076,18 +9264,20 @@ pub const FuncGen = struct { if (byte_offset == 0) { return self.builder.buildBitCast(struct_ptr, result_llvm_ty, ""); } - const llvm_bytes_ptr_ty = self.context.intType(8).pointerType(0); - const ptr_as_bytes = self.builder.buildBitCast(struct_ptr, llvm_bytes_ptr_ty, ""); + const byte_llvm_ty = self.context.intType(8); + const ptr_as_bytes = self.builder.buildBitCast(struct_ptr, byte_llvm_ty.pointerType(0), ""); const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_index = llvm_usize.constInt(byte_offset, .False); const indices: [1]*const llvm.Value = .{llvm_index}; - const new_ptr = self.builder.buildInBoundsGEP(ptr_as_bytes, &indices, indices.len, ""); + const new_ptr = self.builder.buildInBoundsGEP(byte_llvm_ty, ptr_as_bytes, &indices, indices.len, ""); return self.builder.buildBitCast(new_ptr, result_llvm_ty, ""); }, else => { + const struct_llvm_ty = try self.dg.lowerPtrElemTy(struct_ty); + var ty_buf: Type.Payload.Pointer = undefined; if (llvmFieldIndex(struct_ty, field_index, target, &ty_buf)) |llvm_field_index| { - return self.builder.buildStructGEP(struct_ptr, llvm_field_index, ""); + return self.builder.buildStructGEP(struct_llvm_ty, struct_ptr, llvm_field_index, ""); } else { // If we found no index then this means this is a zero sized field at the // end of the struct. Treat our struct pointer as an array of two and get @@ -9096,7 +9286,7 @@ pub const FuncGen = struct { const llvm_usize = try self.dg.lowerType(Type.usize); const llvm_index = llvm_usize.constInt(1, .False); const indices: [1]*const llvm.Value = .{llvm_index}; - return self.builder.buildInBoundsGEP(struct_ptr, &indices, indices.len, ""); + return self.builder.buildInBoundsGEP(struct_llvm_ty, struct_ptr, &indices, indices.len, ""); } }, }, @@ -9111,27 +9301,18 @@ pub const FuncGen = struct { union_ptr: *const llvm.Value, union_ty: Type, ) !?*const llvm.Value { - const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); const target = self.dg.module.getTarget(); const layout = union_ty.unionGetLayout(target); + const result_llvm_ty = try self.dg.lowerType(self.air.typeOfIndex(inst)); if (layout.payload_size == 0) { return self.builder.buildBitCast(union_ptr, result_llvm_ty, ""); } const payload_index = @boolToInt(layout.tag_align >= layout.payload_align); - const union_field_ptr = self.builder.buildStructGEP(union_ptr, payload_index, ""); + const union_llvm_ty = try self.dg.lowerType(union_ty); + const union_field_ptr = self.builder.buildStructGEP(union_llvm_ty, union_ptr, payload_index, ""); return self.builder.buildBitCast(union_field_ptr, result_llvm_ty, ""); } - fn sliceElemPtr( - self: *FuncGen, - slice: *const llvm.Value, - index: *const llvm.Value, - ) *const llvm.Value { - const base_ptr = self.builder.buildExtractValue(slice, 0, ""); - const indices: [1]*const llvm.Value = .{index}; - return self.builder.buildInBoundsGEP(base_ptr, &indices, indices.len, ""); - } - fn getIntrinsic(self: *FuncGen, name: []const u8, types: []const *const llvm.Type) *const llvm.Value { const id = llvm.lookupIntrinsicID(name.ptr, name.len); assert(id != 0); @@ -9146,11 +9327,11 @@ pub const FuncGen = struct { if (!info.pointee_type.hasRuntimeBitsIgnoreComptime()) return null; const target = self.dg.module.getTarget(); - const ptr_alignment = ptr_ty.ptrAlignment(target); + const ptr_alignment = info.alignment(target); const ptr_volatile = llvm.Bool.fromBool(ptr_ty.isVolatilePtr()); if (info.host_size == 0) { + const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); if (isByRef(info.pointee_type)) { - const elem_llvm_ty = try self.dg.lowerType(info.pointee_type); const result_align = info.pointee_type.abiAlignment(target); const max_align = @maximum(result_align, ptr_alignment); const result_ptr = self.buildAlloca(elem_llvm_ty); @@ -9168,15 +9349,15 @@ pub const FuncGen = struct { ); return result_ptr; } - const llvm_inst = self.builder.buildLoad(ptr, ""); + const llvm_inst = self.builder.buildLoad(elem_llvm_ty, ptr, ""); llvm_inst.setAlignment(ptr_alignment); llvm_inst.setVolatile(ptr_volatile); return llvm_inst; } - const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); - const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); - const containing_int = self.builder.buildLoad(int_ptr, ""); + const int_elem_ty = self.context.intType(info.host_size * 8); + const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), ""); + const containing_int = self.builder.buildLoad(int_elem_ty, int_ptr, ""); containing_int.setAlignment(ptr_alignment); containing_int.setVolatile(ptr_volatile); @@ -9229,9 +9410,9 @@ pub const FuncGen = struct { const ptr_alignment = ptr_ty.ptrAlignment(target); const ptr_volatile = llvm.Bool.fromBool(info.@"volatile"); if (info.host_size != 0) { - const int_ptr_ty = self.context.intType(info.host_size * 8).pointerType(0); - const int_ptr = self.builder.buildBitCast(ptr, int_ptr_ty, ""); - const containing_int = self.builder.buildLoad(int_ptr, ""); + const int_elem_ty = self.context.intType(info.host_size * 8); + const int_ptr = self.builder.buildBitCast(ptr, int_elem_ty.pointerType(0), ""); + const containing_int = self.builder.buildLoad(int_elem_ty, int_ptr, ""); assert(ordering == .NotAtomic); containing_int.setAlignment(ptr_alignment); containing_int.setVolatile(ptr_volatile); @@ -9310,8 +9491,9 @@ pub const FuncGen = struct { switch (target.cpu.arch) { .x86_64 => { + const array_llvm_ty = usize_llvm_ty.arrayType(6); const array_ptr = fg.valgrind_client_request_array orelse a: { - const array_ptr = fg.buildAlloca(usize_llvm_ty.arrayType(6)); + const array_ptr = fg.buildAlloca(array_llvm_ty); array_ptr.setAlignment(usize_alignment); fg.valgrind_client_request_array = array_ptr; break :a array_ptr; @@ -9322,7 +9504,7 @@ pub const FuncGen = struct { const indexes = [_]*const llvm.Value{ zero, usize_llvm_ty.constInt(@intCast(c_uint, i), .False), }; - const elem_ptr = fg.builder.buildInBoundsGEP(array_ptr, &indexes, indexes.len, ""); + const elem_ptr = fg.builder.buildInBoundsGEP(array_llvm_ty, array_ptr, &indexes, indexes.len, ""); const store_inst = fg.builder.buildStore(elem, elem_ptr); store_inst.setAlignment(usize_alignment); } @@ -9352,6 +9534,7 @@ pub const FuncGen = struct { ); const call = fg.builder.buildCall( + fn_llvm_ty, asm_fn, &args, args.len, @@ -9538,6 +9721,9 @@ fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void { .kalimba, .renderscript32, .renderscript64, + .dxil, + .loongarch32, + .loongarch64, => {}, .spu_2 => unreachable, // LLVM does not support this backend diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 38f794cfda..81e722bed8 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -31,6 +31,9 @@ pub const Context = opaque { pub const createStringAttribute = LLVMCreateStringAttribute; extern fn LLVMCreateStringAttribute(*const Context, Key: [*]const u8, Key_Len: c_uint, Value: [*]const u8, Value_Len: c_uint) *const Attribute; + pub const pointerType = LLVMPointerTypeInContext; + extern fn LLVMPointerTypeInContext(C: *const Context, AddressSpace: c_uint) *const Type; + pub const intType = LLVMIntTypeInContext; extern fn LLVMIntTypeInContext(C: *const Context, NumBits: c_uint) *const Type; @@ -141,13 +144,6 @@ pub const Value = opaque { pub const setAliasee = LLVMAliasSetAliasee; extern fn LLVMAliasSetAliasee(Alias: *const Value, Aliasee: *const Value) void; - pub const constInBoundsGEP = LLVMConstInBoundsGEP; - extern fn LLVMConstInBoundsGEP( - ConstantVal: *const Value, - ConstantIndices: [*]const *const Value, - NumIndices: c_uint, - ) *const Value; - pub const constBitCast = LLVMConstBitCast; extern fn LLVMConstBitCast(ConstantVal: *const Value, ToType: *const Type) *const Value; @@ -252,6 +248,9 @@ pub const Value = opaque { pub const addFunctionAttr = ZigLLVMAddFunctionAttr; extern fn ZigLLVMAddFunctionAttr(Fn: *const Value, attr_name: [*:0]const u8, attr_value: [*:0]const u8) void; + pub const getGEPResultElementType = ZigLLVMGetGEPResultElementType; + extern fn ZigLLVMGetGEPResultElementType(GEP: *const Value) *const Type; + pub const addByValAttr = ZigLLVMAddByValAttr; extern fn ZigLLVMAddByValAttr(Fn: *const Value, ArgNo: c_uint, type: *const Type) void; }; @@ -319,6 +318,14 @@ pub const Type = opaque { pub const isSized = LLVMTypeIsSized; extern fn LLVMTypeIsSized(Ty: *const Type) Bool; + + pub const constInBoundsGEP = LLVMConstInBoundsGEP2; + extern fn LLVMConstInBoundsGEP2( + Ty: *const Type, + ConstantVal: *const Value, + ConstantIndices: [*]const *const Value, + NumIndices: c_uint, + ) *const Value; }; pub const Module = opaque { @@ -515,6 +522,7 @@ pub const Builder = opaque { pub const buildCall = ZigLLVMBuildCall; extern fn ZigLLVMBuildCall( *const Builder, + *const Type, Fn: *const Value, Args: [*]const *const Value, NumArgs: c_uint, @@ -538,8 +546,8 @@ pub const Builder = opaque { pub const buildStore = LLVMBuildStore; extern fn LLVMBuildStore(*const Builder, Val: *const Value, Ptr: *const Value) *const Value; - pub const buildLoad = LLVMBuildLoad; - extern fn LLVMBuildLoad(*const Builder, PointerVal: *const Value, Name: [*:0]const u8) *const Value; + pub const buildLoad = LLVMBuildLoad2; + extern fn LLVMBuildLoad2(*const Builder, Ty: *const Type, PointerVal: *const Value, Name: [*:0]const u8) *const Value; pub const buildNeg = LLVMBuildNeg; extern fn LLVMBuildNeg(*const Builder, V: *const Value, Name: [*:0]const u8) *const Value; @@ -664,16 +672,7 @@ pub const Builder = opaque { pub const buildBitCast = LLVMBuildBitCast; extern fn LLVMBuildBitCast(*const Builder, Val: *const Value, DestTy: *const Type, Name: [*:0]const u8) *const Value; - pub const buildInBoundsGEP = LLVMBuildInBoundsGEP; - extern fn LLVMBuildInBoundsGEP( - B: *const Builder, - Pointer: *const Value, - Indices: [*]const *const Value, - NumIndices: c_uint, - Name: [*:0]const u8, - ) *const Value; - - pub const buildInBoundsGEP2 = LLVMBuildInBoundsGEP2; + pub const buildInBoundsGEP = LLVMBuildInBoundsGEP2; extern fn LLVMBuildInBoundsGEP2( B: *const Builder, Ty: *const Type, @@ -750,9 +749,10 @@ pub const Builder = opaque { Name: [*:0]const u8, ) *const Value; - pub const buildStructGEP = LLVMBuildStructGEP; - extern fn LLVMBuildStructGEP( + pub const buildStructGEP = LLVMBuildStructGEP2; + extern fn LLVMBuildStructGEP2( B: *const Builder, + Ty: *const Type, Pointer: *const Value, Idx: c_uint, Name: [*:0]const u8, @@ -1221,9 +1221,11 @@ pub const LinkWasm = ZigLLDLinkWasm; pub const ObjectFormatType = enum(c_int) { Unknown, COFF, + DXContainer, ELF, GOFF, MachO, + SPIRV, Wasm, XCOFF, }; @@ -1263,9 +1265,11 @@ pub const OSType = enum(c_int) { NVCL, AMDHSA, PS4, + PS5, ELFIAMCU, TvOS, WatchOS, + DriverKit, Mesa3D, Contiki, AMDPAL, @@ -1273,6 +1277,7 @@ pub const OSType = enum(c_int) { Hurd, WASI, Emscripten, + ShaderModel, }; pub const ArchType = enum(c_int) { @@ -1287,7 +1292,10 @@ pub const ArchType = enum(c_int) { bpfel, bpfeb, csky, + dxil, hexagon, + loongarch32, + loongarch64, m68k, mips, mipsel, @@ -1323,6 +1331,8 @@ pub const ArchType = enum(c_int) { hsail64, spir, spir64, + spirv32, + spirv64, kalimba, shave, lanai, @@ -1724,8 +1734,8 @@ pub const DIBuilder = opaque { dib: *DIBuilder, tag: c_uint, name: [*:0]const u8, - scope: *DIScope, - file: *DIFile, + scope: ?*DIScope, + file: ?*DIFile, line: c_uint, ) *DIType; diff --git a/src/libcxx.zig b/src/libcxx.zig index b19834f8c3..b0261aaed6 100644 --- a/src/libcxx.zig +++ b/src/libcxx.zig @@ -7,6 +7,13 @@ const Compilation = @import("Compilation.zig"); const build_options = @import("build_options"); const trace = @import("tracy.zig").trace; +pub const AbiVersion = enum(u2) { + @"1" = 1, + @"2" = 2, + + pub const default: AbiVersion = .@"1"; +}; + const libcxxabi_files = [_][]const u8{ "src/abort_message.cpp", "src/cxa_aux_runtime.cpp", @@ -54,6 +61,7 @@ const libcxx_files = [_][]const u8{ "src/ios.cpp", "src/ios.instantiations.cpp", "src/iostream.cpp", + "src/legacy_debug_handler.cpp", "src/legacy_pointer_safety.cpp", "src/locale.cpp", "src/memory.cpp", @@ -85,6 +93,7 @@ const libcxx_files = [_][]const u8{ "src/valarray.cpp", "src/variant.cpp", "src/vector.cpp", + "src/verbose_abort.cpp", }; pub fn buildLibCXX(comp: *Compilation) !void { @@ -118,6 +127,12 @@ pub fn buildLibCXX(comp: *Compilation) !void { const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" }); const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" }); const cxx_src_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "src" }); + const abi_version_arg = try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_VERSION={d}", .{ + @enumToInt(comp.libcxx_abi_version), + }); + const abi_namespace_arg = try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{ + @enumToInt(comp.libcxx_abi_version), + }); var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxx_files.len); for (libcxx_files) |cxx_src| { @@ -150,6 +165,10 @@ pub fn buildLibCXX(comp: *Compilation) !void { try cflags.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS"); try cflags.append("-D_LIBCPP_DISABLE_NEW_DELETE_DEFINITIONS"); try cflags.append("-D_LIBCPP_HAS_NO_VENDOR_AVAILABILITY_ANNOTATIONS"); + + try cflags.append(abi_version_arg); + try cflags.append(abi_namespace_arg); + try cflags.append("-fvisibility=hidden"); try cflags.append("-fvisibility-inlines-hidden"); @@ -275,6 +294,12 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { const cxxabi_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", "include" }); const cxx_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "include" }); const cxx_src_include_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxx", "src" }); + const abi_version_arg = try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_VERSION={d}", .{ + @enumToInt(comp.libcxx_abi_version), + }); + const abi_namespace_arg = try std.fmt.allocPrint(arena, "-D_LIBCPP_ABI_NAMESPACE=__{d}", .{ + @enumToInt(comp.libcxx_abi_version), + }); var c_source_files = try std.ArrayList(Compilation.CSourceFile).initCapacity(arena, libcxxabi_files.len); for (libcxxabi_files) |cxxabi_src| { @@ -304,6 +329,10 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { try cflags.append("-D_LIBCXXABI_BUILDING_LIBRARY"); try cflags.append("-D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS"); try cflags.append("-D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS"); + + try cflags.append(abi_version_arg); + try cflags.append(abi_namespace_arg); + try cflags.append("-fvisibility=hidden"); try cflags.append("-fvisibility-inlines-hidden"); @@ -326,7 +355,7 @@ pub fn buildLibCXXABI(comp: *Compilation) !void { try cflags.append("-nostdinc++"); try cflags.append("-fstrict-aliasing"); try cflags.append("-funwind-tables"); - try cflags.append("-std=c++11"); + try cflags.append("-std=c++20"); c_source_files.appendAssumeCapacity(.{ .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libcxxabi", cxxabi_src }), diff --git a/src/libunwind.zig b/src/libunwind.zig index fb4f93af02..11666eec3c 100644 --- a/src/libunwind.zig +++ b/src/libunwind.zig @@ -33,24 +33,13 @@ pub fn buildStaticLib(comp: *Compilation) !void { .directory = null, // Put it in the cache directory. .basename = basename, }; - const unwind_src_list = [_][]const u8{ - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "libunwind.cpp", - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-EHABI.cpp", - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-seh.cpp", - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c", - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c", - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c", - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S", - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S", - "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "gcc_personality_v0.c", - }; var c_source_files: [unwind_src_list.len]Compilation.CSourceFile = undefined; for (unwind_src_list) |unwind_src, i| { var cflags = std.ArrayList([]const u8).init(arena); switch (Compilation.classifyFileExt(unwind_src)) { .c => { - try cflags.append("-std=c99"); + try cflags.append("-std=c11"); }, .cpp => { try cflags.appendSlice(&[_][]const u8{ @@ -120,7 +109,8 @@ pub fn buildStaticLib(comp: *Compilation) !void { .want_tsan = false, .want_pic = comp.bin_file.options.pic, .want_pie = comp.bin_file.options.pie, - .want_lto = comp.bin_file.options.lto, + // Disable LTO to avoid https://github.com/llvm/llvm-project/issues/56825 + .want_lto = false, .function_sections = comp.bin_file.options.function_sections, .emit_h = null, .strip = comp.compilerRtStrip(), @@ -151,3 +141,16 @@ pub fn buildStaticLib(comp: *Compilation) !void { .lock = sub_compilation.bin_file.toOwnedLock(), }; } + +const unwind_src_list = [_][]const u8{ + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "libunwind.cpp", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-EHABI.cpp", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-seh.cpp", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1.c", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindLevel1-gcc-ext.c", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind-sjlj.c", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersRestore.S", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "UnwindRegistersSave.S", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "Unwind_AIXExtras.cpp", + "libunwind" ++ path.sep_str ++ "src" ++ path.sep_str ++ "gcc_personality_v0.c", +}; diff --git a/src/link.zig b/src/link.zig index 5d20e98a32..fe7891a439 100644 --- a/src/link.zig +++ b/src/link.zig @@ -301,6 +301,7 @@ pub const File = struct { .nvptx => &(try NvPtx.createEmpty(allocator, options)).base, .hex => return error.HexObjectFormatUnimplemented, .raw => return error.RawObjectFormatUnimplemented, + .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented, }; } const emit = options.emit.?; @@ -320,6 +321,7 @@ pub const File = struct { .nvptx => &(try NvPtx.createEmpty(allocator, options)).base, .hex => return error.HexObjectFormatUnimplemented, .raw => return error.RawObjectFormatUnimplemented, + .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented, }; } // Open a temporary object file, not the final output file because we @@ -341,6 +343,7 @@ pub const File = struct { .nvptx => &(try NvPtx.openPath(allocator, sub_path, options)).base, .hex => return error.HexObjectFormatUnimplemented, .raw => return error.RawObjectFormatUnimplemented, + .dxcontainer => return error.DirectXContainerObjectFormatUnimplemented, }; if (use_lld) { diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 1d49198937..a70473fe07 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1427,7 +1427,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node) !v try argv.append("-r"); } - try argv.append("-error-limit=0"); + try argv.append("--error-limit=0"); if (self.base.options.sysroot) |sysroot| { try argv.append(try std.fmt.allocPrint(arena, "--sysroot={s}", .{sysroot})); diff --git a/src/link/Wasm.zig b/src/link/Wasm.zig index 6dd3bc56ff..0e6fe5dcc2 100644 --- a/src/link/Wasm.zig +++ b/src/link/Wasm.zig @@ -2927,7 +2927,7 @@ fn linkWithLLD(wasm: *Wasm, comp: *Compilation, prog_node: *std.Progress.Node) ! // This is necessary because LLD does not behave properly as a library - // it calls exit() and does not reset all global data between invocations. try argv.appendSlice(&[_][]const u8{ comp.self_exe_path.?, "wasm-ld" }); - try argv.append("-error-limit=0"); + try argv.append("--error-limit=0"); if (wasm.base.options.lto) { switch (wasm.base.options.optimize_mode) { diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 9f9a6151b8..5f216fe388 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -1595,6 +1595,7 @@ struct ZigTypeFnFrame { struct ZigTypeAnyFrame { ZigType *result_type; // null if `anyframe` instead of `anyframe->T` + LLVMTypeRef struct_llvm_ty; }; struct ZigType { @@ -2044,6 +2045,7 @@ struct CodeGen { LLVMValueRef wasm_memory_grow; LLVMValueRef prefetch; LLVMTypeRef anyframe_fn_type; + LLVMTypeRef any_frame_header_llvm_ty; // reminder: hash tables must be initialized before use HashMap<Buf *, ZigType *, buf_hash, buf_eql_buf> import_table; diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index 90173f384e..f0cad841be 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -9753,6 +9753,7 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re Buf *name = buf_sprintf("(%s header)", buf_ptr(&any_frame_type->name)); LLVMTypeRef frame_header_type = LLVMStructCreateNamed(LLVMGetGlobalContext(), buf_ptr(name)); any_frame_type->llvm_type = LLVMPointerType(frame_header_type, 0); + any_frame_type->data.any_frame.struct_llvm_ty = frame_header_type; unsigned dwarf_kind = ZigLLVMTag_DW_structure_type(); ZigLLVMDIFile *di_file = nullptr; @@ -9775,7 +9776,8 @@ static void resolve_llvm_types_any_frame(CodeGen *g, ZigType *any_frame_type, Re const unsigned fn_addrspace = ZigLLVMDataLayoutGetProgramAddressSpace(g->target_data_ref); LLVMTypeRef ptr_fn_llvm_type = LLVMPointerType(fn_type, fn_addrspace); if (result_type == nullptr) { - g->anyframe_fn_type = ptr_fn_llvm_type; + g->any_frame_header_llvm_ty = frame_header_type; + g->anyframe_fn_type = fn_type; } ZigList<LLVMTypeRef> field_types = {}; diff --git a/src/stage1/codegen.cpp b/src/stage1/codegen.cpp index cc6c0f22a7..55aa73a3b7 100644 --- a/src/stage1/codegen.cpp +++ b/src/stage1/codegen.cpp @@ -88,8 +88,8 @@ static bool value_is_all_undef(CodeGen *g, ZigValue *const_val); static void gen_undef_init(CodeGen *g, ZigType *ptr_type, ZigType *value_type, LLVMValueRef ptr); static LLVMValueRef build_alloca(CodeGen *g, ZigType *type_entry, const char *name, uint32_t alignment); static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_instr, - LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type, - LLVMValueRef result_loc, bool non_async); + LLVMTypeRef target_frame_struct_llvm_ty, LLVMValueRef target_frame_ptr, + ZigType *result_type, ZigType *ptr_result_type, LLVMValueRef result_loc, bool non_async); static void addLLVMAttr(LLVMValueRef val, LLVMAttributeIndex attr_index, const char *attr_name) { unsigned kind_id = LLVMGetEnumAttributeKindForName(attr_name, strlen(attr_name)); @@ -223,7 +223,7 @@ static ZigLLVM_CallingConv get_llvm_cc(CodeGen *g, CallingConvention cc) { static void add_uwtable_attr(CodeGen *g, LLVMValueRef fn_val) { if (g->unwind_tables) { - addLLVMFnAttr(fn_val, "uwtable"); + addLLVMFnAttrStr(fn_val, "uwtable", "sync"); } } @@ -911,14 +911,12 @@ static LLVMValueRef gen_store(CodeGen *g, LLVMValueRef value, LLVMValueRef ptr, return gen_store_untyped(g, value, ptr, alignment, ptr_type->data.pointer.is_volatile); } -static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alignment, bool is_volatile, - const char *name) +static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMTypeRef elem_llvm_ty, LLVMValueRef ptr, + uint32_t alignment, bool is_volatile, const char *name) { - LLVMValueRef result = LLVMBuildLoad(g->builder, ptr, name); + LLVMValueRef result = LLVMBuildLoad2(g->builder, elem_llvm_ty, ptr, name); if (is_volatile) LLVMSetVolatile(result, true); - if (alignment == 0) { - LLVMSetAlignment(result, LLVMABIAlignmentOfType(g->target_data_ref, LLVMGetElementType(LLVMTypeOf(ptr)))); - } else { + if (alignment != 0) { LLVMSetAlignment(result, alignment); } return result; @@ -927,7 +925,9 @@ static LLVMValueRef gen_load_untyped(CodeGen *g, LLVMValueRef ptr, uint32_t alig static LLVMValueRef gen_load(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, const char *name) { assert(ptr_type->id == ZigTypeIdPointer); uint32_t alignment = get_ptr_align(g, ptr_type); - return gen_load_untyped(g, ptr, alignment, ptr_type->data.pointer.is_volatile, name); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_type->data.pointer.child_type); + bool is_volatile = ptr_type->data.pointer.is_volatile; + return gen_load_untyped(g, elem_llvm_ty, ptr, alignment, is_volatile, name); } static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, ZigType *type, ZigType *ptr_type) { @@ -1090,7 +1090,7 @@ static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace msg_arg, stack_trace_arg, }; - ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, ""); + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 2, llvm_cc, ZigLLVM_CallAttrAuto, ""); if (!stack_trace_is_llvm_alloca) { // The stack trace argument is not in the stack of the caller, so // we'd like to set tail call here, but because slices (the type of msg_arg) are @@ -1161,7 +1161,7 @@ static LLVMValueRef gen_prefetch(CodeGen *g) { LLVMInt32Type(), }; LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), param_types, 4, false); - g->prefetch = LLVMAddFunction(g->module, "llvm.prefetch.p0i8", fn_type); + g->prefetch = LLVMAddFunction(g->module, "llvm.prefetch.p0", fn_type); assert(LLVMGetIntrinsicID(g->prefetch)); return g->prefetch; @@ -1265,26 +1265,37 @@ static LLVMValueRef get_add_error_return_trace_addr_fn(CodeGen *g) { LLVMValueRef address_value = LLVMGetParam(fn_val, 1); size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; - LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)index_field_index, ""); + LLVMValueRef index_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), + err_ret_trace_ptr, (unsigned)index_field_index, ""); size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; - LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)addresses_field_index, ""); + LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), + err_ret_trace_ptr, (unsigned)addresses_field_index, ""); ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(addresses_field_ptr), + addresses_field_ptr, (unsigned)ptr_field_index, ""); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); - - LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, ""); - LLVMValueRef index_val = gen_load_untyped(g, index_field_ptr, 0, false, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(addresses_field_ptr), + addresses_field_ptr, (unsigned)len_field_index, ""); + + LLVMValueRef len_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), + len_field_ptr, 0, false, ""); + LLVMValueRef index_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(index_field_ptr), + index_field_ptr, 0, false, ""); LLVMValueRef len_val_minus_one = LLVMBuildSub(g->builder, len_value, LLVMConstInt(usize_type_ref, 1, false), ""); LLVMValueRef masked_val = LLVMBuildAnd(g->builder, index_val, len_val_minus_one, ""); LLVMValueRef address_indices[] = { masked_val, }; - LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); - LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, ""); + LLVMValueRef ptr_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), + ptr_field_ptr, 0, false, ""); + LLVMValueRef address_slot = LLVMBuildInBoundsGEP2(g->builder, usize_type_ref, ptr_value, address_indices, 1, ""); gen_store_untyped(g, address_value, address_slot, 0, false); @@ -1340,7 +1351,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(get_llvm_type(g, g->builtin_types.entry_i32)); - LLVMValueRef return_address_ptr = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); + LLVMValueRef return_address_ptr = LLVMBuildCall2(g->builder, + LLVMGlobalGetValueType(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, return_address_ptr, usize_type_ref, ""); LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return"); @@ -1355,7 +1367,8 @@ static LLVMValueRef get_return_err_fn(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, dest_non_null_block); LLVMValueRef args[] = { err_ret_trace_ptr, return_address }; - ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val), + add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); LLVMBuildRetVoid(g->builder); @@ -1446,25 +1459,32 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMConstNull(usize_ty->llvm_type), err_val, }; - LLVMValueRef err_name_val = LLVMBuildInBoundsGEP(g->builder, g->err_name_table, err_table_indices, 2, ""); + LLVMValueRef err_name_val = LLVMBuildInBoundsGEP2(g->builder, + LLVMGlobalGetValueType(g->err_name_table), + g->err_name_table, err_table_indices, 2, ""); - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_ptr_index, ""); - LLVMValueRef err_name_ptr = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(err_name_val), err_name_val, slice_ptr_index, ""); + LLVMValueRef err_name_ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), + ptr_field_ptr, 0, false, ""); - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, err_name_val, slice_len_index, ""); - LLVMValueRef err_name_len = gen_load_untyped(g, len_field_ptr, 0, false, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(err_name_val), err_name_val, slice_len_index, ""); + LLVMValueRef err_name_len = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), + len_field_ptr, 0, false, ""); LLVMValueRef msg_prefix_len = LLVMConstInt(usize_ty->llvm_type, strlen(unwrap_err_msg_text), false); // Points to the beginning of msg_buffer LLVMValueRef msg_buffer_ptr_indices[] = { LLVMConstNull(usize_ty->llvm_type), }; - LLVMValueRef msg_buffer_ptr = LLVMBuildInBoundsGEP(g->builder, msg_buffer, msg_buffer_ptr_indices, 1, ""); + LLVMValueRef msg_buffer_ptr = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(), msg_buffer, + msg_buffer_ptr_indices, 1, ""); // Points to the beginning of the constant prefix message LLVMValueRef msg_prefix_ptr_indices[] = { LLVMConstNull(usize_ty->llvm_type), }; - LLVMValueRef msg_prefix_ptr = LLVMConstInBoundsGEP(msg_prefix, msg_prefix_ptr_indices, 1); + LLVMValueRef msg_prefix_ptr = LLVMConstInBoundsGEP2(LLVMInt8Type(), msg_prefix, msg_prefix_ptr_indices, 1); // Build the message using the prefix... ZigLLVMBuildMemCpy(g->builder, msg_buffer_ptr, 1, msg_prefix_ptr, 1, msg_prefix_len, false); @@ -1472,16 +1492,18 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { LLVMValueRef msg_buffer_ptr_after_indices[] = { msg_prefix_len, }; - LLVMValueRef msg_buffer_ptr_after = LLVMBuildInBoundsGEP(g->builder, msg_buffer, msg_buffer_ptr_after_indices, 1, ""); + LLVMValueRef msg_buffer_ptr_after = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(), msg_buffer, msg_buffer_ptr_after_indices, 1, ""); ZigLLVMBuildMemCpy(g->builder, msg_buffer_ptr_after, 1, err_name_ptr, 1, err_name_len, false); // Set the slice pointer - LLVMValueRef msg_slice_ptr_field_ptr = LLVMBuildStructGEP(g->builder, msg_slice, slice_ptr_index, ""); + LLVMValueRef msg_slice_ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, str_type), msg_slice, slice_ptr_index, ""); gen_store_untyped(g, msg_buffer_ptr, msg_slice_ptr_field_ptr, 0, false); // Set the slice length LLVMValueRef slice_len = LLVMBuildNUWAdd(g->builder, msg_prefix_len, err_name_len, ""); - LLVMValueRef msg_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, msg_slice, slice_len_index, ""); + LLVMValueRef msg_slice_len_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, str_type), msg_slice, slice_len_index, ""); gen_store_untyped(g, slice_len, msg_slice_len_field_ptr, 0, false); // Call panic() @@ -1522,13 +1544,15 @@ static void gen_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val, Scope *sc err_ret_trace_val, err_val, }; - call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2, + call_instruction = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(safety_crash_err_fn), + safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } else { LLVMValueRef args[] = { err_val, }; - call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 1, + call_instruction = ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(safety_crash_err_fn), + safety_crash_err_fn, args, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } if (!is_llvm_alloca) { @@ -1573,7 +1597,7 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val, static void add_sentinel_check(CodeGen *g, LLVMValueRef sentinel_elem_ptr, ZigValue *sentinel) { LLVMValueRef expected_sentinel = gen_const_val(g, sentinel, ""); - LLVMValueRef actual_sentinel = gen_load_untyped(g, sentinel_elem_ptr, 0, false, ""); + LLVMValueRef actual_sentinel = gen_load_untyped(g, LLVMTypeOf(expected_sentinel), sentinel_elem_ptr, 0, false, ""); LLVMValueRef ok_bit; if (sentinel->type->id == ZigTypeIdFloat) { ok_bit = LLVMBuildFCmp(g->builder, LLVMRealOEQ, actual_sentinel, expected_sentinel, ""); @@ -1706,7 +1730,7 @@ static LLVMValueRef gen_soft_float_widen_or_shorten(CodeGen *g, ZigType *actual_ func_ref = LLVMAddFunction(g->module, fn_name, fn_type); } - result = LLVMBuildCall(g->builder, func_ref, &expr_val, 1, ""); + result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &expr_val, 1, ""); // On non-Arm platforms we need to bitcast __trunc<>fhf2 result back to f16 if (castTruncatedToF16) { @@ -1852,7 +1876,7 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, ZigType *operand_type, AddSubMul val1, val2, }; - LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); + LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); if (operand_type->id == ZigTypeIdVector) { @@ -1944,7 +1968,10 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) { LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.vector_index, false); - LLVMValueRef loaded_vector = gen_load(g, ptr, ptr_type, ""); + uint32_t vec_len = ptr_type->data.pointer.host_int_bytes; + LLVMTypeRef vec_llvm_ty = LLVMVectorType(get_llvm_type(g, ptr_type->data.pointer.child_type), vec_len); + LLVMValueRef loaded_vector = gen_load_untyped(g, vec_llvm_ty, ptr, + get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile, ""); LLVMValueRef new_vector = LLVMBuildInsertElement(g->builder, loaded_vector, value, index_val, ""); gen_store(g, new_vector, ptr, ptr_type); @@ -1961,7 +1988,8 @@ static void gen_assign_raw(CodeGen *g, LLVMValueRef ptr, ZigType *ptr_type, LLVMTypeRef int_ptr_ty = LLVMPointerType(LLVMIntType(host_int_bytes * 8), 0); LLVMValueRef int_ptr = LLVMBuildBitCast(g->builder, ptr, int_ptr_ty, ""); - LLVMValueRef containing_int = gen_load(g, int_ptr, ptr_type, ""); + LLVMValueRef containing_int = gen_load_untyped(g, LLVMIntType(host_int_bytes * 8), int_ptr, + get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile, ""); uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); assert(host_bit_count == host_int_bytes * 8); uint32_t size_in_bits = type_size_bits(g, child_type); @@ -2272,9 +2300,9 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ fn_walk->data.attrs.gen_i += 1; break; case FnWalkIdCall: { - LLVMTypeRef ptr_to_int_type_ref = LLVMPointerType(LLVMIntType((unsigned)ty_size * 8), 0); - LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, val, ptr_to_int_type_ref, ""); - LLVMValueRef loaded = LLVMBuildLoad(g->builder, bitcasted, ""); + LLVMTypeRef int_type_ref = LLVMIntType((unsigned)ty_size * 8); + LLVMValueRef bitcasted = LLVMBuildBitCast(g->builder, val, LLVMPointerType(int_type_ref, 0), ""); + LLVMValueRef loaded = LLVMBuildLoad2(g->builder, int_type_ref, bitcasted, ""); fn_walk->data.call.gen_param_values->append(loaded); break; } @@ -2344,16 +2372,16 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ case FnWalkIdCall: { LLVMValueRef abi_ptr_to_struct = LLVMBuildBitCast(g->builder, val, LLVMPointerType(abi_type, 0), ""); if (number_of_regs == 1) { - LLVMValueRef loaded = LLVMBuildLoad(g->builder, abi_ptr_to_struct, ""); + LLVMValueRef loaded = LLVMBuildLoad2(g->builder, abi_type, abi_ptr_to_struct, ""); fn_walk->data.call.gen_param_values->append(loaded); break; } for (uint32_t i = 0; i < number_of_regs; i += 1) { - LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, false); - LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, false); - LLVMValueRef indices[] = { zero, index }; - LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP(g->builder, abi_ptr_to_struct, indices, 2, ""); - LLVMValueRef loaded = LLVMBuildLoad(g->builder, adjusted_ptr_to_struct, ""); + LLVMValueRef adjusted_ptr_to_struct = LLVMBuildStructGEP2(g->builder, + abi_type, abi_ptr_to_struct, i, ""); + LLVMTypeRef field_llvm_ty = LLVMStructGetTypeAtIndex(abi_type, i); + LLVMValueRef loaded = LLVMBuildLoad2(g->builder, field_llvm_ty, + adjusted_ptr_to_struct, ""); fn_walk->data.call.gen_param_values->append(loaded); } break; @@ -2394,7 +2422,8 @@ static bool iter_function_params_c_abi(CodeGen *g, ZigType *fn_type, FnWalk *fn_ LLVMValueRef zero = LLVMConstInt(LLVMInt32Type(), 0, false); LLVMValueRef index = LLVMConstInt(LLVMInt32Type(), i, false); LLVMValueRef indices[] = { zero, index }; - LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP(g->builder, abi_ptr_to_struct, indices, 2, ""); + LLVMValueRef adjusted_ptr_to_struct = LLVMBuildInBoundsGEP2(g->builder, + abi_type, abi_ptr_to_struct, indices, 2, ""); LLVMBuildStore(g->builder, arg, adjusted_ptr_to_struct); } fn_walk->data.inits.gen_i += 1; @@ -2573,8 +2602,9 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(fn_val, "Return"); LLVMBasicBlockRef non_null_block = LLVMAppendBasicBlock(fn_val, "NonNull"); - LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frame_index"); - LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, g->builtin_types.entry_usize->llvm_type, "frames_left"); + LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; + LLVMValueRef frame_index_ptr = LLVMBuildAlloca(g->builder, usize_type_ref, "frame_index"); + LLVMValueRef frames_left_ptr = LLVMBuildAlloca(g->builder, usize_type_ref, "frames_left"); LLVMValueRef dest_stack_trace_ptr = LLVMGetParam(fn_val, 0); LLVMValueRef src_stack_trace_ptr = LLVMGetParam(fn_val, 1); @@ -2589,18 +2619,27 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, non_null_block); size_t src_index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; size_t src_addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; - LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr, + LLVMValueRef src_index_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), src_stack_trace_ptr, (unsigned)src_index_field_index, ""); - LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP(g->builder, src_stack_trace_ptr, + LLVMValueRef src_addresses_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), src_stack_trace_ptr, (unsigned)src_addresses_field_index, ""); ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; - LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)ptr_field_index, ""); + LLVMValueRef src_ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(src_addresses_field_ptr), + src_addresses_field_ptr, (unsigned)ptr_field_index, ""); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; - LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP(g->builder, src_addresses_field_ptr, (unsigned)len_field_index, ""); - LLVMValueRef src_index_val = LLVMBuildLoad(g->builder, src_index_field_ptr, ""); - LLVMValueRef src_ptr_val = LLVMBuildLoad(g->builder, src_ptr_field_ptr, ""); - LLVMValueRef src_len_val = LLVMBuildLoad(g->builder, src_len_field_ptr, ""); + LLVMValueRef src_len_field_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(src_addresses_field_ptr), + src_addresses_field_ptr, (unsigned)len_field_index, ""); + LLVMValueRef src_index_val = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(src_index_field_ptr), src_index_field_ptr, ""); + LLVMValueRef src_ptr_val = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(src_ptr_field_ptr), src_ptr_field_ptr, ""); + LLVMValueRef src_len_val = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(src_len_field_ptr), src_len_field_ptr, ""); LLVMValueRef no_wrap_bit = LLVMBuildICmp(g->builder, LLVMIntULT, src_index_val, src_len_val, ""); LLVMBasicBlockRef no_wrap_block = LLVMAppendBasicBlock(fn_val, "NoWrap"); LLVMBasicBlockRef yes_wrap_block = LLVMAppendBasicBlock(fn_val, "YesWrap"); @@ -2608,14 +2647,14 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBuildCondBr(g->builder, no_wrap_bit, no_wrap_block, yes_wrap_block); LLVMPositionBuilderAtEnd(g->builder, no_wrap_block); - LLVMValueRef usize_zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type); + LLVMValueRef usize_zero = LLVMConstNull(usize_type_ref); LLVMBuildStore(g->builder, usize_zero, frame_index_ptr); LLVMBuildStore(g->builder, src_index_val, frames_left_ptr); LLVMValueRef frames_left_eq_zero_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, src_index_val, usize_zero, ""); LLVMBuildCondBr(g->builder, frames_left_eq_zero_bit, return_block, loop_block); LLVMPositionBuilderAtEnd(g->builder, yes_wrap_block); - LLVMValueRef usize_one = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 1, false); + LLVMValueRef usize_one = LLVMConstInt(usize_type_ref, 1, false); LLVMValueRef plus_one = LLVMBuildNUWAdd(g->builder, src_index_val, usize_one, ""); LLVMValueRef mod_len = LLVMBuildURem(g->builder, plus_one, src_len_val, ""); LLVMBuildStore(g->builder, mod_len, frame_index_ptr); @@ -2623,12 +2662,15 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMBuildBr(g->builder, loop_block); LLVMPositionBuilderAtEnd(g->builder, loop_block); - LLVMValueRef ptr_index = LLVMBuildLoad(g->builder, frame_index_ptr, ""); - LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr_val, &ptr_index, 1, ""); - LLVMValueRef this_addr_val = LLVMBuildLoad(g->builder, addr_ptr, ""); + LLVMValueRef ptr_index = LLVMBuildLoad2(g->builder, usize_type_ref, frame_index_ptr, ""); + LLVMValueRef addr_ptr = LLVMBuildInBoundsGEP2(g->builder, + usize_type_ref, src_ptr_val, &ptr_index, 1, ""); + LLVMValueRef this_addr_val = LLVMBuildLoad2(g->builder, ZigLLVMGetGEPResultElementType(addr_ptr), + addr_ptr, ""); LLVMValueRef args[] = {dest_stack_trace_ptr, this_addr_val}; - ZigLLVMBuildCall(g->builder, add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); - LLVMValueRef prev_frames_left = LLVMBuildLoad(g->builder, frames_left_ptr, ""); + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(add_error_return_trace_addr_fn_val), + add_error_return_trace_addr_fn_val, args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAlwaysInline, ""); + LLVMValueRef prev_frames_left = LLVMBuildLoad2(g->builder, usize_type_ref, frames_left_ptr, ""); LLVMValueRef new_frames_left = LLVMBuildNUWSub(g->builder, prev_frames_left, usize_one, ""); LLVMValueRef done_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, new_frames_left, usize_zero, ""); LLVMBasicBlockRef continue_block = LLVMAppendBasicBlock(fn_val, "Continue"); @@ -2639,7 +2681,7 @@ static LLVMValueRef get_merge_err_ret_traces_fn_val(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, continue_block); LLVMBuildStore(g->builder, new_frames_left, frames_left_ptr); - LLVMValueRef prev_index = LLVMBuildLoad(g->builder, frame_index_ptr, ""); + LLVMValueRef prev_index = LLVMBuildLoad2(g->builder, usize_type_ref, frame_index_ptr, ""); LLVMValueRef index_plus_one = LLVMBuildNUWAdd(g->builder, prev_index, usize_one, ""); LLVMValueRef index_mod_len = LLVMBuildURem(g->builder, index_plus_one, src_len_val, ""); LLVMBuildStore(g->builder, index_mod_len, frame_index_ptr); @@ -2666,13 +2708,14 @@ static LLVMValueRef ir_render_save_err_ret_addr(CodeGen *g, Stage1Air *executabl bool is_llvm_alloca; LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, save_err_ret_addr_instruction->base.scope, &is_llvm_alloca); - ZigLLVMBuildCall(g->builder, return_err_fn, &my_err_trace_val, 1, + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(return_err_fn), return_err_fn, &my_err_trace_val, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); ZigType *ret_type = g->cur_fn->type_entry->data.fn.fn_type_id.return_type; if (fn_is_async(g->cur_fn) && codegen_fn_has_err_ret_tracing_arg(g, ret_type)) { - LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, - frame_index_trace_arg(g, ret_type), ""); + ZigType *frame_type = get_fn_frame_type(g, g->cur_fn); + LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, frame_type), + g->cur_frame_ptr, frame_index_trace_arg(g, ret_type), ""); LLVMBuildStore(g->builder, my_err_trace_val, trace_ptr_ptr); } @@ -2702,16 +2745,21 @@ static void gen_assert_resume_id(CodeGen *g, Stage1AirInst *source_instr, Resume LLVMPositionBuilderAtEnd(g->builder, end_bb); } -static LLVMValueRef gen_resume(CodeGen *g, LLVMValueRef fn_val, LLVMValueRef target_frame_ptr, ResumeId resume_id) { +static LLVMValueRef gen_resume(CodeGen *g, LLVMTypeRef fn_llvm_ty, LLVMValueRef fn_val, + LLVMValueRef target_frame_ptr, ResumeId resume_id) +{ LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; if (fn_val == nullptr) { - LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_fn_ptr_index, ""); - fn_val = LLVMBuildLoad(g->builder, fn_ptr_ptr, ""); + LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP2(g->builder, g->any_frame_header_llvm_ty, + target_frame_ptr, frame_fn_ptr_index, ""); + fn_val = LLVMBuildLoad2(g->builder, ZigLLVMGetGEPResultElementType(fn_ptr_ptr), + fn_ptr_ptr, ""); } LLVMValueRef arg_val = LLVMConstSub(LLVMConstAllOnes(usize_type_ref), LLVMConstInt(usize_type_ref, resume_id, false)); LLVMValueRef args[] = {target_frame_ptr, arg_val}; - return ZigLLVMBuildCall(g->builder, fn_val, args, 2, ZigLLVM_Fast, ZigLLVM_CallAttrAuto, ""); + return ZigLLVMBuildCall(g->builder, fn_llvm_ty, fn_val, args, 2, ZigLLVM_Fast, + ZigLLVM_CallAttrAuto, ""); } static LLVMBasicBlockRef gen_suspend_begin(CodeGen *g, const char *name_hint) { @@ -2733,11 +2781,11 @@ static void set_tail_call_if_appropriate(CodeGen *g, LLVMValueRef call_inst) { LLVMSetTailCall(call_inst, true); } -static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr, LLVMValueRef val, - LLVMAtomicOrdering order) +static LLVMValueRef gen_maybe_atomic_op(CodeGen *g, LLVMAtomicRMWBinOp op, LLVMValueRef ptr, + LLVMValueRef val, LLVMAtomicOrdering order) { if (g->is_single_threaded) { - LLVMValueRef loaded = LLVMBuildLoad(g->builder, ptr, ""); + LLVMValueRef loaded = LLVMBuildLoad2(g->builder, LLVMTypeOf(val), ptr, ""); LLVMValueRef modified; switch (op) { case LLVMAtomicRMWBinOpXchg: @@ -2811,8 +2859,11 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) { // If the awaiter result pointer is non-null, we need to copy the result to there. LLVMBasicBlockRef copy_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResult"); LLVMBasicBlockRef copy_end_block = LLVMAppendBasicBlock(g->cur_fn_val, "CopyResultEnd"); - LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start + 1, ""); - LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad(g->builder, awaiter_ret_ptr_ptr, ""); + LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_ret_start + 1, ""); + LLVMValueRef awaiter_ret_ptr = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(awaiter_ret_ptr_ptr), awaiter_ret_ptr_ptr, ""); LLVMValueRef zero_ptr = LLVMConstNull(LLVMTypeOf(awaiter_ret_ptr)); LLVMValueRef need_copy_bit = LLVMBuildICmp(g->builder, LLVMIntNE, awaiter_ret_ptr, zero_ptr, ""); LLVMBuildCondBr(g->builder, need_copy_bit, copy_block, copy_end_block); @@ -2831,21 +2882,26 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) { LLVMPositionBuilderAtEnd(g->builder, copy_end_block); if (codegen_fn_has_err_ret_tracing_arg(g, ret_type)) { - LLVMValueRef awaiter_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, - frame_index_trace_arg(g, ret_type) + 1, ""); - LLVMValueRef dest_trace_ptr = LLVMBuildLoad(g->builder, awaiter_trace_ptr_ptr, ""); + LLVMValueRef awaiter_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_index_trace_arg(g, ret_type) + 1, ""); + LLVMValueRef dest_trace_ptr = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(awaiter_trace_ptr_ptr), + awaiter_trace_ptr_ptr, ""); bool is_llvm_alloca; LLVMValueRef my_err_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, my_err_trace_val }; - ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(get_merge_err_ret_traces_fn_val(g)), + get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } } // Resume the caller by tail calling them. ZigType *any_frame_type = get_any_frame_type(g, ret_type); - LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, prev_val, get_llvm_type(g, any_frame_type), ""); - LLVMValueRef call_inst = gen_resume(g, nullptr, their_frame_ptr, ResumeIdReturn); + LLVMValueRef their_frame_ptr = LLVMBuildIntToPtr(g->builder, prev_val, + get_llvm_type(g, any_frame_type), ""); + LLVMValueRef call_inst = gen_resume(g, g->anyframe_fn_type, nullptr, their_frame_ptr, ResumeIdReturn); set_tail_call_if_appropriate(g, call_inst); LLVMBuildRetVoid(g->builder); } @@ -2853,13 +2909,12 @@ static void gen_async_return(CodeGen *g, Stage1AirInstReturn *instruction) { static LLVMValueRef gen_convert_to_c_abi(CodeGen *g, LLVMValueRef location, LLVMValueRef value) { ZigType *return_type = g->cur_fn->type_entry->data.fn.gen_return_type; size_t size = type_size(g, return_type); - LLVMTypeRef abi_return_type = get_llvm_c_abi_type(g, return_type); LLVMTypeRef abi_return_type_pointer = LLVMPointerType(abi_return_type, 0); if (size < 8) { LLVMValueRef bitcast = LLVMBuildBitCast(g->builder, value, abi_return_type_pointer, ""); - return LLVMBuildLoad(g->builder, bitcast, ""); + return LLVMBuildLoad2(g->builder, abi_return_type, bitcast, ""); } else { LLVMTypeRef i8ptr = LLVMPointerType(LLVMInt8Type(), 0); LLVMValueRef bc_location = LLVMBuildBitCast(g->builder, location, i8ptr, ""); @@ -2867,7 +2922,7 @@ static LLVMValueRef gen_convert_to_c_abi(CodeGen *g, LLVMValueRef location, LLVM LLVMValueRef len = LLVMConstInt(LLVMInt64Type(), size, false); ZigLLVMBuildMemCpy(g->builder, bc_location, 8, bc_value, return_type->abi_align, len, false); - return LLVMBuildLoad(g->builder, location, ""); + return LLVMBuildLoad2(g->builder, abi_return_type, location, ""); } } @@ -2903,19 +2958,21 @@ static LLVMValueRef ir_render_return(CodeGen *g, Stage1Air *executable, Stage1Ai } else if (g->cur_fn->type_entry->data.fn.fn_type_id.cc != CallingConventionAsync && handle_is_ptr(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type)) { + LLVMTypeRef ret_llvm_ty = get_llvm_type(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type); if (instruction->operand == nullptr) { - LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, ""); + LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, g->cur_ret_ptr, 0, false, ""); LLVMBuildRet(g->builder, by_val_value); } else { LLVMValueRef value = ir_llvm_value(g, instruction->operand); - LLVMValueRef by_val_value = gen_load_untyped(g, value, 0, false, ""); + LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, value, 0, false, ""); LLVMBuildRet(g->builder, by_val_value); } } else if (instruction->operand == nullptr) { if (g->cur_ret_ptr == nullptr) { LLVMBuildRetVoid(g->builder); } else { - LLVMValueRef by_val_value = gen_load_untyped(g, g->cur_ret_ptr, 0, false, ""); + LLVMTypeRef ret_llvm_ty = get_llvm_type(g, g->cur_fn->type_entry->data.fn.fn_type_id.return_type); + LLVMValueRef by_val_value = gen_load_untyped(g, ret_llvm_ty, g->cur_ret_ptr, 0, false, ""); LLVMBuildRet(g->builder, by_val_value); } } else { @@ -3011,20 +3068,18 @@ static LLVMValueRef gen_soft_float_un_op(CodeGen *g, LLVMValueRef op, ZigType *o float_un_op_to_name(op_id), libc_float_suffix(g, scalar_type)); LLVMValueRef func_ref = get_soft_float_fn(g, fn_name, 1, scalar_type->llvm_type, scalar_type->llvm_type); - LLVMValueRef result; if (vector_len == 0) { - return LLVMBuildCall(g->builder, func_ref, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, &op, 1, ""); } else { - result = build_alloca(g, operand_type, "", 0); + LLVMValueRef result = LLVMGetUndef(operand_type->llvm_type); LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; for (uint32_t i = 0; i < vector_len; i++) { LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); LLVMValueRef param = LLVMBuildExtractElement(g->builder, op, index_value, ""); - LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, ¶m, 1, ""); - LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), - call_result, index_value, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, ¶m, 1, ""); + result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } - return LLVMBuildLoad(g->builder, result, ""); + return result; } } @@ -3038,7 +3093,7 @@ static LLVMValueRef gen_float_un_op(CodeGen *g, LLVMValueRef operand, ZigType *o return gen_soft_float_un_op(g, operand, operand_type, op); } LLVMValueRef float_op_fn = get_float_fn(g, operand_type, ZigLLVMFnIdFloatOp, op); - return LLVMBuildCall(g->builder, float_op_fn, &operand, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(float_op_fn), float_op_fn, &operand, 1, ""); } enum DivKind { @@ -3404,7 +3459,7 @@ static LLVMValueRef gen_soft_int_to_float_op(CodeGen *g, LLVMValueRef value_ref, } LLVMValueRef params[1] = {value_ref}; - return LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); } static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, ZigType *operand_type, ZigType *result_type) { @@ -3440,7 +3495,7 @@ static LLVMValueRef gen_soft_float_to_int_op(CodeGen *g, LLVMValueRef value_ref, } LLVMValueRef params[1] = {value_ref}; - LLVMValueRef result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + LLVMValueRef result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); if ((wider_type->data.integral.bit_count == 128) && (g->zig_target->os == OsWindows) && (g->zig_target->arch == ZigLLVM_x86_64)) { result = LLVMBuildBitCast(g->builder, result, wider_type->llvm_type, ""); @@ -3553,12 +3608,12 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL LLVMValueRef result; if (vector_len == 0) { LLVMValueRef params[2] = {op1_value, op2_value}; - result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); result = add_icmp(g, result, res_icmp); } else { ZigType *alloca_ty = operand_type; if (res_icmp != NONE) alloca_ty = get_vector_type(g, vector_len, g->builtin_types.entry_bool); - result = build_alloca(g, alloca_ty, "", 0); + result = LLVMGetUndef(alloca_ty->llvm_type); LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; for (uint32_t i = 0; i < vector_len; i++) { @@ -3567,13 +3622,10 @@ static LLVMValueRef gen_soft_float_bin_op(CodeGen *g, LLVMValueRef op1_value, LL LLVMBuildExtractElement(g->builder, op1_value, index_value, ""), LLVMBuildExtractElement(g->builder, op2_value, index_value, ""), }; - LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, param_count, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, param_count, ""); call_result = add_icmp(g, call_result, res_icmp); - LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), - call_result, index_value, ""); + result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } - - result = LLVMBuildLoad(g->builder, result, ""); } // Some operations are implemented as compound ops and require us to perform some @@ -3703,7 +3755,9 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, Stage1Air *executable, } // TODO runtime safety - return LLVMBuildInBoundsGEP(g->builder, op1_value, &subscript_value, 1, ""); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, scalar_type->data.pointer.child_type); + return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, op1_value, + &subscript_value, 1, ""); } else if (scalar_type->id == ZigTypeIdFloat) { ZigLLVMSetFastMath(g->builder, ir_want_fast_math(g, &bin_op_instruction->base)); return float_op[add_sub_mul](g->builder, op1_value, op2_value, ""); @@ -4044,20 +4098,22 @@ static LLVMValueRef ir_render_ptr_of_array_to_slice(CodeGen *g, Stage1Air *execu assert(array_type->id == ZigTypeIdArray); if (type_has_bits(g, actual_type)) { - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), + result_loc, ptr_index, ""); LLVMValueRef indices[] = { LLVMConstNull(g->builtin_types.entry_usize->llvm_type), LLVMConstInt(g->builtin_types.entry_usize->llvm_type, 0, false), }; LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand); - LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, expr_val, indices, 2, ""); + LLVMValueRef slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, + get_llvm_type(g, array_type), expr_val, indices, 2, ""); gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); } else if (ir_want_runtime_safety(g, &instruction->base) && ptr_index != SIZE_MAX) { - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, ptr_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), result_loc, ptr_index, ""); gen_undef_init(g, slice_ptr_type, slice_ptr_type, ptr_field_ptr); } - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, result_loc, len_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, slice_type), result_loc, len_index, ""); LLVMValueRef len_value = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, array_type->data.array.len, false); gen_store_untyped(g, len_value, len_field_ptr, 0, false); @@ -4107,10 +4163,11 @@ static LLVMValueRef ir_render_bit_cast(CodeGen *g, Stage1Air *executable, return LLVMBuildBitCast(g->builder, value, wanted_type_ref, ""); } else if (actual_is_ptr) { // A scalar is wanted but we got a pointer - LLVMTypeRef wanted_ptr_type_ref = LLVMPointerType(get_llvm_type(g, wanted_type), 0); - LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, wanted_ptr_type_ref, ""); + LLVMTypeRef wanted_elem_type_ref = get_llvm_type(g, wanted_type); + LLVMValueRef bitcasted_ptr = LLVMBuildBitCast(g->builder, value, + LLVMPointerType(wanted_elem_type_ref, 0), ""); uint32_t alignment = get_abi_alignment(g, actual_type); - return gen_load_untyped(g, bitcasted_ptr, alignment, false, ""); + return gen_load_untyped(g, wanted_elem_type_ref, bitcasted_ptr, alignment, false, ""); } else { // A pointer is wanted but we got a scalar assert(actual_type->id == ZigTypeIdPointer); @@ -4298,32 +4355,26 @@ static LLVMValueRef ir_render_binary_not(CodeGen *g, Stage1Air *executable, static LLVMValueRef gen_soft_float_neg(CodeGen *g, ZigType *operand_type, LLVMValueRef operand) { uint32_t vector_len = operand_type->id == ZigTypeIdVector ? operand_type->data.vector.len : 0; - uint16_t num_bits = operand_type->data.floating.bit_count; + uint16_t num_bits = operand_type->id == ZigTypeIdVector ? + operand_type->data.vector.elem_type->data.floating.bit_count : + operand_type->data.floating.bit_count; ZigType *iX_type = get_int_type(g, true, num_bits); - LLVMValueRef sign_mask = LLVMConstInt(iX_type->llvm_type, 1, false); - sign_mask = LLVMConstShl(sign_mask, LLVMConstInt(iX_type->llvm_type, num_bits - 1, false)); + LLVMValueRef sign_mask = LLVMConstShl( + LLVMConstInt(iX_type->llvm_type, 1, false), + LLVMConstInt(iX_type->llvm_type, num_bits - 1, false)); - if (vector_len == 0) { - LLVMValueRef bitcasted_operand = LLVMBuildBitCast(g->builder, operand, iX_type->llvm_type, ""); - LLVMValueRef result = LLVMBuildXor(g->builder, bitcasted_operand, sign_mask, ""); + LLVMValueRef sign_mask_splat = (vector_len == 0) ? sign_mask : + LLVMBuildVectorSplat(g->builder, vector_len, sign_mask, ""); - return LLVMBuildBitCast(g->builder, result, operand_type->llvm_type, ""); - } else { - LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; - ZigType *iX_vector_type = get_vector_type(g, vector_len, iX_type); + LLVMValueRef bitcasted_operand = LLVMBuildBitCast(g->builder, operand, + (vector_len == 0) ? + iX_type->llvm_type : + get_vector_type(g, vector_len, iX_type)->llvm_type, + ""); - LLVMValueRef result = build_alloca(g, iX_vector_type, "", 0); - LLVMValueRef bitcasted_operand = LLVMBuildBitCast(g->builder, operand, iX_vector_type->llvm_type, ""); - for (uint32_t i = 0; i < vector_len; i++) { - LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); - LLVMValueRef elem = LLVMBuildExtractElement(g->builder, bitcasted_operand, index_value, ""); - LLVMValueRef result_elem = LLVMBuildXor(g->builder, elem, sign_mask, ""); - LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), - result_elem, index_value, ""); - } - return LLVMBuildBitCast(g->builder, LLVMBuildLoad(g->builder, result, ""), operand_type->llvm_type, ""); - } + LLVMValueRef result = LLVMBuildXor(g->builder, bitcasted_operand, sign_mask_splat, ""); + return LLVMBuildBitCast(g->builder, result, operand_type->llvm_type, ""); } static LLVMValueRef gen_negation(CodeGen *g, Stage1AirInst *inst, Stage1AirInst *operand, bool wrapping) { @@ -4398,7 +4449,9 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable, if (ptr_type->data.pointer.vector_index != VECTOR_INDEX_NONE) { LLVMValueRef index_val = LLVMConstInt(LLVMInt32Type(), ptr_type->data.pointer.vector_index, false); - LLVMValueRef loaded_vector = LLVMBuildLoad(g->builder, ptr, ""); + uint32_t vec_len = ptr_type->data.pointer.host_int_bytes; + LLVMTypeRef vec_llvm_ty = LLVMVectorType(get_llvm_type(g, child_type), vec_len); + LLVMValueRef loaded_vector = LLVMBuildLoad2(g->builder, vec_llvm_ty, ptr, ""); return LLVMBuildExtractElement(g->builder, loaded_vector, index_val, ""); } @@ -4410,10 +4463,11 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, Stage1Air *executable, LLVMTypeRef int_ptr_ty = LLVMPointerType(LLVMIntType(host_int_bytes * 8), 0); LLVMValueRef int_ptr = LLVMBuildBitCast(g->builder, ptr, int_ptr_ty, ""); - LLVMValueRef containing_int = gen_load(g, int_ptr, ptr_type, ""); + LLVMValueRef containing_int = gen_load_untyped(g, LLVMIntType(host_int_bytes * 8), int_ptr, + get_ptr_align(g, ptr_type), ptr_type->data.pointer.is_volatile, ""); uint32_t host_bit_count = LLVMGetIntTypeWidth(LLVMTypeOf(containing_int)); - assert(host_bit_count == host_int_bytes * 8); + ir_assert(host_bit_count == host_int_bytes * 8, &instruction->base); uint32_t size_in_bits = type_size_bits(g, child_type); uint32_t bit_offset = ptr_type->data.pointer.bit_offset_in_host; @@ -4524,7 +4578,8 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default zero, LLVMConstInt(usize_type_ref, i, false), }; - LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, ""); + LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder, + LLVMGetAllocatedType(array_ptr), array_ptr, indexes, 2, ""); LLVMBuildStore(g->builder, array_elements[i], elem_ptr); } @@ -4545,7 +4600,7 @@ static LLVMValueRef gen_valgrind_client_request(CodeGen *g, LLVMValueRef default LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(asm_template), buf_len(asm_template), buf_ptr(asm_constraints), buf_len(asm_constraints), asm_has_side_effects, asm_is_alignstack, LLVMInlineAsmDialectATT, false); - return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, ""); + return LLVMBuildCall2(g->builder, function_type, asm_fn, param_values, input_and_output_count, ""); } } zig_unreachable(); @@ -4719,10 +4774,9 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 LLVMValueRef elem_size_bytes = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, size_in_bits / 8, false); LLVMValueRef byte_offset = LLVMBuildNUWMul(g->builder, subscript_value, elem_size_bytes, ""); - LLVMValueRef indices[] = { - byte_offset - }; - LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP(g->builder, u8_array_ptr, indices, 1, ""); + LLVMValueRef indices[] = { byte_offset }; + LLVMValueRef elem_byte_ptr = LLVMBuildInBoundsGEP2(g->builder, LLVMInt8Type(), + u8_array_ptr, indices, 1, ""); return LLVMBuildBitCast(g->builder, elem_byte_ptr, LLVMPointerType(get_llvm_type(g, child_type), 0), ""); } } @@ -4730,14 +4784,14 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstNull(g->builtin_types.entry_usize->llvm_type), subscript_value }; - return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); + return LLVMBuildInBoundsGEP2(g->builder, get_llvm_type(g, array_type), array_ptr, + indices, 2, ""); } else if (array_type->id == ZigTypeIdPointer) { LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); - LLVMValueRef indices[] = { - subscript_value - }; - return LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 1, ""); + LLVMValueRef indices[] = { subscript_value }; + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.pointer.child_type); + return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, indices, 1, ""); } else if (array_type->id == ZigTypeIdStruct) { LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, array_ptr_type); assert(array_type->data.structure.special == StructSpecialSlice); @@ -4752,22 +4806,26 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 } assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); - assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); if (safety_check_on) { size_t len_index = array_type->data.structure.fields[slice_len_index]->gen_index; assert(len_index != SIZE_MAX); - LLVMValueRef len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)len_index, ""); - LLVMValueRef len = gen_load_untyped(g, len_ptr, 0, false, ""); + LLVMValueRef len_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), + array_ptr, (unsigned)len_index, ""); + LLVMValueRef len = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_ptr), len_ptr, + 0, false, ""); LLVMIntPredicate upper_op = (ptr_type->data.pointer.sentinel != nullptr) ? LLVMIntULE : LLVMIntULT; add_bounds_check(g, subscript_value, LLVMIntEQ, nullptr, upper_op, len); } size_t ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; assert(ptr_index != SIZE_MAX); - LLVMValueRef ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, (unsigned)ptr_index, ""); - LLVMValueRef ptr = gen_load_untyped(g, ptr_ptr, 0, false, ""); - return LLVMBuildInBoundsGEP(g->builder, ptr, &subscript_value, 1, ""); + LLVMValueRef ptr_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, array_type), + array_ptr, (unsigned)ptr_index, ""); + LLVMValueRef ptr = gen_load_untyped(g, + LLVMPointerTypeInContext(LLVMGetGlobalContext(), 0), ptr_ptr, 0, false, ""); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_type->data.pointer.child_type); + return LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, ptr, &subscript_value, 1, ""); } else if (array_type->id == ZigTypeIdVector) { return array_ptr_ptr; } else { @@ -4775,12 +4833,16 @@ static LLVMValueRef ir_render_elem_ptr(CodeGen *g, Stage1Air *executable, Stage1 } } -static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMValueRef new_stack) { - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_ptr_index, ""); - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, new_stack, (unsigned)slice_len_index, ""); +static LLVMValueRef get_new_stack_addr(CodeGen *g, LLVMTypeRef new_stack_llvm_ty, + LLVMValueRef new_stack) +{ + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_ptr_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, new_stack_llvm_ty, new_stack, (unsigned)slice_len_index, ""); - LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); - LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, ""); + LLVMValueRef ptr_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_field_ptr), + ptr_field_ptr, 0, false, ""); + LLVMValueRef len_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(len_field_ptr), + len_field_ptr, 0, false, ""); LLVMValueRef ptr_addr = LLVMBuildPtrToInt(g->builder, ptr_value, LLVMTypeOf(len_value), ""); LLVMValueRef end_addr = LLVMBuildNUWAdd(g->builder, ptr_addr, len_value, ""); @@ -4804,7 +4866,7 @@ static void gen_set_stack_pointer(CodeGen *g, LLVMValueRef aligned_end_addr) { aligned_end_addr, }; - LLVMBuildCall(g->builder, write_register_fn_val, params, 2, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(write_register_fn_val), write_register_fn_val, params, 2, ""); } static void render_async_spills(CodeGen *g) { @@ -4834,7 +4896,9 @@ static void render_async_spills(CodeGen *g) { } calc_llvm_field_index_add(g, &arg_calc, var->var_type); - var->value_ref = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, arg_calc.field_index - 1, var->name); + var->value_ref = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, arg_calc.field_index - 1, var->name); if (var->decl_node) { var->di_loc_var = ZigLLVMCreateAutoVariable(g->dbuilder, get_di_scope(g, var->parent_scope), var->name, import->data.structure.root_struct->di_file, @@ -4852,7 +4916,9 @@ static void render_async_spills(CodeGen *g) { continue; size_t gen_index = frame_type->data.structure.fields[instruction->field_index]->gen_index; - instruction->base.llvm_value = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, gen_index, + instruction->base.llvm_value = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, gen_index, instruction->name_hint); } } @@ -4895,8 +4961,8 @@ static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) { LLVMTypeRef ptr_usize_llvm_type = LLVMPointerType(usize_llvm_type, 0); LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, ""); LLVMValueRef negative_one = LLVMConstInt(LLVMInt32Type(), -1, true); - LLVMValueRef prefix_ptr = LLVMBuildInBoundsGEP(g->builder, casted_fn_val, &negative_one, 1, ""); - LLVMValueRef load_inst = LLVMBuildLoad(g->builder, prefix_ptr, ""); + LLVMValueRef prefix_ptr = LLVMBuildInBoundsGEP2(g->builder, usize_llvm_type, casted_fn_val, &negative_one, 1, ""); + LLVMValueRef load_inst = LLVMBuildLoad2(g->builder, usize_llvm_type, prefix_ptr, ""); // Some architectures (e.g SPARCv9) has different alignment requirements between a // function/usize pointer and also require all loads to be aligned. @@ -4910,17 +4976,23 @@ static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) { static void gen_init_stack_trace(CodeGen *g, LLVMValueRef trace_field_ptr, LLVMValueRef addrs_field_ptr) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(usize_type_ref); + LLVMTypeRef stack_trace_llvm_ty = get_llvm_type(g, get_stack_trace_type(g)); - LLVMValueRef index_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 0, ""); + LLVMValueRef index_ptr = LLVMBuildStructGEP2(g->builder, stack_trace_llvm_ty, trace_field_ptr, 0, ""); LLVMBuildStore(g->builder, zero, index_ptr); - LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP(g->builder, trace_field_ptr, 1, ""); - LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_ptr_index, ""); + LLVMValueRef addrs_slice_ptr = LLVMBuildStructGEP2(g->builder, stack_trace_llvm_ty, trace_field_ptr, 1, ""); + LLVMValueRef addrs_ptr_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(addrs_slice_ptr), + addrs_slice_ptr, slice_ptr_index, ""); LLVMValueRef indices[] = { LLVMConstNull(usize_type_ref), LLVMConstNull(usize_type_ref) }; - LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP(g->builder, addrs_field_ptr, indices, 2, ""); + LLVMValueRef trace_field_addrs_as_ptr = LLVMBuildInBoundsGEP2(g->builder, + ZigLLVMGetGEPResultElementType(addrs_field_ptr), addrs_field_ptr, indices, 2, ""); LLVMBuildStore(g->builder, trace_field_addrs_as_ptr, addrs_ptr_ptr); - LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP(g->builder, addrs_slice_ptr, slice_len_index, ""); + LLVMValueRef addrs_len_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(addrs_slice_ptr), + addrs_slice_ptr, slice_len_index, ""); LLVMBuildStore(g->builder, LLVMConstInt(usize_type_ref, stack_trace_ptr_count, false), addrs_len_ptr); } @@ -4930,17 +5002,20 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef fn_val; + LLVMTypeRef fn_llvm_ty; ZigType *fn_type; bool callee_is_async; if (instruction->fn_entry) { fn_val = fn_llvm_value(g, instruction->fn_entry); fn_type = instruction->fn_entry->type_entry; callee_is_async = fn_is_async(instruction->fn_entry); + fn_llvm_ty = LLVMGlobalGetValueType(fn_val); } else { assert(instruction->fn_ref); fn_val = ir_llvm_value(g, instruction->fn_ref); fn_type = instruction->fn_ref->value->type; callee_is_async = fn_type->data.fn.fn_type_id.cc == CallingConventionAsync; + fn_llvm_ty = fn_type->data.fn.raw_type_ref; } FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; @@ -4961,29 +5036,40 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ZigType *anyframe_type = nullptr; LLVMValueRef frame_result_loc_uncasted = nullptr; LLVMValueRef frame_result_loc; + LLVMTypeRef frame_struct_llvm_ty; LLVMValueRef awaiter_init_val; LLVMValueRef ret_ptr; if (callee_is_async) { if (instruction->new_stack == nullptr) { if (instruction->modifier == CallModifierAsync) { frame_result_loc = result_loc; + if (result_loc != nullptr) { + ir_assert(instruction->result_loc->value->type->id == ZigTypeIdPointer, &instruction->base); + frame_struct_llvm_ty = get_llvm_type(g, instruction->result_loc->value->type->data.pointer.child_type); + } else { + frame_struct_llvm_ty = nullptr; + } } else { ir_assert(instruction->frame_result_loc != nullptr, &instruction->base); frame_result_loc_uncasted = ir_llvm_value(g, instruction->frame_result_loc); ir_assert(instruction->fn_entry != nullptr, &instruction->base); + frame_struct_llvm_ty = get_llvm_type(g, instruction->fn_entry->frame_type); frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, - LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), ""); + LLVMPointerType(frame_struct_llvm_ty, 0), ""); } } else { if (instruction->new_stack->value->type->id == ZigTypeIdPointer && instruction->new_stack->value->type->data.pointer.child_type->id == ZigTypeIdFnFrame) { frame_result_loc = ir_llvm_value(g, instruction->new_stack); + frame_struct_llvm_ty = get_llvm_type(g, instruction->new_stack->value->type->data.pointer.child_type); } else { LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); + LLVMTypeRef frame_slice_llvm_ty = get_llvm_type(g, instruction->new_stack->value->type); if (ir_want_runtime_safety(g, &instruction->base)) { - LLVMValueRef given_len_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_len_index, ""); - LLVMValueRef given_frame_len = LLVMBuildLoad(g->builder, given_len_ptr, ""); + LLVMValueRef given_len_ptr = LLVMBuildStructGEP2(g->builder, + frame_slice_llvm_ty, frame_slice_ptr, slice_len_index, ""); + LLVMValueRef given_frame_len = LLVMBuildLoad2(g->builder, usize_type_ref, given_len_ptr, ""); LLVMValueRef actual_frame_len = gen_frame_size(g, fn_val); LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "FrameSizeCheckFail"); @@ -4998,11 +5084,14 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMPositionBuilderAtEnd(g->builder, ok_block); } need_frame_ptr_ptr_spill = true; - LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, ""); - LLVMValueRef frame_ptr = LLVMBuildLoad(g->builder, frame_ptr_ptr, ""); + LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_slice_llvm_ty, + frame_slice_ptr, slice_ptr_index, ""); + LLVMValueRef frame_ptr = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(frame_ptr_ptr), frame_ptr_ptr, ""); if (instruction->fn_entry == nullptr) { anyframe_type = get_any_frame_type(g, src_return_type); frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, anyframe_type), ""); + frame_struct_llvm_ty = anyframe_type->data.any_frame.struct_llvm_ty; } else { ZigType *frame_type = get_fn_frame_type(g, instruction->fn_entry); if ((err = type_resolve(g, frame_type, ResolveStatusLLVMFull))) @@ -5010,6 +5099,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ZigType *ptr_frame_type = get_pointer_to_type(g, frame_type, false); frame_result_loc = LLVMBuildBitCast(g->builder, frame_ptr, get_llvm_type(g, ptr_frame_type), ""); + frame_struct_llvm_ty = get_llvm_type(g, frame_type); } } } @@ -5019,7 +5109,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI if (ret_has_bits) { // Use the result location which is inside the frame if this is an async call. - ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); + ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, + frame_result_loc, frame_ret_start + 2, ""); } } else { awaiter_init_val = zero; @@ -5030,7 +5121,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ret_ptr = result_loc; } else { // no result location provided to @asyncCall - use the one inside the frame. - ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); + ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, + frame_result_loc, frame_ret_start + 2, ""); } } } @@ -5050,20 +5142,20 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI if (ret_has_bits) { if (result_loc == nullptr) { // return type is a scalar, but we still need a pointer to it. Use the async fn frame. - ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); + ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 2, ""); } else { // Use the call instruction's result location. ret_ptr = result_loc; } // Store a zero in the awaiter's result ptr to indicate we do not need a copy made. - LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 1, ""); - LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr))); + LLVMValueRef awaiter_ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 1, ""); + LLVMValueRef zero_ptr = LLVMConstNull(ZigLLVMGetGEPResultElementType(awaiter_ret_ptr)); LLVMBuildStore(g->builder, zero_ptr, awaiter_ret_ptr); } if (prefix_arg_err_ret_stack) { - LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_index_trace_arg(g, src_return_type) + 1, ""); bool is_llvm_alloca; LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, @@ -5074,19 +5166,19 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI assert(frame_result_loc != nullptr); - LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_fn_ptr_index, ""); + LLVMValueRef fn_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_fn_ptr_index, ""); LLVMValueRef bitcasted_fn_val = LLVMBuildBitCast(g->builder, fn_val, - LLVMGetElementType(LLVMTypeOf(fn_ptr_ptr)), ""); + LLVMPointerTypeInContext(LLVMGetGlobalContext(), 0), ""); LLVMBuildStore(g->builder, bitcasted_fn_val, fn_ptr_ptr); - LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_resume_index, ""); + LLVMValueRef resume_index_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_resume_index, ""); LLVMBuildStore(g->builder, zero, resume_index_ptr); - LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_awaiter_index, ""); + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_awaiter_index, ""); LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); if (ret_has_bits) { - LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, ""); + LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start, ""); LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); } } else if (instruction->modifier == CallModifierAsync) { @@ -5095,14 +5187,20 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI zig_panic("TODO @asyncCall of non-async function"); } frame_result_loc = result_loc; + if (result_loc != nullptr) { + ir_assert(instruction->result_loc->value->type->id == ZigTypeIdPointer, &instruction->base); + frame_struct_llvm_ty = get_llvm_type(g, instruction->result_loc->value->type->data.pointer.child_type); + } else { + frame_struct_llvm_ty = nullptr; + } awaiter_init_val = LLVMConstAllOnes(usize_type_ref); - LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_awaiter_index, ""); + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_awaiter_index, ""); LLVMBuildStore(g->builder, awaiter_init_val, awaiter_ptr); if (ret_has_bits) { - ret_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); - LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start, ""); + ret_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start + 2, ""); + LLVMValueRef ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, frame_ret_start, ""); LLVMBuildStore(g->builder, ret_ptr, ret_ptr_ptr); if (first_arg_ret) { @@ -5113,11 +5211,11 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI // Then we have to wire up the StackTrace pointers. // Await is responsible for merging error return traces. uint32_t trace_field_index_start = frame_index_trace_arg(g, src_return_type); - LLVMValueRef callee_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + LLVMValueRef callee_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, trace_field_index_start, ""); - LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + LLVMValueRef trace_field_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, trace_field_index_start + 2, ""); - LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, + LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, frame_result_loc, trace_field_index_start + 3, ""); LLVMBuildStore(g->builder, trace_field_ptr, callee_trace_ptr_ptr); @@ -5178,6 +5276,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI frame_index_arg_calc(g, &arg_calc_start, fn_type->data.fn.fn_type_id.return_type); LLVMValueRef casted_frame; + LLVMTypeRef casted_frame_llvm_ty; if (instruction->new_stack != nullptr && instruction->fn_entry == nullptr) { // We need the frame type to be a pointer to a struct that includes the args @@ -5189,8 +5288,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI size_t field_count = arg_calc.field_index; LLVMTypeRef *field_types = heap::c_allocator.allocate_nonzero<LLVMTypeRef>(field_count); - LLVMGetStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc)), field_types); - assert(LLVMCountStructElementTypes(LLVMGetElementType(LLVMTypeOf(frame_result_loc))) == arg_calc_start.field_index); + LLVMGetStructElementTypes(frame_struct_llvm_ty, field_types); + assert(LLVMCountStructElementTypes(frame_struct_llvm_ty) == arg_calc_start.field_index); arg_calc = arg_calc_start; for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { @@ -5211,32 +5310,34 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI LLVMTypeRef ptr_frame_with_args_type = LLVMPointerType(frame_with_args_type, 0); casted_frame = LLVMBuildBitCast(g->builder, frame_result_loc, ptr_frame_with_args_type, ""); + casted_frame_llvm_ty = frame_with_args_type; } else { casted_frame = frame_result_loc; + casted_frame_llvm_ty = frame_struct_llvm_ty; } CalcLLVMFieldIndex arg_calc = arg_calc_start; for (size_t arg_i = 0; arg_i < gen_param_values.length; arg_i += 1) { calc_llvm_field_index_add(g, &arg_calc, gen_param_types.at(arg_i)); - LLVMValueRef arg_ptr = LLVMBuildStructGEP(g->builder, casted_frame, arg_calc.field_index - 1, ""); + LLVMValueRef arg_ptr = LLVMBuildStructGEP2(g->builder, casted_frame_llvm_ty, casted_frame, arg_calc.field_index - 1, ""); gen_assign_raw(g, arg_ptr, get_pointer_to_type(g, gen_param_types.at(arg_i), true), gen_param_values.at(arg_i)); } gen_param_types.deinit(); if (instruction->modifier == CallModifierAsync) { - gen_resume(g, fn_val, frame_result_loc, ResumeIdCall); + gen_resume(g, fn_llvm_ty, fn_val, frame_result_loc, ResumeIdCall); if (instruction->new_stack != nullptr) { return LLVMBuildBitCast(g->builder, frame_result_loc, get_llvm_type(g, instruction->base.value->type), ""); } return nullptr; } else if (instruction->modifier == CallModifierNoSuspend && !fn_is_async(g->cur_fn)) { - gen_resume(g, fn_val, frame_result_loc, ResumeIdCall); + gen_resume(g, fn_llvm_ty, fn_val, frame_result_loc, ResumeIdCall); if (ir_want_runtime_safety(g, &instruction->base)) { - LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, - frame_awaiter_index, ""); + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, + frame_result_loc, frame_awaiter_index, ""); LLVMValueRef all_ones = LLVMConstAllOnes(usize_type_ref); LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, all_ones, LLVMAtomicOrderingRelease); @@ -5255,14 +5356,15 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI ZigType *result_type = instruction->base.value->type; ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true); - return gen_await_early_return(g, &instruction->base, frame_result_loc, + return gen_await_early_return(g, &instruction->base, + frame_struct_llvm_ty, frame_result_loc, result_type, ptr_result_type, result_loc, true); } else { ZigType *ptr_result_type = get_pointer_to_type(g, src_return_type, true); LLVMBasicBlockRef call_bb = gen_suspend_begin(g, "CallResume"); - LLVMValueRef call_inst = gen_resume(g, fn_val, frame_result_loc, ResumeIdCall); + LLVMValueRef call_inst = gen_resume(g, fn_llvm_ty, fn_val, frame_result_loc, ResumeIdCall); set_tail_call_if_appropriate(g, call_inst); LLVMBuildRetVoid(g->builder); @@ -5284,44 +5386,52 @@ static LLVMValueRef ir_render_call(CodeGen *g, Stage1Air *executable, Stage1AirI if (need_frame_ptr_ptr_spill) { LLVMValueRef frame_slice_ptr = ir_llvm_value(g, instruction->new_stack); - LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP(g->builder, frame_slice_ptr, slice_ptr_index, ""); - frame_result_loc_uncasted = LLVMBuildLoad(g->builder, frame_ptr_ptr, ""); + LLVMValueRef frame_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, instruction->new_stack->value->type), + frame_slice_ptr, slice_ptr_index, ""); + frame_result_loc_uncasted = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(frame_ptr_ptr), frame_ptr_ptr, ""); } if (frame_result_loc_uncasted != nullptr) { if (instruction->fn_entry != nullptr) { + frame_struct_llvm_ty = get_llvm_type(g, instruction->fn_entry->frame_type); frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, - LLVMPointerType(get_llvm_type(g, instruction->fn_entry->frame_type), 0), ""); + LLVMPointerType(frame_struct_llvm_ty, 0), ""); } else { frame_result_loc = LLVMBuildBitCast(g->builder, frame_result_loc_uncasted, get_llvm_type(g, anyframe_type), ""); + frame_struct_llvm_ty = anyframe_type->data.any_frame.struct_llvm_ty; } } - LLVMValueRef result_ptr = LLVMBuildStructGEP(g->builder, frame_result_loc, frame_ret_start + 2, ""); - return LLVMBuildLoad(g->builder, result_ptr, ""); + LLVMValueRef result_ptr = LLVMBuildStructGEP2(g->builder, frame_struct_llvm_ty, + frame_result_loc, frame_ret_start + 2, ""); + return LLVMBuildLoad2(g->builder, get_llvm_type(g, src_return_type), result_ptr, ""); } } else { gen_param_types.deinit(); } if (instruction->new_stack == nullptr || instruction->is_async_call_builtin) { - result = ZigLLVMBuildCall(g->builder, fn_val, + result = ZigLLVMBuildCall(g->builder, fn_llvm_ty, fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, ""); } else if (instruction->modifier == CallModifierAsync) { zig_panic("TODO @asyncCall of non-async function"); } else { - LLVMValueRef new_stack_addr = get_new_stack_addr(g, ir_llvm_value(g, instruction->new_stack)); + LLVMValueRef new_stack_addr = get_new_stack_addr(g, + get_llvm_type(g, instruction->new_stack->value->type), + ir_llvm_value(g, instruction->new_stack)); LLVMValueRef old_stack_ref; if (src_return_type->id != ZigTypeIdUnreachable) { LLVMValueRef stacksave_fn_val = get_stacksave_fn_val(g); - old_stack_ref = LLVMBuildCall(g->builder, stacksave_fn_val, nullptr, 0, ""); + old_stack_ref = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(stacksave_fn_val), stacksave_fn_val, nullptr, 0, ""); } gen_set_stack_pointer(g, new_stack_addr); - result = ZigLLVMBuildCall(g->builder, fn_val, + result = ZigLLVMBuildCall(g->builder, fn_llvm_ty, fn_val, gen_param_values.items, (unsigned)gen_param_values.length, llvm_cc, call_attr, ""); if (src_return_type->id != ZigTypeIdUnreachable) { LLVMValueRef stackrestore_fn_val = get_stackrestore_fn_val(g); - LLVMBuildCall(g->builder, stackrestore_fn_val, &old_stack_ref, 1, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(stackrestore_fn_val), stackrestore_fn_val, &old_stack_ref, 1, ""); } } @@ -5387,7 +5497,8 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, Stage1Air *executable codegen_report_errors_and_exit(g); ir_assert(field->gen_index != SIZE_MAX, &instruction->base); - LLVMValueRef field_ptr_val = LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, ""); + LLVMValueRef field_ptr_val = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, struct_type), struct_ptr, (unsigned)field->gen_index, ""); ZigType *res_type = instruction->base.value->type; ir_assert(res_type->id == ZigTypeIdPointer, &instruction->base); if (res_type->data.pointer.host_int_bytes != 0) { @@ -5432,8 +5543,9 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, LLVMPointerType(tag_type_ref, 0), ""); } else { assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); - tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, - union_type->data.unionation.gen_tag_index, ""); + tag_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), + union_ptr, union_type->data.unionation.gen_tag_index, ""); } LLVMValueRef tag_value = bigint_to_llvm_const(tag_type_ref, @@ -5448,19 +5560,25 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, LLVMTypeRef field_type_ref = LLVMPointerType(get_llvm_type(g, field->type_entry), 0); if (union_type->data.unionation.gen_tag_index == SIZE_MAX) { - LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, 0, ""); + LLVMValueRef union_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), union_ptr, 0, ""); LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); return bitcasted_union_field_ptr; } if (instruction->initializing) { - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); + LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), + union_ptr, union_type->data.unionation.gen_tag_index, ""); LLVMValueRef tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), &field->enum_field->value); gen_store_untyped(g, tag_value, tag_field_ptr, 0, false); } else if (instruction->safety_check_on && ir_want_runtime_safety(g, &instruction->base)) { - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, union_type->data.unionation.gen_tag_index, ""); - LLVMValueRef tag_value = gen_load_untyped(g, tag_field_ptr, 0, false, ""); + LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), + union_ptr, union_type->data.unionation.gen_tag_index, ""); + LLVMValueRef tag_value = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(tag_field_ptr), + tag_field_ptr, 0, false, ""); LLVMValueRef expected_tag_value = bigint_to_llvm_const(get_llvm_type(g, union_type->data.unionation.tag_type), @@ -5476,8 +5594,8 @@ static LLVMValueRef ir_render_union_field_ptr(CodeGen *g, Stage1Air *executable, LLVMPositionBuilderAtEnd(g->builder, ok_block); } - LLVMValueRef union_field_ptr = LLVMBuildStructGEP(g->builder, union_ptr, - union_type->data.unionation.gen_union_index, ""); + LLVMValueRef union_field_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, union_type), + union_ptr, union_type->data.unionation.gen_union_index, ""); LLVMValueRef bitcasted_union_field_ptr = LLVMBuildBitCast(g->builder, union_field_ptr, field_type_ref, ""); return bitcasted_union_field_ptr; } @@ -5555,7 +5673,7 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A size_t param_index = 0; LLVMTypeRef *param_types = heap::c_allocator.allocate<LLVMTypeRef>(input_and_output_count); LLVMValueRef *param_values = heap::c_allocator.allocate<LLVMValueRef>(input_and_output_count); - bool *param_needs_attr = heap::c_allocator.allocate<bool>(input_and_output_count); + LLVMTypeRef *param_needs_attr = heap::c_allocator.allocate<LLVMTypeRef>(input_and_output_count); for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) { AsmOutput *asm_output = asm_expr->output_list.at(i); bool is_return = (asm_output->return_type != nullptr); @@ -5571,7 +5689,8 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1); } else { buf_appendf(&constraint_buf, "=*%s", buf_ptr(asm_output->constraint) + 1); - param_needs_attr[param_index] = true; + ZigVar *variable = instruction->output_vars[i]; + param_needs_attr[param_index] = get_llvm_type(g, variable->var_type); } if (total_index + 1 < total_constraint_count) { buf_append_char(&constraint_buf, ','); @@ -5597,6 +5716,7 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A ZigType *const type = ir_input->value->type; LLVMTypeRef type_ref = get_llvm_type(g, type); LLVMValueRef value_ref = ir_llvm_value(g, ir_input); + LLVMTypeRef elem_type_ref = nullptr; // Handle integers of non pot bitsize by widening them. if (type->id == ZigTypeIdInt) { const size_t bitsize = type->data.integral.bit_count; @@ -5608,6 +5728,7 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A value_ref = gen_widen_or_shorten(g, false, type, wider_type, value_ref); } } else if (handle_is_ptr(g, type)) { + elem_type_ref = type_ref; ZigType *gen_type = get_pointer_to_type(g, type, true); type_ref = get_llvm_type(g, gen_type); } @@ -5615,7 +5736,10 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A param_types[param_index] = type_ref; param_values[param_index] = value_ref; // In the case of indirect inputs, LLVM requires the callsite to have an elementtype(<ty>) attribute. - param_needs_attr[param_index] = buf_ptr(asm_input->constraint)[0] == '*'; + if (buf_ptr(asm_input->constraint)[0] == '*') { + param_needs_attr[param_index] = elem_type_ref ? elem_type_ref : + get_llvm_type(g, type->data.pointer.child_type); + } } for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) { Buf *clobber_buf = asm_expr->clobber_list.at(i); @@ -5660,11 +5784,12 @@ static LLVMValueRef ir_render_asm_gen(CodeGen *g, Stage1Air *executable, Stage1A LLVMValueRef asm_fn = LLVMGetInlineAsm(function_type, buf_ptr(&llvm_template), buf_len(&llvm_template), buf_ptr(&constraint_buf), buf_len(&constraint_buf), is_volatile, false, LLVMInlineAsmDialectATT, false); - LLVMValueRef built_call = LLVMBuildCall(g->builder, asm_fn, param_values, (unsigned)input_and_output_count, ""); + LLVMValueRef built_call = LLVMBuildCall2(g->builder, function_type, + asm_fn, param_values, (unsigned)input_and_output_count, ""); for (size_t i = 0; i < input_and_output_count; i += 1) { - if (param_needs_attr[i]) { - LLVMTypeRef elem_ty = LLVMGetElementType(param_types[i]); + if (param_needs_attr[i] != nullptr) { + LLVMTypeRef elem_ty = param_needs_attr[i]; ZigLLVMSetCallElemTypeAttr(built_call, i, elem_ty); } } @@ -5689,8 +5814,9 @@ static LLVMValueRef gen_non_null_bit(CodeGen *g, ZigType *maybe_type, LLVMValueR if (is_scalar) return LLVMBuildICmp(g->builder, LLVMIntNE, maybe_handle, LLVMConstNull(get_llvm_type(g, maybe_type)), ""); - LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP(g->builder, maybe_handle, maybe_null_index, ""); - return gen_load_untyped(g, maybe_field_ptr, 0, false, ""); + LLVMValueRef maybe_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, maybe_type), maybe_handle, maybe_null_index, ""); + return gen_load_untyped(g, ZigLLVMGetGEPResultElementType(maybe_field_ptr), maybe_field_ptr, 0, false, ""); } static LLVMValueRef ir_render_test_non_null(CodeGen *g, Stage1Air *executable, @@ -5736,12 +5862,13 @@ static LLVMValueRef ir_render_optional_unwrap_ptr(CodeGen *g, Stage1Air *executa } else { LLVMValueRef optional_struct_ref = get_handle_value(g, base_ptr, maybe_type, ptr_type); if (instruction->initializing) { - LLVMValueRef non_null_bit_ptr = LLVMBuildStructGEP(g->builder, optional_struct_ref, - maybe_null_index, ""); + LLVMValueRef non_null_bit_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, maybe_type), optional_struct_ref, maybe_null_index, ""); LLVMValueRef non_null_bit = LLVMConstInt(LLVMInt1Type(), 1, false); gen_store_untyped(g, non_null_bit, non_null_bit_ptr, 0, false); } - return LLVMBuildStructGEP(g->builder, optional_struct_ref, maybe_child_index, ""); + return LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, maybe_type), optional_struct_ref, maybe_child_index, ""); } } } @@ -5818,7 +5945,7 @@ static LLVMValueRef ir_render_clz(CodeGen *g, Stage1Air *executable, Stage1AirIn operand, LLVMConstNull(LLVMInt1Type()), }; - LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, params, 2, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5830,7 +5957,7 @@ static LLVMValueRef ir_render_ctz(CodeGen *g, Stage1Air *executable, Stage1AirIn operand, LLVMConstNull(LLVMInt1Type()), }; - LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, params, 2, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5887,7 +6014,7 @@ static LLVMValueRef ir_render_pop_count(CodeGen *g, Stage1Air *executable, Stage ZigType *int_type = instruction->op->value->type; LLVMValueRef fn_val = get_int_builtin_fn(g, int_type, BuiltinFnIdPopCount); LLVMValueRef operand = ir_llvm_value(g, instruction->op); - LLVMValueRef wrong_size_int = LLVMBuildCall(g->builder, fn_val, &operand, 1, ""); + LLVMValueRef wrong_size_int = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &operand, 1, ""); return gen_widen_or_shorten(g, false, int_type, instruction->base.value->type, wrong_size_int); } @@ -5978,7 +6105,9 @@ static LLVMValueRef ir_render_err_name(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstNull(g->builtin_types.entry_usize->llvm_type), err_val, }; - return LLVMBuildInBoundsGEP(g->builder, g->err_name_table, indices, 2, ""); + return LLVMBuildInBoundsGEP2(g->builder, + LLVMGlobalGetValueType(g->err_name_table), + g->err_name_table, indices, 2, ""); } static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { @@ -6050,7 +6179,7 @@ static LLVMValueRef get_enum_tag_name_function(CodeGen *g, ZigType *enum_type) { LLVMSetAlignment(str_global, LLVMABIAlignmentOfType(g->target_data_ref, LLVMTypeOf(str_init))); LLVMValueRef fields[] = { - LLVMConstGEP(str_global, array_ptr_indices, 2), + LLVMConstInBoundsGEP2(LLVMGlobalGetValueType(str_global), str_global, array_ptr_indices, 2), LLVMConstInt(g->builtin_types.entry_usize->llvm_type, buf_len(name), false), }; LLVMValueRef slice_init_value = LLVMConstNamedStruct(get_llvm_type(g, u8_slice_type), fields, 2); @@ -6099,7 +6228,8 @@ static LLVMValueRef ir_render_enum_tag_name(CodeGen *g, Stage1Air *executable, LLVMValueRef enum_name_function = get_enum_tag_name_function(g, enum_type); LLVMValueRef enum_tag_value = ir_llvm_value(g, instruction->target); - return ZigLLVMBuildCall(g->builder, enum_name_function, &enum_tag_value, 1, + return ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(enum_name_function), enum_name_function, + &enum_tag_value, 1, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } @@ -6166,8 +6296,10 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, Stage1Air *executable, Stag align_bytes = get_ptr_align(g, slice_ptr_type); size_t ptr_index = target_type->data.structure.fields[slice_ptr_index]->gen_index; - LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP(g->builder, target_val, (unsigned)ptr_index, ""); - ptr_val = gen_load_untyped(g, ptr_val_ptr, 0, false, ""); + LLVMValueRef ptr_val_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, target_type), + target_val, (unsigned)ptr_index, ""); + ptr_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(ptr_val_ptr), ptr_val_ptr, 0, false, ""); } else { zig_unreachable(); } @@ -6319,12 +6451,16 @@ static LLVMValueRef ir_render_cmpxchg(CodeGen *g, Stage1Air *executable, Stage1A if (actual_abi_type != nullptr) { payload_val = LLVMBuildTrunc(g->builder, payload_val, get_llvm_type(g, operand_type), ""); } - LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); + LLVMTypeRef result_loc_struct_llvm_ty = get_llvm_type(g, + instruction->result_loc->value->type->data.pointer.child_type); + LLVMValueRef val_ptr = LLVMBuildStructGEP2(g->builder, + result_loc_struct_llvm_ty, result_loc, maybe_child_index, ""); gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); LLVMValueRef success_bit = LLVMBuildExtractValue(g->builder, result_val, 1, ""); LLVMValueRef nonnull_bit = LLVMBuildNot(g->builder, success_bit, ""); - LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, ""); + LLVMValueRef maybe_ptr = LLVMBuildStructGEP2(g->builder, result_loc_struct_llvm_ty, result_loc, + maybe_null_index, ""); gen_store_untyped(g, nonnull_bit, maybe_ptr, 0, false); return result_loc; } @@ -6469,7 +6605,7 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, Stage1Air *executable, Stage1Ai static LLVMValueRef ir_render_wasm_memory_size(CodeGen *g, Stage1Air *executable, Stage1AirInstWasmMemorySize *instruction) { // TODO adjust for wasm64 LLVMValueRef param = ir_llvm_value(g, instruction->index); - LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_size(g), ¶m, 1, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_wasm_memory_size(g)), gen_wasm_memory_size(g), ¶m, 1, ""); return val; } @@ -6479,7 +6615,7 @@ static LLVMValueRef ir_render_wasm_memory_grow(CodeGen *g, Stage1Air *executable ir_llvm_value(g, instruction->index), ir_llvm_value(g, instruction->delta), }; - LLVMValueRef val = LLVMBuildCall(g->builder, gen_wasm_memory_grow(g), params, 2, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_wasm_memory_grow(g)), gen_wasm_memory_grow(g), params, 2, ""); return val; } @@ -6525,7 +6661,7 @@ static LLVMValueRef ir_render_prefetch(CodeGen *g, Stage1Air *executable, Stage1 LLVMConstInt(LLVMInt32Type(), instruction->locality, false), LLVMConstInt(LLVMInt32Type(), instruction->cache, false), }; - LLVMValueRef val = LLVMBuildCall(g->builder, gen_prefetch(g), params, 4, ""); + LLVMValueRef val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(gen_prefetch(g)), gen_prefetch(g), params, 4, ""); return val; } @@ -6591,12 +6727,14 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (value_has_bits) { + LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type); if (want_runtime_safety && sentinel != nullptr) { LLVMValueRef indices[] = { LLVMConstNull(g->builtin_types.entry_usize->llvm_type), end_val, }; - LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); + LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, + array_llvm_ty, array_ptr, indices, 2, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } @@ -6604,7 +6742,7 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air LLVMConstNull(g->builtin_types.entry_usize->llvm_type), start_val, }; - slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indices, 2, ""); + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, indices, 2, ""); } len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, ""); @@ -6623,27 +6761,30 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (value_has_bits) { + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, array_type->data.pointer.child_type); if (want_runtime_safety && sentinel != nullptr) { - LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &end_val, 1, ""); + LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, + array_ptr, &end_val, 1, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } - slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, &start_val, 1, ""); + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, array_ptr, + &start_val, 1, ""); } len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, ""); } else if (array_type->id == ZigTypeIdStruct) { assert(array_type->data.structure.special == StructSpecialSlice); assert(LLVMGetTypeKind(LLVMTypeOf(array_ptr)) == LLVMPointerTypeKind); - assert(LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(array_ptr))) == LLVMStructTypeKind); const size_t gen_len_index = array_type->data.structure.fields[slice_len_index]->gen_index; assert(gen_len_index != SIZE_MAX); LLVMValueRef prev_end = nullptr; if (!instruction->end || want_runtime_safety) { - LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, array_ptr, gen_len_index, ""); - prev_end = gen_load_untyped(g, src_len_ptr, 0, false, ""); + LLVMValueRef src_len_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, array_type), array_ptr, gen_len_index, ""); + prev_end = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(src_len_ptr), src_len_ptr, 0, false, ""); } LLVMValueRef start_val = ir_llvm_value(g, instruction->start); @@ -6682,18 +6823,22 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air codegen_report_errors_and_exit(g); if (ptr_has_bits) { + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, ptr_field_type->data.pointer.child_type); const size_t gen_ptr_index = array_type->data.structure.fields[slice_ptr_index]->gen_index; assert(gen_ptr_index != SIZE_MAX); - LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, array_ptr, gen_ptr_index, ""); - LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); + LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, array_type), array_ptr, gen_ptr_index, ""); + LLVMValueRef src_ptr = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(src_ptr_ptr), + src_ptr_ptr, 0, false, ""); if (sentinel != nullptr) { - LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &end_val, 1, ""); + LLVMValueRef sentinel_elem_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, + src_ptr, &end_val, 1, ""); add_sentinel_check(g, sentinel_elem_ptr, sentinel); } - slice_start_ptr = LLVMBuildInBoundsGEP(g->builder, src_ptr, &start_val, 1, ""); + slice_start_ptr = LLVMBuildInBoundsGEP2(g->builder, elem_llvm_ty, src_ptr, &start_val, 1, ""); } len_value = LLVMBuildNUWSub(g->builder, end_val, start_val, ""); @@ -6735,7 +6880,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air // The slice may not have a pointer at all if it points to a zero-sized type const size_t gen_ptr_index = result_type->data.structure.fields[slice_ptr_index]->gen_index; if (gen_ptr_index != SIZE_MAX) { - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_ptr_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, result_type), tmp_struct_ptr, gen_ptr_index, ""); if (slice_start_ptr != nullptr) { gen_store_untyped(g, slice_start_ptr, ptr_field_ptr, 0, false); } else if (want_runtime_safety) { @@ -6748,7 +6894,8 @@ static LLVMValueRef ir_render_slice(CodeGen *g, Stage1Air *executable, Stage1Air const size_t gen_len_index = result_type->data.structure.fields[slice_len_index]->gen_index; assert(gen_len_index != SIZE_MAX); - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, tmp_struct_ptr, gen_len_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, result_type), tmp_struct_ptr, gen_len_index, ""); gen_store_untyped(g, len_value, len_field_ptr, 0, false); return tmp_struct_ptr; @@ -6767,7 +6914,7 @@ static LLVMValueRef get_trap_fn_val(CodeGen *g) { static LLVMValueRef ir_render_breakpoint(CodeGen *g, Stage1Air *executable, Stage1AirInstBreakpoint *instruction) { - LLVMBuildCall(g->builder, get_trap_fn_val(g), nullptr, 0, ""); + LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_trap_fn_val(g)), get_trap_fn_val(g), nullptr, 0, ""); return nullptr; } @@ -6781,7 +6928,7 @@ static LLVMValueRef ir_render_return_address(CodeGen *g, Stage1Air *executable, } LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_return_address_fn_val(g), &zero, 1, ""); + LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_return_address_fn_val(g)), get_return_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } @@ -6793,7 +6940,7 @@ static LLVMValueRef get_frame_address_fn_val(CodeGen *g) { LLVMTypeRef fn_type = LLVMFunctionType(get_llvm_type(g, return_type), &g->builtin_types.entry_i32->llvm_type, 1, false); - g->frame_address_fn_val = LLVMAddFunction(g->module, "llvm.frameaddress.p0i8", fn_type); + g->frame_address_fn_val = LLVMAddFunction(g->module, "llvm.frameaddress.p0", fn_type); assert(LLVMGetIntrinsicID(g->frame_address_fn_val)); return g->frame_address_fn_val; @@ -6803,7 +6950,7 @@ static LLVMValueRef ir_render_frame_address(CodeGen *g, Stage1Air *executable, Stage1AirInstFrameAddress *instruction) { LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_i32->llvm_type); - LLVMValueRef ptr_val = LLVMBuildCall(g->builder, get_frame_address_fn_val(g), &zero, 1, ""); + LLVMValueRef ptr_val = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(get_frame_address_fn_val(g)), get_frame_address_fn_val(g), &zero, 1, ""); return LLVMBuildPtrToInt(g->builder, ptr_val, g->builtin_types.entry_usize->llvm_type, ""); } @@ -6866,7 +7013,7 @@ static LLVMValueRef ir_render_overflow_op(CodeGen *g, Stage1Air *executable, Sta op2, }; - LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); + LLVMValueRef result_struct = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, params, 2, ""); LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); gen_store(g, result, ptr_result, instruction->result_ptr->value->type); @@ -6881,8 +7028,9 @@ static LLVMValueRef ir_render_test_err(CodeGen *g, Stage1Air *executable, Stage1 LLVMValueRef err_val; if (type_has_bits(g, payload_type)) { - LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); - err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); + LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, err_union_type), err_union_handle, err_union_err_index, ""); + err_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(err_val_ptr), err_val_ptr, 0, false, ""); } else { err_val = err_union_handle; } @@ -6907,7 +7055,8 @@ static LLVMValueRef ir_render_unwrap_err_code(CodeGen *g, Stage1Air *executable, } else { // TODO assign undef to the payload LLVMValueRef err_union_handle = get_handle_value(g, err_union_ptr, err_union_type, ptr_type); - return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); + return LLVMBuildStructGEP2(g->builder, get_llvm_type(g, err_union_type), err_union_handle, + err_union_err_index, ""); } } @@ -6946,11 +7095,14 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executab return err_union_handle; } + LLVMTypeRef err_union_llvm_ty = get_llvm_type(g, err_union_type); + if (want_safety) { LLVMValueRef err_val; if (type_has_bits(g, payload_type)) { - LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); - err_val = gen_load_untyped(g, err_val_ptr, 0, false, ""); + LLVMValueRef err_val_ptr = LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, + err_union_handle, err_union_err_index, ""); + err_val = gen_load_untyped(g, ZigLLVMGetGEPResultElementType(err_val_ptr), err_val_ptr, 0, false, ""); } else { err_val = err_union_handle; } @@ -6967,11 +7119,13 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, Stage1Air *executab if (type_has_bits(g, payload_type)) { if (instruction->initializing) { - LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, err_union_handle, err_union_err_index, ""); + LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, + err_union_handle, err_union_err_index, ""); LLVMValueRef ok_err_val = LLVMConstNull(get_llvm_type(g, g->err_tag_type)); gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false); } - return LLVMBuildStructGEP(g->builder, err_union_handle, err_union_payload_index, ""); + return LLVMBuildStructGEP2(g->builder, err_union_llvm_ty, err_union_handle, + err_union_payload_index, ""); } else { if (instruction->initializing) { gen_store_untyped(g, zero, err_union_ptr, 0, false); @@ -7006,11 +7160,14 @@ static LLVMValueRef ir_render_optional_wrap(CodeGen *g, Stage1Air *executable, S } LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); + LLVMTypeRef result_llvm_struct_ty = get_llvm_type(g, wanted_type); - LLVMValueRef val_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_child_index, ""); + LLVMValueRef val_ptr = LLVMBuildStructGEP2(g->builder, result_llvm_struct_ty, result_loc, + maybe_child_index, ""); // child_type and instruction->value->value->type may differ by constness gen_assign_raw(g, val_ptr, get_pointer_to_type(g, child_type, false), payload_val); - LLVMValueRef maybe_ptr = LLVMBuildStructGEP(g->builder, result_loc, maybe_null_index, ""); + LLVMValueRef maybe_ptr = LLVMBuildStructGEP2(g->builder, result_llvm_struct_ty, result_loc, + maybe_null_index, ""); gen_store_untyped(g, LLVMConstAllOnes(LLVMInt1Type()), maybe_ptr, 0, false); return result_loc; @@ -7028,7 +7185,8 @@ static LLVMValueRef ir_render_err_wrap_code(CodeGen *g, Stage1Air *executable, S LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); - LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, ""); + LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, get_llvm_type(g, wanted_type), + result_loc, err_union_err_index, ""); gen_store_untyped(g, err_val, err_tag_ptr, 0, false); // TODO store undef to the payload @@ -7057,11 +7215,14 @@ static LLVMValueRef ir_render_err_wrap_payload(CodeGen *g, Stage1Air *executable LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); LLVMValueRef payload_val = ir_llvm_value(g, instruction->operand); + LLVMTypeRef result_struct_llvm_ty = get_llvm_type(g, wanted_type); - LLVMValueRef err_tag_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_err_index, ""); + LLVMValueRef err_tag_ptr = LLVMBuildStructGEP2(g->builder, result_struct_llvm_ty, result_loc, + err_union_err_index, ""); gen_store_untyped(g, ok_err_val, err_tag_ptr, 0, false); - LLVMValueRef payload_ptr = LLVMBuildStructGEP(g->builder, result_loc, err_union_payload_index, ""); + LLVMValueRef payload_ptr = LLVMBuildStructGEP2(g->builder, result_struct_llvm_ty, result_loc, + err_union_payload_index, ""); gen_assign_raw(g, payload_ptr, get_pointer_to_type(g, payload_type, false), payload_val); return result_loc; @@ -7079,7 +7240,8 @@ static LLVMValueRef ir_render_union_tag(CodeGen *g, Stage1Air *executable, Stage return union_val; assert(union_type->data.unionation.gen_tag_index != SIZE_MAX); - LLVMValueRef tag_field_ptr = LLVMBuildStructGEP(g->builder, union_val, + LLVMValueRef tag_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, union_type), union_val, union_type->data.unionation.gen_tag_index, ""); ZigType *ptr_type = get_pointer_to_type(g, tag_type, false); return get_handle_value(g, tag_field_ptr, tag_type, ptr_type); @@ -7154,9 +7316,10 @@ static LLVMValueRef ir_render_atomic_load(CodeGen *g, Stage1Air *executable, LLVMTypeRef actual_abi_type = get_atomic_abi_type(g, instruction->ptr, false); if (actual_abi_type != nullptr) { // operand needs widening and truncating - ptr = LLVMBuildBitCast(g->builder, ptr, - LLVMPointerType(actual_abi_type, 0), ""); - LLVMValueRef load_inst = gen_load(g, ptr, instruction->ptr->value->type, ""); + ptr = LLVMBuildBitCast(g->builder, ptr, LLVMPointerType(actual_abi_type, 0), ""); + LLVMValueRef load_inst = gen_load_untyped(g, actual_abi_type, ptr, + get_ptr_align(g, instruction->ptr->value->type), + instruction->ptr->value->type->data.pointer.is_volatile, ""); LLVMSetOrdering(load_inst, ordering); return LLVMBuildTrunc(g->builder, load_inst, get_llvm_type(g, operand_type), ""); } @@ -7221,14 +7384,12 @@ static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, St LLVMValueRef op1 = ir_llvm_value(g, instruction->op1); LLVMValueRef op2 = ir_llvm_value(g, instruction->op2); LLVMValueRef op3 = ir_llvm_value(g, instruction->op3); - LLVMValueRef result; if (vector_len == 0) { LLVMValueRef params[3] = { op1, op2, op3 }; - result = LLVMBuildCall(g->builder, func_ref, params, 3, ""); - } else { - result = build_alloca(g, instruction->op1->value->type, "", 0); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, 3, ""); } + LLVMValueRef result = LLVMGetUndef(get_llvm_type(g, instruction->op1->value->type)); LLVMTypeRef usize_ref = g->builtin_types.entry_usize->llvm_type; for (uint32_t i = 0; i < vector_len; i++) { LLVMValueRef index_value = LLVMConstInt(usize_ref, i, false); @@ -7238,12 +7399,8 @@ static LLVMValueRef ir_render_soft_mul_add(CodeGen *g, Stage1Air *executable, St LLVMBuildExtractElement(g->builder, op2, index_value, ""), LLVMBuildExtractElement(g->builder, op3, index_value, ""), }; - LLVMValueRef call_result = LLVMBuildCall(g->builder, func_ref, params, 3, ""); - LLVMBuildInsertElement(g->builder, LLVMBuildLoad(g->builder, result, ""), - call_result, index_value, ""); - } - if (vector_len != 0) { - result = LLVMBuildLoad(g->builder, result, ""); + LLVMValueRef call_result = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(func_ref), func_ref, params, 3, ""); + result = LLVMBuildInsertElement(g->builder, result, call_result, index_value, ""); } return result; } @@ -7262,7 +7419,7 @@ static LLVMValueRef ir_render_mul_add(CodeGen *g, Stage1Air *executable, Stage1A instruction->base.value->type->id == ZigTypeIdVector); LLVMValueRef fn_val = get_float_fn(g, instruction->base.value->type, ZigLLVMFnIdFMA, BuiltinFnIdMulAdd); LLVMValueRef args[3] = { op1, op2, op3 }; - return LLVMBuildCall(g->builder, fn_val, args, 3, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, args, 3, ""); } static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1AirInstBswap *instruction) { @@ -7273,7 +7430,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1Air assert(int_type->id == ZigTypeIdInt); if (int_type->data.integral.bit_count % 16 == 0) { LLVMValueRef fn_val = get_int_builtin_fn(g, expr_type, BuiltinFnIdBswap); - return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &op, 1, ""); } // Not an even number of bytes, so we zext 1 byte, then bswap, shift right 1 byte, truncate ZigType *extended_type = get_int_type(g, int_type->data.integral.is_signed, @@ -7292,7 +7449,7 @@ static LLVMValueRef ir_render_bswap(CodeGen *g, Stage1Air *executable, Stage1Air LLVMValueRef extended = LLVMBuildZExt(g->builder, op, get_llvm_type(g, extended_type), ""); // 00aabbcc LLVMValueRef fn_val = get_int_builtin_fn(g, extended_type, BuiltinFnIdBswap); - LLVMValueRef swapped = LLVMBuildCall(g->builder, fn_val, &extended, 1, ""); + LLVMValueRef swapped = LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &extended, 1, ""); // ccbbaa00 LLVMValueRef shifted = ZigLLVMBuildLShrExact(g->builder, swapped, shift_amt, ""); // 00ccbbaa @@ -7328,7 +7485,7 @@ static LLVMValueRef ir_render_bit_reverse(CodeGen *g, Stage1Air *executable, Sta ZigType *int_type = instruction->base.value->type; assert(int_type->id == ZigTypeIdInt); LLVMValueRef fn_val = get_int_builtin_fn(g, instruction->base.value->type, BuiltinFnIdBitReverse); - return LLVMBuildCall(g->builder, fn_val, &op, 1, ""); + return LLVMBuildCall2(g->builder, LLVMGlobalGetValueType(fn_val), fn_val, &op, 1, ""); } static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, @@ -7353,11 +7510,12 @@ static LLVMValueRef ir_render_vector_to_array(CodeGen *g, Stage1Air *executable, LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMTypeRef u32_type_ref = LLVMInt32Type(); LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false); + LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type); for (uintptr_t i = 0; i < instruction->vector->value->type->data.vector.len; i++) { LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false); LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false); LLVMValueRef indexes[] = { zero, index_usize }; - LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, result_loc, indexes, 2, ""); + LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, result_loc, indexes, 2, ""); LLVMValueRef elem = LLVMBuildExtractElement(g->builder, vector, index_u32, ""); LLVMBuildStore(g->builder, elem, elem_ptr); } @@ -7376,13 +7534,13 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, Stage1Air *executable, ZigType *elem_type = vector_type->data.vector.elem_type; bool bitcast_ok = elem_type->size_in_bits == elem_type->abi_size * 8; + ZigType *array_type = instruction->array->value->type; + ir_assert(array_type->id == ZigTypeIdArray, &instruction->base); if (bitcast_ok) { LLVMValueRef casted_ptr = LLVMBuildBitCast(g->builder, array_ptr, LLVMPointerType(vector_type_ref, 0), ""); - ZigType *array_type = instruction->array->value->type; - assert(array_type->id == ZigTypeIdArray); uint32_t alignment = get_abi_alignment(g, array_type->data.array.child_type); - return gen_load_untyped(g, casted_ptr, alignment, false, ""); + return gen_load_untyped(g, vector_type_ref, casted_ptr, alignment, false, ""); } else { // If the ABI size of the element type is not evenly divisible by size_in_bits, a simple bitcast // will not work, and we fall back to insertelement. @@ -7390,12 +7548,15 @@ static LLVMValueRef ir_render_array_to_vector(CodeGen *g, Stage1Air *executable, LLVMTypeRef u32_type_ref = LLVMInt32Type(); LLVMValueRef zero = LLVMConstInt(usize_type_ref, 0, false); LLVMValueRef vector = LLVMGetUndef(vector_type_ref); + LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_type); + LLVMTypeRef elem_llvm_ty = get_llvm_type(g, elem_type); for (uintptr_t i = 0; i < instruction->base.value->type->data.vector.len; i++) { LLVMValueRef index_usize = LLVMConstInt(usize_type_ref, i, false); LLVMValueRef index_u32 = LLVMConstInt(u32_type_ref, i, false); LLVMValueRef indexes[] = { zero, index_usize }; - LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP(g->builder, array_ptr, indexes, 2, ""); - LLVMValueRef elem = LLVMBuildLoad(g->builder, elem_ptr, ""); + LLVMValueRef elem_ptr = LLVMBuildInBoundsGEP2(g->builder, array_llvm_ty, array_ptr, + indexes, 2, ""); + LLVMValueRef elem = LLVMBuildLoad2(g->builder, elem_llvm_ty, elem_ptr, ""); vector = LLVMBuildInsertElement(g->builder, vector, elem, index_u32, ""); } return vector; @@ -7461,14 +7622,16 @@ static LLVMValueRef ir_render_suspend_finish(CodeGen *g, Stage1Air *executable, } static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_instr, - LLVMValueRef target_frame_ptr, ZigType *result_type, ZigType *ptr_result_type, - LLVMValueRef result_loc, bool non_async) + LLVMTypeRef target_frame_struct_llvm_ty, LLVMValueRef target_frame_ptr, + ZigType *result_type, ZigType *ptr_result_type, LLVMValueRef result_loc, bool non_async) { LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef their_result_ptr = nullptr; if (type_has_bits(g, result_type) && (non_async || result_loc != nullptr)) { - LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start, ""); - their_result_ptr = LLVMBuildLoad(g->builder, their_result_ptr_ptr, ""); + LLVMValueRef their_result_ptr_ptr = LLVMBuildStructGEP2(g->builder, + target_frame_struct_llvm_ty, target_frame_ptr, frame_ret_start, ""); + their_result_ptr = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(their_result_ptr_ptr), their_result_ptr_ptr, ""); if (result_loc != nullptr) { LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); LLVMValueRef dest_ptr_casted = LLVMBuildBitCast(g->builder, result_loc, ptr_u8, ""); @@ -7482,13 +7645,16 @@ static LLVMValueRef gen_await_early_return(CodeGen *g, Stage1AirInst *source_ins } } if (codegen_fn_has_err_ret_tracing_arg(g, result_type)) { - LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, + LLVMValueRef their_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, + target_frame_struct_llvm_ty, target_frame_ptr, frame_index_trace_arg(g, result_type), ""); - LLVMValueRef src_trace_ptr = LLVMBuildLoad(g->builder, their_trace_ptr_ptr, ""); + LLVMValueRef src_trace_ptr = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(their_trace_ptr_ptr), their_trace_ptr_ptr, ""); bool is_llvm_alloca; LLVMValueRef dest_trace_ptr = get_cur_err_ret_trace_val(g, source_instr->scope, &is_llvm_alloca); LLVMValueRef args[] = { dest_trace_ptr, src_trace_ptr }; - ZigLLVMBuildCall(g->builder, get_merge_err_ret_traces_fn_val(g), args, 2, + ZigLLVMBuildCall(g->builder, LLVMGlobalGetValueType(get_merge_err_ret_traces_fn_val(g)), + get_merge_err_ret_traces_fn_val(g), args, 2, get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_CallAttrAuto, ""); } if (non_async && type_has_bits(g, result_type)) { @@ -7503,6 +7669,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef zero = LLVMConstNull(usize_type_ref); LLVMValueRef target_frame_ptr = ir_llvm_value(g, instruction->frame); + ir_assert(instruction->frame->value->type->id == ZigTypeIdAnyFrame, &instruction->base); + LLVMTypeRef target_frame_llvm_ty = instruction->frame->value->type->data.any_frame.struct_llvm_ty; ZigType *result_type = instruction->base.value->type; ZigType *ptr_result_type = get_pointer_to_type(g, result_type, true); @@ -7512,8 +7680,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air if (instruction->is_nosuspend || (instruction->target_fn != nullptr && !fn_is_async(instruction->target_fn))) { - return gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type, - ptr_result_type, result_loc, true); + return gen_await_early_return(g, &instruction->base, target_frame_llvm_ty, + target_frame_ptr, result_type, ptr_result_type, result_loc, true); } // Prepare to be suspended @@ -7525,10 +7693,11 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air // supply the awaiter return pointer if (type_has_bits(g, result_type)) { - LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_ret_start + 1, ""); + LLVMValueRef awaiter_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty, + target_frame_ptr, frame_ret_start + 1, ""); if (result_loc == nullptr) { // no copy needed - LLVMBuildStore(g->builder, LLVMConstNull(LLVMGetElementType(LLVMTypeOf(awaiter_ret_ptr_ptr))), + LLVMBuildStore(g->builder, LLVMConstNull(ZigLLVMGetGEPResultElementType(awaiter_ret_ptr_ptr)), awaiter_ret_ptr_ptr); } else { LLVMBuildStore(g->builder, result_loc, awaiter_ret_ptr_ptr); @@ -7540,14 +7709,15 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air bool is_llvm_alloca; LLVMValueRef my_err_ret_trace_val = get_cur_err_ret_trace_val(g, instruction->base.scope, &is_llvm_alloca); assert(my_err_ret_trace_val != nullptr); - LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, - frame_index_trace_arg(g, result_type) + 1, ""); + LLVMValueRef err_ret_trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty, + target_frame_ptr, frame_index_trace_arg(g, result_type) + 1, ""); LLVMBuildStore(g->builder, my_err_ret_trace_val, err_ret_trace_ptr_ptr); } // caller's own frame pointer LLVMValueRef awaiter_init_val = LLVMBuildPtrToInt(g->builder, g->cur_frame_ptr, usize_type_ref, ""); - LLVMValueRef awaiter_ptr = LLVMBuildStructGEP(g->builder, target_frame_ptr, frame_awaiter_index, ""); + LLVMValueRef awaiter_ptr = LLVMBuildStructGEP2(g->builder, target_frame_llvm_ty, + target_frame_ptr, frame_awaiter_index, ""); LLVMValueRef prev_val = gen_maybe_atomic_op(g, LLVMAtomicRMWBinOpXchg, awaiter_ptr, awaiter_init_val, LLVMAtomicOrderingRelease); @@ -7572,8 +7742,8 @@ static LLVMValueRef ir_render_await(CodeGen *g, Stage1Air *executable, Stage1Air // Early return: The async function has already completed. We must copy the result and // the error return trace if applicable. LLVMPositionBuilderAtEnd(g->builder, early_return_block); - gen_await_early_return(g, &instruction->base, target_frame_ptr, result_type, ptr_result_type, - result_loc, false); + gen_await_early_return(g, &instruction->base, target_frame_llvm_ty, target_frame_ptr, + result_type, ptr_result_type, result_loc, false); LLVMBuildBr(g->builder, end_bb); LLVMPositionBuilderAtEnd(g->builder, resume_bb); @@ -7591,7 +7761,7 @@ static LLVMValueRef ir_render_resume(CodeGen *g, Stage1Air *executable, Stage1Ai ZigType *frame_type = instruction->frame->value->type; assert(frame_type->id == ZigTypeIdAnyFrame); - gen_resume(g, nullptr, frame, ResumeIdManual); + gen_resume(g, g->anyframe_fn_type, nullptr, frame, ResumeIdManual); return nullptr; } @@ -7631,7 +7801,8 @@ static LLVMValueRef ir_render_spill_end(CodeGen *g, Stage1Air *executable, Stage zig_unreachable(); case SpillIdRetErrCode: { LLVMValueRef ptr = ir_llvm_value(g, g->cur_fn->err_code_spill); - return LLVMBuildLoad(g->builder, ptr, ""); + LLVMTypeRef llvm_ty = g->builtin_types.entry_global_error_set->llvm_type; + return LLVMBuildLoad2(g->builder, llvm_ty, ptr, ""); } } @@ -7923,43 +8094,33 @@ static LLVMValueRef gen_const_ptr_array_recursive(CodeGen *g, ZigValue *array_co ConstParent *parent = &array_const_val->parent; LLVMValueRef base_ptr = gen_parent_ptr(g, array_const_val, parent); - LLVMTypeKind el_type = LLVMGetTypeKind(LLVMGetElementType(LLVMTypeOf(base_ptr))); - if (el_type == LLVMArrayTypeKind) { - ZigType *usize = g->builtin_types.entry_usize; - LLVMValueRef indices[] = { - LLVMConstNull(usize->llvm_type), - LLVMConstInt(usize->llvm_type, index, false), - }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); - } else if (el_type == LLVMStructTypeKind) { - ZigType *u32 = g->builtin_types.entry_u32; - LLVMValueRef indices[] = { - LLVMConstNull(get_llvm_type(g, u32)), - LLVMConstInt(get_llvm_type(g, u32), index, false), - }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); - } else { - return base_ptr; - } + ZigType *usize = g->builtin_types.entry_usize; + LLVMTypeRef array_llvm_ty = get_llvm_type(g, array_const_val->type); + LLVMValueRef casted_base_ptr = LLVMConstBitCast(base_ptr, LLVMPointerType(array_llvm_ty, 0)); + LLVMValueRef indices[] = { + LLVMConstNull(usize->llvm_type), + LLVMConstInt(usize->llvm_type, index, false), + }; + return LLVMConstInBoundsGEP2(array_llvm_ty, casted_base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_struct_recursive(CodeGen *g, ZigValue *struct_const_val, size_t field_index) { ConstParent *parent = &struct_const_val->parent; LLVMValueRef base_ptr = gen_parent_ptr(g, struct_const_val, parent); - ZigType *u32 = g->builtin_types.entry_u32; LLVMValueRef indices[] = { - LLVMConstNull(get_llvm_type(g, u32)), - LLVMConstInt(get_llvm_type(g, u32), field_index, false), + LLVMConstNull(LLVMInt32Type()), + LLVMConstInt(LLVMInt32Type(), field_index, false), }; // The structure pointed by base_ptr may include trailing padding for // alignment purposes and have the following LLVM type: <{ %T, [N x i8] }>. // Add an extra bitcast as we're only interested in the %T part. assert(handle_is_ptr(g, struct_const_val->type)); - LLVMValueRef casted_base_ptr = LLVMConstBitCast(base_ptr, - LLVMPointerType(get_llvm_type(g, struct_const_val->type), 0)); - return LLVMConstInBoundsGEP(casted_base_ptr, indices, 2); + + LLVMTypeRef struct_llvm_ty = get_llvm_type(g, struct_const_val->type); + LLVMValueRef casted_base_ptr = LLVMConstBitCast(base_ptr, LLVMPointerType(struct_llvm_ty, 0)); + return LLVMConstInBoundsGEP2(struct_llvm_ty, casted_base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue *err_union_const_val) { @@ -7971,7 +8132,7 @@ static LLVMValueRef gen_const_ptr_err_union_code_recursive(CodeGen *g, ZigValue LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), err_union_err_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); + return LLVMConstInBoundsGEP2(get_llvm_type(g, err_union_const_val->type), base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ZigValue *err_union_const_val) { @@ -7983,7 +8144,7 @@ static LLVMValueRef gen_const_ptr_err_union_payload_recursive(CodeGen *g, ZigVal LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), err_union_payload_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); + return LLVMConstInBoundsGEP2(get_llvm_type(g, err_union_const_val->type), base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ZigValue *optional_const_val) { @@ -7995,7 +8156,7 @@ static LLVMValueRef gen_const_ptr_optional_payload_recursive(CodeGen *g, ZigValu LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), maybe_child_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, 2); + return LLVMConstInBoundsGEP2(get_llvm_type(g, optional_const_val->type), base_ptr, indices, 2); } static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ZigValue *union_const_val) { @@ -8012,7 +8173,7 @@ static LLVMValueRef gen_const_ptr_union_recursive(CodeGen *g, ZigValue *union_co LLVMConstNull(get_llvm_type(g, u32)), LLVMConstInt(get_llvm_type(g, u32), union_payload_index, false), }; - return LLVMConstInBoundsGEP(base_ptr, indices, (union_payload_index != SIZE_MAX) ? 2 : 1); + return LLVMConstInBoundsGEP2(get_llvm_type(g, union_const_val->type), base_ptr, indices, (union_payload_index != SIZE_MAX) ? 2 : 1); } static LLVMValueRef pack_const_int(CodeGen *g, LLVMTypeRef big_int_type_ref, ZigValue *const_val) { @@ -9206,28 +9367,38 @@ static void do_code_gen(CodeGen *g) { } } + LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; + // finishing error return trace setup. we have to do this after all the allocas. if (have_err_ret_trace_stack) { ZigType *usize = g->builtin_types.entry_usize; size_t index_field_index = g->stack_trace_type->data.structure.fields[0]->gen_index; - LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, ""); + LLVMValueRef index_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), + g->cur_err_ret_trace_val_stack, (unsigned)index_field_index, ""); gen_store_untyped(g, LLVMConstNull(usize->llvm_type), index_field_ptr, 0, false); size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1]->gen_index; - LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, ""); + LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, g->stack_trace_type), + g->cur_err_ret_trace_val_stack, (unsigned)addresses_field_index, ""); ZigType *slice_type = g->stack_trace_type->data.structure.fields[1]->type_entry; size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index]->gen_index; - LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); + LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(addresses_field_ptr), + addresses_field_ptr, (unsigned)ptr_field_index, ""); LLVMValueRef zero = LLVMConstNull(usize->llvm_type); LLVMValueRef indices[] = {zero, zero}; - LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP(g->builder, err_ret_array_val, - indices, 2, ""); + LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP2(g->builder, + LLVMGetAllocatedType(err_ret_array_val), err_ret_array_val, indices, 2, ""); ZigType *ptr_ptr_usize_type = get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false); gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, ptr_ptr_usize_type); size_t len_field_index = slice_type->data.structure.fields[slice_len_index]->gen_index; - LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); + LLVMValueRef len_field_ptr = LLVMBuildStructGEP2(g->builder, + ZigLLVMGetGEPResultElementType(addresses_field_ptr), + addresses_field_ptr, (unsigned)len_field_index, ""); gen_store(g, LLVMConstInt(usize->llvm_type, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); } @@ -9235,7 +9406,6 @@ static void do_code_gen(CodeGen *g) { (void)get_llvm_type(g, fn_table_entry->frame_type); g->cur_resume_block_count = 0; - LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type; LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false); if (g->need_frame_size_prefix_data) { ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val); @@ -9254,22 +9424,31 @@ static void do_code_gen(CodeGen *g) { LLVMPositionBuilderAtEnd(g->builder, g->cur_preamble_llvm_block); render_async_spills(g); - g->cur_async_awaiter_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_awaiter_index, ""); - LLVMValueRef resume_index_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_resume_index, ""); + g->cur_async_awaiter_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_awaiter_index, ""); + LLVMValueRef resume_index_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_resume_index, ""); g->cur_async_resume_index_ptr = resume_index_ptr; if (type_has_bits(g, fn_type_id->return_type)) { - LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, frame_ret_start, ""); - g->cur_ret_ptr = LLVMBuildLoad(g->builder, cur_ret_ptr_ptr, ""); + LLVMValueRef cur_ret_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_ret_start, ""); + g->cur_ret_ptr = LLVMBuildLoad2(g->builder, + ZigLLVMGetGEPResultElementType(cur_ret_ptr_ptr), cur_ret_ptr_ptr, ""); } uint32_t trace_field_index_stack = UINT32_MAX; if (codegen_fn_has_err_ret_tracing_stack(g, fn_table_entry, true)) { trace_field_index_stack = frame_index_trace_stack(g, fn_table_entry); - g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, + g->cur_err_ret_trace_val_stack = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, trace_field_index_stack, ""); } - LLVMValueRef resume_index = LLVMBuildLoad(g->builder, resume_index_ptr, ""); + LLVMValueRef resume_index = LLVMBuildLoad2(g->builder, usize_type_ref, resume_index_ptr, ""); LLVMValueRef switch_instr = LLVMBuildSwitch(g->builder, resume_index, bad_resume_block, 4); g->cur_async_switch_instr = switch_instr; @@ -9293,15 +9472,21 @@ static void do_code_gen(CodeGen *g) { LLVMBuildStore(g->builder, g->cur_bad_not_suspended_index, g->cur_async_resume_index_ptr); if (trace_field_index_stack != UINT32_MAX) { if (codegen_fn_has_err_ret_tracing_arg(g, fn_type_id->return_type)) { - LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, + LLVMValueRef trace_ptr_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, frame_index_trace_arg(g, fn_type_id->return_type), ""); - LLVMValueRef zero_ptr = LLVMConstNull(LLVMGetElementType(LLVMTypeOf(trace_ptr_ptr))); + LLVMValueRef zero_ptr = LLVMConstNull(ZigLLVMGetGEPResultElementType(trace_ptr_ptr)); LLVMBuildStore(g->builder, zero_ptr, trace_ptr_ptr); } - LLVMValueRef trace_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, + LLVMValueRef trace_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, trace_field_index_stack, ""); - LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_frame_ptr, + LLVMValueRef addrs_field_ptr = LLVMBuildStructGEP2(g->builder, + get_llvm_type(g, get_fn_frame_type(g, g->cur_fn)), + g->cur_frame_ptr, trace_field_index_stack + 1, ""); gen_init_stack_trace(g, trace_field_ptr, addrs_field_ptr); diff --git a/src/stage1/stage1.h b/src/stage1/stage1.h index 26b36db879..c8af8b9688 100644 --- a/src/stage1/stage1.h +++ b/src/stage1/stage1.h @@ -83,9 +83,11 @@ enum Os { OsNVCL, // NVIDIA OpenCL OsAMDHSA, // AMD HSA Runtime OsPS4, + OsPS5, OsELFIAMCU, OsTvOS, // Apple tvOS OsWatchOS, // Apple watchOS + OsDriverKit, // Apple DriverKit OsMesa3D, OsContiki, OsAMDPAL, @@ -93,6 +95,7 @@ enum Os { OsHurd, OsWASI, OsEmscripten, + OsShaderModel, // DirectX ShaderModel OsUefi, OsOpenCL, OsGLSL450, diff --git a/src/stage1/target.cpp b/src/stage1/target.cpp index 7c4587cdaa..3031b7e588 100644 --- a/src/stage1/target.cpp +++ b/src/stage1/target.cpp @@ -24,7 +24,10 @@ static const ZigLLVM_ArchType arch_list[] = { ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) ZigLLVM_csky, // CSKY: csky + ZigLLVM_dxil, // DXIL 32-bit DirectX bytecode ZigLLVM_hexagon, // Hexagon: hexagon + ZigLLVM_loongarch32, // LoongArch (32-bit): loongarch32 + ZigLLVM_loongarch64, // LoongArch (64-bit): loongarch64 ZigLLVM_m68k, // M68k: Motorola 680x0 family ZigLLVM_mips, // MIPS: mips, mipsallegrex, mipsr6 ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el @@ -114,9 +117,11 @@ static const Os os_list[] = { OsNVCL, // NVIDIA OpenCL OsAMDHSA, // AMD HSA Runtime OsPS4, + OsPS5, OsELFIAMCU, OsTvOS, // Apple tvOS OsWatchOS, // Apple watchOS + OsDriverKit, // Apple DriverKit OsMesa3D, OsContiki, OsAMDPAL, @@ -124,6 +129,7 @@ static const Os os_list[] = { OsHurd, OsWASI, OsEmscripten, + OsShaderModel, // DirectX ShaderModel OsUefi, OsOpenCL, OsGLSL450, @@ -156,16 +162,34 @@ static const ZigLLVM_EnvironmentType abi_list[] = { ZigLLVM_Itanium, ZigLLVM_Cygnus, ZigLLVM_CoreCLR, - ZigLLVM_Simulator, - ZigLLVM_MacABI, + ZigLLVM_Simulator, // Simulator variants of other systems, e.g., Apple's iOS + ZigLLVM_MacABI, // Mac Catalyst variant of Apple's iOS deployment target. + + ZigLLVM_Pixel, + ZigLLVM_Vertex, + ZigLLVM_Geometry, + ZigLLVM_Hull, + ZigLLVM_Domain, + ZigLLVM_Compute, + ZigLLVM_Library, + ZigLLVM_RayGeneration, + ZigLLVM_Intersection, + ZigLLVM_AnyHit, + ZigLLVM_ClosestHit, + ZigLLVM_Miss, + ZigLLVM_Callable, + ZigLLVM_Mesh, + ZigLLVM_Amplification, }; static const ZigLLVM_ObjectFormatType oformat_list[] = { ZigLLVM_UnknownObjectFormat, ZigLLVM_COFF, + ZigLLVM_DXContainer, ZigLLVM_ELF, ZigLLVM_GOFF, ZigLLVM_MachO, + ZigLLVM_SPIRV, ZigLLVM_Wasm, ZigLLVM_XCOFF, }; @@ -183,9 +207,11 @@ const char *target_oformat_name(ZigLLVM_ObjectFormatType oformat) { switch (oformat) { case ZigLLVM_UnknownObjectFormat: return "unknown"; case ZigLLVM_COFF: return "coff"; + case ZigLLVM_DXContainer: return "dxcontainer"; case ZigLLVM_ELF: return "elf"; case ZigLLVM_GOFF: return "goff"; case ZigLLVM_MachO: return "macho"; + case ZigLLVM_SPIRV: return "spirv"; case ZigLLVM_Wasm: return "wasm"; case ZigLLVM_XCOFF: return "xcoff"; } @@ -276,12 +302,16 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) { return ZigLLVM_AMDHSA; case OsPS4: return ZigLLVM_PS4; + case OsPS5: + return ZigLLVM_PS5; case OsELFIAMCU: return ZigLLVM_ELFIAMCU; case OsTvOS: return ZigLLVM_TvOS; case OsWatchOS: return ZigLLVM_WatchOS; + case OsDriverKit: + return ZigLLVM_DriverKit; case OsMesa3D: return ZigLLVM_Mesa3D; case OsContiki: @@ -296,6 +326,8 @@ ZigLLVM_OSType get_llvm_os_type(Os os_type) { return ZigLLVM_WASI; case OsEmscripten: return ZigLLVM_Emscripten; + case OsShaderModel: + return ZigLLVM_ShaderModel; } zig_unreachable(); } @@ -334,9 +366,11 @@ const char *target_os_name(Os os_type) { case OsNVCL: // NVIDIA OpenCL case OsAMDHSA: // AMD HSA Runtime case OsPS4: + case OsPS5: case OsELFIAMCU: case OsTvOS: // Apple tvOS case OsWatchOS: // Apple watchOS + case OsDriverKit: case OsMesa3D: case OsContiki: case OsAMDPAL: @@ -344,6 +378,7 @@ const char *target_os_name(Os os_type) { case OsHurd: case OsWASI: case OsEmscripten: + case OsShaderModel: case OsOpenCL: case OsGLSL450: case OsVulkan: @@ -532,6 +567,8 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { case ZigLLVM_aarch64_32: case ZigLLVM_csky: case ZigLLVM_spirv32: + case ZigLLVM_loongarch32: + case ZigLLVM_dxil: return 32; case ZigLLVM_aarch64: @@ -556,6 +593,7 @@ uint32_t target_arch_pointer_bit_width(ZigLLVM_ArchType arch) { case ZigLLVM_renderscript64: case ZigLLVM_ve: case ZigLLVM_spirv64: + case ZigLLVM_loongarch64: return 64; } zig_unreachable(); @@ -601,6 +639,8 @@ uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) { case ZigLLVM_renderscript32: case ZigLLVM_csky: case ZigLLVM_spirv32: + case ZigLLVM_loongarch32: + case ZigLLVM_dxil: return 32; case ZigLLVM_aarch64: @@ -625,6 +665,7 @@ uint32_t target_arch_largest_atomic_bits(ZigLLVM_ArchType arch) { case ZigLLVM_renderscript64: case ZigLLVM_ve: case ZigLLVM_spirv64: + case ZigLLVM_loongarch64: return 64; case ZigLLVM_x86_64: @@ -751,6 +792,7 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case OsAIX: case OsAMDHSA: case OsPS4: + case OsPS5: case OsELFIAMCU: case OsTvOS: case OsWatchOS: @@ -763,6 +805,8 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { case OsOpenCL: case OsGLSL450: case OsVulkan: + case OsDriverKit: + case OsShaderModel: zig_panic("TODO c type size in bits for this target"); } zig_unreachable(); @@ -860,6 +904,9 @@ const char *arch_stack_pointer_register_name(ZigLLVM_ArchType arch) { case ZigLLVM_tcele: case ZigLLVM_xcore: case ZigLLVM_ve: + case ZigLLVM_dxil: + case ZigLLVM_loongarch32: + case ZigLLVM_loongarch64: zig_panic("TODO populate this table with stack pointer register name for this CPU architecture"); } zig_unreachable(); @@ -927,6 +974,9 @@ bool target_is_arm(const ZigTarget *target) { case ZigLLVM_ve: case ZigLLVM_spirv32: case ZigLLVM_spirv64: + case ZigLLVM_dxil: + case ZigLLVM_loongarch32: + case ZigLLVM_loongarch64: return false; } zig_unreachable(); @@ -973,6 +1023,7 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { case OsNVCL: case OsAMDHSA: case OsPS4: + case OsPS5: case OsELFIAMCU: case OsMesa3D: case OsContiki: @@ -1004,6 +1055,8 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { case OsIOS: case OsTvOS: case OsWatchOS: + case OsDriverKit: + case OsShaderModel: return ZigLLVM_UnknownEnvironment; } zig_unreachable(); diff --git a/src/stage1/zig0.cpp b/src/stage1/zig0.cpp index f248f6e866..ea0c397243 100644 --- a/src/stage1/zig0.cpp +++ b/src/stage1/zig0.cpp @@ -112,6 +112,8 @@ static Os get_zig_os_type(ZigLLVM_OSType os_type) { return OsAMDHSA; case ZigLLVM_PS4: return OsPS4; + case ZigLLVM_PS5: + return OsPS5; case ZigLLVM_ELFIAMCU: return OsELFIAMCU; case ZigLLVM_TvOS: @@ -132,6 +134,10 @@ static Os get_zig_os_type(ZigLLVM_OSType os_type) { return OsWASI; case ZigLLVM_Emscripten: return OsEmscripten; + case ZigLLVM_DriverKit: + return OsDriverKit; + case ZigLLVM_ShaderModel: + return OsShaderModel; } zig_unreachable(); } diff --git a/src/target.zig b/src/target.zig index f8b44bac0e..b7da04e548 100644 --- a/src/target.zig +++ b/src/target.zig @@ -106,6 +106,23 @@ pub fn libCGenericName(target: std.Target) [:0]const u8 { .simulator, .macabi, => unreachable, + + .pixel, + .vertex, + .geometry, + .hull, + .domain, + .compute, + .library, + .raygeneration, + .intersection, + .anyhit, + .closesthit, + .miss, + .callable, + .mesh, + .amplification, + => unreachable, } } @@ -218,6 +235,7 @@ pub fn hasLlvmSupport(target: std.Target, ofmt: std.Target.ObjectFormat) bool { .hex, .raw, .nvptx, + .dxcontainer, => {}, } @@ -232,7 +250,10 @@ pub fn hasLlvmSupport(target: std.Target, ofmt: std.Target.ObjectFormat) bool { .bpfel, .bpfeb, .csky, + .dxil, .hexagon, + .loongarch32, + .loongarch64, .m68k, .mips, .mipsel, @@ -535,6 +556,8 @@ pub fn atomicPtrAlignment( .renderscript32, .csky, .spirv32, + .dxil, + .loongarch32, => 32, .aarch64, @@ -559,6 +582,7 @@ pub fn atomicPtrAlignment( .renderscript64, .ve, .spirv64, + .loongarch64, => 64, .x86_64 => 128, diff --git a/src/type.zig b/src/type.zig index c72cf2be84..3e2e395d07 100644 --- a/src/type.zig +++ b/src/type.zig @@ -6280,6 +6280,11 @@ pub const Type = extern union { mutable: bool = true, // TODO rename this to const, not mutable @"volatile": bool = false, size: std.builtin.Type.Pointer.Size = .One, + + pub fn alignment(data: Data, target: Target) u32 { + if (data.@"align" != 0) return data.@"align"; + return abiAlignment(data.pointee_type, target); + } }; }; @@ -6696,6 +6701,7 @@ pub const CType = enum { .nvcl, .amdhsa, .ps4, + .ps5, .elfiamcu, .mesa3d, .contiki, @@ -6705,6 +6711,8 @@ pub const CType = enum { .opencl, .glsl450, .vulkan, + .driverkit, + .shadermodel, => @panic("TODO specify the C integer and float type sizes for this OS"), } } diff --git a/src/zig_clang.cpp b/src/zig_clang.cpp index 7b79f8e985..223dc29067 100644 --- a/src/zig_clang.cpp +++ b/src/zig_clang.cpp @@ -317,6 +317,7 @@ void ZigClang_detect_enum_TypeClass(clang::Type::TypeClass ty) { case clang::Type::Enum: case clang::Type::Elaborated: case clang::Type::Attributed: + case clang::Type::BTFTagAttributed: case clang::Type::BitInt: case clang::Type::TemplateTypeParm: case clang::Type::SubstTemplateTypeParm: @@ -346,6 +347,7 @@ static_assert((clang::Type::TypeClass)ZigClangType_IncompleteArray == clang::Typ static_assert((clang::Type::TypeClass)ZigClangType_VariableArray == clang::Type::VariableArray, ""); static_assert((clang::Type::TypeClass)ZigClangType_Atomic == clang::Type::Atomic, ""); static_assert((clang::Type::TypeClass)ZigClangType_Attributed == clang::Type::Attributed, ""); +static_assert((clang::Type::TypeClass)ZigClangType_BTFTagAttributed == clang::Type::BTFTagAttributed, ""); static_assert((clang::Type::TypeClass)ZigClangType_BitInt == clang::Type::BitInt, ""); static_assert((clang::Type::TypeClass)ZigClangType_BlockPointer == clang::Type::BlockPointer, ""); static_assert((clang::Type::TypeClass)ZigClangType_Builtin == clang::Type::Builtin, ""); @@ -432,25 +434,33 @@ void ZigClang_detect_enum_StmtClass(clang::Stmt::StmtClass x) { case clang::Stmt::OMPForDirectiveClass: case clang::Stmt::OMPForSimdDirectiveClass: case clang::Stmt::OMPGenericLoopDirectiveClass: + case clang::Stmt::OMPMaskedTaskLoopDirectiveClass: + case clang::Stmt::OMPMaskedTaskLoopSimdDirectiveClass: case clang::Stmt::OMPMasterTaskLoopDirectiveClass: case clang::Stmt::OMPMasterTaskLoopSimdDirectiveClass: case clang::Stmt::OMPParallelForDirectiveClass: case clang::Stmt::OMPParallelForSimdDirectiveClass: + case clang::Stmt::OMPParallelGenericLoopDirectiveClass: + case clang::Stmt::OMPParallelMaskedTaskLoopDirectiveClass: + case clang::Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass: case clang::Stmt::OMPParallelMasterTaskLoopDirectiveClass: case clang::Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass: case clang::Stmt::OMPSimdDirectiveClass: case clang::Stmt::OMPTargetParallelForSimdDirectiveClass: + case clang::Stmt::OMPTargetParallelGenericLoopDirectiveClass: case clang::Stmt::OMPTargetSimdDirectiveClass: case clang::Stmt::OMPTargetTeamsDistributeDirectiveClass: case clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass: case clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass: case clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass: + case clang::Stmt::OMPTargetTeamsGenericLoopDirectiveClass: case clang::Stmt::OMPTaskLoopDirectiveClass: case clang::Stmt::OMPTaskLoopSimdDirectiveClass: case clang::Stmt::OMPTeamsDistributeDirectiveClass: case clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass: case clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass: case clang::Stmt::OMPTeamsDistributeSimdDirectiveClass: + case clang::Stmt::OMPTeamsGenericLoopDirectiveClass: case clang::Stmt::OMPTileDirectiveClass: case clang::Stmt::OMPUnrollDirectiveClass: case clang::Stmt::OMPMaskedDirectiveClass: @@ -458,6 +468,7 @@ void ZigClang_detect_enum_StmtClass(clang::Stmt::StmtClass x) { case clang::Stmt::OMPMetaDirectiveClass: case clang::Stmt::OMPOrderedDirectiveClass: case clang::Stmt::OMPParallelDirectiveClass: + case clang::Stmt::OMPParallelMaskedDirectiveClass: case clang::Stmt::OMPParallelMasterDirectiveClass: case clang::Stmt::OMPParallelSectionsDirectiveClass: case clang::Stmt::OMPScanDirectiveClass: @@ -659,25 +670,33 @@ static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPDistributeSimdDirectiveCla static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPForDirectiveClass == clang::Stmt::OMPForDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPForSimdDirectiveClass == clang::Stmt::OMPForSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPGenericLoopDirectiveClass == clang::Stmt::OMPGenericLoopDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMaskedTaskLoopDirectiveClass == clang::Stmt::OMPMaskedTaskLoopDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMaskedTaskLoopSimdDirectiveClass == clang::Stmt::OMPMaskedTaskLoopSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMasterTaskLoopDirectiveClass == clang::Stmt::OMPMasterTaskLoopDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMasterTaskLoopSimdDirectiveClass == clang::Stmt::OMPMasterTaskLoopSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelForDirectiveClass == clang::Stmt::OMPParallelForDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelForSimdDirectiveClass == clang::Stmt::OMPParallelForSimdDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelGenericLoopDirectiveClass == clang::Stmt::OMPParallelGenericLoopDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelMaskedTaskLoopDirectiveClass == clang::Stmt::OMPParallelMaskedTaskLoopDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelMaskedTaskLoopSimdDirectiveClass == clang::Stmt::OMPParallelMaskedTaskLoopSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelMasterTaskLoopDirectiveClass == clang::Stmt::OMPParallelMasterTaskLoopDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelMasterTaskLoopSimdDirectiveClass == clang::Stmt::OMPParallelMasterTaskLoopSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPSimdDirectiveClass == clang::Stmt::OMPSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelForSimdDirectiveClass == clang::Stmt::OMPTargetParallelForSimdDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetParallelGenericLoopDirectiveClass == clang::Stmt::OMPTargetParallelGenericLoopDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetSimdDirectiveClass == clang::Stmt::OMPTargetSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeParallelForDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeParallelForSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass == clang::Stmt::OMPTargetTeamsDistributeSimdDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTargetTeamsGenericLoopDirectiveClass == clang::Stmt::OMPTargetTeamsGenericLoopDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskLoopDirectiveClass == clang::Stmt::OMPTaskLoopDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTaskLoopSimdDirectiveClass == clang::Stmt::OMPTaskLoopSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeDirectiveClass == clang::Stmt::OMPTeamsDistributeDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass == clang::Stmt::OMPTeamsDistributeParallelForDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass == clang::Stmt::OMPTeamsDistributeParallelForSimdDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass == clang::Stmt::OMPTeamsDistributeSimdDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTeamsGenericLoopDirectiveClass == clang::Stmt::OMPTeamsGenericLoopDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPTileDirectiveClass == clang::Stmt::OMPTileDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPUnrollDirectiveClass == clang::Stmt::OMPUnrollDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMaskedDirectiveClass == clang::Stmt::OMPMaskedDirectiveClass, ""); @@ -685,6 +704,7 @@ static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMasterDirectiveClass == cl static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPMetaDirectiveClass == clang::Stmt::OMPMetaDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPOrderedDirectiveClass == clang::Stmt::OMPOrderedDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelDirectiveClass == clang::Stmt::OMPParallelDirectiveClass, ""); +static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelMaskedDirectiveClass == clang::Stmt::OMPParallelMaskedDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelMasterDirectiveClass == clang::Stmt::OMPParallelMasterDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPParallelSectionsDirectiveClass == clang::Stmt::OMPParallelSectionsDirectiveClass, ""); static_assert((clang::Stmt::StmtClass)ZigClangStmt_OMPScanDirectiveClass == clang::Stmt::OMPScanDirectiveClass, ""); @@ -958,6 +978,7 @@ void ZigClang_detect_enum_DeclKind(clang::Decl::Kind x) { case clang::Decl::OMPDeclareMapper: case clang::Decl::OMPDeclareReduction: case clang::Decl::TemplateParamObject: + case clang::Decl::UnnamedGlobalConstant: case clang::Decl::UnresolvedUsingValue: case clang::Decl::OMPAllocate: case clang::Decl::OMPRequires: @@ -1046,6 +1067,7 @@ static_assert((clang::Decl::Kind)ZigClangDeclMSGuid == clang::Decl::MSGuid, ""); static_assert((clang::Decl::Kind)ZigClangDeclOMPDeclareMapper == clang::Decl::OMPDeclareMapper, ""); static_assert((clang::Decl::Kind)ZigClangDeclOMPDeclareReduction == clang::Decl::OMPDeclareReduction, ""); static_assert((clang::Decl::Kind)ZigClangDeclTemplateParamObject == clang::Decl::TemplateParamObject, ""); +static_assert((clang::Decl::Kind)ZigClangDeclUnnamedGlobalConstant == clang::Decl::UnnamedGlobalConstant, ""); static_assert((clang::Decl::Kind)ZigClangDeclUnresolvedUsingValue == clang::Decl::UnresolvedUsingValue, ""); static_assert((clang::Decl::Kind)ZigClangDeclOMPRequires == clang::Decl::OMPRequires, ""); static_assert((clang::Decl::Kind)ZigClangDeclOMPThreadPrivate == clang::Decl::OMPThreadPrivate, ""); @@ -1560,6 +1582,8 @@ void ZigClang_detect_enum_CallingConv(clang::CallingConv x) { case clang::CC_PreserveMost: case clang::CC_PreserveAll: case clang::CC_AArch64VectorCall: + case clang::CC_AArch64SVEPCS: + case clang::CC_AMDGPUKernelCall: break; } } @@ -1583,6 +1607,8 @@ static_assert((clang::CallingConv)ZigClangCallingConv_SwiftAsync == clang::CC_Sw static_assert((clang::CallingConv)ZigClangCallingConv_PreserveMost == clang::CC_PreserveMost, ""); static_assert((clang::CallingConv)ZigClangCallingConv_PreserveAll == clang::CC_PreserveAll, ""); static_assert((clang::CallingConv)ZigClangCallingConv_AArch64VectorCall == clang::CC_AArch64VectorCall, ""); +static_assert((clang::CallingConv)ZigClangCallingConv_AArch64SVEPCS == clang::CC_AArch64SVEPCS, ""); +static_assert((clang::CallingConv)ZigClangCallingConv_AMDGPUKernelCall == clang::CC_AMDGPUKernelCall, ""); void ZigClang_detect_enum_StorageClass(clang::StorageClass x) { switch (x) { @@ -1623,22 +1649,6 @@ static_assert((llvm::RoundingMode)ZigClangAPFloat_roundingMode_NearestTiesToAway static_assert((llvm::RoundingMode)ZigClangAPFloat_roundingMode_Dynamic == llvm::RoundingMode::Dynamic, ""); static_assert((llvm::RoundingMode)ZigClangAPFloat_roundingMode_Invalid == llvm::RoundingMode::Invalid, ""); -void ZigClang_detect_enum_StringKind(clang::StringLiteral::StringKind x) { - switch (x) { - case clang::StringLiteral::Ascii: - case clang::StringLiteral::Wide: - case clang::StringLiteral::UTF8: - case clang::StringLiteral::UTF16: - case clang::StringLiteral::UTF32: - break; - } -} -static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_Ascii == clang::StringLiteral::Ascii, ""); -static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_Wide == clang::StringLiteral::Wide, ""); -static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF8 == clang::StringLiteral::UTF8, ""); -static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF16 == clang::StringLiteral::UTF16, ""); -static_assert((clang::StringLiteral::StringKind)ZigClangStringLiteral_StringKind_UTF32 == clang::StringLiteral::UTF32, ""); - void ZigClang_detect_enum_CharacterKind(clang::CharacterLiteral::CharacterKind x) { switch (x) { case clang::CharacterLiteral::Ascii: @@ -2724,9 +2734,9 @@ ZigClangAPFloatBase_Semantics ZigClangFloatingLiteral_getRawSemantics(const ZigC return static_cast<ZigClangAPFloatBase_Semantics>(casted->getRawSemantics()); } -enum ZigClangStringLiteral_StringKind ZigClangStringLiteral_getKind(const struct ZigClangStringLiteral *self) { +enum ZigClangCharacterLiteral_CharacterKind ZigClangStringLiteral_getKind(const struct ZigClangStringLiteral *self) { auto casted = reinterpret_cast<const clang::StringLiteral *>(self); - return (ZigClangStringLiteral_StringKind)casted->getKind(); + return (ZigClangCharacterLiteral_CharacterKind)casted->getKind(); } uint32_t ZigClangStringLiteral_getCodeUnit(const struct ZigClangStringLiteral *self, size_t i) { diff --git a/src/zig_clang.h b/src/zig_clang.h index 3da57d4301..5d556700e6 100644 --- a/src/zig_clang.h +++ b/src/zig_clang.h @@ -252,6 +252,7 @@ enum ZigClangTypeClass { ZigClangType_VariableArray, ZigClangType_Atomic, ZigClangType_Attributed, + ZigClangType_BTFTagAttributed, ZigClangType_BitInt, ZigClangType_BlockPointer, ZigClangType_Builtin, @@ -337,25 +338,33 @@ enum ZigClangStmtClass { ZigClangStmt_OMPForDirectiveClass, ZigClangStmt_OMPForSimdDirectiveClass, ZigClangStmt_OMPGenericLoopDirectiveClass, + ZigClangStmt_OMPMaskedTaskLoopDirectiveClass, + ZigClangStmt_OMPMaskedTaskLoopSimdDirectiveClass, ZigClangStmt_OMPMasterTaskLoopDirectiveClass, ZigClangStmt_OMPMasterTaskLoopSimdDirectiveClass, ZigClangStmt_OMPParallelForDirectiveClass, ZigClangStmt_OMPParallelForSimdDirectiveClass, + ZigClangStmt_OMPParallelGenericLoopDirectiveClass, + ZigClangStmt_OMPParallelMaskedTaskLoopDirectiveClass, + ZigClangStmt_OMPParallelMaskedTaskLoopSimdDirectiveClass, ZigClangStmt_OMPParallelMasterTaskLoopDirectiveClass, ZigClangStmt_OMPParallelMasterTaskLoopSimdDirectiveClass, ZigClangStmt_OMPSimdDirectiveClass, ZigClangStmt_OMPTargetParallelForSimdDirectiveClass, + ZigClangStmt_OMPTargetParallelGenericLoopDirectiveClass, ZigClangStmt_OMPTargetSimdDirectiveClass, ZigClangStmt_OMPTargetTeamsDistributeDirectiveClass, ZigClangStmt_OMPTargetTeamsDistributeParallelForDirectiveClass, ZigClangStmt_OMPTargetTeamsDistributeParallelForSimdDirectiveClass, ZigClangStmt_OMPTargetTeamsDistributeSimdDirectiveClass, + ZigClangStmt_OMPTargetTeamsGenericLoopDirectiveClass, ZigClangStmt_OMPTaskLoopDirectiveClass, ZigClangStmt_OMPTaskLoopSimdDirectiveClass, ZigClangStmt_OMPTeamsDistributeDirectiveClass, ZigClangStmt_OMPTeamsDistributeParallelForDirectiveClass, ZigClangStmt_OMPTeamsDistributeParallelForSimdDirectiveClass, ZigClangStmt_OMPTeamsDistributeSimdDirectiveClass, + ZigClangStmt_OMPTeamsGenericLoopDirectiveClass, ZigClangStmt_OMPTileDirectiveClass, ZigClangStmt_OMPUnrollDirectiveClass, ZigClangStmt_OMPMaskedDirectiveClass, @@ -363,6 +372,7 @@ enum ZigClangStmtClass { ZigClangStmt_OMPMetaDirectiveClass, ZigClangStmt_OMPOrderedDirectiveClass, ZigClangStmt_OMPParallelDirectiveClass, + ZigClangStmt_OMPParallelMaskedDirectiveClass, ZigClangStmt_OMPParallelMasterDirectiveClass, ZigClangStmt_OMPParallelSectionsDirectiveClass, ZigClangStmt_OMPScanDirectiveClass, @@ -667,6 +677,7 @@ enum ZigClangDeclKind { ZigClangDeclOMPDeclareMapper, ZigClangDeclOMPDeclareReduction, ZigClangDeclTemplateParamObject, + ZigClangDeclUnnamedGlobalConstant, ZigClangDeclUnresolvedUsingValue, ZigClangDeclOMPAllocate, ZigClangDeclOMPRequires, @@ -921,25 +932,27 @@ enum ZigClangBuiltinTypeKind { }; enum ZigClangCallingConv { - ZigClangCallingConv_C, // __attribute__((cdecl)) - ZigClangCallingConv_X86StdCall, // __attribute__((stdcall)) - ZigClangCallingConv_X86FastCall, // __attribute__((fastcall)) - ZigClangCallingConv_X86ThisCall, // __attribute__((thiscall)) - ZigClangCallingConv_X86VectorCall, // __attribute__((vectorcall)) - ZigClangCallingConv_X86Pascal, // __attribute__((pascal)) - ZigClangCallingConv_Win64, // __attribute__((ms_abi)) - ZigClangCallingConv_X86_64SysV, // __attribute__((sysv_abi)) - ZigClangCallingConv_X86RegCall, // __attribute__((regcall)) - ZigClangCallingConv_AAPCS, // __attribute__((pcs("aapcs"))) - ZigClangCallingConv_AAPCS_VFP, // __attribute__((pcs("aapcs-vfp"))) - ZigClangCallingConv_IntelOclBicc, // __attribute__((intel_ocl_bicc)) - ZigClangCallingConv_SpirFunction, // default for OpenCL functions on SPIR target - ZigClangCallingConv_OpenCLKernel, // inferred for OpenCL kernels - ZigClangCallingConv_Swift, // __attribute__((swiftcall)) - ZigClangCallingConv_SwiftAsync, // __attribute__((swiftasynccall)) - ZigClangCallingConv_PreserveMost, // __attribute__((preserve_most)) - ZigClangCallingConv_PreserveAll, // __attribute__((preserve_all)) - ZigClangCallingConv_AArch64VectorCall, // __attribute__((aarch64_vector_pcs)) + ZigClangCallingConv_C, + ZigClangCallingConv_X86StdCall, + ZigClangCallingConv_X86FastCall, + ZigClangCallingConv_X86ThisCall, + ZigClangCallingConv_X86VectorCall, + ZigClangCallingConv_X86Pascal, + ZigClangCallingConv_Win64, + ZigClangCallingConv_X86_64SysV, + ZigClangCallingConv_X86RegCall, + ZigClangCallingConv_AAPCS, + ZigClangCallingConv_AAPCS_VFP, + ZigClangCallingConv_IntelOclBicc, + ZigClangCallingConv_SpirFunction, + ZigClangCallingConv_OpenCLKernel, + ZigClangCallingConv_Swift, + ZigClangCallingConv_SwiftAsync, + ZigClangCallingConv_PreserveMost, + ZigClangCallingConv_PreserveAll, + ZigClangCallingConv_AArch64VectorCall, + ZigClangCallingConv_AArch64SVEPCS, + ZigClangCallingConv_AMDGPUKernelCall, }; enum ZigClangStorageClass { @@ -1253,7 +1266,9 @@ ZIG_EXTERN_C double ZigClangFloatingLiteral_getValueAsApproximateDouble(const Zi ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFloatingLiteral_getBeginLoc(const struct ZigClangFloatingLiteral *); ZIG_EXTERN_C ZigClangAPFloatBase_Semantics ZigClangFloatingLiteral_getRawSemantics(const ZigClangFloatingLiteral *self); -ZIG_EXTERN_C enum ZigClangStringLiteral_StringKind ZigClangStringLiteral_getKind(const struct ZigClangStringLiteral *self); + +ZIG_EXTERN_C enum ZigClangCharacterLiteral_CharacterKind ZigClangStringLiteral_getKind( + const struct ZigClangStringLiteral *self); ZIG_EXTERN_C uint32_t ZigClangStringLiteral_getCodeUnit(const struct ZigClangStringLiteral *self, size_t i); ZIG_EXTERN_C unsigned ZigClangStringLiteral_getLength(const struct ZigClangStringLiteral *self); ZIG_EXTERN_C unsigned ZigClangStringLiteral_getCharByteWidth(const struct ZigClangStringLiteral *self); diff --git a/src/zig_clang_cc1_main.cpp b/src/zig_clang_cc1_main.cpp index f648adeba4..de33aa9ea9 100644 --- a/src/zig_clang_cc1_main.cpp +++ b/src/zig_clang_cc1_main.cpp @@ -212,7 +212,9 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { bool Success = CompilerInvocation::CreateFromArgs(Clang->getInvocation(), Argv, Diags, Argv0); - if (Clang->getFrontendOpts().TimeTrace) { + if (Clang->getFrontendOpts().TimeTrace || + !Clang->getFrontendOpts().TimeTracePath.empty()) { + Clang->getFrontendOpts().TimeTrace = 1; llvm::timeTraceProfilerInitialize( Clang->getFrontendOpts().TimeTraceGranularity, Argv0); } @@ -256,12 +258,18 @@ int cc1_main(ArrayRef<const char *> Argv, const char *Argv0, void *MainAddr) { if (llvm::timeTraceProfilerEnabled()) { SmallString<128> Path(Clang->getFrontendOpts().OutputFile); llvm::sys::path::replace_extension(Path, "json"); + if (!Clang->getFrontendOpts().TimeTracePath.empty()) { + // replace the suffix to '.json' directly + SmallString<128> TracePath(Clang->getFrontendOpts().TimeTracePath); + if (llvm::sys::fs::is_directory(TracePath)) + llvm::sys::path::append(TracePath, llvm::sys::path::filename(Path)); + Path.assign(TracePath); + } if (auto profilerOutput = Clang->createOutputFile( Path.str(), /*Binary=*/false, /*RemoveFileOnSignal=*/false, /*useTemporary=*/false)) { llvm::timeTraceProfilerWrite(*profilerOutput); - // FIXME(ibiryukov): make profilerOutput flush in destructor instead. - profilerOutput->flush(); + profilerOutput.reset(); llvm::timeTraceProfilerCleanup(); Clang->clearOutputFiles(false); } diff --git a/src/zig_clang_cc1as_main.cpp b/src/zig_clang_cc1as_main.cpp index 6459d1534b..5498810d83 100644 --- a/src/zig_clang_cc1as_main.cpp +++ b/src/zig_clang_cc1as_main.cpp @@ -137,6 +137,9 @@ struct AssemblerInvocation { unsigned IncrementalLinkerCompatible : 1; unsigned EmbedBitcode : 1; + /// Whether to emit DWARF unwind info. + EmitDwarfUnwindType EmitDwarfUnwind; + /// The name of the relocation model to use. std::string RelocationModel; @@ -144,6 +147,9 @@ struct AssemblerInvocation { /// otherwise. std::string TargetABI; + /// Darwin target variant triple, the variant of the deployment target + /// for which the code is being compiled. + llvm::Optional<llvm::Triple> DarwinTargetVariantTriple; /// @} public: @@ -164,6 +170,7 @@ public: Dwarf64 = 0; DwarfVersion = 0; EmbedBitcode = 0; + EmitDwarfUnwind = EmitDwarfUnwindType::Default; } static bool CreateFromArgs(AssemblerInvocation &Res, @@ -209,6 +216,9 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, // Target Options Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple)); + if (Arg *A = Args.getLastArg(options::OPT_darwin_target_variant_triple)) + Opts.DarwinTargetVariantTriple = llvm::Triple(A->getValue()); + Opts.CPU = std::string(Args.getLastArgValue(OPT_target_cpu)); Opts.Features = Args.getAllArgValues(OPT_target_feature); @@ -311,6 +321,14 @@ bool AssemblerInvocation::CreateFromArgs(AssemblerInvocation &Opts, .Default(0); } + if (auto *A = Args.getLastArg(OPT_femit_dwarf_unwind_EQ)) { + Opts.EmitDwarfUnwind = + llvm::StringSwitch<EmitDwarfUnwindType>(A->getValue()) + .Case("always", EmitDwarfUnwindType::Always) + .Case("no-compact-unwind", EmitDwarfUnwindType::NoCompactUnwind) + .Case("default", EmitDwarfUnwindType::Default); + } + return Success; } @@ -361,6 +379,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, assert(MRI && "Unable to create target register info!"); MCTargetOptions MCOptions; + MCOptions.EmitDwarfUnwind = Opts.EmitDwarfUnwind; + std::unique_ptr<MCAsmInfo> MAI( TheTarget->createMCAsmInfo(*MRI, Opts.Triple, MCOptions)); assert(MAI && "Unable to create target asm info!"); @@ -407,6 +427,8 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, // MCObjectFileInfo needs a MCContext reference in order to initialize itself. std::unique_ptr<MCObjectFileInfo> MOFI( TheTarget->createMCObjectFileInfo(Ctx, PIC)); + if (Opts.DarwinTargetVariantTriple) + MOFI->setDarwinTargetVariantTriple(*Opts.DarwinTargetVariantTriple); Ctx.setObjectFileInfo(MOFI.get()); if (Opts.SaveTemporaryLabels) @@ -455,7 +477,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, std::unique_ptr<MCCodeEmitter> CE; if (Opts.ShowEncoding) - CE.reset(TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); + CE.reset(TheTarget->createMCCodeEmitter(*MCII, Ctx)); std::unique_ptr<MCAsmBackend> MAB( TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); @@ -475,7 +497,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, } std::unique_ptr<MCCodeEmitter> CE( - TheTarget->createMCCodeEmitter(*MCII, *MRI, Ctx)); + TheTarget->createMCCodeEmitter(*MCII, Ctx)); std::unique_ptr<MCAsmBackend> MAB( TheTarget->createMCAsmBackend(*STI, *MRI, MCOptions)); assert(MAB && "Unable to create asm backend!"); @@ -497,7 +519,7 @@ static bool ExecuteAssemblerImpl(AssemblerInvocation &Opts, if (Opts.EmbedBitcode && Ctx.getObjectFileType() == MCContext::IsMachO) { MCSection *AsmLabel = Ctx.getMachOSection( "__LLVM", "__asm", MachO::S_REGULAR, 4, SectionKind::getReadOnly()); - Str.get()->SwitchSection(AsmLabel); + Str.get()->switchSection(AsmLabel); Str.get()->emitZeros(1); } diff --git a/src/zig_clang_driver.cpp b/src/zig_clang_driver.cpp index 1f24131f14..b83cddf202 100644 --- a/src/zig_clang_driver.cpp +++ b/src/zig_clang_driver.cpp @@ -410,18 +410,18 @@ int ZigClang_main(int Argc, const char **Argv) { if (ClangCLMode) { // Arguments in "CL" are prepended. llvm::Optional<std::string> OptCL = llvm::sys::Process::GetEnv("CL"); - if (OptCL.hasValue()) { + if (OptCL) { SmallVector<const char *, 8> PrependedOpts; - getCLEnvVarOptions(OptCL.getValue(), Saver, PrependedOpts); + getCLEnvVarOptions(OptCL.value(), Saver, PrependedOpts); // Insert right after the program name to prepend to the argument list. Args.insert(Args.begin() + 1, PrependedOpts.begin(), PrependedOpts.end()); } // Arguments in "_CL_" are appended. llvm::Optional<std::string> Opt_CL_ = llvm::sys::Process::GetEnv("_CL_"); - if (Opt_CL_.hasValue()) { + if (Opt_CL_) { SmallVector<const char *, 8> AppendedOpts; - getCLEnvVarOptions(Opt_CL_.getValue(), Saver, AppendedOpts); + getCLEnvVarOptions(Opt_CL_.value(), Saver, AppendedOpts); // Insert at the end of the argument list to append. Args.append(AppendedOpts.begin(), AppendedOpts.end()); @@ -488,32 +488,39 @@ int ZigClang_main(int Argc, const char **Argv) { } std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args)); + + Driver::ReproLevel ReproLevel = Driver::ReproLevel::OnCrash; + if (Arg *A = C->getArgs().getLastArg(options::OPT_gen_reproducer_eq)) { + auto Level = llvm::StringSwitch<Optional<Driver::ReproLevel>>(A->getValue()) + .Case("off", Driver::ReproLevel::Off) + .Case("crash", Driver::ReproLevel::OnCrash) + .Case("error", Driver::ReproLevel::OnError) + .Case("always", Driver::ReproLevel::Always) + .Default(None); + if (!Level) { + llvm::errs() << "Unknown value for " << A->getSpelling() << ": '" + << A->getValue() << "'\n"; + return 1; + } + ReproLevel = *Level; + } + if (!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) + ReproLevel = Driver::ReproLevel::Always; + int Res = 1; bool IsCrash = false; + Driver::CommandStatus CommandStatus = Driver::CommandStatus::Ok; + // Pretend the first command failed if ReproStatus is Always. + const Command *FailingCommand = nullptr; + if (!C->getJobs().empty()) + FailingCommand = &*C->getJobs().begin(); if (C && !C->containsError()) { SmallVector<std::pair<int, const Command *>, 4> FailingCommands; Res = TheDriver.ExecuteCompilation(*C, FailingCommands); - // Force a crash to test the diagnostics. - if (TheDriver.GenReproducer) { - Diags.Report(diag::err_drv_force_crash) - << !::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH"); - - // Pretend that every command failed. - FailingCommands.clear(); - for (const auto &J : C->getJobs()) - if (const Command *C = dyn_cast<Command>(&J)) - FailingCommands.push_back(std::make_pair(-1, C)); - - // Print the bug report message that would be printed if we did actually - // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH. - if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) - llvm::dbgs() << llvm::getBugReportMsg(); - } - for (const auto &P : FailingCommands) { int CommandRes = P.first; - const Command *FailingCommand = P.second; + FailingCommand = P.second; if (!Res) Res = CommandRes; @@ -532,13 +539,22 @@ int ZigClang_main(int Argc, const char **Argv) { // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html IsCrash |= CommandRes > 128; #endif - if (IsCrash) { - TheDriver.generateCompilationDiagnostics(*C, *FailingCommand); + CommandStatus = + IsCrash ? Driver::CommandStatus::Crash : Driver::CommandStatus::Error; + if (IsCrash) break; - } } } + // Print the bug report message that would be printed if we did actually + // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH. + if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) + llvm::dbgs() << llvm::getBugReportMsg(); + if (FailingCommand != nullptr && + TheDriver.maybeGenerateCompilationDiagnostics(CommandStatus, ReproLevel, + *C, *FailingCommand)) + Res = 1; + Diags.getClient()->finish(); if (!UseNewCC1Process && IsCrash) { diff --git a/src/zig_llvm-ar.cpp b/src/zig_llvm-ar.cpp index c959f339a2..6e5f9d36d8 100644 --- a/src/zig_llvm-ar.cpp +++ b/src/zig_llvm-ar.cpp @@ -18,10 +18,15 @@ #include "llvm/IR/LLVMContext.h" #include "llvm/Object/Archive.h" #include "llvm/Object/ArchiveWriter.h" +#include "llvm/Object/COFFImportFile.h" +#include "llvm/Object/ELFObjectFile.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Object/MachO.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/SymbolicFile.h" +#include "llvm/Object/TapiFile.h" +#include "llvm/Object/Wasm.h" +#include "llvm/Object/XCOFFObjectFile.h" #include "llvm/Support/Chrono.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ConvertUTF.h" @@ -54,6 +59,7 @@ #endif using namespace llvm; +using namespace llvm::object; // The name this program was invoked as. static StringRef ToolName; @@ -61,37 +67,36 @@ static StringRef ToolName; // The basename of this program. static StringRef Stem; -const char RanlibHelp[] = R"(OVERVIEW: LLVM Ranlib (llvm-ranlib) - - This program generates an index to speed access to archives - -USAGE: llvm-ranlib <archive-file> - -OPTIONS: - -h --help - Display available options - -v --version - Display the version of this program - -D - Use zero for timestamps and uids/gids (default) - -U - Use actual timestamps and uids/gids -)"; - -const char ArHelp[] = R"(OVERVIEW: LLVM Archiver - -USAGE: llvm-ar [options] [-]<operation>[modifiers] [relpos] [count] <archive> [files] - llvm-ar -M [<mri-script] +static void printRanLibHelp(StringRef ToolName) { + outs() << "OVERVIEW: LLVM Ranlib\n\n" + << "This program generates an index to speed access to archives\n\n" + << "USAGE: " + ToolName + " <archive-file>\n\n" + << "OPTIONS:\n" + << " -h --help - Display available options\n" + << " -v --version - Display the version of this program\n" + << " -D - Use zero for timestamps and uids/gids " + "(default)\n" + << " -U - Use actual timestamps and uids/gids\n"; +} -OPTIONS: +static void printArHelp(StringRef ToolName) { + const char ArOptions[] = + R"(OPTIONS: --format - archive format to create =default - default =gnu - gnu =darwin - darwin =bsd - bsd + =bigarchive - big archive (AIX OS) --plugin=<string> - ignored for compatibility -h --help - display this help and exit + --output - the directory to extract archive members to --rsp-quoting - quoting style for response files =posix - posix =windows - windows --thin - create a thin archive --version - print the version and exit + -X{32|64|32_64|any} - object mode (only for AIX OS) @<file> - read options from <file> OPERATIONS: @@ -126,11 +131,20 @@ MODIFIERS: [V] - display the version and exit )"; + outs() << "OVERVIEW: LLVM Archiver\n\n" + << "USAGE: " + ToolName + + " [options] [-]<operation>[modifiers] [relpos] " + "[count] <archive> [files]\n" + << " " + ToolName + " -M [<mri-script]\n\n"; + + outs() << ArOptions; +} + static void printHelpMessage() { if (Stem.contains_insensitive("ranlib")) - outs() << RanlibHelp; + printRanLibHelp(Stem); else if (Stem.contains_insensitive("ar")) - outs() << ArHelp; + printArHelp(Stem); } static unsigned MRILineNumber; @@ -176,12 +190,16 @@ static void failIfError(Error E, Twine Context = "") { }); } +static void warn(Twine Message) { + WithColor::warning(errs(), ToolName) << Message << "\n"; +} + static SmallVector<const char *, 256> PositionalArgs; static bool MRI; namespace { -enum Format { Default, GNU, BSD, DARWIN, Unknown }; +enum Format { Default, GNU, BSD, DARWIN, BIGARCHIVE, Unknown }; } static Format FormatType = Default; @@ -201,6 +219,10 @@ enum ArchiveOperation { CreateSymTab ///< Create a symbol table in an existing archive }; +enum class BitModeTy { Bit32, Bit64, Bit32_64, Any, Unknown }; + +static BitModeTy BitMode = BitModeTy::Bit32; + // Modifiers to follow operation to vary behavior static bool AddAfter = false; ///< 'a' modifier static bool AddBefore = false; ///< 'b' modifier @@ -230,6 +252,9 @@ static int CountParam = 0; // command line. static std::string ArchiveName; +// Output directory specified by --output. +static std::string OutputDir; + static std::vector<std::unique_ptr<MemoryBuffer>> ArchiveBuffers; static std::vector<std::unique_ptr<object::Archive>> Archives; @@ -447,6 +472,19 @@ static ArchiveOperation parseCommandLine() { if (AddLibrary && Operation != QuickAppend) badUsage("the 'L' modifier is only applicable to the 'q' operation"); + if (!OutputDir.empty()) { + if (Operation != Extract) + badUsage("--output is only applicable to the 'x' operation"); + bool IsDir = false; + // If OutputDir is not a directory, create_directories may still succeed if + // all components of the path prefix are directories. Test is_directory as + // well. + if (!sys::fs::create_directories(OutputDir)) + sys::fs::is_directory(OutputDir, IsDir); + if (!IsDir) + fail("'" + OutputDir + "' is not a directory"); + } + // Return the parsed operation to the caller return Operation; } @@ -547,7 +585,15 @@ static void doExtract(StringRef Name, const object::Archive::Child &C) { failIfError(ModeOrErr.takeError()); sys::fs::perms Mode = ModeOrErr.get(); - llvm::StringRef outputFilePath = sys::path::filename(Name); + StringRef outputFilePath; + SmallString<128> path; + if (OutputDir.empty()) { + outputFilePath = sys::path::filename(Name); + } else { + sys::path::append(path, OutputDir, sys::path::filename(Name)); + outputFilePath = path.str(); + } + if (Verbose) outs() << "x - " << outputFilePath << '\n'; @@ -600,6 +646,71 @@ static bool shouldCreateArchive(ArchiveOperation Op) { llvm_unreachable("Missing entry in covered switch."); } +static bool is64BitSymbolicFile(SymbolicFile &Obj) { + if (auto *IRObj = dyn_cast<IRObjectFile>(&Obj)) + return Triple(IRObj->getTargetTriple()).isArch64Bit(); + if (isa<COFFObjectFile>(Obj) || isa<COFFImportFile>(Obj)) + return false; + if (XCOFFObjectFile *XCOFFObj = dyn_cast<XCOFFObjectFile>(&Obj)) + return XCOFFObj->is64Bit(); + if (isa<WasmObjectFile>(Obj)) + return false; + if (TapiFile *Tapi = dyn_cast<TapiFile>(&Obj)) + return Tapi->is64Bit(); + if (MachOObjectFile *MachO = dyn_cast<MachOObjectFile>(&Obj)) + return MachO->is64Bit(); + if (ELFObjectFileBase *ElfO = dyn_cast<ELFObjectFileBase>(&Obj)) + return ElfO->getBytesInAddress() == 8; + + fail("unsupported file format"); +} + +static bool isValidInBitMode(Binary &Bin) { + if (BitMode == BitModeTy::Bit32_64 || BitMode == BitModeTy::Any) + return true; + + if (SymbolicFile *SymFile = dyn_cast<SymbolicFile>(&Bin)) { + bool Is64Bit = is64BitSymbolicFile(*SymFile); + if ((Is64Bit && (BitMode == BitModeTy::Bit32)) || + (!Is64Bit && (BitMode == BitModeTy::Bit64))) + return false; + } + // In AIX "ar", non-object files are always considered to have a valid bit + // mode. + return true; +} + +Expected<std::unique_ptr<Binary>> getAsBinary(const NewArchiveMember &NM, + LLVMContext *Context) { + auto BinaryOrErr = createBinary(NM.Buf->getMemBufferRef(), Context); + if (BinaryOrErr) + return std::move(*BinaryOrErr); + return BinaryOrErr.takeError(); +} + +Expected<std::unique_ptr<Binary>> getAsBinary(const Archive::Child &C, + LLVMContext *Context) { + return C.getAsBinary(Context); +} + +template <class A> static bool isValidInBitMode(const A &Member) { + if (object::Archive::getDefaultKindForHost() != object::Archive::K_AIXBIG) + return true; + LLVMContext Context; + Expected<std::unique_ptr<Binary>> BinOrErr = getAsBinary(Member, &Context); + // In AIX "ar", if there is a non-object file member, it is never ignored due + // to the bit mode setting. + if (!BinOrErr) { + consumeError(BinOrErr.takeError()); + return true; + } + return isValidInBitMode(*BinOrErr.get()); +} + +static void warnInvalidObjectForFileMode(Twine Name) { + warn("'" + Name + "' is not valid with the current object file mode"); +} + static void performReadOperation(ArchiveOperation Operation, object::Archive *OldArchive) { if (Operation == Extract && OldArchive->isThin()) @@ -614,6 +725,10 @@ static void performReadOperation(ArchiveOperation Operation, failIfError(NameOrErr.takeError()); StringRef Name = NameOrErr.get(); + // Check whether to ignore this object due to its bitness. + if (!isValidInBitMode(C)) + continue; + if (Filter) { auto I = find_if(Members, [Name](StringRef Path) { return comparePaths(Name, Path); @@ -652,8 +767,6 @@ static void performReadOperation(ArchiveOperation Operation, static void addChildMember(std::vector<NewArchiveMember> &Members, const object::Archive::Child &M, bool FlattenArchive = false) { - if (Thin && !M.getParent()->isThin()) - fail("cannot convert a regular archive to a thin one"); Expected<NewArchiveMember> NMOrErr = NewArchiveMember::getOldMember(M, Deterministic); failIfError(NMOrErr.takeError()); @@ -692,8 +805,7 @@ static void addChildMember(std::vector<NewArchiveMember> &Members, Members.push_back(std::move(*NMOrErr)); } -static void addMember(std::vector<NewArchiveMember> &Members, - StringRef FileName, bool FlattenArchive = false) { +static NewArchiveMember getArchiveMember(StringRef FileName) { Expected<NewArchiveMember> NMOrErr = NewArchiveMember::getFile(FileName, Deterministic); failIfError(NMOrErr.takeError(), FileName); @@ -713,9 +825,24 @@ static void addMember(std::vector<NewArchiveMember> &Members, PathOrErr ? *PathOrErr : sys::path::convert_to_slash(FileName)); } } + return std::move(*NMOrErr); +} + +static void addMember(std::vector<NewArchiveMember> &Members, + NewArchiveMember &NM) { + Members.push_back(std::move(NM)); +} + +static void addMember(std::vector<NewArchiveMember> &Members, + StringRef FileName, bool FlattenArchive = false) { + NewArchiveMember NM = getArchiveMember(FileName); + if (!isValidInBitMode(NM)) { + warnInvalidObjectForFileMode(FileName); + return; + } if (FlattenArchive && - identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) { + identify_magic(NM.Buf->getBuffer()) == file_magic::archive) { object::Archive &Lib = readLibrary(FileName); // When creating thin archives, only flatten if the member is also thin. if (!Thin || Lib.isThin()) { @@ -727,7 +854,7 @@ static void addMember(std::vector<NewArchiveMember> &Members, return; } } - Members.push_back(std::move(*NMOrErr)); + Members.push_back(std::move(NM)); } enum InsertAction { @@ -743,6 +870,9 @@ static InsertAction computeInsertAction(ArchiveOperation Operation, StringRef Name, std::vector<StringRef>::iterator &Pos, StringMap<int> &MemberCount) { + if (!isValidInBitMode(Member)) + return IA_AddOldMember; + if (Operation == QuickAppend || Members.empty()) return IA_AddOldMember; auto MI = find_if( @@ -804,7 +934,7 @@ computeNewArchiveMembers(ArchiveOperation Operation, Expected<StringRef> NameOrErr = Child.getName(); failIfError(NameOrErr.takeError()); std::string Name = std::string(NameOrErr.get()); - if (comparePaths(Name, RelPos)) { + if (comparePaths(Name, RelPos) && isValidInBitMode(Child)) { assert(AddAfter || AddBefore); if (AddBefore) InsertPos = Pos; @@ -815,12 +945,25 @@ computeNewArchiveMembers(ArchiveOperation Operation, std::vector<StringRef>::iterator MemberI = Members.end(); InsertAction Action = computeInsertAction(Operation, Child, Name, MemberI, MemberCount); + + auto HandleNewMember = [](auto Member, auto &Members, auto &Child) { + NewArchiveMember NM = getArchiveMember(*Member); + if (isValidInBitMode(NM)) + addMember(Members, NM); + else { + // If a new member is not a valid object for the bit mode, add + // the old member back. + warnInvalidObjectForFileMode(*Member); + addChildMember(Members, Child, /*FlattenArchive=*/Thin); + } + }; + switch (Action) { case IA_AddOldMember: addChildMember(Ret, Child, /*FlattenArchive=*/Thin); break; case IA_AddNewMember: - addMember(Ret, *MemberI); + HandleNewMember(MemberI, Ret, Child); break; case IA_Delete: break; @@ -828,7 +971,7 @@ computeNewArchiveMembers(ArchiveOperation Operation, addChildMember(Moved, Child, /*FlattenArchive=*/Thin); break; case IA_MoveNewMember: - addMember(Moved, *MemberI); + HandleNewMember(MemberI, Moved, Child); break; } // When processing elements with the count param, we need to preserve the @@ -875,48 +1018,18 @@ computeNewArchiveMembers(ArchiveOperation Operation, return Ret; } -static object::Archive::Kind getDefaultForHost() { - return Triple(sys::getProcessTriple()).isOSDarwin() - ? object::Archive::K_DARWIN - : object::Archive::K_GNU; -} - -static object::Archive::Kind getKindFromMember(const NewArchiveMember &Member) { - auto MemBufferRef = Member.Buf->getMemBufferRef(); - Expected<std::unique_ptr<object::ObjectFile>> OptionalObject = - object::ObjectFile::createObjectFile(MemBufferRef); - - if (OptionalObject) - return isa<object::MachOObjectFile>(**OptionalObject) - ? object::Archive::K_DARWIN - : object::Archive::K_GNU; - - // squelch the error in case we had a non-object file - consumeError(OptionalObject.takeError()); - - // If we're adding a bitcode file to the archive, detect the Archive kind - // based on the target triple. - LLVMContext Context; - if (identify_magic(MemBufferRef.getBuffer()) == file_magic::bitcode) { - if (auto ObjOrErr = object::SymbolicFile::createSymbolicFile( - MemBufferRef, file_magic::bitcode, &Context)) { - auto &IRObject = cast<object::IRObjectFile>(**ObjOrErr); - return Triple(IRObject.getTargetTriple()).isOSDarwin() - ? object::Archive::K_DARWIN - : object::Archive::K_GNU; - } else { - // Squelch the error in case this was not a SymbolicFile. - consumeError(ObjOrErr.takeError()); - } - } - - return getDefaultForHost(); -} - static void performWriteOperation(ArchiveOperation Operation, object::Archive *OldArchive, std::unique_ptr<MemoryBuffer> OldArchiveBuf, std::vector<NewArchiveMember> *NewMembersP) { + if (OldArchive) { + if (Thin && !OldArchive->isThin()) + fail("cannot convert a regular archive to a thin one"); + + if (OldArchive->isThin()) + Thin = true; + } + std::vector<NewArchiveMember> NewMembers; if (!NewMembersP) NewMembers = computeNewArchiveMembers(Operation, OldArchive); @@ -926,14 +1039,23 @@ static void performWriteOperation(ArchiveOperation Operation, case Default: if (Thin) Kind = object::Archive::K_GNU; - else if (OldArchive) + else if (OldArchive) { Kind = OldArchive->kind(); - else if (NewMembersP) - Kind = !NewMembersP->empty() ? getKindFromMember(NewMembersP->front()) - : getDefaultForHost(); + if (Kind == object::Archive::K_BSD) { + auto InferredKind = object::Archive::K_BSD; + if (NewMembersP && !NewMembersP->empty()) + InferredKind = NewMembersP->front().detectKindFromObject(); + else if (!NewMembers.empty()) + InferredKind = NewMembers.front().detectKindFromObject(); + if (InferredKind == object::Archive::K_DARWIN) + Kind = object::Archive::K_DARWIN; + } + } else if (NewMembersP) + Kind = !NewMembersP->empty() ? NewMembersP->front().detectKindFromObject() + : object::Archive::getDefaultKindForHost(); else - Kind = !NewMembers.empty() ? getKindFromMember(NewMembers.front()) - : getDefaultForHost(); + Kind = !NewMembers.empty() ? NewMembers.front().detectKindFromObject() + : object::Archive::getDefaultKindForHost(); break; case GNU: Kind = object::Archive::K_GNU; @@ -948,6 +1070,11 @@ static void performWriteOperation(ArchiveOperation Operation, fail("only the gnu format has a thin mode"); Kind = object::Archive::K_DARWIN; break; + case BIGARCHIVE: + if (Thin) + fail("only the gnu format has a thin mode"); + Kind = object::Archive::K_AIXBIG; + break; case Unknown: llvm_unreachable(""); } @@ -1029,8 +1156,7 @@ static int performOperation(ArchiveOperation Operation, } else { if (!Create) { // Produce a warning if we should and we're creating the archive - WithColor::warning(errs(), ToolName) - << "creating " << ArchiveName << "\n"; + warn("creating " + ArchiveName); } } @@ -1073,8 +1199,12 @@ static void runMRIScript() { switch (Command) { case MRICommand::AddLib: { + if (!Create) + fail("no output archive has been opened"); object::Archive &Lib = readLibrary(Rest); { + if (Thin && !Lib.isThin()) + fail("cannot add a regular archive's contents to a thin archive"); Error Err = Error::success(); for (auto &Member : Lib.children(Err)) addChildMember(NewMembers, Member, /*FlattenArchive=*/Thin); @@ -1083,6 +1213,8 @@ static void runMRIScript() { break; } case MRICommand::AddMod: + if (!Create) + fail("no output archive has been opened"); addMember(NewMembers, Rest); break; case MRICommand::CreateThin: @@ -1095,6 +1227,8 @@ static void runMRIScript() { if (Saved) fail("file already saved"); ArchiveName = std::string(Rest); + if (ArchiveName.empty()) + fail("missing archive name"); break; case MRICommand::Delete: { llvm::erase_if(NewMembers, [=](NewArchiveMember &M) { @@ -1116,7 +1250,8 @@ static void runMRIScript() { // Nothing to do if not saved. if (Saved) - performOperation(ReplaceOrInsert, &NewMembers); + performOperation(ReplaceOrInsert, /*OldArchive=*/nullptr, + /*OldArchiveBuf=*/nullptr, &NewMembers); exit(0); } @@ -1132,6 +1267,15 @@ static bool handleGenericOption(StringRef arg) { return false; } +static BitModeTy getBitMode(const char *RawBitMode) { + return StringSwitch<BitModeTy>(RawBitMode) + .Case("32", BitModeTy::Bit32) + .Case("64", BitModeTy::Bit64) + .Case("32_64", BitModeTy::Bit32_64) + .Case("any", BitModeTy::Any) + .Default(BitModeTy::Unknown); +} + static const char *matchFlagWithArg(StringRef Expected, ArrayRef<const char *>::iterator &ArgIt, ArrayRef<const char *> Args) { @@ -1181,6 +1325,14 @@ static int ar_main(int argc, char **argv) { cl::ExpandResponseFiles(Saver, getRspQuoting(makeArrayRef(argv, argc)), Argv); + // Get BitMode from enviorment variable "OBJECT_MODE" for AIX OS, if + // specified. + if (object::Archive::getDefaultKindForHost() == object::Archive::K_AIXBIG) { + BitMode = getBitMode(getenv("OBJECT_MODE")); + if (BitMode == BitModeTy::Unknown) + BitMode = BitModeTy::Bit32; + } + for (ArrayRef<const char *>::iterator ArgIt = Argv.begin(); ArgIt != Argv.end(); ++ArgIt) { const char *Match = nullptr; @@ -1219,16 +1371,35 @@ static int ar_main(int argc, char **argv) { .Case("gnu", GNU) .Case("darwin", DARWIN) .Case("bsd", BSD) + .Case("bigarchive", BIGARCHIVE) .Default(Unknown); if (FormatType == Unknown) fail(std::string("Invalid format ") + Match); continue; } + if ((Match = matchFlagWithArg("output", ArgIt, Argv))) { + OutputDir = Match; + continue; + } + if (matchFlagWithArg("plugin", ArgIt, Argv) || matchFlagWithArg("rsp-quoting", ArgIt, Argv)) continue; + if (strncmp(*ArgIt, "-X", 2) == 0) { + if (object::Archive::getDefaultKindForHost() == + object::Archive::K_AIXBIG) { + Match = *(*ArgIt + 2) != '\0' ? *ArgIt + 2 : *(++ArgIt); + BitMode = getBitMode(Match); + if (BitMode == BitModeTy::Unknown) + fail(Twine("invalid bit mode: ") + Match); + continue; + } else { + fail(Twine(*ArgIt) + " option not supported on non AIX OS"); + } + } + Options += *ArgIt + 1; } diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 52c202fded..4f9cd76c6a 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -417,12 +417,13 @@ LLVMValueRef ZigLLVMAddFunctionInAddressSpace(LLVMModuleRef M, const char *Name, return wrap(func); } -LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, - unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, const char *Name) +LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef Ty, LLVMValueRef Fn, + LLVMValueRef *Args, unsigned NumArgs, ZigLLVM_CallingConv CC, ZigLLVM_CallAttr attr, + const char *Name) { - Value *V = unwrap(Fn); - FunctionType *FnT = cast<FunctionType>(V->getType()->getNonOpaquePointerElementType()); - CallInst *call_inst = CallInst::Create(FnT, V, makeArrayRef(unwrap(Args), NumArgs), Name); + FunctionType *FTy = unwrap<FunctionType>(Ty); + CallInst *call_inst = unwrap(B)->CreateCall(FTy, unwrap(Fn), makeArrayRef(unwrap(Args), + NumArgs), Name); call_inst->setCallingConv(static_cast<CallingConv::ID>(CC)); switch (attr) { case ZigLLVM_CallAttrAuto: @@ -440,7 +441,7 @@ LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *A call_inst->addFnAttr(Attribute::AlwaysInline); break; } - return wrap(unwrap(B)->Insert(call_inst)); + return wrap(call_inst); } LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, @@ -1194,6 +1195,10 @@ void ZigLLVMSetCallElemTypeAttr(LLVMValueRef Call, size_t arg_index, LLVMTypeRef Attribute::get(call_inst->getContext(), Attribute::ElementType, llvm_type)); } +LLVMTypeRef ZigLLVMGetGEPResultElementType(LLVMValueRef GEP) { + return wrap(unwrap<GEPOperator>(GEP)->getResultElementType()); +} + void ZigLLVMFunctionSetPrefixData(LLVMValueRef function, LLVMValueRef data) { unwrap<Function>(function)->setPrefixData(unwrap<Constant>(data)); } diff --git a/src/zig_llvm.h b/src/zig_llvm.h index 804caf616e..7fdddda6a4 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -125,8 +125,9 @@ enum ZigLLVM_CallAttr { ZigLLVM_CallAttrAlwaysTail, ZigLLVM_CallAttrAlwaysInline, }; -ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMValueRef Fn, LLVMValueRef *Args, - unsigned NumArgs, enum ZigLLVM_CallingConv CC, enum ZigLLVM_CallAttr attr, const char *Name); +ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildCall(LLVMBuilderRef B, LLVMTypeRef function_type, + LLVMValueRef Fn, LLVMValueRef *Args, unsigned NumArgs, enum ZigLLVM_CallingConv CC, + enum ZigLLVM_CallAttr attr, const char *Name); ZIG_EXTERN_C LLVMValueRef ZigLLVMBuildMemCpy(LLVMBuilderRef B, LLVMValueRef Dst, unsigned DstAlign, LLVMValueRef Src, unsigned SrcAlign, LLVMValueRef Size, bool isVolatile); @@ -321,11 +322,15 @@ ZIG_EXTERN_C void ZigLLVMAddSretAttr(LLVMValueRef fn_ref, LLVMTypeRef type_val); ZIG_EXTERN_C void ZigLLVMAddFunctionElemTypeAttr(LLVMValueRef fn_ref, size_t arg_index, LLVMTypeRef elem_ty); ZIG_EXTERN_C void ZigLLVMAddFunctionAttrCold(LLVMValueRef fn); +ZIG_EXTERN_C LLVMTypeRef ZigLLVMGetGEPResultElementType(LLVMValueRef GEP); + ZIG_EXTERN_C void ZigLLVMParseCommandLineOptions(size_t argc, const char *const *argv); -// copied from include/llvm/ADT/Triple.h -// synchronize with target.cpp::arch_list +// synchronize with llvm/include/ADT/Triple.h::ArchType +// synchronize with std.Target.Cpu.Arch +// synchronize with src/stage1/target.cpp::arch_list +// synchronize with codegen/llvm/bindings.zig::ArchType enum ZigLLVM_ArchType { ZigLLVM_UnknownArch, @@ -339,7 +344,10 @@ enum ZigLLVM_ArchType { ZigLLVM_bpfel, // eBPF or extended BPF or 64-bit BPF (little endian) ZigLLVM_bpfeb, // eBPF or extended BPF or 64-bit BPF (big endian) ZigLLVM_csky, // CSKY: csky + ZigLLVM_dxil, // DXIL 32-bit DirectX bytecode ZigLLVM_hexagon, // Hexagon: hexagon + ZigLLVM_loongarch32, // LoongArch (32-bit): loongarch32 + ZigLLVM_loongarch64, // LoongArch (64-bit): loongarch64 ZigLLVM_m68k, // M68k: Motorola 680x0 family ZigLLVM_mips, // MIPS: mips, mipsallegrex, mipsr6 ZigLLVM_mipsel, // MIPSEL: mipsel, mipsallegrexe, mipsr6el @@ -409,6 +417,10 @@ enum ZigLLVM_VendorType { ZigLLVM_LastVendorType = ZigLLVM_OpenEmbedded }; +// synchronize with llvm/include/ADT/Triple.h::OsType +// synchronize with std.Target.Os.Tag +// synchronize with codegen/llvm/bindings.zig::OsType +// synchronize with src/stage1/target.cpp::os_list enum ZigLLVM_OSType { ZigLLVM_UnknownOS, @@ -437,9 +449,11 @@ enum ZigLLVM_OSType { ZigLLVM_NVCL, // NVIDIA OpenCL ZigLLVM_AMDHSA, // AMD HSA Runtime ZigLLVM_PS4, + ZigLLVM_PS5, ZigLLVM_ELFIAMCU, ZigLLVM_TvOS, // Apple tvOS ZigLLVM_WatchOS, // Apple watchOS + ZigLLVM_DriverKit, // Apple DriverKit ZigLLVM_Mesa3D, ZigLLVM_Contiki, ZigLLVM_AMDPAL, // AMD PAL Runtime @@ -447,8 +461,8 @@ enum ZigLLVM_OSType { ZigLLVM_Hurd, // GNU/Hurd ZigLLVM_WASI, // Experimental WebAssembly OS ZigLLVM_Emscripten, - - ZigLLVM_LastOSType = ZigLLVM_Emscripten + ZigLLVM_ShaderModel, // DirectX ShaderModel + ZigLLVM_LastOSType = ZigLLVM_ShaderModel }; // Synchronize with target.cpp::abi_list @@ -477,16 +491,35 @@ enum ZigLLVM_EnvironmentType { ZigLLVM_CoreCLR, ZigLLVM_Simulator, // Simulator variants of other systems, e.g., Apple's iOS ZigLLVM_MacABI, // Mac Catalyst variant of Apple's iOS deployment target. - ZigLLVM_LastEnvironmentType = ZigLLVM_MacABI + + ZigLLVM_Pixel, + ZigLLVM_Vertex, + ZigLLVM_Geometry, + ZigLLVM_Hull, + ZigLLVM_Domain, + ZigLLVM_Compute, + ZigLLVM_Library, + ZigLLVM_RayGeneration, + ZigLLVM_Intersection, + ZigLLVM_AnyHit, + ZigLLVM_ClosestHit, + ZigLLVM_Miss, + ZigLLVM_Callable, + ZigLLVM_Mesh, + ZigLLVM_Amplification, + + ZigLLVM_LastEnvironmentType = ZigLLVM_Amplification }; enum ZigLLVM_ObjectFormatType { ZigLLVM_UnknownObjectFormat, ZigLLVM_COFF, + ZigLLVM_DXContainer, ZigLLVM_ELF, ZigLLVM_GOFF, ZigLLVM_MachO, + ZigLLVM_SPIRV, ZigLLVM_Wasm, ZigLLVM_XCOFF, }; |
