[llvm] [llubi] Add initial support for llubi (PR #180022)
Antonio Frighetto via llvm-commits
llvm-commits at lists.llvm.org
Fri Feb 6 07:10:04 PST 2026
================
@@ -0,0 +1,202 @@
+//===- Interpreter.cpp - Interpreter Loop for llubi -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the evaluation loop for each kind of instruction.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Context.h"
+#include "Value.h"
+#include "llvm/IR/InstVisitor.h"
+#include "llvm/Support/Allocator.h"
+
+namespace llvm::ubi {
+
+enum class FrameState {
+ // It is about to enter the function.
+ // Valid transition:
+ // -> Running
+ Entry,
+ // It is executing instructions inside the function.
+ // Valid transitions:
+ // -> Pending (on call)
+ // -> Exit (on return)
+ Running,
+ // It is about to enter a callee or handle return value from the callee.
+ // Valid transitions:
+ // -> Running (after returning from callee)
+ Pending,
+ // It is about to return the control to the caller.
+ Exit,
+};
+
+/// Context for a function call.
+/// This struct maintains the state during the execution of a function,
+/// including the control flow, values of executed instructions, and stack
+/// objects.
+struct Frame {
+ Function &Func;
+ Frame *LastFrame;
+ CallBase *CallSite;
+ ArrayRef<AnyValue> Args;
+ AnyValue &RetVal;
+
+ TargetLibraryInfo TLI;
+ BasicBlock *BB;
+ BasicBlock::iterator PC;
+ FrameState State = FrameState::Entry;
+ // Stack objects allocated in this frame. They will be automatically freed
+ // when the function returns.
+ SmallVector<IntrusiveRefCntPtr<MemoryObject>> Allocas;
+ // Values of arguments and executed instructions in this function.
+ DenseMap<Value *, AnyValue> ValueMap;
+
+ // Reserved for in-flight subroutines.
+ SmallVector<AnyValue> CalleeArgs;
+ AnyValue CalleeRetVal;
+
+ Frame(Function &F, CallBase *CallSite, Frame *LastFrame,
+ ArrayRef<AnyValue> Args, AnyValue &RetVal,
+ const TargetLibraryInfoImpl &TLIImpl)
+ : Func(F), LastFrame(LastFrame), CallSite(CallSite), Args(Args),
+ RetVal(RetVal), TLI(TLIImpl, &F) {
+ assert((Args.size() == F.arg_size() ||
+ (F.isVarArg() && Args.size() >= F.arg_size())) &&
+ "Expected enough arguments to call the function.");
+ BB = &Func.getEntryBlock();
+ PC = BB->begin();
+ for (Argument &Arg : F.args())
+ ValueMap[&Arg] = Args[Arg.getArgNo()];
+ }
+};
+
+/// Instruction executor using the visitor pattern.
+/// visit* methods return true on success, false on error.
+/// Unlike the Context class that manages the global state,
+/// InstExecutor only maintains the state for call frames.
+class InstExecutor : public InstVisitor<InstExecutor, bool> {
+ Context &Ctx;
+ EventHandler &Handler;
+ std::list<Frame> CallStack;
----------------
antoniofrighetto wrote:
Just wondering, any particular choice why std::list was favoured for walking the stack (and not, e.g., a std::deque)?
https://github.com/llvm/llvm-project/pull/180022
More information about the llvm-commits
mailing list