| author | |
| committer | |
| log | b2cb090c3790dd10a784f9e291230cf6052b514c |
| tree | ea100c2fcb20b1b8f73856bc01f25fdbc1a07c13 |
| parent | 031d8248e02f019a4c689dfa2913b30ec796dfa5 |
| signature |
6 files changed, 116 insertions(+), 65 deletions(-)
src/arch/riscv64/CodeGen.zig+22-9| ... | @@ -5226,13 +5226,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! | ... | @@ -5226,13 +5226,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 5226 | 5226 | ||
| 5227 | const src_reg_class = src_reg.class(); | 5227 | const src_reg_class = src_reg.class(); |
| 5228 | 5228 | ||
| 5229 | if (src_reg_class == .float) { | 5229 | if (src_reg_class == .float and dst_reg_class == .int) { |
| 5230 | if (dst_reg_class == .float) { | ||
| 5231 | return self.fail("TODO: genSetReg float -> float", .{}); | ||
| 5232 | } | ||
| 5233 | |||
| 5234 | assert(dst_reg_class == .int); // a bit of future proofing | ||
| 5235 | |||
| 5236 | // to move from float -> int, we use FMV.X.W | 5230 | // to move from float -> int, we use FMV.X.W |
| 5237 | return self.fail("TODO: genSetReg float -> int", .{}); | 5231 | return self.fail("TODO: genSetReg float -> int", .{}); |
| 5238 | } | 5232 | } |
| ... | @@ -6031,6 +6025,7 @@ fn resolveCallingConventionValues( | ... | @@ -6031,6 +6025,7 @@ fn resolveCallingConventionValues( |
| 6031 | } else { | 6025 | } else { |
| 6032 | var ret_tracking: [2]InstTracking = undefined; | 6026 | var ret_tracking: [2]InstTracking = undefined; |
| 6033 | var ret_tracking_i: usize = 0; | 6027 | var ret_tracking_i: usize = 0; |
| 6028 | var ret_float_reg_i: usize = 0; | ||
| 6034 | 6029 | ||
| 6035 | const classes = mem.sliceTo(&abi.classifySystem(ret_ty, zcu), .none); | 6030 | const classes = mem.sliceTo(&abi.classifySystem(ret_ty, zcu), .none); |
| 6036 | 6031 | ||
| ... | @@ -6042,6 +6037,13 @@ fn resolveCallingConventionValues( | ... | @@ -6042,6 +6037,13 @@ fn resolveCallingConventionValues( |
| 6042 | ret_tracking[ret_tracking_i] = InstTracking.init(.{ .register = ret_int_reg }); | 6037 | ret_tracking[ret_tracking_i] = InstTracking.init(.{ .register = ret_int_reg }); |
| 6043 | ret_tracking_i += 1; | 6038 | ret_tracking_i += 1; |
| 6044 | }, | 6039 | }, |
| 6040 | .float => { | ||
| 6041 | const ret_float_reg = abi.Registers.Float.function_ret_regs[ret_float_reg_i]; | ||
| 6042 | ret_float_reg_i += 1; | ||
| 6043 | |||
| 6044 | ret_tracking[ret_tracking_i] = InstTracking.init(.{ .register = ret_float_reg }); | ||
| 6045 | ret_tracking_i += 1; | ||
| 6046 | }, | ||
| 6045 | .memory => { | 6047 | .memory => { |
| 6046 | const ret_int_reg = abi.Registers.Integer.function_ret_regs[ret_int_reg_i]; | 6048 | const ret_int_reg = abi.Registers.Integer.function_ret_regs[ret_int_reg_i]; |
| 6047 | ret_int_reg_i += 1; | 6049 | ret_int_reg_i += 1; |
| ... | @@ -6076,6 +6078,8 @@ fn resolveCallingConventionValues( | ... | @@ -6076,6 +6078,8 @@ fn resolveCallingConventionValues( |
| 6076 | var arg_mcv: [2]MCValue = undefined; | 6078 | var arg_mcv: [2]MCValue = undefined; |
| 6077 | var arg_mcv_i: usize = 0; | 6079 | var arg_mcv_i: usize = 0; |
| 6078 | 6080 | ||
| 6081 | var param_float_reg_i: usize = 0; | ||
| 6082 | |||
| 6079 | const classes = mem.sliceTo(&abi.classifySystem(ty, zcu), .none); | 6083 | const classes = mem.sliceTo(&abi.classifySystem(ty, zcu), .none); |
| 6080 | 6084 | ||
| 6081 | for (classes) |class| switch (class) { | 6085 | for (classes) |class| switch (class) { |
| ... | @@ -6089,6 +6093,16 @@ fn resolveCallingConventionValues( | ... | @@ -6089,6 +6093,16 @@ fn resolveCallingConventionValues( |
| 6089 | arg_mcv[arg_mcv_i] = .{ .register = param_int_reg }; | 6093 | arg_mcv[arg_mcv_i] = .{ .register = param_int_reg }; |
| 6090 | arg_mcv_i += 1; | 6094 | arg_mcv_i += 1; |
| 6091 | }, | 6095 | }, |
| 6096 | .float => { | ||
| 6097 | const param_float_regs = abi.Registers.Float.function_arg_regs; | ||
| 6098 | if (param_float_reg_i >= param_float_regs.len) break; | ||
| 6099 | |||
| 6100 | const param_float_reg = param_float_regs[param_float_reg_i]; | ||
| 6101 | param_float_reg_i += 1; | ||
| 6102 | |||
| 6103 | arg_mcv[arg_mcv_i] = .{ .register = param_float_reg }; | ||
| 6104 | arg_mcv_i += 1; | ||
| 6105 | }, | ||
| 6092 | .memory => { | 6106 | .memory => { |
| 6093 | const param_int_regs = abi.Registers.Integer.function_arg_regs; | 6107 | const param_int_regs = abi.Registers.Integer.function_arg_regs; |
| 6094 | 6108 | ||
| ... | @@ -6118,9 +6132,8 @@ fn resolveCallingConventionValues( | ... | @@ -6118,9 +6132,8 @@ fn resolveCallingConventionValues( |
| 6118 | return result; | 6132 | return result; |
| 6119 | } | 6133 | } |
| 6120 | 6134 | ||
| 6121 | /// TODO support scope overrides. Also note this logic is duplicated with `Module.wantSafety`. | ||
| 6122 | fn wantSafety(self: *Self) bool { | 6135 | fn wantSafety(self: *Self) bool { |
| 6123 | return switch (self.bin_file.comp.root_mod.optimize_mode) { | 6136 | return switch (self.mod.optimize_mode) { |
| 6124 | .Debug => true, | 6137 | .Debug => true, |
| 6125 | .ReleaseSafe => true, | 6138 | .ReleaseSafe => true, |
| 6126 | .ReleaseFast => false, | 6139 | .ReleaseFast => false, |
src/arch/riscv64/Encoding.zig+48-43| ... | @@ -124,115 +124,119 @@ pub const Mnemonic = enum { | ... | @@ -124,115 +124,119 @@ pub const Mnemonic = enum { |
| 124 | fsd, | 124 | fsd, |
| 125 | fsw, | 125 | fsw, |
| 126 | 126 | ||
| 127 | fsgnjns, | ||
| 128 | |||
| 127 | pub fn encoding(mnem: Mnemonic) Enc { | 129 | pub fn encoding(mnem: Mnemonic) Enc { |
| 128 | return switch (mnem) { | 130 | return switch (mnem) { |
| 129 | // zig fmt: off | 131 | // zig fmt: off |
| 130 | 132 | ||
| 131 | // OP | 133 | // OP |
| 132 | 134 | ||
| 133 | .add => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } }, | 135 | .add => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000000 } } }, |
| 134 | .sub => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } }, | 136 | .sub => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0100000 } } }, |
| 135 | 137 | ||
| 136 | .@"and" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000000 } } }, | 138 | .@"and" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b111, .funct7 = 0b0000000 } } }, |
| 137 | .@"or" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000000 } } }, | 139 | .@"or" => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b110, .funct7 = 0b0000000 } } }, |
| 138 | .xor => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000000 } } }, | 140 | .xor => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b100, .funct7 = 0b0000000 } } }, |
| 139 | 141 | ||
| 140 | .sltu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000000 } } }, | 142 | .sltu => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b011, .funct7 = 0b0000000 } } }, |
| 141 | .slt => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } }, | 143 | .slt => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b010, .funct7 = 0b0000000 } } }, |
| 142 | 144 | ||
| 143 | .mul => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } }, | 145 | .mul => .{ .opcode = .OP, .data = .{ .ff = .{ .funct3 = 0b000, .funct7 = 0b0000001 } } }, |
| 144 | 146 | ||
| 145 | 147 | ||
| 146 | // OP_IMM | 148 | // OP_IMM |
| 147 | 149 | ||
| 148 | .addi => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 150 | .addi => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 149 | .andi => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b111 } } }, | 151 | .andi => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b111 } } }, |
| 150 | .xori => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b100 } } }, | 152 | .xori => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b100 } } }, |
| 151 | 153 | ||
| 152 | .sltiu => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | 154 | .sltiu => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b011 } } }, |
| 153 | 155 | ||
| 154 | .slli => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b001 } } }, | 156 | .slli => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b001 } } }, |
| 155 | .srli => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b101 } } }, | 157 | .srli => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b101 } } }, |
| 156 | .srai => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b101, .offset = 1 << 10 } } }, | 158 | .srai => .{ .opcode = .OP_IMM, .data = .{ .fo = .{ .funct3 = 0b101, .offset = 1 << 10 } } }, |
| 157 | 159 | ||
| 158 | 160 | ||
| 159 | // OP_FP | 161 | // OP_FP |
| 160 | 162 | ||
| 161 | .fadds => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } }, | 163 | .fadds => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .S, .rm = 0b111 } } }, |
| 162 | .faddd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } }, | 164 | .faddd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00000, .fmt = .D, .rm = 0b111 } } }, |
| 165 | |||
| 166 | .feqs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } }, | ||
| 167 | .feqd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } }, | ||
| 163 | 168 | ||
| 164 | .feqs => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .S, .rm = 0b010 } } }, | 169 | .fsgnjns => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b00100, .fmt = .S, .rm = 0b000 } } }, |
| 165 | .feqd => .{ .opcode = .OP_FP, .data = .{ .fmt = .{ .funct5 = 0b10100, .fmt = .D, .rm = 0b010 } } }, | ||
| 166 | 170 | ||
| 167 | // LOAD | 171 | // LOAD |
| 168 | 172 | ||
| 169 | .ld => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | 173 | .ld => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b011 } } }, |
| 170 | .lw => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | 174 | .lw => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b010 } } }, |
| 171 | .lwu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b110 } } }, | 175 | .lwu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b110 } } }, |
| 172 | .lh => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b001 } } }, | 176 | .lh => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b001 } } }, |
| 173 | .lhu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b101 } } }, | 177 | .lhu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b101 } } }, |
| 174 | .lb => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 178 | .lb => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 175 | .lbu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b100 } } }, | 179 | .lbu => .{ .opcode = .LOAD, .data = .{ .fo = .{ .funct3 = 0b100 } } }, |
| 176 | 180 | ||
| 177 | 181 | ||
| 178 | // STORE | 182 | // STORE |
| 179 | 183 | ||
| 180 | .sd => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | 184 | .sd => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b011 } } }, |
| 181 | .sw => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | 185 | .sw => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b010 } } }, |
| 182 | .sh => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b001 } } }, | 186 | .sh => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b001 } } }, |
| 183 | .sb => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 187 | .sb => .{ .opcode = .STORE, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 184 | 188 | ||
| 185 | 189 | ||
| 186 | // LOAD_FP | 190 | // LOAD_FP |
| 187 | 191 | ||
| 188 | .fld => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | 192 | .fld => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } }, |
| 189 | .flw => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | 193 | .flw => .{ .opcode = .LOAD_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } }, |
| 190 | 194 | ||
| 191 | // STORE_FP | 195 | // STORE_FP |
| 192 | 196 | ||
| 193 | .fsd => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } }, | 197 | .fsd => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b011 } } }, |
| 194 | .fsw => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } }, | 198 | .fsw => .{ .opcode = .STORE_FP, .data = .{ .fo = .{ .funct3 = 0b010 } } }, |
| 195 | 199 | ||
| 196 | 200 | ||
| 197 | // JALR | 201 | // JALR |
| 198 | 202 | ||
| 199 | .jalr => .{ .opcode = .JALR, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 203 | .jalr => .{ .opcode = .JALR, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 200 | 204 | ||
| 201 | 205 | ||
| 202 | // OP_32 | 206 | // OP_32 |
| 203 | 207 | ||
| 204 | .sllw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } }, | 208 | .sllw => .{ .opcode = .OP_32, .data = .{ .ff = .{ .funct3 = 0b001, .funct7 = 0b0000000 } } }, |
| 205 | 209 | ||
| 206 | 210 | ||
| 207 | // LUI | 211 | // LUI |
| 208 | 212 | ||
| 209 | .lui => .{ .opcode = .LUI, .data = .{ .none = {} } }, | 213 | .lui => .{ .opcode = .LUI, .data = .{ .none = {} } }, |
| 210 | 214 | ||
| 211 | 215 | ||
| 212 | // AUIPC | 216 | // AUIPC |
| 213 | 217 | ||
| 214 | .auipc => .{ .opcode = .AUIPC, .data = .{ .none = {} } }, | 218 | .auipc => .{ .opcode = .AUIPC, .data = .{ .none = {} } }, |
| 215 | 219 | ||
| 216 | 220 | ||
| 217 | // JAL | 221 | // JAL |
| 218 | 222 | ||
| 219 | .jal => .{ .opcode = .JAL, .data = .{ .none = {} } }, | 223 | .jal => .{ .opcode = .JAL, .data = .{ .none = {} } }, |
| 220 | 224 | ||
| 221 | 225 | ||
| 222 | // BRANCH | 226 | // BRANCH |
| 223 | 227 | ||
| 224 | .beq => .{ .opcode = .BRANCH, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 228 | .beq => .{ .opcode = .BRANCH, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 225 | 229 | ||
| 226 | 230 | ||
| 227 | // SYSTEM | 231 | // SYSTEM |
| 228 | 232 | ||
| 229 | .ecall => .{ .opcode = .SYSTEM, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 233 | .ecall => .{ .opcode = .SYSTEM, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 230 | .ebreak => .{ .opcode = .SYSTEM, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 234 | .ebreak => .{ .opcode = .SYSTEM, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 231 | 235 | ||
| 232 | 236 | ||
| 233 | // NONE | 237 | // NONE |
| 234 | 238 | ||
| 235 | .unimp => .{ .opcode = .NONE, .data = .{ .fo = .{ .funct3 = 0b000 } } }, | 239 | .unimp => .{ .opcode = .NONE, .data = .{ .fo = .{ .funct3 = 0b000 } } }, |
| 236 | 240 | ||
| 237 | 241 | ||
| 238 | // zig fmt: on | 242 | // zig fmt: on |
| ... | @@ -308,6 +312,7 @@ pub const InstEnc = enum { | ... | @@ -308,6 +312,7 @@ pub const InstEnc = enum { |
| 308 | .faddd, | 312 | .faddd, |
| 309 | .feqs, | 313 | .feqs, |
| 310 | .feqd, | 314 | .feqd, |
| 315 | .fsgnjns, | ||
| 311 | => .R, | 316 | => .R, |
| 312 | 317 | ||
| 313 | .ecall, | 318 | .ecall, |
src/arch/riscv64/Lower.zig+21-5| ... | @@ -132,11 +132,27 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { | ... | @@ -132,11 +132,27 @@ pub fn lowerMir(lower: *Lower, index: Mir.Inst.Index) Error!struct { |
| 132 | .pseudo_mv => { | 132 | .pseudo_mv => { |
| 133 | const rr = inst.data.rr; | 133 | const rr = inst.data.rr; |
| 134 | 134 | ||
| 135 | try lower.emit(.addi, &.{ | 135 | const dst_class = rr.rd.class(); |
| 136 | .{ .reg = rr.rd }, | 136 | const src_class = rr.rs.class(); |
| 137 | .{ .reg = rr.rs }, | 137 | |
| 138 | .{ .imm = Immediate.s(0) }, | 138 | assert(dst_class == src_class); |
| 139 | }); | 139 | |
| 140 | switch (dst_class) { | ||
| 141 | .float => { | ||
| 142 | try lower.emit(.fsgnjns, &.{ | ||
| 143 | .{ .reg = rr.rd }, | ||
| 144 | .{ .reg = rr.rs }, | ||
| 145 | .{ .reg = rr.rs }, | ||
| 146 | }); | ||
| 147 | }, | ||
| 148 | .int => { | ||
| 149 | try lower.emit(.addi, &.{ | ||
| 150 | .{ .reg = rr.rd }, | ||
| 151 | .{ .reg = rr.rs }, | ||
| 152 | .{ .imm = Immediate.s(0) }, | ||
| 153 | }); | ||
| 154 | }, | ||
| 155 | } | ||
| 140 | }, | 156 | }, |
| 141 | 157 | ||
| 142 | .pseudo_ret => { | 158 | .pseudo_ret => { |
src/arch/riscv64/abi.zig+18-4| ... | @@ -7,7 +7,7 @@ const InternPool = @import("../../InternPool.zig"); | ... | @@ -7,7 +7,7 @@ const InternPool = @import("../../InternPool.zig"); |
| 7 | const Module = @import("../../Module.zig"); | 7 | const Module = @import("../../Module.zig"); |
| 8 | const assert = std.debug.assert; | 8 | const assert = std.debug.assert; |
| 9 | 9 | ||
| 10 | pub const Class = enum { memory, byval, integer, double_integer, fields, none }; | 10 | pub const Class = enum { memory, byval, integer, double_integer, fields }; |
| 11 | 11 | ||
| 12 | pub fn classifyType(ty: Type, mod: *Module) Class { | 12 | pub fn classifyType(ty: Type, mod: *Module) Class { |
| 13 | const target = mod.getTarget(); | 13 | const target = mod.getTarget(); |
| ... | @@ -93,11 +93,13 @@ pub fn classifyType(ty: Type, mod: *Module) Class { | ... | @@ -93,11 +93,13 @@ pub fn classifyType(ty: Type, mod: *Module) Class { |
| 93 | } | 93 | } |
| 94 | } | 94 | } |
| 95 | 95 | ||
| 96 | pub const SystemClass = enum { integer, float, memory, none }; | ||
| 97 | |||
| 96 | /// There are a maximum of 8 possible return slots. Returned values are in | 98 | /// There are a maximum of 8 possible return slots. Returned values are in |
| 97 | /// the beginning of the array; unused slots are filled with .none. | 99 | /// the beginning of the array; unused slots are filled with .none. |
| 98 | pub fn classifySystem(ty: Type, zcu: *Module) [8]Class { | 100 | pub fn classifySystem(ty: Type, zcu: *Module) [8]SystemClass { |
| 99 | var result = [1]Class{.none} ** 8; | 101 | var result = [1]SystemClass{.none} ** 8; |
| 100 | const memory_class = [_]Class{ | 102 | const memory_class = [_]SystemClass{ |
| 101 | .memory, .none, .none, .none, | 103 | .memory, .none, .none, .none, |
| 102 | .none, .none, .none, .none, | 104 | .none, .none, .none, .none, |
| 103 | }; | 105 | }; |
| ... | @@ -139,6 +141,18 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class { | ... | @@ -139,6 +141,18 @@ pub fn classifySystem(ty: Type, zcu: *Module) [8]Class { |
| 139 | } | 141 | } |
| 140 | unreachable; // support > 128 bit int arguments | 142 | unreachable; // support > 128 bit int arguments |
| 141 | }, | 143 | }, |
| 144 | .Float => { | ||
| 145 | const target = zcu.getTarget(); | ||
| 146 | const features = target.cpu.features; | ||
| 147 | |||
| 148 | const float_bits = ty.floatBits(zcu.getTarget()); | ||
| 149 | const float_reg_size: u32 = if (std.Target.riscv.featureSetHas(features, .d)) 64 else 32; | ||
| 150 | if (float_bits <= float_reg_size) { | ||
| 151 | result[0] = .float; | ||
| 152 | return result; | ||
| 153 | } | ||
| 154 | unreachable; // support split float args | ||
| 155 | }, | ||
| 142 | .ErrorUnion => { | 156 | .ErrorUnion => { |
| 143 | const payload_ty = ty.errorUnionPayload(zcu); | 157 | const payload_ty = ty.errorUnionPayload(zcu); |
| 144 | const payload_bits = payload_ty.bitSize(zcu); | 158 | const payload_bits = payload_ty.bitSize(zcu); |
src/arch/riscv64/bits.zig+7-2| ... | @@ -2,6 +2,9 @@ const std = @import("std"); | ... | @@ -2,6 +2,9 @@ const std = @import("std"); |
| 2 | const DW = std.dwarf; | 2 | const DW = std.dwarf; |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const testing = std.testing; | 4 | const testing = std.testing; |
| 5 | const Target = std.Target; | ||
| 6 | |||
| 7 | const Module = @import("../../Module.zig"); | ||
| 5 | const Encoding = @import("Encoding.zig"); | 8 | const Encoding = @import("Encoding.zig"); |
| 6 | const Mir = @import("Mir.zig"); | 9 | const Mir = @import("Mir.zig"); |
| 7 | const abi = @import("abi.zig"); | 10 | const abi = @import("abi.zig"); |
| ... | @@ -227,11 +230,13 @@ pub const Register = enum(u8) { | ... | @@ -227,11 +230,13 @@ pub const Register = enum(u8) { |
| 227 | return @as(u8, reg.id()); | 230 | return @as(u8, reg.id()); |
| 228 | } | 231 | } |
| 229 | 232 | ||
| 230 | pub fn bitSize(reg: Register) u32 { | 233 | pub fn bitSize(reg: Register, zcu: Module) u32 { |
| 234 | const features = zcu.getTarget().cpu.features; | ||
| 235 | |||
| 231 | return switch (@intFromEnum(reg)) { | 236 | return switch (@intFromEnum(reg)) { |
| 232 | // zig fmt: off | 237 | // zig fmt: off |
| 233 | @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => 64, | 238 | @intFromEnum(Register.zero) ... @intFromEnum(Register.x31) => 64, |
| 234 | @intFromEnum(Register.ft0) ... @intFromEnum(Register.f31) => 32, | 239 | @intFromEnum(Register.ft0) ... @intFromEnum(Register.f31) => if (Target.riscv.featureSetHas(features, .d)) 64 else 32, |
| 235 | else => unreachable, | 240 | else => unreachable, |
| 236 | // zig fmt: on | 241 | // zig fmt: on |
| 237 | }; | 242 | }; |
src/codegen/llvm.zig-2| ... | @@ -11148,7 +11148,6 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu | ... | @@ -11148,7 +11148,6 @@ fn lowerFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!Bu |
| 11148 | } | 11148 | } |
| 11149 | return o.builder.structType(.normal, types[0..types_len]); | 11149 | return o.builder.structType(.normal, types[0..types_len]); |
| 11150 | }, | 11150 | }, |
| 11151 | .none => unreachable, | ||
| 11152 | } | 11151 | } |
| 11153 | }, | 11152 | }, |
| 11154 | // TODO investigate C ABI for other architectures | 11153 | // TODO investigate C ABI for other architectures |
| ... | @@ -11406,7 +11405,6 @@ const ParamTypeIterator = struct { | ... | @@ -11406,7 +11405,6 @@ const ParamTypeIterator = struct { |
| 11406 | it.llvm_index += it.types_len - 1; | 11405 | it.llvm_index += it.types_len - 1; |
| 11407 | return .multiple_llvm_types; | 11406 | return .multiple_llvm_types; |
| 11408 | }, | 11407 | }, |
| 11409 | .none => unreachable, | ||
| 11410 | } | 11408 | } |
| 11411 | }, | 11409 | }, |
| 11412 | // TODO investigate C ABI for other architectures | 11410 | // TODO investigate C ABI for other architectures |