authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-18 02:07:40-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-18 02:07:40-05:00
loged31ae8867fd2d7b5274c6b127d42360b48fc49c
tree31fa0c177955c8003c6c9235e8413411cf66adef
parentc3b603fdf9f1edcfe8a0e45413a1c30a563e87d4

IR: inline assembly working


2 files changed, 136 insertions(+), 130 deletions(-)

src/codegen.cpp+123-127
...@@ -1544,133 +1544,129 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa...@@ -1544,133 +1544,129 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
1544 return LLVMBuildStructGEP(g->builder, struct_ptr, field->gen_index, "");1544 return LLVMBuildStructGEP(g->builder, struct_ptr, field->gen_index, "");
1545}1545}
15461546
1547static 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
1547static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstructionAsm *instruction) {1566static LLVMValueRef ir_render_asm(CodeGen *g, IrExecutable *executable, IrInstructionAsm *instruction) {
1548 zig_panic("TODO render asm");1567 AstNode *asm_node = instruction->base.source_node;
1549}1568 assert(asm_node->type == NodeTypeAsmExpr);
1550//static size_t find_asm_index(CodeGen *g, AstNode *node, AsmToken *tok) {1569 AstNodeAsmExpr *asm_expr = &asm_node->data.asm_expr;
1551// const char *ptr = buf_ptr(node->data.asm_expr.asm_template) + tok->start + 2;1570
1552// size_t len = tok->end - tok->start - 2;1571 Buf *src_template = asm_expr->asm_template;
1553// size_t result = 0;1572
1554// for (size_t i = 0; i < node->data.asm_expr.output_list.length; i += 1, result += 1) {1573 Buf llvm_template = BUF_INIT;
1555// AsmOutput *asm_output = node->data.asm_expr.output_list.at(i);1574 buf_resize(&llvm_template, 0);
1556// if (buf_eql_mem(asm_output->asm_symbolic_name, ptr, len)) {1575
1557// return result;1576 for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) {
1558// }1577 AsmToken *asm_token = &asm_expr->token_list.at(token_i);
1559// }1578 switch (asm_token->id) {
1560// for (size_t i = 0; i < node->data.asm_expr.input_list.length; i += 1, result += 1) {1579 case AsmTokenIdTemplate:
1561// AsmInput *asm_input = node->data.asm_expr.input_list.at(i);1580 for (size_t offset = asm_token->start; offset < asm_token->end; offset += 1) {
1562// if (buf_eql_mem(asm_input->asm_symbolic_name, ptr, len)) {1581 uint8_t c = *((uint8_t*)(buf_ptr(src_template) + offset));
1563// return result;1582 if (c == '$') {
1564// }1583 buf_append_str(&llvm_template, "$$");
1565// }1584 } else {
1566// return SIZE_MAX;1585 buf_append_char(&llvm_template, c);
1567//}1586 }
1568//1587 }
1569//static LLVMValueRef gen_asm_expr(CodeGen *g, AstNode *node) {1588 break;
1570// assert(node->type == NodeTypeAsmExpr);1589 case AsmTokenIdPercent:
1571//1590 buf_append_char(&llvm_template, '%');
1572// AstNodeAsmExpr *asm_expr = &node->data.asm_expr;1591 break;
1573//1592 case AsmTokenIdVar:
1574// Buf *src_template = asm_expr->asm_template;1593 size_t index = find_asm_index(g, asm_node, asm_token);
1575//1594 assert(index < SIZE_MAX);
1576// Buf llvm_template = BUF_INIT;1595 buf_appendf(&llvm_template, "$%zu", index);
1577// buf_resize(&llvm_template, 0);1596 break;
1578//1597 }
1579// for (size_t token_i = 0; token_i < asm_expr->token_list.length; token_i += 1) {1598 }
1580// AsmToken *asm_token = &asm_expr->token_list.at(token_i);1599
1581// switch (asm_token->id) {1600 Buf constraint_buf = BUF_INIT;
1582// case AsmTokenIdTemplate:1601 buf_resize(&constraint_buf, 0);
1583// for (size_t offset = asm_token->start; offset < asm_token->end; offset += 1) {1602
1584// uint8_t c = *((uint8_t*)(buf_ptr(src_template) + offset));1603 assert(instruction->return_count == 0 || instruction->return_count == 1);
1585// if (c == '$') {1604
1586// buf_append_str(&llvm_template, "$$");1605 size_t total_constraint_count = asm_expr->output_list.length +
1587// } else {1606 asm_expr->input_list.length +
1588// buf_append_char(&llvm_template, c);1607 asm_expr->clobber_list.length;
1589// }1608 size_t input_and_output_count = asm_expr->output_list.length +
1590// }1609 asm_expr->input_list.length -
1591// break;1610 instruction->return_count;
1592// case AsmTokenIdPercent:1611 size_t total_index = 0;
1593// buf_append_char(&llvm_template, '%');1612 size_t param_index = 0;
1594// break;1613 LLVMTypeRef *param_types = allocate<LLVMTypeRef>(input_and_output_count);
1595// case AsmTokenIdVar:1614 LLVMValueRef *param_values = allocate<LLVMValueRef>(input_and_output_count);
1596// size_t index = find_asm_index(g, node, asm_token);1615 for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) {
1597// assert(index < SIZE_MAX);1616 AsmOutput *asm_output = asm_expr->output_list.at(i);
1598// buf_appendf(&llvm_template, "$%zu", index);1617 bool is_return = (asm_output->return_type != nullptr);
1599// break;1618 assert(*buf_ptr(asm_output->constraint) == '=');
1600// }1619 if (is_return) {
1601// }1620 buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);
1602//1621 } else {
1603// Buf constraint_buf = BUF_INIT;1622 buf_appendf(&constraint_buf, "=*%s", buf_ptr(asm_output->constraint) + 1);
1604// buf_resize(&constraint_buf, 0);1623 }
1605//1624 if (total_index + 1 < total_constraint_count) {
1606// assert(asm_expr->return_count == 0 || asm_expr->return_count == 1);1625 buf_append_char(&constraint_buf, ',');
1607//1626 }
1608// size_t total_constraint_count = asm_expr->output_list.length +1627
1609// asm_expr->input_list.length +1628 if (!is_return) {
1610// asm_expr->clobber_list.length;1629 VariableTableEntry *variable = asm_output->variable;
1611// size_t input_and_output_count = asm_expr->output_list.length +1630 assert(variable);
1612// asm_expr->input_list.length -1631 param_types[param_index] = LLVMTypeOf(variable->value_ref);
1613// asm_expr->return_count;1632 param_values[param_index] = variable->value_ref;
1614// size_t total_index = 0;1633 param_index += 1;
1615// size_t param_index = 0;1634 }
1616// LLVMTypeRef *param_types = allocate<LLVMTypeRef>(input_and_output_count);1635 }
1617// LLVMValueRef *param_values = allocate<LLVMValueRef>(input_and_output_count);1636 for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {
1618// for (size_t i = 0; i < asm_expr->output_list.length; i += 1, total_index += 1) {1637 AsmInput *asm_input = asm_expr->input_list.at(i);
1619// AsmOutput *asm_output = asm_expr->output_list.at(i);1638 IrInstruction *ir_input = instruction->input_list[i];
1620// bool is_return = (asm_output->return_type != nullptr);1639 buf_append_buf(&constraint_buf, asm_input->constraint);
1621// assert(*buf_ptr(asm_output->constraint) == '=');1640 if (total_index + 1 < total_constraint_count) {
1622// if (is_return) {1641 buf_append_char(&constraint_buf, ',');
1623// buf_appendf(&constraint_buf, "=%s", buf_ptr(asm_output->constraint) + 1);1642 }
1624// } else {1643
1625// buf_appendf(&constraint_buf, "=*%s", buf_ptr(asm_output->constraint) + 1);1644 param_types[param_index] = ir_input->type_entry->type_ref;
1626// }1645 param_values[param_index] = ir_llvm_value(g, ir_input);
1627// if (total_index + 1 < total_constraint_count) {1646 }
1628// buf_append_char(&constraint_buf, ',');1647 for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {
1629// }1648 Buf *clobber_buf = asm_expr->clobber_list.at(i);
1630//1649 buf_appendf(&constraint_buf, "~{%s}", buf_ptr(clobber_buf));
1631// if (!is_return) {1650 if (total_index + 1 < total_constraint_count) {
1632// VariableTableEntry *variable = asm_output->variable;1651 buf_append_char(&constraint_buf, ',');
1633// assert(variable);1652 }
1634// param_types[param_index] = LLVMTypeOf(variable->value_ref);1653 }
1635// param_values[param_index] = variable->value_ref;1654
1636// param_index += 1;1655 LLVMTypeRef ret_type;
1637// }1656 if (instruction->return_count == 0) {
1638// }1657 ret_type = LLVMVoidType();
1639// for (size_t i = 0; i < asm_expr->input_list.length; i += 1, total_index += 1, param_index += 1) {1658 } else {
1640// AsmInput *asm_input = asm_expr->input_list.at(i);1659 ret_type = instruction->base.type_entry->type_ref;
1641// buf_append_buf(&constraint_buf, asm_input->constraint);1660 }
1642// if (total_index + 1 < total_constraint_count) {1661 LLVMTypeRef function_type = LLVMFunctionType(ret_type, param_types, input_and_output_count, false);
1643// buf_append_char(&constraint_buf, ',');1662
1644// }1663 bool is_volatile = asm_expr->is_volatile || (asm_expr->output_list.length == 0);
1645//1664 LLVMValueRef asm_fn = LLVMConstInlineAsm(function_type, buf_ptr(&llvm_template),
1646// TypeTableEntry *expr_type = get_expr_type(asm_input->expr);1665 buf_ptr(&constraint_buf), is_volatile, false);
1647// param_types[param_index] = expr_type->type_ref;1666
1648// param_values[param_index] = gen_expr(g, asm_input->expr);1667 set_debug_source_node(g, asm_node);
1649// }1668 return LLVMBuildCall(g->builder, asm_fn, param_values, input_and_output_count, "");
1650// for (size_t i = 0; i < asm_expr->clobber_list.length; i += 1, total_index += 1) {1669}
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//
16741670
16751671
16761672
...@@ -3307,7 +3303,7 @@ void codegen_generate_h_file(CodeGen *g) {...@@ -3307,7 +3303,7 @@ void codegen_generate_h_file(CodeGen *g) {
3307 continue;3303 continue;
33083304
3309 Buf return_type_c = BUF_INIT;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);
33113307
3312 buf_appendf(&h_buf, "%s %s %s(",3308 buf_appendf(&h_buf, "%s %s %s(",
3313 buf_ptr(export_macro),3309 buf_ptr(export_macro),
src/ir.cpp+13-3
...@@ -4095,18 +4095,28 @@ static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionA...@@ -4095,18 +4095,28 @@ static TypeTableEntry *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionA
40954095
4096 AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr;4096 AstNodeAsmExpr *asm_expr = &asm_instruction->base.source_node->data.asm_expr;
40974097
4098 IrInstruction **input_list = allocate<IrInstruction *>(asm_expr->input_list.length);
4099 IrInstruction **output_types = allocate<IrInstruction *>(asm_expr->output_list.length);
4100
4098 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;4101 TypeTableEntry *return_type = ira->codegen->builtin_types.entry_void;
4099 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {4102 for (size_t i = 0; i < asm_expr->output_list.length; i += 1) {
4100 AsmOutput *asm_output = asm_expr->output_list.at(i);4103 AsmOutput *asm_output = asm_expr->output_list.at(i);
4101 if (asm_output->return_type) {4104 if (asm_output->return_type) {
4102 return_type = ir_resolve_type(ira, asm_instruction->output_types[i]);4105 output_types[i] = asm_instruction->output_types[i]->other;
4106 return_type = ir_resolve_type(ira, output_types[i]);
4103 if (return_type->id == TypeTableEntryIdInvalid)4107 if (return_type->id == TypeTableEntryIdInvalid)
4104 return ira->codegen->builtin_types.entry_invalid;4108 return ira->codegen->builtin_types.entry_invalid;
4105 }4109 }
4106 }4110 }
41074111
4108 ir_build_asm_from(&ira->new_irb, &asm_instruction->base, asm_instruction->input_list,4112 for (size_t i = 0; i < asm_expr->input_list.length; i += 1) {
4109 asm_instruction->output_types, asm_instruction->return_count, asm_instruction->has_side_effects);4113 input_list[i] = asm_instruction->input_list[i]->other;
4114 if (input_list[i]->type_entry->id == TypeTableEntryIdInvalid)
4115 return ira->codegen->builtin_types.entry_invalid;
4116 }
4117
4118 ir_build_asm_from(&ira->new_irb, &asm_instruction->base, input_list, output_types,
4119 asm_instruction->return_count, asm_instruction->has_side_effects);
4110 return return_type;4120 return return_type;
4111}4121}
41124122