diff --git a/core/uint.go b/core/uint.go index 68c7bf2..3bdb25c 100644 --- a/core/uint.go +++ b/core/uint.go @@ -14,10 +14,7 @@ type UsmUint = uint32 const UsmUintBitSize = 8 * unsafe.Sizeof(UsmUint(0)) func ParseUint(s string) (UsmUint, error) { - // TODO: assert that strconv.ParseUint does not have edge cases and is dead - // simple, so it won't break our grammar and allow weird behavior which is - // not defined in the USM spec. - n, err := strconv.ParseUint(s, 10, int(UsmUintBitSize)) + n, err := strconv.ParseUint(s, 0, int(UsmUintBitSize)) return UsmUint(n), err } diff --git a/core/uint_test.go b/core/uint_test.go index 84263e1..3a7a23d 100644 --- a/core/uint_test.go +++ b/core/uint_test.go @@ -18,9 +18,10 @@ func TestParseUintDecimal(t *testing.T) { // expected behavior). // TODO: consider adding support for other bases? -func TestParseUintBinaryFail(t *testing.T) { - _, err := core.ParseUint("0b101") - assert.NotNil(t, err) +func TestParseUintBinary(t *testing.T) { + n, err := core.ParseUint("0b101") + assert.Nil(t, err) + assert.Equal(t, core.UsmUint(5), n) } func TestParseUintPadding(t *testing.T) { diff --git a/gen/type.go b/gen/type.go index a55702f..ca6f9e1 100644 --- a/gen/type.go +++ b/gen/type.go @@ -40,44 +40,11 @@ type TypeDescriptorInfo struct { type ReferencedTypeInfo struct { // A pointer to the base, named type that this type reference refers to. Base *NamedTypeInfo + Size core.UsmUint Descriptors []TypeDescriptorInfo Declaration core.UnmanagedSourceView } -// Calculate the size of the type. -// Iterates over all type descriptors in linear time. -func (i *ReferencedTypeInfo) Size( - archInfo *ArchInfo, -) (core.UsmUint, core.ResultList) { - size := core.UsmUint(i.Base.Size) - - for _, descriptor := range i.Descriptors { - switch descriptor.Type { - case PointerTypeDescriptor: - size = archInfo.PointerSize - case RepeatTypeDescriptor: - var ok bool - size, ok = core.Mul(size, descriptor.Amount) - if !ok { - return 0, list.FromSingle(core.Result{{ - Type: core.ErrorResult, - Message: "Type size overflow", - Location: &i.Declaration, - }}) - } - default: - // notest - return 0, list.FromSingle(core.Result{{ - Type: core.InternalErrorResult, - Message: "Unknown type descriptor", - Location: &i.Declaration, - }}) - } - } - - return size, core.ResultList{} -} - // MARK: Manager type TypeManager interface { @@ -202,7 +169,43 @@ func NewReferencedTypeGenerator[InstT BaseInstruction]() Generator[InstT, parse. DescriptorGenerator: NewDescriptorGenerator[InstT](), }, ) +} + +func (g *ReferencedTypeGenerator[InstT]) calculateTypeSize( + ctx *GenerationContext[InstT], + node parse.TypeNode, + baseType *NamedTypeInfo, + descriptors []TypeDescriptorInfo, +) (core.UsmUint, core.ResultList) { + size := core.UsmUint(baseType.Size) + + for _, descriptor := range descriptors { + switch descriptor.Type { + case PointerTypeDescriptor: + size = ctx.ArchInfo.PointerSize + case RepeatTypeDescriptor: + var ok bool + size, ok = core.Mul(size, descriptor.Amount) + if !ok { + v := node.View() + return 0, list.FromSingle(core.Result{{ + Type: core.ErrorResult, + Message: "Type size overflow", + Location: &v, + }}) + } + default: + // notest + v := node.View() + return 0, list.FromSingle(core.Result{{ + Type: core.InternalErrorResult, + Message: "Unknown type descriptor", + Location: &v, + }}) + } + } + return size, core.ResultList{} } func (g *ReferencedTypeGenerator[InstT]) Generate( @@ -233,8 +236,14 @@ func (g *ReferencedTypeGenerator[InstT]) Generate( descriptors = append(descriptors, descriptorInfo) } + size, results := g.calculateTypeSize(ctx, node, baseType, descriptors) + if !results.IsEmpty() { + return nil, results + } + typeInfo := &ReferencedTypeInfo{ Base: baseType, + Size: size, Descriptors: descriptors, Declaration: node.View(), } @@ -293,14 +302,9 @@ func (g *NamedTypeGenerator[InstT]) Generate( return nil, results } - typeSize, results := referencedTypeInfo.Size(&ctx.ArchInfo) - if !results.IsEmpty() { - return nil, results - } - typeInfo = &NamedTypeInfo{ Name: identifier, - Size: typeSize, + Size: referencedTypeInfo.Size, Declaration: declaration, }