Commit 16032e15 authored by dbarbera's avatar dbarbera
Browse files

Raise compile error for unexpected cases in bitwise/shortcircuit expressions

parent 87bc8ba6
...@@ -307,6 +307,10 @@ class Scope: ...@@ -307,6 +307,10 @@ class Scope:
return label_block return label_block
class CompileError(Exception):
pass
@singledispatch @singledispatch
def generate(ast): def generate(ast):
''' Generate the code for an item of the AST ''' ''' Generate the code for an item of the AST '''
...@@ -1075,7 +1079,13 @@ def generate_assign(left, right): ...@@ -1075,7 +1079,13 @@ def generate_assign(left, right):
@expression.register(ogAST.ExprXor) @expression.register(ogAST.ExprXor)
def _logic(expr): def _logic(expr):
''' Generate the code for a logic expression ''' ''' Generate the code for a logic expression '''
bty = find_basic_type(expr.exprType)
if expr.shortcircuit: if expr.shortcircuit:
if bty.kind != 'BooleanType':
raise CompileError('Type "%s" not supported in shortcircuit expressions'
% bty.kind)
func = ctx.builder.basic_block.function func = ctx.builder.basic_block.function
right_block = func.append_basic_block('') right_block = func.append_basic_block('')
...@@ -1090,7 +1100,7 @@ def _logic(expr): ...@@ -1090,7 +1100,7 @@ def _logic(expr):
elif expr.operand == 'or': elif expr.operand == 'or':
ctx.builder.cbranch(left_val, end_block, right_block) ctx.builder.cbranch(left_val, end_block, right_block)
else: else:
raise NotImplementedError raise CompileError('Unknown shortcircuit operator "%s"' % expr.operand)
ctx.builder.position_at_end(right_block) ctx.builder.position_at_end(right_block)
right_val = expression(expr.right) right_val = expression(expr.right)
...@@ -1100,73 +1110,72 @@ def _logic(expr): ...@@ -1100,73 +1110,72 @@ def _logic(expr):
ctx.builder.position_at_end(end_block) ctx.builder.position_at_end(end_block)
return ctx.builder.load(res_ptr) return ctx.builder.load(res_ptr)
else: elif bty.kind == 'BooleanType':
bty = find_basic_type(expr.exprType) left_val = expression(expr.left)
right_val = expression(expr.right)
if bty.kind == 'BooleanType': if expr.operand == 'and':
left_val = expression(expr.left) return ctx.builder.and_(left_val, right_val)
right_val = expression(expr.right) elif expr.operand == 'or':
if expr.operand == 'and': return ctx.builder.or_(left_val, right_val)
return ctx.builder.and_(left_val, right_val) elif expr.operand == 'xor':
elif expr.operand == 'or': return ctx.builder.xor(left_val, right_val)
return ctx.builder.or_(left_val, right_val) raise CompileError('Unknown bitwise operator "%s"' % expr.operand)
else:
return ctx.builder.xor(left_val, right_val)
elif bty.kind == 'SequenceOfType' and bty.Min == bty.Max: elif bty.kind == 'SequenceOfType' and bty.Min == bty.Max:
func = ctx.builder.basic_block.function func = ctx.builder.basic_block.function
body_block = func.append_basic_block('%s:body' % expr.operand) body_block = func.append_basic_block('%s:body' % expr.operand)
next_block = func.append_basic_block('%s:next' % expr.operand) next_block = func.append_basic_block('%s:next' % expr.operand)
end_block = func.append_basic_block('%s:end' % expr.operand) end_block = func.append_basic_block('%s:end' % expr.operand)
left_ptr = expression(expr.left) left_ptr = expression(expr.left)
right_ptr = expression(expr.right) right_ptr = expression(expr.right)
res_ptr = ctx.builder.alloca(left_ptr.type.pointee) res_ptr = ctx.builder.alloca(left_ptr.type.pointee)
array_ty = res_ptr.type.pointee.elements[0] array_ty = res_ptr.type.pointee.elements[0]
len_val = core.Constant.int(ctx.i32, array_ty.count) len_val = core.Constant.int(ctx.i32, array_ty.count)
idx_ptr = ctx.builder.alloca(ctx.i32) idx_ptr = ctx.builder.alloca(ctx.i32)
ctx.builder.store(core.Constant.int(ctx.i32, 0), idx_ptr) ctx.builder.store(core.Constant.int(ctx.i32, 0), idx_ptr)
ctx.builder.branch(body_block) ctx.builder.branch(body_block)
# body block # body block
ctx.builder.position_at_end(body_block) ctx.builder.position_at_end(body_block)
idx_val = ctx.builder.load(idx_ptr) idx_val = ctx.builder.load(idx_ptr)
left_elem_ptr = ctx.builder.gep(left_ptr, [ctx.zero, ctx.zero, idx_val]) left_elem_ptr = ctx.builder.gep(left_ptr, [ctx.zero, ctx.zero, idx_val])
left_elem_val = ctx.builder.load(left_elem_ptr) left_elem_val = ctx.builder.load(left_elem_ptr)
right_elem_ptr = ctx.builder.gep(right_ptr, [ctx.zero, ctx.zero, idx_val]) right_elem_ptr = ctx.builder.gep(right_ptr, [ctx.zero, ctx.zero, idx_val])
right_elem_val = ctx.builder.load(right_elem_ptr) right_elem_val = ctx.builder.load(right_elem_ptr)
if expr.operand == 'and': if expr.operand == 'and':
res_elem_val = ctx.builder.and_(left_elem_val, right_elem_val) res_elem_val = ctx.builder.and_(left_elem_val, right_elem_val)
elif expr.operand == 'or': elif expr.operand == 'or':
res_elem_val = ctx.builder.or_(left_elem_val, right_elem_val) res_elem_val = ctx.builder.or_(left_elem_val, right_elem_val)
else: elif expr.operand == 'xor':
res_elem_val = ctx.builder.xor(left_elem_val, right_elem_val) res_elem_val = ctx.builder.xor(left_elem_val, right_elem_val)
else:
raise CompileError('Unknown bitwise operator "%s"' % expr.operand)
res_elem_ptr = ctx.builder.gep(res_ptr, [ctx.zero, ctx.zero, idx_val]) res_elem_ptr = ctx.builder.gep(res_ptr, [ctx.zero, ctx.zero, idx_val])
ctx.builder.store(res_elem_val, res_elem_ptr) ctx.builder.store(res_elem_val, res_elem_ptr)
ctx.builder.branch(next_block) ctx.builder.branch(next_block)
# next block # next block
ctx.builder.position_at_end(next_block) ctx.builder.position_at_end(next_block)
idx_tmp_val = ctx.builder.add(idx_val, ctx.one) idx_tmp_val = ctx.builder.add(idx_val, ctx.one)
ctx.builder.store(idx_tmp_val, idx_ptr) ctx.builder.store(idx_tmp_val, idx_ptr)
end_cond_val = ctx.builder.icmp(core.ICMP_SGE, idx_tmp_val, len_val) end_cond_val = ctx.builder.icmp(core.ICMP_SGE, idx_tmp_val, len_val)
ctx.builder.cbranch(end_cond_val, end_block, body_block) ctx.builder.cbranch(end_cond_val, end_block, body_block)
# end block # end block
ctx.builder.position_at_end(end_block) ctx.builder.position_at_end(end_block)
return res_ptr return res_ptr
else: raise CompileError('Type "%s" not supported in bitwise expressions' % bty.kind)
raise NotImplementedError
@expression.register(ogAST.ExprNot) @expression.register(ogAST.ExprNot)
...@@ -1177,7 +1186,7 @@ def _not(expr): ...@@ -1177,7 +1186,7 @@ def _not(expr):
if bty.kind == 'BooleanType': if bty.kind == 'BooleanType':
return ctx.builder.not_(expression(expr.expr)) return ctx.builder.not_(expression(expr.expr))
elif bty.kind == 'SequenceOfType': elif bty.kind == 'SequenceOfType' and bty.Min == bty.Max:
func = ctx.builder.basic_block.function func = ctx.builder.basic_block.function
not_block = func.append_basic_block('not:not') not_block = func.append_basic_block('not:not')
...@@ -1190,24 +1199,15 @@ def _not(expr): ...@@ -1190,24 +1199,15 @@ def _not(expr):
struct_ptr = expression(expr.expr) struct_ptr = expression(expr.expr)
res_struct_ptr = ctx.builder.alloca(struct_ptr.type.pointee) res_struct_ptr = ctx.builder.alloca(struct_ptr.type.pointee)
if bty.Min != bty.Max: array_ty = struct_ptr.type.pointee.elements[0]
len_ptr = ctx.builder.gep(struct_ptr, [ctx.zero, ctx.zero]) len_val = core.Constant.int(ctx.i32, array_ty.count)
len_val = ctx.builder.load(len_ptr)
res_len_ptr = ctx.builder.gep(res_struct_ptr, [ctx.zero, ctx.zero])
ctx.builder.store(len_val, res_len_ptr)
else:
array_ty = struct_ptr.type.pointee.elements[0]
len_val = core.Constant.int(ctx.i32, array_ty.count)
ctx.builder.branch(not_block) ctx.builder.branch(not_block)
ctx.builder.position_at_end(not_block) ctx.builder.position_at_end(not_block)
idx_val = ctx.builder.load(idx_ptr) idx_val = ctx.builder.load(idx_ptr)
if bty.Min != bty.Max: elem_idxs = [ctx.zero, ctx.zero, idx_val]
elem_idxs = [ctx.zero, ctx.one, idx_val]
else:
elem_idxs = [ctx.zero, ctx.zero, idx_val]
elem_ptr = ctx.builder.gep(struct_ptr, elem_idxs) elem_ptr = ctx.builder.gep(struct_ptr, elem_idxs)
elem_val = ctx.builder.load(elem_ptr) elem_val = ctx.builder.load(elem_ptr)
...@@ -1226,8 +1226,7 @@ def _not(expr): ...@@ -1226,8 +1226,7 @@ def _not(expr):
ctx.builder.position_at_end(end_block) ctx.builder.position_at_end(end_block)
return res_struct_ptr return res_struct_ptr
else: raise CompileError('Type "%s" not supported in bitwise expressions' % bty.kind)
raise NotImplementedError
@expression.register(ogAST.ExprAppend) @expression.register(ogAST.ExprAppend)
......
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