aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-02-04 22:33:58 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-02-04 22:33:58 -0500
commit64a0510205b4d224413de52fd87632fbe6bfe083 (patch)
treec673e98af23f82d939ec0513bfbf8f757704a9a6 /src
parentb840184bb09b9d5e4272f848dcaa7c4973dfdcd5 (diff)
downloadzig-64a0510205b4d224413de52fd87632fbe6bfe083.tar.gz
zig-64a0510205b4d224413de52fd87632fbe6bfe083.zip
inline assembly supports `%=` syntax
it outputs a number that is unique to each instance of the asm statement in the entire compilation. useful when creating local labels and referring to them multiple times in a single template that generates multiple assembler instructions
Diffstat (limited to 'src')
-rw-r--r--src/all_types.hpp3
-rw-r--r--src/codegen.cpp14
-rw-r--r--src/parser.cpp4
3 files changed, 18 insertions, 3 deletions
diff --git a/src/all_types.hpp b/src/all_types.hpp
index 18f668c0ef..169e2266b6 100644
--- a/src/all_types.hpp
+++ b/src/all_types.hpp
@@ -604,6 +604,7 @@ enum AsmTokenId {
AsmTokenIdTemplate,
AsmTokenIdPercent,
AsmTokenIdVar,
+ AsmTokenIdUniqueId,
};
struct AsmToken {
@@ -1286,6 +1287,8 @@ struct CodeGen {
IrInstruction *invalid_instruction;
ConstExprValue const_void_val;
+
+ uint32_t unique_asm_id;
};
enum VarLinkage {
diff --git a/src/codegen.cpp b/src/codegen.cpp
index 9ade5cda42..3328bc3de4 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1481,6 +1481,9 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
Buf llvm_template = BUF_INIT;
buf_resize(&llvm_template, 0);
+ uint32_t unique_id = g->unique_asm_id;
+ g->unique_asm_id += 1;
+
for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) {
AsmToken *asm_token = &asm_expr->token_list.at(token_i);
switch (asm_token->id) {
@@ -1498,9 +1501,14 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
buf_append_char(&llvm_template, '%');
break;
case AsmTokenIdVar:
- size_t index = find_asm_index(g, asm_node, asm_token);
- assert(index < SIZE_MAX);
- buf_appendf(&llvm_template, "$%zu", index);
+ {
+ size_t index = find_asm_index(g, asm_node, asm_token);
+ assert(index < SIZE_MAX);
+ buf_appendf(&llvm_template, "$%zu", index);
+ break;
+ }
+ case AsmTokenIdUniqueId:
+ buf_appendf(&llvm_template, "%" PRIu32, unique_id);
break;
}
}
diff --git a/src/parser.cpp b/src/parser.cpp
index aa0d7ddff3..68ccd6aff4 100644
--- a/src/parser.cpp
+++ b/src/parser.cpp
@@ -136,6 +136,10 @@ static void parse_asm_template(ParseContext *pc, AstNode *node) {
} else if (c == '[') {
cur_tok->id = AsmTokenIdVar;
state = StateVar;
+ } else if (c == '=') {
+ cur_tok->id = AsmTokenIdUniqueId;
+ cur_tok->end = i;
+ state = StateStart;
} else {
ast_asm_error(pc, node, i, "expected a '%%' or '['");
}