Compare commits

...

4 commits

Author SHA1 Message Date
Ronald Caesar
18fa5dd65a
jit/ir: Add IR types
Signed-off-by: Ronald Caesar <github43132@proton.me>
2025-10-26 14:05:45 -04:00
Ronald Caesar
ac950250a8
jit: Remove global decoder variable
The decoder is created in main.cpp so having a global decoder is
useless.

Signed-off-by: Ronald Caesar <github43132@proton.me>
2025-10-26 14:01:59 -04:00
Ronald Caesar
1c3b730899
jit: Add Barr C code standard
Signed-off-by: Ronald Caesar <github43132@proton.me>
2025-10-26 13:59:48 -04:00
Ronald Caesar
a543f78b77
jit: made private functions static
This comforms to Rule 6.2 of Barr C code standard.

Signed-off-by: Ronald Caesar <github43132@proton.me>
2025-10-26 06:07:29 -04:00
6 changed files with 1654 additions and 129 deletions

173
.clang-format Executable file → Normal file
View file

@ -1,83 +1,140 @@
# Google C/C++ Code Style settings
# https://clang.llvm.org/docs/ClangFormatStyleOptions.html
# Author: Kehan Xue, kehan.xue (at) gmail.com
Language: Cpp
BasedOnStyle: Google
AccessModifierOffset: -1
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: None
AlignOperands: Align
AlignConsecutiveMacros: true
AlignConsecutiveAssignments: true
AlignConsecutiveDeclarations: true
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllConstructorInitializersOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: Empty
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: Inline
AllowShortIfStatementsOnASingleLine: Never # To avoid conflict, set this "Never" and each "if statement" should include brace when coding
AllowShortLambdasOnASingleLine: Inline
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: None
AlwaysBreakAfterDefinitionReturnType: TopLevel
AlwaysBreakAfterReturnType: TopLevelDefinitions
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
BreakBeforeBraces: Allman
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterCaseLabel: false
AfterClass: false
AfterStruct: false
AfterControlStatement: Never
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterUnion: false
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
BeforeLambdaBody: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: false
BreakBeforeBinaryOperators: None
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: true
AfterEnum: true
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: All
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeComma
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakInheritanceList: BeforeColon
ColumnLimit: 120
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeComma
BreakAfterJavaFieldAnnotations: true
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false # Make sure the * or & align on the left
EmptyLineBeforeAccessModifier: LogicalBlock
FixNamespaceComments: true
IncludeBlocks: Preserve
Cpp11BracedListStyle: false
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: false
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
- Regex: '.*'
Priority: 1
SortPriority: 0
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentCaseLabels: true
IndentGotoLabels: true
IndentPPDirectives: None
IndentWidth: 4
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertBraces: true
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PointerAlignment: Left
ReflowComments: false
# SeparateDefinitionBlocks: Always # Only support since clang-format 14
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: false
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceAfterTemplateKeyword: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCpp11BracedList: true
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParens: Custom
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterFunctionDefinitionName: true
SpaceBeforeRangeBasedForLoopColon: true
SpaceBeforeSquareBrackets: false
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInCStyleCastParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInConditionalStatement: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: c++11
TabWidth: 4
UseTab: Never
SpaceBeforeSquareBrackets: false
Standard: Latest
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 8
UseCRLF: false
UseTab: Never
...

1428
BARC-style-guide.pdf Executable file

File diff suppressed because one or more lines are too long

View file

@ -2,6 +2,7 @@ add_library(jit STATIC)
target_sources(jit PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/decoder/arm32.cpp
${CMAKE_CURRENT_SOURCE_DIR}/ir/type.cpp
)
target_link_libraries(jit PRIVATE common host)

View file

@ -1,65 +1,73 @@
#include "arm32.h"
#include <string.h>
#include "common/passert.h"
#include <string.h>
#define LOG_MODULE "jit"
#include "common/logging.h"
namespace pound::jit::decoder
{
namespace pound::jit::decoder {
#define INSTRUCTION_ARRAY_CAPACITY 261
#define HASH_TABLE_INVALID_INDEX 0xFFFF
#define INSTRUCTION_BITSTRING_LENGTH 32
/*
* ============================================================================
* Foward Declarations
* ============================================================================
*/
void arm32_add_instruction(arm32_decoder_t* decoder, const char* name, const char* bitstring);
void arm32_parse_bitstring(const char* bitstring, uint32_t* mask, uint32_t* expected);
void arm32_grow_instructions_array(arm32_decoder_t* decoder, size_t new_capacity);
static void arm32_add_instruction(arm32_decoder_t *p_decoder,
const char *p_name,
const char *p_bitstring);
static void arm32_parse_bitstring(const char *p_bitstring,
uint32_t *p_mask,
uint32_t *p_expected);
/*
* ============================================================================
* Public Functions
* ============================================================================
*/
void arm32_init(pound::host::memory::arena_t allocator, arm32_decoder_t* decoder)
void
arm32_init (pound::host::memory::arena_t allocator, arm32_decoder_t *p_decoder)
{
PVM_ASSERT(nullptr != decoder);
PVM_ASSERT(nullptr != p_decoder);
PVM_ASSERT(nullptr != allocator.data);
(void)memset(decoder, 0, sizeof(arm32_decoder_t));
decoder->allocator = allocator;
(void)memset(p_decoder, 0, sizeof(arm32_decoder_t));
p_decoder->allocator = allocator;
/* Setup Instructions array.*/
size_t instructions_array_size = INSTRUCTION_ARRAY_CAPACITY * sizeof(arm32_instruction_info_t);
PVM_ASSERT(instructions_array_size <= decoder->allocator.capacity);
LOG_TRACE("Allocated %d bytes to instructions array", instructions_array_size);
size_t instructions_array_size
= INSTRUCTION_ARRAY_CAPACITY * sizeof(arm32_instruction_info_t);
PVM_ASSERT(instructions_array_size <= p_decoder->allocator.capacity);
LOG_TRACE("Allocated %d bytes to instructions array",
instructions_array_size);
void* new_ptr = pound::host::memory::arena_allocate(&decoder->allocator, instructions_array_size);
PVM_ASSERT(nullptr != new_ptr);
void *p_memory = pound::host::memory::arena_allocate(
&p_decoder->allocator, instructions_array_size);
PVM_ASSERT(nullptr != p_memory);
decoder->instructions = (arm32_instruction_info_t*)new_ptr;
decoder->instruction_capacity = INSTRUCTION_ARRAY_CAPACITY;
p_decoder->p_instructions = (arm32_instruction_info_t *)p_memory;
p_decoder->instruction_capacity = INSTRUCTION_ARRAY_CAPACITY;
/* Add all Arm32 instructions */
#define INST(fn, name, bitstring) arm32_add_instruction(decoder, name, bitstring);
#define INST(fn, name, bitstring) \
arm32_add_instruction(p_decoder, name, bitstring);
#include "./arm32.inc"
#undef INST
}
arm32_instruction_info_t* arm32_decode(arm32_decoder_t* decoder, uint32_t instruction)
arm32_instruction_info_t *
arm32_decode (arm32_decoder_t *p_decoder, uint32_t instruction)
{
for (size_t i = 0; i < decoder->instruction_count; ++i)
for (size_t i = 0; i < p_decoder->instruction_count; ++i)
{
arm32_instruction_info_t* info = &decoder->instructions[i];
if ((instruction & info->mask) == info->expected)
arm32_instruction_info_t *p_info = &p_decoder->p_instructions[i];
if ((instruction & p_info->mask) == p_info->expected)
{
LOG_TRACE("Instruction found for 0x%08X: %s", instruction, info->name);
return info;
LOG_TRACE("Instruction found for 0x%08X: %s",
instruction,
p_info->p_name);
return p_info;
}
}
PVM_ASSERT_MSG(false, "No instruction found for 0x%08X", instruction);
@ -71,55 +79,64 @@ arm32_instruction_info_t* arm32_decode(arm32_decoder_t* decoder, uint32_t instru
* ============================================================================
*/
void arm32_add_instruction(arm32_decoder_t* decoder, const char* name, const char* bitstring)
static void
arm32_add_instruction (arm32_decoder_t *p_decoder,
const char *p_name,
const char *p_bitstring)
{
PVM_ASSERT(nullptr != decoder);
PVM_ASSERT(nullptr != decoder->allocator.data);
PVM_ASSERT(nullptr != name);
PVM_ASSERT(nullptr != bitstring);
PVM_ASSERT(decoder->instruction_count < decoder->instruction_capacity);
PVM_ASSERT(nullptr != p_decoder);
PVM_ASSERT(nullptr != p_decoder->allocator.data);
PVM_ASSERT(nullptr != p_name);
PVM_ASSERT(nullptr != p_bitstring);
PVM_ASSERT(p_decoder->instruction_count < p_decoder->instruction_capacity);
uint32_t mask = 0;
uint32_t mask = 0;
uint32_t expected = 0;
arm32_parse_bitstring(bitstring, &mask, &expected);
arm32_parse_bitstring(p_bitstring, &mask, &expected);
arm32_instruction_info_t* info = &decoder->instructions[decoder->instruction_count];
PVM_ASSERT(nullptr != info);
info->name = name;
info->mask = mask;
info->expected = expected;
arm32_instruction_info_t *p_info
= &p_decoder->p_instructions[p_decoder->instruction_count];
PVM_ASSERT(nullptr != p_info);
p_info->p_name = p_name;
p_info->mask = mask;
p_info->expected = expected;
++decoder->instruction_count;
++p_decoder->instruction_count;
LOG_TRACE("Instruction Registered: %s", info->name);
LOG_TRACE("Mask: 0x%08X", info->mask);
LOG_TRACE("Expected: 0x%08X", info->expected);
LOG_TRACE("Instruction Registered: %s", p_info->p_name);
LOG_TRACE("Mask: 0x%08X", p_info->mask);
LOG_TRACE("Expected: 0x%08X", p_info->expected);
}
void arm32_parse_bitstring(const char* bitstring, uint32_t* mask, uint32_t* expected)
static void
arm32_parse_bitstring (const char *p_bitstring,
uint32_t *p_mask,
uint32_t *p_expected)
{
PVM_ASSERT(nullptr != bitstring);
PVM_ASSERT(nullptr != mask);
PVM_ASSERT(nullptr != expected);
PVM_ASSERT(32 == strlen(bitstring));
PVM_ASSERT(nullptr != p_bitstring);
PVM_ASSERT(nullptr != p_mask);
PVM_ASSERT(nullptr != p_expected);
PVM_ASSERT(INSTRUCTION_BITSTRING_LENGTH == strlen(p_bitstring));
*mask = 0;
*expected = 0;
*p_mask = 0;
*p_expected = 0;
uint8_t instruction_size_bits = 32;
for (unsigned int i = 0; (i < instruction_size_bits) && (bitstring[i] != '\0'); ++i)
for (unsigned int i = 0;
(i < instruction_size_bits) && (p_bitstring[i] != '\0');
++i)
{
uint32_t bit_position = 31 - i;
switch (bitstring[i])
switch (p_bitstring[i])
{
case '0':
*mask |= (1U << bit_position);
*p_mask |= (1U << bit_position);
break;
case '1':
*mask |= (1U << bit_position);
*expected |= (1U << bit_position);
*p_mask |= (1U << bit_position);
*p_expected |= (1U << bit_position);
default:
break;
}
}
}
} // namespace pound::jit::decoder
} // namespace pound::jit::p_decoder

View file

@ -5,29 +5,27 @@
#include <stdint.h>
#include "host/memory/arena.h"
namespace pound::jit::decoder
{
namespace pound::jit::decoder {
typedef struct arm32_decoder arm32_decoder_t;
typedef void (*arm32_handler_fn)(arm32_decoder_t* decoder, uint32_t instruction);
typedef struct
{
const char* name;
uint32_t mask;
uint32_t expected;
const char *p_name;
uint32_t mask;
uint32_t expected;
} arm32_instruction_info_t;
struct arm32_decoder
{
pound::host::memory::arena_t allocator;
arm32_instruction_info_t* instructions;
size_t instruction_count;
size_t instruction_capacity;
arm32_instruction_info_t *p_instructions;
size_t instruction_count;
size_t instruction_capacity;
};
extern arm32_decoder_t g_arm32_decoder;
void arm32_init(pound::host::memory::arena_t allocator, arm32_decoder_t* decoder);
arm32_instruction_info_t* arm32_decode(arm32_decoder_t* decoder, uint32_t instruction);
void arm32_init(pound::host::memory::arena_t allocator,
arm32_decoder_t *p_decoder);
arm32_instruction_info_t *arm32_decode(arm32_decoder_t *p_decoder,
uint32_t instruction);
}
#endif // POUND_JIT_DECODER_ARM32_H
#endif // POUND_JIT_DECODER_ARM32_H

24
src/jit/ir/type.cpp Normal file
View file

@ -0,0 +1,24 @@
namespace pound::jit::decoder
{
typedef enum {
IR_TYPE_VOID = 0,
IR_TYPE_U1 = 1 << 0,
IR_TYPE_U8 = 1 << 1,
IR_TYPE_U16 = 1 << 2,
IR_TYPE_U32 = 1 << 3,
IR_TYPE_U64 = 1 << 4,
IR_TYPE_U128 = 1 << 5,
IR_TYPE_A32_REG = 1 << 6, // ARM32 GPR R0-R14
IR_TYPE_A32_EXT_REG = 1 << 7, // ARM32 Extended Registers (e.g., for VFP/NEON, or just R15 if treated specially)
IR_TYPE_A32_CPSR = 1 << 8, // ARM32 CPSR/SPSR
IR_TYPE_COND = 1 << 9, // Condition codes
IR_TYPE_ACC_TYPE = 1 << 10, // Memory access type
IR_TYPE_OPAQUE = 1 << 11, // Represents a value defined by another IR instruction
} ir_type_t;
bool ir_are_types_compatible(ir_type_t t1, ir_type_t t2)
{
const bool is_compatible = (t1 == t2) || (IR_TYPE_OPAQUE == t1) || (IR_TYPE_OPAQUE == t2);
return is_compatible;
}
}