Difference between revisions of "NaplesPUCallingConv.td"

From NaplesPU Documentation
Jump to: navigation, search
(Results returning)
 
(4 intermediate revisions by 2 users not shown)
Line 2: Line 2:
 
This file describes the conventions to use when a function is called, such as how to pass the arguments and how to return the function results.
 
This file describes the conventions to use when a function is called, such as how to pass the arguments and how to return the function results.
  
== Arguments passing ==
+
<syntaxhighlight>
 +
//===-- NaplesPUCallingConv.td - Calling Conventions NaplesPU ----*- tablegen -*-===//
 +
//
 +
//                    The LLVM Compiler Infrastructure
 +
//
 +
// This file is distributed under the University of Illinois Open Source
 +
// License. See LICENSE.TXT for details.
 +
//
 +
//===----------------------------------------------------------------------===//
 +
//
 +
// This describes the calling conventions for the NaplesPU architectures.
 +
//
 +
//===----------------------------------------------------------------------===//
  
The nu+ architecture natively supports 32-bit scalar integers (i32), 64-bit scalar integers (i64), 32-bit vector integers (v16i32), 64-bit vector integers (v8i64), 32-bit scalar floating-point (f32), 64-bit scalar floating-point (f64), 32-bit vector floating-point (v16f32) and 64-bit vector floating-point (v8f64).
+
def CC_NaplesPU32 : CallingConv<[
  
The convention is to use the first '''eight''' register to pass arguments of the types listed above. For example, given the function foo
+
  // i1, i8 and i16 integers are promoted to i32 by the caller.
 +
  CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
  
<syntaxhighlight lang="c" line="line">
+
  CCIfType<[v16i8, v16i16], CCPromoteToType<v16i32>>,
void foo (int a, long long int b, vec16f32 c);
+
  CCIfType<[v8i8, v8i16, v8i32], CCPromoteToType<v8i64>>,
</syntaxhighlight>
 
  
the variable '''a''' will be passed using the register '''s0''', '''b''' using '''s2_s3''' and '''c''' will be stored in '''v0'''.
+
  // i32 f32 arguments get passed in integer registers if there is space.
If there are no registers available the variables will be passed using the stack.
+
  CCIfNotVarArg<CCIfType<[i32, f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7]>>>,
  
The non-native data-types are passed the same way as the native ones, however they are first extended to the nearest native data-type then they are passed using the convention discussed before.
+
    // Vector arguments can be passed in their own registers, as above
 +
  CCIfNotVarArg<CCIfType<[v16i32, v16f32], CCAssignToReg<[V0, V1, V2, V3, V4, V5, V6, V7]>>>,
  
The description is done defining the class '''CC_NuPlus32''' and using the tablegen classes contained in "compiler/include/llvm/Target/TargetCallingConv.td". The most used are '''CCIfType''',
+
  // Stick remaining registers onto stack, aligned by size
'''CCPromoteToType''', '''CCAssignToReg''', '''CCAssignToStack''' and '''CCIfNotVarArg'''.
+
  CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
 +
  CCIfType<[v16i32, v16f32], CCAssignToStack<64, 64>>
 +
]>;
  
The following code shows how the conventions for the i8, i16, i32 and f32 are described.
+
def RetCC_NaplesPU32 : CallingConv<[
 +
  CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
  
<syntaxhighlight lang="c" line="line">
+
  CCIfType<[i32, f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5]>>,
// i1, i8 and i16 integers are promoted to i32 by the caller.
 
CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
 
// If the current function is not vararg, i32 f32 arguments get passed in integer registers if there is space.
 
CCIfNotVarArg<CCIfType<[i32, f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7]>>>,
 
// Stick remaining registers onto stack, aligned by size
 
CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
 
...
 
</syntaxhighlight>
 
  
Note that the registers in "CCAssignToReg" are the registers defined inside [[NuPlusRegisterInfo.td]].
+
  CCIfType<[v16i8, v16i16], CCPromoteToType<v16i32>>,
  
== Results returning ==
+
  CCIfType<[v16i32, v16f32], CCAssignToReg<[V0, V1, V2, V3, V4, V5]>>
 +
]>;
  
The results of a function are passed using the first '''six''' registers. Like the arguments passed, the results must be of a native data-type, the non-native ones are first converted to the nearest native data-type.
+
//Callee only needs to save the callee-save registers that are used in the body of its subroutine.
 
+
def NaplesPUCSR : CalleeSavedRegs<(add (sequence "S%u", 50, 57), MR_REG, FP_REG, RA_REG,
The conventions are described defining the class '''RetCC_NuPlus32''' and using the tablegen classes contained in "compiler/include/llvm/Target/TargetCallingConv.td", similarly as they are used in [[#Arguments passing|Arguments passing]].
+
                              (sequence "V%u", 56, 63))>;
 
 
<syntaxhighlight lang="c" line="line">
 
CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,
 
CCIfType<[i32, f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5]>>,
 
CCIfType<[i64, f64], CCAssignToReg<[S0_S1, S2_S3, S4_S5, S6_S7, S8_S9, S10_S11]>>,
 
</syntaxhighlight>
 
 
 
== Callee saved registers ==
 
 
 
In NuPlusCallingConv.td are also defined the registers that must be saved before to call a function. In nu+ these registers are the last eight registers with the addition of the mask register, the return address register and the frame pointer.
 
 
 
<syntaxhighlight lang="c" line="line">
 
 
 
def NuPlusCSR : CalleeSavedRegs<(add (sequence "S%u", 50, 57), MR_REG, FP_REG, RA_REG,
 
                                    (sequence "V%u", 56, 63))>;
 
 
</syntaxhighlight>
 
</syntaxhighlight>

Latest revision as of 16:58, 21 June 2019

This file describes the conventions to use when a function is called, such as how to pass the arguments and how to return the function results.

//===-- NaplesPUCallingConv.td - Calling Conventions NaplesPU ----*- tablegen -*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This describes the calling conventions for the NaplesPU architectures.
//
//===----------------------------------------------------------------------===//

def CC_NaplesPU32 : CallingConv<[

  // i1, i8 and i16 integers are promoted to i32 by the caller.
  CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,

  CCIfType<[v16i8, v16i16], CCPromoteToType<v16i32>>,
  CCIfType<[v8i8, v8i16, v8i32], CCPromoteToType<v8i64>>,

  // i32 f32 arguments get passed in integer registers if there is space.
  CCIfNotVarArg<CCIfType<[i32, f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5, S6, S7]>>>,

    // Vector arguments can be passed in their own registers, as above
  CCIfNotVarArg<CCIfType<[v16i32, v16f32], CCAssignToReg<[V0, V1, V2, V3, V4, V5, V6, V7]>>>,

  // Stick remaining registers onto stack, aligned by size
  CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
  CCIfType<[v16i32, v16f32], CCAssignToStack<64, 64>>
]>;

def RetCC_NaplesPU32 : CallingConv<[
  CCIfType<[i1, i8, i16], CCPromoteToType<i32>>,

  CCIfType<[i32, f32], CCAssignToReg<[S0, S1, S2, S3, S4, S5]>>,

  CCIfType<[v16i8, v16i16], CCPromoteToType<v16i32>>,

  CCIfType<[v16i32, v16f32], CCAssignToReg<[V0, V1, V2, V3, V4, V5]>>
]>;

//Callee only needs to save the callee-save registers that are used in the body of its subroutine.
def NaplesPUCSR : CalleeSavedRegs<(add (sequence "S%u", 50, 57), MR_REG, FP_REG, RA_REG,
                               (sequence "V%u", 56, 63))>;