| ... | @@ -37,6 +37,69 @@ pub fn generateSymbol( | ... | @@ -37,6 +37,69 @@ pub fn generateSymbol( |
| 37 | .Fn => { | 37 | .Fn => { |
| 38 | const module_fn = typed_value.val.cast(Value.Payload.Function).?.func; | 38 | const module_fn = typed_value.val.cast(Value.Payload.Function).?.func; |
| 39 | | 39 | |
| | 40 | const fn_type = module_fn.owner_decl.typed_value.most_recent.typed_value.ty; |
| | 41 | const param_types = try bin_file.allocator.alloc(Type, fn_type.fnParamLen()); |
| | 42 | defer bin_file.allocator.free(param_types); |
| | 43 | fn_type.fnParamTypes(param_types); |
| | 44 | // A parameter may be broken into multiple machine code parameters, so we don't |
| | 45 | // know the size up front. |
| | 46 | var mc_args = try std.ArrayList(Function.MCValue).initCapacity(bin_file.allocator, param_types.len); |
| | 47 | defer mc_args.deinit(); |
| | 48 | |
| | 49 | var next_stack_offset: u64 = 0; |
| | 50 | |
| | 51 | switch (fn_type.fnCallingConvention()) { |
| | 52 | .Naked => assert(mc_args.items.len == 0), |
| | 53 | .Unspecified, .C => { |
| | 54 | // Prepare the function parameters |
| | 55 | switch (bin_file.options.target.cpu.arch) { |
| | 56 | .x86_64 => { |
| | 57 | const integer_registers = [_]Reg(.x86_64){.rdi, .rsi, .rdx, .rcx, .r8, .r9}; |
| | 58 | var next_int_reg: usize = 0; |
| | 59 | |
| | 60 | for (param_types) |param_type, src_i| { |
| | 61 | switch (param_type.zigTypeTag()) { |
| | 62 | .Bool, .Int => { |
| | 63 | if (next_int_reg >= integer_registers.len) { |
| | 64 | try mc_args.append(.{ .stack_offset = next_stack_offset }); |
| | 65 | next_stack_offset += param_type.abiSize(bin_file.options.target); |
| | 66 | } else { |
| | 67 | try mc_args.append(.{ .register = @enumToInt(integer_registers[next_int_reg])}); |
| | 68 | next_int_reg += 1; |
| | 69 | } |
| | 70 | }, |
| | 71 | else => return Result{ |
| | 72 | .fail = try ErrorMsg.create( |
| | 73 | bin_file.allocator, |
| | 74 | src, |
| | 75 | "TODO implement function parameters of type {}", |
| | 76 | .{@tagName(param_type.zigTypeTag())}, |
| | 77 | ), |
| | 78 | } |
| | 79 | } |
| | 80 | } |
| | 81 | |
| | 82 | }, |
| | 83 | else => return Result{ |
| | 84 | .fail = try ErrorMsg.create( |
| | 85 | bin_file.allocator, |
| | 86 | src, |
| | 87 | "TODO implement function parameters for {}", |
| | 88 | .{bin_file.options.target.cpu.arch}, |
| | 89 | ), |
| | 90 | }, |
| | 91 | } |
| | 92 | }, |
| | 93 | else => return Result{ |
| | 94 | .fail = try ErrorMsg.create( |
| | 95 | bin_file.allocator, |
| | 96 | src, |
| | 97 | "TODO implement {} calling convention", |
| | 98 | .{fn_type.fnCallingConvention()}, |
| | 99 | ), |
| | 100 | }, |
| | 101 | } |
| | 102 | |
| 40 | var function = Function{ | 103 | var function = Function{ |
| 41 | .target = &bin_file.options.target, | 104 | .target = &bin_file.options.target, |
| 42 | .bin_file = bin_file, | 105 | .bin_file = bin_file, |
| ... | @@ -44,16 +107,14 @@ pub fn generateSymbol( | ... | @@ -44,16 +107,14 @@ pub fn generateSymbol( |
| 44 | .code = code, | 107 | .code = code, |
| 45 | .inst_table = std.AutoHashMap(*ir.Inst, Function.MCValue).init(bin_file.allocator), | 108 | .inst_table = std.AutoHashMap(*ir.Inst, Function.MCValue).init(bin_file.allocator), |
| 46 | .err_msg = null, | 109 | .err_msg = null, |
| | 110 | .args = mc_args.items, |
| 47 | }; | 111 | }; |
| 48 | defer function.inst_table.deinit(); | 112 | defer function.inst_table.deinit(); |
| 49 | | 113 | |
| 50 | for (module_fn.analysis.success.instructions) |inst| { | 114 | function.gen() catch |err| switch (err) { |
| 51 | const new_inst = function.genFuncInst(inst) catch |err| switch (err) { | 115 | error.CodegenFail => return Result{ .fail = function.err_msg.? }, |
| 52 | error.CodegenFail => return Result{ .fail = function.err_msg.? }, | 116 | else => |e| return e, |
| 53 | else => |e| return e, | 117 | }; |
| 54 | }; | | |
| 55 | try function.inst_table.putNoClobber(inst, new_inst); | | |
| 56 | } | | |
| 57 | | 118 | |
| 58 | if (function.err_msg) |em| { | 119 | if (function.err_msg) |em| { |
| 59 | return Result{ .fail = em }; | 120 | return Result{ .fail = em }; |
| ... | @@ -157,6 +218,7 @@ const Function = struct { | ... | @@ -157,6 +218,7 @@ const Function = struct { |
| 157 | code: *std.ArrayList(u8), | 218 | code: *std.ArrayList(u8), |
| 158 | inst_table: std.AutoHashMap(*ir.Inst, MCValue), | 219 | inst_table: std.AutoHashMap(*ir.Inst, MCValue), |
| 159 | err_msg: ?*ErrorMsg, | 220 | err_msg: ?*ErrorMsg, |
| | 221 | args: []MCValue, |
| 160 | | 222 | |
| 161 | const MCValue = union(enum) { | 223 | const MCValue = union(enum) { |
| 162 | none, | 224 | none, |
| ... | @@ -170,44 +232,119 @@ const Function = struct { | ... | @@ -170,44 +232,119 @@ const Function = struct { |
| 170 | register: usize, | 232 | register: usize, |
| 171 | /// The value is in memory at a hard-coded address. | 233 | /// The value is in memory at a hard-coded address. |
| 172 | memory: u64, | 234 | memory: u64, |
| | 235 | /// The value is one of the stack variables. |
| | 236 | stack_offset: u64, |
| 173 | }; | 237 | }; |
| 174 | | 238 | |
| 175 | fn genFuncInst(self: *Function, inst: *ir.Inst) !MCValue { | 239 | fn gen(self: *Function) !void { |
| | 240 | switch (self.target.cpu.arch) { |
| | 241 | .arm => return self.genArch(.arm), |
| | 242 | .armeb => return self.genArch(.armeb), |
| | 243 | .aarch64 => return self.genArch(.aarch64), |
| | 244 | .aarch64_be => return self.genArch(.aarch64_be), |
| | 245 | .aarch64_32 => return self.genArch(.aarch64_32), |
| | 246 | .arc => return self.genArch(.arc), |
| | 247 | .avr => return self.genArch(.avr), |
| | 248 | .bpfel => return self.genArch(.bpfel), |
| | 249 | .bpfeb => return self.genArch(.bpfeb), |
| | 250 | .hexagon => return self.genArch(.hexagon), |
| | 251 | .mips => return self.genArch(.mips), |
| | 252 | .mipsel => return self.genArch(.mipsel), |
| | 253 | .mips64 => return self.genArch(.mips64), |
| | 254 | .mips64el => return self.genArch(.mips64el), |
| | 255 | .msp430 => return self.genArch(.msp430), |
| | 256 | .powerpc => return self.genArch(.powerpc), |
| | 257 | .powerpc64 => return self.genArch(.powerpc64), |
| | 258 | .powerpc64le => return self.genArch(.powerpc64le), |
| | 259 | .r600 => return self.genArch(.r600), |
| | 260 | .amdgcn => return self.genArch(.amdgcn), |
| | 261 | .riscv32 => return self.genArch(.riscv32), |
| | 262 | .riscv64 => return self.genArch(.riscv64), |
| | 263 | .sparc => return self.genArch(.sparc), |
| | 264 | .sparcv9 => return self.genArch(.sparcv9), |
| | 265 | .sparcel => return self.genArch(.sparcel), |
| | 266 | .s390x => return self.genArch(.s390x), |
| | 267 | .tce => return self.genArch(.tce), |
| | 268 | .tcele => return self.genArch(.tcele), |
| | 269 | .thumb => return self.genArch(.thumb), |
| | 270 | .thumbeb => return self.genArch(.thumbeb), |
| | 271 | .i386 => return self.genArch(.i386), |
| | 272 | .x86_64 => return self.genArch(.x86_64), |
| | 273 | .xcore => return self.genArch(.xcore), |
| | 274 | .nvptx => return self.genArch(.nvptx), |
| | 275 | .nvptx64 => return self.genArch(.nvptx64), |
| | 276 | .le32 => return self.genArch(.le32), |
| | 277 | .le64 => return self.genArch(.le64), |
| | 278 | .amdil => return self.genArch(.amdil), |
| | 279 | .amdil64 => return self.genArch(.amdil64), |
| | 280 | .hsail => return self.genArch(.hsail), |
| | 281 | .hsail64 => return self.genArch(.hsail64), |
| | 282 | .spir => return self.genArch(.spir), |
| | 283 | .spir64 => return self.genArch(.spir64), |
| | 284 | .kalimba => return self.genArch(.kalimba), |
| | 285 | .shave => return self.genArch(.shave), |
| | 286 | .lanai => return self.genArch(.lanai), |
| | 287 | .wasm32 => return self.genArch(.wasm32), |
| | 288 | .wasm64 => return self.genArch(.wasm64), |
| | 289 | .renderscript32 => return self.genArch(.renderscript32), |
| | 290 | .renderscript64 => return self.genArch(.renderscript64), |
| | 291 | .ve => return self.genArch(.ve), |
| | 292 | } |
| | 293 | } |
| | 294 | |
| | 295 | fn genArch(self: *Function, comptime arch: std.Target.Cpu.Arch) !void { |
| | 296 | for (self.mod_fn.analysis.success.instructions) |inst| { |
| | 297 | const new_inst = try self.genFuncInst(inst, arch); |
| | 298 | try self.inst_table.putNoClobber(inst, new_inst); |
| | 299 | } |
| | 300 | } |
| | 301 | |
| | 302 | fn genFuncInst(self: *Function, inst: *ir.Inst, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 176 | switch (inst.tag) { | 303 | switch (inst.tag) { |
| 177 | .add => return self.genAdd(inst.cast(ir.Inst.Add).?), | 304 | .add => return self.genAdd(inst.cast(ir.Inst.Add).?, arch), |
| 178 | .arg => return self.genArg(inst.src), | 305 | .arg => return self.genArg(inst.cast(ir.Inst.Arg).?), |
| 179 | .block => return self.genBlock(inst.cast(ir.Inst.Block).?), | 306 | .block => return self.genBlock(inst.cast(ir.Inst.Block).?, arch), |
| 180 | .breakpoint => return self.genBreakpoint(inst.src), | 307 | .breakpoint => return self.genBreakpoint(inst.src, arch), |
| 181 | .call => return self.genCall(inst.cast(ir.Inst.Call).?), | 308 | .call => return self.genCall(inst.cast(ir.Inst.Call).?, arch), |
| 182 | .unreach => return MCValue{ .unreach = {} }, | 309 | .unreach => return MCValue{ .unreach = {} }, |
| 183 | .constant => unreachable, // excluded from function bodies | 310 | .constant => unreachable, // excluded from function bodies |
| 184 | .assembly => return self.genAsm(inst.cast(ir.Inst.Assembly).?), | 311 | .assembly => return self.genAsm(inst.cast(ir.Inst.Assembly).?, arch), |
| 185 | .ptrtoint => return self.genPtrToInt(inst.cast(ir.Inst.PtrToInt).?), | 312 | .ptrtoint => return self.genPtrToInt(inst.cast(ir.Inst.PtrToInt).?), |
| 186 | .bitcast => return self.genBitCast(inst.cast(ir.Inst.BitCast).?), | 313 | .bitcast => return self.genBitCast(inst.cast(ir.Inst.BitCast).?), |
| 187 | .ret => return self.genRet(inst.cast(ir.Inst.Ret).?), | 314 | .ret => return self.genRet(inst.cast(ir.Inst.Ret).?, arch), |
| 188 | .retvoid => return self.genRetVoid(inst.cast(ir.Inst.RetVoid).?), | 315 | .retvoid => return self.genRetVoid(inst.cast(ir.Inst.RetVoid).?, arch), |
| 189 | .cmp => return self.genCmp(inst.cast(ir.Inst.Cmp).?), | 316 | .cmp => return self.genCmp(inst.cast(ir.Inst.Cmp).?, arch), |
| 190 | .condbr => return self.genCondBr(inst.cast(ir.Inst.CondBr).?), | 317 | .condbr => return self.genCondBr(inst.cast(ir.Inst.CondBr).?, arch), |
| 191 | .isnull => return self.genIsNull(inst.cast(ir.Inst.IsNull).?), | 318 | .isnull => return self.genIsNull(inst.cast(ir.Inst.IsNull).?, arch), |
| 192 | .isnonnull => return self.genIsNonNull(inst.cast(ir.Inst.IsNonNull).?), | 319 | .isnonnull => return self.genIsNonNull(inst.cast(ir.Inst.IsNonNull).?, arch), |
| 193 | } | 320 | } |
| 194 | } | 321 | } |
| 195 | | 322 | |
| 196 | fn genAdd(self: *Function, inst: *ir.Inst.Add) !MCValue { | 323 | fn genAdd(self: *Function, inst: *ir.Inst.Add, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 197 | switch (self.target.cpu.arch) { | 324 | const lhs = try self.resolveInst(inst.args.lhs); |
| | 325 | const rhs = try self.resolveInst(inst.args.rhs); |
| | 326 | switch (arch) { |
| | 327 | .i386, .x86_64 => { |
| | 328 | // const lhs_reg = try self.instAsReg(lhs); |
| | 329 | // const rhs_reg = try self.instAsReg(rhs); |
| | 330 | // const result = try self.allocateReg(); |
| | 331 | |
| | 332 | // try self.code.append(??); |
| | 333 | |
| | 334 | // lhs_reg.release(); |
| | 335 | // rhs_reg.release(); |
| | 336 | return self.fail(inst.base.src, "TODO implement register allocation", .{}); |
| | 337 | }, |
| 198 | else => return self.fail(inst.base.src, "TODO implement add for {}", .{self.target.cpu.arch}), | 338 | else => return self.fail(inst.base.src, "TODO implement add for {}", .{self.target.cpu.arch}), |
| 199 | } | 339 | } |
| 200 | } | 340 | } |
| 201 | | 341 | |
| 202 | fn genArg(self: *Function, src: usize) !MCValue { | 342 | fn genArg(self: *Function, inst: *ir.Inst.Arg) !MCValue { |
| 203 | switch (self.target.cpu.arch) { | 343 | return self.args[inst.args.index]; |
| 204 | else => return self.fail(src, "TODO implement function parameters for {}", .{self.target.cpu.arch}), | | |
| 205 | } | | |
| 206 | return .none; | | |
| 207 | } | 344 | } |
| 208 | | 345 | |
| 209 | fn genBreakpoint(self: *Function, src: usize) !MCValue { | 346 | fn genBreakpoint(self: *Function, src: usize, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 210 | switch (self.target.cpu.arch) { | 347 | switch (arch) { |
| 211 | .i386, .x86_64 => { | 348 | .i386, .x86_64 => { |
| 212 | try self.code.append(0xcc); // int3 | 349 | try self.code.append(0xcc); // int3 |
| 213 | }, | 350 | }, |
| ... | @@ -216,8 +353,8 @@ const Function = struct { | ... | @@ -216,8 +353,8 @@ const Function = struct { |
| 216 | return .none; | 353 | return .none; |
| 217 | } | 354 | } |
| 218 | | 355 | |
| 219 | fn genCall(self: *Function, inst: *ir.Inst.Call) !MCValue { | 356 | fn genCall(self: *Function, inst: *ir.Inst.Call, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 220 | switch (self.target.cpu.arch) { | 357 | switch (arch) { |
| 221 | .x86_64, .i386 => { | 358 | .x86_64, .i386 => { |
| 222 | if (inst.args.func.cast(ir.Inst.Constant)) |func_inst| { | 359 | if (inst.args.func.cast(ir.Inst.Constant)) |func_inst| { |
| 223 | if (inst.args.args.len != 0) { | 360 | if (inst.args.args.len != 0) { |
| ... | @@ -251,11 +388,11 @@ const Function = struct { | ... | @@ -251,11 +388,11 @@ const Function = struct { |
| 251 | } | 388 | } |
| 252 | } | 389 | } |
| 253 | | 390 | |
| 254 | fn ret(self: *Function, src: usize, mcv: MCValue) !MCValue { | 391 | fn ret(self: *Function, src: usize, comptime arch: std.Target.Cpu.Arch, mcv: MCValue) !MCValue { |
| 255 | if (mcv != .none) { | 392 | if (mcv != .none) { |
| 256 | return self.fail(src, "TODO implement return with non-void operand", .{}); | 393 | return self.fail(src, "TODO implement return with non-void operand", .{}); |
| 257 | } | 394 | } |
| 258 | switch (self.target.cpu.arch) { | 395 | switch (arch) { |
| 259 | .i386, .x86_64 => { | 396 | .i386, .x86_64 => { |
| 260 | try self.code.append(0xc3); // ret | 397 | try self.code.append(0xc3); // ret |
| 261 | }, | 398 | }, |
| ... | @@ -264,43 +401,43 @@ const Function = struct { | ... | @@ -264,43 +401,43 @@ const Function = struct { |
| 264 | return .unreach; | 401 | return .unreach; |
| 265 | } | 402 | } |
| 266 | | 403 | |
| 267 | fn genRet(self: *Function, inst: *ir.Inst.Ret) !MCValue { | 404 | fn genRet(self: *Function, inst: *ir.Inst.Ret, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 268 | const operand = try self.resolveInst(inst.args.operand); | 405 | const operand = try self.resolveInst(inst.args.operand); |
| 269 | return self.ret(inst.base.src, operand); | 406 | return self.ret(inst.base.src, arch, operand); |
| 270 | } | 407 | } |
| 271 | | 408 | |
| 272 | fn genRetVoid(self: *Function, inst: *ir.Inst.RetVoid) !MCValue { | 409 | fn genRetVoid(self: *Function, inst: *ir.Inst.RetVoid, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 273 | return self.ret(inst.base.src, .none); | 410 | return self.ret(inst.base.src, arch, .none); |
| 274 | } | 411 | } |
| 275 | | 412 | |
| 276 | fn genCmp(self: *Function, inst: *ir.Inst.Cmp) !MCValue { | 413 | fn genCmp(self: *Function, inst: *ir.Inst.Cmp, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 277 | switch (self.target.cpu.arch) { | 414 | switch (arch) { |
| 278 | else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.target.cpu.arch}), | 415 | else => return self.fail(inst.base.src, "TODO implement cmp for {}", .{self.target.cpu.arch}), |
| 279 | } | 416 | } |
| 280 | } | 417 | } |
| 281 | | 418 | |
| 282 | fn genCondBr(self: *Function, inst: *ir.Inst.CondBr) !MCValue { | 419 | fn genCondBr(self: *Function, inst: *ir.Inst.CondBr, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 283 | switch (self.target.cpu.arch) { | 420 | switch (arch) { |
| 284 | else => return self.fail(inst.base.src, "TODO implement condbr for {}", .{self.target.cpu.arch}), | 421 | else => return self.fail(inst.base.src, "TODO implement condbr for {}", .{self.target.cpu.arch}), |
| 285 | } | 422 | } |
| 286 | } | 423 | } |
| 287 | | 424 | |
| 288 | fn genIsNull(self: *Function, inst: *ir.Inst.IsNull) !MCValue { | 425 | fn genIsNull(self: *Function, inst: *ir.Inst.IsNull, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 289 | switch (self.target.cpu.arch) { | 426 | switch (arch) { |
| 290 | else => return self.fail(inst.base.src, "TODO implement isnull for {}", .{self.target.cpu.arch}), | 427 | else => return self.fail(inst.base.src, "TODO implement isnull for {}", .{self.target.cpu.arch}), |
| 291 | } | 428 | } |
| 292 | } | 429 | } |
| 293 | | 430 | |
| 294 | fn genIsNonNull(self: *Function, inst: *ir.Inst.IsNonNull) !MCValue { | 431 | fn genIsNonNull(self: *Function, inst: *ir.Inst.IsNonNull, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 295 | // Here you can specialize this instruction if it makes sense to, otherwise the default | 432 | // Here you can specialize this instruction if it makes sense to, otherwise the default |
| 296 | // will call genIsNull and invert the result. | 433 | // will call genIsNull and invert the result. |
| 297 | switch (self.target.cpu.arch) { | 434 | switch (arch) { |
| 298 | else => return self.fail(inst.base.src, "TODO call genIsNull and invert the result ", .{}), | 435 | else => return self.fail(inst.base.src, "TODO call genIsNull and invert the result ", .{}), |
| 299 | } | 436 | } |
| 300 | } | 437 | } |
| 301 | | 438 | |
| 302 | fn genRelativeFwdJump(self: *Function, src: usize, amount: u32) !void { | 439 | fn genRelativeFwdJump(self: *Function, src: usize, comptime arch: std.Target.Cpu.Arch, amount: u32) !void { |
| 303 | switch (self.target.cpu.arch) { | 440 | switch (arch) { |
| 304 | .i386, .x86_64 => { | 441 | .i386, .x86_64 => { |
| 305 | // TODO x86 treats the operands as signed | 442 | // TODO x86 treats the operands as signed |
| 306 | if (amount <= std.math.maxInt(u8)) { | 443 | if (amount <= std.math.maxInt(u8)) { |
| ... | @@ -318,70 +455,13 @@ const Function = struct { | ... | @@ -318,70 +455,13 @@ const Function = struct { |
| 318 | } | 455 | } |
| 319 | } | 456 | } |
| 320 | | 457 | |
| 321 | fn genBlock(self: *Function, inst: *ir.Inst.Block) !MCValue { | 458 | fn genBlock(self: *Function, inst: *ir.Inst.Block, comptime arch: std.Target.Cpu.Arch) !MCValue { |
| 322 | switch (self.target.cpu.arch) { | 459 | switch (arch) { |
| 323 | else => return self.fail(inst.base.src, "TODO implement codegen Block for {}", .{self.target.cpu.arch}), | 460 | else => return self.fail(inst.base.src, "TODO implement codegen Block for {}", .{self.target.cpu.arch}), |
| 324 | } | 461 | } |
| 325 | } | 462 | } |
| 326 | | 463 | |
| 327 | fn genAsm(self: *Function, inst: *ir.Inst.Assembly) !MCValue { | 464 | fn genAsm(self: *Function, inst: *ir.Inst.Assembly, comptime arch: Target.Cpu.Arch) !MCValue { |
| 328 | // TODO convert to inline function | | |
| 329 | switch (self.target.cpu.arch) { | | |
| 330 | .arm => return self.genAsmArch(.arm, inst), | | |
| 331 | .armeb => return self.genAsmArch(.armeb, inst), | | |
| 332 | .aarch64 => return self.genAsmArch(.aarch64, inst), | | |
| 333 | .aarch64_be => return self.genAsmArch(.aarch64_be, inst), | | |
| 334 | .aarch64_32 => return self.genAsmArch(.aarch64_32, inst), | | |
| 335 | .arc => return self.genAsmArch(.arc, inst), | | |
| 336 | .avr => return self.genAsmArch(.avr, inst), | | |
| 337 | .bpfel => return self.genAsmArch(.bpfel, inst), | | |
| 338 | .bpfeb => return self.genAsmArch(.bpfeb, inst), | | |
| 339 | .hexagon => return self.genAsmArch(.hexagon, inst), | | |
| 340 | .mips => return self.genAsmArch(.mips, inst), | | |
| 341 | .mipsel => return self.genAsmArch(.mipsel, inst), | | |
| 342 | .mips64 => return self.genAsmArch(.mips64, inst), | | |
| 343 | .mips64el => return self.genAsmArch(.mips64el, inst), | | |
| 344 | .msp430 => return self.genAsmArch(.msp430, inst), | | |
| 345 | .powerpc => return self.genAsmArch(.powerpc, inst), | | |
| 346 | .powerpc64 => return self.genAsmArch(.powerpc64, inst), | | |
| 347 | .powerpc64le => return self.genAsmArch(.powerpc64le, inst), | | |
| 348 | .r600 => return self.genAsmArch(.r600, inst), | | |
| 349 | .amdgcn => return self.genAsmArch(.amdgcn, inst), | | |
| 350 | .riscv32 => return self.genAsmArch(.riscv32, inst), | | |
| 351 | .riscv64 => return self.genAsmArch(.riscv64, inst), | | |
| 352 | .sparc => return self.genAsmArch(.sparc, inst), | | |
| 353 | .sparcv9 => return self.genAsmArch(.sparcv9, inst), | | |
| 354 | .sparcel => return self.genAsmArch(.sparcel, inst), | | |
| 355 | .s390x => return self.genAsmArch(.s390x, inst), | | |
| 356 | .tce => return self.genAsmArch(.tce, inst), | | |
| 357 | .tcele => return self.genAsmArch(.tcele, inst), | | |
| 358 | .thumb => return self.genAsmArch(.thumb, inst), | | |
| 359 | .thumbeb => return self.genAsmArch(.thumbeb, inst), | | |
| 360 | .i386 => return self.genAsmArch(.i386, inst), | | |
| 361 | .x86_64 => return self.genAsmArch(.x86_64, inst), | | |
| 362 | .xcore => return self.genAsmArch(.xcore, inst), | | |
| 363 | .nvptx => return self.genAsmArch(.nvptx, inst), | | |
| 364 | .nvptx64 => return self.genAsmArch(.nvptx64, inst), | | |
| 365 | .le32 => return self.genAsmArch(.le32, inst), | | |
| 366 | .le64 => return self.genAsmArch(.le64, inst), | | |
| 367 | .amdil => return self.genAsmArch(.amdil, inst), | | |
| 368 | .amdil64 => return self.genAsmArch(.amdil64, inst), | | |
| 369 | .hsail => return self.genAsmArch(.hsail, inst), | | |
| 370 | .hsail64 => return self.genAsmArch(.hsail64, inst), | | |
| 371 | .spir => return self.genAsmArch(.spir, inst), | | |
| 372 | .spir64 => return self.genAsmArch(.spir64, inst), | | |
| 373 | .kalimba => return self.genAsmArch(.kalimba, inst), | | |
| 374 | .shave => return self.genAsmArch(.shave, inst), | | |
| 375 | .lanai => return self.genAsmArch(.lanai, inst), | | |
| 376 | .wasm32 => return self.genAsmArch(.wasm32, inst), | | |
| 377 | .wasm64 => return self.genAsmArch(.wasm64, inst), | | |
| 378 | .renderscript32 => return self.genAsmArch(.renderscript32, inst), | | |
| 379 | .renderscript64 => return self.genAsmArch(.renderscript64, inst), | | |
| 380 | .ve => return self.genAsmArch(.ve, inst), | | |
| 381 | } | | |
| 382 | } | | |
| 383 | | | |
| 384 | fn genAsmArch(self: *Function, comptime arch: Target.Cpu.Arch, inst: *ir.Inst.Assembly) !MCValue { | | |
| 385 | if (arch != .x86_64 and arch != .i386) { | 465 | if (arch != .x86_64 and arch != .i386) { |
| 386 | return self.fail(inst.base.src, "TODO implement inline asm support for more architectures", .{}); | 466 | return self.fail(inst.base.src, "TODO implement inline asm support for more architectures", .{}); |
| 387 | } | 467 | } |
| ... | @@ -607,6 +687,9 @@ const Function = struct { | ... | @@ -607,6 +687,9 @@ const Function = struct { |
| 607 | } | 687 | } |
| 608 | } | 688 | } |
| 609 | }, | 689 | }, |
| | 690 | .stack_offset => |off| { |
| | 691 | return self.fail(src, "TODO implement genSetReg for stack variables", .{}); |
| | 692 | } |
| 610 | }, | 693 | }, |
| 611 | else => return self.fail(src, "TODO implement genSetReg for more architectures", .{}), | 694 | else => return self.fail(src, "TODO implement genSetReg for more architectures", .{}), |
| 612 | } | 695 | } |