Skip to content

Commit 3f9649a

Browse files
0xrinegadeclaude
andcommitted
feat: Major updates across OVSM compiler, BBS federation, and research tooling
OVSM Compiler: - Enhanced IR generator with improved macro handling - Updated verifier with better diagnostics - Reorganized AEA protocol into aea/ directory with new modules: - aea_agent_brain.ovsm: Agent cognitive architecture - aea_economics_tests.ovsm: Economic simulation tests - aea_game_theory.ovsm: Game-theoretic decision models - aea_governance.ovsm: Decentralized governance primitives - aea_negotiation.ovsm: Multi-party negotiation protocols BBS System: - Added voting system with db/votes.rs backend - Enhanced HTTP server with WebSocket support - Improved federation with peer sync and gossip - Extended models for richer post metadata Research Command: - Major enhancements to research tooling - Improved MCP pool integration - Better CLI argument parsing All changes compile successfully with cargo check. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 76e3496 commit 3f9649a

File tree

22 files changed

+7284
-88
lines changed

22 files changed

+7284
-88
lines changed

crates/ovsm/src/compiler/ir/generator.rs

Lines changed: 44 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1472,31 +1472,49 @@ impl IrGenerator {
14721472
}
14731473

14741474
// Handle (mem-store base offset value) - direct memory store
1475+
// Supports both constant and dynamic offsets
14751476
if name == "mem-store" && args.len() == 3 {
14761477
let base_reg = self.generate_expr(&args[0].value)?
14771478
.ok_or_else(|| Error::runtime("mem-store base has no result"))?;
1478-
let offset = match &args[1].value {
1479-
Expression::IntLiteral(n) => *n,
1480-
_ => return Err(Error::runtime("mem-store offset must be constant")),
1481-
};
14821479
let value_reg = self.generate_expr(&args[2].value)?
14831480
.ok_or_else(|| Error::runtime("mem-store value has no result"))?;
1484-
self.emit(IrInstruction::Store(base_reg, value_reg, offset));
1481+
1482+
// Try constant offset first (most common case)
1483+
if let Expression::IntLiteral(offset) = &args[1].value {
1484+
self.emit(IrInstruction::Store(base_reg, value_reg, *offset));
1485+
} else {
1486+
// Dynamic offset: compute effective address = base + offset
1487+
let offset_reg = self.generate_expr(&args[1].value)?
1488+
.ok_or_else(|| Error::runtime("mem-store offset has no result"))?;
1489+
let addr_reg = self.alloc_reg();
1490+
self.emit(IrInstruction::Add(addr_reg, base_reg, offset_reg));
1491+
// Store at computed address with 0 offset
1492+
self.emit(IrInstruction::Store(addr_reg, value_reg, 0));
1493+
}
14851494
return Ok(None); // Store has no result
14861495
}
14871496

14881497
// Handle (mem-store1 base offset value) - store 1 byte to memory
14891498
// Stores the low byte of value at ptr+offset
1499+
// Supports both constant and dynamic offsets
14901500
if name == "mem-store1" && args.len() == 3 {
14911501
let base_reg = self.generate_expr(&args[0].value)?
14921502
.ok_or_else(|| Error::runtime("mem-store1 base has no result"))?;
1493-
let offset = match &args[1].value {
1494-
Expression::IntLiteral(n) => *n,
1495-
_ => return Err(Error::runtime("mem-store1 offset must be constant")),
1496-
};
14971503
let value_reg = self.generate_expr(&args[2].value)?
14981504
.ok_or_else(|| Error::runtime("mem-store1 value has no result"))?;
1499-
self.emit(IrInstruction::Store1(base_reg, value_reg, offset));
1505+
1506+
// Try constant offset first (most common case)
1507+
if let Expression::IntLiteral(offset) = &args[1].value {
1508+
self.emit(IrInstruction::Store1(base_reg, value_reg, *offset));
1509+
} else {
1510+
// Dynamic offset: compute effective address = base + offset
1511+
let offset_reg = self.generate_expr(&args[1].value)?
1512+
.ok_or_else(|| Error::runtime("mem-store1 offset has no result"))?;
1513+
let addr_reg = self.alloc_reg();
1514+
self.emit(IrInstruction::Add(addr_reg, base_reg, offset_reg));
1515+
// Store at computed address with 0 offset
1516+
self.emit(IrInstruction::Store1(addr_reg, value_reg, 0));
1517+
}
15001518
return Ok(None); // Store has no result
15011519
}
15021520

@@ -5751,18 +5769,26 @@ impl IrGenerator {
57515769
self.emit(IrInstruction::JumpIf(cond_reg, then_label.clone()));
57525770
self.emit(IrInstruction::Jump(else_label.clone()));
57535771

5754-
// Then
5772+
// Then - if branch returns None, use 0 (null) as default value
57555773
self.emit(IrInstruction::Label(then_label));
5756-
let then_reg = self.generate_expr(then_expr)?
5757-
.ok_or_else(|| Error::runtime("Ternary then has no result"))?;
5758-
self.emit(IrInstruction::Move(result_reg, then_reg));
5774+
let then_result = self.generate_expr(then_expr)?;
5775+
if let Some(then_reg) = then_result {
5776+
self.emit(IrInstruction::Move(result_reg, then_reg));
5777+
} else {
5778+
// Side-effect only branch - use null (0) as value
5779+
self.emit(IrInstruction::ConstNull(result_reg));
5780+
}
57595781
self.emit(IrInstruction::Jump(end_label.clone()));
57605782

5761-
// Else
5783+
// Else - if branch returns None, use 0 (null) as default value
57625784
self.emit(IrInstruction::Label(else_label));
5763-
let else_reg = self.generate_expr(else_expr)?
5764-
.ok_or_else(|| Error::runtime("Ternary else has no result"))?;
5765-
self.emit(IrInstruction::Move(result_reg, else_reg));
5785+
let else_result = self.generate_expr(else_expr)?;
5786+
if let Some(else_reg) = else_result {
5787+
self.emit(IrInstruction::Move(result_reg, else_reg));
5788+
} else {
5789+
// Side-effect only branch - use null (0) as value
5790+
self.emit(IrInstruction::ConstNull(result_reg));
5791+
}
57665792

57675793
// End
57685794
self.emit(IrInstruction::Label(end_label));

crates/ovsm/src/compiler/verifier.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@ impl Verifier {
161161
let mut has_exit = false;
162162
let mut offset = 0;
163163

164+
// Build slot-to-instruction mapping for proper jump validation
165+
// LDDW instructions take 2 slots, all others take 1 slot
166+
let mut slot_positions: Vec<usize> = Vec::with_capacity(program.len());
167+
let mut current_slot: usize = 0;
168+
for instr in program.iter() {
169+
slot_positions.push(current_slot);
170+
current_slot += instr.size() / 8; // LDDW = 2, others = 1
171+
}
172+
let total_slots = current_slot;
173+
164174
for (idx, instr) in program.iter().enumerate() {
165175
// Check for exit instruction
166176
if instr.opcode == 0x95 {
@@ -181,13 +191,16 @@ impl Verifier {
181191
});
182192
}
183193

184-
// Check jump targets
194+
// Check jump targets using slot-based coordinates
195+
// sBPF jump semantics: PC = current_slot + 1 + offset
196+
// LDDW advances PC by 2, others by 1
185197
if self.is_jump_opcode(instr.opcode) && instr.opcode != 0x95 {
186-
let target = idx as i64 + 1 + instr.offset as i64;
187-
if target < 0 || target as usize >= program.len() {
198+
let current_slot_pos = slot_positions[idx];
199+
let target_slot = current_slot_pos as i64 + 1 + instr.offset as i64;
200+
if target_slot < 0 || target_slot as usize > total_slots {
188201
errors.push(VerifyError::JumpOutOfBounds {
189202
offset,
190-
target,
203+
target: target_slot,
191204
});
192205
}
193206
}

0 commit comments

Comments
 (0)