@@ -163,6 +163,44 @@ func (b *builder) emitSVCall(args []ssa.Value) (llvm.Value, error) {
163163 return b .CreateCall (target , llvmArgs , "" ), nil
164164}
165165
166+ // This is a compiler builtin which emits an inline SVCall instruction. It can
167+ // be one of:
168+ //
169+ // func SVCall0(num uintptr) uintptr
170+ // func SVCall1(num uintptr, a1 interface{}) uintptr
171+ // func SVCall2(num uintptr, a1, a2 interface{}) uintptr
172+ // func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr
173+ // func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr
174+ //
175+ // The num parameter must be a constant. All other parameters may be any scalar
176+ // value supported by LLVM inline assembly.
177+ // Same as emitSVCall but for AArch64
178+ func (b * builder ) emitSV64Call (args []ssa.Value ) (llvm.Value , error ) {
179+ num , _ := constant .Uint64Val (args [0 ].(* ssa.Const ).Value )
180+ llvmArgs := []llvm.Value {}
181+ argTypes := []llvm.Type {}
182+ asm := "svc #" + strconv .FormatUint (num , 10 )
183+ constraints := "={x0}"
184+ for i , arg := range args [1 :] {
185+ arg = arg .(* ssa.MakeInterface ).X
186+ if i == 0 {
187+ constraints += ",0"
188+ } else {
189+ constraints += ",{x" + strconv .Itoa (i ) + "}"
190+ }
191+ llvmValue := b .getValue (arg )
192+ llvmArgs = append (llvmArgs , llvmValue )
193+ argTypes = append (argTypes , llvmValue .Type ())
194+ }
195+ // Implement the ARM64 calling convention by marking x1-x7 as
196+ // clobbered. x0 is used as an output register so doesn't have to be
197+ // marked as clobbered.
198+ constraints += ",~{x1},~{x2},~{x3},~{x4},~{x5},~{x6},~{x7}"
199+ fnType := llvm .FunctionType (b .uintptrType , argTypes , false )
200+ target := llvm .InlineAsm (fnType , asm , constraints , true , false , 0 )
201+ return b .CreateCall (target , llvmArgs , "" ), nil
202+ }
203+
166204// This is a compiler builtin which emits CSR instructions. It can be one of:
167205//
168206// func (csr CSR) Get() uintptr
0 commit comments