xref: /freebsd-src/contrib/llvm-project/llvm/lib/ExecutionEngine/Interpreter/Interpreter.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
10b57cec5SDimitry Andric //===- Interpreter.cpp - Top-Level LLVM Interpreter Implementation --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the top-level functionality for the LLVM interpreter.
100b57cec5SDimitry Andric // This interpreter is designed to be a very simple, portable, inefficient
110b57cec5SDimitry Andric // interpreter.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "Interpreter.h"
160b57cec5SDimitry Andric #include "llvm/CodeGen/IntrinsicLowering.h"
170b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
180b57cec5SDimitry Andric #include "llvm/IR/Module.h"
190b57cec5SDimitry Andric #include <cstring>
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace {
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric static struct RegisterInterp {
RegisterInterp__anon2a38c8320111::RegisterInterp250b57cec5SDimitry Andric   RegisterInterp() { Interpreter::Register(); }
260b57cec5SDimitry Andric } InterpRegistrator;
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric }
290b57cec5SDimitry Andric 
LLVMLinkInInterpreter()300b57cec5SDimitry Andric extern "C" void LLVMLinkInInterpreter() { }
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric /// Create a new interpreter object.
330b57cec5SDimitry Andric ///
create(std::unique_ptr<Module> M,std::string * ErrStr)340b57cec5SDimitry Andric ExecutionEngine *Interpreter::create(std::unique_ptr<Module> M,
350b57cec5SDimitry Andric                                      std::string *ErrStr) {
360b57cec5SDimitry Andric   // Tell this Module to materialize everything and release the GVMaterializer.
370b57cec5SDimitry Andric   if (Error Err = M->materializeAll()) {
380b57cec5SDimitry Andric     std::string Msg;
390b57cec5SDimitry Andric     handleAllErrors(std::move(Err), [&](ErrorInfoBase &EIB) {
400b57cec5SDimitry Andric       Msg = EIB.message();
410b57cec5SDimitry Andric     });
420b57cec5SDimitry Andric     if (ErrStr)
430b57cec5SDimitry Andric       *ErrStr = Msg;
440b57cec5SDimitry Andric     // We got an error, just return 0
450b57cec5SDimitry Andric     return nullptr;
460b57cec5SDimitry Andric   }
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric   return new Interpreter(std::move(M));
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
520b57cec5SDimitry Andric // Interpreter ctor - Initialize stuff
530b57cec5SDimitry Andric //
Interpreter(std::unique_ptr<Module> M)540b57cec5SDimitry Andric Interpreter::Interpreter(std::unique_ptr<Module> M)
550b57cec5SDimitry Andric     : ExecutionEngine(std::move(M)) {
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   memset(&ExitValue.Untyped, 0, sizeof(ExitValue.Untyped));
580b57cec5SDimitry Andric   // Initialize the "backend"
590b57cec5SDimitry Andric   initializeExecutionEngine();
600b57cec5SDimitry Andric   initializeExternalFunctions();
610b57cec5SDimitry Andric   emitGlobals();
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric   IL = new IntrinsicLowering(getDataLayout());
640b57cec5SDimitry Andric }
650b57cec5SDimitry Andric 
~Interpreter()660b57cec5SDimitry Andric Interpreter::~Interpreter() {
670b57cec5SDimitry Andric   delete IL;
680b57cec5SDimitry Andric }
690b57cec5SDimitry Andric 
runAtExitHandlers()700b57cec5SDimitry Andric void Interpreter::runAtExitHandlers () {
710b57cec5SDimitry Andric   while (!AtExitHandlers.empty()) {
72*bdd1243dSDimitry Andric     callFunction(AtExitHandlers.back(), std::nullopt);
730b57cec5SDimitry Andric     AtExitHandlers.pop_back();
740b57cec5SDimitry Andric     run();
750b57cec5SDimitry Andric   }
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric /// run - Start execution with the specified function and arguments.
790b57cec5SDimitry Andric ///
runFunction(Function * F,ArrayRef<GenericValue> ArgValues)800b57cec5SDimitry Andric GenericValue Interpreter::runFunction(Function *F,
810b57cec5SDimitry Andric                                       ArrayRef<GenericValue> ArgValues) {
820b57cec5SDimitry Andric   assert (F && "Function *F was null at entry to run()");
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   // Try extra hard not to pass extra args to a function that isn't
850b57cec5SDimitry Andric   // expecting them.  C programmers frequently bend the rules and
860b57cec5SDimitry Andric   // declare main() with fewer parameters than it actually gets
870b57cec5SDimitry Andric   // passed, and the interpreter barfs if you pass a function more
880b57cec5SDimitry Andric   // parameters than it is declared to take. This does not attempt to
890b57cec5SDimitry Andric   // take into account gratuitous differences in declared types,
900b57cec5SDimitry Andric   // though.
910b57cec5SDimitry Andric   const size_t ArgCount = F->getFunctionType()->getNumParams();
920b57cec5SDimitry Andric   ArrayRef<GenericValue> ActualArgs =
930b57cec5SDimitry Andric       ArgValues.slice(0, std::min(ArgValues.size(), ArgCount));
940b57cec5SDimitry Andric 
950b57cec5SDimitry Andric   // Set up the function call.
960b57cec5SDimitry Andric   callFunction(F, ActualArgs);
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric   // Start executing the function.
990b57cec5SDimitry Andric   run();
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric   return ExitValue;
1020b57cec5SDimitry Andric }
103