Commit 64a0510205

Andrew Kelley <superjoe30@gmail.com>
2017-02-05 04:33:58
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
1 parent b840184
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 {
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;
         }
     }
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 '['");
                 }