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 {}'
|
return ('bitcast {} {} to {}'
|
||||||
.format(ty2s(insn.from_ty), oper2s(insn.oper),
|
.format(ty2s(insn.from_ty), oper2s(insn.oper),
|
||||||
ty2s(insn.to_ty)))
|
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):
|
elif isinstance(insn, Zext):
|
||||||
return ('zext {} {} to {}'
|
return ('zext {} {} to {}'
|
||||||
.format(ty2s(insn.from_ty), oper2s(insn.oper),
|
.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 {}'
|
print('bitcast {} {} to {}'
|
||||||
.format(ll.ty2s(from_ty), oper_v, ll.ty2s(to_ty)))
|
.format(ll.ty2s(from_ty), oper_v, ll.ty2s(to_ty)))
|
||||||
elif isinstance(next_insn, ll.Gep):
|
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):
|
elif isinstance(next_insn, ll.Zext):
|
||||||
oper = next_insn.oper
|
oper = next_insn.oper
|
||||||
from_ty = next_insn.from_ty
|
from_ty = next_insn.from_ty
|
||||||
|
@ -346,6 +372,57 @@ def eval_icmp(cnd, left, right):
|
||||||
return 0
|
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=[]):
|
def ty2base_ty(ty, tdecs, seen=[]):
|
||||||
if isinstance(ty, ll.SimpleType):
|
if isinstance(ty, ll.SimpleType):
|
||||||
return ty
|
return ty
|
||||||
|
@ -392,14 +469,14 @@ def gogo():
|
||||||
p = parser.LLVMParser()
|
p = parser.LLVMParser()
|
||||||
p.build()
|
p.build()
|
||||||
data = r'''
|
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) {
|
define i64 @tigermain (i64 %U_mainSL_8, i64 %U_mainDummy_9) {
|
||||||
%a = alloca i64
|
|
||||||
%t = alloca %T_tigermain
|
%t = alloca %T_tigermain
|
||||||
|
%a = getelementptr %T_tigermain, %T_tigermain* %t, i32 0, i32 2, i32 1
|
||||||
store i64 9, i64* %a
|
store i64 9, i64* %a
|
||||||
%b = load i64, i64* %a
|
%r = load i64, i64* %a
|
||||||
ret i64 %b
|
ret i64 %r
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user