| ... | ... | @@ -1544,133 +1544,129 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa |
| 1544 | 1544 | return LLVMBuildStructGEP(g->builder, struct_ptr, field->gen_index, ""); |
| 1545 | 1545 | } |
| 1546 | 1546 | |
| 1547 | static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok) { |
| 1548 | const char *ptr = buf_ptr(node->data.asm_expr.asm_template) + tok->start + 2; |
| 1549 | size_t len = tok->end - tok->start - 2; |
| 1550 | size_t result = 0; |
| 1551 | for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) { |
| 1552 | AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); |
| 1553 | if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) { |
| 1554 | return result; |
| 1555 | } |
| 1556 | } |
| 1557 | for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) { |
| 1558 | AsmInput *asm_input = node->data.asm_expr.input_list.at(i); |
| 1559 | if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) { |
| 1560 | return result; |
| 1561 | } |
| 1562 | } |
| 1563 | return SIZE_MAX; |
| 1564 | } |
| 1565 | |
| 1547 | 1566 | static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstructionAsm *instruction) { |
| 1548 | | zig_panic("TODO render asm"); |
| 1549 | | } |
| 1550 | | //static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok) { |
| 1551 | | // const char *ptr = buf_ptr(node->data.asm_expr.asm_template) + tok->start + 2; |
| 1552 | | // size_t len = tok->end - tok->start - 2; |
| 1553 | | // size_t result = 0; |
| 1554 | | // for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) { |
| 1555 | | // AsmOutput *asm_output = node->data.asm_expr.output_list.at(i); |
| 1556 | | // if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) { |
| 1557 | | // return result; |
| 1558 | | // } |
| 1559 | | // } |
| 1560 | | // for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) { |
| 1561 | | // AsmInput *asm_input = node->data.asm_expr.input_list.at(i); |
| 1562 | | // if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) { |
| 1563 | | // return result; |
| 1564 | | // } |
| 1565 | | // } |
| 1566 | | // return SIZE_MAX; |
| 1567 | | //} |
| 1568 | | // |
| 1569 | | //static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) { |
| 1570 | | // assert(node->type == NodeTypeAsmExpr); |
| 1571 | | // |
| 1572 | | // AstNodeAsmExpr *asm_expr = &node->data.asm_expr; |
| 1573 | | // |
| 1574 | | // Buf *src_template = asm_expr->asm_template; |
| 1575 | | // |
| 1576 | | // Buf llvm_template = BUF_INIT; |
| 1577 | | // buf_resize(&llvm_template, 0); |
| 1578 | | // |
| 1579 | | // for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) { |
| 1580 | | // AsmToken *asm_token = &asm_expr->token_list.at(token_i); |
| 1581 | | // switch (asm_token->id) { |
| 1582 | | // case AsmTokenIdTemplate: |
| 1583 | | // for (size_t offset = asm_token->start; offset < asm_token->end; offset += 1) { |
| 1584 | | // uint8_t c = *((uint8_t*)(buf_ptr(src_template) + offset)); |
| 1585 | | // if (c == '$') { |
| 1586 | | // buf_append_str(&llvm_template, "$$"); |
| 1587 | | // } else { |
| 1588 | | // buf_append_char(&llvm_template, c); |
| 1589 | | // } |
| 1590 | | // } |
| 1591 | | // break; |
| 1592 | | // case AsmTokenIdPercent: |
| 1593 | | // buf_append_char(&llvm_template, '%'); |
| 1594 | | // break; |
| 1595 | | // case AsmTokenIdVar: |
| 1596 | | // size_t index = find_asm_index(g, node, asm_token); |
| 1597 | | // assert(index < SIZE_MAX); |
| 1598 | | // buf_appendf(&llvm_template, "$%zu", index); |
| 1599 | | // break; |
| 1600 | | // } |
| 1601 | | // } |
| 1602 | | // |
| 1603 | | // Buf constraint_buf = BUF_INIT; |
| 1604 | | // buf_resize(&constraint_buf, 0); |
| 1605 | | // |
| 1606 | | // assert(asm_expr->return_count == 0 || asm_expr->return_count == 1); |
| 1607 | | // |
| 1608 | | // size_t total_constraint_count = asm_expr->output_list.length + |
| 1609 | | // asm_expr->input_list.length + |
| 1610 | | // asm_expr->clobber_list.length; |
| 1611 | | // size_t input_and_output_count = asm_expr->output_list.length + |
| 1612 | | // asm_expr->input_list.length - |
| 1613 | | // asm_expr->return_count; |
| 1614 | | // size_t total_index = 0; |
| 1615 | | // size_t param_index = 0; |
| 1616 | | // LLVMTypeRef *param_types = allocate<LLVMTypeRef>(input_and_output_count); |
| 1617 | | // LLVMValueRef *param_values = allocate<LLVMValueRef>(input_and_output_count); |
| 1618 | | // for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) { |
| 1619 | | // AsmOutput *asm_output = asm_expr->output_list.at(i); |
| 1620 | | // bool is_return = (asm_output->return_type != nullptr); |
| 1621 | | // assert(*buf_ptr(asm_output->constraint) == '='); |
| 1622 | | // if (is_return) { |
| 1623 | | // buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1); |
| 1624 | | // } else { |
| 1625 | | // buf_appendf(&constraint_buf, "=*%s", buf_ptr(asm_output->constraint) + 1); |
| 1626 | | // } |
| 1627 | | // if (total_index + 1 < total_constraint_count) { |
| 1628 | | // buf_append_char(&constraint_buf, ','); |
| 1629 | | // } |
| 1630 | | // |
| 1631 | | // if (!is_return) { |
| 1632 | | // VariableTableEntry *variable = asm_output->variable; |
| 1633 | | // assert(variable); |
| 1634 | | // param_types[param_index] = LLVMTypeOf(variable->value_ref); |
| 1635 | | // param_values[param_index] = variable->value_ref; |
| 1636 | | // param_index += 1; |
| 1637 | | // } |
| 1638 | | // } |
| 1639 | | // for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) { |
| 1640 | | // AsmInput *asm_input = asm_expr->input_list.at(i); |
| 1641 | | // buf_append_buf(&constraint_buf, asm_input->constraint); |
| 1642 | | // if (total_index + 1 < total_constraint_count) { |
| 1643 | | // buf_append_char(&constraint_buf, ','); |
| 1644 | | // } |
| 1645 | | // |
| 1646 | | // TypeTableEntry *expr_type = get_expr_type(asm_input->expr); |
| 1647 | | // param_types[param_index] = expr_type->type_ref; |
| 1648 | | // param_values[param_index] = gen_expr(g, asm_input->expr); |
| 1649 | | // } |
| 1650 | | // for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) { |
| 1651 | | // Buf *clobber_buf = asm_expr->clobber_list.at(i); |
| 1652 | | // buf_appendf(&constraint_buf, "~{%s}", buf_ptr(clobber_buf)); |
| 1653 | | // if (total_index + 1 < total_constraint_count) { |
| 1654 | | // buf_append_char(&constraint_buf, ','); |
| 1655 | | // } |
| 1656 | | // } |
| 1657 | | // |
| 1658 | | // LLVMTypeRef ret_type; |
| 1659 | | // if (asm_expr->return_count == 0) { |
| 1660 | | // ret_type = LLVMVoidType(); |
| 1661 | | // } else { |
| 1662 | | // ret_type = get_expr_type(node)->type_ref; |
| 1663 | | // } |
| 1664 | | // LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, input_and_output_count, false); |
| 1665 | | // |
| 1666 | | // bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0); |
| 1667 | | // LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template), |
| 1668 | | // buf_ptr(&constraint_buf), is_volatile, false); |
| 1669 | | // |
| 1670 | | // set_debug_source_node(g, node); |
| 1671 | | // return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, ""); |
| 1672 | | //} |
| 1673 | | // |
| 1567 | AstNode *asm_node = instruction->base.source_node; |
| 1568 | assert(asm_node->type == NodeTypeAsmExpr); |
| 1569 | AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr; |
| 1570 | |
| 1571 | Buf *src_template = asm_expr->asm_template; |
| 1572 | |
| 1573 | Buf llvm_template = BUF_INIT; |
| 1574 | buf_resize(&llvm_template, 0); |
| 1575 | |
| 1576 | for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) { |
| 1577 | AsmToken *asm_token = &asm_expr->token_list.at(token_i); |
| 1578 | switch (asm_token->id) { |
| 1579 | case AsmTokenIdTemplate: |
| 1580 | for (size_t offset = asm_token->start; offset < asm_token->end; offset += 1) { |
| 1581 | uint8_t c = *((uint8_t*)(buf_ptr(src_template) + offset)); |
| 1582 | if (c == '$') { |
| 1583 | buf_append_str(&llvm_template, "$$"); |
| 1584 | } else { |
| 1585 | buf_append_char(&llvm_template, c); |
| 1586 | } |
| 1587 | } |
| 1588 | break; |
| 1589 | case AsmTokenIdPercent: |
| 1590 | buf_append_char(&llvm_template, '%'); |
| 1591 | break; |
| 1592 | case AsmTokenIdVar: |
| 1593 | size_t index = find_asm_index(g, asm_node, asm_token); |
| 1594 | assert(index < SIZE_MAX); |
| 1595 | buf_appendf(&llvm_template, "$%zu", index); |
| 1596 | break; |
| 1597 | } |
| 1598 | } |
| 1599 | |
| 1600 | Buf constraint_buf = BUF_INIT; |
| 1601 | buf_resize(&constraint_buf, 0); |
| 1602 | |
| 1603 | assert(instruction->return_count == 0 || instruction->return_count == 1); |
| 1604 | |
| 1605 | size_t total_constraint_count = asm_expr->output_list.length + |
| 1606 | asm_expr->input_list.length + |
| 1607 | asm_expr->clobber_list.length; |
| 1608 | size_t input_and_output_count = asm_expr->output_list.length + |
| 1609 | asm_expr->input_list.length - |
| 1610 | instruction->return_count; |
| 1611 | size_t total_index = 0; |
| 1612 | size_t param_index = 0; |
| 1613 | LLVMTypeRef *param_types = allocate<LLVMTypeRef>(input_and_output_count); |
| 1614 | LLVMValueRef *param_values = allocate<LLVMValueRef>(input_and_output_count); |
| 1615 | for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) { |
| 1616 | AsmOutput *asm_output = asm_expr->output_list.at(i); |
| 1617 | bool is_return = (asm_output->return_type != nullptr); |
| 1618 | assert(*buf_ptr(asm_output->constraint) == '='); |
| 1619 | if (is_return) { |
| 1620 | buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1); |
| 1621 | } else { |
| 1622 | buf_appendf(&constraint_buf, "=*%s", buf_ptr(asm_output->constraint) + 1); |
| 1623 | } |
| 1624 | if (total_index + 1 < total_constraint_count) { |
| 1625 | buf_append_char(&constraint_buf, ','); |
| 1626 | } |
| 1627 | |
| 1628 | if (!is_return) { |
| 1629 | VariableTableEntry *variable = asm_output->variable; |
| 1630 | assert(variable); |
| 1631 | param_types[param_index] = LLVMTypeOf(variable->value_ref); |
| 1632 | param_values[param_index] = variable->value_ref; |
| 1633 | param_index += 1; |
| 1634 | } |
| 1635 | } |
| 1636 | for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) { |
| 1637 | AsmInput *asm_input = asm_expr->input_list.at(i); |
| 1638 | IrInstruction *ir_input = instruction->input_list[i]; |
| 1639 | buf_append_buf(&constraint_buf, asm_input->constraint); |
| 1640 | if (total_index + 1 < total_constraint_count) { |
| 1641 | buf_append_char(&constraint_buf, ','); |
| 1642 | } |
| 1643 | |
| 1644 | param_types[param_index] = ir_input->type_entry->type_ref; |
| 1645 | param_values[param_index] = ir_llvm_value(g, ir_input); |
| 1646 | } |
| 1647 | for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) { |
| 1648 | Buf *clobber_buf = asm_expr->clobber_list.at(i); |
| 1649 | buf_appendf(&constraint_buf, "~{%s}", buf_ptr(clobber_buf)); |
| 1650 | if (total_index + 1 < total_constraint_count) { |
| 1651 | buf_append_char(&constraint_buf, ','); |
| 1652 | } |
| 1653 | } |
| 1654 | |
| 1655 | LLVMTypeRef ret_type; |
| 1656 | if (instruction->return_count == 0) { |
| 1657 | ret_type = LLVMVoidType(); |
| 1658 | } else { |
| 1659 | ret_type = instruction->base.type_entry->type_ref; |
| 1660 | } |
| 1661 | LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, input_and_output_count, false); |
| 1662 | |
| 1663 | bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0); |
| 1664 | LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template), |
| 1665 | buf_ptr(&constraint_buf), is_volatile, false); |
| 1666 | |
| 1667 | set_debug_source_node(g, asm_node); |
| 1668 | return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, ""); |
| 1669 | } |
| 1674 | 1670 | |
| 1675 | 1671 | |
| 1676 | 1672 | |
| ... | ... | @@ -3307,7 +3303,7 @@ void codegen_generate_h_file(CodeGen *g) { |
| 3307 | 3303 | continue; |
| 3308 | 3304 | |
| 3309 | 3305 | Buf return_type_c = BUF_INIT; |
| 3310 | | get_c_type_node(g, fn_proto->return_type, &return_type_c); |
| 3306 | get_c_type(g, fn_table_entry->type_entry->data.fn.fn_type_id.return_type, &return_type_c); |
| 3311 | 3307 | |
| 3312 | 3308 | buf_appendf(&h_buf, "%s %s %s(", |
| 3313 | 3309 | buf_ptr(export_macro), |