Commit 7066283004

Andrew Kelley <superjoe30@gmail.com>
2017-11-29 05:44:45
translate-c: support const ptr initializer
1 parent 26096e7
Changed files (2)
src/translate_c.cpp
@@ -28,36 +28,6 @@ struct Alias {
     Buf *canon_name;
 };
 
-struct Context {
-    ImportTableEntry *import;
-    ZigList<ErrorMsg *> *errors;
-    VisibMod visib_mod;
-    VisibMod export_visib_mod;
-    AstNode *root;
-    HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
-    HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
-    HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
-    SourceManager *source_manager;
-    ZigList<Alias> aliases;
-    AstNode *source_node;
-    bool warnings_on;
-
-    CodeGen *codegen;
-    ASTContext *ctx;
-
-    HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
-};
-
-enum ResultUsed {
-    ResultUsedNo,
-    ResultUsedYes,
-};
-
-enum TransLRValue {
-    TransLValue,
-    TransRValue,
-};
-
 enum TransScopeId {
     TransScopeIdSwitch,
     TransScopeIdVar,
@@ -99,6 +69,37 @@ struct TransScopeWhile {
     AstNode *node;
 };
 
+struct Context {
+    ImportTableEntry *import;
+    ZigList<ErrorMsg *> *errors;
+    VisibMod visib_mod;
+    VisibMod export_visib_mod;
+    AstNode *root;
+    HashMap<const void *, AstNode *, ptr_hash, ptr_eq> decl_table;
+    HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> macro_table;
+    HashMap<Buf *, AstNode *, buf_hash, buf_eql_buf> global_table;
+    SourceManager *source_manager;
+    ZigList<Alias> aliases;
+    AstNode *source_node;
+    bool warnings_on;
+
+    CodeGen *codegen;
+    ASTContext *ctx;
+
+    TransScopeRoot *global_scope;
+    HashMap<Buf *, bool, buf_hash, buf_eql_buf> ptr_params;
+};
+
+enum ResultUsed {
+    ResultUsedNo,
+    ResultUsedYes,
+};
+
+enum TransLRValue {
+    TransLValue,
+    TransRValue,
+};
+
 static TransScopeRoot *trans_scope_root_create(Context *c);
 static TransScopeWhile *trans_scope_while_create(Context *c, TransScope *parent_scope);
 static TransScopeBlock *trans_scope_block_create(Context *c, TransScope *parent_scope);
@@ -3233,8 +3234,7 @@ static void visit_fn_decl(Context *c, const FunctionDecl *fn_decl) {
         return;
     }
 
-    TransScopeRoot *root_scope = trans_scope_root_create(c);
-    TransScope *scope = &root_scope->base;
+    TransScope *scope = &c->global_scope->base;
 
     for (size_t i = 0; i < proto_node->data.fn_proto.params.length; i += 1) {
         AstNode *param_node = proto_node->data.fn_proto.params.at(i);
@@ -3600,6 +3600,93 @@ static AstNode *resolve_record_decl(Context *c, const RecordDecl *record_decl) {
     }
 }
 
+static AstNode *trans_ap_value(Context *c, APValue *ap_value, QualType qt, const SourceLocation &source_loc) {
+    switch (ap_value->getKind()) {
+        case APValue::Int:
+            return trans_create_node_apint(c, ap_value->getInt());
+        case APValue::Uninitialized:
+            return trans_create_node(c, NodeTypeUndefinedLiteral);
+        case APValue::Array: {
+            emit_warning(c, source_loc, "TODO add a test case for this code");
+
+            unsigned init_count = ap_value->getArrayInitializedElts();
+            unsigned all_count = ap_value->getArraySize();
+            unsigned leftover_count = all_count - init_count;
+            AstNode *init_node = trans_create_node(c, NodeTypeContainerInitExpr);
+            AstNode *arr_type_node = trans_qual_type(c, qt, source_loc);
+            init_node->data.container_init_expr.type = arr_type_node;
+            init_node->data.container_init_expr.kind = ContainerInitKindArray;
+
+            QualType child_qt = qt.getTypePtr()->getLocallyUnqualifiedSingleStepDesugaredType();
+
+            for (size_t i = 0; i < init_count; i += 1) {
+                APValue &elem_ap_val = ap_value->getArrayInitializedElt(i);
+                AstNode *elem_node = trans_ap_value(c, &elem_ap_val, child_qt, source_loc);
+                if (elem_node == nullptr)
+                    return nullptr;
+                init_node->data.container_init_expr.entries.append(elem_node);
+            }
+            if (leftover_count == 0) {
+                return init_node;
+            }
+
+            APValue &filler_ap_val = ap_value->getArrayFiller();
+            AstNode *filler_node = trans_ap_value(c, &filler_ap_val, child_qt, source_loc);
+            if (filler_node == nullptr)
+                return nullptr;
+
+            AstNode *filler_arr_1 = trans_create_node(c, NodeTypeContainerInitExpr);
+            init_node->data.container_init_expr.type = arr_type_node;
+            init_node->data.container_init_expr.kind = ContainerInitKindArray;
+            init_node->data.container_init_expr.entries.append(filler_node);
+
+            AstNode *rhs_node;
+            if (leftover_count == 1) {
+                rhs_node = filler_arr_1;
+            } else {
+                AstNode *amt_node = trans_create_node_unsigned(c, leftover_count);
+                rhs_node = trans_create_node_bin_op(c, filler_arr_1, BinOpTypeArrayMult, amt_node);
+            }
+
+            return trans_create_node_bin_op(c, init_node, BinOpTypeArrayCat, rhs_node);
+        }
+        case APValue::LValue: {
+            const APValue::LValueBase lval_base = ap_value->getLValueBase();
+            if (const Expr *expr = lval_base.dyn_cast<const Expr *>()) {
+                return trans_expr(c, ResultUsedYes, &c->global_scope->base, expr, TransRValue);
+            }
+            //const ValueDecl *value_decl = lval_base.get<const ValueDecl *>();
+            emit_warning(c, source_loc, "TODO handle initializer LValue ValueDecl");
+            return nullptr;
+        }
+        case APValue::Float:
+            emit_warning(c, source_loc, "unsupported initializer value kind: Float");
+            return nullptr;
+        case APValue::ComplexInt:
+            emit_warning(c, source_loc, "unsupported initializer value kind: ComplexInt");
+            return nullptr;
+        case APValue::ComplexFloat:
+            emit_warning(c, source_loc, "unsupported initializer value kind: ComplexFloat");
+            return nullptr;
+        case APValue::Vector:
+            emit_warning(c, source_loc, "unsupported initializer value kind: Vector");
+            return nullptr;
+        case APValue::Struct:
+            emit_warning(c, source_loc, "unsupported initializer value kind: Struct");
+            return nullptr;
+        case APValue::Union:
+            emit_warning(c, source_loc, "unsupported initializer value kind: Union");
+            return nullptr;
+        case APValue::MemberPointer:
+            emit_warning(c, source_loc, "unsupported initializer value kind: MemberPointer");
+            return nullptr;
+        case APValue::AddrLabelDiff:
+            emit_warning(c, source_loc, "unsupported initializer value kind: AddrLabelDiff");
+            return nullptr;
+    }
+    zig_unreachable();
+}
+
 static void visit_var_decl(Context *c, const VarDecl *var_decl) {
     Buf *name = buf_create_from_str(decl_name(var_decl));
 
@@ -3636,27 +3723,9 @@ static void visit_var_decl(Context *c, const VarDecl *var_decl) {
                         "ignoring variable '%s' - unable to evaluate initializer", buf_ptr(name));
                 return;
             }
-            switch (ap_value->getKind()) {
-                case APValue::Int:
-                    init_node = trans_create_node_apint(c, ap_value->getInt());
-                    break;
-                case APValue::Uninitialized:
-                    init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
-                    break;
-                case APValue::Float:
-                case APValue::ComplexInt:
-                case APValue::ComplexFloat:
-                case APValue::LValue:
-                case APValue::Vector:
-                case APValue::Array:
-                case APValue::Struct:
-                case APValue::Union:
-                case APValue::MemberPointer:
-                case APValue::AddrLabelDiff:
-                    emit_warning(c, var_decl->getLocation(),
-                            "ignoring variable '%s' - unrecognized initializer value kind", buf_ptr(name));
-                    return;
-            }
+            init_node = trans_ap_value(c, ap_value, qt, var_decl->getLocation());
+            if (init_node == nullptr)
+                return;
         } else {
             init_node = trans_create_node(c, NodeTypeUndefinedLiteral);
         }
@@ -4101,6 +4170,7 @@ int parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const ch
     c->ptr_params.init(8);
     c->codegen = codegen;
     c->source_node = source_node;
+    c->global_scope = trans_scope_root_create(c);
 
     ZigList<const char *> clang_argv = {0};
 
test/translate_c.zig
@@ -1172,4 +1172,10 @@ pub fn addCases(cases: &tests.TranslateCContext) {
         \\    return u32_0;
         \\}
     );
+
+    cases.add("const ptr initializer",
+        \\static const char *v0 = "0.0.0";
+    ,
+        \\pub var v0: ?&const u8 = c"0.0.0";
+    );
 }