interp: do cast operations at runtime if needed

Cast operations will still be evaluated at compile time in all cases
they did before because of the built-in constant propagation of the
IRBuilder, but when one of the parameters is not a constant it will
transparently be evaluated at runtime.

This avoids some errors in the partial evaluator. It is not yet complete
as all binops will need a similar treatment.
Этот коммит содержится в:
Ayke van Laethem 2018-11-09 16:27:49 +01:00
родитель c4ef2908ee
коммит eccbd572eb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED

Просмотреть файл

@ -135,31 +135,31 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
// Cast operators // Cast operators
case !inst.IsATruncInst().IsNil(): case !inst.IsATruncInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstTrunc(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateTrunc(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsAZExtInst().IsNil(): case !inst.IsAZExtInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstZExt(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateZExt(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsASExtInst().IsNil(): case !inst.IsASExtInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstSExt(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateSExt(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsAFPToUIInst().IsNil(): case !inst.IsAFPToUIInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstFPToUI(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateFPToUI(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsAFPToSIInst().IsNil(): case !inst.IsAFPToSIInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstFPToSI(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateFPToSI(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsAUIToFPInst().IsNil(): case !inst.IsAUIToFPInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstUIToFP(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateUIToFP(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsASIToFPInst().IsNil(): case !inst.IsASIToFPInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstSIToFP(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateSIToFP(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsAFPTruncInst().IsNil(): case !inst.IsAFPTruncInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstFPTrunc(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateFPTrunc(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsAFPExtInst().IsNil(): case !inst.IsAFPExtInst().IsNil():
value := fr.getLocal(inst.Operand(0)) value := fr.getLocal(inst.Operand(0))
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstFPExt(value.(*LocalValue).Value(), inst.Type())} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateFPExt(value.(*LocalValue).Value(), inst.Type(), "")}
case !inst.IsABitCastInst().IsNil() && inst.Type().TypeKind() == llvm.PointerTypeKind: case !inst.IsABitCastInst().IsNil() && inst.Type().TypeKind() == llvm.PointerTypeKind:
operand := inst.Operand(0) operand := inst.Operand(0)
if !operand.IsACallInst().IsNil() { if !operand.IsACallInst().IsNil() {
@ -179,12 +179,12 @@ func (fr *frame) evalBasicBlock(bb, incoming llvm.BasicBlock, indent string) (re
lhs := fr.getLocal(inst.Operand(0)).(*LocalValue).Underlying lhs := fr.getLocal(inst.Operand(0)).(*LocalValue).Underlying
rhs := fr.getLocal(inst.Operand(1)).(*LocalValue).Underlying rhs := fr.getLocal(inst.Operand(1)).(*LocalValue).Underlying
predicate := inst.IntPredicate() predicate := inst.IntPredicate()
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstICmp(predicate, lhs, rhs)} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateICmp(predicate, lhs, rhs, "")}
case !inst.IsAFCmpInst().IsNil(): case !inst.IsAFCmpInst().IsNil():
lhs := fr.getLocal(inst.Operand(0)).(*LocalValue).Underlying lhs := fr.getLocal(inst.Operand(0)).(*LocalValue).Underlying
rhs := fr.getLocal(inst.Operand(1)).(*LocalValue).Underlying rhs := fr.getLocal(inst.Operand(1)).(*LocalValue).Underlying
predicate := inst.FloatPredicate() predicate := inst.FloatPredicate()
fr.locals[inst] = &LocalValue{fr.Eval, llvm.ConstFCmp(predicate, lhs, rhs)} fr.locals[inst] = &LocalValue{fr.Eval, fr.builder.CreateFCmp(predicate, lhs, rhs, "")}
case !inst.IsAPHINode().IsNil(): case !inst.IsAPHINode().IsNil():
for i := 0; i < inst.IncomingCount(); i++ { for i := 0; i < inst.IncomingCount(); i++ {
if inst.IncomingBlock(i) == incoming { if inst.IncomingBlock(i) == incoming {