Add basic C++ support

This commit is contained in:
Michael Vines 2018-11-11 09:54:27 -08:00 committed by Grimes
parent 5fce8d2ce1
commit e702515312
4 changed files with 77 additions and 29 deletions

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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");
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;
}
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;
}