Add basic C++ support
This commit is contained in:
parent
5fce8d2ce1
commit
e702515312
|
@ -17,10 +17,12 @@ endif
|
|||
|
||||
ifdef LLVM_DIR
|
||||
CC := $(LLVM_DIR)/bin/clang
|
||||
CXX := $(LLVM_DIR)/bin/clang++
|
||||
LLC := $(LLVM_DIR)/bin/llc
|
||||
OBJ_DUMP := $(LLVM_DIR)/bin/llvm-objdump
|
||||
else
|
||||
CC := clang-7
|
||||
CXX := clang++-7
|
||||
LLC := llc-7
|
||||
OBJ_DUMP := llvm-objdump-7
|
||||
endif
|
||||
|
@ -33,6 +35,11 @@ CC_FLAGS := \
|
|||
-O2 \
|
||||
-emit-llvm \
|
||||
-fno-builtin \
|
||||
-std=c17 \
|
||||
|
||||
CXX_FLAGS := \
|
||||
$(CC_FLAGS) \
|
||||
-std=c++17 \
|
||||
|
||||
LLC_FLAGS := \
|
||||
-march=bpf \
|
||||
|
@ -46,12 +53,12 @@ OBJ_DUMP_FLAGS := \
|
|||
help:
|
||||
@echo 'BPF Program makefile'
|
||||
@echo ''
|
||||
@echo 'This makefile will build BPF Programs from C source files into ELFs'
|
||||
@echo 'This makefile will build BPF Programs from C or C++ source files into ELFs'
|
||||
@echo ''
|
||||
@echo 'Assumptions:'
|
||||
@echo ' - Programs are a single .c source file (may include headers)'
|
||||
@echo ' - Programs are a single .c or .cc source file (may include headers)'
|
||||
@echo ' - Programs are located in the source directory: $(SRC_DIR)'
|
||||
@echo ' - Programs are named by their basename (eg. file name:foo.c -> program name:foo)'
|
||||
@echo ' - Programs are named by their basename (eg. file name:foo.c/foo.cc -> program name:foo)'
|
||||
@echo ' - Output files will be placed in the directory: $(OUT_DIR)'
|
||||
@echo ''
|
||||
@echo 'User settings'
|
||||
|
@ -90,6 +97,11 @@ $(OUT_DIR)/%.bc: $(SRC_DIR)/%.c
|
|||
$(_@)mkdir -p $(OUT_DIR)
|
||||
$(_@)$(CC) $(CC_FLAGS) $(SYSTEM_INC_DIRS) $(INC_DIRS) -o $@ -c $< -MD -MF $(@:.bc=.d)
|
||||
|
||||
$(OUT_DIR)/%.bc: $(SRC_DIR)/%.cc
|
||||
@echo "[cc] $@ ($<)"
|
||||
$(_@)mkdir -p $(OUT_DIR)
|
||||
$(_@)$(CXX) $(CXX_FLAGS) $(SYSTEM_INC_DIRS) $(INC_DIRS) -o $@ -c $< -MD -MF $(@:.bc=.d)
|
||||
|
||||
.PRECIOUS: $(OUT_DIR)/%.o
|
||||
$(OUT_DIR)/%.o: $(OUT_DIR)/%.bc
|
||||
@echo "[llc] $@ ($<)"
|
||||
|
@ -97,7 +109,7 @@ $(OUT_DIR)/%.o: $(OUT_DIR)/%.bc
|
|||
|
||||
-include $(wildcard $(OUT_DIR)/*.d)
|
||||
|
||||
PROGRAM_NAMES := $(notdir $(basename $(wildcard $(SRC_DIR)/*.c)))
|
||||
PROGRAM_NAMES := $(notdir $(basename $(wildcard $(SRC_DIR)/*.c $(SRC_DIR)/*.cc)))
|
||||
|
||||
define \n
|
||||
|
||||
|
|
|
@ -7,6 +7,16 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Pick up static_assert if C11 or greater
|
||||
*
|
||||
* Inlined here until <assert.h> is available
|
||||
*/
|
||||
#if (defined _ISOC11_SOURCE || (defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L)) && !defined (__cplusplus)
|
||||
#undef static_assert
|
||||
#define static_assert _Static_assert
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Numeric types
|
||||
*/
|
||||
|
@ -23,15 +33,28 @@ typedef unsigned int uint32_t;
|
|||
typedef signed long int int64_t;
|
||||
typedef unsigned long int uint64_t;
|
||||
|
||||
#if defined (__cplusplus) || defined(static_assert)
|
||||
static_assert(sizeof(int8_t) == 1);
|
||||
static_assert(sizeof(uint8_t) == 1);
|
||||
static_assert(sizeof(int16_t) == 2);
|
||||
static_assert(sizeof(uint16_t) == 2);
|
||||
static_assert(sizeof(int32_t) == 4);
|
||||
static_assert(sizeof(uint32_t) == 4);
|
||||
static_assert(sizeof(int64_t) == 8);
|
||||
static_assert(sizeof(uint64_t) == 8);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* NULL
|
||||
*/
|
||||
#define NULL 0
|
||||
|
||||
#ifndef __cplusplus
|
||||
/**
|
||||
* Boolean type
|
||||
*/
|
||||
typedef enum { false = 0, true } bool;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Helper function that prints a string to stdout
|
||||
|
@ -194,7 +217,7 @@ SOL_FN_PREFIX bool sol_deserialize(
|
|||
// account userdata
|
||||
ka[i].userdata_len = *(uint64_t *) input;
|
||||
input += sizeof(uint64_t);
|
||||
ka[i].userdata = input;
|
||||
ka[i].userdata = (uint8_t *) input;
|
||||
input += ka[i].userdata_len;
|
||||
|
||||
// program_id
|
||||
|
@ -240,19 +263,19 @@ SOL_FN_PREFIX void sol_log_array(const uint8_t *array, int len) {
|
|||
/**
|
||||
* Prints the hexadecimal representation of the program's input parameters
|
||||
*
|
||||
* @param num_ka Numer of SolKeyedAccounts to print
|
||||
* @param ka A pointer to an array of SolKeyedAccounts to print
|
||||
* @param ka_len Number of SolKeyedAccounts to print
|
||||
* @param data A pointer to the instruction data to print
|
||||
* @param data_len The length in bytes of the instruction data
|
||||
*/
|
||||
SOL_FN_PREFIX void sol_log_params(
|
||||
uint64_t num_ka,
|
||||
const SolKeyedAccounts *ka,
|
||||
uint64_t ka_len,
|
||||
const uint8_t *data,
|
||||
uint64_t data_len
|
||||
) {
|
||||
sol_log_64(0, 0, 0, 0, num_ka);
|
||||
for (int i = 0; i < num_ka; i++) {
|
||||
sol_log_64(0, 0, 0, 0, ka_len);
|
||||
for (int i = 0; i < ka_len; i++) {
|
||||
sol_log_key(ka[i].key);
|
||||
sol_log_64(0, 0, 0, 0, *ka[i].tokens);
|
||||
sol_log_array(ka[i].userdata, ka[i].userdata_len);
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* @brief Example C++-based BPF program that prints out the parameters
|
||||
* passed to it
|
||||
*/
|
||||
#include <solana_sdk.h>
|
||||
|
||||
extern bool entrypoint(const uint8_t *input) {
|
||||
SolKeyedAccounts ka[1];
|
||||
uint64_t ka_len;
|
||||
const uint8_t *data;
|
||||
uint64_t data_len;
|
||||
|
||||
sol_log("noop++");
|
||||
|
||||
if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Log the provided account keys and instruction input data. In the case of
|
||||
// the no-op program, no account keys or input data are expected but real
|
||||
// programs will have specific requirements so they can do their work.
|
||||
sol_log_params(ka, ka_len, data, data_len);
|
||||
return true;
|
||||
}
|
|
@ -2,34 +2,23 @@
|
|||
* @brief Example C-based BPF program that prints out the parameters
|
||||
* passed to it
|
||||
*/
|
||||
|
||||
#include <solana_sdk.h>
|
||||
|
||||
/**
|
||||
* Number of SolKeyedAccounts expected. The program should bail if an
|
||||
* unexpected number of accounts are passed to the program's entrypoint
|
||||
*/
|
||||
#define NUM_KA 1
|
||||
|
||||
extern bool entrypoint(const uint8_t *input) {
|
||||
SolKeyedAccounts ka[NUM_KA];
|
||||
SolKeyedAccounts ka[1];
|
||||
uint64_t ka_len;
|
||||
const uint8_t *data;
|
||||
uint64_t data_len;
|
||||
|
||||
sol_log("noop");
|
||||
sol_log(__FILE__);
|
||||
|
||||
if (!sol_deserialize(input, ka, NUM_KA, NULL, &data, &data_len)) {
|
||||
if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len)) {
|
||||
return false;
|
||||
}
|
||||
sol_log_params(NUM_KA, ka, data, data_len);
|
||||
|
||||
sol_assert(sizeof(int8_t) == 1);
|
||||
sol_assert(sizeof(uint8_t) == 1);
|
||||
sol_assert(sizeof(int16_t) == 2);
|
||||
sol_assert(sizeof(uint16_t) == 2);
|
||||
sol_assert(sizeof(int32_t) == 4);
|
||||
sol_assert(sizeof(uint32_t) == 4);
|
||||
sol_assert(sizeof(int64_t) == 8);
|
||||
sol_assert(sizeof(uint64_t) == 8);
|
||||
// Log the provided account keys and instruction input data. In the case of
|
||||
// the no-op program, no account keys or input data are expected but real
|
||||
// programs will have specific requirements so they can do their work.
|
||||
sol_log_params(ka, ka_len, data, data_len);
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue