Skip to content

Commit

Permalink
Add xtensa AOT support and fix build issue of alios (bytecodealliance…
Browse files Browse the repository at this point in the history
…#223)

* Clean compiling warnings of zephyr samples

* Support xtensa AOT and fix build issue of alios
  • Loading branch information
Weining2019 authored Apr 1, 2020
1 parent c1a0e6d commit c6fc12b
Show file tree
Hide file tree
Showing 20 changed files with 762 additions and 68 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ Execute following commands to build **wamrc** compiler:

```shell
cd wamr-compiler
./build_llvm.sh
./build_llvm.sh (use build_llvm_xtensa.sh instead to support xtensa target)
mkdir build && cd build
cmake ..
make
Expand Down
35 changes: 28 additions & 7 deletions core/iwasm/aot/aot_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -985,14 +985,21 @@ load_text_section(const uint8 *buf, const uint8 *buf_end,
return false;
}

module->code = (void*)buf;
module->code_size = (uint32)(buf_end - buf);
read_uint32(buf, buf_end, module->literal_size);

/* literal data is at begining of the text section */
module->literal = (uint8*)buf;
module->code = (void*)(buf + module->literal_size);
module->code_size = (uint32)(buf_end - (uint8*)module->code);

if (module->code_size > 0) {
plt_base = (uint8*)buf_end - get_plt_table_size();
init_plt_table(plt_base);
}
return true;

fail:
return false;
}

static bool
Expand Down Expand Up @@ -1184,13 +1191,20 @@ resolve_target_sym(const char *symbol, int32 *p_index)
return NULL;
}

static bool
is_literal_relocation(const char *reloc_sec_name)
{
return !strcmp(reloc_sec_name, ".rela.literal");
}

static bool
do_text_relocation(AOTModule *module,
AOTRelocationGroup *group,
char *error_buf, uint32 error_buf_size)
{
uint8 *aot_text = module->code;
uint32 aot_text_size = module->code_size;
bool is_literal = is_literal_relocation(group->section_name);
uint8 *aot_text = is_literal ? module->literal : module->code;
uint32 aot_text_size = is_literal ? module->literal_size : module->code_size;
uint32 i, func_index, symbol_len;
char symbol_buf[128] = { 0 }, *symbol, *p;
void *symbol_addr;
Expand Down Expand Up @@ -1248,6 +1262,9 @@ do_text_relocation(AOTModule *module,
goto check_symbol_fail;
}
}
else if (!strcmp(symbol, ".literal")) {
symbol_addr = module->literal;
}
else if (!(symbol_addr = resolve_target_sym(symbol, &symbol_index))) {
if (error_buf != NULL)
snprintf(error_buf, error_buf_size,
Expand Down Expand Up @@ -1495,7 +1512,8 @@ load_relocation_section(const uint8 *buf, const uint8 *buf_end,
}

if (!strcmp(group->section_name, ".rel.text")
|| !strcmp(group->section_name, ".rela.text")) {
|| !strcmp(group->section_name, ".rela.text")
|| !strcmp(group->section_name, ".rela.literal")) {
if (!do_text_relocation(module, group, error_buf, error_buf_size))
return false;
}
Expand Down Expand Up @@ -2079,8 +2097,11 @@ aot_unload(AOTModule *module)
if (module->const_str_set)
bh_hash_map_destroy(module->const_str_set);

if (module->code)
os_munmap(module->code, module->code_size);
if (module->code) {
uint8 *mmap_addr = module->literal - sizeof(module->literal_size);
uint32 total_size = sizeof(module->literal_size) + module->literal_size + module->code_size;
os_munmap(mmap_addr, total_size);
}

if (module->data_sections)
destroy_object_data_sections(module->data_sections,
Expand Down
4 changes: 4 additions & 0 deletions core/iwasm/aot/aot_runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ typedef struct AOTModule {
void *code;
uint32 code_size;

/* literal for AOTed code, NULL for JIT mode */
uint8 *literal;
uint32 literal_size;

/* data sections in AOT object file, including .data, .rodata
* and .rodata.cstN. NULL for JIT mode. */
AOTObjectDataSection *data_sections;
Expand Down
171 changes: 169 additions & 2 deletions core/iwasm/aot/arch/aot_reloc_xtensa.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,50 @@

#include "aot_reloc.h"

#define R_XTENSA_32 1 /* Direct 32 bit */
#define R_XTENSA_SLOT0_OP 20 /* PC relative */

/* for soft-float */
void __floatsidf();
void __divdf3();
void __ltdf2();

/* for mul32 */
void __mulsi3();
void __muldi3();

void __modsi3();

void __divdi3();

static SymbolMap target_sym_map[] = {
REG_COMMON_SYMBOLS
REG_COMMON_SYMBOLS,

/* API's for soft-float */
/* TODO: only register these symbols when Floating-Point Coprocessor
* Option is not enabled */
REG_SYM(__floatsidf),
REG_SYM(__divdf3),
REG_SYM(__ltdf2),

/* API's for 32-bit integer multiply */
/* TODO: only register these symbols when 32-bit Integer Multiply Option
* is not enabled */
REG_SYM(__mulsi3),
REG_SYM(__muldi3),

REG_SYM(__modsi3),

REG_SYM(__divdi3),
};

static void
set_error_buf(char *error_buf, uint32 error_buf_size, const char *string)
{
if (error_buf != NULL)
snprintf(error_buf, error_buf_size, "%s", string);
}

SymbolMap *
get_target_symbol_map(uint32 *sym_num)
{
Expand Down Expand Up @@ -40,6 +80,67 @@ get_plt_table_size()
return get_plt_item_size() * (sizeof(target_sym_map) / sizeof(SymbolMap));
}

static bool
check_reloc_offset(uint32 target_section_size,
uint64 reloc_offset, uint32 reloc_data_size,
char *error_buf, uint32 error_buf_size)
{
if (!(reloc_offset < (uint64)target_section_size
&& reloc_offset + reloc_data_size <= (uint64)target_section_size)) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: invalid relocation offset.");
return false;
}
return true;
}

/*
* CPU like esp32 can read and write data through the instruction bus, but only
* in a word aligned manner; non-word-aligned access will cause a CPU exception.
* This function uses a world aligned manner to write 16bit value to instruction
* addreess.
*/
static void
put_imm16_to_addr(int16 imm16, int16 *addr)
{
int8 bytes[8];
int32 *addr_aligned1, *addr_aligned2;

addr_aligned1 = (int32*)((intptr_t)addr & ~3);

if ((intptr_t)addr % 4 != 3) {
*(int32*)bytes = *addr_aligned1;
*(int16*)(bytes + ((intptr_t)addr % 4)) = imm16;
memcpy(addr_aligned1, bytes, 4);
}
else {
addr_aligned2 = (int32*)(((intptr_t)addr + 3) & ~3);
*(int32*)bytes = *addr_aligned1;
*(int32*)(bytes + 4) = *addr_aligned2;
*(int16*)(bytes + 3) = imm16;
memcpy(addr_aligned1, bytes, 8);
}
}

static union {
int a;
char b;
} __ue = { .a = 1 };

#define is_little_endian() (__ue.b == 1)

typedef union {
struct l32r_le {
int8 other;
int16 imm16;
} __packed l;

struct l32r_be {
int16 imm16;
int8 other;
} __packed b;
} l32r_insn_t;

bool
apply_relocation(AOTModule *module,
uint8 *target_section_addr, uint32 target_section_size,
Expand All @@ -48,7 +149,73 @@ apply_relocation(AOTModule *module,
char *error_buf, uint32 error_buf_size)
{
switch (reloc_type) {
/* TODO: implement relocation for xtensa */
case R_XTENSA_32:
{
uint8 *insn_addr = target_section_addr + reloc_offset;
int32 initial_addend;
/* (S + A) */
if ((intptr_t)insn_addr & 3) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"instruction address unaligned.");
return false;
}
CHECK_RELOC_OFFSET(4);
initial_addend = *(int32*)insn_addr;
*(uint8**)insn_addr
= (uint8*)symbol_addr + initial_addend + reloc_addend;
break;
}

case R_XTENSA_SLOT0_OP:
{
uint8 *insn_addr = target_section_addr + reloc_offset;
/* Currently only l32r instruction generates R_XTENSA_SLOT0_OP relocation */
l32r_insn_t *l32r_insn = (l32r_insn_t *)insn_addr;
uint8 *reloc_addr;
int32 relative_offset/*, initial_addend */;
int16 imm16;

CHECK_RELOC_OFFSET(3); /* size of l32r instruction */

/*
imm16 = is_little_endian() ?
l32r_insn->l.imm16 : l32r_insn->b.imm16;
initial_addend = (int32)imm16 << 2;
*/

reloc_addr = (uint8*)symbol_addr + reloc_addend;

if ((intptr_t)reloc_addr & 3) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"relocation address unaligned.");
return false;
}

relative_offset = (int32)
((intptr_t)reloc_addr -
(((intptr_t)insn_addr + 3) & ~(intptr_t)3));
/* relative_offset += initial_addend; */

/* check relative offset boundary */
if (relative_offset < -256 * BH_KB || relative_offset > -4) {
set_error_buf(error_buf, error_buf_size,
"AOT module load failed: "
"target address out of range.");
return false;
}

imm16 = (int16)(relative_offset >> 2);

/* write back the imm16 to the l32r instruction */
if (is_little_endian())
put_imm16_to_addr(imm16, &l32r_insn->l.imm16);
else
put_imm16_to_addr(imm16, &l32r_insn->b.imm16);

break;
}

default:
if (error_buf != NULL)
Expand Down
38 changes: 37 additions & 1 deletion core/iwasm/compilation/aot_emit_aot_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ typedef struct AOTObjectData {
void *text;
uint32 text_size;

/* literal data and size */
void *literal;
uint32 literal_size;

AOTObjectDataSection *data_sections;
uint32 data_sections_count;

Expand Down Expand Up @@ -379,7 +383,7 @@ get_init_data_section_size(AOTCompData *comp_data, AOTObjectData *obj_data)
static uint32
get_text_section_size(AOTObjectData *obj_data)
{
return obj_data->text_size;
return (sizeof(uint32) + obj_data->literal_size + obj_data->text_size + 3) & ~3;
}

static uint32
Expand Down Expand Up @@ -1118,13 +1122,20 @@ aot_emit_text_section(uint8 *buf, uint8 *buf_end, uint32 *p_offset,
{
uint32 section_size = get_text_section_size(obj_data);
uint32 offset = *p_offset;
uint8 placeholder = 0;

*p_offset = offset = align_uint(offset, 4);

EMIT_U32(AOT_SECTION_TYPE_TEXT);
EMIT_U32(section_size);
EMIT_U32(obj_data->literal_size);
if (obj_data->literal_size > 0)
EMIT_BUF(obj_data->literal, obj_data->literal_size);
EMIT_BUF(obj_data->text, obj_data->text_size);

while (offset & 3)
EMIT_BUF(&placeholder, 1);

if (offset - *p_offset != section_size + sizeof(uint32) * 2) {
aot_set_last_error("emit text section failed.");
return false;
Expand Down Expand Up @@ -1449,6 +1460,29 @@ aot_resolve_text(AOTObjectData *obj_data)
return true;
}

static bool
aot_resolve_literal(AOTObjectData *obj_data)
{
LLVMSectionIteratorRef sec_itr;
char *name;

if (!(sec_itr = LLVMObjectFileCopySectionIterator(obj_data->binary))) {
aot_set_last_error("llvm get section iterator failed.");
return false;
}
while (!LLVMObjectFileIsSectionIteratorAtEnd(obj_data->binary, sec_itr)) {
if ((name = (char *)LLVMGetSectionName(sec_itr)) && !strcmp(name, ".literal")) {
obj_data->literal = (char *)LLVMGetSectionContents(sec_itr);
obj_data->literal_size = (uint32)LLVMGetSectionSize(sec_itr);
break;
}
LLVMMoveToNextSection(sec_itr);
}
LLVMDisposeSectionIterator(sec_itr);

return true;
}

static bool
is_data_section(char *section_name)
{
Expand Down Expand Up @@ -1701,6 +1735,7 @@ is_relocation_section(char *section_name)
{
return (!strcmp(section_name, ".rela.text")
|| !strcmp(section_name, ".rel.text")
|| !strcmp(section_name, ".rela.literal")
|| !strcmp(section_name, ".rela.data")
|| !strcmp(section_name, ".rel.data")
|| !strcmp(section_name, ".rela.rodata")
Expand Down Expand Up @@ -1873,6 +1908,7 @@ aot_obj_data_create(AOTCompContext *comp_ctx)
/* resolve target info/text/relocations/functions */
if (!aot_resolve_target_info(comp_ctx, obj_data)
|| !aot_resolve_text(obj_data)
|| !aot_resolve_literal(obj_data)
|| !aot_resolve_object_data_sections(obj_data)
|| !aot_resolve_object_relocation_groups(obj_data)
|| !aot_resolve_functions(comp_ctx, obj_data))
Expand Down
Loading

0 comments on commit c6fc12b

Please sign in to comment.