diff --git a/src/runtime/print.go b/src/runtime/print.go index a22b2efe..bb606827 100644 --- a/src/runtime/print.go +++ b/src/runtime/print.go @@ -1,12 +1,40 @@ package runtime +import ( + "unsafe" +) + func printstring(s string) { for i := 0; i < len(s); i++ { putchar(s[i]) } } +func printuint8(n uint8) { + if TargetBits >= 32 { + printuint32(uint32(n)) + } else { + prevdigits := n / 10 + if prevdigits != 0 { + printuint8(prevdigits) + } + putchar(byte((n % 10) + '0')) + } +} + +func printint8(n int8) { + if TargetBits >= 32 { + printint32(int32(n)) + } else { + if n < 0 { + putchar('-') + n = -n + } + printuint8(uint8(n)) + } +} + func printuint32(n uint32) { // TODO: don't recurse, but still be compact (and don't divide/mod // more than necessary). @@ -64,3 +92,17 @@ func printitf(msg interface{}) { print("???") } } + +func printptr(ptr uintptr) { + putchar('0') + putchar('x') + for i := 0; i < int(unsafe.Sizeof(ptr)) * 2; i++ { + nibble := byte(ptr >> (unsafe.Sizeof(ptr) * 8 - 4)) + if nibble < 10 { + putchar(nibble + '0') + } else { + putchar(nibble - 10 + 'a') + } + ptr <<= 4 + } +} diff --git a/src/runtime/runtime.go b/src/runtime/runtime.go index 92d1a2ed..ac8ee4ca 100644 --- a/src/runtime/runtime.go +++ b/src/runtime/runtime.go @@ -3,6 +3,9 @@ package runtime const Compiler = "tgo" +// The bitness of the CPU (e.g. 8, 32, 64). Set by the compiler as a constant. +var TargetBits uint8 + func _panic(message interface{}) { printstring("panic: ") printitf(message) diff --git a/tgo.go b/tgo.go index 8f035b1f..a801d195 100644 --- a/tgo.go +++ b/tgo.go @@ -113,7 +113,12 @@ func (c *Compiler) Parse(mainPath string, buildTags []string) error { tripleSplit := strings.Split(c.triple, "-") config := loader.Config { - // TODO: TypeChecker.Sizes + TypeChecker: types.Config{ + Sizes: &types.StdSizes{ + int64(c.targetData.PointerSize()), + int64(c.targetData.PrefTypeAlignment(c.i8ptrType)), + }, + }, Build: &build.Context { GOARCH: tripleSplit[0], GOOS: tripleSplit[2], @@ -390,11 +395,25 @@ func (c *Compiler) parsePackage(program *ssa.Program, pkg *ssa.Package) error { global := llvm.AddGlobal(c.mod, llvmType, c.getGlobalName(member)) if !strings.HasPrefix(member.Name(), "_extern_") { global.SetLinkage(llvm.PrivateLinkage) - initializer, err := c.getZeroValue(llvmType) - if err != nil { - return err + if c.getGlobalName(member) == "runtime.TargetBits" { + bitness := c.targetData.PointerSize() + if bitness < 32 { + // Only 8 and 32+ architectures supported at the moment. + // On 8 bit architectures, pointers are normally bigger + // than 8 bits to do anything meaningful. + // TODO: clean up this hack to support 16-bit + // architectures. + bitness = 8 + } + global.SetInitializer(llvm.ConstInt(llvm.Int8Type(), uint64(bitness), false)) + global.SetGlobalConstant(true) + } else { + initializer, err := c.getZeroValue(llvmType) + if err != nil { + return err + } + global.SetInitializer(initializer) } - global.SetInitializer(initializer) } case *ssa.Type: ms := program.MethodSets.MethodSet(member.Type()) @@ -714,8 +733,10 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string) switch typ := typ.(type) { case *types.Basic: switch typ.Kind() { + case types.Int8: + c.builder.CreateCall(c.mod.NamedFunction("runtime.printint8"), []llvm.Value{value}, "") case types.Uint8: - c.builder.CreateCall(c.mod.NamedFunction("runtime.printbyte"), []llvm.Value{value}, "") + c.builder.CreateCall(c.mod.NamedFunction("runtime.printuint8"), []llvm.Value{value}, "") case types.Int, types.Int32: // TODO: assumes a 32-bit int type c.builder.CreateCall(c.mod.NamedFunction("runtime.printint32"), []llvm.Value{value}, "") case types.Uint, types.Uint32: @@ -726,9 +747,17 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string) c.builder.CreateCall(c.mod.NamedFunction("runtime.printuint64"), []llvm.Value{value}, "") case types.String: c.builder.CreateCall(c.mod.NamedFunction("runtime.printstring"), []llvm.Value{value}, "") + case types.Uintptr: + c.builder.CreateCall(c.mod.NamedFunction("runtime.printptr"), []llvm.Value{value}, "") + case types.UnsafePointer: + ptrValue := c.builder.CreatePtrToInt(value, c.uintptrType, "") + c.builder.CreateCall(c.mod.NamedFunction("runtime.printptr"), []llvm.Value{ptrValue}, "") default: return llvm.Value{}, errors.New("unknown basic arg type: " + fmt.Sprintf("%#v", typ)) } + case *types.Pointer: + ptrValue := c.builder.CreatePtrToInt(value, c.uintptrType, "") + c.builder.CreateCall(c.mod.NamedFunction("runtime.printptr"), []llvm.Value{ptrValue}, "") default: return llvm.Value{}, errors.New("unknown arg type: " + fmt.Sprintf("%#v", typ)) }