Add basic C++ support
This commit is contained in:
parent
5fce8d2ce1
commit
e702515312
|
@ -17,10 +17,12 @@ endif
|
||||||
|
|
||||||
ifdef LLVM_DIR
|
ifdef LLVM_DIR
|
||||||
CC := $(LLVM_DIR)/bin/clang
|
CC := $(LLVM_DIR)/bin/clang
|
||||||
|
CXX := $(LLVM_DIR)/bin/clang++
|
||||||
LLC := $(LLVM_DIR)/bin/llc
|
LLC := $(LLVM_DIR)/bin/llc
|
||||||
OBJ_DUMP := $(LLVM_DIR)/bin/llvm-objdump
|
OBJ_DUMP := $(LLVM_DIR)/bin/llvm-objdump
|
||||||
else
|
else
|
||||||
CC := clang-7
|
CC := clang-7
|
||||||
|
CXX := clang++-7
|
||||||
LLC := llc-7
|
LLC := llc-7
|
||||||
OBJ_DUMP := llvm-objdump-7
|
OBJ_DUMP := llvm-objdump-7
|
||||||
endif
|
endif
|
||||||
|
@ -33,6 +35,11 @@ CC_FLAGS := \
|
||||||
-O2 \
|
-O2 \
|
||||||
-emit-llvm \
|
-emit-llvm \
|
||||||
-fno-builtin \
|
-fno-builtin \
|
||||||
|
-std=c17 \
|
||||||
|
|
||||||
|
CXX_FLAGS := \
|
||||||
|
$(CC_FLAGS) \
|
||||||
|
-std=c++17 \
|
||||||
|
|
||||||
LLC_FLAGS := \
|
LLC_FLAGS := \
|
||||||
-march=bpf \
|
-march=bpf \
|
||||||
|
@ -46,12 +53,12 @@ OBJ_DUMP_FLAGS := \
|
||||||
help:
|
help:
|
||||||
@echo 'BPF Program makefile'
|
@echo 'BPF Program makefile'
|
||||||
@echo ''
|
@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 ''
|
||||||
@echo 'Assumptions:'
|
@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 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 ' - Output files will be placed in the directory: $(OUT_DIR)'
|
||||||
@echo ''
|
@echo ''
|
||||||
@echo 'User settings'
|
@echo 'User settings'
|
||||||
|
@ -90,6 +97,11 @@ $(OUT_DIR)/%.bc: $(SRC_DIR)/%.c
|
||||||
$(_@)mkdir -p $(OUT_DIR)
|
$(_@)mkdir -p $(OUT_DIR)
|
||||||
$(_@)$(CC) $(CC_FLAGS) $(SYSTEM_INC_DIRS) $(INC_DIRS) -o $@ -c $< -MD -MF $(@:.bc=.d)
|
$(_@)$(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
|
.PRECIOUS: $(OUT_DIR)/%.o
|
||||||
$(OUT_DIR)/%.o: $(OUT_DIR)/%.bc
|
$(OUT_DIR)/%.o: $(OUT_DIR)/%.bc
|
||||||
@echo "[llc] $@ ($<)"
|
@echo "[llc] $@ ($<)"
|
||||||
|
@ -97,7 +109,7 @@ $(OUT_DIR)/%.o: $(OUT_DIR)/%.bc
|
||||||
|
|
||||||
-include $(wildcard $(OUT_DIR)/*.d)
|
-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
|
define \n
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,16 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
* Numeric types
|
||||||
*/
|
*/
|
||||||
|
@ -23,15 +33,28 @@ typedef unsigned int uint32_t;
|
||||||
typedef signed long int int64_t;
|
typedef signed long int int64_t;
|
||||||
typedef unsigned long int uint64_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
|
* NULL
|
||||||
*/
|
*/
|
||||||
#define NULL 0
|
#define NULL 0
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
/**
|
/**
|
||||||
* Boolean type
|
* Boolean type
|
||||||
*/
|
*/
|
||||||
typedef enum { false = 0, true } bool;
|
typedef enum { false = 0, true } bool;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function that prints a string to stdout
|
* Helper function that prints a string to stdout
|
||||||
|
@ -194,7 +217,7 @@ SOL_FN_PREFIX bool sol_deserialize(
|
||||||
// account userdata
|
// account userdata
|
||||||
ka[i].userdata_len = *(uint64_t *) input;
|
ka[i].userdata_len = *(uint64_t *) input;
|
||||||
input += sizeof(uint64_t);
|
input += sizeof(uint64_t);
|
||||||
ka[i].userdata = input;
|
ka[i].userdata = (uint8_t *) input;
|
||||||
input += ka[i].userdata_len;
|
input += ka[i].userdata_len;
|
||||||
|
|
||||||
// program_id
|
// 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
|
* 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 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 A pointer to the instruction data to print
|
||||||
* @param data_len The length in bytes of the instruction data
|
* @param data_len The length in bytes of the instruction data
|
||||||
*/
|
*/
|
||||||
SOL_FN_PREFIX void sol_log_params(
|
SOL_FN_PREFIX void sol_log_params(
|
||||||
uint64_t num_ka,
|
|
||||||
const SolKeyedAccounts *ka,
|
const SolKeyedAccounts *ka,
|
||||||
|
uint64_t ka_len,
|
||||||
const uint8_t *data,
|
const uint8_t *data,
|
||||||
uint64_t data_len
|
uint64_t data_len
|
||||||
) {
|
) {
|
||||||
sol_log_64(0, 0, 0, 0, num_ka);
|
sol_log_64(0, 0, 0, 0, ka_len);
|
||||||
for (int i = 0; i < num_ka; i++) {
|
for (int i = 0; i < ka_len; i++) {
|
||||||
sol_log_key(ka[i].key);
|
sol_log_key(ka[i].key);
|
||||||
sol_log_64(0, 0, 0, 0, *ka[i].tokens);
|
sol_log_64(0, 0, 0, 0, *ka[i].tokens);
|
||||||
sol_log_array(ka[i].userdata, ka[i].userdata_len);
|
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
|
* @brief Example C-based BPF program that prints out the parameters
|
||||||
* passed to it
|
* passed to it
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <solana_sdk.h>
|
#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) {
|
extern bool entrypoint(const uint8_t *input) {
|
||||||
SolKeyedAccounts ka[NUM_KA];
|
SolKeyedAccounts ka[1];
|
||||||
|
uint64_t ka_len;
|
||||||
const uint8_t *data;
|
const uint8_t *data;
|
||||||
uint64_t data_len;
|
uint64_t data_len;
|
||||||
|
|
||||||
sol_log("noop");
|
|
||||||
|
|
||||||
if (!sol_deserialize(input, ka, NUM_KA, NULL, &data, &data_len)) {
|
sol_log(__FILE__);
|
||||||
|
|
||||||
|
if (!sol_deserialize(input, ka, SOL_ARRAY_SIZE(ka), &ka_len, &data, &data_len)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
sol_log_params(NUM_KA, ka, data, data_len);
|
|
||||||
|
|
||||||
sol_assert(sizeof(int8_t) == 1);
|
// Log the provided account keys and instruction input data. In the case of
|
||||||
sol_assert(sizeof(uint8_t) == 1);
|
// the no-op program, no account keys or input data are expected but real
|
||||||
sol_assert(sizeof(int16_t) == 2);
|
// programs will have specific requirements so they can do their work.
|
||||||
sol_assert(sizeof(uint16_t) == 2);
|
sol_log_params(ka, ka_len, data, data_len);
|
||||||
sol_assert(sizeof(int32_t) == 4);
|
|
||||||
sol_assert(sizeof(uint32_t) == 4);
|
|
||||||
sol_assert(sizeof(int64_t) == 8);
|
|
||||||
sol_assert(sizeof(uint64_t) == 8);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue