mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
astgen: implement inline assembly
This commit is contained in:
parent
260c610708
commit
8bad5dfa72
@ -29,4 +29,4 @@ Performance optimizations to look into:
|
||||
tags associated with them.
|
||||
* use a smaller encoding for the auto generated return void at the end of
|
||||
function ZIR.
|
||||
|
||||
* enum literals can use small strings
|
||||
|
||||
@ -1183,6 +1183,22 @@ pub const Scope = struct {
|
||||
});
|
||||
}
|
||||
|
||||
pub fn addStrTok(
|
||||
gz: *GenZir,
|
||||
tag: zir.Inst.Tag,
|
||||
str_index: u32,
|
||||
/// Absolute token index. This function does the conversion to Decl offset.
|
||||
abs_tok_index: ast.TokenIndex,
|
||||
) !zir.Inst.Ref {
|
||||
return gz.add(.{
|
||||
.tag = tag,
|
||||
.data = .{ .str_tok = .{
|
||||
.start = str_index,
|
||||
.src_tok = abs_tok_index - gz.zir_code.decl.srcToken(),
|
||||
} },
|
||||
});
|
||||
}
|
||||
|
||||
pub fn addBin(
|
||||
gz: *GenZir,
|
||||
tag: zir.Inst.Tag,
|
||||
@ -4090,10 +4106,10 @@ pub fn identifierTokenString(mod: *Module, scope: *Scope, token: ast.TokenIndex)
|
||||
if (!mem.startsWith(u8, ident_name, "@")) {
|
||||
return ident_name;
|
||||
}
|
||||
var buf = std.ArrayList(u8).init(mod.gpa);
|
||||
defer buf.deinit();
|
||||
var buf: std.ArrayListUnmanaged(u8) = .{};
|
||||
defer buf.deinit(mod.gpa);
|
||||
try parseStrLit(mod, scope, token, &buf, ident_name, 1);
|
||||
return buf.toOwnedSlice();
|
||||
return buf.toOwnedSlice(mod.gpa);
|
||||
}
|
||||
|
||||
/// Given an identifier token, obtain the string for it (possibly parsing as a string
|
||||
@ -4103,16 +4119,16 @@ pub fn appendIdentStr(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
token: ast.TokenIndex,
|
||||
buf: *ArrayList(u8),
|
||||
buf: *std.ArrayListUnmanaged(u8),
|
||||
) InnerError!void {
|
||||
const tree = scope.tree();
|
||||
const token_tags = tree.tokens.items(.tag);
|
||||
assert(token_tags[token] == .identifier);
|
||||
const ident_name = tree.tokenSlice(token);
|
||||
if (!mem.startsWith(u8, ident_name, "@")) {
|
||||
return buf.appendSlice(ident_name);
|
||||
return buf.appendSlice(mod.gpa, ident_name);
|
||||
} else {
|
||||
return parseStrLit(scope, token, buf, ident_name, 1);
|
||||
return mod.parseStrLit(scope, token, buf, ident_name, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -4121,14 +4137,17 @@ pub fn parseStrLit(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
token: ast.TokenIndex,
|
||||
buf: *std.ArrayList(u8),
|
||||
buf: *std.ArrayListUnmanaged(u8),
|
||||
bytes: []const u8,
|
||||
offset: u32,
|
||||
) InnerError!void {
|
||||
const tree = scope.tree();
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const raw_string = bytes[offset..];
|
||||
switch (try std.zig.string_literal.parseAppend(buf, raw_string)) {
|
||||
var buf_managed = buf.toManaged(mod.gpa);
|
||||
const result = std.zig.string_literal.parseAppend(&buf_managed, raw_string);
|
||||
buf.* = buf_managed.toUnmanaged();
|
||||
switch (try result) {
|
||||
.success => return,
|
||||
.invalid_character => |bad_index| {
|
||||
return mod.failOff(
|
||||
|
||||
@ -787,8 +787,7 @@ fn zirBlockFlat(
|
||||
try parent_block.instructions.appendSlice(sema.gpa, copied_instructions);
|
||||
|
||||
// The result of a flat block is the last instruction.
|
||||
const last_zir_inst = body[body.len - 1];
|
||||
return sema.resolveInst(last_zir_inst);
|
||||
return sema.inst_map[body[body.len - 1]];
|
||||
}
|
||||
|
||||
fn zirBlock(
|
||||
|
||||
@ -383,8 +383,8 @@ pub fn expr(mod: *Module, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) In
|
||||
|
||||
.identifier => return identifier(mod, scope, rl, node),
|
||||
|
||||
.asm_simple => return asmExpr(mod, scope, rl, tree.asmSimple(node)),
|
||||
.@"asm" => return asmExpr(mod, scope, rl, tree.asmFull(node)),
|
||||
.asm_simple => return asmExpr(mod, scope, rl, node, tree.asmSimple(node)),
|
||||
.@"asm" => return asmExpr(mod, scope, rl, node, tree.asmFull(node)),
|
||||
|
||||
.string_literal => return stringLiteral(mod, scope, rl, node),
|
||||
.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
|
||||
return blockExpr(mod, scope, rl, node, statements);
|
||||
},
|
||||
.enum_literal => {
|
||||
if (true) @panic("TODO update for zir-memory-layout");
|
||||
const ident_token = main_tokens[node];
|
||||
const gen_zir = scope.getGenZir();
|
||||
const string_bytes = &gen_zir.zir_exec.string_bytes;
|
||||
const str_index = string_bytes.items.len;
|
||||
const string_bytes = &gz.zir_code.string_bytes;
|
||||
const str_index = @intCast(u32, string_bytes.items.len);
|
||||
try mod.appendIdentStr(scope, ident_token, string_bytes);
|
||||
const str_len = string_bytes.items.len - str_index;
|
||||
const result = try gen_zir.addStr(.enum_literal, str_index, str_len);
|
||||
return rvalue(mod, scope, rl, result);
|
||||
try string_bytes.append(mod.gpa, 0);
|
||||
const result = try gz.addStrTok(.enum_literal, str_index, ident_token);
|
||||
return rvalue(mod, scope, rl, result, node);
|
||||
},
|
||||
.error_value => {
|
||||
if (true) @panic("TODO update for zir-memory-layout");
|
||||
@ -2994,48 +2992,58 @@ fn floatLiteral(
|
||||
return rvalue(mod, scope, rl, result);
|
||||
}
|
||||
|
||||
fn asmExpr(mod: *Module, scope: *Scope, rl: ResultLoc, full: ast.full.Asm) InnerError!zir.Inst.Ref {
|
||||
if (true) @panic("TODO update for zir-memory-layout");
|
||||
fn asmExpr(
|
||||
mod: *Module,
|
||||
scope: *Scope,
|
||||
rl: ResultLoc,
|
||||
node: ast.Node.Index,
|
||||
full: ast.full.Asm,
|
||||
) InnerError!zir.Inst.Ref {
|
||||
const arena = scope.arena();
|
||||
const tree = scope.tree();
|
||||
const main_tokens = tree.nodes.items(.main_token);
|
||||
const token_starts = tree.tokens.items(.start);
|
||||
const node_datas = tree.nodes.items(.data);
|
||||
const gz = scope.getGenZir();
|
||||
|
||||
const str_type = @enumToInt(zir.Const.const_slice_u8_type);
|
||||
const str_type_rl: ResultLoc = .{ .ty = str_type };
|
||||
const asm_source = try expr(mod, scope, str_type_rl, full.ast.template);
|
||||
|
||||
if (full.outputs.len != 0) {
|
||||
return mod.failTok(scope, full.ast.asm_token, "TODO implement asm with an output", .{});
|
||||
}
|
||||
const return_type = @enumToInt(zir.Const.void_type);
|
||||
|
||||
const inputs = try arena.alloc([]const u8, full.inputs.len);
|
||||
const constraints = try arena.alloc(u32, full.inputs.len);
|
||||
const args = try arena.alloc(zir.Inst.Ref, full.inputs.len);
|
||||
|
||||
const str_type = try addZIRInstConst(mod, scope, src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.const_slice_u8_type),
|
||||
});
|
||||
const str_type_rl: ResultLoc = .{ .ty = str_type };
|
||||
|
||||
for (full.inputs) |input, i| {
|
||||
// TODO semantically analyze constraints
|
||||
const constraint_token = main_tokens[input] + 2;
|
||||
inputs[i] = try parseStringLiteral(mod, scope, constraint_token);
|
||||
args[i] = try expr(mod, scope, .none, node_datas[input].lhs);
|
||||
const string_bytes = &gz.zir_code.string_bytes;
|
||||
constraints[i] = @intCast(u32, string_bytes.items.len);
|
||||
try mod.appendIdentStr(scope, constraint_token, string_bytes);
|
||||
try string_bytes.append(mod.gpa, 0);
|
||||
|
||||
const usize_rl: ResultLoc = .{ .ty = @enumToInt(zir.Const.usize_type) };
|
||||
args[i] = try expr(mod, scope, usize_rl, node_datas[input].lhs);
|
||||
}
|
||||
|
||||
const return_type = try addZIRInstConst(mod, scope, src, .{
|
||||
.ty = Type.initTag(.type),
|
||||
.val = Value.initTag(.void_type),
|
||||
});
|
||||
const asm_inst = try addZIRInst(mod, scope, src, zir.Inst.Asm, .{
|
||||
.asm_source = try expr(mod, scope, str_type_rl, full.ast.template),
|
||||
const tag: zir.Inst.Tag = if (full.volatile_token != null) .asm_volatile else .@"asm";
|
||||
const result = try gz.addPlNode(.@"asm", node, zir.Inst.Asm{
|
||||
.asm_source = asm_source,
|
||||
.return_type = return_type,
|
||||
}, .{
|
||||
.@"volatile" = full.volatile_token != null,
|
||||
//.clobbers = TODO handle clobbers
|
||||
.inputs = inputs,
|
||||
.args = args,
|
||||
.output = 0,
|
||||
.args_len = @intCast(u32, full.inputs.len),
|
||||
.clobbers_len = 0, // TODO implement asm clobbers
|
||||
});
|
||||
return rvalue(mod, scope, rl, asm_inst);
|
||||
|
||||
try gz.zir_code.extra.ensureCapacity(mod.gpa, gz.zir_code.extra.items.len +
|
||||
args.len + constraints.len);
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(args);
|
||||
gz.zir_code.extra.appendSliceAssumeCapacity(constraints);
|
||||
|
||||
return rvalue(mod, scope, rl, result, node);
|
||||
}
|
||||
|
||||
fn as(
|
||||
|
||||
@ -1145,7 +1145,7 @@ pub const Inst = struct {
|
||||
/// Stored in extra. Trailing is:
|
||||
/// * output_name: u32 // index into string_bytes (null terminated) if output is present
|
||||
/// * arg: Ref // for every args_len.
|
||||
/// * arg_name: u32 // index into string_bytes (null terminated) for every args_len.
|
||||
/// * constraint: u32 // index into string_bytes (null terminated) for every args_len.
|
||||
/// * clobber: u32 // index into string_bytes (null terminated) for every clobbers_len.
|
||||
pub const Asm = struct {
|
||||
asm_source: Ref,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user