Commit 6f50457b61

Josh Wolfe <thejoshwolfe@gmail.com>
2017-09-12 04:58:14
wip c to zig stuff
1 parent 373785a
Changed files (1)
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;