adding an name_of enum
Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
parent
a1139cfaf1
commit
1640cc12c4
6
.gitmodules
vendored
6
.gitmodules
vendored
|
@ -1,9 +1,3 @@
|
|||
[submodule "vendored-tests/lily"]
|
||||
path = vendored-tests/lily
|
||||
url = https://git.ablecorp.us/lily-org/lily.git
|
||||
[submodule "vendored-tests/mumd"]
|
||||
path = vendored-tests/mumd
|
||||
url = https://github.com/Ducklett/mumd.git
|
||||
[submodule "vendored/mumd"]
|
||||
path = vendored/mumd
|
||||
url = https://github.com/Ducklett/mumd.git
|
||||
|
|
73
README.md
73
README.md
|
@ -227,6 +227,17 @@ main := fn(): uint {
|
|||
}
|
||||
```
|
||||
|
||||
#### literals 3
|
||||
```hb
|
||||
expectations := .{
|
||||
return_value: 69,
|
||||
}
|
||||
|
||||
main := fn(): uint {
|
||||
return 'E'
|
||||
}
|
||||
```
|
||||
|
||||
#### functions 1
|
||||
```hb
|
||||
expectations := .{
|
||||
|
@ -1209,6 +1220,64 @@ main := fn(): uint {
|
|||
}
|
||||
```
|
||||
|
||||
#### enums 4
|
||||
```hb
|
||||
expectations := .{
|
||||
return_value: 69,
|
||||
}
|
||||
|
||||
NameMap := fn($Enum: type): type {
|
||||
sum := 0
|
||||
i: u8 = 0
|
||||
$loop $if i == @len_of(Enum) break else {
|
||||
sum += @int_cast(@name_of(@as(Enum, @bit_cast(i))).len)
|
||||
i += 1
|
||||
}
|
||||
|
||||
StrBuf := [sum]u8
|
||||
IndexBuf := [@len_of(Enum) + 1]uint
|
||||
return struct {
|
||||
.buf: StrBuf;
|
||||
.index: IndexBuf
|
||||
|
||||
new := fn(): @CurrentScope() {
|
||||
buf: StrBuf = idk
|
||||
index: IndexBuf = idk
|
||||
index[0] = 0
|
||||
|
||||
ii: u8 = 0
|
||||
bi := 0
|
||||
$loop $if ii == @len_of(Enum) break else {
|
||||
name := @name_of(@as(Enum, @bit_cast(ii)))
|
||||
ij := 0
|
||||
$loop $if ij == name.len break else {
|
||||
buf[bi + ij] = name[ij]
|
||||
ij += 1
|
||||
}
|
||||
|
||||
bi += @int_cast(name.len)
|
||||
ii += 1
|
||||
index[ii] = bi
|
||||
}
|
||||
|
||||
return .(buf, index)
|
||||
}
|
||||
|
||||
get := fn(self: ^@CurrentScope(), k: Enum): []u8 {
|
||||
return self.buf[self.index[k]..self.index[@as(u8, k) + 1]]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Nm := enum{.E; .bcd; .cd}
|
||||
|
||||
map := NameMap(Nm).new()
|
||||
|
||||
main := fn(): uint {
|
||||
return map.get(.E)[0]
|
||||
}
|
||||
```
|
||||
|
||||
#### match 1
|
||||
```hb
|
||||
main := fn(): uint {
|
||||
|
@ -1795,11 +1864,11 @@ func := fn(a: @Any(), b: @TypeOf(a)): uint {
|
|||
#### directives 14 (@name_of)
|
||||
```hb
|
||||
expectations := .{
|
||||
return_value: 4,
|
||||
return_value: 7,
|
||||
}
|
||||
|
||||
main := fn(): uint {
|
||||
return @name_of(uint).len
|
||||
return @name_of(uint).len + @name_of(enum{.foo}.foo).len
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ pub fn build(b: *std.Build) !void {
|
|||
}
|
||||
|
||||
const test_step = b.step("test", "run tests");
|
||||
const test_filter = b.option([]const u8, "tf", "passed as a filter to tests");
|
||||
|
||||
vendored_tests: {
|
||||
const grn = b.addExecutable(.{
|
||||
|
@ -53,6 +54,7 @@ pub fn build(b: *std.Build) !void {
|
|||
.root_source_file = out,
|
||||
.target = b.graph.host,
|
||||
.optimize = optimize,
|
||||
.filter = test_filter,
|
||||
.use_llvm = false,
|
||||
.use_lld = false,
|
||||
});
|
||||
|
@ -82,6 +84,7 @@ pub fn build(b: *std.Build) !void {
|
|||
.root_source_file = out,
|
||||
.target = b.graph.host,
|
||||
.optimize = optimize,
|
||||
.filter = test_filter,
|
||||
.use_llvm = false,
|
||||
.use_lld = false,
|
||||
});
|
||||
|
@ -199,7 +202,6 @@ pub fn build(b: *std.Build) !void {
|
|||
};
|
||||
|
||||
testing: {
|
||||
const test_filter = b.option([]const u8, "tf", "passed as a filter to tests");
|
||||
const unit_tests = b.addTest(.{
|
||||
.root_module = test_module,
|
||||
.filter = test_filter,
|
||||
|
|
|
@ -102,19 +102,6 @@ pub fn addFieldStore(self: *Builder, base: *BuildNode, offset: i64, ty: DataType
|
|||
_ = self.addStore(self.addFieldOffset(base, offset), ty, value);
|
||||
}
|
||||
|
||||
pub fn addIndexOffset(self: *Builder, base: *BuildNode, op: enum(u8) {
|
||||
iadd = @intFromEnum(BinOp.iadd),
|
||||
isub = @intFromEnum(BinOp.isub),
|
||||
}, elem_size: u64, subscript: *BuildNode) SpecificNode(.BinOp) {
|
||||
const offset = if (elem_size == 1)
|
||||
subscript
|
||||
else if (subscript.kind == .CInt)
|
||||
self.addIntImm(.int, subscript.extra(.CInt).* * @as(i64, @bitCast(elem_size)))
|
||||
else
|
||||
self.addBinOp(.imul, .int, subscript, self.addIntImm(.int, @bitCast(elem_size)));
|
||||
return self.addBinOp(@enumFromInt(@intFromEnum(op)), .int, base, offset);
|
||||
}
|
||||
|
||||
pub fn addSpill(self: *Builder, sloc: graph.Sloc, value: *BuildNode) SpecificNode(.Local) {
|
||||
const local = self.addLocal(sloc, value.data_type.size());
|
||||
_ = self.addStore(local, value.data_type, value);
|
||||
|
@ -135,6 +122,19 @@ pub fn addGlobalAddr(self: *Builder, arbitrary_global_id: u32) SpecificNode(.Glo
|
|||
|
||||
// #MATH =======================================================================
|
||||
|
||||
pub fn addIndexOffset(self: *Builder, base: *BuildNode, op: enum(u8) {
|
||||
iadd = @intFromEnum(BinOp.iadd),
|
||||
isub = @intFromEnum(BinOp.isub),
|
||||
}, elem_size: u64, subscript: *BuildNode) SpecificNode(.BinOp) {
|
||||
const offset = if (elem_size == 1)
|
||||
subscript
|
||||
else if (subscript.kind == .CInt)
|
||||
self.addIntImm(.int, subscript.extra(.CInt).* * @as(i64, @bitCast(elem_size)))
|
||||
else
|
||||
self.addBinOp(.imul, .int, subscript, self.addIntImm(.int, @bitCast(elem_size)));
|
||||
return self.addBinOp(@enumFromInt(@intFromEnum(op)), .int, base, offset);
|
||||
}
|
||||
|
||||
pub fn addIntImm(self: *Builder, ty: DataType, value: i64) SpecificNode(.CInt) {
|
||||
std.debug.assert(ty != .bot);
|
||||
const val = self.func.addNode(.CInt, ty, &.{null}, value);
|
||||
|
|
|
@ -409,7 +409,7 @@ pub fn GcmMixin(comptime MachNode: type) type {
|
|||
|
||||
var scheduled: usize = 0;
|
||||
if (ready != scheduled) while (scheduled < outs.len) {
|
||||
std.debug.assert(ready != scheduled);
|
||||
if (ready == scheduled) root.panic("{} {} {}", .{ scheduled, outs.len, node });
|
||||
|
||||
var pick = scheduled;
|
||||
for (outs[scheduled + 1 .. ready], scheduled + 1..) |o, i| {
|
||||
|
|
|
@ -183,6 +183,10 @@ pub const Expr = union(enum) {
|
|||
pos: Pos,
|
||||
end: u32,
|
||||
},
|
||||
Quotes: struct {
|
||||
pos: Pos,
|
||||
end: u32,
|
||||
},
|
||||
|
||||
pub const Type = struct {
|
||||
pos: Pos,
|
||||
|
|
|
@ -342,7 +342,7 @@ pub fn emit(self: *Codegen, ctx: Ctx, expr: Ast.Id) EmitError!Value {
|
|||
.String => |e| {
|
||||
const lit = ast.source[e.pos.index + 1 .. e.end - 1];
|
||||
|
||||
const data = switch (encodeString(lit, self.types.arena.alloc(u8, lit.len))) {
|
||||
const data = switch (encodeString(lit, self.types.arena.alloc(u8, lit.len)) catch unreachable) {
|
||||
.ok => |dt| dt,
|
||||
.err => |err| {
|
||||
var pos = e.pos;
|
||||
|
@ -353,6 +353,24 @@ pub fn emit(self: *Codegen, ctx: Ctx, expr: Ast.Id) EmitError!Value {
|
|||
|
||||
return self.emitStirng(ctx, data, expr);
|
||||
},
|
||||
.Quotes => |e| {
|
||||
const lit = ast.source[e.pos.index + 1 .. e.end - 1];
|
||||
|
||||
var char: [1]u8 = undefined;
|
||||
|
||||
const data = switch (encodeString(lit, &char) catch {
|
||||
return self.report(expr, "the char encodes into more then 1 byte", .{});
|
||||
}) {
|
||||
.ok => |dt| dt,
|
||||
.err => |err| {
|
||||
var pos = e.pos;
|
||||
pos.index += @intCast(err.pos);
|
||||
return self.report(pos, "{s}", .{err.reason});
|
||||
},
|
||||
};
|
||||
|
||||
return .mkv(.u8, self.bl.addIntImm(.i8, data[0]));
|
||||
},
|
||||
.Integer => |e| {
|
||||
var ty = ctx.ty orelse .uint;
|
||||
if (!ty.isInteger()) ty = .uint;
|
||||
|
@ -657,7 +675,8 @@ pub fn emit(self: *Codegen, ctx: Ctx, expr: Ast.Id) EmitError!Value {
|
|||
|
||||
// #OPS ========================================================================
|
||||
.SliceTy => |e| {
|
||||
const len: ?usize = if (e.len.tag() == .Void) null else @intCast(self.types.ct.evalIntConst(.{ .Tmp = self }, e.len) catch 0);
|
||||
var value = if (e.len.tag() == .Void) null else try self.emitTyped(.{}, .uint, e.len);
|
||||
const len: ?usize = if (value) |*vl| @intCast(self.partialEval(expr, vl.getValue(self)) catch 0) else null;
|
||||
const elem = try self.resolveAnonTy(e.elem);
|
||||
return self.emitTyConst(self.types.makeSlice(len, elem));
|
||||
},
|
||||
|
@ -1954,7 +1973,7 @@ pub const StringEncodeResutl = union(enum) {
|
|||
pub fn encodeString(
|
||||
literal: []const u8,
|
||||
buf: []u8,
|
||||
) StringEncodeResutl {
|
||||
) !StringEncodeResutl {
|
||||
const SPECIAL_CHARS = "nrt\\'\"0";
|
||||
const TO_BYTES = "\n\r\t\\\'\"\x00";
|
||||
|
||||
|
@ -1964,7 +1983,7 @@ pub fn encodeString(
|
|||
var bytes = std.mem.splitScalar(u8, literal, '\\');
|
||||
|
||||
while (bytes.next()) |chunk| {
|
||||
str.appendSliceAssumeCapacity(chunk);
|
||||
try str.appendSlice(std.testing.failing_allocator, chunk);
|
||||
if (bytes.rest().len == 0) break;
|
||||
switch (bytes.rest()[0]) {
|
||||
'{' => {
|
||||
|
@ -1977,14 +1996,14 @@ pub fn encodeString(
|
|||
const byte_val = std.fmt.parseInt(u8, hex_bytes[i .. i + 2], 16) catch {
|
||||
return .{ .err = .{ .reason = "expected hex digit or '}'", .pos = literal.len - bytes.rest().len } };
|
||||
};
|
||||
str.appendAssumeCapacity(byte_val);
|
||||
try str.append(std.testing.failing_allocator, byte_val);
|
||||
}
|
||||
bytes.index.? += i + 1;
|
||||
},
|
||||
else => |b| {
|
||||
for (SPECIAL_CHARS, TO_BYTES) |s, sb| {
|
||||
if (s == b) {
|
||||
str.appendAssumeCapacity(sb);
|
||||
try str.append(std.testing.failing_allocator, sb);
|
||||
break;
|
||||
}
|
||||
} else return .{ .err = .{ .reason = "unknown escape sequence", .pos = literal.len - bytes.rest().len } };
|
||||
|
@ -2249,8 +2268,22 @@ fn emitDirective(self: *Codegen, ctx: Ctx, expr: Ast.Id, e: *const Ast.Store.Tag
|
|||
.name_of => {
|
||||
try static.assertArgs(self, expr, args, "<ty>");
|
||||
|
||||
const ty = try self.resolveAnonTy(args[0]);
|
||||
const data = std.fmt.allocPrint(self.types.arena.allocator(), "{}", .{ty.fmt(self.types)}) catch unreachable;
|
||||
var value = try self.emit(.{}, args[0]);
|
||||
|
||||
const data = if (value.ty == .type) dt: {
|
||||
const ty = try self.unwrapTyConst(args[0], &value);
|
||||
break :dt std.fmt.allocPrint(self.types.arena.allocator(), "{}", .{ty.fmt(self.types)}) catch unreachable;
|
||||
} else switch (value.ty.data()) {
|
||||
.Enum => |enum_ty| dt: {
|
||||
if (enum_ty.getFields(self.types).len == 1) {
|
||||
break :dt enum_ty.getFields(self.types)[0].name;
|
||||
}
|
||||
|
||||
const id = try self.partialEval(args[0], value.getValue(self));
|
||||
break :dt enum_ty.getFields(self.types)[@intCast(id)].name;
|
||||
},
|
||||
else => return self.report(args[0], "can't compute a name of {}", .{value.ty}),
|
||||
};
|
||||
|
||||
return self.emitStirng(ctx, data, expr);
|
||||
},
|
||||
|
|
|
@ -73,6 +73,7 @@ pub fn partialEval(self: *Comptime, bl: *Builder, expr: *Node) PartialEvalResult
|
|||
|
||||
while (true) {
|
||||
const curr = work_list.pop().?;
|
||||
if (curr.id == std.math.maxInt(u16)) continue;
|
||||
const res = switch (curr.kind) {
|
||||
.CInt => {
|
||||
if (work_list.items.len == 0) {
|
||||
|
|
|
@ -228,6 +228,7 @@ fn fmtExprPrec(self: *Fmt, id: Id, prec: u8) Error!void {
|
|||
.Float => |f| try self.buf.appendSlice(Lexer.peekStr(self.ast.source, f.index)),
|
||||
.Bool => |b| try self.buf.appendSlice(if (b.value) "true" else "false"),
|
||||
.String => |s| try self.buf.appendSlice(Lexer.peekStr(self.ast.source, s.pos.index)),
|
||||
.Quotes => |s| try self.buf.appendSlice(Lexer.peekStr(self.ast.source, s.pos.index)),
|
||||
.Null => try self.buf.appendSlice("null"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -317,6 +317,8 @@ pub fn next(self: *Lexer) Token {
|
|||
block_comment,
|
||||
block_comment_end,
|
||||
line_commnet,
|
||||
double_quotes,
|
||||
double_quotes_slash,
|
||||
quotes,
|
||||
quotes_slash,
|
||||
zero,
|
||||
|
@ -340,13 +342,14 @@ pub fn next(self: *Lexer) Token {
|
|||
'$', '@', 'a'...'z', 'A'...'Z', '_', 128...255 => continue :state .ident,
|
||||
'0' => continue :state .zero,
|
||||
'1'...'9' => continue :state .dec,
|
||||
'"' => continue :state .quotes,
|
||||
'"' => continue :state .double_quotes,
|
||||
'\'' => continue :state .quotes,
|
||||
'/' => continue :state .slash,
|
||||
'.' => continue :state .dot,
|
||||
'=' => continue :state .equal,
|
||||
'<', '>' => continue :state .angle_bracket,
|
||||
':', '+', '-', '*', '%', '|', '^', '&', '!' => continue :state .op_equal,
|
||||
'#', '\'', '(', ')', ',', ';', '?', '[', '\\', ']', '`', '{', '}', '~' => |c| {
|
||||
'#', '(', ')', ',', ';', '?', '[', '\\', ']', '`', '{', '}', '~' => |c| {
|
||||
self.cursor += 1;
|
||||
break :state @enumFromInt(c);
|
||||
},
|
||||
|
@ -468,9 +471,9 @@ pub fn next(self: *Lexer) Token {
|
|||
.quotes => {
|
||||
self.cursor += 1;
|
||||
switch (self.source[self.cursor]) {
|
||||
'"' => {
|
||||
'\'' => {
|
||||
self.cursor += 1;
|
||||
break :state .@"\"";
|
||||
break :state .@"'";
|
||||
},
|
||||
'\\' => {
|
||||
self.cursor += 1;
|
||||
|
@ -484,6 +487,25 @@ pub fn next(self: *Lexer) Token {
|
|||
0 => break :state .@"unterminated string",
|
||||
else => continue :state .quotes,
|
||||
},
|
||||
.double_quotes => {
|
||||
self.cursor += 1;
|
||||
switch (self.source[self.cursor]) {
|
||||
'"' => {
|
||||
self.cursor += 1;
|
||||
break :state .@"\"";
|
||||
},
|
||||
'\\' => {
|
||||
self.cursor += 1;
|
||||
continue :state .double_quotes_slash;
|
||||
},
|
||||
0 => break :state .@"unterminated string",
|
||||
else => continue :state .double_quotes,
|
||||
}
|
||||
},
|
||||
.double_quotes_slash => switch (self.source[self.cursor]) {
|
||||
0 => break :state .@"unterminated string",
|
||||
else => continue :state .double_quotes,
|
||||
},
|
||||
.zero => {
|
||||
self.cursor += 1;
|
||||
switch (self.source[self.cursor]) {
|
||||
|
|
|
@ -471,6 +471,7 @@ fn parseUnitWithoutTail(self: *Parser) Error!Id {
|
|||
.Float => .{ .Float = .init(token.pos) },
|
||||
.true => .{ .Bool = .{ .value = true, .pos = .init(token.pos) } },
|
||||
.@"\"" => .{ .String = .{ .pos = .init(token.pos), .end = token.end } },
|
||||
.@"'" => .{ .Quotes = .{ .pos = .init(token.pos), .end = token.end } },
|
||||
.false => .{ .Bool = .{ .value = false, .pos = .init(token.pos) } },
|
||||
else => |k| {
|
||||
self.report(token.pos, "no idea how to handle this: {s}", .{@tagName(k)});
|
||||
|
|
|
@ -546,7 +546,7 @@ pub const Id = enum(usize) {
|
|||
|
||||
pub fn len(self: Id, types: *Types) ?usize {
|
||||
return switch (self.data()) {
|
||||
inline .Struct, .Union => |s| s.getFields(types).len,
|
||||
inline .Struct, .Union, .Enum => |s| s.getFields(types).len,
|
||||
.Slice => |s| s.len,
|
||||
else => null,
|
||||
};
|
||||
|
|
|
@ -1,20 +1,25 @@
|
|||
const std = @import("std");
|
||||
pub const root = @import("utils.zig");
|
||||
pub const utils = @import("utils.zig");
|
||||
pub const root = @import("root.zig");
|
||||
pub const test_util = @import("test_util.zig");
|
||||
pub const hbc = @import("hbc.zig");
|
||||
pub const fuzz = @import("fuzz.zig");
|
||||
|
||||
comptime {
|
||||
if (@import("root") == @This()) std.testing.refAllDeclsRecursive(@This());
|
||||
std.testing.refAllDeclsRecursive(@This());
|
||||
}
|
||||
|
||||
var ran = false;
|
||||
|
||||
pub fn runTest(name: []const u8, code: [:0]const u8) !void {
|
||||
root.Arena.initScratch(1024 * 1024);
|
||||
defer root.Arena.deinitScratch();
|
||||
if (!ran) {
|
||||
utils.Arena.initScratch(1024 * 1024);
|
||||
ran = true;
|
||||
}
|
||||
|
||||
const gpa = std.testing.allocator;
|
||||
|
||||
try test_util.testFmt(name, name, code);
|
||||
//try test_util.testFmt(name, name, code);
|
||||
|
||||
var out = std.ArrayList(u8).init(gpa);
|
||||
defer out.deinit();
|
||||
|
@ -22,7 +27,7 @@ pub fn runTest(name: []const u8, code: [:0]const u8) !void {
|
|||
errdefer {
|
||||
const stderr = std.io.getStdErr();
|
||||
const colors = std.io.tty.detectConfig(stderr);
|
||||
test_util.testBuilder(name, code, gpa, stderr.writer().any(), colors, true) catch unreachable;
|
||||
test_util.testBuilder(name, code, gpa, stderr.writer().any(), colors, true) catch {};
|
||||
}
|
||||
|
||||
try test_util.testBuilder(name, code, gpa, out.writer().any(), .no_color, false);
|
||||
|
@ -32,8 +37,8 @@ pub fn runTest(name: []const u8, code: [:0]const u8) !void {
|
|||
}
|
||||
|
||||
pub fn runFuzzFindingTest(name: []const u8, code: []const u8) !void {
|
||||
root.Arena.initScratch(1024 * 1024);
|
||||
defer root.Arena.deinitScratch();
|
||||
utils.Arena.initScratch(1024 * 1024);
|
||||
defer utils.Arena.deinitScratch();
|
||||
|
||||
const gpa = std.testing.allocator;
|
||||
|
||||
|
@ -49,8 +54,8 @@ pub fn runFuzzFindingTest(name: []const u8, code: []const u8) !void {
|
|||
}
|
||||
|
||||
pub fn runVendoredTest(path: []const u8) !void {
|
||||
if (true) return;
|
||||
root.Arena.initScratch(1024 * 1024);
|
||||
defer root.Arena.deinitScratch();
|
||||
if (std.mem.count(u8, path, "lily") == 2) return;
|
||||
utils.Arena.initScratch(1024 * 1024);
|
||||
defer utils.Arena.deinitScratch();
|
||||
try test_util.runVendoredTest(std.testing.allocator, path);
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
main:
|
||||
li64 $13, 4
|
||||
addi64 $13, $13, 3
|
||||
cp $1, $13
|
||||
tx
|
32
tests/enums 4.txt
Normal file
32
tests/enums 4.txt
Normal file
|
@ -0,0 +1,32 @@
|
|||
main:
|
||||
st $31, $254, -24, 24
|
||||
addi64 $254, $254, -24
|
||||
lra $32, $0, :map
|
||||
li64 $33, 0
|
||||
cp $1, $32
|
||||
cp $2, $33
|
||||
jal $31, $0, :NameMap(Enum = Nm)(StrBuf = [6]u8, IndexBuf = [4]uint).get
|
||||
cp $32, $1
|
||||
ld $32, $32, 0, 1
|
||||
andi $32, $32, 255
|
||||
cp $1, $32
|
||||
addi64 $254, $254, 24
|
||||
ld $31, $254, -24, 24
|
||||
tx
|
||||
NameMap(Enum = Nm)(StrBuf = [6]u8, IndexBuf = [4]uint).get:
|
||||
cp $13, $1
|
||||
cp $14, $2
|
||||
andi $15, $14, 255
|
||||
addi64 $15, $15, 1
|
||||
addi64 $16, $13, 8
|
||||
muli64 $14, $14, 8
|
||||
muli64 $15, $15, 8
|
||||
add64 $14, $16, $14
|
||||
add64 $15, $16, $15
|
||||
ld $14, $14, 0, 8
|
||||
ld $15, $15, 0, 8
|
||||
add64 $13, $13, $14
|
||||
sub64 $14, $15, $14
|
||||
cp $1, $13
|
||||
cp $2, $14
|
||||
jala $0, $31, 0
|
4
tests/literals 3.txt
Normal file
4
tests/literals 3.txt
Normal file
|
@ -0,0 +1,4 @@
|
|||
main:
|
||||
li64 $13, 69
|
||||
cp $1, $13
|
||||
tx
|
Loading…
Reference in a new issue