all: basic support for the os package
The resulting binary is pretty big due to lacking optimizations (probably because of interfaces), so that should be fixed.
Этот коммит содержится в:
		
							родитель
							
								
									c237633d34
								
							
						
					
					
						коммит
						1484bb5c2c
					
				
					 6 изменённых файлов: 141 добавлений и 3 удалений
				
			
		| 
						 | 
				
			
			@ -22,6 +22,7 @@ var ignoreInitCalls = map[string]struct{}{
 | 
			
		|||
	"(syscall/js.Value).Get": struct{}{},
 | 
			
		||||
	"(syscall/js.Value).New": struct{}{},
 | 
			
		||||
	"(syscall/js.Value).Int": struct{}{},
 | 
			
		||||
	"os.init$1":              struct{}{},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Interpret instructions as far as possible, and drop those instructions from
 | 
			
		||||
| 
						 | 
				
			
			@ -91,14 +92,67 @@ func (p *Program) interpret(instrs []ssa.Instruction, paramKeys []*ssa.Parameter
 | 
			
		|||
			if callee == nil {
 | 
			
		||||
				return i, nil // don't understand dynamic dispatch
 | 
			
		||||
			}
 | 
			
		||||
			if _, ok := ignoreInitCalls[callee.String()]; ok && callee.Signature.Results().Len() == 1 {
 | 
			
		||||
			if _, ok := ignoreInitCalls[callee.String()]; ok {
 | 
			
		||||
				// These calls are not needed and can be ignored, for the time
 | 
			
		||||
				// being.
 | 
			
		||||
				var err error
 | 
			
		||||
				locals[instr], err = p.getZeroValue(callee.Signature.Results().At(0).Type())
 | 
			
		||||
				results := make([]Value, callee.Signature.Results().Len())
 | 
			
		||||
				for i := range results {
 | 
			
		||||
					var err error
 | 
			
		||||
					results[i], err = p.getZeroValue(callee.Signature.Results().At(i).Type())
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return i, err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if len(results) == 1 {
 | 
			
		||||
					locals[instr] = results[0]
 | 
			
		||||
				} else if len(results) > 1 {
 | 
			
		||||
					locals[instr] = &StructValue{Fields: results}
 | 
			
		||||
				}
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if callee.String() == "os.NewFile" {
 | 
			
		||||
				// Emulate the creation of os.Stdin, os.Stdout and os.Stderr.
 | 
			
		||||
				resultPtrType := callee.Signature.Results().At(0).Type().(*types.Pointer)
 | 
			
		||||
				resultStructOuterType := resultPtrType.Elem().Underlying().(*types.Struct)
 | 
			
		||||
				if resultStructOuterType.NumFields() != 1 {
 | 
			
		||||
					panic("expected 1 field in os.File struct")
 | 
			
		||||
				}
 | 
			
		||||
				fileInnerPtrType := resultStructOuterType.Field(0).Type().(*types.Pointer)
 | 
			
		||||
				fileInnerType := fileInnerPtrType.Elem().(*types.Named)
 | 
			
		||||
				fileInnerStructType := fileInnerType.Underlying().(*types.Struct)
 | 
			
		||||
				fileInner, err := p.getZeroValue(fileInnerType) // os.file
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return i, err
 | 
			
		||||
				}
 | 
			
		||||
				for fieldIndex := 0; fieldIndex < fileInnerStructType.NumFields(); fieldIndex++ {
 | 
			
		||||
					field := fileInnerStructType.Field(fieldIndex)
 | 
			
		||||
					if field.Name() == "name" {
 | 
			
		||||
						// Set the 'name' field.
 | 
			
		||||
						name, err := p.getValue(common.Args[1], locals)
 | 
			
		||||
						if err != nil {
 | 
			
		||||
							return i, err
 | 
			
		||||
						}
 | 
			
		||||
						fileInner.(*StructValue).Fields[fieldIndex] = name
 | 
			
		||||
					} else if field.Type().String() == "internal/poll.FD" {
 | 
			
		||||
						// Set the file descriptor field.
 | 
			
		||||
						field := field.Type().Underlying().(*types.Struct)
 | 
			
		||||
						for subfieldIndex := 0; subfieldIndex < field.NumFields(); subfieldIndex++ {
 | 
			
		||||
							subfield := field.Field(subfieldIndex)
 | 
			
		||||
							if subfield.Name() == "Sysfd" {
 | 
			
		||||
								sysfd, err := p.getValue(common.Args[0], locals)
 | 
			
		||||
								if err != nil {
 | 
			
		||||
									return i, err
 | 
			
		||||
								}
 | 
			
		||||
								sysfd = &ConstValue{Expr: ssa.NewConst(sysfd.(*ConstValue).Expr.Value, subfield.Type())}
 | 
			
		||||
								fileInner.(*StructValue).Fields[fieldIndex].(*StructValue).Fields[subfieldIndex] = sysfd
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				fileInnerPtr := &PointerValue{fileInnerPtrType, &fileInner}                                   // *os.file
 | 
			
		||||
				var fileOuter Value = &StructValue{Type: resultPtrType.Elem(), Fields: []Value{fileInnerPtr}} // os.File
 | 
			
		||||
				result := &PointerValue{resultPtrType.Elem(), &fileOuter}                                     // *os.File
 | 
			
		||||
				locals[instr] = result
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
			if canInterpret(callee) {
 | 
			
		||||
| 
						 | 
				
			
			@ -165,6 +219,12 @@ func (p *Program) interpret(instrs []ssa.Instruction, paramKeys []*ssa.Parameter
 | 
			
		|||
			}
 | 
			
		||||
		case *ssa.DebugRef:
 | 
			
		||||
			// ignore
 | 
			
		||||
		case *ssa.Extract:
 | 
			
		||||
			tuple, err := p.getValue(instr.Tuple, locals)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return i, err
 | 
			
		||||
			}
 | 
			
		||||
			locals[instr] = tuple.(*StructValue).Fields[instr.Index]
 | 
			
		||||
		case *ssa.FieldAddr:
 | 
			
		||||
			x, err := p.getValue(instr.X, locals)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -311,6 +371,7 @@ func canInterpret(callee *ssa.Function) bool {
 | 
			
		|||
		case *ssa.Alloc:
 | 
			
		||||
		case *ssa.Convert:
 | 
			
		||||
		case *ssa.DebugRef:
 | 
			
		||||
		case *ssa.Extract:
 | 
			
		||||
		case *ssa.FieldAddr:
 | 
			
		||||
		case *ssa.IndexAddr:
 | 
			
		||||
		case *ssa.MakeInterface:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								src/runtime/atomic.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										24
									
								
								src/runtime/atomic.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
package runtime
 | 
			
		||||
 | 
			
		||||
// This file contains implementations for the sync/atomic package.
 | 
			
		||||
 | 
			
		||||
// All implementations assume there are no goroutines, threads or interrupts.
 | 
			
		||||
 | 
			
		||||
//go:linkname loadUint64 sync/atomic.LoadUint64
 | 
			
		||||
func loadUint64(addr *uint64) uint64 {
 | 
			
		||||
	return *addr
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//go:linkname storeUint32 sync/atomic.StoreUint32
 | 
			
		||||
func storeUint32(addr *uint32, val uint32) {
 | 
			
		||||
	*addr = val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//go:linkname compareAndSwapUint64 sync/atomic.CompareAndSwapUint64
 | 
			
		||||
func compareAndSwapUint64(addr *uint64, old, new uint64) bool {
 | 
			
		||||
	if *addr == old {
 | 
			
		||||
		*addr = new
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return false
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								src/runtime/poll.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										23
									
								
								src/runtime/poll.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
package runtime
 | 
			
		||||
 | 
			
		||||
// This file implements stub functions for internal/poll.
 | 
			
		||||
 | 
			
		||||
//go:linkname poll_runtime_pollServerInit internal/poll.runtime_pollServerInit
 | 
			
		||||
func poll_runtime_pollServerInit(ctx *uint8) {
 | 
			
		||||
	panic("todo: runtime_pollServerInit")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//go:linkname poll_runtime_pollOpen internal/poll.runtime_pollOpen
 | 
			
		||||
func poll_runtime_pollOpen(fd uintptr) (uintptr, int) {
 | 
			
		||||
	panic("todo: runtime_pollOpen")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//go:linkname poll_runtime_pollClose internal/poll.runtime_pollClose
 | 
			
		||||
func poll_runtime_pollClose(ctx uintptr) {
 | 
			
		||||
	panic("todo: runtime_pollClose")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//go:linkname poll_runtime_pollUnblock internal/poll.runtime_pollUnblock
 | 
			
		||||
func poll_runtime_pollUnblock(ctx uintptr) {
 | 
			
		||||
	panic("todo: runtime_pollUnblock")
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -49,6 +49,11 @@ func GOROOT() string {
 | 
			
		|||
	return "/usr/local/go"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//go:linkname os_runtime_args os.runtime_args
 | 
			
		||||
func os_runtime_args() []string {
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Copy size bytes from src to dst. The memory areas must not overlap.
 | 
			
		||||
func memcpy(dst, src unsafe.Pointer, size uintptr) {
 | 
			
		||||
	for i := uintptr(0); i < size; i++ {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1 +1,13 @@
 | 
			
		|||
package runtime
 | 
			
		||||
 | 
			
		||||
// This file contains stub implementations for internal/poll.
 | 
			
		||||
 | 
			
		||||
//go:linkname semacquire internal/poll.runtime_Semacquire
 | 
			
		||||
func semacquire(sema *uint32) {
 | 
			
		||||
	panic("todo: semacquire")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//go:linkname semrelease internal/poll.runtime_Semrelease
 | 
			
		||||
func semrelease(sema *uint32) {
 | 
			
		||||
	panic("todo: semrelease")
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										13
									
								
								src/runtime/syscall.go
									
										
									
									
									
										Обычный файл
									
								
							
							
						
						
									
										13
									
								
								src/runtime/syscall.go
									
										
									
									
									
										Обычный файл
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
package runtime
 | 
			
		||||
 | 
			
		||||
// This file implements syscall.Syscall and the like.
 | 
			
		||||
 | 
			
		||||
//go:linkname syscall_Syscall syscall.Syscall
 | 
			
		||||
func syscall_Syscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err uintptr) {
 | 
			
		||||
	panic("syscall")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//go:linkname syscall_Syscall6 syscall.Syscall6
 | 
			
		||||
func syscall_Syscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err uintptr) {
 | 
			
		||||
	panic("syscall6")
 | 
			
		||||
}
 | 
			
		||||
		Загрузка…
	
	Создание таблицы
		
		Сослаться в новой задаче