Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
Greenplum
Gpdb
提交
4916a606
G
Gpdb
项目概览
Greenplum
/
Gpdb
通知
7
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
G
Gpdb
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
4916a606
编写于
4月 23, 2016
作者:
S
Shreedhar Hardikar
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Add support for registering vararg external functions with codegen utils.
上级
a9c1ef15
变更
2
隐藏空白更改
内联
并排
Showing
2 changed file
with
95 addition
and
8 deletion
+95
-8
src/backend/codegen/include/codegen/utils/codegen_utils.h
src/backend/codegen/include/codegen/utils/codegen_utils.h
+28
-8
src/backend/codegen/tests/codegen_utils_unittest.cc
src/backend/codegen/tests/codegen_utils_unittest.cc
+67
-0
未找到文件。
src/backend/codegen/include/codegen/utils/codegen_utils.h
浏览文件 @
4916a606
...
...
@@ -162,11 +162,12 @@ class CodegenUtils {
*
* @tparam ReturnType The function's return type.
* @tparam ArgumentTypes The types of any number of arguments to the function.
* @param is_var_arg Whether the function has trailing variable arguments list
* @return A pointer to the complete function type-signature's equivalent as
* an LLVM FunctionType in this CodegenUtils's context.
**/
template
<
typename
ReturnType
,
typename
...
ArgumentTypes
>
llvm
::
FunctionType
*
GetFunctionType
();
llvm
::
FunctionType
*
GetFunctionType
(
const
bool
is_var_arg
=
false
);
/**
* @brief Get an LLVM constant based on a C++ value.
...
...
@@ -231,6 +232,7 @@ class CodegenUtils {
* @tparam FuncType FunctionType. e.g ReturnType (*)(ArgumenTypes)
*
* @param name The function's name.
* @param is_var_arg Whether the function has trailing variable arguments list
* @param linkage The linkage visibility of the function. Defaults to
* ExternalLinkage, which makes the function visible and callable from
* anywhere.
...
...
@@ -240,6 +242,7 @@ class CodegenUtils {
template
<
typename
FuncType
>
llvm
::
Function
*
CreateFunction
(
const
llvm
::
Twine
&
name
,
const
bool
is_var_arg
=
false
,
const
llvm
::
GlobalValue
::
LinkageTypes
linkage
=
llvm
::
GlobalValue
::
ExternalLinkage
);
...
...
@@ -294,12 +297,14 @@ class CodegenUtils {
* so that the registered function will also be callable by its name
* in C++ source code compiled by ClangCompiler (see
* ClangCompiler::GenerateExternalFunctionDeclarations()).
* @param is_var_arg Whether the function has trailing variable arguments list
* @return A callable LLVM function.
**/
template
<
typename
ReturnType
,
typename
...
ArgumentTypes
>
llvm
::
Function
*
RegisterExternalFunction
(
ReturnType
(
*
external_function
)(
ArgumentTypes
...),
const
std
::
string
&
name
=
""
)
{
const
std
::
string
&
name
=
""
,
const
bool
is_var_arg
=
false
)
{
external_functions_
.
emplace_back
(
name
.
empty
()
?
GenerateExternalFunctionName
()
:
name
,
...
...
@@ -310,9 +315,20 @@ class CodegenUtils {
}
return
CreateFunctionImpl
<
ReturnType
,
ArgumentTypes
...
>
(
external_functions_
.
back
().
first
);
external_functions_
.
back
().
first
,
is_var_arg
);
}
template
<
typename
ReturnType
,
typename
...
ArgumentTypes
>
llvm
::
Function
*
RegisterExternalFunction
(
ReturnType
(
*
external_function
)(
ArgumentTypes
...,
...),
const
std
::
string
&
name
=
""
)
{
return
RegisterExternalFunction
(
reinterpret_cast
<
ReturnType
(
*
)
(
ArgumentTypes
...)
>
(
external_function
),
name
,
true
);
}
/**
* @brief Optimize the code in the module managed by this CodegenUtils before
* execution.
...
...
@@ -412,6 +428,7 @@ class CodegenUtils {
template
<
typename
ReturnType
,
typename
...
ArgumentTypes
>
llvm
::
Function
*
CreateFunctionImpl
(
const
llvm
::
Twine
&
name
,
const
bool
is_var_arg
=
false
,
const
llvm
::
GlobalValue
::
LinkageTypes
linkage
=
llvm
::
GlobalValue
::
ExternalLinkage
);
...
...
@@ -781,12 +798,12 @@ class TypeVectorBuilder<HeadType, TailTypes...> {
}
// namespace codegen_utils_detail
template
<
typename
ReturnType
,
typename
...
ArgumentTypes
>
llvm
::
FunctionType
*
CodegenUtils
::
GetFunctionType
()
{
llvm
::
FunctionType
*
CodegenUtils
::
GetFunctionType
(
const
bool
is_var_arg
)
{
std
::
vector
<
llvm
::
Type
*>
argument_types
;
codegen_utils_detail
::
TypeVectorBuilder
<
ArgumentTypes
...
>::
AppendTypes
(
this
,
&
argument_types
);
return
llvm
::
FunctionType
::
get
(
GetType
<
ReturnType
>
(),
argument_types
,
false
);
return
llvm
::
FunctionType
::
get
(
GetType
<
ReturnType
>
(),
argument_types
,
is_var_arg
);
}
// ----------------------------------------------------------------------------
...
...
@@ -985,9 +1002,10 @@ class FunctionTypeUnpacker<ReturnType(*)(ArgumentTypes...)> {
static
llvm
::
Function
*
CreateFunctionImpl
(
CodegenUtils
*
codegen_utils
,
const
llvm
::
Twine
&
name
,
const
bool
is_var_arg
,
const
llvm
::
GlobalValue
::
LinkageTypes
linkage
)
{
return
codegen_utils
->
CreateFunctionImpl
<
ReturnType
,
ArgumentTypes
...
>
(
name
,
linkage
);
name
,
is_var_arg
,
linkage
);
}
static
auto
GetFunctionPointerImpl
(
gpcodegen
::
CodegenUtils
*
codegen_utils
,
...
...
@@ -1002,17 +1020,19 @@ class FunctionTypeUnpacker<ReturnType(*)(ArgumentTypes...)> {
template
<
typename
FunctionType
>
llvm
::
Function
*
CodegenUtils
::
CreateFunction
(
const
llvm
::
Twine
&
name
,
const
bool
is_var_arg
,
const
llvm
::
GlobalValue
::
LinkageTypes
linkage
)
{
return
codegen_utils_detail
::
FunctionTypeUnpacker
<
FunctionType
>::
CreateFunctionImpl
(
this
,
name
,
linkage
);
CreateFunctionImpl
(
this
,
name
,
is_var_arg
,
linkage
);
}
template
<
typename
ReturnType
,
typename
...
ArgumentTypes
>
llvm
::
Function
*
CodegenUtils
::
CreateFunctionImpl
(
const
llvm
::
Twine
&
name
,
const
bool
is_var_arg
,
const
llvm
::
GlobalValue
::
LinkageTypes
linkage
)
{
return
llvm
::
Function
::
Create
(
GetFunctionType
<
ReturnType
,
ArgumentTypes
...
>
(),
GetFunctionType
<
ReturnType
,
ArgumentTypes
...
>
(
is_var_arg
),
linkage
,
name
,
module_
.
get
());
...
...
src/backend/codegen/tests/codegen_utils_unittest.cc
浏览文件 @
4916a606
...
...
@@ -1776,6 +1776,73 @@ TEST_F(CodegenUtilsTest, ExternalFunctionTest) {
EXPECT_EQ
(
42
,
StaticIntWrapper
::
Get
());
}
TEST_F
(
CodegenUtilsTest
,
VariadicExternalFunctionTest
)
{
// Test a function with overloads an external function that contains
// variable length arguments : printf and sprintf
// Register printf with takes variable arguments past char*
llvm
::
Function
*
llvm_printf_function
=
codegen_utils_
->
RegisterExternalFunction
(
printf
);
ASSERT_NE
(
llvm_printf_function
,
nullptr
);
ASSERT_EQ
(
(
codegen_utils_
->
GetFunctionType
<
int
,
char
*>
(
true
)
->
getPointerTo
()),
llvm_printf_function
->
getType
());
// Register sprintf with takes variable arguments past char*, char*
llvm
::
Function
*
llvm_sprintf_function
=
codegen_utils_
->
RegisterExternalFunction
(
sprintf
);
ASSERT_NE
(
llvm_sprintf_function
,
nullptr
);
ASSERT_EQ
(
(
codegen_utils_
->
GetFunctionType
<
int
,
char
*
,
char
*>
(
true
)
->
getPointerTo
()),
llvm_sprintf_function
->
getType
());
char
sprintf_with_three_args_buffer
[
16
],
sprintf_with_four_args_buffer
[
16
];
// Create a simple function that calls sprintf with 3 and 4 arguments and uses
// the buffers allocated above
typedef
void
(
*
SprintfTestType
)();
llvm
::
Function
*
sprintf_test
=
codegen_utils_
->
CreateFunction
<
SprintfTestType
>
(
"sprintf_test"
);
llvm
::
BasicBlock
*
main_block
=
codegen_utils_
->
CreateBasicBlock
(
"main"
,
sprintf_test
);
codegen_utils_
->
ir_builder
()
->
SetInsertPoint
(
main_block
);
codegen_utils_
->
ir_builder
()
->
CreateCall
(
llvm_printf_function
,
{
codegen_utils_
->
GetConstant
(
"%s %d"
),
codegen_utils_
->
GetConstant
(
"Zero is another way of saying "
),
codegen_utils_
->
GetConstant
(
0
)
});
codegen_utils_
->
ir_builder
()
->
CreateCall
(
llvm_sprintf_function
,
{
codegen_utils_
->
GetConstant
(
sprintf_with_three_args_buffer
),
codegen_utils_
->
GetConstant
(
"%d"
),
codegen_utils_
->
GetConstant
(
42
)
});
codegen_utils_
->
ir_builder
()
->
CreateCall
(
llvm_sprintf_function
,
{
codegen_utils_
->
GetConstant
(
sprintf_with_four_args_buffer
),
codegen_utils_
->
GetConstant
(
"%d %s"
),
codegen_utils_
->
GetConstant
(
51
),
codegen_utils_
->
GetConstant
(
"fifty-one"
)
});
codegen_utils_
->
ir_builder
()
->
CreateRetVoid
();
// Check that the module is well-formed and prepare the generated wrapper
// functions for execution.
EXPECT_FALSE
(
llvm
::
verifyModule
(
*
codegen_utils_
->
module
()));
EXPECT_TRUE
(
codegen_utils_
->
PrepareForExecution
(
CodegenUtils
::
OptimizationLevel
::
kNone
,
true
));
SprintfTestType
llvm_sprintf_test
=
codegen_utils_
->
GetFunctionPointer
<
SprintfTestType
>
(
"sprintf_test"
);
llvm_sprintf_test
();
ASSERT_EQ
(
strcmp
(
sprintf_with_three_args_buffer
,
"42"
),
0
);
ASSERT_EQ
(
strcmp
(
sprintf_with_four_args_buffer
,
"51 fifty-one"
),
0
);
}
TEST_F
(
CodegenUtilsTest
,
RecursionTest
)
{
// Test a version of the factorial function that works by recursion.
typedef
unsigned
(
*
FactorialRecursiveFn
)
(
unsigned
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录