Hello,
Yesterday was the last Google Summer of Code day. This wonderful experience is now over, and I will see if I pass the final evaluation.
The GSoC is over, but not my work. These following days will be a bit more light on development, as I need holidays now that I have worked hard for nearly one year (for school since September 2010, for a big school project during the holidays, then for Google since May).
But after this break, I will continue to work for Clover, and the following feature will be built-in functions. I will implement them using a small preprocessor written in Python. I'll give it an input in the form of :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # def <var> : [values]
def vecf : float2 float3 float4 float8 float16
def gentype : float $vecf
# Normal function, placed in stdlib.c, can use Clang features
# func <name> [types] : <return type> [args]
# - args : <name>:<type>
# - $type is replaced with the current type of the implementation
# - in the body, $vecdim is replaced by the vector dimension of the type
func min $gentype : $type x:$type y:$type
return (x < y ? x : y)
end
# Native function, placed in src/core/cpu/builtins.cpp
native cos float : float x:float
return std::cos(x);
end
# Function overloading possible
native cos $vecf : $type x:$type
for (unsigned int i=0; i<$vecdim; ++i)
result[i] = std::cos(x[i]);
end
|
The Python preprocessor will duplicate each function for each of the types given, either in stdlib.c (for functions that will be byte-compiled by Clang and executed using the LLVM JIT, allowing inlining) or in builtins.cpp (for functions that need to use external C or C++ functions, like STL or system ones).
The current preprocessor (yes, I already started working on it) currently can produce this code for the example above :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | static float cos_floatfloat(float x)
{
return std::cos(x);
}
static void cos_float2float2(float *result, float *x)
{
for (unsigned int i=0; i<2; ++i)
result[i] = std::cos(x[i]);
}
static void cos_float3float3(float *result, float *x)
{
for (unsigned int i=0; i<3; ++i)
result[i] = std::cos(x[i]);
}
static void cos_float4float4(float *result, float *x)
{
for (unsigned int i=0; i<4; ++i)
result[i] = std::cos(x[i]);
}
static void cos_float8float8(float *result, float *x)
{
for (unsigned int i=0; i<8; ++i)
result[i] = std::cos(x[i]);
}
static void cos_float16float16(float *result, float *x)
{
for (unsigned int i=0; i<16; ++i)
result[i] = std::cos(x[i]);
}
|
You can see that the function names are mangled, as the preprocessor knows more things about the function than the C++ compiler (for example, the dimension of the vectors). If they had the same name, these function (except the first) should have looked the same for a C++ compiler as they take the same parameters and all return void. These functions will be put in builtins.cpp. For "normal" functions, mangling will not be necessary as Clang is aware of the vector dimension (using __attribute__((__ext_vector_size(foo)))) and can mangle even C functions using __attribute__((overloadable)).
Working on this preprocessor is exciting and I hope to be able to do that in the following days, and I will try my best to keep the code clean (Python is a clean programming language but it is easy to have programs like shell scripts).
By the way, the Clover git repository is still online and you can read the code if you didn't do so before. You can also enjoy the documentation that is now finished (link in the right menu of this blog). I hope you'll find it helpful and understandable.