authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-20 21:48:35-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-03-20 21:48:35-07:00
log8bad5dfa72a33dec3919c3c3cb7590e51d03723b
treed70339e575f8f209364ef6066bf6d3e2cece7ca9
parent260c610708451624eab783bc4e99388e2b28a3ba

astgen: implement inline assembly


5 files changed, 71 insertions(+), 45 deletions(-)

BRANCH_TODO+1-1
......@@ -29,4 +29,4 @@ Performance optimizations to look into:
2929 tags associated with them.
3030 * use a smaller encoding for the auto generated return void at the end of
3131 function ZIR.
32
32 * enum literals can use small strings
src/Module.zig+27-8
......@@ -1183,6 +1183,22 @@ pub const Scope = struct {
11831183 });
11841184 }
11851185
1186 pub fn addStrTok(
1187 gz: *GenZir,
1188 tag: zir.Inst.Tag,
1189 str_index: u32,
1190 /// Absolute token index. This function does the conversion to Decl offset.
1191 abs_tok_index: ast.TokenIndex,
1192 ) !zir.Inst.Ref {
1193 return gz.add(.{
1194 .tag = tag,
1195 .data = .{ .str_tok = .{
1196 .start = str_index,
1197 .src_tok = abs_tok_index - gz.zir_code.decl.srcToken(),
1198 } },
1199 });
1200 }
1201
11861202 pub fn addBin(
11871203 gz: *GenZir,
11881204 tag: zir.Inst.Tag,
......@@ -4090,10 +4106,10 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)
40904106 if (!mem.startsWith(u8, ident_name, "@")) {
40914107 return ident_name;
40924108 }
4093 var buf = std.ArrayList(u8).init(mod.gpa);
4094 defer buf.deinit();
4109 var buf: std.ArrayListUnmanaged(u8) = .{};
4110 defer buf.deinit(mod.gpa);
40954111 try parseStrLit(mod, scope, token, &buf, ident_name, 1);
4096 return buf.toOwnedSlice();
4112 return buf.toOwnedSlice(mod.gpa);
40974113}
40984114
40994115/// Given an identifier token, obtain the string for it (possibly parsing as a string
......@@ -4103,16 +4119,16 @@ pub fn appendIdentStr(
41034119 mod: *Module,
41044120 scope: *Scope,
41054121 token: ast.TokenIndex,
4106 buf: *ArrayList(u8),
4122 buf: *std.ArrayListUnmanaged(u8),
41074123) InnerError!void {
41084124 const tree = scope.tree();
41094125 const token_tags = tree.tokens.items(.tag);
41104126 assert(token_tags[token] == .identifier);
41114127 const ident_name = tree.tokenSlice(token);
41124128 if (!mem.startsWith(u8, ident_name, "@")) {
4113 return buf.appendSlice(ident_name);
4129 return buf.appendSlice(mod.gpa, ident_name);
41144130 } else {
4115 return parseStrLit(scope, token, buf, ident_name, 1);
4131 return mod.parseStrLit(scope, token, buf, ident_name, 1);
41164132 }
41174133}
41184134
......@@ -4121,14 +4137,17 @@ pub fn parseStrLit(
41214137 mod: *Module,
41224138 scope: *Scope,
41234139 token: ast.TokenIndex,
4124 buf: *std.ArrayList(u8),
4140 buf: *std.ArrayListUnmanaged(u8),
41254141 bytes: []const u8,
41264142 offset: u32,
41274143) InnerError!void {
41284144 const tree = scope.tree();
41294145 const token_starts = tree.tokens.items(.start);
41304146 const raw_string = bytes[offset..];
4131 switch (try std.zig.string_literal.parseAppend(buf, raw_string)) {
4147 var buf_managed = buf.toManaged(mod.gpa);
4148 const result = std.zig.string_literal.parseAppend(&buf_managed, raw_string);
4149 buf.* = buf_managed.toUnmanaged();
4150 switch (try result) {
41324151 .success => return,
41334152 .invalid_character => |bad_index| {
41344153 return mod.failOff(
src/Sema.zig+1-2
......@@ -787,8 +787,7 @@ fn zirBlockFlat(
787787 try parent_block.instructions.appendSlice(sema.gpa, copied_instructions);
788788
789789 // The result of a flat block is the last instruction.
790 const last_zir_inst = body[body.len - 1];
791 return sema.resolveInst(last_zir_inst);
790 return sema.inst_map[body[body.len - 1]];
792791}
793792
794793fn zirBlock(
src/astgen.zig+41-33
......@@ -383,8 +383,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
383383
384384 .identifier => return identifier(mod, scope, rl, node),
385385
386 .asm_simple => return asmExpr(mod, scope, rl, tree.asmSimple(node)),
387 .@"asm" => return asmExpr(mod, scope, rl, tree.asmFull(node)),
386 .asm_simple => return asmExpr(mod, scope, rl, node, tree.asmSimple(node)),
387 .@"asm" => return asmExpr(mod, scope, rl, node, tree.asmFull(node)),
388388
389389 .string_literal => return stringLiteral(mod, scope, rl, node),
390390 .multiline_string_literal => return multilineStringLiteral(mod, scope, rl, node),
......@@ -497,15 +497,13 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
497497 return blockExpr(mod, scope, rl, node, statements);
498498 },
499499 .enum_literal => {
500 if (true) @panic("TODO update for zir-memory-layout");
501500 const ident_token = main_tokens[node];
502 const gen_zir = scope.getGenZir();
503 const string_bytes = &gen_zir.zir_exec.string_bytes;
504 const str_index = string_bytes.items.len;
501 const string_bytes = &gz.zir_code.string_bytes;
502 const str_index = @intCast(u32, string_bytes.items.len);
505503 try mod.appendIdentStr(scope, ident_token, string_bytes);
506 const str_len = string_bytes.items.len - str_index;
507 const result = try gen_zir.addStr(.enum_literal, str_index, str_len);
508 return rvalue(mod, scope, rl, result);
504 try string_bytes.append(mod.gpa, 0);
505 const result = try gz.addStrTok(.enum_literal, str_index, ident_token);
506 return rvalue(mod, scope, rl, result, node);
509507 },
510508 .error_value => {
511509 if (true) @panic("TODO update for zir-memory-layout");
......@@ -2994,48 +2992,58 @@ fn floatLiteral(
29942992 return rvalue(mod, scope, rl, result);
29952993}
29962994
2997fn asmExpr(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) InnerError!zir.Inst.Ref {
2998 if (true) @panic("TODO update for zir-memory-layout");
2995fn asmExpr(
2996 mod: *Module,
2997 scope: *Scope,
2998 rl: ResultLoc,
2999 node: ast.Node.Index,
3000 full: ast.full.Asm,
3001) InnerError!zir.Inst.Ref {
29993002 const arena = scope.arena();
30003003 const tree = scope.tree();
30013004 const main_tokens = tree.nodes.items(.main_token);
30023005 const token_starts = tree.tokens.items(.start);
30033006 const node_datas = tree.nodes.items(.data);
3007 const gz = scope.getGenZir();
3008
3009 const str_type = @enumToInt(zir.Const.const_slice_u8_type);
3010 const str_type_rl: ResultLoc = .{ .ty = str_type };
3011 const asm_source = try expr(mod, scope, str_type_rl, full.ast.template);
30043012
30053013 if (full.outputs.len != 0) {
30063014 return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{});
30073015 }
3016 const return_type = @enumToInt(zir.Const.void_type);
30083017
3009 const inputs = try arena.alloc([]const u8, full.inputs.len);
3018 const constraints = try arena.alloc(u32, full.inputs.len);
30103019 const args = try arena.alloc(zir.Inst.Ref, full.inputs.len);
30113020
3012 const str_type = try addZIRInstConst(mod, scope, src, .{
3013 .ty = Type.initTag(.type),
3014 .val = Value.initTag(.const_slice_u8_type),
3015 });
3016 const str_type_rl: ResultLoc = .{ .ty = str_type };
3017
30183021 for (full.inputs) |input, i| {
3019 // TODO semantically analyze constraints
30203022 const constraint_token = main_tokens[input] + 2;
3021 inputs[i] = try parseStringLiteral(mod, scope, constraint_token);
3022 args[i] = try expr(mod, scope, .none, node_datas[input].lhs);
3023 const string_bytes = &gz.zir_code.string_bytes;
3024 constraints[i] = @intCast(u32, string_bytes.items.len);
3025 try mod.appendIdentStr(scope, constraint_token, string_bytes);
3026 try string_bytes.append(mod.gpa, 0);
3027
3028 const usize_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.usize_type) };
3029 args[i] = try expr(mod, scope, usize_rl, node_datas[input].lhs);
30233030 }
30243031
3025 const return_type = try addZIRInstConst(mod, scope, src, .{
3026 .ty = Type.initTag(.type),
3027 .val = Value.initTag(.void_type),
3028 });
3029 const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.Asm, .{
3030 .asm_source = try expr(mod, scope, str_type_rl, full.ast.template),
3032 const tag: zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm";
3033 const result = try gz.addPlNode(.@"asm", node, zir.Inst.Asm{
3034 .asm_source = asm_source,
30313035 .return_type = return_type,
3032 }, .{
3033 .@"volatile" = full.volatile_token != null,
3034 //.clobbers = TODO handle clobbers
3035 .inputs = inputs,
3036 .args = args,
3036 .output = 0,
3037 .args_len = @intCast(u32, full.inputs.len),
3038 .clobbers_len = 0, // TODO implement asm clobbers
30373039 });
3038 return rvalue(mod, scope, rl, asm_inst);
3040
3041 try gz.zir_code.extra.ensureCapacity(mod.gpa, gz.zir_code.extra.items.len +
3042 args.len + constraints.len);
3043 gz.zir_code.extra.appendSliceAssumeCapacity(args);
3044 gz.zir_code.extra.appendSliceAssumeCapacity(constraints);
3045
3046 return rvalue(mod, scope, rl, result, node);
30393047}
30403048
30413049fn as(
src/zir.zig+1-1
......@@ -1145,7 +1145,7 @@ pub const Inst = struct {
11451145 /// Stored in extra. Trailing is:
11461146 /// * output_name: u32 // index into string_bytes (null terminated) if output is present
11471147 /// * arg: Ref // for every args_len.
1148 /// * arg_name: u32 // index into string_bytes (null terminated) for every args_len.
1148 /// * constraint: u32 // index into string_bytes (null terminated) for every args_len.
11491149 /// * clobber: u32 // index into string_bytes (null terminated) for every clobbers_len.
11501150 pub const Asm = struct {
11511151 asm_source: Ref,