types.mx raw

   1  package emit
   2  
   3  import (
   4  	"git.smesh.lol/moxie/pkg/syntax"
   5  	"git.smesh.lol/moxie/pkg/ssa"
   6  	"git.smesh.lol/moxie/pkg/types"
   7  )
   8  
   9  func llvmArrayByteSize(t string) int64 {
  10  	if len(t) == 0 || t[0] != '[' {
  11  		return 0
  12  	}
  13  	i := 1
  14  	for i < len(t) && t[i] >= '0' && t[i] <= '9' {
  15  		i++
  16  	}
  17  	if i <= 1 {
  18  		return 0
  19  	}
  20  	n := int64(0)
  21  	for j := 1; j < i; j++ {
  22  		n = n*10 + int64(t[j]-'0')
  23  	}
  24  	xpos := -1
  25  	for k := i; k < len(t)-1; k++ {
  26  		if t[k] == 'x' && t[k-1] == ' ' && k+2 < len(t) && t[k+1] == ' ' {
  27  			xpos = k + 2
  28  			break
  29  		}
  30  	}
  31  	if xpos < 0 {
  32  		return 0
  33  	}
  34  	elemT := t[xpos:]
  35  	if len(elemT) > 0 && elemT[len(elemT)-1] == ']' {
  36  		elemT = elemT[:len(elemT)-1]
  37  	}
  38  	var elemSize int64
  39  	switch elemT {
  40  	case "i8":
  41  		elemSize = 1
  42  	case "i16":
  43  		elemSize = 2
  44  	case "i32", "float":
  45  		elemSize = 4
  46  	case "i64", "double", "ptr":
  47  		elemSize = 8
  48  	default:
  49  		inner := llvmArrayByteSize(elemT)
  50  		if inner > 0 {
  51  			elemSize = inner
  52  		} else {
  53  			elemSize = 8
  54  		}
  55  	}
  56  	return n * elemSize
  57  }
  58  
  59  func (e *irEmitter) emitZeroInit(typ, reg string) {
  60  	sz := llvmArrayByteSize(typ)
  61  	if sz >= 1024 {
  62  		e.w("  call void @llvm.memset.p0.i64(ptr ") ; e.w(reg) ; e.w(", i8 0, i64 ") ; e.w(irItoa64(sz)) ; e.w(", i1 false)\n")
  63  		e.declareRuntime("llvm.memset.p0.i64", "void", "ptr, i8, i64, i1")
  64  	} else {
  65  		e.w("  store ") ; e.w(typ) ; e.w(" zeroinitializer, ptr ") ; e.w(reg) ; e.w("\n")
  66  	}
  67  }
  68  
  69  func (e *irEmitter) regName(v ssa.SSAValue) string {
  70  	if v == nil {
  71  		e.nextReg++
  72  		return "%r" | irItoa(e.nextReg)
  73  	}
  74  	if n, ok := e.valName[v]; ok {
  75  		return n
  76  	}
  77  	name := v.SSAName()
  78  	if name == "" {
  79  		e.nextReg++
  80  		name = "r" | irItoa(e.nextReg)
  81  	}
  82  	n := "%" | name
  83  	for e.nameUsed[n] {
  84  		e.nextReg++
  85  		n = "%r" | irItoa(e.nextReg)
  86  	}
  87  	e.valName[v] = n
  88  	e.nameUsed[n] = true
  89  	return n
  90  }
  91  
  92  func (e *irEmitter) setRegType(v ssa.SSAValue, reg string, typ string) {
  93  	e.allocTypes[v] = typ
  94  	if len(reg) > 0 && reg[0] == '%' {
  95  		e.regTypes[reg] = typ
  96  	}
  97  }
  98  
  99  func (e *irEmitter) resolvedType(v ssa.SSAValue, fallback string) string {
 100  	if _, isIdx := v.(*ssa.SSAIndexAddr); isIdx {
 101  		return "ptr"
 102  	}
 103  	if at, ok := e.allocTypes[v]; ok {
 104  		return at
 105  	}
 106  	if n, ok := e.valName[v]; ok {
 107  		if rt, ok2 := e.regTypes[n]; ok2 {
 108  			return rt
 109  		}
 110  	}
 111  	op := e.operandNoSideEffect(v)
 112  	if len(op) > 0 && op[0] == '%' {
 113  		if rt, ok := e.regTypes[op]; ok {
 114  			return rt
 115  		}
 116  	}
 117  	return fallback
 118  }
 119  
 120  func (e *irEmitter) llvmType(t syntax.Type) string {
 121  	if t == nil {
 122  		return "void"
 123  	}
 124  	u := types.SafeUnderlying(t)
 125  	if u == nil {
 126  		if _, ok := t.(*types.Slice); ok {
 127  			return e.sliceType()
 128  		}
 129  		if n, ok := t.(*types.Named); ok {
 130  			_ = n
 131  			return "ptr"
 132  		}
 133  		return "ptr"
 134  	}
 135  	t = u
 136  	switch t := t.(type) {
 137  	case *types.Basic:
 138  		return e.llvmBasicType(t)
 139  	case *types.Pointer:
 140  		return "ptr"
 141  	case *types.Slice:
 142  		return e.sliceType()
 143  	case *types.Array:
 144  		n := t.Len()
 145  		if n < 0 {
 146  			return e.sliceType()
 147  		}
 148  		elem := e.llvmType(t.Elem())
 149  		return "[" | irItoa(int32(n)) | " x " | elem | "]"
 150  	case *types.TCStruct:
 151  		return e.llvmStructType(t)
 152  	case *types.Signature:
 153  		return "{ptr, ptr}"
 154  	case *types.TCMap:
 155  		return "ptr"
 156  	case *types.TCChan:
 157  		return "ptr"
 158  	case *types.TCInterface:
 159  		return e.ifaceType()
 160  	case *types.Named:
 161  		if t.Obj() != nil && t.Obj().Name() == "error" {
 162  			return e.ifaceType()
 163  		}
 164  		if t.NumMethods() > 0 && len(t.TypeArgs()) == 0 {
 165  			return e.ifaceType()
 166  		}
 167  		return "ptr"
 168  	case *types.Tuple:
 169  		if t == nil || t.Len() == 0 {
 170  			return "void"
 171  		}
 172  		if t.Len() == 1 {
 173  			return e.llvmType(t.At(0).Type())
 174  		}
 175  		s := "{"
 176  		for i := 0; i < t.Len(); i++ {
 177  			if i > 0 {
 178  				s = s | ", "
 179  			}
 180  			ft := e.llvmType(t.At(i).Type())
 181  			if ft == "void" {
 182  				ft = "ptr"
 183  			}
 184  			s = s | ft
 185  		}
 186  		return s | "}"
 187  	}
 188  	return "i8"
 189  }
 190  
 191  func (e *irEmitter) llvmBasicType(t *types.Basic) string {
 192  	switch t.Kind() {
 193  	case types.Bool:
 194  		return "i1"
 195  	case types.Int8, types.Uint8:
 196  		return "i8"
 197  	case types.Int16, types.Uint16:
 198  		return "i16"
 199  	case types.Int32, types.Uint32:
 200  		return "i32"
 201  	case types.Int64, types.Uint64:
 202  		return "i64"
 203  	case types.Float32:
 204  		return "float"
 205  	case types.Float64:
 206  		return "double"
 207  	case types.TCString:
 208  		return e.sliceType()
 209  	case types.UnsafePointer:
 210  		return "ptr"
 211  	case types.UntypedBool:
 212  		return "i1"
 213  	case types.UntypedInt, types.UntypedRune:
 214  		return "i32"
 215  	case types.UntypedFloat:
 216  		return "double"
 217  	case types.UntypedString:
 218  		return e.sliceType()
 219  	}
 220  	return "i32"
 221  }
 222  
 223  func (e *irEmitter) ptrType() string {
 224  	return "ptr"
 225  }
 226  
 227  func (e *irEmitter) intptrType() string {
 228  	if e.ptrBits == 32 {
 229  		return "i32"
 230  	}
 231  	return "i64"
 232  }
 233  
 234  func (e *irEmitter) sliceType() string {
 235  	ipt := e.intptrType()
 236  	return "{ptr, " | ipt | ", " | ipt | "}"
 237  }
 238  
 239  func (e *irEmitter) ifaceType() string {
 240  	return "{ptr, ptr}"
 241  }
 242  
 243  func (e *irEmitter) emitIntCast(dst, srcType, src, dstType string) string {
 244  	if srcType == dstType {
 245  		return src
 246  	}
 247  	srcBits := llvmTypeBits(srcType)
 248  	dstBits := llvmTypeBits(dstType)
 249  	if srcBits > dstBits {
 250  		e.w("  ") ; e.w(dst) ; e.w(" = trunc ") ; e.w(srcType) ; e.w(" ") ; e.w(src) ; e.w(" to ") ; e.w(dstType) ; e.w("\n")
 251  	} else {
 252  		e.w("  ") ; e.w(dst) ; e.w(" = sext ") ; e.w(srcType) ; e.w(" ") ; e.w(src) ; e.w(" to ") ; e.w(dstType) ; e.w("\n")
 253  	}
 254  	return dst
 255  }
 256  
 257  func llvmTypeBits(t string) int32 {
 258  	if t == "i1" { return 1 }
 259  	if t == "i8" { return 8 }
 260  	if t == "i16" { return 16 }
 261  	if t == "i32" { return 32 }
 262  	if t == "i64" { return 64 }
 263  	return 0
 264  }
 265  
 266  func (e *irEmitter) nextReg2(prefix string) string {
 267  	e.nextReg++
 268  	return "%" | prefix | irItoa(e.nextReg)
 269  }
 270  
 271  func (e *irEmitter) llvmStructType(t *types.TCStruct) string {
 272  	if t == nil {
 273  		return "{}"
 274  	}
 275  	s := "{"
 276  	for i := 0; i < t.NumFields(); i++ {
 277  		if i > 0 {
 278  			s = s | ", "
 279  		}
 280  		ft := e.llvmType(t.Field(i).Type())
 281  		if ft == "void" {
 282  			ft = "ptr"
 283  		}
 284  		s = s | ft
 285  	}
 286  	return s | "}"
 287  }
 288