createBuiltin lowers a builtin Go function (append, close, delete, etc.) to LLVM IR. It uses runtime calls for some builtins.
(argTypes []types.Type, argValues []llvm.Value, callName string, pos token.Pos)
| 1592 | // createBuiltin lowers a builtin Go function (append, close, delete, etc.) to |
| 1593 | // LLVM IR. It uses runtime calls for some builtins. |
| 1594 | func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, callName string, pos token.Pos) (llvm.Value, error) { |
| 1595 | switch callName { |
| 1596 | case "append": |
| 1597 | src := argValues[0] |
| 1598 | elems := argValues[1] |
| 1599 | srcBuf := b.CreateExtractValue(src, 0, "append.srcBuf") |
| 1600 | srcLen := b.CreateExtractValue(src, 1, "append.srcLen") |
| 1601 | srcCap := b.CreateExtractValue(src, 2, "append.srcCap") |
| 1602 | elemsBuf := b.CreateExtractValue(elems, 0, "append.elemsBuf") |
| 1603 | elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen") |
| 1604 | elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem()) |
| 1605 | elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false) |
| 1606 | elemLayout := b.createObjectLayout(elemType, pos) |
| 1607 | result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcBuf, elemsBuf, srcLen, srcCap, elemsLen, elemSize, elemLayout}, "append.new") |
| 1608 | newPtr := b.CreateExtractValue(result, 0, "append.newPtr") |
| 1609 | newLen := b.CreateExtractValue(result, 1, "append.newLen") |
| 1610 | newCap := b.CreateExtractValue(result, 2, "append.newCap") |
| 1611 | newSlice := llvm.Undef(src.Type()) |
| 1612 | newSlice = b.CreateInsertValue(newSlice, newPtr, 0, "") |
| 1613 | newSlice = b.CreateInsertValue(newSlice, newLen, 1, "") |
| 1614 | newSlice = b.CreateInsertValue(newSlice, newCap, 2, "") |
| 1615 | return newSlice, nil |
| 1616 | case "cap": |
| 1617 | value := argValues[0] |
| 1618 | var llvmCap llvm.Value |
| 1619 | switch argTypes[0].Underlying().(type) { |
| 1620 | case *types.Chan: |
| 1621 | llvmCap = b.createRuntimeCall("chanCap", []llvm.Value{value}, "cap") |
| 1622 | case *types.Slice: |
| 1623 | llvmCap = b.CreateExtractValue(value, 2, "cap") |
| 1624 | default: |
| 1625 | return llvm.Value{}, b.makeError(pos, "todo: cap: unknown type") |
| 1626 | } |
| 1627 | if b.targetData.TypeAllocSize(llvmCap.Type()) < b.targetData.TypeAllocSize(b.intType) { |
| 1628 | llvmCap = b.CreateZExt(llvmCap, b.intType, "len.int") |
| 1629 | } |
| 1630 | return llvmCap, nil |
| 1631 | case "close": |
| 1632 | b.createChanClose(argValues[0]) |
| 1633 | return llvm.Value{}, nil |
| 1634 | case "complex": |
| 1635 | r := argValues[0] |
| 1636 | i := argValues[1] |
| 1637 | t := argTypes[0].Underlying().(*types.Basic) |
| 1638 | var cplx llvm.Value |
| 1639 | switch t.Kind() { |
| 1640 | case types.Float32: |
| 1641 | cplx = llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.FloatType(), b.ctx.FloatType()}, false)) |
| 1642 | case types.Float64: |
| 1643 | cplx = llvm.Undef(b.ctx.StructType([]llvm.Type{b.ctx.DoubleType(), b.ctx.DoubleType()}, false)) |
| 1644 | default: |
| 1645 | return llvm.Value{}, b.makeError(pos, "unsupported type in complex builtin: "+t.String()) |
| 1646 | } |
| 1647 | cplx = b.CreateInsertValue(cplx, r, 0, "") |
| 1648 | cplx = b.CreateInsertValue(cplx, i, 1, "") |
| 1649 | return cplx, nil |
| 1650 | case "clear": |
| 1651 | value := argValues[0] |
no test coverage detected