Skip to content

Commit

Permalink
self-hosted translate-c: iterate over top level decls
Browse files Browse the repository at this point in the history
See #1964
  • Loading branch information
andrewrk committed Apr 30, 2019
1 parent 01365be commit a7f99c8
Show file tree
Hide file tree
Showing 5 changed files with 404 additions and 22 deletions.
82 changes: 81 additions & 1 deletion src-self-hosted/clang.zig
Original file line number Diff line number Diff line change
Expand Up @@ -813,7 +813,7 @@ pub extern fn ZigClangSourceManager_getCharacterData(arg0: ?*const struct_ZigCla
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_visitLocalTopLevelDecls(arg0: ?*struct_ZigClangASTUnit, context: ?*c_void, Fn: ?extern fn (?*c_void, ?*const struct_ZigClangDecl) bool) bool;
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;
pub extern fn ZigClangRecordDecl_getCanonicalDecl(record_decl: ?*const struct_ZigClangRecordDecl) ?*const struct_ZigClangTagDecl;
Expand Down Expand Up @@ -967,3 +967,83 @@ pub extern fn ZigClangLoadFromCommandLine(
errors_len: *usize,
resources_path: [*c]const u8,
) ?*ZigClangASTUnit;


pub extern fn ZigClangDecl_getKind(decl: *const ZigClangDecl) ZigClangDeclKind;

pub const ZigClangDeclKind = extern enum {
AccessSpec,
Block,
Captured,
ClassScopeFunctionSpecialization,
Empty,
Export,
ExternCContext,
FileScopeAsm,
Friend,
FriendTemplate,
Import,
LinkageSpec,
Label,
Namespace,
NamespaceAlias,
ObjCCompatibleAlias,
ObjCCategory,
ObjCCategoryImpl,
ObjCImplementation,
ObjCInterface,
ObjCProtocol,
ObjCMethod,
ObjCProperty,
BuiltinTemplate,
ClassTemplate,
FunctionTemplate,
TypeAliasTemplate,
VarTemplate,
TemplateTemplateParm,
Enum,
Record,
CXXRecord,
ClassTemplateSpecialization,
ClassTemplatePartialSpecialization,
TemplateTypeParm,
ObjCTypeParam,
TypeAlias,
Typedef,
UnresolvedUsingTypename,
Using,
UsingDirective,
UsingPack,
UsingShadow,
ConstructorUsingShadow,
Binding,
Field,
ObjCAtDefsField,
ObjCIvar,
Function,
CXXDeductionGuide,
CXXMethod,
CXXConstructor,
CXXConversion,
CXXDestructor,
MSProperty,
NonTypeTemplateParm,
Var,
Decomposition,
ImplicitParam,
OMPCapturedExpr,
ParmVar,
VarTemplateSpecialization,
VarTemplatePartialSpecialization,
EnumConstant,
IndirectField,
OMPDeclareReduction,
UnresolvedUsingValue,
OMPRequires,
OMPThreadPrivate,
ObjCPropertyImpl,
PragmaComment,
PragmaDetectMismatch,
StaticAssert,
TranslationUnit,
};
68 changes: 60 additions & 8 deletions src-self-hosted/translate_c.zig
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// This is the userland implementation of translate-c which will be used by both stage1
// and stage2. Currently it's not used by anything, as it's not feature complete.
// and stage2. Currently the only way it is used is with `zig translate-c-2`.

const std = @import("std");
const ast = std.zig.ast;
Expand All @@ -13,6 +13,16 @@ pub const Mode = enum {

pub const ClangErrMsg = Stage2ErrorMsg;

pub const Error = error {
OutOfMemory,
};

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

pub fn translate(
backing_allocator: *std.mem.Allocator,
args_begin: [*]?[*]const u8,
Expand Down Expand Up @@ -57,23 +67,65 @@ pub fn translate(

var source_buffer = try std.Buffer.initSize(arena, 0);

try appendToken(tree, &source_buffer, "// TODO: implement more than just an empty source file", .LineComment);
var context = Context{
.tree = tree,
.source_buffer = &source_buffer,
.err = undefined,
};

if (!ZigClangASTUnit_visitLocalTopLevelDecls(ast_unit, &context, declVisitorC)) {
return context.err;
}

try appendToken(tree, &source_buffer, "", .Eof);
try appendToken(&context, .Eof, "");
tree.source = source_buffer.toOwnedSlice();
return tree;
}

fn appendToken(tree: *ast.Tree, source_buffer: *std.Buffer, src_text: []const u8, token_id: Token.Id) !void {
const start_index = source_buffer.len();
try source_buffer.append(src_text);
const end_index = source_buffer.len();
const new_token = try tree.tokens.addOne();
extern fn declVisitorC(context: ?*c_void, decl: *const ZigClangDecl) bool {
const c = @ptrCast(*Context, @alignCast(@alignOf(Context), context));
declVisitor(c, decl) catch |err| {
c.err = err;
return false;
};
return true;
}

fn declVisitor(c: *Context, decl: *const ZigClangDecl) Error!void {
switch (ZigClangDecl_getKind(decl)) {
.Function => {
try appendToken(c, .LineComment, "// TODO translate function decl");
},
.Typedef => {
try appendToken(c, .LineComment, "// TODO translate typedef");
},
.Enum => {
try appendToken(c, .LineComment, "// TODO translate enum");
},
.Record => {
try appendToken(c, .LineComment, "// TODO translate struct");
},
.Var => {
try appendToken(c, .LineComment, "// TODO translate variable");
},
else => {
// TODO emit_warning(c, bitcast(decl->getLocation()), "ignoring %s decl", decl->getDeclKindName());
try appendToken(c, .LineComment, "// TODO translate unknown decl");
},
}
}

fn appendToken(c: *Context, token_id: Token.Id, src_text: []const u8) !void {
const start_index = c.source_buffer.len();
try c.source_buffer.append(src_text);
const end_index = c.source_buffer.len();
const new_token = try c.tree.tokens.addOne();
new_token.* = Token{
.id = token_id,
.start = start_index,
.end = end_index,
};
try c.source_buffer.appendByte('\n');
}

pub fn freeErrors(errors: []ClangErrMsg) void {
Expand Down
23 changes: 11 additions & 12 deletions src/translate_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4554,28 +4554,27 @@ static void visit_var_decl(Context *c, const clang::VarDecl *var_decl) {
return;
}

static bool decl_visitor(void *context, const ZigClangDecl *zdecl) {
const clang::Decl *decl = reinterpret_cast<const clang::Decl *>(zdecl);
static bool decl_visitor(void *context, const ZigClangDecl *decl) {
Context *c = (Context*)context;

switch (decl->getKind()) {
case clang::Decl::Function:
visit_fn_decl(c, static_cast<const clang::FunctionDecl*>(decl));
switch (ZigClangDecl_getKind(decl)) {
case ZigClangDeclFunction:
visit_fn_decl(c, reinterpret_cast<const clang::FunctionDecl*>(decl));
break;
case clang::Decl::Typedef:
case ZigClangDeclTypedef:
resolve_typedef_decl(c, reinterpret_cast<const ZigClangTypedefNameDecl *>(decl));
break;
case clang::Decl::Enum:
case ZigClangDeclEnum:
resolve_enum_decl(c, reinterpret_cast<const ZigClangEnumDecl *>(decl));
break;
case clang::Decl::Record:
resolve_record_decl(c, (const ZigClangRecordDecl *)(decl));
case ZigClangDeclRecord:
resolve_record_decl(c, reinterpret_cast<const ZigClangRecordDecl *>(decl));
break;
case clang::Decl::Var:
visit_var_decl(c, static_cast<const clang::VarDecl *>(decl));
case ZigClangDeclVar:
visit_var_decl(c, reinterpret_cast<const clang::VarDecl *>(decl));
break;
default:
emit_warning(c, bitcast(decl->getLocation()), "ignoring %s decl", decl->getDeclKindName());
emit_warning(c, ZigClangDecl_getLocation(decl), "ignoring %s decl", ZigClangDecl_getDeclKindName(decl));
}

return true;
Expand Down
Loading

0 comments on commit a7f99c8

Please sign in to comment.