mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 01:58:44 +08:00
Illustrate a redirector using the example of round function from math.h.
Setup demonstrated in this patch is only for ELF-ish platforms. Also note: 1. Use of redirectors is a temporary scheme. They will be removed once LLVM-libc has implementations for the redirected functions. 2. Redirectors are optional. One can choose to not include them in the LLVM-libc build for their platform. 3. Even with redirectors used, we want to link to the system libc dynamically. Reviewers: dlj, hfinkel, jakehehrlich, phosek, stanshebs, theraven, alexshap Subscribers: mgorny, libc-commits Tags: #libc-project Differential Revision: https://reviews.llvm.org/D69020
This commit is contained in:
@@ -100,6 +100,7 @@ set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")
|
||||
# Usage:
|
||||
# add_entrypoint_object(
|
||||
# <target_name>
|
||||
# [REDIRECTED] # Specified if the entrypoint is redirected.
|
||||
# SRCS <list of .cpp files>
|
||||
# HDRS <list of .h files>
|
||||
# DEPENDS <list of dependencies>
|
||||
@@ -107,7 +108,7 @@ set(ENTRYPOINT_OBJ_TARGET_TYPE "ENTRYPOINT_OBJ")
|
||||
function(add_entrypoint_object target_name)
|
||||
cmake_parse_arguments(
|
||||
"ADD_ENTRYPOINT_OBJ"
|
||||
"" # No optional arguments
|
||||
"REDIRECTED" # Optional argument
|
||||
"" # No single value arguments
|
||||
"SRCS;HDRS;DEPENDS" # Multi value arguments
|
||||
${ARGN}
|
||||
@@ -131,7 +132,7 @@ function(add_entrypoint_object target_name)
|
||||
${target_name}_objects
|
||||
BEFORE
|
||||
PRIVATE
|
||||
-fpie -std=${LLVM_CXX_STD_default}
|
||||
-fpie ${LLVM_CXX_STD_default}
|
||||
)
|
||||
target_include_directories(
|
||||
${target_name}_objects
|
||||
@@ -158,10 +159,16 @@ function(add_entrypoint_object target_name)
|
||||
COMMAND ${CMAKE_LINKER} -r $<TARGET_OBJECTS:${target_name}_objects> -o ${object_file_raw}
|
||||
)
|
||||
|
||||
set(alias_attributes "0,function,global")
|
||||
if(ADD_ENTRYPOINT_OBJ_REDIRECTED)
|
||||
set(alias_attributes "${alias_attributes},hidden")
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${object_file}
|
||||
DEPENDS ${object_file_raw}
|
||||
COMMAND ${CMAKE_OBJCOPY} --add-symbol "${target_name}=.llvm.libc.entrypoint.${target_name}:0,function,weak,global" ${object_file_raw} ${object_file}
|
||||
# We llvm-objcopy here as GNU-binutils objcopy does not support the 'hidden' flag.
|
||||
DEPENDS ${object_file_raw} ${llvm-objcopy}
|
||||
COMMAND $<TARGET_FILE:llvm-objcopy> --add-symbol "${target_name}=.llvm.libc.entrypoint.${target_name}:${alias_attributes}" ${object_file_raw} ${object_file}
|
||||
)
|
||||
|
||||
add_custom_target(
|
||||
@@ -219,6 +226,67 @@ function(add_entrypoint_library target_name)
|
||||
)
|
||||
endfunction(add_entrypoint_library)
|
||||
|
||||
# Rule build a redirector object file.
|
||||
function(add_redirector_object target_name)
|
||||
cmake_parse_arguments(
|
||||
"REDIRECTOR_OBJECT"
|
||||
"" # No optional arguments
|
||||
"SRC" # The cpp file in which the redirector is defined.
|
||||
"" # No multivalue arguments
|
||||
${ARGN}
|
||||
)
|
||||
if(NOT REDIRECTOR_OBJECT_SRC)
|
||||
message(FATAL_ERROR "'add_redirector_object' rule requires SRC option listing one source file.")
|
||||
endif()
|
||||
|
||||
add_library(
|
||||
${target_name}
|
||||
OBJECT
|
||||
${REDIRECTOR_OBJECT_SRC}
|
||||
)
|
||||
target_compile_options(
|
||||
${target_name}
|
||||
BEFORE PRIVATE -fPIC
|
||||
)
|
||||
endfunction(add_redirector_object)
|
||||
|
||||
# Rule to build a shared library of redirector objects
|
||||
function(add_redirector_library target_name)
|
||||
cmake_parse_arguments(
|
||||
"REDIRECTOR_LIBRARY"
|
||||
""
|
||||
""
|
||||
"DEPENDS"
|
||||
${ARGN}
|
||||
)
|
||||
|
||||
set(obj_files "")
|
||||
foreach(dep IN LISTS REDIRECTOR_LIBRARY_DEPENDS)
|
||||
# TODO: Ensure that each dep is actually a add_redirector_object target.
|
||||
list(APPEND obj_files $<TARGET_OBJECTS:${dep}>)
|
||||
endforeach(dep)
|
||||
|
||||
# TODO: Call the linker explicitly instead of calling the compiler driver to
|
||||
# prevent DT_NEEDED on C++ runtime.
|
||||
add_library(
|
||||
${target_name}
|
||||
SHARED
|
||||
${obj_files}
|
||||
)
|
||||
set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
target_link_libraries(
|
||||
${target_name}
|
||||
-nostdlib -lc -lm
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
${target_name}
|
||||
PROPERTIES
|
||||
LINKER_LANGUAGE "C"
|
||||
)
|
||||
endfunction(add_redirector_library)
|
||||
|
||||
function(add_libc_unittest target_name)
|
||||
if(NOT LLVM_INCLUDE_TESTS)
|
||||
return()
|
||||
|
||||
@@ -13,6 +13,10 @@ Every entrypoint in LLVM-libc has its own build target. This target is listed
|
||||
using the ``add_entrypoint_object`` rule. This rule generates a single object
|
||||
file containing the implementation of the entrypoint.
|
||||
|
||||
Targets for redirecting entrypoints are also listed using the
|
||||
``add_entrypoint_object`` rule. However, one will have to additionally specify
|
||||
the ``REDIRECTED`` option with the rule.
|
||||
|
||||
Targets for entrypoint libraries
|
||||
--------------------------------
|
||||
|
||||
@@ -22,3 +26,18 @@ the ``lib`` directory as ``add_entrypoint_library`` targets. An
|
||||
``add_entrypoint_library`` target takes a list of ``add_entrypoint_object``
|
||||
targets and produces a static library containing the object files corresponding
|
||||
to the ``add_entrypoint_targets``.
|
||||
|
||||
Targets for redirectors
|
||||
-----------------------
|
||||
|
||||
Similar to how every entrypoint in LLVM-libc has its own build target, every
|
||||
redirector function also has its own build target. This target is listed using
|
||||
the ``add_redirector_object`` rule. This rule generates a single object file
|
||||
which can be packaged along with other redirector objects into shared library
|
||||
of redirectors (see below).
|
||||
|
||||
Targets for library of redirectors
|
||||
----------------------------------
|
||||
|
||||
Targets for shared libraries of redirectors are listed using the
|
||||
``add_redirector_library`` rule.
|
||||
|
||||
69
libc/docs/redirectors.rst
Normal file
69
libc/docs/redirectors.rst
Normal file
@@ -0,0 +1,69 @@
|
||||
Redirectors
|
||||
===========
|
||||
|
||||
When implementing a new C standard library (referred to as *libc* henceforth in
|
||||
this document) starting from scratch, it is unrealistic to expect that we will
|
||||
have the entire library available from day one. In such a scenario, a practical
|
||||
approach is to redirect calls to the unimplemented functions to the same
|
||||
functions from another fully functional libc implementation. Such a scheme can
|
||||
also serve users who would like to mix and match implementations from LLVM libc
|
||||
and another libc implementation. On most platforms, this other libc can be the
|
||||
system libc itself. In this document, we present a strategy one can employ to
|
||||
build redirectors to redirect from LLVM libc to the system libc. For now, the
|
||||
scheme presented is limited to ELF platforms.
|
||||
|
||||
Highlevel Mechanism
|
||||
-------------------
|
||||
|
||||
The highlevel scheme is as below:
|
||||
|
||||
<img src="./redirectors_schematic.svg">
|
||||
|
||||
As shown in the diagram, the mechanism involves a redirector dynamic library
|
||||
which goes in between the llvm-libc static library and the system libc dynamic
|
||||
library. Essentially, LLVM libc provides implementations for all public
|
||||
functions. However, some of the implementations do not actually implement the
|
||||
expected functionality. Instead, they just call the corresponding function in
|
||||
the redirector library, which in turn calls the same function from the system
|
||||
libc.
|
||||
|
||||
Implementation of redirecting entrypoints
|
||||
-----------------------------------------
|
||||
|
||||
Let us take the ``round`` function from ``math.h`` as an example to see what
|
||||
it's implementation looks like when it just redirects to the ``round`` function
|
||||
from the system libc.
|
||||
|
||||
::
|
||||
namespace llvm_libc {
|
||||
|
||||
double __redirected_round(double);
|
||||
|
||||
double LLVM_LIBC_ENTRYPOINT(round)(double x) {
|
||||
return __redirected_round(x);
|
||||
}
|
||||
|
||||
} // namespace llvm_libc
|
||||
|
||||
As can be seen, the ``round`` function from LLVM libc does not call the
|
||||
``round`` function from the system libc directly. It calls a function
|
||||
``__redirected_round`` from the redirector library. The rest of the
|
||||
code follows the conventions described in the *implementation standard*
|
||||
document.
|
||||
|
||||
Implementation of the redirector function
|
||||
-----------------------------------------
|
||||
|
||||
The function ``__redirected_round`` calls the ``round`` function from the system
|
||||
libc. Its implementation is as follows::
|
||||
|
||||
#include <math.h> // Header file from the system libc
|
||||
|
||||
namespace llvm_libc {
|
||||
|
||||
double __redirected_round(double x) {
|
||||
return ::round(x); // Call to round from the system libc
|
||||
}
|
||||
|
||||
} // namespace llvm_libc
|
||||
|
||||
1
libc/docs/redirectors_schematic.svg
Normal file
1
libc/docs/redirectors_schematic.svg
Normal file
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 44 KiB |
@@ -2,8 +2,21 @@
|
||||
add_entrypoint_library(
|
||||
llvmlibc
|
||||
DEPENDS
|
||||
### C standard library entrypoints
|
||||
# string.h entrypoints
|
||||
## C standard library entrypoints
|
||||
strcpy
|
||||
strcat
|
||||
)
|
||||
|
||||
add_entrypoint_library(
|
||||
llvmlibm
|
||||
DEPENDS
|
||||
# math.h entrypoints
|
||||
round
|
||||
)
|
||||
|
||||
add_redirector_library(
|
||||
llvmlibc_redirectors
|
||||
DEPENDS
|
||||
round_redirector
|
||||
)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
add_subdirectory(string)
|
||||
add_subdirectory(math)
|
||||
|
||||
add_subdirectory(__support)
|
||||
|
||||
1
libc/src/math/CMakeLists.txt
Normal file
1
libc/src/math/CMakeLists.txt
Normal file
@@ -0,0 +1 @@
|
||||
add_subdirectory(round)
|
||||
14
libc/src/math/round/CMakeLists.txt
Normal file
14
libc/src/math/round/CMakeLists.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
add_entrypoint_object(
|
||||
round
|
||||
REDIRECTED
|
||||
SRCS
|
||||
round.cpp
|
||||
HDRS
|
||||
round.h
|
||||
)
|
||||
|
||||
add_redirector_object(
|
||||
round_redirector
|
||||
SRC
|
||||
round_redirector.cpp
|
||||
)
|
||||
21
libc/src/math/round/round.cpp
Normal file
21
libc/src/math/round/round.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
//===---------------------- Implementation of round -----------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "src/math/round/round.h"
|
||||
|
||||
#include "src/__support/common.h"
|
||||
|
||||
namespace llvm_libc {
|
||||
|
||||
double __round_redirector(double x);
|
||||
|
||||
double LLVM_LIBC_ENTRYPOINT(round)(double x) {
|
||||
return __round_redirector(x);
|
||||
}
|
||||
|
||||
} // namespace llvm_libc
|
||||
18
libc/src/math/round/round.h
Normal file
18
libc/src/math/round/round.h
Normal file
@@ -0,0 +1,18 @@
|
||||
//===------------------ Implementation header for round -------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_LIBC_SRC_MATH_ROUND_H
|
||||
#define LLVM_LIBC_SRC_MATH_ROUND_H
|
||||
|
||||
namespace llvm_libc {
|
||||
|
||||
double round(double x);
|
||||
|
||||
} // namespace llvm_libc
|
||||
|
||||
#endif // LLVM_LIBC_SRC_MATH_ROUND_H
|
||||
17
libc/src/math/round/round_redirector.cpp
Normal file
17
libc/src/math/round/round_redirector.cpp
Normal file
@@ -0,0 +1,17 @@
|
||||
//===---------------- Implementation of round redirector -----------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include <math.h>
|
||||
|
||||
namespace llvm_libc {
|
||||
|
||||
double __round_redirector(double x) {
|
||||
return ::round(x);
|
||||
}
|
||||
|
||||
} // namespace llvm_libc
|
||||
Reference in New Issue
Block a user