Skip to content

Commit

Permalink
self-hosted translate-c progress on function decls
Browse files Browse the repository at this point in the history
See #1964
  • Loading branch information
andrewrk committed May 9, 2019
1 parent 9bbd71c commit 46e1c34
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 27 deletions.
23 changes: 18 additions & 5 deletions src-self-hosted/clang.zig
Original file line number Diff line number Diff line change
Expand Up @@ -806,13 +806,13 @@ pub const enum_ZigClangAPValueKind = extern enum {
ZigClangAPValueAddrLabelDiff,
};
pub extern fn ZigClangSourceManager_getSpellingLoc(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) struct_ZigClangSourceLocation;
pub extern fn ZigClangSourceManager_getFilename(arg0: ?*const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) [*c]const u8;
pub extern fn ZigClangSourceManager_getFilename(self: *const struct_ZigClangSourceManager, SpellingLoc: struct_ZigClangSourceLocation) ?[*]const u8;
pub extern fn ZigClangSourceManager_getSpellingLineNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
pub extern fn ZigClangSourceManager_getSpellingColumnNumber(arg0: ?*const struct_ZigClangSourceManager, Loc: struct_ZigClangSourceLocation) c_uint;
pub extern fn ZigClangSourceManager_getCharacterData(arg0: ?*const struct_ZigClangSourceManager, SL: struct_ZigClangSourceLocation) [*c]const u8;
pub extern fn ZigClangASTContext_getPointerType(arg0: ?*const struct_ZigClangASTContext, T: struct_ZigClangQualType) struct_ZigClangQualType;
pub extern fn ZigClangASTUnit_getASTContext(arg0: ?*struct_ZigClangASTUnit) ?*struct_ZigClangASTContext;
pub extern fn ZigClangASTUnit_getSourceManager(arg0: ?*struct_ZigClangASTUnit) ?*struct_ZigClangSourceManager;
pub extern fn ZigClangASTUnit_getSourceManager(self: *struct_ZigClangASTUnit) *struct_ZigClangSourceManager;
pub extern fn ZigClangASTUnit_visitLocalTopLevelDecls(self: *struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, *const struct_ZigClangDecl) bool) bool;
pub extern fn ZigClangRecordType_getDecl(record_ty: ?*const struct_ZigClangRecordType) ?*const struct_ZigClangRecordDecl;
pub extern fn ZigClangEnumType_getDecl(record_ty: ?*const struct_ZigClangEnumType) ?*const struct_ZigClangEnumDecl;
Expand All @@ -824,6 +824,7 @@ pub extern fn ZigClangEnumDecl_getDefinition(arg0: ?*const struct_ZigClangEnumDe
pub extern fn ZigClangRecordDecl_getLocation(arg0: ?*const struct_ZigClangRecordDecl) struct_ZigClangSourceLocation;
pub extern fn ZigClangEnumDecl_getLocation(arg0: ?*const struct_ZigClangEnumDecl) struct_ZigClangSourceLocation;
pub extern fn ZigClangTypedefNameDecl_getLocation(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangSourceLocation;
pub extern fn ZigClangDecl_getLocation(self: *const ZigClangDecl) ZigClangSourceLocation;
pub extern fn ZigClangRecordDecl_isUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
pub extern fn ZigClangRecordDecl_isStruct(record_decl: ?*const struct_ZigClangRecordDecl) bool;
pub extern fn ZigClangRecordDecl_isAnonymousStructOrUnion(record_decl: ?*const struct_ZigClangRecordDecl) bool;
Expand All @@ -833,15 +834,15 @@ pub extern fn ZigClangSourceLocation_eq(a: struct_ZigClangSourceLocation, b: str
pub extern fn ZigClangTypedefType_getDecl(arg0: ?*const struct_ZigClangTypedefType) ?*const struct_ZigClangTypedefNameDecl;
pub extern fn ZigClangTypedefNameDecl_getUnderlyingType(arg0: ?*const struct_ZigClangTypedefNameDecl) struct_ZigClangQualType;
pub extern fn ZigClangQualType_getCanonicalType(arg0: struct_ZigClangQualType) struct_ZigClangQualType;
pub extern fn ZigClangQualType_getTypePtr(arg0: struct_ZigClangQualType) ?*const struct_ZigClangType;
pub extern fn ZigClangQualType_getTypePtr(self: struct_ZigClangQualType) *const struct_ZigClangType;
pub extern fn ZigClangQualType_addConst(arg0: [*c]struct_ZigClangQualType) void;
pub extern fn ZigClangQualType_eq(arg0: struct_ZigClangQualType, arg1: struct_ZigClangQualType) bool;
pub extern fn ZigClangQualType_isConstQualified(arg0: struct_ZigClangQualType) bool;
pub extern fn ZigClangQualType_isVolatileQualified(arg0: struct_ZigClangQualType) bool;
pub extern fn ZigClangQualType_isRestrictQualified(arg0: struct_ZigClangQualType) bool;
pub extern fn ZigClangType_getTypeClass(self: ?*const struct_ZigClangType) enum_ZigClangTypeClass;
pub extern fn ZigClangType_isVoidType(self: ?*const struct_ZigClangType) bool;
pub extern fn ZigClangType_getTypeClassName(self: ?*const struct_ZigClangType) [*c]const u8;
pub extern fn ZigClangType_getTypeClassName(self: *const struct_ZigClangType) [*]const u8;
pub extern fn ZigClangStmt_getBeginLoc(self: ?*const struct_ZigClangStmt) struct_ZigClangSourceLocation;
pub extern fn ZigClangStmt_getStmtClass(self: ?*const struct_ZigClangStmt) enum_ZigClangStmtClass;
pub extern fn ZigClangStmt_classof_Expr(self: ?*const struct_ZigClangStmt) bool;
Expand All @@ -863,6 +864,10 @@ pub extern fn ZigClangAPSInt_getRawData(self: ?*const struct_ZigClangAPSInt) [*c
pub extern fn ZigClangAPSInt_getNumWords(self: ?*const struct_ZigClangAPSInt) c_uint;
pub extern fn ZigClangAPValueLValueBase_dyn_cast_Expr(self: struct_ZigClangAPValueLValueBase) ?*const struct_ZigClangExpr;
pub extern fn ZigClangASTUnit_delete(arg0: ?*struct_ZigClangASTUnit) void;

pub extern fn ZigClangFunctionDecl_getType(self: *const struct_ZigClangFunctionDecl) struct_ZigClangQualType;
pub extern fn ZigClangFunctionDecl_getLocation(self: *const struct_ZigClangFunctionDecl) struct_ZigClangSourceLocation;

pub const ZigClangSourceLocation = struct_ZigClangSourceLocation;
pub const ZigClangQualType = struct_ZigClangQualType;
pub const ZigClangAPValueLValueBase = struct_ZigClangAPValueLValueBase;
Expand Down Expand Up @@ -944,6 +949,10 @@ pub const ZigClangStmtClass = enum_ZigClangStmtClass;
pub const ZigClangCK = enum_ZigClangCK;
pub const ZigClangAPValueKind = enum_ZigClangAPValueKind;

pub const struct_ZigClangSourceLocation = extern struct {
ID: c_uint,
};

pub const Stage2ErrorMsg = extern struct {
filename_ptr: ?[*]const u8,
filename_len: usize,
Expand All @@ -968,8 +977,8 @@ pub extern fn ZigClangLoadFromCommandLine(
resources_path: [*c]const u8,
) ?*ZigClangASTUnit;


pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;
pub extern fn ZigClangDecl_getDeclKindName(decl: *const struct_ZigClangDecl) [*]const u8;

pub const ZigClangDeclKind = extern enum {
AccessSpec,
Expand Down Expand Up @@ -1047,3 +1056,7 @@ pub const ZigClangDeclKind = extern enum {
StaticAssert,
TranslationUnit,
};

pub const struct_ZigClangQualType = extern struct {
ptr: ?*c_void,
};
3 changes: 2 additions & 1 deletion src-self-hosted/stage1.zig
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ export fn stage2_translate_c(
.import => translate_c.Mode.import,
.translate => translate_c.Mode.translate,
}, &errors, resources_path) catch |err| switch (err) {
error.SemanticAnalyzeFail => {
// TODO after https://github.com/ziglang/zig/issues/769 we can remove error.UnsupportedType
error.SemanticAnalyzeFail, error.UnsupportedType => {
out_errors_ptr.* = errors.ptr;
out_errors_len.* = errors.len;
return Error.CCompileErrors;
Expand Down
62 changes: 54 additions & 8 deletions src-self-hosted/translate_c.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ pub const Mode = enum {

pub const ClangErrMsg = Stage2ErrorMsg;

pub const Error = error{OutOfMemory};
pub const Error = error{
OutOfMemory,
UnsupportedType,
};

const Context = struct {
tree: *ast.Tree,
source_buffer: *std.Buffer,
err: Error,
source_manager: *ZigClangSourceManager,

fn a(c: *Context) *std.mem.Allocator {
return &c.tree.arena_allocator.allocator;
Expand All @@ -28,6 +32,17 @@ const Context = struct {
fn str(c: *Context, s: [*]const u8) ![]u8 {
return std.mem.dupe(c.a(), u8, std.mem.toSliceConst(u8, s));
}

/// Convert a clang source location to a file:line:column string
fn locStr(c: *Context, loc: ZigClangSourceLocation) ![]u8 {
const spelling_loc = ZigClangSourceManager_getSpellingLoc(c.source_manager, loc);
const filename_c = ZigClangSourceManager_getFilename(c.source_manager, spelling_loc);
const filename = if (filename_c) |s| try c.str(s) else ([]const u8)("(no file)");

const line = ZigClangSourceManager_getSpellingLineNumber(c.source_manager, spelling_loc);
const column = ZigClangSourceManager_getSpellingColumnNumber(c.source_manager, spelling_loc);
return std.fmt.allocPrint(c.a(), "{}:{}:{}", filename, line, column);
}
};

pub fn translate(
Expand Down Expand Up @@ -78,6 +93,7 @@ pub fn translate(
var context = Context{
.tree = tree,
.source_buffer = &source_buffer,
.source_manager = ZigClangASTUnit_getSourceManager(ast_unit),
.err = undefined,
};

Expand Down Expand Up @@ -105,27 +121,57 @@ fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
return visitFnDecl(c, @ptrCast(*const ZigClangFunctionDecl, decl));
},
.Typedef => {
try appendToken(c, .LineComment, "// TODO translate typedef");
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for typedefs");
},
.Enum => {
try appendToken(c, .LineComment, "// TODO translate enum");
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for enums");
},
.Record => {
try appendToken(c, .LineComment, "// TODO translate struct");
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for structs");
},
.Var => {
try appendToken(c, .LineComment, "// TODO translate variable");
try emitWarning(c, ZigClangDecl_getLocation(decl), "TODO implement translate-c for variables");
},
else => {
// TODO emit_warning(c, bitcast(decl->getLocation()), "ignoring %s decl", decl->getDeclKindName());
try appendToken(c, .LineComment, "// TODO translate unknown decl");
const decl_name = try c.str(ZigClangDecl_getDeclKindName(decl));
try emitWarning(c, ZigClangDecl_getLocation(decl), "ignoring {} declaration", decl_name);
},
}
}

fn visitFnDecl(c: *Context, fn_decl: *const ZigClangFunctionDecl) Error!void {
const fn_name = c.str(ZigClangDecl_getName_bytes_begin(@ptrCast(*const ZigClangDecl, fn_decl)));
try appendToken(c, .LineComment, "// TODO translate function '{}'", fn_name);

// TODO The C++ code has this:
//if (get_global(c, fn_name)) {
// // we already saw this function
// return;
//}

const fn_decl_loc = ZigClangFunctionDecl_getLocation(fn_decl);
const proto_node = transQualType(c, ZigClangFunctionDecl_getType(fn_decl), fn_decl_loc) catch |e| switch (e) {
error.UnsupportedType => {
try emitWarning(c, fn_decl_loc, "unable to resolve prototype of function '{}'", fn_name);
return;
},
else => return e,
};

try emitWarning(c, fn_decl_loc, "TODO implement translate-c for function decls");
}

fn transQualType(c: *Context, qt: ZigClangQualType, source_loc: ZigClangSourceLocation) !*ast.Node {
return transType(c, ZigClangQualType_getTypePtr(qt), source_loc);
}

fn transType(c: *Context, ty: *const ZigClangType, source_loc: ZigClangSourceLocation) !*ast.Node {
const type_name = c.str(ZigClangType_getTypeClassName(ty));
try emitWarning(c, source_loc, "unsupported type: '{}'", type_name);
return error.UnsupportedType;
}

fn emitWarning(c: *Context, loc: ZigClangSourceLocation, comptime format: []const u8, args: ...) !void {
try appendToken(c, .LineComment, "// {}: warning: " ++ format, c.locStr(loc), args);
}

fn appendToken(c: *Context, token_id: Token.Id, comptime format: []const u8, args: ...) !void {
Expand Down
28 changes: 15 additions & 13 deletions src/translate_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4009,42 +4009,44 @@ static TransScope *trans_stmt(Context *c, TransScope *scope, const ZigClangStmt
return child_scope;
}

static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
Buf *fn_name = buf_create_from_str(ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)fn_decl));

if (get_global(c, fn_name)) {
// we already saw this function
return;
}

AstNode *proto_node = trans_qual_type(c, bitcast(fn_decl->getType()), bitcast(fn_decl->getLocation()));
AstNode *proto_node = trans_qual_type(c, ZigClangFunctionDecl_getType(fn_decl),
ZigClangFunctionDecl_getLocation(fn_decl));
if (proto_node == nullptr) {
emit_warning(c, bitcast(fn_decl->getLocation()), "unable to resolve prototype of function '%s'", buf_ptr(fn_name));
emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl),
"unable to resolve prototype of function '%s'", buf_ptr(fn_name));
return;
}

proto_node->data.fn_proto.name = fn_name;
proto_node->data.fn_proto.is_extern = !fn_decl->hasBody();
proto_node->data.fn_proto.is_extern = !((const clang::FunctionDecl*)fn_decl)->hasBody();

clang::StorageClass sc = fn_decl->getStorageClass();
clang::StorageClass sc = ((const clang::FunctionDecl*)fn_decl)->getStorageClass();
if (sc == clang::SC_None) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
proto_node->data.fn_proto.is_export = fn_decl->hasBody() ? c->want_export : false;
proto_node->data.fn_proto.is_export = ((const clang::FunctionDecl*)fn_decl)->hasBody() ? c->want_export : false;
} else if (sc == clang::SC_Extern || sc == clang::SC_Static) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
} else if (sc == clang::SC_PrivateExtern) {
emit_warning(c, bitcast(fn_decl->getLocation()), "unsupported storage class: private extern");
emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern");
return;
} else {
emit_warning(c, bitcast(fn_decl->getLocation()), "unsupported storage class: unknown");
emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: unknown");
return;
}

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);
const clang::ParmVarDecl *param = fn_decl->getParamDecl(i);
const clang::ParmVarDecl *param = ((const clang::FunctionDecl*)fn_decl)->getParamDecl(i);
const char *name = ZigClangDecl_getName_bytes_begin((const ZigClangDecl *)param);

Buf *proto_param_name;
Expand All @@ -4063,19 +4065,19 @@ static void visit_fn_decl(Context *c, const clang::FunctionDecl *fn_decl) {
param_node->data.param_decl.name = scope_var->zig_name;
}

if (!fn_decl->hasBody()) {
if (!((const clang::FunctionDecl*)fn_decl)->hasBody()) {
// just a prototype
add_top_level_decl(c, proto_node->data.fn_proto.name, proto_node);
return;
}

// actual function definition with body
c->ptr_params.clear();
const ZigClangStmt *body = bitcast(fn_decl->getBody());
const ZigClangStmt *body = bitcast(((const clang::FunctionDecl*)fn_decl)->getBody());
AstNode *actual_body_node;
TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
if (result_scope == nullptr) {
emit_warning(c, bitcast(fn_decl->getLocation()), "unable to translate function");
emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unable to translate function");
return;
}
assert(actual_body_node != nullptr);
Expand Down Expand Up @@ -4558,7 +4560,7 @@ static bool decl_visitor(void *context, const ZigClangDecl *decl) {

switch (ZigClangDecl_getKind(decl)) {
case ZigClangDeclFunction:
visit_fn_decl(c, reinterpret_cast<const clang::FunctionDecl*>(decl));
visit_fn_decl(c, reinterpret_cast<const ZigClangFunctionDecl*>(decl));
break;
case ZigClangDeclTypedef:
resolve_typedef_decl(c, reinterpret_cast<const ZigClangTypedefNameDecl *>(decl));
Expand Down
10 changes: 10 additions & 0 deletions src/zig_clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,16 @@ ZigClangQualType ZigClangEnumDecl_getIntegerType(const ZigClangEnumDecl *self) {
return bitcast(reinterpret_cast<const clang::EnumDecl *>(self)->getIntegerType());
}

struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *self) {
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
return bitcast(casted->getType());
}

struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *self) {
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
return bitcast(casted->getLocation());
}

const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) {
auto casted = reinterpret_cast<const clang::TypedefType *>(self);
const clang::TypedefNameDecl *name_decl = casted->getDecl();
Expand Down
3 changes: 3 additions & 0 deletions src/zig_clang.h
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,9 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangEnumDecl_getLocation(const st
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangTypedefNameDecl_getLocation(const struct ZigClangTypedefNameDecl *);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDecl_getLocation(const struct ZigClangDecl *);

ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *);

ZIG_EXTERN_C bool ZigClangRecordDecl_isUnion(const struct ZigClangRecordDecl *record_decl);
ZIG_EXTERN_C bool ZigClangRecordDecl_isStruct(const struct ZigClangRecordDecl *record_decl);
ZIG_EXTERN_C bool ZigClangRecordDecl_isAnonymousStructOrUnion(const struct ZigClangRecordDecl *record_decl);
Expand Down

0 comments on commit 46e1c34

Please sign in to comment.