diff --git a/examples/point/point.q b/examples/point/point.q new file mode 100644 index 0000000..8c90e1f --- /dev/null +++ b/examples/point/point.q @@ -0,0 +1,11 @@ +struct Point { + x Int + y Int +} + +main() { + p := new(Point) + p.x = 4 + p.y = 2 + delete(p) +} \ No newline at end of file diff --git a/lib/sys/sys_linux.q b/lib/sys/sys_linux.q index c1207f7..a2f0e97 100644 --- a/lib/sys/sys_linux.q +++ b/lib/sys/sys_linux.q @@ -22,8 +22,8 @@ munmap(address Pointer, length Int) -> Int { return syscall(11, address, length) } -nanosleep(timespec Pointer) -> Int { - return syscall(35, timespec, 0) +nanosleep(duration Pointer) -> Int { + return syscall(35, duration, 0) } clone(flags Int, stack Pointer) -> Int { diff --git a/lib/time/time.q b/lib/time/time.q index 9890e67..bd22148 100644 --- a/lib/time/time.q +++ b/lib/time/time.q @@ -1,4 +1,3 @@ -import mem import sys sleep(nanoseconds Int) { @@ -8,10 +7,9 @@ sleep(nanoseconds Int) { seconds, nanoseconds = nanoseconds / 1000000000 } - timespec := mem.alloc(16) - store(timespec, 8, seconds) - offset := timespec + 8 - store(offset, 8, nanoseconds) - sys.nanosleep(timespec) - mem.free(timespec, 16) + duration := new(timespec) + duration.seconds = seconds + duration.nanoseconds = nanoseconds + sys.nanosleep(duration) + delete(duration) } \ No newline at end of file diff --git a/src/asm/MemoryLabel.go b/src/asm/MemoryLabel.go index 0d4ebf7..63108c8 100644 --- a/src/asm/MemoryLabel.go +++ b/src/asm/MemoryLabel.go @@ -2,6 +2,7 @@ package asm import ( "fmt" + "math" ) // MemoryLabel operates with a memory address and a number. @@ -12,6 +13,10 @@ type MemoryLabel struct { // String returns a human readable version. func (data *MemoryLabel) String() string { + if data.Address.OffsetRegister == math.MaxUint8 { + return fmt.Sprintf("%dB [%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.Offset, data.Label) + } + return fmt.Sprintf("%dB [%s+%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Label) } diff --git a/src/asm/MemoryNumber.go b/src/asm/MemoryNumber.go index 3e7a54a..1a255b3 100644 --- a/src/asm/MemoryNumber.go +++ b/src/asm/MemoryNumber.go @@ -2,6 +2,7 @@ package asm import ( "fmt" + "math" ) // MemoryNumber operates with a memory address and a number. @@ -12,6 +13,10 @@ type MemoryNumber struct { // String returns a human readable version. func (data *MemoryNumber) String() string { + if data.Address.OffsetRegister == math.MaxUint8 { + return fmt.Sprintf("%dB [%s+%d], %d", data.Address.Length, data.Address.Base, data.Address.Offset, data.Number) + } + return fmt.Sprintf("%dB [%s+%s+%d], %d", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Number) } diff --git a/src/asm/MemoryRegister.go b/src/asm/MemoryRegister.go index ae232e5..c35a3c8 100644 --- a/src/asm/MemoryRegister.go +++ b/src/asm/MemoryRegister.go @@ -2,6 +2,7 @@ package asm import ( "fmt" + "math" "git.akyoto.dev/cli/q/src/cpu" ) @@ -14,6 +15,10 @@ type MemoryRegister struct { // String returns a human readable version. func (data *MemoryRegister) String() string { + if data.Address.OffsetRegister == math.MaxUint8 { + return fmt.Sprintf("%dB [%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.Offset, data.Register) + } + return fmt.Sprintf("%dB [%s+%s+%d], %s", data.Address.Length, data.Address.Base, data.Address.OffsetRegister, data.Address.Offset, data.Register) } diff --git a/src/compiler/Compile.go b/src/compiler/Compile.go index dd35a48..28ffb2e 100644 --- a/src/compiler/Compile.go +++ b/src/compiler/Compile.go @@ -10,11 +10,11 @@ import ( ) // Compile waits for the scan to finish and compiles all functions. -func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-chan *types.Type, errs <-chan error) (Result, error) { +func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-chan types.Type, errs <-chan error) (Result, error) { result := Result{} allFiles := make([]*fs.File, 0, 8) allFunctions := map[string]*core.Function{} - allTypes := map[string]*types.Type{} + allTypes := map[string]types.Type{} for functions != nil || files != nil || errs != nil { select { @@ -25,6 +25,7 @@ func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-c } function.Functions = allFunctions + function.Types = allTypes allFunctions[function.UniqueName] = function case typ, ok := <-structs: @@ -33,7 +34,7 @@ func Compile(files <-chan *fs.File, functions <-chan *core.Function, structs <-c continue } - allTypes[typ.Name] = typ + allTypes[typ.UniqueName()] = typ case file, ok := <-files: if !ok { diff --git a/src/core/CompileAssign.go b/src/core/CompileAssign.go index 8949cbc..6325e21 100644 --- a/src/core/CompileAssign.go +++ b/src/core/CompileAssign.go @@ -26,6 +26,10 @@ func (f *Function) CompileAssign(node *ast.Assign) error { return f.Execute(operator, variable.Register, right) } + if left.Token.Kind == token.Period { + return f.CompileAssignField(node) + } + if left.Token.Kind == token.Array { return f.CompileAssignArray(node) } diff --git a/src/core/CompileAssignField.go b/src/core/CompileAssignField.go new file mode 100644 index 0000000..4b74e78 --- /dev/null +++ b/src/core/CompileAssignField.go @@ -0,0 +1,44 @@ +package core + +import ( + "math" + + "git.akyoto.dev/cli/q/src/asm" + "git.akyoto.dev/cli/q/src/ast" + "git.akyoto.dev/cli/q/src/errors" + "git.akyoto.dev/cli/q/src/types" +) + +// CompileAssignField compiles a memory write to a struct field. +func (f *Function) CompileAssignField(node *ast.Assign) error { + destination := node.Expression.Children[0] + value := node.Expression.Children[1] + name := destination.Children[0].Token.Text(f.File.Bytes) + fieldName := destination.Children[1].Token.Text(f.File.Bytes) + variable := f.VariableByName(name) + + if variable == nil { + return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, destination.Children[0].Token.Position) + } + + defer f.UseVariable(variable) + pointer := variable.Type.(*types.Pointer) + structure := pointer.To.(*types.Struct) + + for _, field := range structure.Fields { + if field.Name == fieldName { + memory := asm.Memory{ + Base: variable.Register, + Offset: field.Offset, + OffsetRegister: math.MaxUint8, + Length: field.Type.TotalSize(), + } + + _, err := f.ExpressionToMemory(value, memory) + return err + } + } + + // TODO: unknown field error + return nil +} diff --git a/src/core/CompileCall.go b/src/core/CompileCall.go index a723240..f476d94 100644 --- a/src/core/CompileCall.go +++ b/src/core/CompileCall.go @@ -26,11 +26,20 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) { if nameNode.IsLeaf() { name = nameNode.Token.Text(f.File.Bytes) - if name == "syscall" { + switch name { + case "syscall": return nil, f.CompileSyscall(root) - } - - if name == "store" { + case "new": + return &Function{ + ReturnTypes: []types.Type{ + &types.Pointer{ + To: f.Types[root.Children[1].Token.Text(f.File.Bytes)], + }, + }, + }, f.CompileNew(root) + case "delete": + return nil, f.CompileDelete(root) + case "store": return nil, f.CompileMemoryStore(root) } } else { @@ -85,8 +94,8 @@ func (f *Function) CompileCall(root *expression.Expression) (*Function, error) { if !types.Check(typ, fn.Parameters[i].Type) { return nil, errors.New(&errors.TypeMismatch{ - Encountered: typ.Name, - Expected: fn.Parameters[i].Type.Name, + Encountered: typ.UniqueName(), + Expected: fn.Parameters[i].Type.UniqueName(), ParameterName: fn.Parameters[i].Name, }, f.File, parameters[i].Token.Position) } diff --git a/src/core/CompileDelete.go b/src/core/CompileDelete.go new file mode 100644 index 0000000..1e1b475 --- /dev/null +++ b/src/core/CompileDelete.go @@ -0,0 +1,37 @@ +package core + +import ( + "git.akyoto.dev/cli/q/src/asm" + "git.akyoto.dev/cli/q/src/expression" + "git.akyoto.dev/cli/q/src/types" +) + +// CompileDelete compiles a `delete` function call which deallocates a struct. +func (f *Function) CompileDelete(root *expression.Expression) error { + parameters := root.Children[1:] + variableName := parameters[0].Token.Text(f.File.Bytes) + variable := f.VariableByName(variableName) + defer f.UseVariable(variable) + f.SaveRegister(f.CPU.Input[0]) + f.SaveRegister(f.CPU.Input[1]) + f.RegisterRegister(asm.MOVE, f.CPU.Input[0], variable.Register) + f.RegisterNumber(asm.MOVE, f.CPU.Input[1], int(variable.Type.(*types.Pointer).To.TotalSize())) + + for _, register := range f.CPU.General { + if f.RegisterIsUsed(register) { + f.Register(asm.PUSH, register) + } + } + + f.Call("mem.free") + + for i := len(f.CPU.General) - 1; i >= 0; i-- { + register := f.CPU.General[i] + + if f.RegisterIsUsed(register) { + f.Register(asm.POP, register) + } + } + + return nil +} diff --git a/src/core/CompileMemoryStore.go b/src/core/CompileMemoryStore.go index b0dd120..1c84e72 100644 --- a/src/core/CompileMemoryStore.go +++ b/src/core/CompileMemoryStore.go @@ -8,7 +8,7 @@ import ( "git.akyoto.dev/cli/q/src/expression" ) -// CompileMemoryStore ... +// CompileMemoryStore compiles a variable-width store to memory. func (f *Function) CompileMemoryStore(root *expression.Expression) error { parameters := root.Children[1:] name := parameters[0].Token.Text(f.File.Bytes) diff --git a/src/core/CompileNew.go b/src/core/CompileNew.go new file mode 100644 index 0000000..04c6eb1 --- /dev/null +++ b/src/core/CompileNew.go @@ -0,0 +1,33 @@ +package core + +import ( + "git.akyoto.dev/cli/q/src/asm" + "git.akyoto.dev/cli/q/src/expression" +) + +// CompileNew compiles a `new` function call which allocates a struct. +func (f *Function) CompileNew(root *expression.Expression) error { + parameters := root.Children[1:] + structName := parameters[0].Token.Text(f.File.Bytes) + typ := f.Types[structName] + f.SaveRegister(f.CPU.Input[0]) + f.RegisterNumber(asm.MOVE, f.CPU.Input[0], int(typ.TotalSize())) + + for _, register := range f.CPU.General { + if f.RegisterIsUsed(register) { + f.Register(asm.PUSH, register) + } + } + + f.Call("mem.alloc") + + for i := len(f.CPU.General) - 1; i >= 0; i-- { + register := f.CPU.General[i] + + if f.RegisterIsUsed(register) { + f.Register(asm.POP, register) + } + } + + return nil +} diff --git a/src/core/CompileReturn.go b/src/core/CompileReturn.go index 8fa72c8..023da02 100644 --- a/src/core/CompileReturn.go +++ b/src/core/CompileReturn.go @@ -27,8 +27,8 @@ func (f *Function) CompileReturn(node *ast.Return) error { if !types.Check(typ, f.ReturnTypes[i]) { return errors.New(&errors.TypeMismatch{ - Encountered: typ.Name, - Expected: f.ReturnTypes[i].Name, + Encountered: typ.UniqueName(), + Expected: f.ReturnTypes[i].UniqueName(), ParameterName: "", IsReturn: true, }, f.File, node.Values[i].Token.Position) diff --git a/src/core/Evaluate.go b/src/core/Evaluate.go index 349c077..cd3f384 100644 --- a/src/core/Evaluate.go +++ b/src/core/Evaluate.go @@ -8,7 +8,7 @@ import ( ) // Evaluate evaluates an expression and returns a register that contains the value of the expression. -func (f *Function) Evaluate(expr *expression.Expression) (*types.Type, cpu.Register, bool, error) { +func (f *Function) Evaluate(expr *expression.Expression) (types.Type, cpu.Register, bool, error) { if expr.Token.Kind == token.Identifier { name := expr.Token.Text(f.File.Bytes) variable := f.VariableByName(name) diff --git a/src/core/ExpressionToMemory.go b/src/core/ExpressionToMemory.go index 29ca917..e50262d 100644 --- a/src/core/ExpressionToMemory.go +++ b/src/core/ExpressionToMemory.go @@ -10,21 +10,21 @@ import ( ) // ExpressionToMemory puts the result of an expression into the specified memory address. -func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Memory) (*types.Type, error) { +func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Memory) (types.Type, error) { if node.IsLeaf() { if node.Token.Kind == token.Identifier { name := node.Token.Text(f.File.Bytes) variable, function := f.Identifier(name) if variable != nil { - f.UseVariable(variable) f.MemoryRegister(asm.STORE, memory, variable.Register) - return types.Pointer, nil + f.UseVariable(variable) + return types.PointerAny, nil } if function != nil { f.MemoryLabel(asm.STORE, memory, function.UniqueName) - return types.Pointer, nil + return types.PointerAny, nil } return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, node.Token.Position) @@ -39,7 +39,7 @@ func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Me size := byte(sizeof.Signed(int64(number))) - if size != memory.Length { + if size > memory.Length { return nil, errors.New(&errors.NumberExceedsBounds{Number: number, ExpectedSize: memory.Length, Size: size}, f.File, node.Token.Position) } diff --git a/src/core/ExpressionToRegister.go b/src/core/ExpressionToRegister.go index 7c5b31f..16d8e7c 100644 --- a/src/core/ExpressionToRegister.go +++ b/src/core/ExpressionToRegister.go @@ -11,7 +11,7 @@ import ( ) // ExpressionToRegister puts the result of an expression into the specified register. -func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) (*types.Type, error) { +func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) (types.Type, error) { f.SaveRegister(register) if node.IsFolded { @@ -72,7 +72,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp return nil, err } - if typ == types.Pointer && right.Token.Kind == token.Identifier && f.VariableByName(right.Token.Text(f.File.Bytes)).Type == types.Pointer { + if typ == types.PointerAny && right.Token.Kind == token.Identifier && f.VariableByName(right.Token.Text(f.File.Bytes)).Type == types.PointerAny { typ = types.Int } diff --git a/src/core/Function.go b/src/core/Function.go index 4694800..966b00c 100644 --- a/src/core/Function.go +++ b/src/core/Function.go @@ -18,8 +18,9 @@ type Function struct { File *fs.File Body token.List Parameters []*scope.Variable - ReturnTypes []*types.Type + ReturnTypes []types.Type Functions map[string]*Function + Types map[string]types.Type DLLs dll.List Err error deferred []func() diff --git a/src/core/TokenToRegister.go b/src/core/TokenToRegister.go index 8f8d53a..af65813 100644 --- a/src/core/TokenToRegister.go +++ b/src/core/TokenToRegister.go @@ -10,7 +10,7 @@ import ( // TokenToRegister moves a token into a register. // It only works with identifiers, numbers and strings. -func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (*types.Type, error) { +func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (types.Type, error) { switch t.Kind { case token.Identifier: name := t.Text(f.File.Bytes) @@ -26,7 +26,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (*types if function != nil { f.SaveRegister(register) f.RegisterLabel(asm.MOVE, register, function.UniqueName) - return types.Pointer, nil + return types.PointerAny, nil } return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position) @@ -48,7 +48,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (*types label := f.AddBytes(data) f.SaveRegister(register) f.RegisterLabel(asm.MOVE, register, label) - return types.Pointer, nil + return types.PointerAny, nil default: return nil, errors.New(errors.InvalidExpression, f.File, t.Position) diff --git a/src/scanner/Scan.go b/src/scanner/Scan.go index df17032..f2d3163 100644 --- a/src/scanner/Scan.go +++ b/src/scanner/Scan.go @@ -1,20 +1,25 @@ package scanner import ( + "path/filepath" + + "git.akyoto.dev/cli/q/src/config" "git.akyoto.dev/cli/q/src/core" "git.akyoto.dev/cli/q/src/fs" "git.akyoto.dev/cli/q/src/types" ) // Scan scans the list of files. -func Scan(files []string) (<-chan *fs.File, <-chan *core.Function, <-chan *types.Type, <-chan error) { +func Scan(files []string) (<-chan *fs.File, <-chan *core.Function, <-chan types.Type, <-chan error) { scanner := Scanner{ files: make(chan *fs.File), functions: make(chan *core.Function), - types: make(chan *types.Type), + types: make(chan types.Type), errors: make(chan error), } + scanner.queueDirectory(filepath.Join(config.Library, "mem"), "mem") + go func() { scanner.queue(files...) scanner.group.Wait() diff --git a/src/scanner/Scanner.go b/src/scanner/Scanner.go index f1f0835..13485f5 100644 --- a/src/scanner/Scanner.go +++ b/src/scanner/Scanner.go @@ -12,7 +12,7 @@ import ( type Scanner struct { files chan *fs.File functions chan *core.Function - types chan *types.Type + types chan types.Type errors chan error queued sync.Map group sync.WaitGroup diff --git a/src/scanner/scanStruct.go b/src/scanner/scanStruct.go index dddf481..40ecf36 100644 --- a/src/scanner/scanStruct.go +++ b/src/scanner/scanStruct.go @@ -17,7 +17,7 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro structName := tokens[i].Text(file.Bytes) - typ := &types.Type{ + structure := &types.Struct{ Name: structName, } @@ -39,14 +39,14 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro fieldType := types.Parse(fieldTypeName) i++ - typ.Fields = append(typ.Fields, &types.Field{ + structure.Fields = append(structure.Fields, &types.Field{ Type: fieldType, Name: fieldName, Position: token.Position(fieldPosition), - Offset: typ.Size, + Offset: structure.Size, }) - typ.Size += fieldType.Size + structure.Size += fieldType.TotalSize() } if tokens[i].Kind == token.BlockEnd { @@ -61,6 +61,6 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro return i, errors.New(errors.MissingBlockEnd, file, tokens[i].Position) } - s.types <- typ + s.types <- structure return i, nil } diff --git a/src/scope/Variable.go b/src/scope/Variable.go index d64ddca..7387ab6 100644 --- a/src/scope/Variable.go +++ b/src/scope/Variable.go @@ -7,7 +7,7 @@ import ( // Variable represents a named register. type Variable struct { - Type *types.Type + Type types.Type Name string Alive uint8 Register cpu.Register diff --git a/src/types/Base.go b/src/types/Base.go index f28b5dd..5f3d27b 100644 --- a/src/types/Base.go +++ b/src/types/Base.go @@ -1,13 +1,13 @@ package types var ( - Float64 = &Type{Name: "Float64", Size: 8} - Float32 = &Type{Name: "Float32", Size: 4} - Int64 = &Type{Name: "Int64", Size: 8} - Int32 = &Type{Name: "Int32", Size: 4} - Int16 = &Type{Name: "Int16", Size: 2} - Int8 = &Type{Name: "Int8", Size: 1} - Pointer = &Type{Name: "Pointer", Size: 8} + Float64 = &Struct{Name: "Float64", Size: 8} + Float32 = &Struct{Name: "Float32", Size: 4} + Int64 = &Struct{Name: "Int64", Size: 8} + Int32 = &Struct{Name: "Int32", Size: 4} + Int16 = &Struct{Name: "Int16", Size: 2} + Int8 = &Struct{Name: "Int8", Size: 1} + PointerAny = &Pointer{To: nil} ) var ( diff --git a/src/types/Check.go b/src/types/Check.go index dbf9808..fe1eb20 100644 --- a/src/types/Check.go +++ b/src/types/Check.go @@ -1,6 +1,21 @@ package types -// Check returns true if the first type can be converted into the second type. -func Check(a *Type, b *Type) bool { - return a == nil || a == b +// Check returns true if the encountered type `a` can be converted into the expected type `b`. +func Check(a Type, b Type) bool { + if a == nil { + return true + } + + if a == b { + return true + } + + aPointer, aIsPointer := a.(*Pointer) + bPointer, bIsPointer := b.(*Pointer) + + if aIsPointer && bIsPointer && (bPointer.To == nil || aPointer.To == bPointer.To) { + return true + } + + return false } diff --git a/src/types/Field.go b/src/types/Field.go index aa0d554..6e155ff 100644 --- a/src/types/Field.go +++ b/src/types/Field.go @@ -4,7 +4,7 @@ import "git.akyoto.dev/cli/q/src/token" // Field is a field in a data structure. type Field struct { - Type *Type + Type Type Name string Position token.Position Offset uint8 diff --git a/src/types/Parse.go b/src/types/Parse.go index 0cfc305..6fcc1f2 100644 --- a/src/types/Parse.go +++ b/src/types/Parse.go @@ -1,7 +1,7 @@ package types // Parse creates a new type from a list of tokens. -func Parse(name string) *Type { +func Parse(name string) Type { switch name { case "Int": return Int @@ -20,7 +20,7 @@ func Parse(name string) *Type { case "Float32": return Float32 case "Pointer": - return Pointer + return PointerAny default: panic("Unknown type " + name) } diff --git a/src/types/ParseList.go b/src/types/ParseList.go index 56a8592..137aec2 100644 --- a/src/types/ParseList.go +++ b/src/types/ParseList.go @@ -3,8 +3,8 @@ package types import "git.akyoto.dev/cli/q/src/token" // ParseList generates a list of types from comma separated tokens. -func ParseList(tokens token.List, source []byte) []*Type { - var list []*Type +func ParseList(tokens token.List, source []byte) []Type { + var list []Type tokens.Split(func(parameter token.List) error { typ := Parse(parameter.Text(source)) diff --git a/src/types/Pointer.go b/src/types/Pointer.go new file mode 100644 index 0000000..ccc92e7 --- /dev/null +++ b/src/types/Pointer.go @@ -0,0 +1,17 @@ +package types + +type Pointer struct { + To Type +} + +func (p *Pointer) UniqueName() string { + if p.To == nil { + return "Pointer" + } + + return "Pointer:" + p.To.UniqueName() +} + +func (p *Pointer) TotalSize() uint8 { + return 8 +} diff --git a/src/types/Struct.go b/src/types/Struct.go new file mode 100644 index 0000000..d6f7c7a --- /dev/null +++ b/src/types/Struct.go @@ -0,0 +1,16 @@ +package types + +// Struct is a structure in memory whose regions are addressable with fields. +type Struct struct { + Name string + Fields []*Field + Size uint8 +} + +func (s *Struct) UniqueName() string { + return s.Name +} + +func (s *Struct) TotalSize() uint8 { + return s.Size +} diff --git a/src/types/Type.go b/src/types/Type.go index d9ce347..d548867 100644 --- a/src/types/Type.go +++ b/src/types/Type.go @@ -1,8 +1,6 @@ package types -// Type represents a type in the type system. -type Type struct { - Name string - Fields []*Field - Size uint8 +type Type interface { + UniqueName() string + TotalSize() uint8 } diff --git a/src/x64/Registers.go b/src/x64/Registers.go index 0dc55b9..57d4e8b 100644 --- a/src/x64/Registers.go +++ b/src/x64/Registers.go @@ -25,7 +25,7 @@ var ( AllRegisters = []cpu.Register{RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15} SyscallInputRegisters = []cpu.Register{RAX, RDI, RSI, RDX, R10, R8, R9} SyscallOutputRegisters = []cpu.Register{RAX, RCX, R11} - GeneralRegisters = []cpu.Register{RCX, RBX, RBP, R11, R12, R13, R14, R15} + GeneralRegisters = []cpu.Register{RCX, RBX, R11, R12, R13, R14, R15, RBP} InputRegisters = SyscallInputRegisters OutputRegisters = SyscallInputRegisters WindowsInputRegisters = []cpu.Register{RCX, RDX, R8, R9}