Commit 3262b570 authored by dbarbera's avatar dbarbera
Browse files

Renamed global context variable

parent cb659277
......@@ -31,7 +31,7 @@ __all__ = ['generate']
# Global context
g = None
ctx = None
class Context():
......@@ -106,8 +106,8 @@ class UnionType():
self.field_types = field_types
# Unions are represented a struct with a field indicating the index of its type
# and a byte array with the size of the biggest type in the union
self.size = max([g.target_data.size(ty) for ty in field_types])
self.ty = core.Type.struct([g.i32, core.Type.array(g.i8, self.size)], name)
self.size = max([ctx.target_data.size(ty) for ty in field_types])
self.ty = core.Type.struct([ctx.i32, core.Type.array(ctx.i8, self.size)], name)
def kind(self, name):
idx = self.field_names.index(name)
......@@ -136,7 +136,7 @@ class Scope:
name = name.lower()
label_block = self.labels.get(name)
if not label_block:
func = g.builder.basic_block.function
func = ctx.builder.basic_block.function
label_block = func.append_basic_block(name)
self.labels[name] = label_block
return label_block
......@@ -155,8 +155,8 @@ def _process(process):
process_name = str(process.processName)
LOG.info('Generating LLVM IR code for process ' + process_name)
global g
g = Context(process)
global ctx
ctx = Context(process)
# In case model has nested states, flatten everything
Helper.flatten(process)
......@@ -168,29 +168,29 @@ def _process(process):
# Initialize states
for name, val in process.mapping.viewitems():
if not name.endswith('START'):
cons_val = core.Constant.int(g.i32, len(g.states))
g.states[name] = cons_val
cons_val = core.Constant.int(ctx.i32, len(ctx.states))
ctx.states[name] = cons_val
elif name != 'START':
cons_val = core.Constant.int(g.i32, val)
g.states[name] = cons_val
cons_val = core.Constant.int(ctx.i32, val)
ctx.states[name] = cons_val
# Generate state var
state_cons = g.module.add_global_variable(g.i32, 'state')
state_cons.initializer = core.Constant.int(g.i32, -1)
g.scope.define('state', state_cons)
state_cons = ctx.module.add_global_variable(ctx.i32, 'state')
state_cons.initializer = core.Constant.int(ctx.i32, -1)
ctx.scope.define('state', state_cons)
# Generare process-level vars
for name, (ty, expr) in process.variables.viewitems():
var_ty = generate_type(ty)
global_var = g.module.add_global_variable(var_ty, str(name))
global_var = ctx.module.add_global_variable(var_ty, str(name))
global_var.initializer = core.Constant.null(var_ty)
g.scope.define(str(name).lower(), global_var)
ctx.scope.define(str(name).lower(), global_var)
# Declare timer set/reset functions
for timer in process.timers:
# TODO: Should be uint?
decl_func("set_%s" % str(timer), g.void, [g.i32_ptr], True)
decl_func("reset_%s" % str(timer), g.void, [], True)
decl_func("set_%s" % str(timer), ctx.void, [ctx.i32_ptr], True)
decl_func("reset_%s" % str(timer), ctx.void, [], True)
# Declare output signal functions
for signal in process.output_signals:
......@@ -198,12 +198,12 @@ def _process(process):
param_tys = [core.Type.pointer(generate_type(signal['type']))]
else:
param_tys = []
decl_func(str(signal['name']), g.void, param_tys, True)
decl_func(str(signal['name']), ctx.void, param_tys, True)
# Declare external procedures functions
for proc in [proc for proc in process.procedures if proc.external]:
param_tys = [core.Type.pointer(generate_type(p['type'])) for p in proc.fpar]
decl_func(str(proc.inputString), g.void, param_tys, True)
decl_func(str(proc.inputString), ctx.void, param_tys, True)
# Generate internal procedures
for proc in process.content.inner_procedures:
......@@ -217,15 +217,15 @@ def _process(process):
for signal in process.input_signals:
generate_input_signal(signal, mapping[signal['name']])
g.module.verify()
ctx.module.verify()
with open(g.name + '.ll', 'w') as ll_file:
ll_file.write(str(g.module))
with open(ctx.name + '.ll', 'w') as ll_file:
ll_file.write(str(ctx.module))
def generate_runtr_func(process):
''' Generate code for the run_transition function '''
func = decl_func('run_transition', g.void, [g.i32])
func = decl_func('run_transition', ctx.void, [ctx.i32])
open_scope()
......@@ -234,47 +234,47 @@ def generate_runtr_func(process):
body_block = func.append_basic_block('body')
exit_block = func.append_basic_block('exit')
g.builder = core.Builder.new(entry_block)
ctx.builder = core.Builder.new(entry_block)
# entry
id_ptr = g.builder.alloca(g.i32, None, 'id')
g.scope.define('id', id_ptr)
g.builder.store(func.args[0], id_ptr)
g.builder.branch(cond_block)
id_ptr = ctx.builder.alloca(ctx.i32, None, 'id')
ctx.scope.define('id', id_ptr)
ctx.builder.store(func.args[0], id_ptr)
ctx.builder.branch(cond_block)
# cond
g.builder.position_at_end(cond_block)
no_tr_cons = core.Constant.int(g.i32, -1)
id_val = g.builder.load(id_ptr)
cond_val = g.builder.icmp(core.ICMP_NE, id_val, no_tr_cons, 'cond')
g.builder.cbranch(cond_val, body_block, exit_block)
ctx.builder.position_at_end(cond_block)
no_tr_cons = core.Constant.int(ctx.i32, -1)
id_val = ctx.builder.load(id_ptr)
cond_val = ctx.builder.icmp(core.ICMP_NE, id_val, no_tr_cons, 'cond')
ctx.builder.cbranch(cond_val, body_block, exit_block)
# body
g.builder.position_at_end(body_block)
switch = g.builder.switch(func.args[0], exit_block)
ctx.builder.position_at_end(body_block)
switch = ctx.builder.switch(func.args[0], exit_block)
# transitions
for idx, tr in enumerate(process.transitions):
tr_block = func.append_basic_block('tr%d' % idx)
const = core.Constant.int(g.i32, idx)
const = core.Constant.int(ctx.i32, idx)
switch.add_case(const, tr_block)
g.builder.position_at_end(tr_block)
ctx.builder.position_at_end(tr_block)
generate(tr)
if not g.builder.basic_block.terminator:
g.builder.branch(cond_block)
if not ctx.builder.basic_block.terminator:
ctx.builder.branch(cond_block)
# exit
g.builder.position_at_end(exit_block)
g.builder.ret_void()
ctx.builder.position_at_end(exit_block)
ctx.builder.ret_void()
Helper.inner_labels_to_floating(process)
for label in process.content.floating_labels:
generate(label)
# TODO: Use defined cond_block instead?
next_tr_label_block = g.scope.label('next_transition')
g.builder.position_at_end(next_tr_label_block)
g.builder.branch(cond_block)
next_tr_label_block = ctx.scope.label('next_transition')
ctx.builder.position_at_end(next_tr_label_block)
ctx.builder.branch(cond_block)
close_scope()
......@@ -284,21 +284,21 @@ def generate_runtr_func(process):
def generate_startup_func(process):
''' Generate code for the startup function '''
func = decl_func(g.name + '_startup', g.void, [])
func = decl_func(ctx.name + '_startup', ctx.void, [])
open_scope()
entry_block = func.append_basic_block('entry')
g.builder = core.Builder.new(entry_block)
ctx.builder = core.Builder.new(entry_block)
# Initialize process level variables
for name, (ty, expr) in process.variables.viewitems():
if expr:
global_var = g.scope.resolve(str(name))
global_var = ctx.scope.resolve(str(name))
generate_assign(global_var, expression(expr))
g.builder.call(g.funcs['run_transition'], [core.Constant.int(g.i32, 0)])
g.builder.ret_void()
ctx.builder.call(ctx.funcs['run_transition'], [core.Constant.int(ctx.i32, 0)])
ctx.builder.ret_void()
close_scope()
......@@ -308,47 +308,47 @@ def generate_startup_func(process):
def generate_input_signal(signal, inputs):
''' Generate code for an input signal '''
func_name = g.name + "_" + str(signal['name'])
func_name = ctx.name + "_" + str(signal['name'])
param_tys = []
if 'type' in signal:
param_tys.append(core.Type.pointer(generate_type(signal['type'])))
func = decl_func(func_name, g.void, param_tys)
func = decl_func(func_name, ctx.void, param_tys)
open_scope()
entry_block = func.append_basic_block('entry')
exit_block = func.append_basic_block('exit')
g.builder = core.Builder.new(entry_block)
ctx.builder = core.Builder.new(entry_block)
g_state_val = g.builder.load(g.global_scope.resolve('state'))
switch = g.builder.switch(g_state_val, exit_block)
g_state_val = ctx.builder.load(ctx.global_scope.resolve('state'))
switch = ctx.builder.switch(g_state_val, exit_block)
for state_name, state_id in g.states.iteritems():
for state_name, state_id in ctx.states.iteritems():
if state_name.endswith('START'):
continue
state_block = func.append_basic_block('state_%s' % str(state_name))
switch.add_case(state_id, state_block)
g.builder.position_at_end(state_block)
ctx.builder.position_at_end(state_block)
# TODO: Nested states
input = inputs.get(state_name)
if input:
for var_name in input.parameters:
var_ptr = g.scope.resolve(str(var_name))
var_ptr = ctx.scope.resolve(str(var_name))
if is_struct_ptr(var_ptr):
generate_assign(var_ptr, func.args[0])
else:
generate_assign(var_ptr, g.builder.load(func.args[0]))
generate_assign(var_ptr, ctx.builder.load(func.args[0]))
if input.transition:
id_val = core.Constant.int(g.i32, input.transition_id)
g.builder.call(g.funcs['run_transition'], [id_val])
id_val = core.Constant.int(ctx.i32, input.transition_id)
ctx.builder.call(ctx.funcs['run_transition'], [id_val])
g.builder.ret_void()
ctx.builder.ret_void()
g.builder.position_at_end(exit_block)
g.builder.ret_void()
ctx.builder.position_at_end(exit_block)
ctx.builder.ret_void()
close_scope()
......@@ -375,20 +375,20 @@ def _call_external_function(output):
generate_set_timer(out['params'])
continue
func = g.funcs[str(name).lower()]
func = ctx.funcs[str(name).lower()]
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)
p_var = ctx.builder.alloca(p_val.type, None)
ctx.builder.store(p_val, p_var)
params.append(p_var)
else:
params.append(p_val)
g.builder.call(func, params)
ctx.builder.call(func, params)
def generate_write(params):
......@@ -399,24 +399,24 @@ def generate_write(params):
if basic_ty.kind in ['IntegerType', 'Integer32Type']:
fmt_val = get_string_cons('% d')
fmt_ptr = g.builder.gep(fmt_val, [g.zero, g.zero])
g.builder.call(g.funcs['printf'], [fmt_ptr, expr_val])
fmt_ptr = ctx.builder.gep(fmt_val, [ctx.zero, ctx.zero])
ctx.builder.call(ctx.funcs['printf'], [fmt_ptr, expr_val])
elif basic_ty.kind == 'RealType':
fmt_val = get_string_cons('% .14E')
fmt_ptr = g.builder.gep(fmt_val, [g.zero, g.zero])
g.builder.call(g.funcs['printf'], [fmt_ptr, expr_val])
fmt_ptr = ctx.builder.gep(fmt_val, [ctx.zero, ctx.zero])
ctx.builder.call(ctx.funcs['printf'], [fmt_ptr, expr_val])
elif basic_ty.kind == 'BooleanType':
true_str_val = get_string_cons('TRUE')
true_str_ptr = g.builder.gep(true_str_val, [g.zero, g.zero])
true_str_ptr = ctx.builder.gep(true_str_val, [ctx.zero, ctx.zero])
false_str_val = get_string_cons('FALSE')
false_str_ptr = g.builder.gep(false_str_val, [g.zero, g.zero])
str_ptr = g.builder.select(expr_val, true_str_ptr, false_str_ptr)
g.builder.call(g.funcs['printf'], [str_ptr])
false_str_ptr = ctx.builder.gep(false_str_val, [ctx.zero, ctx.zero])
str_ptr = ctx.builder.select(expr_val, true_str_ptr, false_str_ptr)
ctx.builder.call(ctx.funcs['printf'], [str_ptr])
elif basic_ty.kind in ['StringType', 'OctetStringType']:
fmt_val = get_string_cons('%s')
fmt_ptr = g.builder.gep(fmt_val, [g.zero, g.zero])
arr_ptr = g.builder.gep(expr_val, [g.zero, g.one])
g.builder.call(g.funcs['printf'], [fmt_ptr, arr_ptr])
fmt_ptr = ctx.builder.gep(fmt_val, [ctx.zero, ctx.zero])
arr_ptr = ctx.builder.gep(expr_val, [ctx.zero, ctx.one])
ctx.builder.call(ctx.funcs['printf'], [fmt_ptr, arr_ptr])
else:
raise NotImplementedError
......@@ -425,33 +425,33 @@ def generate_writeln(params):
''' Generate the code for the writeln operator '''
generate_write(params)
zero = core.Constant.int(g.i32, 0)
zero = core.Constant.int(ctx.i32, 0)
str_cons = get_string_cons('\n')
str_ptr = g.builder.gep(str_cons, [zero, zero])
g.builder.call(g.funcs['printf'], [str_ptr])
str_ptr = ctx.builder.gep(str_cons, [zero, zero])
ctx.builder.call(ctx.funcs['printf'], [str_ptr])
def generate_reset_timer(params):
''' Generate the code for the reset timer operator '''
timer_id = params[0]
reset_func_name = 'reset_%s' % timer_id.value[0]
reset_func = g.funcs[reset_func_name.lower()]
reset_func = ctx.funcs[reset_func_name.lower()]
g.builder.call(reset_func, [])
ctx.builder.call(reset_func, [])
def generate_set_timer(params):
''' Generate the code for the set timer operator '''
timer_expr, timer_id = params
set_func_name = 'set_%s' % timer_id.value[0]
set_func = g.funcs[set_func_name.lower()]
set_func = ctx.funcs[set_func_name.lower()]
expr_val = expression(timer_expr)
tmp_ptr = g.builder.alloca(expr_val.type)
g.builder.store(expr_val, tmp_ptr)
tmp_ptr = ctx.builder.alloca(expr_val.type)
ctx.builder.store(expr_val, tmp_ptr)
g.builder.call(set_func, [tmp_ptr])
ctx.builder.call(set_func, [tmp_ptr])
@generate.register(ogAST.TaskAssign)
......@@ -479,7 +479,7 @@ def _task_forloop(task):
def generate_for_range(loop):
''' Generate the code for a for x in range loop '''
func = g.builder.basic_block.function
func = ctx.builder.basic_block.function
cond_block = func.append_basic_block('for:cond')
body_block = func.append_basic_block('for:body')
inc_block = func.append_basic_block('for:inc')
......@@ -487,35 +487,35 @@ def generate_for_range(loop):
open_scope()
loop_var = g.builder.alloca(g.i32, None, str(loop['var']))
g.scope.define(str(loop['var']), loop_var)
loop_var = ctx.builder.alloca(ctx.i32, None, str(loop['var']))
ctx.scope.define(str(loop['var']), loop_var)
if loop['range']['start']:
start_val = expression(loop['range']['start'])
g.builder.store(start_val, loop_var)
ctx.builder.store(start_val, loop_var)
else:
g.builder.store(core.Constant.int(g.i32, 0), loop_var)
ctx.builder.store(core.Constant.int(ctx.i32, 0), loop_var)
stop_val = expression(loop['range']['stop'])
g.builder.branch(cond_block)
ctx.builder.branch(cond_block)
g.builder.position_at_end(cond_block)
loop_val = g.builder.load(loop_var)
cond_val = g.builder.icmp(core.ICMP_SLT, loop_val, stop_val)
g.builder.cbranch(cond_val, body_block, end_block)
ctx.builder.position_at_end(cond_block)
loop_val = ctx.builder.load(loop_var)
cond_val = ctx.builder.icmp(core.ICMP_SLT, loop_val, stop_val)
ctx.builder.cbranch(cond_val, body_block, end_block)
g.builder.position_at_end(body_block)
ctx.builder.position_at_end(body_block)
generate(loop['transition'])
g.builder.branch(inc_block)
ctx.builder.branch(inc_block)
g.builder.position_at_end(inc_block)
step_val = core.Constant.int(g.i32, loop['range']['step'])
loop_val = g.builder.load(loop_var)
temp_val = g.builder.add(loop_val, step_val)
g.builder.store(temp_val, loop_var)
g.builder.branch(cond_block)
ctx.builder.position_at_end(inc_block)
step_val = core.Constant.int(ctx.i32, loop['range']['step'])
loop_val = ctx.builder.load(loop_var)
temp_val = ctx.builder.add(loop_val, step_val)
ctx.builder.store(temp_val, loop_var)
ctx.builder.branch(cond_block)
g.builder.position_at_end(end_block)
ctx.builder.position_at_end(end_block)
close_scope()
......@@ -525,7 +525,7 @@ def generate_for_iterable(loop):
seqof_asn1ty = find_basic_type(loop['list'].exprType)
is_variable_size = seqof_asn1ty.Min != seqof_asn1ty.Max
func = g.builder.basic_block.function
func = ctx.builder.basic_block.function
# block for loading the value from the secuence
# at the current index, incrementing the index afterwards
......@@ -538,51 +538,51 @@ def generate_for_iterable(loop):
open_scope()
idx_ptr = g.builder.alloca(g.i32)
g.builder.store(core.Constant.int(g.i32, 0), idx_ptr)
idx_ptr = ctx.builder.alloca(ctx.i32)
ctx.builder.store(core.Constant.int(ctx.i32, 0), idx_ptr)
seqof_struct_ptr = expression(loop['list'])
if is_variable_size:
# In variable size SequenceOfs the array values are in the second field
array_ptr = g.builder.gep(seqof_struct_ptr, [g.zero, g.one])
array_ptr = ctx.builder.gep(seqof_struct_ptr, [ctx.zero, ctx.one])
else:
array_ptr = g.builder.gep(seqof_struct_ptr, [g.zero, g.zero])
array_ptr = ctx.builder.gep(seqof_struct_ptr, [ctx.zero, ctx.zero])
element_typ = array_ptr.type.pointee.element
if is_variable_size:
# load the current number of elements that is on the first field
end_idx = g.builder.load(g.builder.gep(seqof_struct_ptr, [g.zero, g.zero]))
end_idx = ctx.builder.load(ctx.builder.gep(seqof_struct_ptr, [ctx.zero, ctx.zero]))
else:
end_idx = core.Constant.int(g.i32, array_ptr.type.pointee.count)
end_idx = core.Constant.int(ctx.i32, array_ptr.type.pointee.count)
var_ptr = g.builder.alloca(element_typ, None, str(loop['var']))
g.scope.define(str(loop['var']), var_ptr)
var_ptr = ctx.builder.alloca(element_typ, None, str(loop['var']))
ctx.scope.define(str(loop['var']), var_ptr)
g.builder.branch(load_block)
ctx.builder.branch(load_block)
# load block
g.builder.position_at_end(load_block)
idx_var = g.builder.load(idx_ptr)
ctx.builder.position_at_end(load_block)
idx_var = ctx.builder.load(idx_ptr)
if element_typ.kind == core.TYPE_STRUCT:
generate_assign(var_ptr, g.builder.gep(array_ptr, [g.zero, idx_var]))
generate_assign(var_ptr, ctx.builder.gep(array_ptr, [ctx.zero, idx_var]))
else:
generate_assign(var_ptr, g.builder.load(g.builder.gep(array_ptr, [g.zero, idx_var])))
g.builder.branch(body_block)
generate_assign(var_ptr, ctx.builder.load(ctx.builder.gep(array_ptr, [ctx.zero, idx_var])))
ctx.builder.branch(body_block)
# body block
g.builder.position_at_end(body_block)
ctx.builder.position_at_end(body_block)
generate(loop['transition'])
g.builder.branch(cond_block)
ctx.builder.branch(cond_block)
# cond block
g.builder.position_at_end(cond_block)
tmp_val = g.builder.add(idx_var, g.one)
g.builder.store(tmp_val, idx_ptr)
cond_val = g.builder.icmp(core.ICMP_SLT, tmp_val, end_idx)
g.builder.cbranch(cond_val, load_block, end_block)
ctx.builder.position_at_end(cond_block)
tmp_val = ctx.builder.add(idx_var, ctx.one)
ctx.builder.store(tmp_val, idx_ptr)
cond_val = ctx.builder.icmp(core.ICMP_SLT, tmp_val, end_idx)
ctx.builder.cbranch(cond_val, load_block, end_block)
g.builder.position_at_end(end_block)
ctx.builder.position_at_end(end_block)
close_scope()
......@@ -596,14 +596,14 @@ def reference(prim):
@reference.register(ogAST.PrimVariable)
def _prim_var_reference(prim):
''' Generate a primary variable reference '''
return g.scope.resolve(str(prim.value[0]))
return ctx.scope.resolve(str(prim.value[0]))
@reference.register(ogAST.PrimPath)
def _prim_path_reference(prim):
''' Generate a primary path reference '''
var_name = prim.value[0].lower()
var_ptr = g.scope.resolve(str(var_name))
var_ptr = ctx.scope.resolve(str(var_name))
if not prim.value:
return var_ptr
......@@ -612,28 +612,28 @@ def _prim_path_reference(prim):
if type(elem) == dict:
if 'index' in elem:
idx_val = expression(elem['index'][0])
array_ptr = g.builder.gep(var_ptr, [g.zero, g.zero])
array_ptr = ctx.builder.gep(var_ptr, [ctx.zero, ctx.zero])
# TODO: Refactor this
if array_ptr.type.pointee.kind != core.TYPE_ARRAY:
# If is not an array this is a pointer to a variable size SeqOf
# The array is in the second field of the struct
var_ptr = g.builder.gep(var_ptr, [g.zero, g.one, idx_val])
var_ptr = ctx.builder.gep(var_ptr, [ctx.zero, ctx.one, idx_val])
else:
var_ptr = g.builder.gep(var_ptr, [g.zero, g.zero, idx_val])
var_ptr = ctx.builder.gep(var_ptr, [ctx.zero, ctx.zero, idx_val])
else:
raise NotImplementedError
else:
var_ty = var_ptr.type
if var_ty.pointee.name in g.structs:
struct = g.structs[var_ty.pointee.name]
field_idx_cons = core.Constant.int(g.i32, struct.idx(elem))
field_ptr = g.builder.gep(var_ptr, [g.zero, field_idx_cons])
if var_ty.pointee.name in ctx.structs:
struct = ctx.structs[var_ty.pointee.name]
field_idx_cons = core.Constant.int(ctx.i32, struct.idx(elem))
field_ptr = ctx.builder.gep(var_ptr, [ctx.zero, field_idx_cons])
var_ptr = field_ptr
elif var_ty.pointee.name in g.unions:
union = g.unions[var_ty.pointee.name]
elif var_ty.pointee.name in ctx.unions:
union = ctx.unions[var_ty.pointee.name]
_, field_ty = union.kind(elem)
field_ptr = g.builder.gep(var_ptr, [g.zero, g.one])
var_ptr = g.builder.bitcast(field_ptr, core.Type.pointer(field_ty))
field_ptr = ctx.builder.gep(var_ptr, [ctx.zero, ctx.one])
var_ptr = ctx.builder.bitcast(field_ptr, core.Type.pointer(field_ty))
else:
raise NotImplementedError
return var_ptr
......@@ -649,7 +649,7 @@ def expression(expr):
def _primary_variable(prim):
''' Generate the code for a variable expression '''
var_ptr = reference(prim)
return var_ptr if is_struct_ptr(var_ptr) else g.builder.load(var_ptr)
return var_ptr if is_struct_ptr(var_ptr) else ctx.builder.load(var_ptr)
@expression.register(ogAST.PrimPath)
......@@ -675,14 +675,14 @@ def _prim_path(prim):
def generate_access(prim):
''' Generate the code for an access '''
var_ptr = reference(prim)
return var_ptr if is_struct_ptr(var_ptr) else g.builder.load(var_ptr)
return var_ptr if is_struct_ptr(var_ptr) else ctx.builder.load(var_ptr)