Handle getelementptr.

This commit is contained in:
cfreksen 2017-10-30 00:00:56 +01:00
parent 5fc3e23ae5
commit 89439593e4
No known key found for this signature in database
GPG Key ID: EAC13EE101008978
2 changed files with 89 additions and 5 deletions

7
ll.py
View File

@ -137,6 +137,13 @@ def insn2s(insn):
return ('bitcast {} {} to {}'
.format(ty2s(insn.from_ty), oper2s(insn.oper),
ty2s(insn.to_ty)))
elif isinstance(insn, Gep):
return ('getelementptr {}, {} {}, {}'
.format(ty2s(insn.base_ty), ty2s(insn.oper_ty),
oper2s(insn.oper),
', '.join('{} {}'.format(ty2s(t), oper2s(o))
for t, o in insn.steps)))
elif isinstance(insn, Zext):
return ('zext {} {} to {}'
.format(ty2s(insn.from_ty), oper2s(insn.oper),

View File

@ -162,7 +162,33 @@ def step(insns, terminator, blocks, stack_frames, ssa_env, global_env, heap,
print('bitcast {} {} to {}'
.format(ll.ty2s(from_ty), oper_v, ll.ty2s(to_ty)))
elif isinstance(next_insn, ll.Gep):
TODO('Gep')
res = 0
base_ty = next_insn.base_ty
oper_ty = next_insn.oper_ty
oper = next_insn.oper
steps = next_insn.steps
actual_base_ty = ty2base_ty(base_ty, tdecs)
actual_oper_ty = ty2base_ty(oper_ty, tdecs)
if not isinstance(actual_oper_ty, ll.PointerType):
err('Type of main operand to getelementptr must be a pointer type. It was {}'
.format(ll.ty2s(actual_oper_ty)))
elif actual_base_ty != actual_oper_ty.inner_ty:
err(('Type of the main operand does not match the type getelementptr'
' navigates through.\n'
' Getelementptr type: {}\n'
' Operand type: {}')
.format(ll.ty2s(actual_base_ty), ll.ty2s(actual_oper_ty.inner_ty)))
else:
oper_v = eval_oper(oper, ssa_env, global_env)
gep_res, formula = handle_gep(oper_v, actual_base_ty, steps, ssa_env,
global_env)
res = gep_res
# TODO
print('Gep formula: {}'
.format(formula))
elif isinstance(next_insn, ll.Zext):
oper = next_insn.oper
from_ty = next_insn.from_ty
@ -346,6 +372,57 @@ def eval_icmp(cnd, left, right):
return 0
def handle_gep(starting_location, starting_type, starting_steps, ssa_env, global_env):
def visit(current_location, current_type, current_steps, current_formula):
if len(current_steps) == 0:
return current_location, current_formula
else:
s_ty, s_oper = current_steps[0]
s_oper_v = eval_oper(s_oper, ssa_env, global_env)
next_steps = current_steps[1:]
if isinstance(current_type, ll.StructType):
if not isinstance(s_oper, ll.Const):
err('Index into struct must be a constant. It was: {}'
.format(ll.oper2s(s_oper)))
return current_location, current_formula + ' + ???'
jumps = [base_ty2size(current_type.fields[i])
for i in range(s_oper_v)]
next_location = current_location + sum(jumps)
next_type = current_type.fields[s_oper_v]
if len(jumps) > 0:
next_formula = ('{} + ({})'
.format(current_formula,
' + '.join(map(str, jumps))))
else:
next_formula = ('{} + 0'
.format(current_formula))
return visit(next_location, next_type, next_steps, next_formula)
elif isinstance(current_type, ll.ArrayType):
TODO('gep arrays')
return current_location, current_formula + ' + ???'
elif isinstance(current_type, ll.PointerType):
err(('Cannot use getelementptr to traverse pointers.'
' Use Load, and getelementptr on the result from that'
' to go through a pointer.'))
return current_location, current_formula + ' + ???'
else:
err('Unknown type to getelementptr on: {}'
.format(ll.ty2s(current_type)))
return current_location, current_formula + ' + ???'
if len(starting_steps) == 0:
err('There must be at least one stepping argument to a getelementptr instruction')
return 0, ''
s_ty, s_oper = starting_steps[0]
s_oper_v = eval_oper(s_oper, ssa_env, global_env)
size = base_ty2size(starting_type)
next_location = starting_location + s_oper_v * size
formula = ('{} + {} * {}'
.format(starting_location, s_oper_v, size))
return visit(next_location, starting_type, starting_steps[1:], formula)
def ty2base_ty(ty, tdecs, seen=[]):
if isinstance(ty, ll.SimpleType):
return ty
@ -392,14 +469,14 @@ def gogo():
p = parser.LLVMParser()
p.build()
data = r'''
%T_tigermain = type { i64, i64 }
%T_tigermain = type { i64, i64, {i64, i64}, i64 }
define i64 @tigermain (i64 %U_mainSL_8, i64 %U_mainDummy_9) {
%a = alloca i64
%t = alloca %T_tigermain
%a = getelementptr %T_tigermain, %T_tigermain* %t, i32 0, i32 2, i32 1
store i64 9, i64* %a
%b = load i64, i64* %a
ret i64 %b
%r = load i64, i64* %a
ret i64 %r
}
'''