[go: nahoru, domu]

Skip to content

Commit

Permalink
Implement Global Instructions
Browse files Browse the repository at this point in the history
Signed-off-by: Adam Laszlo Kulcsar <kuladam@inf.u-szeged.hu>
  • Loading branch information
kulcsaradam committed May 18, 2023
1 parent 04050cb commit 140fb34
Show file tree
Hide file tree
Showing 8 changed files with 233 additions and 2 deletions.
58 changes: 58 additions & 0 deletions src/jit/Backend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

#include "runtime/JITExec.h"
#include "runtime/Memory.h"
#include "runtime/Global.h"
#include "jit/Compiler.h"
#include "util/MathOperation.h"
#include "runtime/Instance.h"

#include <math.h>
#include <map>
Expand Down Expand Up @@ -84,6 +86,12 @@ class JITFieldAccessor {
{
return offsetof(Memory, m_buffer);
}

static sljit_sw
globalValueOffset()
{
return offsetof(Global, m_value) + offsetof(Value, m_i32);
}
};

class SlowCase {
Expand Down Expand Up @@ -120,6 +128,9 @@ struct CompileContext {
, trapLabel(nullptr)
, memoryTrapLabel(nullptr)
{
// same calculation as in Instance::alingedSize() but that is private
sljit_sw offset = (sizeof(Instance) + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
globalStart = offset + sizeof(void*) * compiler->module()->numberOfMemoryTypes();
}

static CompileContext* get(sljit_compiler* compiler)
Expand All @@ -136,6 +147,7 @@ struct CompileContext {
sljit_label* memoryTrapLabel;
sljit_label* returnToLabel;
sljit_uw branchTableOffset;
sljit_sw globalStart;
std::vector<TrapBlock> trapBlocks;
std::vector<SlowCase*> slowCases;
std::vector<sljit_jump*> earlyReturns;
Expand Down Expand Up @@ -424,6 +436,36 @@ static void emitMove32(sljit_compiler* compiler, Instruction* instr)
sljit_emit_op1(compiler, SLJIT_MOV32, dst.arg, dst.argw, src.arg, src.argw);
}

static void emitGlobalGet32(sljit_compiler* compiler, Instruction* instr)
{
CompileContext* context = CompileContext::get(compiler);
Operand* operands = instr->operands();
JITArg dst;

operandToArg(operands, dst);

GlobalGet32* globalGet = reinterpret_cast<GlobalGet32*>(instr->byteCode());

sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_MEM1(kContextReg), OffsetOfContextField(instance));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), context->globalStart + globalGet->index() * sizeof(void*));
sljit_emit_op1(compiler, SLJIT_MOV, dst.arg, dst.argw, SLJIT_MEM1(SLJIT_R0), JITFieldAccessor::globalValueOffset());
}

static void emitGlobalSet32(sljit_compiler* compiler, Instruction* instr)
{
CompileContext* context = CompileContext::get(compiler);
Operand* operands = instr->operands();
JITArg src;

operandToArg(operands, src);

GlobalSet32* globalSet = reinterpret_cast<GlobalSet32*>(instr->byteCode());

sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(kContextReg), OffsetOfContextField(instance));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), context->globalStart + globalSet->index() * sizeof(void*));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), JITFieldAccessor::globalValueOffset(), src.arg, src.argw);
}

JITModule::~JITModule()
{
delete m_instanceConstData->trapHandlers;
Expand Down Expand Up @@ -570,6 +612,22 @@ JITModule* JITCompiler::compile()
emitMemory(m_compiler, item->asInstruction());
break;
}
case Instruction::GlobalGet: {
if (item->asInstruction()->opcode() == GlobalGet32Opcode) {
emitGlobalGet32(m_compiler, item->asInstruction());
} else {
emitGlobalGet64(m_compiler, item->asInstruction());
}
break;
}
case Instruction::GlobalSet: {
if (item->asInstruction()->opcode() == GlobalSet32Opcode) {
emitGlobalSet32(m_compiler, item->asInstruction());
} else {
emitGlobalSet64(m_compiler, item->asInstruction());
}
break;
}
case Instruction::Move: {
if (item->asInstruction()->opcode() == Move32Opcode) {
emitMove32(m_compiler, item->asInstruction());
Expand Down
46 changes: 45 additions & 1 deletion src/jit/ByteCodeParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,50 @@ static void createInstructionList(JITCompiler* compiler, ModuleFunction* functio
operands[1].offset = STACK_OFFSET(move64->dstOffset());
break;
}
case GlobalGet32Opcode: {
Instruction* instr = compiler->append(byteCode, Instruction::GlobalGet, GlobalGet32Opcode, 0, 1);

GlobalGet32* globalGet32 = reinterpret_cast<GlobalGet32*>(byteCode);
Operand* operands = instr->operands();

operands[0].item = nullptr;
operands[0].offset = STACK_OFFSET(globalGet32->dstOffset());

break;
}
case GlobalGet64Opcode: {
Instruction* instr = compiler->append(byteCode, Instruction::GlobalGet, GlobalGet64Opcode, 0, 1);

GlobalGet64* globalGet64 = reinterpret_cast<GlobalGet64*>(byteCode);
Operand* operands = instr->operands();

operands[0].item = nullptr;
operands[0].offset = STACK_OFFSET(globalGet64->dstOffset());

break;
}
case GlobalSet32Opcode: {
Instruction* instr = compiler->append(byteCode, Instruction::GlobalSet, GlobalSet32Opcode, 1, 0);

GlobalSet32* globalSet32 = reinterpret_cast<GlobalSet32*>(byteCode);
Operand* operands = instr->operands();

operands[0].item = nullptr;
operands[0].offset = STACK_OFFSET(globalSet32->srcOffset());

break;
}
case GlobalSet64Opcode: {
Instruction* instr = compiler->append(byteCode, Instruction::GlobalSet, GlobalSet64Opcode, 1, 0);

GlobalSet64* globalSet64 = reinterpret_cast<GlobalSet64*>(byteCode);
Operand* operands = instr->operands();

operands[0].item = nullptr;
operands[0].offset = STACK_OFFSET(globalSet64->srcOffset());

break;
}
case EndOpcode: {
uint32_t size = function->functionType()->result().size();

Expand Down Expand Up @@ -621,7 +665,7 @@ void Module::jitCompile(int verboseLevel)
return;
}

JITCompiler compiler(verboseLevel);
JITCompiler compiler(this, verboseLevel);

for (size_t i = 0; i < functionCount; i++) {
if (verboseLevel >= 1) {
Expand Down
9 changes: 8 additions & 1 deletion src/jit/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ class InstructionListItem {
Memory,
// Move operation. (e.g. Move32, Move64)
Move,
// GlobalGet operation (e.g. GlobalGet32, GlobalGet64)
GlobalGet,
// GlobalSet operation (e.g. GlobalSet32, GlobalSet64)
GlobalSet,
};

virtual ~InstructionListItem() {}
Expand Down Expand Up @@ -397,12 +401,13 @@ class JITCompiler {
public:
static const uint32_t kHasCondMov = 1 << 0;

JITCompiler(int verboseLevel)
JITCompiler(Module* module, int verboseLevel)
: m_first(nullptr)
, m_last(nullptr)
, m_functionListFirst(nullptr)
, m_functionListLast(nullptr)
, m_compiler(nullptr)
, m_module(module)
, m_branchTableSize(0)
, m_verboseLevel(verboseLevel)
, m_options(0)
Expand All @@ -416,6 +421,7 @@ class JITCompiler {
releaseFunctionList();
}

Module* module() { return m_module; }
int verboseLevel() { return m_verboseLevel; }
uint32_t options() { return m_options; }
InstructionListItem* first() { return m_first; }
Expand Down Expand Up @@ -484,6 +490,7 @@ class JITCompiler {
InstructionListItem* m_functionListLast;

sljit_compiler* m_compiler;
Module* m_module;
size_t m_branchTableSize;
int m_verboseLevel;
uint32_t m_options;
Expand Down
32 changes: 32 additions & 0 deletions src/jit/IntMath32Inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -1159,3 +1159,35 @@ static void emitMove64(sljit_compiler* compiler, Instruction* instr)
sljit_emit_op1(compiler, SLJIT_MOV, dst.arg1, dst.arg1w, src.arg1, src.arg1w);
sljit_emit_op1(compiler, SLJIT_MOV, dst.arg2, dst.arg2w, src.arg2, src.arg2w);
}

static void emitGlobalGet64(sljit_compiler* compiler, Instruction* instr)
{
CompileContext* context = CompileContext::get(compiler);
Operand* operands = instr->operands();
JITArgPair dst;

operandToArgPair(operands, dst);

GlobalGet64* globalGet = reinterpret_cast<GlobalGet64*>(instr->byteCode());

sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_MEM1(kContextReg), OffsetOfContextField(instance));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), context->globalStart + globalGet->index() * sizeof(void*));
sljit_emit_op1(compiler, SLJIT_MOV, dst.arg1, dst.arg1w, SLJIT_MEM1(SLJIT_R0), JITFieldAccessor::globalValueOffset());
sljit_emit_op1(compiler, SLJIT_MOV, dst.arg2, dst.arg2w, SLJIT_MEM1(SLJIT_R0), JITFieldAccessor::globalValueOffset() + 4);
}

static void emitGlobalSet64(sljit_compiler* compiler, Instruction* instr)
{
CompileContext* context = CompileContext::get(compiler);
Operand* operands = instr->operands();
JITArgPair src;

operandToArgPair(operands, src);

GlobalSet32* globalSet = reinterpret_cast<GlobalSet32*>(instr->byteCode());

sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(kContextReg), OffsetOfContextField(instance));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), context->globalStart + globalSet->index() * sizeof(void*));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), JITFieldAccessor::globalValueOffset(), src.arg1, src.arg1w);
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), JITFieldAccessor::globalValueOffset() + 4, src.arg2, src.arg2w);
}
30 changes: 30 additions & 0 deletions src/jit/IntMath64Inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,33 @@ static void emitMove64(sljit_compiler* compiler, Instruction* instr)

sljit_emit_op1(compiler, SLJIT_MOV, dst.arg, dst.argw, src.arg, src.argw);
}

static void emitGlobalGet64(sljit_compiler* compiler, Instruction* instr)
{
CompileContext* context = CompileContext::get(compiler);
Operand* operands = instr->operands();
JITArg dst;

operandToArg(operands, dst);

GlobalGet64* globalGet = reinterpret_cast<GlobalGet64*>(instr->byteCode());

sljit_emit_op1(compiler, SLJIT_MOV_P, SLJIT_R0, 0, SLJIT_MEM1(kContextReg), OffsetOfContextField(instance));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), context->globalStart + globalGet->index() * sizeof(void*));
sljit_emit_op1(compiler, SLJIT_MOV, dst.arg, dst.argw, SLJIT_MEM1(SLJIT_R0), JITFieldAccessor::globalValueOffset());
}

static void emitGlobalSet64(sljit_compiler* compiler, Instruction* instr)
{
CompileContext* context = CompileContext::get(compiler);
Operand* operands = instr->operands();
JITArg src;

operandToArg(operands, src);

GlobalSet64* globalSet = reinterpret_cast<GlobalSet64*>(instr->byteCode());

sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(kContextReg), OffsetOfContextField(instance));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_R0, 0, SLJIT_MEM1(SLJIT_R0), context->globalStart + globalSet->index() * sizeof(void*));
sljit_emit_op1(compiler, SLJIT_MOV, SLJIT_MEM1(SLJIT_R0), JITFieldAccessor::globalValueOffset(), src.arg, src.argw);
}
2 changes: 2 additions & 0 deletions src/runtime/Global.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
namespace Walrus {

class Global : public Extern {
friend class JITFieldAccessor;

public:
static Global* createGlobal(Store* store, const Value& value)
{
Expand Down
2 changes: 2 additions & 0 deletions src/runtime/Value.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ size_t stackAllocatedSize()
}

class Value {
friend class JITFieldAccessor;

public:
// https://webassembly.github.io/spec/core/syntax/types.html

Expand Down
56 changes: 56 additions & 0 deletions test/jit/global.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
(module

(global $a (mut i32) (i32.const 1))
(global $b (mut i64) (i64.const 2))
(global (;2;) i32 (i32.const 3))
(global (;3;) i64 (i64.const 4))
(global $c (mut f32) (f32.const 5.5))
(global $d (mut f64) (f64.const 6.6))
(global (;6;) f32 (f32.const 7.7))
(global (;7;) f64 (f64.const 8.8))

(func (export "global_a") (result i32) global.get $a )
(func (export "global_b") (result i64) global.get $b )
(func (export "global_c") (result f32) global.get $c )
(func (export "global_d") (result f64) global.get $d )

(func (export "global_2") (result i32) global.get 2 )
(func (export "global_3") (result i64) global.get 3 )
(func (export "global_6") (result f32) global.get 6 )
(func (export "global_7") (result f64) global.get 7 )

(func (export "global_set_a") (param i32) (global.set $a (local.get 0)) )
(func (export "global_set_b") (param i64) (global.set $b (local.get 0)) )
(func (export "global_set_c") (param f32) (global.set $c (local.get 0)) )
(func (export "global_set_d") (param f64) (global.set $d (local.get 0)) )

(global $r externref (ref.null extern))
(global $mr externref (ref.null extern))
(global $fr funcref (ref.null func))

(func (export "global_r") (result externref) global.get $r )
(func (export "global_mr") (result externref) global.get $mr )
(func (export "global_fr") (result funcref) global.get $fr )

)

(assert_return (invoke "global_a" ) (i32.const 1))
(assert_return (invoke "global_b" ) (i64.const 2))
(assert_return (invoke "global_c" ) (f32.const 5.5))
(assert_return (invoke "global_d" ) (f64.const 6.6))
(assert_return (invoke "global_2" ) (i32.const 3))
(assert_return (invoke "global_3" ) (i64.const 4))
(assert_return (invoke "global_6" ) (f32.const 7.7))
(assert_return (invoke "global_7" ) (f64.const 8.8))
(assert_return (invoke "global_set_a" (i32.const 11)))
(assert_return (invoke "global_a" ) (i32.const 11))
(assert_return (invoke "global_set_b" (i64.const 22)))
(assert_return (invoke "global_b" ) (i64.const 22))
(assert_return (invoke "global_set_c" (f32.const 55.5)))
(assert_return (invoke "global_c" ) (f32.const 55.5))
(assert_return (invoke "global_set_d" (f64.const 66.6)))
(assert_return (invoke "global_d" ) (f64.const 66.6))

(assert_return (invoke "global_r") (ref.null extern))
(assert_return (invoke "global_mr") (ref.null extern))
(assert_return (invoke "global_fr") ( ref.null func))

0 comments on commit 140fb34

Please sign in to comment.