| ... | @@ -140,6 +140,29 @@ pub fn generateFunction( | ... | @@ -140,6 +140,29 @@ pub fn generateFunction( |
| 140 | } | 140 | } |
| 141 | } | 141 | } |
| 142 | | 142 | |
| | 143 | fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void { |
| | 144 | if (F == f80) { |
| | 145 | switch (target.cpu.arch) { |
| | 146 | .i386, .x86_64 => { |
| | 147 | const repr = math.break_f80(f); |
| | 148 | mem.writeIntLittle(u64, code[0..8], repr.fraction); |
| | 149 | mem.writeIntLittle(u16, code[8..10], repr.exp); |
| | 150 | // TODO set the rest of the bytes to undefined. should we use 0xaa |
| | 151 | // or is there a different way? |
| | 152 | return; |
| | 153 | }, |
| | 154 | else => {}, |
| | 155 | } |
| | 156 | } else { |
| | 157 | const Int = @Type(.{ .Int = .{ |
| | 158 | .signedness = .unsigned, |
| | 159 | .bits = @typeInfo(F).Float.bits, |
| | 160 | } }); |
| | 161 | const int = @bitCast(Int, f); |
| | 162 | mem.writeInt(Int, code[0..@sizeOf(Int)], int, endian); |
| | 163 | } |
| | 164 | } |
| | 165 | |
| 143 | pub fn generateSymbol( | 166 | pub fn generateSymbol( |
| 144 | bin_file: *link.File, | 167 | bin_file: *link.File, |
| 145 | src_loc: Module.SrcLoc, | 168 | src_loc: Module.SrcLoc, |
| ... | @@ -151,10 +174,12 @@ pub fn generateSymbol( | ... | @@ -151,10 +174,12 @@ pub fn generateSymbol( |
| 151 | const tracy = trace(@src()); | 174 | const tracy = trace(@src()); |
| 152 | defer tracy.end(); | 175 | defer tracy.end(); |
| 153 | | 176 | |
| | 177 | const target = bin_file.options.target; |
| | 178 | const endian = target.cpu.arch.endian(); |
| | 179 | |
| 154 | log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val }); | 180 | log.debug("generateSymbol: ty = {}, val = {}", .{ typed_value.ty, typed_value.val }); |
| 155 | | 181 | |
| 156 | if (typed_value.val.isUndefDeep()) { | 182 | if (typed_value.val.isUndefDeep()) { |
| 157 | const target = bin_file.options.target; | | |
| 158 | const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); | 183 | const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); |
| 159 | try code.appendNTimes(0xaa, abi_size); | 184 | try code.appendNTimes(0xaa, abi_size); |
| 160 | return Result{ .appended = {} }; | 185 | return Result{ .appended = {} }; |
| ... | @@ -171,6 +196,18 @@ pub fn generateSymbol( | ... | @@ -171,6 +196,18 @@ pub fn generateSymbol( |
| 171 | ), | 196 | ), |
| 172 | }; | 197 | }; |
| 173 | }, | 198 | }, |
| | 199 | .Float => { |
| | 200 | const float_bits = typed_value.ty.floatBits(target); |
| | 201 | switch (float_bits) { |
| | 202 | 16 => writeFloat(f16, typed_value.val.toFloat(f16), target, endian, try code.addManyAsArray(2)), |
| | 203 | 32 => writeFloat(f32, typed_value.val.toFloat(f32), target, endian, try code.addManyAsArray(4)), |
| | 204 | 64 => writeFloat(f64, typed_value.val.toFloat(f64), target, endian, try code.addManyAsArray(8)), |
| | 205 | 80 => writeFloat(f80, typed_value.val.toFloat(f80), target, endian, try code.addManyAsArray(10)), |
| | 206 | 128 => writeFloat(f128, typed_value.val.toFloat(f128), target, endian, try code.addManyAsArray(16)), |
| | 207 | else => unreachable, |
| | 208 | } |
| | 209 | return Result{ .appended = {} }; |
| | 210 | }, |
| 174 | .Array => switch (typed_value.val.tag()) { | 211 | .Array => switch (typed_value.val.tag()) { |
| 175 | .bytes => { | 212 | .bytes => { |
| 176 | // TODO populate .debug_info for the array | 213 | // TODO populate .debug_info for the array |
| ... | @@ -311,7 +348,6 @@ pub fn generateSymbol( | ... | @@ -311,7 +348,6 @@ pub fn generateSymbol( |
| 311 | return Result{ .appended = {} }; | 348 | return Result{ .appended = {} }; |
| 312 | }, | 349 | }, |
| 313 | .field_ptr => { | 350 | .field_ptr => { |
| 314 | const target = bin_file.options.target; | | |
| 315 | const field_ptr = typed_value.val.castTag(.field_ptr).?.data; | 351 | const field_ptr = typed_value.val.castTag(.field_ptr).?.data; |
| 316 | const container_ptr = field_ptr.container_ptr; | 352 | const container_ptr = field_ptr.container_ptr; |
| 317 | | 353 | |
| ... | @@ -373,7 +409,6 @@ pub fn generateSymbol( | ... | @@ -373,7 +409,6 @@ pub fn generateSymbol( |
| 373 | }, | 409 | }, |
| 374 | .Int => { | 410 | .Int => { |
| 375 | // TODO populate .debug_info for the integer | 411 | // TODO populate .debug_info for the integer |
| 376 | const endian = bin_file.options.target.cpu.arch.endian(); | | |
| 377 | const info = typed_value.ty.intInfo(bin_file.options.target); | 412 | const info = typed_value.ty.intInfo(bin_file.options.target); |
| 378 | if (info.bits <= 8) { | 413 | if (info.bits <= 8) { |
| 379 | const x = @intCast(u8, typed_value.val.toUnsignedInt()); | 414 | const x = @intCast(u8, typed_value.val.toUnsignedInt()); |
| ... | @@ -423,7 +458,6 @@ pub fn generateSymbol( | ... | @@ -423,7 +458,6 @@ pub fn generateSymbol( |
| 423 | var int_buffer: Value.Payload.U64 = undefined; | 458 | var int_buffer: Value.Payload.U64 = undefined; |
| 424 | const int_val = typed_value.enumToInt(&int_buffer); | 459 | const int_val = typed_value.enumToInt(&int_buffer); |
| 425 | | 460 | |
| 426 | const target = bin_file.options.target; | | |
| 427 | const info = typed_value.ty.intInfo(target); | 461 | const info = typed_value.ty.intInfo(target); |
| 428 | if (info.bits <= 8) { | 462 | if (info.bits <= 8) { |
| 429 | const x = @intCast(u8, int_val.toUnsignedInt()); | 463 | const x = @intCast(u8, int_val.toUnsignedInt()); |
| ... | @@ -440,7 +474,6 @@ pub fn generateSymbol( | ... | @@ -440,7 +474,6 @@ pub fn generateSymbol( |
| 440 | ), | 474 | ), |
| 441 | }; | 475 | }; |
| 442 | } | 476 | } |
| 443 | const endian = target.cpu.arch.endian(); | | |
| 444 | switch (info.signedness) { | 477 | switch (info.signedness) { |
| 445 | .unsigned => { | 478 | .unsigned => { |
| 446 | if (info.bits <= 16) { | 479 | if (info.bits <= 16) { |
| ... | @@ -506,7 +539,6 @@ pub fn generateSymbol( | ... | @@ -506,7 +539,6 @@ pub fn generateSymbol( |
| 506 | const unpadded_field_end = code.items.len - struct_begin; | 539 | const unpadded_field_end = code.items.len - struct_begin; |
| 507 | | 540 | |
| 508 | // Pad struct members if required | 541 | // Pad struct members if required |
| 509 | const target = bin_file.options.target; | | |
| 510 | const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target); | 542 | const padded_field_end = typed_value.ty.structFieldOffset(index + 1, target); |
| 511 | const padding = try math.cast(usize, padded_field_end - unpadded_field_end); | 543 | const padding = try math.cast(usize, padded_field_end - unpadded_field_end); |
| 512 | | 544 | |
| ... | @@ -519,7 +551,6 @@ pub fn generateSymbol( | ... | @@ -519,7 +551,6 @@ pub fn generateSymbol( |
| 519 | }, | 551 | }, |
| 520 | .Union => { | 552 | .Union => { |
| 521 | // TODO generate debug info for unions | 553 | // TODO generate debug info for unions |
| 522 | const target = bin_file.options.target; | | |
| 523 | const union_obj = typed_value.val.castTag(.@"union").?.data; | 554 | const union_obj = typed_value.val.castTag(.@"union").?.data; |
| 524 | const layout = typed_value.ty.unionGetLayout(target); | 555 | const layout = typed_value.ty.unionGetLayout(target); |
| 525 | | 556 | |
| ... | @@ -590,19 +621,69 @@ pub fn generateSymbol( | ... | @@ -590,19 +621,69 @@ pub fn generateSymbol( |
| 590 | return Result{ .appended = {} }; | 621 | return Result{ .appended = {} }; |
| 591 | }, | 622 | }, |
| 592 | .Optional => { | 623 | .Optional => { |
| 593 | // TODO generateSymbol for optionals | 624 | // TODO generate debug info for optionals |
| 594 | const target = bin_file.options.target; | 625 | var opt_buf: Type.Payload.ElemType = undefined; |
| | 626 | const payload_type = typed_value.ty.optionalChild(&opt_buf); |
| | 627 | const is_pl = !typed_value.val.isNull(); |
| 595 | const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); | 628 | const abi_size = try math.cast(usize, typed_value.ty.abiSize(target)); |
| 596 | try code.writer().writeByteNTimes(0xaa, abi_size); | 629 | const offset = abi_size - try math.cast(usize, payload_type.abiSize(target)); |
| | 630 | |
| | 631 | if (!payload_type.hasRuntimeBits()) { |
| | 632 | try code.writer().writeByteNTimes(@boolToInt(is_pl), abi_size); |
| | 633 | return Result{ .appended = {} }; |
| | 634 | } |
| | 635 | |
| | 636 | if (typed_value.ty.isPtrLikeOptional()) { |
| | 637 | if (typed_value.val.castTag(.opt_payload)) |payload| { |
| | 638 | switch (try generateSymbol(bin_file, src_loc, .{ |
| | 639 | .ty = payload_type, |
| | 640 | .val = payload.data, |
| | 641 | }, code, debug_output, reloc_info)) { |
| | 642 | .appended => {}, |
| | 643 | .externally_managed => |external_slice| { |
| | 644 | code.appendSliceAssumeCapacity(external_slice); |
| | 645 | }, |
| | 646 | .fail => |em| return Result{ .fail = em }, |
| | 647 | } |
| | 648 | } else if (!typed_value.val.isNull()) { |
| | 649 | switch (try generateSymbol(bin_file, src_loc, .{ |
| | 650 | .ty = payload_type, |
| | 651 | .val = typed_value.val, |
| | 652 | }, code, debug_output, reloc_info)) { |
| | 653 | .appended => {}, |
| | 654 | .externally_managed => |external_slice| { |
| | 655 | code.appendSliceAssumeCapacity(external_slice); |
| | 656 | }, |
| | 657 | .fail => |em| return Result{ .fail = em }, |
| | 658 | } |
| | 659 | } else { |
| | 660 | try code.writer().writeByteNTimes(0, abi_size); |
| | 661 | } |
| | 662 | |
| | 663 | return Result{ .appended = {} }; |
| | 664 | } |
| | 665 | |
| | 666 | const value = if (typed_value.val.castTag(.opt_payload)) |payload| payload.data else Value.initTag(.undef); |
| | 667 | try code.writer().writeByteNTimes(@boolToInt(is_pl), offset); |
| | 668 | switch (try generateSymbol(bin_file, src_loc, .{ |
| | 669 | .ty = payload_type, |
| | 670 | .val = value, |
| | 671 | }, code, debug_output, reloc_info)) { |
| | 672 | .appended => {}, |
| | 673 | .externally_managed => |external_slice| { |
| | 674 | code.appendSliceAssumeCapacity(external_slice); |
| | 675 | }, |
| | 676 | .fail => |em| return Result{ .fail = em }, |
| | 677 | } |
| 597 | | 678 | |
| 598 | return Result{ .appended = {} }; | 679 | return Result{ .appended = {} }; |
| 599 | }, | 680 | }, |
| 600 | .ErrorUnion => { | 681 | .ErrorUnion => { |
| | 682 | // TODO generate debug info for error unions |
| 601 | const error_ty = typed_value.ty.errorUnionSet(); | 683 | const error_ty = typed_value.ty.errorUnionSet(); |
| 602 | const payload_ty = typed_value.ty.errorUnionPayload(); | 684 | const payload_ty = typed_value.ty.errorUnionPayload(); |
| 603 | const is_payload = typed_value.val.errorUnionIsPayload(); | 685 | const is_payload = typed_value.val.errorUnionIsPayload(); |
| 604 | | 686 | |
| 605 | const target = bin_file.options.target; | | |
| 606 | const abi_align = typed_value.ty.abiAlignment(target); | 687 | const abi_align = typed_value.ty.abiAlignment(target); |
| 607 | | 688 | |
| 608 | const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero); | 689 | const error_val = if (!is_payload) typed_value.val else Value.initTag(.zero); |
| ... | @@ -643,12 +724,11 @@ pub fn generateSymbol( | ... | @@ -643,12 +724,11 @@ pub fn generateSymbol( |
| 643 | return Result{ .appended = {} }; | 724 | return Result{ .appended = {} }; |
| 644 | }, | 725 | }, |
| 645 | .ErrorSet => { | 726 | .ErrorSet => { |
| 646 | const target = bin_file.options.target; | 727 | // TODO generate debug info for error sets |
| 647 | switch (typed_value.val.tag()) { | 728 | switch (typed_value.val.tag()) { |
| 648 | .@"error" => { | 729 | .@"error" => { |
| 649 | const name = typed_value.val.getError().?; | 730 | const name = typed_value.val.getError().?; |
| 650 | const kv = try bin_file.options.module.?.getErrorValue(name); | 731 | const kv = try bin_file.options.module.?.getErrorValue(name); |
| 651 | const endian = target.cpu.arch.endian(); | | |
| 652 | try code.writer().writeInt(u32, kv.value, endian); | 732 | try code.writer().writeInt(u32, kv.value, endian); |
| 653 | }, | 733 | }, |
| 654 | else => { | 734 | else => { |