Skip to content

Commit efa0410

Browse files
aykevldeadprogram
authored andcommitted
interp: fix bug in compiler-time/run-time package initializers
Make sure that if a package initializer cannot be run, later package initializers won't try to access any global variables touched by the uninterpretable package initializer.
1 parent 607d824 commit efa0410

File tree

3 files changed

+40
-0
lines changed

3 files changed

+40
-0
lines changed

interp/interp.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,16 @@ func Run(mod llvm.Module, debug bool) error {
116116
if r.debug {
117117
fmt.Fprintln(os.Stderr, "not interpreting", r.pkgName, "because of error:", callErr.Error())
118118
}
119+
// Remove instructions that were created as part of interpreting
120+
// the package.
119121
mem.revert()
122+
// Create a call to the package initializer (which was
123+
// previously deleted).
120124
i8undef := llvm.Undef(r.i8ptrType)
121125
r.builder.CreateCall(fn, []llvm.Value{i8undef, i8undef}, "")
126+
// Make sure that any globals touched by the package
127+
// initializer, won't be accessed by later package initializers.
128+
r.markExternalLoad(fn)
122129
continue
123130
}
124131
return callErr
@@ -272,3 +279,19 @@ func (r *runner) getFunction(llvmFn llvm.Value) *function {
272279
r.functionCache[llvmFn] = fn
273280
return fn
274281
}
282+
283+
// markExternalLoad marks the given llvmValue as being loaded externally. This
284+
// is primarily used to mark package initializers that could not be run at
285+
// compile time. As an example, a package initialize might store to a global
286+
// variable. Another package initializer might read from the same global
287+
// variable. By marking this function as being run at runtime, that load
288+
// instruction will need to be run at runtime instead of at compile time.
289+
func (r *runner) markExternalLoad(llvmValue llvm.Value) {
290+
mem := memoryView{r: r}
291+
mem.markExternalLoad(llvmValue)
292+
for index, obj := range mem.objects {
293+
if obj.marked > r.objects[index].marked {
294+
r.objects[index].marked = obj.marked
295+
}
296+
}
297+
}

interp/testdata/revert.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,28 @@ target triple = "x86_64--linux"
33

44
declare void @externalCall(i64)
55

6+
@foo.knownAtRuntime = global i64 0
7+
@bar.knownAtRuntime = global i64 0
8+
69
define void @runtime.initAll() unnamed_addr {
710
entry:
811
call void @foo.init(i8* undef, i8* undef)
12+
call void @bar.init(i8* undef, i8* undef)
913
call void @main.init(i8* undef, i8* undef)
1014
ret void
1115
}
1216

1317
define internal void @foo.init(i8* %context, i8* %parentHandle) unnamed_addr {
18+
store i64 5, i64* @foo.knownAtRuntime
1419
unreachable ; this triggers a revert of @foo.init.
1520
}
1621

22+
define internal void @bar.init(i8* %context, i8* %parentHandle) unnamed_addr {
23+
%val = load i64, i64* @foo.knownAtRuntime
24+
store i64 %val, i64* @bar.knownAtRuntime
25+
ret void
26+
}
27+
1728
define internal void @main.init(i8* %context, i8* %parentHandle) unnamed_addr {
1829
entry:
1930
call void @externalCall(i64 3)

interp/testdata/revert.out.ll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,21 @@
11
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
22
target triple = "x86_64--linux"
33

4+
@foo.knownAtRuntime = local_unnamed_addr global i64 0
5+
@bar.knownAtRuntime = local_unnamed_addr global i64 0
6+
47
declare void @externalCall(i64) local_unnamed_addr
58

69
define void @runtime.initAll() unnamed_addr {
710
entry:
811
call fastcc void @foo.init(i8* undef, i8* undef)
12+
%val = load i64, i64* @foo.knownAtRuntime, align 8
13+
store i64 %val, i64* @bar.knownAtRuntime, align 8
914
call void @externalCall(i64 3)
1015
ret void
1116
}
1217

1318
define internal fastcc void @foo.init(i8* %context, i8* %parentHandle) unnamed_addr {
19+
store i64 5, i64* @foo.knownAtRuntime, align 8
1420
unreachable
1521
}

0 commit comments

Comments
 (0)