authorgravatar for codroid@gmail.comhryx <codroid@gmail.com> 2019-05-27 23:55:48-07:00
committergravatar for codroid@gmail.comhryx <codroid@gmail.com> 2019-05-27 23:55:48-07:00
loge632c2ade3d9ea2cfaa201b20f523d315d9c47fd
tree5c4b01964ba063e61f60b5a877185cfc1092c7c6
parentb558d0996a8a18475f91483d3e3962502422a315
signature Commit is signed but in an unrecognized format.

(broken) port a bunch of stuff from stage1 translate-c


2 files changed, 212 insertions(+), 7 deletions(-)

src-self-hosted/clang.zig+1
......@@ -486,6 +486,7 @@ pub extern fn ZigClangQualType_isConstQualified(arg0: struct_ZigClangQualType) b
486486pub extern fn ZigClangQualType_isVolatileQualified(arg0: struct_ZigClangQualType) bool;
487487pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType) bool;
488488pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) ZigClangTypeClass;
489pub extern fn ZigClangType_getPointeeType(self: ?*const struct_ZigClangType) struct_ZigClangQualType;
489490pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
490491pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
491492pub extern fn ZigClangStmt_getBeginLoc(self: *const struct_ZigClangStmt) struct_ZigClangSourceLocation;
src-self-hosted/translate_c.zig+211-7
......@@ -20,7 +20,7 @@ pub const ClangErrMsg = Stage2ErrorMsg;
2020
2121pub const Error = error{OutOfMemory};
2222const TypeError = Error || error{UnsupportedType};
23const TransError = Error || error{UnsupportedTranslation};
23const TransError = TypeError || error{UnsupportedTranslation};
2424
2525const DeclTable = std.HashMap(usize, void, addrHash, addrEql);
2626
......@@ -199,7 +199,7 @@ pub fn translate(
199199 return context.err;
200200 }
201201
202 _ = try appendToken(&context, .Eof, "");
202 tree.root_node.eof_token = try appendToken(&context, .Eof, "");
203203 tree.source = source_buffer.toOwnedSlice();
204204 if (false) {
205205 std.debug.warn("debug source:\n{}\n==EOF==\ntokens:\n", tree.source);
......@@ -299,7 +299,9 @@ fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
299299 const body_stmt = ZigClangFunctionDecl_getBody(fn_decl);
300300 const result = transStmt(rp, scope, body_stmt, .unused, .r_value) catch |err| switch (err) {
301301 error.OutOfMemory => |e| return e,
302 error.UnsupportedTranslation => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
302 error.UnsupportedTranslation,
303 error.UnsupportedType,
304 => return failDecl(c, fn_decl_loc, fn_name, "unable to translate function"),
303305 };
304306 assert(result.node.id == ast.Node.Id.Block);
305307 proto_node.body_node = result.node;
......@@ -484,7 +486,11 @@ fn transImplicitCastExpr(
484486 const node = try transExpr(rp, scope, @ptrCast(*const ZigClangExpr, sub_expr), .used, .r_value);
485487 const dest_type = getExprQualType(c, @ptrCast(*const ZigClangExpr, expr));
486488 const src_type = getExprQualType(c, sub_expr);
487 return try transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, node.node);
489 return TransResult{
490 .node = try transCCast(rp, scope, ZigClangImplicitCastExpr_getBeginLoc(expr), dest_type, src_type, node.node),
491 .node_scope = scope,
492 .child_scope = scope,
493 };
488494 },
489495 .FunctionToPointerDecay, .ArrayToPointerDecay => {
490496 return maybeSuppressResult(
......@@ -510,9 +516,27 @@ fn transCCast(
510516 loc: ZigClangSourceLocation,
511517 dst_type: ZigClangQualType,
512518 src_type: ZigClangQualType,
513 target_node: *ast.Node,
514) !TransResult {
515 return revertAndWarn(rp, error.UnsupportedTranslation, loc, "TODO implement translation of C cast");
519 expr: *ast.Node,
520) !*ast.Node {
521 if (ZigClangType_isVoidType(qualTypeCanon(dst_type))) return expr;
522 if (ZigClangQualType_eq(dst_type, src_type)) return expr;
523 if (qualTypeIsPtr(dst_type) and qualTypeIsPtr(src_type))
524 return transCPtrCast(rp, loc, dst_type, src_type, expr);
525 if (cIsUnsignedInteger(dst_type) and qualTypeIsPtr(src_type)) {
526 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "ptrToInt");
527 try builtin_node.params.push(expr);
528 return &(try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc), &builtin_node.base)).base;
529 }
530 if (cIsUnsignedInteger(src_type) and qualTypeIsPtr(dst_type)) {
531 const builtin_node = try transCreateNodeBuiltinFnCall(rp.c, "intToPtr");
532 try builtin_node.params.push(try transQualType(rp, dst_type, loc));
533 try builtin_node.params.push(expr);
534 return &builtin_node.base;
535 }
536 // TODO: maybe widen to increase size
537 // TODO: maybe bitcast to change sign
538 // TODO: maybe truncate to reduce size
539 return &(try transCreateNodeFnCall(rp.c, try transQualType(rp, dst_type, loc), expr)).base;
516540}
517541
518542fn transExpr(
......@@ -542,6 +566,38 @@ fn transLookupZigIdentifier(inner: *Scope, c_name: []const u8) []const u8 {
542566 }
543567}
544568
569fn transCPtrCast(
570 rp: RestorePoint,
571 loc: ZigClangSourceLocation,
572 dst_type: ZigClangQualType,
573 src_type: ZigClangQualType,
574 expr: *ast.Node,
575) !*ast.Node {
576 const ty = ZigClangQualType_getTypePtr(dst_type);
577 const child_type = ZigClangType_getPointeeType(ty);
578 const dst_type_node = try transType(rp, ty, loc);
579 const child_type_node = try transQualType(rp, child_type, loc);
580
581 // Implicit downcasting from higher to lower alignment values is forbidden,
582 // use @alignCast to side-step this problem
583 const ptrcast_node = try transCreateNodeBuiltinFnCall(rp.c, "ptrCast");
584 try ptrcast_node.params.push(dst_type_node);
585
586 if (ZigClangType_isVoidType(qualTypeCanon(child_type))) {
587 // void has 1-byte alignment, so @alignCast is not needed
588 try ptrcast_node.params.push(expr);
589 } else {
590 const alignof_node = try transCreateNodeBuiltinFnCall(rp.c, "alignOf");
591 try alignof_node.params.push(child_type_node);
592 const aligncast_node = try transCreateNodeBuiltinFnCall(rp.c, "alignCast");
593 try aligncast_node.params.push(&alignof_node.base);
594 try aligncast_node.params.push(expr);
595 try ptrcast_node.params.push(&aligncast_node.base);
596 }
597
598 return &ptrcast_node.base;
599}
600
545601fn maybeSuppressResult(
546602 rp: RestorePoint,
547603 scope: *Scope,
......@@ -574,6 +630,24 @@ fn transQualType(rp: RestorePoint, qt: ZigClangQualType, source_loc: ZigClangSou
574630 return transType(rp, ZigClangQualType_getTypePtr(qt), source_loc);
575631}
576632
633fn qualTypeIsPtr(qt: ZigClangQualType) bool {
634 return ZigClangType_getTypeClass(qualTypeCanon(qt)) == .Pointer;
635}
636
637fn qualTypeChildIsFnProto(qt: ZigClangQualType) bool {
638 const ty = ZigClangQualType_getTypePtr(qt);
639 if (ZigClangType_getTypeClass(ty) == .Paren) {
640 const paren_type = @ptrCast(*const ZigClangParenType, ty);
641 const inner_type = ZigClangParenType_getInnerType(ty);
642 return ZigClangQualType_getTypeClass(inner_type) == .FunctionProto;
643 }
644 if (ZigClangType_getTypeClass(ty) == .Attributed) {
645 const attr_type = @ptrCast(*const ZigClangAttributedType, ty);
646 return qualTypeChildIsFnProto(bitcast(ZigClangAttributedType_getEquivalentType(attr_type)));
647 }
648 return false;
649}
650
577651fn qualTypeCanon(qt: ZigClangQualType) *const ZigClangType {
578652 const canon = ZigClangQualType_getCanonicalType(qt);
579653 return ZigClangQualType_getTypePtr(canon);
......@@ -596,6 +670,113 @@ fn getExprQualType(c: *Context, expr: *const ZigClangExpr) ZigClangQualType {
596670 return ZigClangExpr_getType(expr);
597671}
598672
673fn typeIsOpaque(c: *Context, ty: *const ZigClangType, loc: ZigClangSourceLocation) bool {
674 switch (ZigClangType_getTypeClass(ty)) {
675 .Builtin => {
676 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, ty);
677 return ZigClangBuiltinType_getKind(builtin_ty) == .Void;
678 },
679 .Record => {
680 const record_ty = @ptrCast(*const ZigClangRecordType, ty);
681 const record_decl = ZigClangRecordType_getDecl(record_ty);
682 return (ZigClangRecordDecl_getDefinition(record_decl) == null);
683 },
684 .Elaborated => {
685 const elaborated_ty = @ptrCast(*const ZigClangElaboratedType, ty);
686 const qt = ZigClangElaboratedType_getNamedType(elaborated_ty);
687 return typeIsOpaque(c, ZigClangQualType_getTypePtr(qt), loc);
688 },
689 .Typedef => {
690 const typedef_ty = @ptrCast(*const ZigClangTypedefType, ty);
691 const typedef_decl = ZigClangTypedefType_getDecl(typedef_ty);
692 const underlying_type = ZigClangTypedefNameDecl_getUnderlyingType(typedef_decl);
693 return typeIsOpaque(c, ZigClangQualType_getTypePtr(underlying_type), loc);
694 },
695 else => return false,
696 }
697}
698
699fn cIsUnsignedInteger(qt: ZigClangQualType) bool {
700 const c_type = qualTypeCanon(qt);
701 if (ZigClangType_getTypeClass(c_type) != .Builtin) return false;
702 const builtin_ty = @ptrCast(*const ZigClangBuiltinType, c_type);
703 return switch (ZigClangBuiltinType_getKind(builtin_ty)) {
704 .Char_U,
705 .UChar,
706 .Char_S,
707 .UShort,
708 .UInt,
709 .ULong,
710 .ULongLong,
711 .UInt128,
712 .WChar_U,
713 => true,
714 else => false,
715 };
716}
717
718fn transCreateNodeBuiltinFnCall(c: *Context, name: []const u8) !*ast.Node.BuiltinCall {
719 const node = try c.a().create(ast.Node.BuiltinCall);
720 node.* = ast.Node.BuiltinCall{
721 .base = ast.Node{ .id = .BuiltinCall },
722 .builtin_token = try appendToken(c, .Builtin, name),
723 .params = ast.Node.BuiltinCall.ParamList.init(c.a()),
724 .rparen_token = undefined, // TODO TokenIndex,
725 };
726 return node;
727}
728
729fn transCreateNodeFnCall(c: *Context, fn_expr: *ast.Node, first_arg: *ast.Node) !*ast.Node.SuffixOp {
730 const node = try c.a().create(ast.Node.SuffixOp);
731 node.* = ast.Node.SuffixOp{
732 .base = ast.Node{ .id = .SuffixOp },
733 .lhs = fn_expr,
734 .op = ast.Node.SuffixOp.Op{
735 .Call = ast.Node.SuffixOp.Op.Call{
736 .params = ast.Node.SuffixOp.Op.Call.ParamList.init(c.a()),
737 .async_attr = null,
738 },
739 },
740 .rtoken = undefined, // TODO TokenIndex
741 };
742 return node;
743}
744
745fn transCreateNodePrefixOp(c: *Context, op: ast.Node.PrefixOp.Op, rhs: *ast.Node) !*ast.Node {
746 const node = try c.a().create(ast.Node.PrefixOp);
747 node.* = ast.Node.PrefixOp{
748 .base = ast.Node{ .id = .PrefixOp },
749 .op_token = undefined, // TODO TokenIndex,
750 .op = op,
751 .rhs = rhs,
752 };
753 return &node.base;
754}
755
756fn transCreateNodePtrType(
757 c: *Context,
758 is_const: bool,
759 is_volatile: bool,
760 rhs: *ast.Node,
761 op_tok_id: std.zig.Token.Id,
762) !*ast.Node {
763 const node = try c.a().create(ast.Node.PrefixOp);
764 node.* = ast.Node.PrefixOp{
765 .base = ast.Node{ .id = .PrefixOp },
766 .op_token = try appendToken(c, op_tok_id, ""), // TODO TokenIndex,
767 .op = ast.Node.PrefixOp.Op{
768 .PtrType = ast.Node.PrefixOp.PtrInfo{
769 .allowzero_token = null,
770 .align_info = null,
771 .const_token = if (is_const) try appendToken(c, .Keyword_const, "const") else null,
772 .volatile_token = if (is_volatile) try appendToken(c, .Keyword_volatile, "volatile") else null,
773 },
774 },
775 .rhs = rhs,
776 };
777 return &node.base;
778}
779
599780const RestorePoint = struct {
600781 c: *Context,
601782 token_index: ast.TokenIndex,
......@@ -642,6 +823,29 @@ fn transType(rp: RestorePoint, ty: *const ZigClangType, source_loc: ZigClangSour
642823 else => return revertAndWarn(rp, error.UnsupportedType, source_loc, "unsupported builtin type"),
643824 }
644825 },
826 .Pointer => {
827 const child_qt = ZigClangType_getPointeeType(ty);
828 const child_node = try transQualType(rp, child_qt, source_loc);
829 if (qualTypeChildIsFnProto(child_qt))
830 return transCreateNodePrefixOp(rp.c, .OptionalType, child_node);
831 if (typeIsOpaque(rp.c, ZigClangQualType_getTypePtr(child_qt), source_loc)) {
832 const pointer_node = try transCreateNodePtrType(
833 rp.c,
834 ZigClangQualType_isConstQualified(child_qt),
835 ZigClangQualType_isVolatileQualified(child_qt),
836 child_node,
837 .Asterisk,
838 );
839 return transCreateNodePrefixOp(rp.c, .OptionalType, pointer_node);
840 }
841 return transCreateNodePtrType(
842 rp.c,
843 ZigClangQualType_isConstQualified(child_qt),
844 ZigClangQualType_isVolatileQualified(child_qt),
845 child_node,
846 .BracketStarCBracket,
847 );
848 },
645849 .FunctionProto => {
646850 const fn_proto_ty = @ptrCast(*const ZigClangFunctionProtoType, ty);
647851 const fn_proto = try transFnProto(rp, fn_proto_ty, source_loc, null);