createFunctionCall lowers a Go SSA call instruction (to a simple function, closure, function pointer, builtin, method, etc.) to LLVM IR, usually a call instruction. This is also where compiler intrinsics are implemented.
(instr *ssa.CallCommon)
| 1964 | // |
| 1965 | // This is also where compiler intrinsics are implemented. |
| 1966 | func (b *builder) createFunctionCall(instr *ssa.CallCommon) (llvm.Value, error) { |
| 1967 | // See if this is an intrinsic function that is handled specially. |
| 1968 | if fn := instr.StaticCallee(); fn != nil { |
| 1969 | // Direct function call, either to a named or anonymous (directly |
| 1970 | // applied) function call. If it is anonymous, it may be a closure. |
| 1971 | name := fn.RelString(nil) |
| 1972 | switch { |
| 1973 | case name == "device.Asm" || name == "device/arm.Asm" || name == "device/arm64.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm": |
| 1974 | return b.createInlineAsm(instr.Args) |
| 1975 | case name == "device.AsmFull" || name == "device/arm.AsmFull" || name == "device/arm64.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull": |
| 1976 | return b.createInlineAsmFull(instr) |
| 1977 | case strings.HasPrefix(name, "device/arm.SVCall"): |
| 1978 | return b.emitSVCall(instr.Args, getPos(instr)) |
| 1979 | case strings.HasPrefix(name, "device/arm64.SVCall"): |
| 1980 | return b.emitSV64Call(instr.Args, getPos(instr)) |
| 1981 | case strings.HasPrefix(name, "(device/riscv.CSR)."): |
| 1982 | return b.emitCSROperation(instr) |
| 1983 | case (strings.HasPrefix(name, "syscall.Syscall") || strings.HasPrefix(name, "syscall.RawSyscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.Syscall") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscall")) && name != "syscall.SyscallN": |
| 1984 | if b.GOOS != "darwin" { |
| 1985 | return b.createSyscall(instr) |
| 1986 | } |
| 1987 | case name == "syscall.syscalln": |
| 1988 | if b.GOOS == "windows" { |
| 1989 | return b.createSyscalln(instr) |
| 1990 | } |
| 1991 | case strings.HasPrefix(name, "syscall.rawSyscallNoError") || strings.HasPrefix(name, "golang.org/x/sys/unix.RawSyscallNoError"): |
| 1992 | return b.createRawSyscallNoError(instr) |
| 1993 | case name == "runtime.supportsRecover": |
| 1994 | supportsRecover := uint64(0) |
| 1995 | if b.supportsRecover() { |
| 1996 | supportsRecover = 1 |
| 1997 | } |
| 1998 | return llvm.ConstInt(b.ctx.Int1Type(), supportsRecover, false), nil |
| 1999 | case name == "runtime.panicStrategy": |
| 2000 | panicStrategy := map[string]uint64{ |
| 2001 | "print": tinygo.PanicStrategyPrint, |
| 2002 | "trap": tinygo.PanicStrategyTrap, |
| 2003 | }[b.Config.PanicStrategy] |
| 2004 | return llvm.ConstInt(b.ctx.Int8Type(), panicStrategy, false), nil |
| 2005 | case name == "runtime/interrupt.New": |
| 2006 | return b.createInterruptGlobal(instr) |
| 2007 | case name == "runtime.exportedFuncPtr": |
| 2008 | _, ptr := b.getFunction(instr.Args[0].(*ssa.Function)) |
| 2009 | return b.CreatePtrToInt(ptr, b.uintptrType, ""), nil |
| 2010 | case name == "(*runtime/interrupt.Checkpoint).Save": |
| 2011 | return b.createInterruptCheckpoint(instr.Args[0]), nil |
| 2012 | case name == "internal/abi.FuncPCABI0": |
| 2013 | retval := b.createDarwinFuncPCABI0Call(instr) |
| 2014 | if !retval.IsNil() { |
| 2015 | return retval, nil |
| 2016 | } |
| 2017 | } |
| 2018 | } |
| 2019 | |
| 2020 | var params []llvm.Value |
| 2021 | for _, param := range instr.Args { |
| 2022 | params = append(params, b.getValue(param, getPos(instr))) |
| 2023 | } |
no test coverage detected