| author | |
| committer | |
| log | ce293c982e1b6d9db775e02fefb8905caa4ee748 |
| tree | bb3a9a7ef4746efaeb656857aff91172520ee309 |
| parent | 58789cb054b16e87d0a9b69ed8484cd30664fdb0 |
Changes:
- Add `isMangledIdent` to determine if `fmtIdent` would make any edits to the identifier
- Any function that has a mangled identifier is referred to using the mangled identifer
within the current file, but if it is exported the first export will be with the non-mangled name.
- Add `zig_import` to import a symbol under a different name
- Add a level of indirection to float function names. Now, they are referred to as
`zig_float_fn_<float type>_<operation>`. The definitions in zig.h are wrapped
with `zig_import` to import the symbol under the real name.
The specific problem that sparked this change was the combination of
`zig_libc_name_f80(name) __##name##x` with the input `fma`, resulting
in `__fmax`, which is a new intrinsic in recent versions of cl.exe.
With the above changes in place, compiler_rt can output the following:
```
static zig_weak_linkage_fn zig_f80 zig_e___fmax(zig_f80, zig_f80, zig_f80);
zig_export(zig_weak_linkage_fn zig_f80 zig_e___fmax(zig_f80, zig_f80, zig_f80), __fmax, "__fmax");
```
Within compiler_rt, `zig_e___fmax` is used to refer to the function, but consumers
will import `__fmax`, which maps to their `zig_float_fn_f80_fma` definition from zig.h.2 files changed, 89 insertions(+), 52 deletions(-)
lib/zig.h+42-28| ... | ... | @@ -175,19 +175,33 @@ typedef char bool; |
| 175 | 175 | #endif |
| 176 | 176 | |
| 177 | 177 | #if zig_has_attribute(alias) |
| 178 | #define zig_export(sig, symbol, name) zig_extern sig __attribute__((alias(symbol))) | |
| 178 | #define zig_export(sig, symbol, name) zig_extern sig __attribute__((alias(#symbol))) | |
| 179 | 179 | #elif _MSC_VER |
| 180 | 180 | #if _M_X64 |
| 181 | #define zig_export(sig, symbol, name) sig;\ | |
| 182 | __pragma(comment(linker, "/alternatename:" name "=" symbol )) | |
| 181 | #define zig_export(sig, symbol, name) zig_extern sig;\ | |
| 182 | __pragma(comment(linker, "/alternatename:" name "=" #symbol )) | |
| 183 | 183 | #else /*_M_X64 */ |
| 184 | #define zig_export(sig, symbol, name) sig;\ | |
| 185 | __pragma(comment(linker, "/alternatename:_" name "=_" symbol )) | |
| 184 | #define zig_export(sig, symbol, name) zig_extern sig;\ | |
| 185 | __pragma(comment(linker, "/alternatename:" name "=" #symbol )) | |
| 186 | 186 | #endif /*_M_X64 */ |
| 187 | 187 | #else |
| 188 | #define zig_export(sig, symbol, name) __asm(name " = " symbol) | |
| 188 | #define zig_export(sig, symbol, name) __asm(name " = " #symbol) | |
| 189 | 189 | #endif |
| 190 | 190 | |
| 191 | #if _MSC_VER | |
| 192 | #if _M_X64 | |
| 193 | #define zig_import(sig, symbol, name) sig;\ | |
| 194 | __pragma(comment(linker, "/alternatename:" #symbol "=" #name )) | |
| 195 | #else /*_M_X64 */ | |
| 196 | #define zig_import(sig, symbol, name) sig;\ | |
| 197 | __pragma(comment(linker, "/alternatename:_" #symbol "=_" #name )) | |
| 198 | #endif /*_M_X64 */ | |
| 199 | #else | |
| 200 | #define zig_import(sig, symbol, name) zig_extern sig asm(#name); | |
| 201 | #endif | |
| 202 | ||
| 203 | #define zig_expand_import(sig, symbol, name) zig_import(sig, symbol, name) | |
| 204 | ||
| 191 | 205 | #if zig_has_attribute(weak) || defined(zig_gnuc) |
| 192 | 206 | #define zig_weak_linkage __attribute__((weak)) |
| 193 | 207 | #define zig_weak_linkage_fn __attribute__((weak)) |
| ... | ... | @@ -3330,31 +3344,31 @@ zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) |
| 3330 | 3344 | zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, sub, -) \ |
| 3331 | 3345 | zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, mul, *) \ |
| 3332 | 3346 | zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, div, /) \ |
| 3333 | zig_extern zig_f##w zig_libc_name_f##w(sqrt)(zig_f##w); \ | |
| 3334 | zig_extern zig_f##w zig_libc_name_f##w(sin)(zig_f##w); \ | |
| 3335 | zig_extern zig_f##w zig_libc_name_f##w(cos)(zig_f##w); \ | |
| 3336 | zig_extern zig_f##w zig_libc_name_f##w(tan)(zig_f##w); \ | |
| 3337 | zig_extern zig_f##w zig_libc_name_f##w(exp)(zig_f##w); \ | |
| 3338 | zig_extern zig_f##w zig_libc_name_f##w(exp2)(zig_f##w); \ | |
| 3339 | zig_extern zig_f##w zig_libc_name_f##w(log)(zig_f##w); \ | |
| 3340 | zig_extern zig_f##w zig_libc_name_f##w(log2)(zig_f##w); \ | |
| 3341 | zig_extern zig_f##w zig_libc_name_f##w(log10)(zig_f##w); \ | |
| 3342 | zig_extern zig_f##w zig_libc_name_f##w(fabs)(zig_f##w); \ | |
| 3343 | zig_extern zig_f##w zig_libc_name_f##w(floor)(zig_f##w); \ | |
| 3344 | zig_extern zig_f##w zig_libc_name_f##w(ceil)(zig_f##w); \ | |
| 3345 | zig_extern zig_f##w zig_libc_name_f##w(round)(zig_f##w); \ | |
| 3346 | zig_extern zig_f##w zig_libc_name_f##w(trunc)(zig_f##w); \ | |
| 3347 | zig_extern zig_f##w zig_libc_name_f##w(fmod)(zig_f##w, zig_f##w); \ | |
| 3348 | zig_extern zig_f##w zig_libc_name_f##w(fmin)(zig_f##w, zig_f##w); \ | |
| 3349 | zig_extern zig_f##w zig_libc_name_f##w(fmax)(zig_f##w, zig_f##w); \ | |
| 3350 | zig_extern zig_f##w zig_libc_name_f##w(fma)(zig_f##w, zig_f##w, zig_f##w); \ | |
| 3347 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_sqrt(zig_f##w), zig_float_fn_f##w##_sqrt, zig_libc_name_f##w(sqrt)) \ | |
| 3348 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_sin(zig_f##w), zig_float_fn_f##w##_sin, zig_libc_name_f##w(sin)) \ | |
| 3349 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_cos(zig_f##w), zig_float_fn_f##w##_cos, zig_libc_name_f##w(cos)) \ | |
| 3350 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_tan(zig_f##w), zig_float_fn_f##w##_tan, zig_libc_name_f##w(tan)) \ | |
| 3351 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_exp(zig_f##w), zig_float_fn_f##w##_exp, zig_libc_name_f##w(exp)) \ | |
| 3352 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_exp2(zig_f##w), zig_float_fn_f##w##_exp2, zig_libc_name_f##w(exp2)) \ | |
| 3353 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_log(zig_f##w), zig_float_fn_f##w##_log, zig_libc_name_f##w(log)) \ | |
| 3354 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_log2(zig_f##w), zig_float_fn_f##w##_log2, zig_libc_name_f##w(log2)) \ | |
| 3355 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_log10(zig_f##w), zig_float_fn_f##w##_log10, zig_libc_name_f##w(log10)) \ | |
| 3356 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_fabs(zig_f##w), zig_float_fn_f##w##_fabs, zig_libc_name_f##w(fabs)) \ | |
| 3357 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_floor(zig_f##w), zig_float_fn_f##w##_floor, zig_libc_name_f##w(floor)) \ | |
| 3358 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_ceil(zig_f##w), zig_float_fn_f##w##_ceil, zig_libc_name_f##w(ceil)) \ | |
| 3359 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_round(zig_f##w), zig_float_fn_f##w##_round, zig_libc_name_f##w(round)) \ | |
| 3360 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_trunc(zig_f##w), zig_float_fn_f##w##_trunc, zig_libc_name_f##w(trunc)) \ | |
| 3361 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_fmod(zig_f##w, zig_f##w), zig_float_fn_f##w##_fmod, zig_libc_name_f##w(fmod)) \ | |
| 3362 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_fmin(zig_f##w, zig_f##w), zig_float_fn_f##w##_fmin, zig_libc_name_f##w(fmin)) \ | |
| 3363 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_fmax(zig_f##w, zig_f##w), zig_float_fn_f##w##_fmax, zig_libc_name_f##w(fmax)) \ | |
| 3364 | zig_expand_import(zig_extern zig_f##w zig_float_fn_f##w##_fma(zig_f##w, zig_f##w, zig_f##w), zig_float_fn_f##w##_fma, zig_libc_name_f##w(fma)) \ | |
| 3351 | 3365 | \ |
| 3352 | 3366 | static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \ |
| 3353 | return zig_libc_name_f##w(trunc)(zig_div_f##w(lhs, rhs)); \ | |
| 3367 | return zig_float_fn_f##w##_trunc(zig_div_f##w(lhs, rhs)); \ | |
| 3354 | 3368 | } \ |
| 3355 | 3369 | \ |
| 3356 | 3370 | static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \ |
| 3357 | return zig_libc_name_f##w(floor)(zig_div_f##w(lhs, rhs)); \ | |
| 3371 | return zig_float_fn_f##w##_floor(zig_div_f##w(lhs, rhs)); \ | |
| 3358 | 3372 | } \ |
| 3359 | 3373 | \ |
| 3360 | 3374 | static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \ |
| ... | ... | @@ -3458,7 +3472,7 @@ zig_float_builtins(64) |
| 3458 | 3472 | zig_##Type zig_atomicrmw_desired; \ |
| 3459 | 3473 | zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \ |
| 3460 | 3474 | do { \ |
| 3461 | zig_atomicrmw_desired = zig_libc_name_##Type(fmin)(zig_atomicrmw_expected, arg); \ | |
| 3475 | zig_atomicrmw_desired = zig_float_fn_##Type##_fmin(zig_atomicrmw_expected, arg); \ | |
| 3462 | 3476 | } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \ |
| 3463 | 3477 | res = zig_atomicrmw_expected; \ |
| 3464 | 3478 | } while (0) |
| ... | ... | @@ -3467,7 +3481,7 @@ zig_float_builtins(64) |
| 3467 | 3481 | zig_##Type zig_atomicrmw_desired; \ |
| 3468 | 3482 | zig_atomic_load(zig_atomicrmw_expected, obj, memory_order_relaxed, Type, ReprType); \ |
| 3469 | 3483 | do { \ |
| 3470 | zig_atomicrmw_desired = zig_libc_name_##Type(fmax)(zig_atomicrmw_expected, arg); \ | |
| 3484 | zig_atomicrmw_desired = zig_float_fn_##Type##_fmax(zig_atomicrmw_expected, arg); \ | |
| 3471 | 3485 | } while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, memory_order_relaxed, Type, ReprType)); \ |
| 3472 | 3486 | res = zig_atomicrmw_expected; \ |
| 3473 | 3487 | } while (0) |
src/codegen/c.zig+47-24| ... | ... | @@ -258,6 +258,20 @@ pub fn fmtIdent(ident: []const u8) std.fmt.Formatter(formatIdent) { |
| 258 | 258 | return .{ .data = ident }; |
| 259 | 259 | } |
| 260 | 260 | |
| 261 | // Returns true if `formatIdent` would make any edits to ident. | |
| 262 | // This must be kept in sync with `formatIdent`. | |
| 263 | pub fn isMangledIdent(ident: []const u8, solo: bool) bool { | |
| 264 | if (solo and isReservedIdent(ident)) return true; | |
| 265 | for (ident, 0..) |c, i| { | |
| 266 | switch (c) { | |
| 267 | 'a'...'z', 'A'...'Z', '_' => {}, | |
| 268 | '0'...'9' => if (i == 0) return true, | |
| 269 | else => return true, | |
| 270 | } | |
| 271 | } | |
| 272 | return false; | |
| 273 | } | |
| 274 | ||
| 261 | 275 | /// This data is available when outputting .c code for a `InternPool.Index` |
| 262 | 276 | /// that corresponds to `func`. |
| 263 | 277 | /// It is not available when generating .h file. |
| ... | ... | @@ -526,6 +540,7 @@ pub const DeclGen = struct { |
| 526 | 540 | is_naked_fn: bool, |
| 527 | 541 | /// This is a borrowed reference from `link.C`. |
| 528 | 542 | fwd_decl: std.ArrayList(u8), |
| 543 | ||
| 529 | 544 | error_msg: ?*Module.ErrorMsg, |
| 530 | 545 | ctypes: CType.Store, |
| 531 | 546 | /// Keeps track of anonymous decls that need to be rendered before this |
| ... | ... | @@ -1598,7 +1613,7 @@ pub const DeclGen = struct { |
| 1598 | 1613 | |
| 1599 | 1614 | switch (name) { |
| 1600 | 1615 | .export_index => |export_index| try dg.renderDeclName(w, fn_decl_index, export_index), |
| 1601 | .string => |string| try w.writeAll(string), | |
| 1616 | .string => |string| try w.print("{ }", .{fmtIdent(string)}), | |
| 1602 | 1617 | } |
| 1603 | 1618 | |
| 1604 | 1619 | try renderTypeSuffix( |
| ... | ... | @@ -1813,9 +1828,17 @@ pub const DeclGen = struct { |
| 1813 | 1828 | fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool { |
| 1814 | 1829 | const mod = dg.module; |
| 1815 | 1830 | return switch (mod.intern_pool.indexToKey(tv.val.ip_index)) { |
| 1816 | .variable => |variable| mod.decl_exports.contains(variable.decl), | |
| 1831 | .variable => |variable| { | |
| 1832 | if (mod.decl_exports.get(variable.decl)) |exports| { | |
| 1833 | return !isMangledIdent(dg.module.intern_pool.stringToSlice(exports.items[0].opts.name), true); | |
| 1834 | } else return false; | |
| 1835 | }, | |
| 1817 | 1836 | .extern_func => true, |
| 1818 | .func => |func| mod.decl_exports.contains(func.owner_decl), | |
| 1837 | .func => |func| { | |
| 1838 | if (mod.decl_exports.get(func.owner_decl)) |exports| { | |
| 1839 | return !isMangledIdent(dg.module.intern_pool.stringToSlice(exports.items[0].opts.name), true); | |
| 1840 | } else return false; | |
| 1841 | }, | |
| 1819 | 1842 | else => unreachable, |
| 1820 | 1843 | }; |
| 1821 | 1844 | } |
| ... | ... | @@ -1925,9 +1948,9 @@ pub const DeclGen = struct { |
| 1925 | 1948 | try mod.markDeclAlive(decl); |
| 1926 | 1949 | |
| 1927 | 1950 | if (mod.decl_exports.get(decl_index)) |exports| { |
| 1928 | try writer.print("{}", .{exports.items[export_index].opts.name.fmt(&mod.intern_pool)}); | |
| 1951 | try writer.print("{ }", .{fmtIdent(mod.intern_pool.stringToSlice(exports.items[export_index].opts.name))}); | |
| 1929 | 1952 | } else if (decl.getExternDecl(mod).unwrap()) |extern_decl_index| { |
| 1930 | try writer.print("{}", .{mod.declPtr(extern_decl_index).name.fmt(&mod.intern_pool)}); | |
| 1953 | try writer.print("{ }", .{fmtIdent(mod.intern_pool.stringToSlice(mod.declPtr(extern_decl_index).name))}); | |
| 1931 | 1954 | } else { |
| 1932 | 1955 | // MSVC has a limit of 4095 character token length limit, and fmtIdent can (worst case), |
| 1933 | 1956 | // expand to 3x the length of its input, but let's cut it off at a much shorter limit. |
| ... | ... | @@ -2564,16 +2587,19 @@ fn genExports(o: *Object) !void { |
| 2564 | 2587 | const fwd = o.dg.fwd_decl.writer(); |
| 2565 | 2588 | |
| 2566 | 2589 | const exports = mod.decl_exports.get(decl_index) orelse return; |
| 2567 | if (exports.items.len < 2) return; | |
| 2590 | ||
| 2591 | const is_mangled = isMangledIdent(ip.stringToSlice(exports.items[0].opts.name), true); | |
| 2592 | if (exports.items.len < 2 and !is_mangled) return; | |
| 2568 | 2593 | |
| 2569 | 2594 | switch (ip.indexToKey(tv.val.toIntern())) { |
| 2570 | 2595 | .func => { |
| 2571 | for (exports.items[1..], 1..) |@"export", i| { | |
| 2596 | const start_i = 1 - @intFromBool(is_mangled); | |
| 2597 | for (exports.items[start_i..], start_i..) |@"export", i| { | |
| 2572 | 2598 | try fwd.writeAll("zig_export("); |
| 2573 | 2599 | if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage_fn "); |
| 2574 | 2600 | try o.dg.renderFunctionSignature(fwd, decl_index, .forward, .{ .export_index = @as(u32, @intCast(i)) }); |
| 2575 | try fwd.print(", {s}, {s});\n", .{ | |
| 2576 | fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null), | |
| 2601 | try fwd.print(", { }, {s});\n", .{ | |
| 2602 | fmtIdent(ip.stringToSlice(exports.items[0].opts.name)), | |
| 2577 | 2603 | fmtStringLiteral(ip.stringToSlice(@"export".opts.name), null), |
| 2578 | 2604 | }); |
| 2579 | 2605 | } |
| ... | ... | @@ -2583,7 +2609,8 @@ fn genExports(o: *Object) !void { |
| 2583 | 2609 | unreachable; |
| 2584 | 2610 | }, |
| 2585 | 2611 | .variable => |variable| { |
| 2586 | for (exports.items[1..], 1..) |@"export", i| { | |
| 2612 | const start_i = 1 - @intFromBool(is_mangled); | |
| 2613 | for (exports.items[start_i..], start_i..) |@"export", i| { | |
| 2587 | 2614 | try fwd.writeAll("zig_export("); |
| 2588 | 2615 | if (exports.items[i].opts.linkage == .Weak) try fwd.writeAll("zig_weak_linkage "); |
| 2589 | 2616 | const alias = ip.stringToSlice(@"export".opts.name); |
| ... | ... | @@ -2595,8 +2622,8 @@ fn genExports(o: *Object) !void { |
| 2595 | 2622 | decl.alignment, |
| 2596 | 2623 | .complete, |
| 2597 | 2624 | ); |
| 2598 | try fwd.print(", {s}, {s});\n", .{ | |
| 2599 | fmtStringLiteral(ip.stringToSlice(exports.items[0].opts.name), null), | |
| 2625 | try fwd.print(", { }, {s});\n", .{ | |
| 2626 | fmtIdent(ip.stringToSlice(exports.items[0].opts.name)), | |
| 2600 | 2627 | fmtStringLiteral(alias, null), |
| 2601 | 2628 | }); |
| 2602 | 2629 | } |
| ... | ... | @@ -6861,9 +6888,9 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6861 | 6888 | try f.writeCValue(writer, accum, .Other); |
| 6862 | 6889 | switch (op) { |
| 6863 | 6890 | .float_op => |func| { |
| 6864 | try writer.writeAll(" = zig_libc_name_"); | |
| 6891 | try writer.writeAll(" = zig_float_fn_"); | |
| 6865 | 6892 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| 6866 | try writer.print("({s})(", .{func.operation}); | |
| 6893 | try writer.print("_{s}(", .{func.operation}); | |
| 6867 | 6894 | try f.writeCValue(writer, accum, .FunctionArgument); |
| 6868 | 6895 | try writer.writeAll(", "); |
| 6869 | 6896 | try f.writeCValue(writer, operand, .Other); |
| ... | ... | @@ -7195,11 +7222,9 @@ fn unFloatOp(f: *Function, inst: Air.Inst.Index, operand: CValue, ty: Type, oper |
| 7195 | 7222 | const v = try Vectorize.start(f, inst, writer, ty); |
| 7196 | 7223 | try f.writeCValue(writer, local, .Other); |
| 7197 | 7224 | try v.elem(f, writer); |
| 7198 | try writer.writeAll(" = zig_libc_name_"); | |
| 7225 | try writer.writeAll(" = zig_float_fn_"); | |
| 7199 | 7226 | try f.object.dg.renderTypeForBuiltinFnName(writer, scalar_ty); |
| 7200 | try writer.writeByte('('); | |
| 7201 | try writer.writeAll(operation); | |
| 7202 | try writer.writeAll(")("); | |
| 7227 | try writer.print("_{s}(", .{operation}); | |
| 7203 | 7228 | try f.writeCValue(writer, operand, .FunctionArgument); |
| 7204 | 7229 | try v.elem(f, writer); |
| 7205 | 7230 | try writer.writeAll(");\n"); |
| ... | ... | @@ -7234,11 +7259,9 @@ fn airBinFloatOp(f: *Function, inst: Air.Inst.Index, operation: []const u8) !CVa |
| 7234 | 7259 | const v = try Vectorize.start(f, inst, writer, inst_ty); |
| 7235 | 7260 | try f.writeCValue(writer, local, .Other); |
| 7236 | 7261 | try v.elem(f, writer); |
| 7237 | try writer.writeAll(" = zig_libc_name_"); | |
| 7262 | try writer.writeAll(" = zig_float_fn_"); | |
| 7238 | 7263 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); |
| 7239 | try writer.writeByte('('); | |
| 7240 | try writer.writeAll(operation); | |
| 7241 | try writer.writeAll(")("); | |
| 7264 | try writer.print("_{s}(", .{operation}); | |
| 7242 | 7265 | try f.writeCValue(writer, lhs, .FunctionArgument); |
| 7243 | 7266 | try v.elem(f, writer); |
| 7244 | 7267 | try writer.writeAll(", "); |
| ... | ... | @@ -7268,9 +7291,9 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue { |
| 7268 | 7291 | const v = try Vectorize.start(f, inst, writer, inst_ty); |
| 7269 | 7292 | try f.writeCValue(writer, local, .Other); |
| 7270 | 7293 | try v.elem(f, writer); |
| 7271 | try writer.writeAll(" = zig_libc_name_"); | |
| 7294 | try writer.writeAll(" = zig_float_fn_"); | |
| 7272 | 7295 | try f.object.dg.renderTypeForBuiltinFnName(writer, inst_scalar_ty); |
| 7273 | try writer.writeAll("(fma)("); | |
| 7296 | try writer.writeAll("_fma("); | |
| 7274 | 7297 | try f.writeCValue(writer, mulend1, .FunctionArgument); |
| 7275 | 7298 | try v.elem(f, writer); |
| 7276 | 7299 | try writer.writeAll(", "); |