interp: keep reverted package initializers in order

Previously, a package initializer that could not be reverted correctly
would be called at runtime. But the initializer would be called in the
wrong order: after later packages are initialized.

This commit fixes this oversight and adds a test to verify the new
behavior.
Этот коммит содержится в:
Ayke van Laethem 2021-07-14 15:45:11 +02:00 коммит произвёл Ron Evans
родитель 8cc7c6d572
коммит 607d824211
4 изменённых файлов: 40 добавлений и 1 удалений

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

@ -110,17 +110,19 @@ func Run(mod llvm.Module, debug bool) error {
fmt.Fprintln(os.Stderr, "call:", fn.Name()) fmt.Fprintln(os.Stderr, "call:", fn.Name())
} }
_, mem, callErr := r.run(r.getFunction(fn), nil, nil, " ") _, mem, callErr := r.run(r.getFunction(fn), nil, nil, " ")
call.EraseFromParentAsInstruction()
if callErr != nil { if callErr != nil {
if isRecoverableError(callErr.Err) { if isRecoverableError(callErr.Err) {
if r.debug { if r.debug {
fmt.Fprintln(os.Stderr, "not interpreting", r.pkgName, "because of error:", callErr.Error()) fmt.Fprintln(os.Stderr, "not interpreting", r.pkgName, "because of error:", callErr.Error())
} }
mem.revert() mem.revert()
i8undef := llvm.Undef(r.i8ptrType)
r.builder.CreateCall(fn, []llvm.Value{i8undef, i8undef}, "")
continue continue
} }
return callErr return callErr
} }
call.EraseFromParentAsInstruction()
for index, obj := range mem.objects { for index, obj := range mem.objects {
r.objects[index] = obj r.objects[index] = obj
} }

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

@ -17,6 +17,7 @@ func TestInterp(t *testing.T) {
"slice-copy", "slice-copy",
"consteval", "consteval",
"interface", "interface",
"revert",
} { } {
name := name // make tc local to this closure name := name // make tc local to this closure
t.Run(name, func(t *testing.T) { t.Run(name, func(t *testing.T) {

21
interp/testdata/revert.ll предоставленный Обычный файл
Просмотреть файл

@ -0,0 +1,21 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"
declare void @externalCall(i64)
define void @runtime.initAll() unnamed_addr {
entry:
call void @foo.init(i8* undef, i8* undef)
call void @main.init(i8* undef, i8* undef)
ret void
}
define internal void @foo.init(i8* %context, i8* %parentHandle) unnamed_addr {
unreachable ; this triggers a revert of @foo.init.
}
define internal void @main.init(i8* %context, i8* %parentHandle) unnamed_addr {
entry:
call void @externalCall(i64 3)
ret void
}

15
interp/testdata/revert.out.ll предоставленный Обычный файл
Просмотреть файл

@ -0,0 +1,15 @@
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64--linux"
declare void @externalCall(i64) local_unnamed_addr
define void @runtime.initAll() unnamed_addr {
entry:
call fastcc void @foo.init(i8* undef, i8* undef)
call void @externalCall(i64 3)
ret void
}
define internal fastcc void @foo.init(i8* %context, i8* %parentHandle) unnamed_addr {
unreachable
}