Commit 6858956c authored by dbarbera's avatar dbarbera
Browse files

Added basic internal procedure generation

parent d75f7a61
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
""" """
import logging import logging
from singledispatch import singledispatch from singledispatch import singledispatch
from llvm import core from llvm import core
...@@ -39,7 +40,8 @@ class GlobalState(): ...@@ -39,7 +40,8 @@ class GlobalState():
self.module = core.Module.new(self.name) self.module = core.Module.new(self.name)
self.dataview = process.dataview self.dataview = process.dataview
self.scope = {} self.scope = Scope()
self.global_scope = self.scope
self.states = {} self.states = {}
self.structs = {} self.structs = {}
self.strings = {} self.strings = {}
...@@ -78,6 +80,23 @@ class StructType(): ...@@ -78,6 +80,23 @@ class StructType():
return self.field_names.index(field_name) return self.field_names.index(field_name)
class Scope:
def __init__(self, parent=None):
self.vars = {}
self.parent = parent
def define(self, name, var):
self.vars[name.lower()] = var
def resolve(self, name):
var = self.vars.get(name.lower())
if var:
return var
if self.parent:
return self.parent.resolve(name)
else:
raise NameError
@singledispatch @singledispatch
def generate(ast): def generate(ast):
...@@ -110,12 +129,14 @@ def _process(process): ...@@ -110,12 +129,14 @@ def _process(process):
# Generate state var # Generate state var
state_cons = g.module.add_global_variable(g.i32, 'state') state_cons = g.module.add_global_variable(g.i32, 'state')
state_cons.initializer = core.Constant.int(g.i32, -1) state_cons.initializer = core.Constant.int(g.i32, -1)
g.scope.define('state', state_cons)
# Generare process-level vars # Generare process-level vars
for name, (ty, expr) in process.variables.viewitems(): for name, (ty, expr) in process.variables.viewitems():
var_ty = _generate_type(ty) var_ty = _generate_type(ty)
global_var = g.module.add_global_variable(var_ty, str(name).lower()) global_var = g.module.add_global_variable(var_ty, str(name))
global_var.initializer = core.Constant.null(var_ty) global_var.initializer = core.Constant.null(var_ty)
g.scope.define(str(name).lower(), global_var)
# Initialize output signals # Initialize output signals
for signal in process.output_signals: for signal in process.output_signals:
...@@ -138,7 +159,7 @@ def _process(process): ...@@ -138,7 +159,7 @@ def _process(process):
# Generate internal procedures # Generate internal procedures
for proc in process.content.inner_procedures: for proc in process.content.inner_procedures:
raise NotImplementedError generate(proc)
# Generate process functions # Generate process functions
_generate_runtr_func(process) _generate_runtr_func(process)
...@@ -161,6 +182,8 @@ def _generate_runtr_func(process): ...@@ -161,6 +182,8 @@ def _generate_runtr_func(process):
func = core.Function.new(g.module, func_type, func_name) func = core.Function.new(g.module, func_type, func_name)
g.funcs[func_name] = func g.funcs[func_name] = func
_push_scope()
entry_block = func.append_basic_block('entry') entry_block = func.append_basic_block('entry')
cond_block = func.append_basic_block('cond') cond_block = func.append_basic_block('cond')
body_block = func.append_basic_block('body') body_block = func.append_basic_block('body')
...@@ -170,7 +193,7 @@ def _generate_runtr_func(process): ...@@ -170,7 +193,7 @@ def _generate_runtr_func(process):
# entry # entry
id_ptr = g.builder.alloca(g.i32, None, 'id') id_ptr = g.builder.alloca(g.i32, None, 'id')
g.scope['id'] = id_ptr g.scope.define('id', id_ptr)
g.builder.store(func.args[0], id_ptr) g.builder.store(func.args[0], id_ptr)
g.builder.branch(cond_block) g.builder.branch(cond_block)
...@@ -198,8 +221,9 @@ def _generate_runtr_func(process): ...@@ -198,8 +221,9 @@ def _generate_runtr_func(process):
g.builder.position_at_end(exit_block) g.builder.position_at_end(exit_block)
g.builder.ret_void() g.builder.ret_void()
_pop_scope()
func.verify() func.verify()
g.scope.clear()
return func return func
...@@ -210,18 +234,22 @@ def _generate_startup_func(process): ...@@ -210,18 +234,22 @@ def _generate_startup_func(process):
func = core.Function.new(g.module, func_type, func_name) func = core.Function.new(g.module, func_type, func_name)
g.funcs[func_name] = func g.funcs[func_name] = func
_push_scope()
entry_block = func.append_basic_block('entry') entry_block = func.append_basic_block('entry')
g.builder = core.Builder.new(entry_block) g.builder = core.Builder.new(entry_block)
# Initialize process level variables # Initialize process level variables
for name, (ty, expr) in process.variables.viewitems(): for name, (ty, expr) in process.variables.viewitems():
if expr: if expr:
global_var = g.module.get_global_variable_named(str(name).lower()) global_var = _resolve(str(name))
_generate_assign(global_var, expression(expr)) _generate_assign(global_var, expression(expr))
g.builder.call(g.funcs['run_transition'], [core.Constant.int(g.i32, 0)]) g.builder.call(g.funcs['run_transition'], [core.Constant.int(g.i32, 0)])
g.builder.ret_void() g.builder.ret_void()
_pop_scope()
func.verify() func.verify()
return func return func
...@@ -236,13 +264,13 @@ def _generate_input_signal(signal, inputs): ...@@ -236,13 +264,13 @@ def _generate_input_signal(signal, inputs):
func = core.Function.new(g.module, func_type, func_name) func = core.Function.new(g.module, func_type, func_name)
g.funcs[func_name.lower()] = func g.funcs[func_name.lower()] = func
_push_scope()
entry_block = func.append_basic_block('entry') entry_block = func.append_basic_block('entry')
exit_block = func.append_basic_block('exit') exit_block = func.append_basic_block('exit')
g.builder = core.Builder.new(entry_block) g.builder = core.Builder.new(entry_block)
runtr_func = g.module.get_function_named('run_transition') g_state_val = g.builder.load(g.global_scope.resolve('state'))
g_state_val = g.builder.load(g.module.get_global_variable_named('state'))
switch = g.builder.switch(g_state_val, exit_block) switch = g.builder.switch(g_state_val, exit_block)
for state_name, state_id in g.states.iteritems(): for state_name, state_id in g.states.iteritems():
...@@ -255,17 +283,19 @@ def _generate_input_signal(signal, inputs): ...@@ -255,17 +283,19 @@ def _generate_input_signal(signal, inputs):
input = inputs.get(state_name) input = inputs.get(state_name)
if input: if input:
for var_name in input.parameters: for var_name in input.parameters:
var_val = g.module.get_global_variable_named(str(var_name).lower()) var_val = g.scope.resolve(str(var_name))
_generate_assign(var_val, func.args[0]) _generate_assign(var_val, func.args[0])
if input.transition: if input.transition:
id_val = core.Constant.int(g.i32, input.transition_id) id_val = core.Constant.int(g.i32, input.transition_id)
g.builder.call(runtr_func, [id_val]) g.builder.call(g.funcs['run_transition'], [id_val])
g.builder.ret_void() g.builder.ret_void()
g.builder.position_at_end(exit_block) g.builder.position_at_end(exit_block)
g.builder.ret_void() g.builder.ret_void()
_pop_scope()
func.verify() func.verify()
...@@ -273,7 +303,7 @@ def _generate_input_signal(signal, inputs): ...@@ -273,7 +303,7 @@ def _generate_input_signal(signal, inputs):
@generate.register(ogAST.ProcedureCall) @generate.register(ogAST.ProcedureCall)
def _call_external_function(output): def _call_external_function(output):
''' Generate the code of a set of output or procedure call statement ''' ''' Generate the code of a set of output or procedure call statement '''
zero = core.Constant.int(g.i32, 0)
for out in output.output: for out in output.output:
name = out['outputName'].lower() name = out['outputName'].lower()
...@@ -291,7 +321,19 @@ def _call_external_function(output): ...@@ -291,7 +321,19 @@ def _call_external_function(output):
continue continue
func = g.funcs[str(name).lower()] func = g.funcs[str(name).lower()]
g.builder.call(func, [expression(p) for p in out.get('params', [])])
params = []
for p in out.get('params', []):
p_val = expression(p)
# Pass by reference
if p_val.type.kind != core.TYPE_POINTER:
p_var = g.builder.alloca(p_val.type, None)
g.builder.store(p_val, p_var)
params.append(p_var)
else:
params.append(p_val)
g.builder.call(func, params)
def _generate_write(params): def _generate_write(params):
...@@ -376,14 +418,14 @@ def expression(expr): ...@@ -376,14 +418,14 @@ def expression(expr):
@expression.register(ogAST.PrimVariable) @expression.register(ogAST.PrimVariable)
def _primary_variable(prim): def _primary_variable(prim):
''' Generate the code for a single variable reference ''' ''' Generate the code for a single variable reference '''
return g.module.get_global_variable_named(str(prim.value[0]).lower()) return g.scope.resolve(str(prim.value[0]))
@expression.register(ogAST.PrimPath) @expression.register(ogAST.PrimPath)
def _prim_path(prim): def _prim_path(prim):
''' Generate the code for an of an element list (path) ''' ''' Generate the code for an of an element list (path) '''
var_ptr = g.module.get_global_variable_named(str(prim.value.pop(0)).lower()) var_ptr = g.scope.resolve(str(prim.value.pop(0)))
if not prim.value: if not prim.value:
return var_ptr return var_ptr
...@@ -719,16 +761,15 @@ def _transition(tr): ...@@ -719,16 +761,15 @@ def _transition(tr):
def _generate_terminator(term): def _generate_terminator(term):
''' Generate the code for a transition termiantor ''' ''' Generate the code for a transition termiantor '''
id_ptr = g.scope['id']
if term.label: if term.label:
raise NotImplementedError raise NotImplementedError
if term.kind == 'next_state': if term.kind == 'next_state':
state = term.inputString.lower() state = term.inputString.lower()
if state.strip() != '-': if state.strip() != '-':
next_id_cons = core.Constant.int(g.i32, term.next_id) next_id_cons = core.Constant.int(g.i32, term.next_id)
g.builder.store(next_id_cons, id_ptr) g.builder.store(next_id_cons, g.scope.resolve('id'))
if term.next_id == -1: if term.next_id == -1:
state_ptr = g.module.get_global_variable_named('state') state_ptr = g.global_scope.resolve('state')
state_id_cons = g.states[state] state_id_cons = g.states[state]
g.builder.store(state_id_cons, state_ptr) g.builder.store(state_id_cons, state_ptr)
else: else:
...@@ -738,7 +779,14 @@ def _generate_terminator(term): ...@@ -738,7 +779,14 @@ def _generate_terminator(term):
elif term.kind == 'stop': elif term.kind == 'stop':
raise NotImplementedError raise NotImplementedError
elif term.kind == 'return': elif term.kind == 'return':
raise NotImplementedError if term.next_id == -1 and term.return_expr:
g.builder.ret(expression(term.return_expr))
elif term.next_id == -1:
g.builder.ret_void()
else:
next_id_cons = core.Constant.int(g.i32, term.next_id)
g.builder.store(next_id_cons, g.scope.resolve('id'))
g.builder.ret_void()
@generate.register(ogAST.Floating_label) @generate.register(ogAST.Floating_label)
...@@ -750,7 +798,31 @@ def _floating_label(label): ...@@ -750,7 +798,31 @@ def _floating_label(label):
@generate.register(ogAST.Procedure) @generate.register(ogAST.Procedure)
def _inner_procedure(proc): def _inner_procedure(proc):
''' Generate the code for a procedure ''' ''' Generate the code for a procedure '''
raise NotImplementedError func_name = str(proc.inputString)
param_tys = [core.Type.pointer(_generate_type(p['type'])) for p in proc.fpar]
func_ty = core.Type.function(g.void, param_tys)
func = core.Function.new(g.module, func_ty, func_name)
g.funcs[func_name] = func
_push_scope()
for arg, param in zip(func.args, proc.fpar):
g.scope.define(str(param['name']), arg)
entry_block = func.append_basic_block('entry')
g.builder = core.Builder.new(entry_block)
for name, (ty, expr) in proc.variables.viewitems():
raise NotImplementedError
generate(proc.content.start.transition)
for label in proc.content.floating_labels:
raise NotImplementedError
_pop_scope()
func.verify()
def _generate_type(ty): def _generate_type(ty):
...@@ -795,6 +867,16 @@ def _generate_type(ty): ...@@ -795,6 +867,16 @@ def _generate_type(ty):
raise NotImplementedError raise NotImplementedError
def _push_scope():
''' Push a new scope '''
g.scope = Scope(g.scope)
def _pop_scope():
''' Pop the current scope '''
g.scope = g.scope.parent
def _get_string_cons(str): def _get_string_cons(str):
''' Returns a reference to a global string constant with the given value ''' ''' Returns a reference to a global string constant with the given value '''
if str in g.strings: if str in g.strings:
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment