diff --git a/interp/memory.go b/interp/memory.go index 54bfcb62..ccd98c8b 100644 --- a/interp/memory.go +++ b/interp/memory.go @@ -178,6 +178,9 @@ func (mv *memoryView) markExternal(llvmValue llvm.Value, mark uint8) { default: panic("interp: unknown constant expression") } + } else if !llvmValue.IsAInlineAsm().IsNil() { + // Inline assembly can modify globals but only exported globals. Let's + // hope the author knows what they're doing. } else { llvmType := llvmValue.Type() switch llvmType.TypeKind() { diff --git a/interp/testdata/basic.ll b/interp/testdata/basic.ll index 00117058..d0af3af3 100644 --- a/interp/testdata/basic.ll +++ b/interp/testdata/basic.ll @@ -66,6 +66,9 @@ entry: call void @modifyExternal(i32* bitcast (void ()* @willModifyGlobal to i32*)) store i16 7, i16* @main.exposedValue2 + ; Test that inline assembly is ignored. + call void @modifyExternal(i32* bitcast (void ()* @hasInlineAsm to i32*)) + ; Test switch statement. %switch1 = call i64 @testSwitch(i64 1) ; 1 returns 6 %switch2 = call i64 @testSwitch(i64 9) ; 9 returns the default value -1 @@ -102,6 +105,15 @@ entry: ret void } +; Inline assembly should be ignored in the interp package. While it is possible +; to modify other globals that way, usually that's not the case and there is no +; real way to check. +define void @hasInlineAsm() { +entry: + call void asm sideeffect "", ""() + ret void +} + define i64 @testSwitch(i64 %val) { entry: ; Test switch statement. diff --git a/interp/testdata/basic.out.ll b/interp/testdata/basic.out.ll index 24f5558b..51a3b3f4 100644 --- a/interp/testdata/basic.out.ll +++ b/interp/testdata/basic.out.ll @@ -26,6 +26,7 @@ entry: store i16 5, i16* @main.exposedValue1 call void @modifyExternal(i32* bitcast (void ()* @willModifyGlobal to i32*)) store i16 7, i16* @main.exposedValue2 + call void @modifyExternal(i32* bitcast (void ()* @hasInlineAsm to i32*)) call void @runtime.printint64(i64 6) call void @runtime.printint64(i64 -1) %agg = call { i8, i32, { float, { i64, i16 } } } @nestedStruct() @@ -59,6 +60,12 @@ entry: ret void } +define void @hasInlineAsm() { +entry: + call void asm sideeffect "", ""() + ret void +} + define i64 @testSwitch(i64 %val) local_unnamed_addr { entry: switch i64 %val, label %otherwise [