Skip to content

Commit

Permalink
ignore type recursion
Browse files Browse the repository at this point in the history
this isn't good, but slightly better than before
  • Loading branch information
aep committed Jan 31, 2020
1 parent 3b41762 commit bb7497a
Show file tree
Hide file tree
Showing 11 changed files with 157 additions and 38 deletions.
2 changes: 1 addition & 1 deletion modules/pool/src/asan.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ void __asan_poison_memory_region(void const volatile *addr, size_t size);
void __asan_unpoison_memory_region(void const volatile *addr, size_t size);

// User code should use macros instead of functions.
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#if defined(__SANITIZE_ADDRESS__)
#define ASAN_POISON_MEMORY_REGION(addr, size) \
__asan_poison_memory_region((addr), (size))
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
Expand Down
18 changes: 17 additions & 1 deletion modules/pool/src/lib.zz
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using <string.h>::{memset};
using <assert.h>::{assert};
using <stdio.h>::{stderr};
using <stdio.h>::{stderr, printf};
using hex;
using err;
using <stdint.h>::{uintptr_t};
Expand Down Expand Up @@ -30,6 +30,8 @@ export struct Pool+ {
export fn new(Pool+pt mut *self, u8 mut blocksize)
where pt > pt/(usize)blocksize
{
assert((usize)blocksize % ALIGN == 0);

self->blocksize = blocksize;
usize mut usedmemlen = pt / (usize)blocksize / 8;
unsafe { usedmemlen += (ALIGN - (usedmemlen % ALIGN)); }
Expand All @@ -47,6 +49,20 @@ export fn new(Pool+pt mut *self, u8 mut blocksize)
ASAN_POISON_MEMORY_REGION(self->pool, self->poolsize);
}

export fn free_bytes(Pool *self) -> usize
{
static_attest(safe(self->used));
static_attest(len(self->used) == self->poolsize/(usize)self->blocksize);

usize mut c = 0;
for (usize mut i = 0 ; i < self->poolsize/(usize)self->blocksize; i++) {
if !bitarray_test(self->used, i) {
c += (usize)self->blocksize;
}
}
return c;
}

export fn alloc(Pool mut *self, usize mut size) -> void mut*
model member(return, self)
{
Expand Down
3 changes: 1 addition & 2 deletions modules/std/src/lib.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
#include <memory.h>
#include <alloca.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
110 changes: 81 additions & 29 deletions src/emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,26 @@ impl Emitter {
if self.header && d.vis != ast::Visibility::Export {
continue
}
match d.def {
ast::Def::Struct{..} => {
self.emit_struct_def(&d, *def_here, None);
if let Some(vs) = module.typevariants.get(&Name::from(&d.name)) {
for v in vs {
let mut d = d.clone();
d.name = format!("{}_{}", d.name, v);
self.emit_struct_def(&d, *def_here, Some(*v));
}
}
}
_ => (),
}
write!(self.f, "\n").unwrap();
}

for (d, decl_here, def_here) in &module.d {
if !decl_here{
continue
}
match d.def {
ast::Def::Macro{..} => {
self.emit_macro(&d)
Expand All @@ -191,24 +211,9 @@ impl Emitter {
ast::Def::Static{..} => {
self.emit_static(&d)
}
ast::Def::Struct{..} => {
self.emit_struct(&d, *def_here, None);
if let Some(vs) = module.typevariants.get(&Name::from(&d.name)) {
for v in vs {
let mut d = d.clone();
d.name = format!("{}_{}", d.name, v);
self.emit_struct(&d, *def_here, Some(*v));
}
}
}
ast::Def::Enum{..} => {
self.emit_enum(&d)
}
ast::Def::Function{..} => {
if !d.name.ends_with("::main") {
self.emit_decl(&d);
}
}
ast::Def::Fntype{..} => {
self.emit_fntype(&d);
}
Expand All @@ -217,11 +222,27 @@ impl Emitter {
ast::Def::Testcase {..} => {
self.emit_testcase(&d);
}
ast::Def::Include {..} => {
ast::Def::Function{..} => {
if !d.name.ends_with("::main") {
self.emit_decl(&d);
}
}
ast::Def::Include {inline,..} => {
self.emit_include(&d);
}
ast::Def::Struct{..} => {
self.emit_struct(&d, *def_here, None);
if let Some(vs) = module.typevariants.get(&Name::from(&d.name)) {
for v in vs {
let mut d = d.clone();
d.name = format!("{}_{}", d.name, v);
self.emit_struct(&d, *def_here, Some(*v));
}
}
}

_ => (),
}
write!(self.f, "\n").unwrap();
}

if self.header {
Expand All @@ -234,12 +255,15 @@ impl Emitter {
if !def_here {
continue
}
if let ast::Def::Function{..} = d.def {
let mut name = Name::from(&d.name);
name.pop();
if name == module.name {
self.emit_def(&d);
match d.def {
ast::Def::Function{..} => {
let mut name = Name::from(&d.name);
name.pop();
if name == module.name {
self.emit_def(&d);
}
}
_ => (),
}
}
}
Expand Down Expand Up @@ -474,23 +498,48 @@ impl Emitter {
}


pub fn emit_struct(&mut self, ast: &ast::Local, def_here: bool, tail_variant: Option<u64>) {
pub fn emit_struct_def(&mut self, ast: &ast::Local, def_here: bool, tail_variant: Option<u64>) {
let (fields, packed, _tail, union) = match &ast.def {
ast::Def::Struct{fields, packed, tail, union, ..} => (fields, packed, tail, union),
_ => unreachable!(),
};

self.emit_loc(&ast.loc);
if *union {
write!(self.f, "typedef union \n").unwrap();
write!(self.f, "union ").unwrap();
} else {
write!(self.f, "typedef struct \n").unwrap();
write!(self.f, "struct ").unwrap();
}
write!(self.f, "{}_t;\n", self.to_local_name(&Name::from(&ast.name))).unwrap();

write!(self.f, "typedef ").unwrap();
if *union {
write!(self.f, "union ").unwrap();
} else {
write!(self.f, "struct ").unwrap();
}
write!(self.f, "{}_t {};\n",
self.to_local_name(&Name::from(&ast.name)),
self.to_local_name(&Name::from(&ast.name))
).unwrap();

if *packed {
write!(self.f, " __attribute__((__packed__)) ").unwrap();
}

pub fn emit_struct(&mut self, ast: &ast::Local, def_here: bool, tail_variant: Option<u64>) {
let (fields, packed, _tail, union) = match &ast.def {
ast::Def::Struct{fields, packed, tail, union, ..} => (fields, packed, tail, union),
_ => unreachable!(),
};

self.emit_loc(&ast.loc);
if *union {
write!(self.f, "union ").unwrap();
} else {
write!(self.f, "struct ").unwrap();
}
write!(self.f, "{}_t ", self.to_local_name(&Name::from(&ast.name))).unwrap();




write!(self.f, "{{\n").unwrap();
Expand Down Expand Up @@ -534,10 +583,13 @@ impl Emitter {
write!(self.f, " uint8_t _____tail [{}];\n", tt).unwrap();
}
}
write!(self.f, "}}\n").unwrap();

write!(self.f, "}} {}", self.to_local_name(&Name::from(&ast.name))).unwrap();
write!(self.f, " ;\n").unwrap();
if *packed {
write!(self.f, " __attribute__((__packed__)) ").unwrap();
}

write!(self.f, ";\n").unwrap();

if def_here {
if ast.vis == ast::Visibility::Export {
Expand Down
20 changes: 15 additions & 5 deletions src/flatten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,10 @@ pub fn flatten(md: &mut ast::Module, all_modules: &HashMap<Name, loader::Module>
let mut ast = local.clone();
let ast_name = local.name.clone();

let mut decl_deps : Vec<(Name, ast::Location)> = Vec::new();
let mut impl_deps : Vec<(Name, ast::Location)> = Vec::new();
let mut decl_deps : Vec<(Name, ast::Location)> = Vec::new();
let mut impl_deps : Vec<(Name, ast::Location)> = Vec::new();
let mut weak_deps : Vec<(Name, ast::Location)> = Vec::new();

match &local.def {
ast::Def::Enum{names, ..} => {
let mut ns = module_name.clone();
Expand Down Expand Up @@ -457,7 +459,12 @@ pub fn flatten(md: &mut ast::Module, all_modules: &HashMap<Name, loader::Module>
}
ast::Def::Struct{fields,..} => {
for field in fields {
decl_deps.extend(type_deps(cr, &field.typed));
if field.typed.ptr.len() > 0 {
weak_deps.extend(type_deps(cr, &field.typed));
} else {
decl_deps.extend(type_deps(cr, &field.typed));
}

if let Some(ref expr) = &field.array {
if let Some(ref expr) = expr {
decl_deps.extend(expr_deps(cr, expr));
Expand Down Expand Up @@ -494,6 +501,9 @@ pub fn flatten(md: &mut ast::Module, all_modules: &HashMap<Name, loader::Module>
for (dep,loc) in &decl_deps {
incomming.push((dep.clone(), loc.clone()));
}
for (dep,loc) in &weak_deps {
incomming.push((dep.clone(), loc.clone()));
}


let ns = if module_name.0[1] == "ext" {
Expand All @@ -509,7 +519,7 @@ pub fn flatten(md: &mut ast::Module, all_modules: &HashMap<Name, loader::Module>
collected.0.insert(ns, Local{
decl_deps,
impl_deps,
use_deps: Vec::new(),
use_deps: weak_deps,
ast: Some(ast),
in_scope_here: loc,
});
Expand Down Expand Up @@ -757,7 +767,7 @@ fn sort_visit(
}

for (dep,loc) in &n.decl_deps {
sort_visit(sorted, sorted_mark, unsorted, dep.clone(), Some(loc), false, depth+1, Some(&mut use_deps_here));
sort_visit(sorted, sorted_mark, unsorted, dep.clone(), Some(loc), allow_recursion, depth+1, Some(&mut use_deps_here));
}


Expand Down
3 changes: 3 additions & 0 deletions tests/mustpass/recursive_struct/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/target
.gdb_history
vgcore.*
7 changes: 7 additions & 0 deletions tests/mustpass/recursive_struct/src/a.zz
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using b;
using c;
pub struct A {
b::B b;
c::C c;
}

7 changes: 7 additions & 0 deletions tests/mustpass/recursive_struct/src/b.zz
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using c;
using a;
pub struct B {
a::A *a;
c::C c;
}

5 changes: 5 additions & 0 deletions tests/mustpass/recursive_struct/src/c.zz
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
using a;
pub struct C {
a::A * a;
}

7 changes: 7 additions & 0 deletions tests/mustpass/recursive_struct/src/main.zz
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using <stdio.h>::{printf};


export fn main() -> int {
printf("hello recursive_struct\n");
return 0;
}
13 changes: 13 additions & 0 deletions tests/mustpass/recursive_struct/zz.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[project]
version = "0.1.0"
name = "recursive_struct"
cincludes = []
cobjects = []
pkgconfig = []
cflags = []
lflags = []

[variants]
default = []

[dependencies]

0 comments on commit bb7497a

Please sign in to comment.