Skip to content

Commit 7bc9a55

Browse files
authored
Merge pull request llir#72 from llir/type-check-store
Type check NewStore operands
2 parents b973432 + 40ca264 commit 7bc9a55

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

ir/inst_memory.go

+8
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ type InstStore struct {
209209
// NewStore returns a new store instruction based on the given source value and
210210
// destination address.
211211
func NewStore(src, dst value.Value) *InstStore {
212+
// Type-check operands.
213+
dstPtrType, ok := dst.Type().(*types.PointerType)
214+
if !ok {
215+
panic(fmt.Errorf("invalid store dst operand type; expected *types.Pointer, got %T", dst.Type()))
216+
}
217+
if !src.Type().Equal(dstPtrType.ElemType) {
218+
panic(fmt.Errorf("store operands are not compatible: src=%v; dst=%v", src.Type(), dst.Type()))
219+
}
212220
return &InstStore{Src: src, Dst: dst}
213221
}
214222

ir/inst_memory_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package ir
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/llir/llvm/ir/constant"
8+
"github.com/llir/llvm/ir/types"
9+
"github.com/pkg/errors"
10+
)
11+
12+
func TestTypeCheckStore(t *testing.T) {
13+
cases := []struct {
14+
fromTyp, toTyp types.Type
15+
panicMessage string // "OK" if not panic'ing.
16+
}{
17+
{types.I8, types.I8Ptr,
18+
"OK"},
19+
20+
{types.I64, types.I8Ptr,
21+
"store operands are not compatible: src=i64; dst=i8*"},
22+
{types.I8, types.I8,
23+
"invalid store dst operand type; expected *types.Pointer, got *types.IntType"},
24+
}
25+
26+
errOK := errors.New("OK")
27+
28+
for _, c := range cases {
29+
testName := fmt.Sprintf("%v to %v", c.fromTyp, c.toTyp)
30+
t.Run(testName, func(t *testing.T) {
31+
var panicErr error
32+
fromVal := constant.NewZeroInitializer(c.fromTyp)
33+
toVal := constant.NewZeroInitializer(c.toTyp)
34+
func() {
35+
defer func() { panicErr = recover().(error) }()
36+
store := NewStore(fromVal, toVal)
37+
_ = store.LLString()
38+
panic(errOK)
39+
}()
40+
got := panicErr.Error()
41+
if got != c.panicMessage {
42+
t.Errorf("expected %q, got %q", c.panicMessage, got)
43+
}
44+
})
45+
}
46+
}

0 commit comments

Comments
 (0)