Skip to content

Commit

Permalink
translate-c: we have our first test of self-hosted
Browse files Browse the repository at this point in the history
See #1964
  • Loading branch information
andrewrk committed May 10, 2019
1 parent d065f29 commit a6f7a9c
Show file tree
Hide file tree
Showing 7 changed files with 320 additions and 123 deletions.
15 changes: 13 additions & 2 deletions src-self-hosted/clang.zig
Expand Up @@ -56,7 +56,6 @@ pub const struct_ZigClangSkipFunctionBodiesScope = @OpaqueType();
pub const struct_ZigClangSourceManager = @OpaqueType();
pub const struct_ZigClangSourceRange = @OpaqueType();
pub const struct_ZigClangStmt = @OpaqueType();
pub const struct_ZigClangStorageClass = @OpaqueType();
pub const struct_ZigClangStringLiteral = @OpaqueType();
pub const struct_ZigClangStringRef = @OpaqueType();
pub const struct_ZigClangSwitchStmt = @OpaqueType();
Expand Down Expand Up @@ -513,6 +512,10 @@ 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 extern fn ZigClangFunctionDecl_hasBody(self: *const struct_ZigClangFunctionDecl) bool;
pub extern fn ZigClangFunctionDecl_getStorageClass(self: *const struct_ZigClangFunctionDecl) ZigClangStorageClass;
pub extern fn ZigClangFunctionDecl_getParamDecl(self: *const struct_ZigClangFunctionDecl, i: c_uint) *const struct_ZigClangParmVarDecl;

pub extern fn ZigClangBuiltinType_getKind(self: *const struct_ZigClangBuiltinType) ZigClangBuiltinTypeKind;

pub extern fn ZigClangFunctionType_getNoReturnAttr(self: *const ZigClangFunctionType) bool;
Expand Down Expand Up @@ -584,7 +587,6 @@ pub const ZigClangSkipFunctionBodiesScope = struct_ZigClangSkipFunctionBodiesSco
pub const ZigClangSourceManager = struct_ZigClangSourceManager;
pub const ZigClangSourceRange = struct_ZigClangSourceRange;
pub const ZigClangStmt = struct_ZigClangStmt;
pub const ZigClangStorageClass = struct_ZigClangStorageClass;
pub const ZigClangStringLiteral = struct_ZigClangStringLiteral;
pub const ZigClangStringRef = struct_ZigClangStringRef;
pub const ZigClangSwitchStmt = struct_ZigClangSwitchStmt;
Expand Down Expand Up @@ -849,3 +851,12 @@ pub const ZigClangCallingConv = extern enum {
PreserveAll,
AArch64VectorCall,
};

pub const ZigClangStorageClass = extern enum {
None,
Extern,
Static,
PrivateExtern,
Auto,
Register,
};
316 changes: 207 additions & 109 deletions src-self-hosted/translate_c.zig

Large diffs are not rendered by default.

18 changes: 9 additions & 9 deletions src/translate_c.cpp
Expand Up @@ -4038,15 +4038,15 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
}

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

clang::StorageClass sc = ((const clang::FunctionDecl*)fn_decl)->getStorageClass();
if (sc == clang::SC_None) {
ZigClangStorageClass sc = ZigClangFunctionDecl_getStorageClass(fn_decl);
if (sc == ZigClangStorageClass_None) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
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.is_export = ZigClangFunctionDecl_hasBody(fn_decl) ? c->want_export : false;
} else if (sc == ZigClangStorageClass_Extern || sc == ZigClangStorageClass_Static) {
proto_node->data.fn_proto.visib_mod = c->visib_mod;
} else if (sc == clang::SC_PrivateExtern) {
} else if (sc == ZigClangStorageClass_PrivateExtern) {
emit_warning(c, ZigClangFunctionDecl_getLocation(fn_decl), "unsupported storage class: private extern");
return;
} else {
Expand All @@ -4058,7 +4058,7 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {

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

Buf *proto_param_name;
Expand All @@ -4077,15 +4077,15 @@ static void visit_fn_decl(Context *c, const ZigClangFunctionDecl *fn_decl) {
param_node->data.param_decl.name = scope_var->zig_name;
}

if (!((const clang::FunctionDecl*)fn_decl)->hasBody()) {
if (!ZigClangFunctionDecl_hasBody(fn_decl)) {
// 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(((const clang::FunctionDecl*)fn_decl)->getBody());
const ZigClangStmt *body = ZigClangFunctionDecl_getBody(fn_decl);
AstNode *actual_body_node;
TransScope *result_scope = trans_stmt(c, scope, body, &actual_body_node);
if (result_scope == nullptr) {
Expand Down
43 changes: 43 additions & 0 deletions src/zig_clang.cpp
Expand Up @@ -1236,6 +1236,25 @@ static_assert((clang::CallingConv)ZigClangCallingConv_PreserveMost == clang::CC_
static_assert((clang::CallingConv)ZigClangCallingConv_PreserveAll == clang::CC_PreserveAll, "");
static_assert((clang::CallingConv)ZigClangCallingConv_AArch64VectorCall == clang::CC_AArch64VectorCall, "");

void ZigClang_detect_enum_StorageClass(clang::StorageClass x) {
switch (x) {
case clang::SC_None:
case clang::SC_Extern:
case clang::SC_Static:
case clang::SC_PrivateExtern:
case clang::SC_Auto:
case clang::SC_Register:
break;
}
}

static_assert((clang::StorageClass)ZigClangStorageClass_None == clang::SC_None, "");
static_assert((clang::StorageClass)ZigClangStorageClass_Extern == clang::SC_Extern, "");
static_assert((clang::StorageClass)ZigClangStorageClass_Static == clang::SC_Static, "");
static_assert((clang::StorageClass)ZigClangStorageClass_PrivateExtern == clang::SC_PrivateExtern, "");
static_assert((clang::StorageClass)ZigClangStorageClass_Auto == clang::SC_Auto, "");
static_assert((clang::StorageClass)ZigClangStorageClass_Register == clang::SC_Register, "");


static_assert(sizeof(ZigClangSourceLocation) == sizeof(clang::SourceLocation), "");
static ZigClangSourceLocation bitcast(clang::SourceLocation src) {
Expand Down Expand Up @@ -1434,6 +1453,30 @@ struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigC
return bitcast(casted->getLocation());
}

bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *self) {
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
return casted->hasBody();
}

enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *self) {
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
return (ZigClangStorageClass)casted->getStorageClass();
}

const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *self,
unsigned i)
{
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
const clang::ParmVarDecl *parm_var_decl = casted->getParamDecl(i);
return reinterpret_cast<const ZigClangParmVarDecl *>(parm_var_decl);
}

const struct ZigClangStmt *ZigClangFunctionDecl_getBody(const struct ZigClangFunctionDecl *self) {
auto casted = reinterpret_cast<const clang::FunctionDecl *>(self);
const clang::Stmt *stmt = casted->getBody();
return reinterpret_cast<const ZigClangStmt *>(stmt);
}

const ZigClangTypedefNameDecl *ZigClangTypedefType_getDecl(const ZigClangTypedefType *self) {
auto casted = reinterpret_cast<const clang::TypedefType *>(self);
const clang::TypedefNameDecl *name_decl = casted->getDecl();
Expand Down
17 changes: 16 additions & 1 deletion src/zig_clang.h
Expand Up @@ -88,7 +88,6 @@ struct ZigClangSkipFunctionBodiesScope;
struct ZigClangSourceManager;
struct ZigClangSourceRange;
struct ZigClangStmt;
struct ZigClangStorageClass;
struct ZigClangStringLiteral;
struct ZigClangStringRef;
struct ZigClangSwitchStmt;
Expand Down Expand Up @@ -700,6 +699,18 @@ enum ZigClangCallingConv {
ZigClangCallingConv_AArch64VectorCall, // __attribute__((aarch64_vector_pcs))
};

enum ZigClangStorageClass {
// These are legal on both functions and variables.
ZigClangStorageClass_None,
ZigClangStorageClass_Extern,
ZigClangStorageClass_Static,
ZigClangStorageClass_PrivateExtern,

// These are only legal on variables.
ZigClangStorageClass_Auto,
ZigClangStorageClass_Register,
};

ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangSourceManager_getSpellingLoc(const struct ZigClangSourceManager *,
struct ZigClangSourceLocation Loc);
ZIG_EXTERN_C const char *ZigClangSourceManager_getFilename(const struct ZigClangSourceManager *,
Expand Down Expand Up @@ -742,6 +753,10 @@ ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangDecl_getLocation(const struct

ZIG_EXTERN_C struct ZigClangQualType ZigClangFunctionDecl_getType(const struct ZigClangFunctionDecl *);
ZIG_EXTERN_C struct ZigClangSourceLocation ZigClangFunctionDecl_getLocation(const struct ZigClangFunctionDecl *);
ZIG_EXTERN_C bool ZigClangFunctionDecl_hasBody(const struct ZigClangFunctionDecl *);
ZIG_EXTERN_C enum ZigClangStorageClass ZigClangFunctionDecl_getStorageClass(const struct ZigClangFunctionDecl *);
ZIG_EXTERN_C const struct ZigClangParmVarDecl *ZigClangFunctionDecl_getParamDecl(const struct ZigClangFunctionDecl *, unsigned i);
ZIG_EXTERN_C const struct ZigClangStmt *ZigClangFunctionDecl_getBody(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);
Expand Down
28 changes: 26 additions & 2 deletions test/tests.zig
Expand Up @@ -903,6 +903,7 @@ pub const TranslateCContext = struct {
sources: ArrayList(SourceFile),
expected_lines: ArrayList([]const u8),
allow_warnings: bool,
stage2: bool,

const SourceFile = struct {
filename: []const u8,
Expand Down Expand Up @@ -955,7 +956,8 @@ pub const TranslateCContext = struct {
var zig_args = ArrayList([]const u8).init(b.allocator);
zig_args.append(b.zig_exe) catch unreachable;

zig_args.append("translate-c") catch unreachable;
const translate_c_cmd = if (self.case.stage2) "translate-c-2" else "translate-c";
zig_args.append(translate_c_cmd) catch unreachable;
zig_args.append(b.pathFromRoot(root_src)) catch unreachable;

warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
Expand Down Expand Up @@ -1052,6 +1054,7 @@ pub const TranslateCContext = struct {
.sources = ArrayList(TestCase.SourceFile).init(self.b.allocator),
.expected_lines = ArrayList([]const u8).init(self.b.allocator),
.allow_warnings = allow_warnings,
.stage2 = false,
};

tc.addSourceFile(filename, source);
Expand All @@ -1072,6 +1075,26 @@ pub const TranslateCContext = struct {
self.addCase(tc);
}

pub fn add_both(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
for ([]bool{ false, true }) |stage2| {
const tc = self.create(false, "source.c", name, source, expected_lines);
tc.stage2 = stage2;
self.addCase(tc);
}
}

pub fn add_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create(false, "source.c", name, source, expected_lines);
tc.stage2 = true;
self.addCase(tc);
}

pub fn addC_2(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create(false, "source.c", name, source, expected_lines);
tc.stage2 = true;
self.addCase(tc);
}

pub fn addAllowWarnings(self: *TranslateCContext, name: []const u8, source: []const u8, expected_lines: ...) void {
const tc = self.create(true, "source.h", name, source, expected_lines);
self.addCase(tc);
Expand All @@ -1080,7 +1103,8 @@ pub const TranslateCContext = struct {
pub fn addCase(self: *TranslateCContext, case: *const TestCase) void {
const b = self.b;

const annotated_case_name = fmt.allocPrint(self.b.allocator, "translate-c {}", case.name) catch unreachable;
const translate_c_cmd = if (case.stage2) "translate-c-2" else "translate-c";
const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {}", translate_c_cmd, case.name) catch unreachable;
if (self.test_filter) |filter| {
if (mem.indexOf(u8, annotated_case_name, filter) == null) return;
}
Expand Down
6 changes: 6 additions & 0 deletions test/translate_c.zig
Expand Up @@ -2,6 +2,12 @@ const tests = @import("tests.zig");
const builtin = @import("builtin");

pub fn addCases(cases: *tests.TranslateCContext) void {
cases.add_both("simple noreturn fn",
\\void __attribute__((noreturn)) foo(void);
,
\\extern fn foo() noreturn;
);

cases.add("macro with left shift",
\\#define REDISMODULE_READ (1<<0)
,
Expand Down

0 comments on commit a6f7a9c

Please sign in to comment.