From cde356ee235d83d82e4b501aa045c934684b2345 Mon Sep 17 00:00:00 2001 From: Rafael Ravedutti Lucio Machado <rafael.r.ravedutti@fau.de> Date: Tue, 5 Jan 2021 23:41:13 +0100 Subject: [PATCH] Separate code generation from IR elements Signed-off-by: Rafael Ravedutti Lucio Machado <rafael.r.ravedutti@fau.de> --- ast/arrays.py | 20 +-- ast/assign.py | 10 -- ast/block.py | 11 -- ast/branches.py | 11 -- ast/cast.py | 3 - ast/expr.py | 52 +----- ast/lit.py | 4 - ast/loops.py | 26 +-- ast/math.py | 3 - ast/memory.py | 16 +- ast/properties.py | 3 - ast/select.py | 3 - ast/sizeof.py | 3 - ast/utils.py | 3 - ast/variables.py | 7 - code_gen/cgen.py | 338 ++++++++++++++++++++++++------------- sim/arrays.py | 2 +- sim/particle_simulation.py | 5 +- sim/properties.py | 4 +- sim/resize.py | 2 +- sim/timestep.py | 3 - sim/vtk.py | 13 +- 22 files changed, 245 insertions(+), 297 deletions(-) diff --git a/ast/arrays.py b/ast/arrays.py index c801935..56f2f03 100644 --- a/ast/arrays.py +++ b/ast/arrays.py @@ -80,9 +80,6 @@ class Array: def children(self): return [] - def generate(self, mem=False, index=None): - return self.arr_name - def transform(self, fn): return fn(self) @@ -110,7 +107,7 @@ class ArrayND(Array): f"type: {self.arr_type}>") def realloc(self): - return Realloc(self.sim, self, self.arr_type, self.alloc_size()) + return Realloc(self.sim, self, self.alloc_size()) class ArrayAccess: @@ -174,6 +171,9 @@ class ArrayAccess: def add(self, other): return self.sim.add_statement(Assign(self.sim, self, self + other)) + def id(self): + return self.acc_id + def type(self): return self.array.type() # return self.array.type() if self.index is None else Type_Array @@ -196,15 +196,6 @@ class ArrayAccess: def children(self): return [self.array] + self.indexes - def generate(self, mem=False, index=None): - agen = self.array.generate() - igen = self.index.generate() - if mem is False and self.generated is False: - self.sim.code_gen.generate_array_access(self.acc_id, self.array.type(), agen, igen) - self.generated = True - - return self.sim.code_gen.generate_array_access_ref(self.acc_id, agen, igen, mem) - def transform(self, fn): self.array = self.array.transform(fn) self.indexes = [i.transform(fn) for i in self.indexes] @@ -220,8 +211,5 @@ class ArrayDecl: def children(self): return [] - def generate(self, mem=False, index=None): - self.sim.code_gen.generate_array_decl(self.array.name(), self.array.type(), BinOp.inline(self.array.alloc_size()).generate()) - def transform(self, fn): return fn(self) diff --git a/ast/assign.py b/ast/assign.py index 98b78b1..59f11e4 100644 --- a/ast/assign.py +++ b/ast/assign.py @@ -8,7 +8,6 @@ class Assign: self.sim = sim self.parent_block = None self.type = dest.type() - self.generated = False src = as_lit_ast(sim, src) if dest.type() == Type_Vector: @@ -32,15 +31,6 @@ class Assign: [self.assignments[i][0], self.assignments[i][1]] for i in range(0, len(self.assignments))]) - def generate(self): - if self.generated is False: - for dest, src in self.assignments: - d = dest.generate(True) - s = src.generate() - self.sim.code_gen.generate_assignment(d, s) - - self.generated = True - def transform(self, fn): self.assignments = [( self.assignments[i][0].transform(fn), diff --git a/ast/block.py b/ast/block.py index de9e32b..4ed52ee 100644 --- a/ast/block.py +++ b/ast/block.py @@ -50,17 +50,6 @@ class Block: def children(self): return self.stmts - def generate(self): - self.sim.code_gen.generate_block_preamble() - - for expr in self.expressions: - expr.generate() - - for stmt in self.stmts: - stmt.generate() - - self.sim.code_gen.generate_block_epilogue() - def transform(self, fn): for i in range(0, len(self.stmts)): self.stmts[i] = self.stmts[i].transform(fn) diff --git a/ast/branches.py b/ast/branches.py index aa9dcd5..a3ff5f1 100644 --- a/ast/branches.py +++ b/ast/branches.py @@ -36,17 +36,6 @@ class Branch: return [self.cond, self.block_if] + \ ([] if self.block_else is None else [self.block_else]) - def generate(self): - cond_gen = self.cond.generate() - self.sim.code_gen.generate_if(cond_gen) - self.block_if.generate() - - if self.block_else is not None: - self.sim.code_gen.generate_else() - self.block_else.generate() - - self.sim.code_gen.generate_endif() - def transform(self, fn): self.cond = self.cond.transform(fn) self.block_if = self.block_if.transform(fn) diff --git a/ast/cast.py b/ast/cast.py index aa10180..8036676 100644 --- a/ast/cast.py +++ b/ast/cast.py @@ -28,9 +28,6 @@ class Cast: def children(self): return [self.expr] - def generate(self, mem=False, index=None): - return self.sim.code_gen.generate_cast(self.cast_type, self.expr.generate()) - def transform(self, fn): self.expr = self.expr.transform(fn) return fn(self) diff --git a/ast/expr.py b/ast/expr.py index 723759f..371ca0e 100644 --- a/ast/expr.py +++ b/ast/expr.py @@ -15,29 +15,6 @@ class BinOpDef: def children(self): return [self.bin_op] - def generate(self, mem=False): - bin_op = self.bin_op - - if not isinstance(bin_op, BinOp): - return None - - if bin_op.inlined is False and bin_op.operator() != '[]' and bin_op.generated is False: - if bin_op.kind() == BinOp.Kind_Scalar: - lhs = bin_op.lhs.generate(bin_op.mem) - rhs = bin_op.rhs.generate() - bin_op.sim.code_gen.generate_expr(bin_op.id(), bin_op.type(), lhs, rhs, bin_op.op) - - elif bin_op.kind() == BinOp.Kind_Vector: - for i in bin_op.vector_indexes(): - lhs = bin_op.lhs.generate(bin_op.mem, index=i) - rhs = bin_op.rhs.generate(index=i) - bin_op.sim.code_gen.generate_vec_expr(bin_op.id(), i, lhs, rhs, bin_op.operator(), bin_op.mem) - - else: - raise Exception("Invalid BinOp kind!") - - bin_op.generated = True - def transform(self, fn): self.bin_op = self.bin_op.transform(fn) return fn(self) @@ -224,6 +201,9 @@ class BinOp: def type(self): return self.bin_op_type + def definition(self): + return self.bin_op_def + def operator(self): return self.op @@ -244,32 +224,6 @@ class BinOp: def children(self): return [self.lhs, self.rhs] - def generate(self, mem=False, index=None): - if isinstance(self.lhs, BinOp) and self.lhs.kind() == BinOp.Kind_Vector and self.op == '[]': - return self.lhs.generate(self.mem, self.rhs.generate()) - - lhs = self.lhs.generate(mem, index) - rhs = self.rhs.generate(index=index) - - if self.op == '[]': - idx = self.mapped_vector_index(index).generate() if self.is_vector_property_access() else rhs - return self.sim.code_gen.generate_expr_access(lhs, idx, self.mem) - - if self.inlined is True: - assert self.bin_op_type != Type_Vector, "Vector operations cannot be inlined!" - return self.sim.code_gen.generate_inline_expr(lhs, rhs, self.op) - - # Some expressions can be defined on-the-fly during transformations, hence they do not have - # a definition statement, so we generate them right before usage - if not self.generated: - self.bin_op_def.generate() - - if self.kind() == BinOp.Kind_Vector: - assert index is not None, "Index must be set for vector reference!" - return self.sim.code_gen.generate_vec_expr_ref(self.id(), index, self.mem) - - return self.sim.code_gen.generate_expr_ref(self.id()) - def transform(self, fn): self.lhs = self.lhs.transform(fn) self.rhs = self.rhs.transform(fn) diff --git a/ast/lit.py b/ast/lit.py index 58b25a7..b04a969 100644 --- a/ast/lit.py +++ b/ast/lit.py @@ -57,9 +57,5 @@ class Lit: def children(self): return [] - def generate(self, mem=False, index=None): - assert mem is False, "Literal is not lvalue!" - return self.value - def transform(self, fn): return fn(self) diff --git a/ast/loops.py b/ast/loops.py index bd81620..96ccca0 100644 --- a/ast/loops.py +++ b/ast/loops.py @@ -17,6 +17,9 @@ class Iter(): self.loop = loop self.iter_id = Iter.new_id() + def id(self): + return self.iter_id + def type(self): return Type_Int @@ -62,10 +65,6 @@ class Iter(): def children(self): return [] - def generate(self, mem=False, index=None): - assert mem is False, "Iterator is not lvalue!" - return f"i{self.iter_id}" - def transform(self, fn): return fn(self) @@ -97,14 +96,6 @@ class For(): def children(self): return [self.iterator, self.block] - def generate(self): - it_id = self.iterator.generate() - rmin = self.min.generate() - rmax = self.max.generate() - self.sim.code_gen.generate_for_preamble(it_id, rmin, rmax) - self.block.generate() - self.sim.code_gen.generate_for_epilogue() - def transform(self, fn): self.iterator = self.iterator.transform(fn) self.block = self.block.transform(fn) @@ -119,12 +110,6 @@ class ParticleFor(For): def __str__(self): return f"ParticleFor<>" - def generate(self): - upper_range = self.sim.nlocal if self.local_only else self.sim.nlocal + self.sim.pbc.npbc - self.sim.code_gen.generate_for_preamble(self.iterator.generate(), 0, upper_range.generate()) - self.block.generate() - self.sim.code_gen.generate_for_epilogue() - class While(): def __init__(self, sim, cond, block=None): @@ -149,11 +134,6 @@ class While(): def children(self): return [self.cond, self.block] - def generate(self): - self.sim.code_gen.generate_while_preamble(self.cond.generate()) - self.block.generate() - self.sim.code_gen.generate_while_epilogue() - def transform(self, fn): self.cond = self.cond.transform(fn) self.block = self.block.transform(fn) diff --git a/ast/math.py b/ast/math.py index 656543c..cc38fb8 100644 --- a/ast/math.py +++ b/ast/math.py @@ -21,9 +21,6 @@ class Sqrt: def children(self): return [self.expr] - def generate(self, mem=False, index=None): - return self.sim.code_gen.generate_sqrt(self.expr.generate()) - def transform(self, fn): self.expr = self.expr.transform(fn) return fn(self) diff --git a/ast/memory.py b/ast/memory.py index 205bd44..bb26d4c 100644 --- a/ast/memory.py +++ b/ast/memory.py @@ -5,22 +5,18 @@ import operator class Malloc: - def __init__(self, sim, array, a_type, sizes, decl=False): + def __init__(self, sim, array, sizes, decl=False): self.sim = sim self.parent_block = None self.array = array - self.array_type = a_type self.decl = decl - self.prim_size = Sizeof(sim, a_type) + self.prim_size = Sizeof(sim, array.type()) self.size = BinOp.inline(self.prim_size * (reduce(operator.mul, sizes) if isinstance(sizes, list) else sizes)) self.sim.add_statement(self) def children(self): return [self.array, self.size] - def generate(self, mem=False, index=None): - self.sim.code_gen.generate_malloc(self.array.generate(), self.array_type, self.size.generate(), self.decl) - def transform(self, fn): self.array = self.array.transform(fn) self.size = self.size.transform(fn) @@ -28,21 +24,17 @@ class Malloc: class Realloc: - def __init__(self, sim, array, a_type, size): + def __init__(self, sim, array, size): self.sim = sim self.parent_block = None self.array = array - self.array_type = a_type - self.prim_size = Sizeof(sim, a_type) + self.prim_size = Sizeof(sim, array.type()) self.size = BinOp.inline(self.prim_size * size) self.sim.add_statement(self) def children(self): return [self.array, self.size] - def generate(self, mem=False, index=None): - self.sim.code_gen.generate_realloc(self.array.generate(), self.array_type, self.size.generate()) - def transform(self, fn): self.array = self.array.transform(fn) self.size = self.size.transform(fn) diff --git a/ast/properties.py b/ast/properties.py index 0c6b2a4..bbb6465 100644 --- a/ast/properties.py +++ b/ast/properties.py @@ -77,8 +77,5 @@ class Property: def children(self): return [] - def generate(self, mem=False, index=None): - return self.prop_name - def transform(self, fn): return fn(self) diff --git a/ast/select.py b/ast/select.py index 8ba489c..bdb1546 100644 --- a/ast/select.py +++ b/ast/select.py @@ -12,9 +12,6 @@ class Select: def children(self): return [self.cond, self.expr_if, self.expr_else] - def generate(self): - return self.sim.code_gen.generate_select(self.cond.generate(), self.expr_if.generate(), self.expr_else.generate()) - def transform(self, fn): self.cond = self.cond.transform(fn) self.expr_if = self.expr_if.transform(fn) diff --git a/ast/sizeof.py b/ast/sizeof.py index ee25987..e18f89e 100644 --- a/ast/sizeof.py +++ b/ast/sizeof.py @@ -22,8 +22,5 @@ class Sizeof: def children(self): return [] - def generate(self, mem=False, index=None): - return self.sim.code_gen.generate_sizeof(self.data_type) - def transform(self, fn): return fn(self) diff --git a/ast/utils.py b/ast/utils.py index 55d630b..922dcbe 100644 --- a/ast/utils.py +++ b/ast/utils.py @@ -9,8 +9,5 @@ class Print: def children(self): return [] - def generate(self): - self.sim.code_gen.generate_print(self.string) - def transform(self, fn): return fn(self) diff --git a/ast/variables.py b/ast/variables.py index 9604b28..5f12719 100644 --- a/ast/variables.py +++ b/ast/variables.py @@ -104,9 +104,6 @@ class Var: def children(self): return [] - def generate(self, mem=False, index=None): - return self.var_name - def transform(self, fn): return fn(self) @@ -120,9 +117,5 @@ class VarDecl: def children(self): return [] - def generate(self, mem=False, index=None): - self.sim.code_gen.generate_var_decl( - self.var.name(), self.var.type(), self.var.init_value()) - def transform(self, fn): return fn(self) diff --git a/code_gen/cgen.py b/code_gen/cgen.py index 6482e91..96e0d9d 100644 --- a/code_gen/cgen.py +++ b/code_gen/cgen.py @@ -1,4 +1,21 @@ +from ast.assign import Assign +from ast.arrays import ArrayAccess, ArrayDecl +from ast.block import Block +from ast.branches import Branch +from ast.cast import Cast +from ast.expr import BinOp, BinOpDef from ast.data_types import Type_Int, Type_Float, Type_Vector +from ast.lit import Lit +from ast.loops import For, Iter, ParticleFor, While +from ast.math import Sqrt +from ast.memory import Malloc, Realloc +from ast.properties import Property +from ast.select import Select +from ast.sizeof import Sizeof +from ast.utils import Print +from ast.variables import Var, VarDecl +from sim.timestep import Timestep +from sim.vtk import VTKWrite from code_gen.printer import printer @@ -10,170 +27,261 @@ class CGen: else 'bool' ) - def generate_program_preamble(): + def generate_program(sim, ast_node): printer.print("#include <stdio.h>") printer.print("#include <stdlib.h>") printer.print("#include <stdbool.h>") printer.print("") printer.print("int main() {") - - def generate_program_epilogue(): - printer.print("}") - - def generate_block_preamble(): - printer.add_ind(4) - - def generate_block_epilogue(): - printer.add_ind(-4) - - def generate_cast(ctype, expr): - tkw = CGen.type2keyword(ctype) - return f"({tkw})({expr})" - - def generate_if(cond): - printer.print(f"if({cond}) {{") - - def generate_else(): - printer.print("} else {") - - def generate_endif(): - printer.print("}") - - def generate_assignment(dest, src): - printer.print(f"{dest} = {src};") - - def generate_array_decl(array, a_type, size): - tkw = CGen.type2keyword(a_type) - printer.print(f"{tkw} {array}[{size}];") - - def generate_array_access_ref(acc_id, array, index, mem=False): - if mem: - return f"{array}[{index}]" - - return f"a{acc_id}" - - def generate_array_access(acc_id, acc_type, array, index): - ref = CGen.generate_array_access_ref(acc_id, array, index) - tkw = CGen.type2keyword(acc_type) - acc = f"const {tkw} {ref} = {array}[{index}];" - printer.print(acc) - - def generate_malloc(array, a_type, size, decl): - tkw = CGen.type2keyword(a_type) - if decl: - printer.print(f"{tkw} *{array} = ({tkw} *) malloc({size});") - else: - printer.print(f"{array} = ({tkw} *) malloc({size});") - - def generate_realloc(array, a_type, size): - tkw = CGen.type2keyword(a_type) - printer.print(f"{array} = ({tkw} *) realloc({array}, {size});") - - def generate_sizeof(data_type): - tkw = CGen.type2keyword(data_type) - return f"sizeof({tkw})" - - def generate_for_preamble(iter_id, rmin, rmax): - printer.print(f"for(int {iter_id} = {rmin}; {iter_id} < {rmax}; {iter_id}++) {{") - - def generate_for_epilogue(): + CGen.generate_statement(sim, ast_node) printer.print("}") - def generate_while_preamble(cond): - printer.print(f"while({cond}) {{") - - def generate_while_epilogue(): - printer.print("}") - - def generate_expr_ref(expr_id): - return f"e{expr_id}" - - def generate_expr(expr_id, expr_type, lhs, rhs, op): - ref = CGen.generate_expr_ref(expr_id) - tkw = CGen.type2keyword(expr_type) - printer.print(f"const {tkw} {ref} = {lhs} {op} {rhs};") - - def generate_expr_access(lhs, rhs, mem): - return f"{lhs}[{rhs}]" if mem else f"{lhs}_{rhs}" + def generate_statement(sim, ast_node): + if isinstance(ast_node, ArrayDecl): + tkw = CGen.type2keyword(ast_node.array.type()) + size = CGen.generate_expression(sim, BinOp.inline(ast_node.array.alloc_size())) + printer.print(f"{tkw} {ast_node.array.name()}[{size}];") - def generate_vec_expr_ref(expr_id, index, mem): - return f"e{expr_id}[{index}]" if mem else f"e{expr_id}_{index}" + if isinstance(ast_node, Assign): + for assign_dest, assign_src in ast_node.assignments: + dest = CGen.generate_expression(sim, assign_dest, mem=True) + src = CGen.generate_expression(sim, assign_src) + printer.print(f"{dest} = {src};") + + if isinstance(ast_node, Block): + printer.add_ind(4) + + for stmt in ast_node.statements(): + CGen.generate_statement(sim, stmt) + + printer.add_ind(-4) + + if isinstance(ast_node, BinOpDef): + bin_op = ast_node.bin_op + + if not isinstance(bin_op, BinOp): + return None + + if bin_op.inlined is False and bin_op.operator() != '[]' and bin_op.generated is False: + if bin_op.kind() == BinOp.Kind_Scalar: + lhs = CGen.generate_expression(sim, bin_op.lhs, bin_op.mem) + rhs = CGen.generate_expression(sim, bin_op.rhs) + tkw = CGen.type2keyword(bin_op.type()) + printer.print(f"const {tkw} e{bin_op.id()} = {lhs} {bin_op.operator()} {rhs};") + + elif bin_op.kind() == BinOp.Kind_Vector: + for i in bin_op.vector_indexes(): + lhs = CGen.generate_expression(sim, bin_op.lhs, bin_op.mem, index=i) + rhs = CGen.generate_expression(sim, bin_op.rhs, index=i) + printer.print(f"const double e{bin_op.id()}_{i} = {lhs} {bin_op.operator()} {rhs};") + + else: + raise Exception("Invalid BinOp kind!") - def generate_vec_expr(expr_id, index, lhs, rhs, op, mem): - ref = CGen.generate_vec_expr_ref(expr_id, index, mem) - printer.print(f"const double {ref} = {lhs} {op} {rhs};") + bin_op.generated = True + + if isinstance(ast_node, Branch): + cond = CGen.generate_expression(sim, ast_node.cond) + printer.print(f"if({cond}) {{") + CGen.generate_statement(sim, ast_node.block_if) + + if ast_node.block_else is not None: + printer.print("} else {") + CGen.generate_statement(sim, ast_node.block_else) + + printer.print("}") + + if isinstance(ast_node, For): + iterator = CGen.generate_expression(sim, ast_node.iterator) + lower_range = None + upper_range = None + + if isinstance(ast_node, ParticleFor): + n = sim.nlocal if ast_node.local_only else sim.nlocal + sim.pbc.npbc + lower_range = 0 + upper_range = CGen.generate_expression(sim, n) + + else: + lower_range = CGen.generate_expression(sim, ast_node.min) + upper_range = CGen.generate_expression(sim, ast_node.max) + + printer.print(f"for(int {iterator} = {lower_range}; {iterator} < {upper_range}; {iterator}++) {{") + CGen.generate_statement(sim, ast_node.block) + printer.print("}") - def generate_inline_expr(lhs, rhs, op): - return f"({lhs} {op} {rhs})" - def generate_var_decl(v_name, v_type, v_value): - tkw = CGen.type2keyword(v_type) - printer.print(f"{tkw} {v_name} = {v_value};") - - def generate_sqrt(expr): - return f"sqrt({expr})" - - def generate_select(cond, expr_if, expr_else): - return f"({cond}) ? ({expr_if}) : ({expr_else})" - - def generate_print(string): - printer.print(f"fprintf(stdout, \"{string}\\n\");") - printer.print(f"fflush(stdout);") - - def generate_vtk_writing(id, filename, start, n, timestep): + if isinstance(ast_node, Malloc): + tkw = CGen.type2keyword(ast_node.array.type()) + size = CGen.generate_expression(sim, ast_node.size) + array_name = ast_node.array.name() + + if ast_node.decl: + printer.print(f"{tkw} *{array_name} = ({tkw} *) malloc({size});") + else: + printer.print(f"{array_name} = ({tkw} *) malloc({size});") + + if isinstance(ast_node, Print): + printer.print(f"fprintf(stdout, \"{ast_node.string}\\n\");") + printer.print(f"fflush(stdout);") + + if isinstance(ast_node, Realloc): + tkw = CGen.type2keyword(ast_node.array.type()) + size = CGen.generate_expression(sim, ast_node.size) + array_name = ast_node.array.name() + printer.print(f"{array_name} = ({tkw} *) realloc({array_name}, {size});") + + if isinstance(ast_node, Timestep): + CGen.generate_statement(sim, ast_node.block) + + if isinstance(ast_node, VarDecl): + tkw = CGen.type2keyword(ast_node.var.type()) + printer.print(f"{tkw} {ast_node.var.name()} = {ast_node.var.init_value()};") + + if isinstance(ast_node, VTKWrite): + nlocal = CGen.generate_expression(sim, sim.nlocal) + npbc = CGen.generate_expression(sim, sim.pbc.npbc) + nall = CGen.generate_expression(sim, sim.nlocal + sim.pbc.npbc) + timestep = CGen.generate_expression(sim, ast_node.timestep) + CGen.generate_vtk_writing(ast_node.vtk_id * 2, f"{ast_node.filename}_local", 0, nlocal, nlocal, timestep) + CGen.generate_vtk_writing(ast_node.vtk_id * 2 + 1, f"{ast_node.filename}_pbc", nlocal, nall, npbc, timestep) + + if isinstance(ast_node, While): + cond = CGen.generate_expression(sim, ast_node.cond) + printer.print(f"while({cond}) {{") + CGen.generate_statement(sim, ast_node.block) + printer.print("}") + + def generate_expression(sim, ast_node, mem=False, index=None): + if isinstance(ast_node, ArrayAccess): + index = CGen.generate_expression(sim, ast_node.index) + array_name = ast_node.array.name() + + if mem: + return f"{array_name}[{index}]" + + acc_ref = f"a{ast_node.id()}" + if ast_node.generated is False: + tkw = CGen.type2keyword(ast_node.type()) + printer.print(f"const {tkw} {acc_ref} = {array_name}[{index}];") + ast_node.generated = True + + return acc_ref + + if isinstance(ast_node, BinOp): + if isinstance(ast_node.lhs, BinOp) and ast_node.lhs.kind() == BinOp.Kind_Vector and ast_node.operator() == '[]': + return CGen.generate_expression(sim, ast_node.lhs, ast_node.mem, CGen.generate_expression(sim, ast_node.rhs)) + + lhs = CGen.generate_expression(sim, ast_node.lhs, mem, index) + rhs = CGen.generate_expression(sim, ast_node.rhs, index=index) + + if ast_node.operator() == '[]': + idx = CGen.generate_expression(sim, ast_node.mapped_vector_index(index)) if ast_node.is_vector_property_access() else rhs + return f"{lhs}[{idx}]" if ast_node.mem else f"{lhs}_{idx}" + + if ast_node.inlined is True: + assert ast_node.type() != Type_Vector, "Vector operations cannot be inlined!" + return f"({lhs} {ast_node.operator()} {rhs})" + + # Some expressions can be defined on-the-fly during transformations, hence they do not have + # a definition statement in the tree, so we generate them right before usage + if not ast_node.generated: + CGen.generate_statement(sim, ast_node.definition()) + + if ast_node.kind() == BinOp.Kind_Vector: + assert index is not None, "Index must be set for vector reference!" + return f"e{ast_node.id()}[{index}]" if ast_node.mem else f"e{ast_node.id()}_{index}" + + return f"e{ast_node.id()}" + + if isinstance(ast_node, Cast): + tkw = CGen.type2keyword(ast_node.cast_type) + expr = CGen.generate_expression(sim, ast_node.expr) + return f"({tkw})({expr})" + + if isinstance(ast_node, Iter): + assert mem is False, "Iterator is not lvalue!" + return f"i{ast_node.id()}" + + if isinstance(ast_node, Lit): + assert mem is False, "Literal is not lvalue!" + return ast_node.value + + if isinstance(ast_node, Property): + return ast_node.name() + + if isinstance(ast_node, Sizeof): + assert mem is False, "Sizeof expression is not lvalue!" + tkw = CGen.type2keyword(ast_node.data_type) + return f"sizeof({tkw})" + + if isinstance(ast_node, Sqrt): + assert mem is False, "Square root call is not lvalue!" + expr = CGen.generate_expression(sim, ast_node.expr) + return f"sqrt({expr})" + + if isinstance(ast_node, Select): + assert mem is False, "Select expression is not lvalue!" + cond = CGen.generate_expression(sim, ast_node.cond) + expr_if = CGen.generate_expression(sim, ast_node.expr_if) + expr_else = CGen.generate_expression(sim, ast_node.expr_else) + return f"({cond}) ? ({expr_if}) : ({expr_else})" + + if isinstance(ast_node, Var): + return ast_node.name() + + def generate_vtk_writing(id, filename, start, end, n, timestep): # TODO: Do this in a more elegant way, without hard coded stuff header = "# vtk DataFile Version 2.0\n" \ "Particle data\n" \ "ASCII\n" \ "DATASET UNSTRUCTURED_GRID\n" - end = start + n filename_var = f"filename{id}" filehandle_var = f"vtk{id}" printer.print(f"char {filename_var}[128];") - printer.print(f"snprintf({filename_var}, sizeof {filename_var}, \"{filename}_%d.vtk\", {timestep.generate()});") + printer.print(f"snprintf({filename_var}, sizeof {filename_var}, \"{filename}_%d.vtk\", {timestep});") printer.print(f"FILE *{filehandle_var} = fopen({filename_var}, \"w\");") for line in header.split('\n'): if len(line) > 0: printer.print(f"fwrite(\"{line}\\n\", 1, {len(line) + 1}, {filehandle_var});") # Write positions - printer.print(f"fprintf({filehandle_var}, \"POINTS %d double\\n\", {n.generate()});") - CGen.generate_for_preamble("i", start.generate(), end.generate()) + printer.print(f"fprintf({filehandle_var}, \"POINTS %d double\\n\", {n});") + printer.print(f"for(int i = {start}; i < {end}; i++) {{") printer.add_ind(4) printer.print(f"fprintf({filehandle_var}, \"%.4f %.4f %.4f\\n\", position[i * 3], position[i * 3 + 1], position[i * 3 + 2]);") printer.add_ind(-4) - CGen.generate_for_epilogue() + printer.print("}") printer.print(f"fwrite(\"\\n\\n\", 1, 2, {filehandle_var});") # Write cells - printer.print(f"fprintf({filehandle_var}, \"CELLS %d %d\\n\", {n.generate()}, {n.generate()} * 2);") - CGen.generate_for_preamble("i", start.generate(), end.generate()) + printer.print(f"fprintf({filehandle_var}, \"CELLS %d %d\\n\", {n}, {n} * 2);") + printer.print(f"for(int i = {start}; i < {end}; i++) {{") printer.add_ind(4) - printer.print(f"fprintf({filehandle_var}, \"1 %d\\n\", i - {start.generate()});") + printer.print(f"fprintf({filehandle_var}, \"1 %d\\n\", i - {start});") printer.add_ind(-4) - CGen.generate_for_epilogue() + printer.print("}") printer.print(f"fwrite(\"\\n\\n\", 1, 2, {filehandle_var});") # Write cell types - printer.print(f"fprintf({filehandle_var}, \"CELL_TYPES %d\\n\", {n.generate()});") - CGen.generate_for_preamble("i", start.generate(), end.generate()) + printer.print(f"fprintf({filehandle_var}, \"CELL_TYPES %d\\n\", {n});") + printer.print(f"for(int i = {start}; i < {end}; i++) {{") printer.add_ind(4) printer.print(f"fwrite(\"1\\n\", 1, 2, {filehandle_var});") printer.add_ind(-4) - CGen.generate_for_epilogue() + printer.print("}") printer.print(f"fwrite(\"\\n\\n\", 1, 2, {filehandle_var});") # Write masses - printer.print(f"fprintf({filehandle_var}, \"POINT_DATA %d\\n\", {n.generate()});") + printer.print(f"fprintf({filehandle_var}, \"POINT_DATA %d\\n\", {n});") printer.print(f"fprintf({filehandle_var}, \"SCALARS mass double\\n\");") printer.print(f"fprintf({filehandle_var}, \"LOOKUP_TABLE default\\n\");") - CGen.generate_for_preamble("i", start.generate(), end.generate()) + printer.print(f"for(int i = {start}; i < {end}; i++) {{") printer.add_ind(4) #printer.print(f"fprintf({filehandle_var}, \"%4.f\\n\", mass[i]);") printer.print(f"fprintf({filehandle_var}, \"1.0\\n\");") printer.add_ind(-4) - CGen.generate_for_epilogue() + printer.print("}") printer.print(f"fwrite(\"\\n\\n\", 1, 2, {filehandle_var});") printer.print(f"fclose({filehandle_var});") diff --git a/sim/arrays.py b/sim/arrays.py index 000ad3f..0d01954 100644 --- a/sim/arrays.py +++ b/sim/arrays.py @@ -12,6 +12,6 @@ class ArraysDecl: if a.is_static(): ArrayDecl(self.sim, a) else: - Malloc(self.sim, a, a.type(), a.alloc_size(), True) + Malloc(self.sim, a, a.alloc_size(), True) return self.sim.block diff --git a/sim/particle_simulation.py b/sim/particle_simulation.py index 5d98291..ddabe68 100644 --- a/sim/particle_simulation.py +++ b/sim/particle_simulation.py @@ -200,6 +200,5 @@ class ParticleSimulation: #Transform.apply(program, Transform.reuse_array_access_expressions) #Transform.apply(program, Transform.move_loop_invariant_expressions) - self.code_gen.generate_program_preamble() - program.generate() - self.code_gen.generate_program_epilogue() + self.code_gen.generate_program(self, program) + diff --git a/sim/properties.py b/sim/properties.py index e9b6791..f07f9d5 100644 --- a/sim/properties.py +++ b/sim/properties.py @@ -26,9 +26,9 @@ class PropertiesAlloc: raise Exception("Invalid property type!") if self.realloc: - Realloc(self.sim, p, p.type(), sizes) + Realloc(self.sim, p, sizes) else: - Malloc(self.sim, p, p.type(), sizes, True) + Malloc(self.sim, p, sizes, True) return self.sim.block diff --git a/sim/resize.py b/sim/resize.py index 7a2d93b..eada642 100644 --- a/sim/resize.py +++ b/sim/resize.py @@ -33,4 +33,4 @@ class Resize: else: sizes = capacity * self.sim.dimensions - Realloc(self.sim, p, p.type(), sizes) + Realloc(self.sim, p, sizes) diff --git a/sim/timestep.py b/sim/timestep.py index 5a67648..86e5c95 100644 --- a/sim/timestep.py +++ b/sim/timestep.py @@ -42,8 +42,5 @@ class Timestep: def as_block(self): return Block(self.sim, [self.timestep_loop]) - def generate(self): - self.block.generate() - def transform(self, fn): self.block = self.block.transform(fn) diff --git a/sim/vtk.py b/sim/vtk.py index 53e4df7..c1620f8 100644 --- a/sim/vtk.py +++ b/sim/vtk.py @@ -5,22 +5,13 @@ class VTKWrite: def __init__(self, sim, filename, timestep): self.sim = sim + self.vtk_id = VTKWrite.vtk_id self.filename = filename self.timestep = as_lit_ast(sim, timestep) + VTKWrite.vtk_id += 1 def children(self): return [] - def generate(self): - self.sim.code_gen.generate_vtk_writing( - VTKWrite.vtk_id * 2, f"{self.filename}_local", - as_lit_ast(self.sim, 0), self.sim.nlocal, self.timestep) - - self.sim.code_gen.generate_vtk_writing( - VTKWrite.vtk_id * 2 + 1, f"{self.filename}_pbc", - self.sim.nlocal, self.sim.pbc.npbc, self.timestep) - - VTKWrite.vtk_id += 1 - def transform(self, fn): return fn(self) -- GitLab