authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-04 22:33:58-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-04 22:33:58-05:00
log64a0510205b4d224413de52fd87632fbe6bfe083
treec673e98af23f82d939ec0513bfbf8f757704a9a6
parentb840184bb09b9d5e4272f848dcaa7c4973dfdcd5

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

3 files changed, 18 insertions(+), 3 deletions(-)

src/all_types.hpp+3
...@@ -604,6 +604,7 @@ enum AsmTokenId {...@@ -604,6 +604,7 @@ enum AsmTokenId {
604 AsmTokenIdTemplate,604 AsmTokenIdTemplate,
605 AsmTokenIdPercent,605 AsmTokenIdPercent,
606 AsmTokenIdVar,606 AsmTokenIdVar,
607 AsmTokenIdUniqueId,
607};608};
608609
609struct AsmToken {610struct AsmToken {
...@@ -1286,6 +1287,8 @@ struct CodeGen {...@@ -1286,6 +1287,8 @@ struct CodeGen {
12861287
1287 IrInstruction *invalid_instruction;1288 IrInstruction *invalid_instruction;
1288 ConstExprValue const_void_val;1289 ConstExprValue const_void_val;
1290
1291 uint32_t unique_asm_id;
1289};1292};
12901293
1291enum VarLinkage {1294enum VarLinkage {
src/codegen.cpp+11-3
...@@ -1481,6 +1481,9 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru...@@ -1481,6 +1481,9 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
1481 Buf llvm_template = BUF_INIT;1481 Buf llvm_template = BUF_INIT;
1482 buf_resize(&llvm_template, 0);1482 buf_resize(&llvm_template, 0);
14831483
1484 uint32_t unique_id = g->unique_asm_id;
1485 g->unique_asm_id += 1;
1486
1484 for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) {1487 for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) {
1485 AsmToken *asm_token = &asm_expr->token_list.at(token_i);1488 AsmToken *asm_token = &asm_expr->token_list.at(token_i);
1486 switch (asm_token->id) {1489 switch (asm_token->id) {
...@@ -1498,9 +1501,14 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru...@@ -1498,9 +1501,14 @@ static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstru
1498 buf_append_char(&llvm_template, '%');1501 buf_append_char(&llvm_template, '%');
1499 break;1502 break;
1500 case AsmTokenIdVar:1503 case AsmTokenIdVar:
1501 size_t index = find_asm_index(g, asm_node, asm_token);1504 {
1502 assert(index < SIZE_MAX);1505 size_t index = find_asm_index(g, asm_node, asm_token);
1503 buf_appendf(&llvm_template, "$%zu", index);1506 assert(index < SIZE_MAX);
1507 buf_appendf(&llvm_template, "$%zu", index);
1508 break;
1509 }
1510 case AsmTokenIdUniqueId:
1511 buf_appendf(&llvm_template, "%" PRIu32, unique_id);
1504 break;1512 break;
1505 }1513 }
1506 }1514 }
src/parser.cpp+4
...@@ -136,6 +136,10 @@ static void parse_asm_template(ParseContext *pc, AstNode *node) {...@@ -136,6 +136,10 @@ static void parse_asm_template(ParseContext *pc, AstNode *node) {
136 } else if (c == '[') {136 } else if (c == '[') {
137 cur_tok->id = AsmTokenIdVar;137 cur_tok->id = AsmTokenIdVar;
138 state = StateVar;138 state = StateVar;
139 } else if (c == '=') {
140 cur_tok->id = AsmTokenIdUniqueId;
141 cur_tok->end = i;
142 state = StateStart;
139 } else {143 } else {
140 ast_asm_error(pc, node, i, "expected a '%%' or '['");144 ast_asm_error(pc, node, i, "expected a '%%' or '['");
141 }145 }