Handle getelementptr.
This commit is contained in:
parent
5fc3e23ae5
commit
89439593e4
7
ll.py
7
ll.py
|
@ -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),
|
||||
|
|
87
stepper.py
87
stepper.py
|
@ -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
|
||||
}
|
||||
'''
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user