Commit 6f50457b61
Changed files (1)
src
src/parsec.cpp
@@ -126,6 +126,13 @@ static AstNode *trans_create_node_opaque(Context *c) {
return trans_create_node_builtin_fn_call_str(c, "OpaqueType");
}
+static AstNode *trans_create_node_fn_call_1(Context *c, AstNode *fn_ref_expr, AstNode *arg1) {
+ AstNode *node = trans_create_node(c, NodeTypeFnCallExpr);
+ node->data.fn_call_expr.fn_ref_expr = fn_ref_expr;
+ node->data.fn_call_expr.params.append(arg1);
+ return node;
+}
+
static AstNode *trans_create_node_field_access(Context *c, AstNode *container, Buf *field_name) {
AstNode *node = trans_create_node(c, NodeTypeFieldAccessExpr);
node->data.field_access_expr.struct_expr = container;
@@ -133,6 +140,10 @@ static AstNode *trans_create_node_field_access(Context *c, AstNode *container, B
return node;
}
+static AstNode *trans_create_node_field_access_str(Context *c, AstNode *container, const char *field_name) {
+ return trans_create_node_field_access(c, container, buf_create_from_str(field_name));
+}
+
static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *child_node) {
AstNode *node = trans_create_node(c, NodeTypePrefixOpExpr);
node->data.prefix_op_expr.prefix_op = op;
@@ -140,6 +151,14 @@ static AstNode *trans_create_node_prefix_op(Context *c, PrefixOp op, AstNode *ch
return node;
}
+static AstNode *trans_create_node_bin_op(Context *c, AstNode *lhs_node, BinOpType op, AstNode *rhs_node) {
+ AstNode *node = trans_create_node(c, NodeTypeBinOpExpr);
+ node->data.bin_op_expr.op1 = lhs_node;
+ node->data.bin_op_expr.bin_op = op;
+ node->data.bin_op_expr.op2 = rhs_node;
+ return node;
+}
+
static AstNode *trans_create_node_addr_of(Context *c, bool is_const, bool is_volatile, AstNode *child_node) {
AstNode *node = trans_create_node(c, NodeTypeAddrOfExpr);
node->data.addr_of_expr.is_const = is_const;
@@ -155,6 +174,13 @@ static AstNode *trans_create_node_str_lit_c(Context *c, Buf *buf) {
return node;
}
+static AstNode *trans_create_node_str_lit_non_c(Context *c, Buf *buf) {
+ AstNode *node = trans_create_node(c, NodeTypeStringLiteral);
+ node->data.string_literal.buf = buf;
+ node->data.string_literal.c = false;
+ return node;
+}
+
static AstNode *trans_create_node_unsigned_negative(Context *c, uint64_t x, bool is_negative) {
AstNode *node = trans_create_node(c, NodeTypeIntLiteral);
node->data.int_literal.bigint = allocate<BigInt>(1);
@@ -286,10 +312,45 @@ static AstNode *trans_create_node_apint(Context *c, const llvm::APSInt &aps_int)
}
+static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
+
static bool is_c_void_type(AstNode *node) {
return (node->type == NodeTypeSymbol && buf_eql_str(node->data.symbol_expr.symbol, "c_void"));
}
+static AstNode* trans_c_cast(Context *c, const SourceLocation &source_location, const QualType &qt, AstNode *expr) {
+ // TODO: maybe widen to increase size
+ // TODO: maybe bitcast to change sign
+ // TODO: maybe truncate to reduce size
+ return trans_create_node_fn_call_1(c, trans_qual_type(c, qt, source_location), expr);
+}
+
+static AstNode *qual_type_to_log2_int_ref(Context *c, const QualType &qt,
+ const SourceLocation &source_loc)
+{
+ AstNode *zig_type_node = trans_qual_type(c, qt, source_loc);
+
+// @import("std").math.Log2Int(c_long);
+//
+// FnCall
+// FieldAccess
+// FieldAccess
+// FnCall (.builtin = true)
+// Symbol "import"
+// StringLiteral "std"
+// Symbol "math"
+// Symbol "Log2Int"
+// zig_type_node
+
+ AstNode *import_fn_call = trans_create_node_builtin_fn_call_str(c, "import");
+ import_fn_call->data.fn_call_expr.params.append(trans_create_node_str_lit_non_c(c, buf_create_from_str("std")));
+ AstNode *inner_field_access = trans_create_node_field_access_str(c, import_fn_call, "math");
+ AstNode *outer_field_access = trans_create_node_field_access_str(c, inner_field_access, "Log2Int");
+ AstNode *log2int_fn_call = trans_create_node_fn_call_1(c, outer_field_access, zig_type_node);
+
+ return log2int_fn_call;
+}
+
static bool qual_type_child_is_fn_proto(const QualType &qt) {
if (qt.getTypePtr()->getTypeClass() == Type::Paren) {
const ParenType *paren_type = static_cast<const ParenType *>(qt.getTypePtr());
@@ -361,7 +422,6 @@ static bool c_is_float(Context *c, QualType qt) {
}
static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt);
-static AstNode *trans_qual_type(Context *c, QualType qt, const SourceLocation &source_loc);
static AstNode *const skip_add_to_block_node = (AstNode *) 0x2;
static AstNode *trans_expr(Context *c, AstNode *block, Expr *expr) {
@@ -877,25 +937,127 @@ static AstNode *trans_binary_operator(Context *c, AstNode *block, BinaryOperator
zig_unreachable();
}
+static AstNode *trans_compound_assign_operator(Context *c, AstNode *block, CompoundAssignOperator *stmt) {
+ switch (stmt->getOpcode()) {
+ case BO_MulAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_MulAssign");
+ return nullptr;
+ case BO_DivAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_DivAssign");
+ return nullptr;
+ case BO_RemAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_RemAssign");
+ return nullptr;
+ case BO_AddAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AddAssign");
+ return nullptr;
+ case BO_SubAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_SubAssign");
+ return nullptr;
+ case BO_ShlAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_ShlAssign");
+ return nullptr;
+ case BO_ShrAssign: {
+ BinOpType bin_op = BinOpTypeBitShiftRight;
+ // c: lhs >>= rhs;
+ // zig: {
+ // zig: const _ref = &lhs;
+ // zig: *_ref = result_type(operation_type(*_ref) >> u5(rhs));
+ // zig: *_ref
+ // zig: };
+ // where u5 is the appropriate type
+
+ // TODO: avoid mess when we don't need the assignment value for chained assignments or anything.
+ AstNode *child_block = trans_create_node(c, NodeTypeBlock);
+
+ // const _ref = &lhs;
+ AstNode *lhs = trans_expr(c, child_block, stmt->getLHS());
+ if (lhs == nullptr) return nullptr;
+ AstNode *addr_of_lhs = trans_create_node_addr_of(c, false, false, lhs);
+ // TODO: avoid name collisions with generated variable names
+ Buf* tmp_var_name = buf_create_from_str("_ref");
+ AstNode *tmp_var_decl = trans_create_node_var_decl(c, true, tmp_var_name, nullptr, addr_of_lhs);
+ child_block->data.block.statements.append(tmp_var_decl);
+
+ // *_ref = result_type(operation_type(*_ref) >> u5(rhs));
+
+ AstNode *rhs = trans_expr(c, child_block, stmt->getRHS());
+ if (rhs == nullptr) return nullptr;
+ const SourceLocation &rhs_location = stmt->getRHS()->getLocStart();
+ AstNode *rhs_type = qual_type_to_log2_int_ref(c, stmt->getComputationLHSType(), rhs_location);
+
+ AstNode *assign_statement = trans_create_node_bin_op(c,
+ trans_create_node_prefix_op(c, PrefixOpDereference,
+ trans_create_node_symbol(c, tmp_var_name)),
+ BinOpTypeAssign,
+ trans_c_cast(c, rhs_location,
+ stmt->getComputationResultType(),
+ trans_create_node_bin_op(c,
+ trans_c_cast(c, rhs_location,
+ stmt->getComputationLHSType(),
+ trans_create_node_prefix_op(c, PrefixOpDereference,
+ trans_create_node_symbol(c, tmp_var_name))),
+ bin_op,
+ trans_create_node_fn_call_1(c,
+ rhs_type,
+ rhs))));
+ child_block->data.block.statements.append(assign_statement);
+
+ // *_ref
+ child_block->data.block.statements.append(
+ trans_create_node_prefix_op(c, PrefixOpDereference,
+ trans_create_node_symbol(c, tmp_var_name)));
+ child_block->data.block.last_statement_is_result_expression = true;
+
+ return child_block;
+ }
+ case BO_AndAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_AndAssign");
+ return nullptr;
+ case BO_XorAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_XorAssign");
+ return nullptr;
+ case BO_OrAssign:
+ emit_warning(c, stmt->getLocStart(), "TODO handle more C compound assign operators: BO_OrAssign");
+ return nullptr;
+ case BO_PtrMemD:
+ case BO_PtrMemI:
+ case BO_Assign:
+ case BO_Mul:
+ case BO_Div:
+ case BO_Rem:
+ case BO_Add:
+ case BO_Sub:
+ case BO_Shl:
+ case BO_Shr:
+ case BO_LT:
+ case BO_GT:
+ case BO_LE:
+ case BO_GE:
+ case BO_EQ:
+ case BO_NE:
+ case BO_And:
+ case BO_Xor:
+ case BO_Or:
+ case BO_LAnd:
+ case BO_LOr:
+ case BO_Comma:
+ zig_panic("compound assign expected to be handled by binary operator");
+ }
+
+ zig_unreachable();
+}
+
static AstNode *trans_implicit_cast_expr(Context *c, AstNode *block, ImplicitCastExpr *stmt) {
switch (stmt->getCastKind()) {
case CK_LValueToRValue:
return trans_expr(c, block, stmt->getSubExpr());
case CK_IntegralCast:
{
- AstNode *node = trans_create_node_builtin_fn_call_str(c, "bitCast");
-
- AstNode *result_type_node = trans_qual_type(c, stmt->getType(), stmt->getExprLoc());
- if (result_type_node == nullptr)
- return nullptr;
-
AstNode *target_node = trans_expr(c, block, stmt->getSubExpr());
if (target_node == nullptr)
return nullptr;
-
- node->data.fn_call_expr.params.append(result_type_node);
- node->data.fn_call_expr.params.append(target_node);
- return node;
+ return trans_c_cast(c, stmt->getExprLoc(), stmt->getType(), target_node);
}
case CK_Dependent:
emit_warning(c, stmt->getLocStart(), "TODO handle C translation cast CK_Dependent");
@@ -1422,6 +1584,8 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
return trans_conditional_operator(c, block, (ConditionalOperator *)stmt);
case Stmt::BinaryOperatorClass:
return trans_binary_operator(c, block, (BinaryOperator *)stmt);
+ case Stmt::CompoundAssignOperatorClass:
+ return trans_compound_assign_operator(c, block, (CompoundAssignOperator *)stmt);
case Stmt::ImplicitCastExprClass:
return trans_implicit_cast_expr(c, block, (ImplicitCastExpr *)stmt);
case Stmt::DeclRefExprClass:
@@ -1504,9 +1668,6 @@ static AstNode *trans_stmt(Context *c, AstNode *block, Stmt *stmt) {
case Stmt::AtomicExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C AtomicExprClass");
return nullptr;
- case Stmt::CompoundAssignOperatorClass:
- emit_warning(c, stmt->getLocStart(), "TODO handle C CompoundAssignOperatorClass");
- return nullptr;
case Stmt::BlockExprClass:
emit_warning(c, stmt->getLocStart(), "TODO handle C BlockExprClass");
return nullptr;