ir_iter.mx raw

   1  package main
   2  
   3  import (
   4  	. "git.smesh.lol/moxie/pkg/types"
   5  )
   6  
   7  func (e *irEmitter) emitRange(r *SSARange) {
   8  	reg := e.regName(r)
   9  	ipt := e.intptrType()
  10  	if _, ok := SafeUnderlying(r.X.SSAType()).(*TCMap); ok {
  11  		e.w("  ") ; e.w(reg) ; e.w(" = alloca [48 x i8]\n")
  12  		e.w("  call void @llvm.memset.p0." | ipt | "(ptr ") ; e.w(reg) ; e.w(", i8 0, " | ipt | " 48, i1 false)\n")
  13  		e.declareRuntime("llvm.memset.p0." | ipt, "void", "ptr, i8, " | ipt | ", i1")
  14  		return
  15  	}
  16  	ipt := e.intptrType()
  17  	e.w("  ") ; e.w(reg) ; e.w(" = alloca ") ; e.w(ipt) ; e.w("\n")
  18  	e.w("  store ") ; e.w(ipt) ; e.w(" 0, ptr ") ; e.w(reg) ; e.w("\n")
  19  }
  20  
  21  func (e *irEmitter) emitNext(n *SSANext) {
  22  	reg := e.regName(n)
  23  	rangeInstr := n.Iter.(*SSARange)
  24  	iterPtr := e.regName(rangeInstr)
  25  	collVal := e.operand(rangeInstr.X)
  26  	if mt, ok := SafeUnderlying(rangeInstr.X.SSAType()).(*TCMap); ok {
  27  		e.emitNextMap(reg, iterPtr, collVal, mt, n)
  28  		return
  29  	}
  30  	if arr, ok := SafeUnderlying(rangeInstr.X.SSAType()).(*Array); ok && arr.Len >= 0 {
  31  		e.emitNextArray(reg, iterPtr, collVal, arr, n)
  32  		return
  33  	}
  34  	if p, ok := SafeUnderlying(rangeInstr.X.SSAType()).(*Pointer); ok {
  35  		if ar, ok2 := SafeUnderlying(p.Base).(*Array); ok2 && ar.Len >= 0 {
  36  			e.emitNextPtrArray(reg, iterPtr, collVal, ar, n)
  37  			return
  38  		}
  39  	}
  40  	collLLVM := e.llvmType(rangeInstr.X.SSAType())
  41  	if len(collLLVM) > 0 && collLLVM[0] == 'i' {
  42  		tupType := e.llvmType(n.SSAType())
  43  		if at, ok := e.allocTypes[n]; ok {
  44  			tupType = at
  45  		}
  46  		e.w("  ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" zeroinitializer, i1 false, 0\n")
  47  		return
  48  	}
  49  	e.emitNextSlice(reg, iterPtr, collVal, rangeInstr, n)
  50  }
  51  
  52  func (e *irEmitter) emitNextSlice(reg, iterPtr, collVal string, rangeInstr *SSARange, n *SSANext) {
  53  	ipt := e.intptrType()
  54  	sty := e.sliceType()
  55  	idx := e.nextReg2("rn")
  56  	e.w("  ") ; e.w(idx) ; e.w(" = load ") ; e.w(ipt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
  57  	slLen := e.nextReg2("rn")
  58  	e.w("  ") ; e.w(slLen) ; e.w(" = extractvalue ") ; e.w(sty) ; e.w(" ") ; e.w(collVal) ; e.w(", 1\n")
  59  	ok := e.nextReg2("rn")
  60  	e.w("  ") ; e.w(ok) ; e.w(" = icmp ult ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", ") ; e.w(slLen) ; e.w("\n")
  61  	key := e.nextReg2("rn")
  62  	e.truncToI32(key, idx)
  63  	dataPtr := e.nextReg2("rn")
  64  	e.w("  ") ; e.w(dataPtr) ; e.w(" = extractvalue ") ; e.w(sty) ; e.w(" ") ; e.w(collVal) ; e.w(", 0\n")
  65  	elemType := "i32"
  66  	if sl, ok2 := SafeUnderlying(rangeInstr.X.SSAType()).(*Slice); ok2 {
  67  		elemType = e.llvmType(sl.Elem)
  68  	}
  69  	eptr := e.nextReg2("rn")
  70  	e.w("  ") ; e.w(eptr) ; e.w(" = getelementptr ") ; e.w(elemType)
  71  	e.w(", ptr ") ; e.w(dataPtr) ; e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
  72  	fallback := e.nextReg2("rn")
  73  	e.w("  ") ; e.w(fallback) ; e.w(" = alloca ") ; e.w(elemType) ; e.w("\n")
  74  	e.w("  store ") ; e.w(elemType) ; e.w(" zeroinitializer, ptr ") ; e.w(fallback) ; e.w("\n")
  75  	safePtr := e.nextReg2("rn")
  76  	e.w("  ") ; e.w(safePtr) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ptr ") ; e.w(eptr)
  77  	e.w(", ptr ") ; e.w(fallback) ; e.w("\n")
  78  	elem := e.nextReg2("rn")
  79  	e.w("  ") ; e.w(elem) ; e.w(" = load ") ; e.w(elemType) ; e.w(", ptr ") ; e.w(safePtr) ; e.w("\n")
  80  	inc := e.nextReg2("rn")
  81  	e.w("  ") ; e.w(inc) ; e.w(" = add ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", 1\n")
  82  	newCnt := e.nextReg2("rn")
  83  	e.w("  ") ; e.w(newCnt) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(inc)
  84  	e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
  85  	e.w("  store ") ; e.w(ipt) ; e.w(" ") ; e.w(newCnt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
  86  	tupType := "{i1, i32, " | elemType | "}"
  87  	e.allocTypes[n] = tupType
  88  	t1 := e.nextReg2("rn")
  89  	e.w("  ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, i1 ") ; e.w(ok) ; e.w(", 0\n")
  90  	t2 := e.nextReg2("rn")
  91  	e.w("  ") ; e.w(t2) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i32 ") ; e.w(key) ; e.w(", 1\n")
  92  	e.w("  ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t2) ; e.w(", ") ; e.w(elemType) ; e.w(" ") ; e.w(elem) ; e.w(", 2\n")
  93  }
  94  
  95  func (e *irEmitter) emitNextArray(reg, iterPtr, collVal string, arr *Array, n *SSANext) {
  96  	ipt := e.intptrType()
  97  	arrLen := arr.Len
  98  	elemType := e.llvmType(arr.Elem)
  99  	arrType := "[" | irItoa(int32(arrLen)) | " x " | elemType | "]"
 100  	idx := e.nextReg2("rn")
 101  	e.w("  ") ; e.w(idx) ; e.w(" = load ") ; e.w(ipt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
 102  	ok := e.nextReg2("rn")
 103  	e.w("  ") ; e.w(ok) ; e.w(" = icmp ult ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", ") ; e.w(irItoa(int32(arrLen))) ; e.w("\n")
 104  	key := e.nextReg2("rn")
 105  	e.truncToI32(key, idx)
 106  	// Store array to memory to get element pointer via GEP
 107  	arrAlloca := e.nextReg2("rn")
 108  	e.w("  ") ; e.w(arrAlloca) ; e.w(" = alloca ") ; e.w(arrType) ; e.w("\n")
 109  	e.w("  store ") ; e.w(arrType) ; e.w(" ") ; e.w(collVal) ; e.w(", ptr ") ; e.w(arrAlloca) ; e.w("\n")
 110  	eptr := e.nextReg2("rn")
 111  	e.w("  ") ; e.w(eptr) ; e.w(" = getelementptr inbounds ") ; e.w(arrType)
 112  	e.w(", ptr ") ; e.w(arrAlloca) ; e.w(", i32 0, ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
 113  	fallback := e.nextReg2("rn")
 114  	e.w("  ") ; e.w(fallback) ; e.w(" = alloca ") ; e.w(elemType) ; e.w("\n")
 115  	e.w("  store ") ; e.w(elemType) ; e.w(" zeroinitializer, ptr ") ; e.w(fallback) ; e.w("\n")
 116  	safePtr := e.nextReg2("rn")
 117  	e.w("  ") ; e.w(safePtr) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ptr ") ; e.w(eptr)
 118  	e.w(", ptr ") ; e.w(fallback) ; e.w("\n")
 119  	elem := e.nextReg2("rn")
 120  	e.w("  ") ; e.w(elem) ; e.w(" = load ") ; e.w(elemType) ; e.w(", ptr ") ; e.w(safePtr) ; e.w("\n")
 121  	inc := e.nextReg2("rn")
 122  	e.w("  ") ; e.w(inc) ; e.w(" = add ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", 1\n")
 123  	newCnt := e.nextReg2("rn")
 124  	e.w("  ") ; e.w(newCnt) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(inc)
 125  	e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
 126  	e.w("  store ") ; e.w(ipt) ; e.w(" ") ; e.w(newCnt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
 127  	tupType := "{i1, i32, " | elemType | "}"
 128  	e.allocTypes[n] = tupType
 129  	t1 := e.nextReg2("rn")
 130  	e.w("  ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, i1 ") ; e.w(ok) ; e.w(", 0\n")
 131  	t2 := e.nextReg2("rn")
 132  	e.w("  ") ; e.w(t2) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i32 ") ; e.w(key) ; e.w(", 1\n")
 133  	e.w("  ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t2) ; e.w(", ") ; e.w(elemType) ; e.w(" ") ; e.w(elem) ; e.w(", 2\n")
 134  }
 135  
 136  func (e *irEmitter) emitNextPtrArray(reg, iterPtr, collVal string, arr *Array, n *SSANext) {
 137  	ipt := e.intptrType()
 138  	arrLen := arr.Len
 139  	elemType := e.llvmType(arr.Elem)
 140  	arrType := "[" | irItoa(int32(arrLen)) | " x " | elemType | "]"
 141  	idx := e.nextReg2("rn")
 142  	e.w("  ") ; e.w(idx) ; e.w(" = load ") ; e.w(ipt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
 143  	ok := e.nextReg2("rn")
 144  	e.w("  ") ; e.w(ok) ; e.w(" = icmp ult ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", ") ; e.w(irItoa(int32(arrLen))) ; e.w("\n")
 145  	key := e.nextReg2("rn")
 146  	e.truncToI32(key, idx)
 147  	eptr := e.nextReg2("rn")
 148  	e.w("  ") ; e.w(eptr) ; e.w(" = getelementptr inbounds ") ; e.w(arrType)
 149  	e.w(", ptr ") ; e.w(collVal) ; e.w(", i32 0, ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
 150  	fallback := e.nextReg2("rn")
 151  	e.w("  ") ; e.w(fallback) ; e.w(" = alloca ") ; e.w(elemType) ; e.w("\n")
 152  	e.w("  store ") ; e.w(elemType) ; e.w(" zeroinitializer, ptr ") ; e.w(fallback) ; e.w("\n")
 153  	safePtr := e.nextReg2("rn")
 154  	e.w("  ") ; e.w(safePtr) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ptr ") ; e.w(eptr)
 155  	e.w(", ptr ") ; e.w(fallback) ; e.w("\n")
 156  	elem := e.nextReg2("rn")
 157  	e.w("  ") ; e.w(elem) ; e.w(" = load ") ; e.w(elemType) ; e.w(", ptr ") ; e.w(safePtr) ; e.w("\n")
 158  	inc := e.nextReg2("rn")
 159  	e.w("  ") ; e.w(inc) ; e.w(" = add ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w(", 1\n")
 160  	newCnt := e.nextReg2("rn")
 161  	e.w("  ") ; e.w(newCnt) ; e.w(" = select i1 ") ; e.w(ok) ; e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(inc)
 162  	e.w(", ") ; e.w(ipt) ; e.w(" ") ; e.w(idx) ; e.w("\n")
 163  	e.w("  store ") ; e.w(ipt) ; e.w(" ") ; e.w(newCnt) ; e.w(", ptr ") ; e.w(iterPtr) ; e.w("\n")
 164  	tupType := "{i1, i32, " | elemType | "}"
 165  	e.allocTypes[n] = tupType
 166  	t1 := e.nextReg2("rn")
 167  	e.w("  ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, i1 ") ; e.w(ok) ; e.w(", 0\n")
 168  	t2 := e.nextReg2("rn")
 169  	e.w("  ") ; e.w(t2) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", i32 ") ; e.w(key) ; e.w(", 1\n")
 170  	e.w("  ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t2) ; e.w(", ") ; e.w(elemType) ; e.w(" ") ; e.w(elem) ; e.w(", 2\n")
 171  }
 172  
 173  func (e *irEmitter) emitNextMap(reg, iterPtr, collVal string, mt *TCMap, n *SSANext) {
 174  	keyType := e.llvmType(mt.Key)
 175  	valType := e.llvmType(mt.Elem)
 176  	keyAlloca := e.nextReg2("mn")
 177  	e.w("  ") ; e.w(keyAlloca) ; e.w(" = alloca ") ; e.w(keyType) ; e.w("\n")
 178  	valAlloca := e.nextReg2("mn")
 179  	e.w("  ") ; e.w(valAlloca) ; e.w(" = alloca ") ; e.w(valType) ; e.w("\n")
 180  	ok := e.nextReg2("mn")
 181  	e.w("  ") ; e.w(ok) ; e.w(" = call i1 @runtime.hashmapNext(ptr ") ; e.w(collVal)
 182  	e.w(", ptr ") ; e.w(iterPtr)
 183  	e.w(", ptr ") ; e.w(keyAlloca)
 184  	e.w(", ptr ") ; e.w(valAlloca) ; e.w(", ptr null)\n")
 185  	key := e.nextReg2("mn")
 186  	e.w("  ") ; e.w(key) ; e.w(" = load ") ; e.w(keyType) ; e.w(", ptr ") ; e.w(keyAlloca) ; e.w("\n")
 187  	val := e.nextReg2("mn")
 188  	e.w("  ") ; e.w(val) ; e.w(" = load ") ; e.w(valType) ; e.w(", ptr ") ; e.w(valAlloca) ; e.w("\n")
 189  	tupType := e.llvmType(n.SSAType())
 190  	t1 := e.nextReg2("mn")
 191  	e.w("  ") ; e.w(t1) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" undef, i1 ") ; e.w(ok) ; e.w(", 0\n")
 192  	t2 := e.nextReg2("mn")
 193  	e.w("  ") ; e.w(t2) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t1) ; e.w(", ") ; e.w(keyType) ; e.w(" ") ; e.w(key) ; e.w(", 1\n")
 194  	e.w("  ") ; e.w(reg) ; e.w(" = insertvalue ") ; e.w(tupType) ; e.w(" ") ; e.w(t2) ; e.w(", ") ; e.w(valType) ; e.w(" ") ; e.w(val) ; e.w(", 2\n")
 195  	e.declareRuntime("runtime.hashmapNext", "i1", "ptr, ptr, ptr, ptr")
 196  }
 197