MCJIT.cpp revision c0ceedb6f885b1cbd3d3cea02f695afe393dfd2c
1bb498ca5c2acb7567d8d4d84b00229bed6f501b1Eric Christopher//===-- MCJIT.cpp - MC-based Just-in-Time Compiler ------------------------===//
26aec29848676494867e26307698155bc2c5a4033Daniel Dunbar//
36aec29848676494867e26307698155bc2c5a4033Daniel Dunbar//                     The LLVM Compiler Infrastructure
46aec29848676494867e26307698155bc2c5a4033Daniel Dunbar//
56aec29848676494867e26307698155bc2c5a4033Daniel Dunbar// This file is distributed under the University of Illinois Open Source
66aec29848676494867e26307698155bc2c5a4033Daniel Dunbar// License. See LICENSE.TXT for details.
76aec29848676494867e26307698155bc2c5a4033Daniel Dunbar//
86aec29848676494867e26307698155bc2c5a4033Daniel Dunbar//===----------------------------------------------------------------------===//
96aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
106aec29848676494867e26307698155bc2c5a4033Daniel Dunbar#include "MCJIT.h"
11fcbe5b71936b820647dffff0e4f9c60ece3988a5Jim Grosbach#include "MCJITMemoryManager.h"
1234714a06096f854c76371295d8c20b017fbba50bJim Grosbach#include "llvm/DerivedTypes.h"
1331649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach#include "llvm/Function.h"
146aec29848676494867e26307698155bc2c5a4033Daniel Dunbar#include "llvm/ExecutionEngine/GenericValue.h"
156aec29848676494867e26307698155bc2c5a4033Daniel Dunbar#include "llvm/ExecutionEngine/MCJIT.h"
16f922910494377909b4cf2a0b73f509b2b1925799Jim Grosbach#include "llvm/ExecutionEngine/JITMemoryManager.h"
17f922910494377909b4cf2a0b73f509b2b1925799Jim Grosbach#include "llvm/MC/MCAsmInfo.h"
186aec29848676494867e26307698155bc2c5a4033Daniel Dunbar#include "llvm/Support/ErrorHandling.h"
191f6efa3996dd1929fbc129203ce5009b620e6969Michael J. Spencer#include "llvm/Support/DynamicLibrary.h"
20f922910494377909b4cf2a0b73f509b2b1925799Jim Grosbach#include "llvm/Support/MemoryBuffer.h"
2131649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach#include "llvm/Target/TargetData.h"
226aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
236aec29848676494867e26307698155bc2c5a4033Daniel Dunbarusing namespace llvm;
246aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
256aec29848676494867e26307698155bc2c5a4033Daniel Dunbarnamespace {
266aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
276aec29848676494867e26307698155bc2c5a4033Daniel Dunbarstatic struct RegisterJIT {
286aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  RegisterJIT() { MCJIT::Register(); }
296aec29848676494867e26307698155bc2c5a4033Daniel Dunbar} JITRegistrator;
306aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
316aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
326aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
336aec29848676494867e26307698155bc2c5a4033Daniel Dunbarextern "C" void LLVMLinkInMCJIT() {
346aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
356aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
366aec29848676494867e26307698155bc2c5a4033Daniel DunbarExecutionEngine *MCJIT::createJIT(Module *M,
376aec29848676494867e26307698155bc2c5a4033Daniel Dunbar                                  std::string *ErrorStr,
386aec29848676494867e26307698155bc2c5a4033Daniel Dunbar                                  JITMemoryManager *JMM,
396aec29848676494867e26307698155bc2c5a4033Daniel Dunbar                                  CodeGenOpt::Level OptLevel,
406aec29848676494867e26307698155bc2c5a4033Daniel Dunbar                                  bool GVsWithCode,
41c5b28580a94e247300e5d3ccf532e153f2ae6f12Dylan Noblesmith                                  TargetMachine *TM) {
426aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  // Try to register the program as a source of symbols to resolve against.
436aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  //
446aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  // FIXME: Don't do this here.
456aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  sys::DynamicLibrary::LoadLibraryPermanently(0, NULL);
466aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
476aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  // If the target supports JIT code generation, create the JIT.
486aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  if (TargetJITInfo *TJ = TM->getJITInfo())
49c154514e2daf5497141980544f6b0b03a8e6c37cJim Grosbach    return new MCJIT(M, TM, *TJ, new MCJITMemoryManager(JMM, M), OptLevel,
50fcbe5b71936b820647dffff0e4f9c60ece3988a5Jim Grosbach                     GVsWithCode);
516aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
526aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  if (ErrorStr)
536aec29848676494867e26307698155bc2c5a4033Daniel Dunbar    *ErrorStr = "target does not support JIT code generation";
546aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  return 0;
556aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
566aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
5731649e61bcead26a63c7cd452da90fff5e000b91Jim GrosbachMCJIT::MCJIT(Module *m, TargetMachine *tm, TargetJITInfo &tji,
58fcbe5b71936b820647dffff0e4f9c60ece3988a5Jim Grosbach             RTDyldMemoryManager *MM, CodeGenOpt::Level OptLevel,
596aec29848676494867e26307698155bc2c5a4033Daniel Dunbar             bool AllocateGVsWithCode)
60fcbe5b71936b820647dffff0e4f9c60ece3988a5Jim Grosbach  : ExecutionEngine(m), TM(tm), MemMgr(MM), M(m), OS(Buffer), Dyld(MM) {
6131649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach
6231649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  PM.add(new TargetData(*TM->getTargetData()));
6331649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach
6431649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  // Turn the machine code intermediate representation into bytes in memory
6531649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  // that may be executed.
6631649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  if (TM->addPassesToEmitMC(PM, Ctx, OS, CodeGenOpt::Default, false)) {
6731649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach    report_fatal_error("Target does not support MC emission!");
6831649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  }
6931649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach
7031649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  // Initialize passes.
7131649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  // FIXME: When we support multiple modules, we'll want to move the code
7231649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  // gen and finalization out of the constructor here and do it more
7331649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  // on-demand as part of getPointerToFunction().
7431649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  PM.run(*M);
7531649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  // Flush the output buffer so the SmallVector gets its data.
7631649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  OS.flush();
77f922910494377909b4cf2a0b73f509b2b1925799Jim Grosbach
78f922910494377909b4cf2a0b73f509b2b1925799Jim Grosbach  // Load the object into the dynamic linker.
79f922910494377909b4cf2a0b73f509b2b1925799Jim Grosbach  // FIXME: It would be nice to avoid making yet another copy.
80f922910494377909b4cf2a0b73f509b2b1925799Jim Grosbach  MemoryBuffer *MB = MemoryBuffer::getMemBufferCopy(StringRef(Buffer.data(),
81f922910494377909b4cf2a0b73f509b2b1925799Jim Grosbach                                                              Buffer.size()));
828086f3b49429e02603270c8e09e2aabac9215a21Jim Grosbach  if (Dyld.loadObject(MB))
838086f3b49429e02603270c8e09e2aabac9215a21Jim Grosbach    report_fatal_error(Dyld.getErrorString());
8469e813282d4aa078102ce058f8269d0c13260061Jim Grosbach  // Resolve any relocations.
8569e813282d4aa078102ce058f8269d0c13260061Jim Grosbach  Dyld.resolveRelocations();
866aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
876aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
886aec29848676494867e26307698155bc2c5a4033Daniel DunbarMCJIT::~MCJIT() {
89fcbe5b71936b820647dffff0e4f9c60ece3988a5Jim Grosbach  delete MemMgr;
906aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
916aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
926aec29848676494867e26307698155bc2c5a4033Daniel Dunbarvoid *MCJIT::getPointerToBasicBlock(BasicBlock *BB) {
936aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  report_fatal_error("not yet implemented");
946aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  return 0;
956aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
966aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
976aec29848676494867e26307698155bc2c5a4033Daniel Dunbarvoid *MCJIT::getPointerToFunction(Function *F) {
9834714a06096f854c76371295d8c20b017fbba50bJim Grosbach  if (F->isDeclaration() || F->hasAvailableExternallyLinkage()) {
9934714a06096f854c76371295d8c20b017fbba50bJim Grosbach    bool AbortOnFailure = !F->hasExternalWeakLinkage();
10034714a06096f854c76371295d8c20b017fbba50bJim Grosbach    void *Addr = getPointerToNamedFunction(F->getName(), AbortOnFailure);
10134714a06096f854c76371295d8c20b017fbba50bJim Grosbach    addGlobalMapping(F, Addr);
10234714a06096f854c76371295d8c20b017fbba50bJim Grosbach    return Addr;
10334714a06096f854c76371295d8c20b017fbba50bJim Grosbach  }
10434714a06096f854c76371295d8c20b017fbba50bJim Grosbach
1053ec2c7c3e48f1fbab749870c51a74920f91c82c1Jim Grosbach  // FIXME: Should we be using the mangler for this? Probably.
1063ec2c7c3e48f1fbab749870c51a74920f91c82c1Jim Grosbach  StringRef BaseName = F->getName();
1073ec2c7c3e48f1fbab749870c51a74920f91c82c1Jim Grosbach  if (BaseName[0] == '\1')
108c0ceedb6f885b1cbd3d3cea02f695afe393dfd2cJim Grosbach    return (void*)Dyld.getSymbolAddress(BaseName.substr(1));
109c0ceedb6f885b1cbd3d3cea02f695afe393dfd2cJim Grosbach  return (void*)Dyld.getSymbolAddress((TM->getMCAsmInfo()->getGlobalPrefix()
110c0ceedb6f885b1cbd3d3cea02f695afe393dfd2cJim Grosbach                                       + BaseName).str());
1116aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
1126aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
1136aec29848676494867e26307698155bc2c5a4033Daniel Dunbarvoid *MCJIT::recompileAndRelinkFunction(Function *F) {
1146aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  report_fatal_error("not yet implemented");
1156aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
1166aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
1176aec29848676494867e26307698155bc2c5a4033Daniel Dunbarvoid MCJIT::freeMachineCodeForFunction(Function *F) {
1186aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  report_fatal_error("not yet implemented");
1196aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
1206aec29848676494867e26307698155bc2c5a4033Daniel Dunbar
1216aec29848676494867e26307698155bc2c5a4033Daniel DunbarGenericValue MCJIT::runFunction(Function *F,
1226aec29848676494867e26307698155bc2c5a4033Daniel Dunbar                                const std::vector<GenericValue> &ArgValues) {
12334714a06096f854c76371295d8c20b017fbba50bJim Grosbach  assert(F && "Function *F was null at entry to run()");
12434714a06096f854c76371295d8c20b017fbba50bJim Grosbach
12531649e61bcead26a63c7cd452da90fff5e000b91Jim Grosbach  void *FPtr = getPointerToFunction(F);
12634714a06096f854c76371295d8c20b017fbba50bJim Grosbach  assert(FPtr && "Pointer to fn's code was null after getPointerToFunction");
12734714a06096f854c76371295d8c20b017fbba50bJim Grosbach  const FunctionType *FTy = F->getFunctionType();
12834714a06096f854c76371295d8c20b017fbba50bJim Grosbach  const Type *RetTy = FTy->getReturnType();
12934714a06096f854c76371295d8c20b017fbba50bJim Grosbach
13034714a06096f854c76371295d8c20b017fbba50bJim Grosbach  assert((FTy->getNumParams() == ArgValues.size() ||
13134714a06096f854c76371295d8c20b017fbba50bJim Grosbach          (FTy->isVarArg() && FTy->getNumParams() <= ArgValues.size())) &&
13234714a06096f854c76371295d8c20b017fbba50bJim Grosbach         "Wrong number of arguments passed into function!");
13334714a06096f854c76371295d8c20b017fbba50bJim Grosbach  assert(FTy->getNumParams() == ArgValues.size() &&
13434714a06096f854c76371295d8c20b017fbba50bJim Grosbach         "This doesn't support passing arguments through varargs (yet)!");
13534714a06096f854c76371295d8c20b017fbba50bJim Grosbach
13634714a06096f854c76371295d8c20b017fbba50bJim Grosbach  // Handle some common cases first.  These cases correspond to common `main'
13734714a06096f854c76371295d8c20b017fbba50bJim Grosbach  // prototypes.
13834714a06096f854c76371295d8c20b017fbba50bJim Grosbach  if (RetTy->isIntegerTy(32) || RetTy->isVoidTy()) {
13934714a06096f854c76371295d8c20b017fbba50bJim Grosbach    switch (ArgValues.size()) {
14034714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case 3:
14134714a06096f854c76371295d8c20b017fbba50bJim Grosbach      if (FTy->getParamType(0)->isIntegerTy(32) &&
14234714a06096f854c76371295d8c20b017fbba50bJim Grosbach          FTy->getParamType(1)->isPointerTy() &&
14334714a06096f854c76371295d8c20b017fbba50bJim Grosbach          FTy->getParamType(2)->isPointerTy()) {
14434714a06096f854c76371295d8c20b017fbba50bJim Grosbach        int (*PF)(int, char **, const char **) =
14534714a06096f854c76371295d8c20b017fbba50bJim Grosbach          (int(*)(int, char **, const char **))(intptr_t)FPtr;
14634714a06096f854c76371295d8c20b017fbba50bJim Grosbach
14734714a06096f854c76371295d8c20b017fbba50bJim Grosbach        // Call the function.
14834714a06096f854c76371295d8c20b017fbba50bJim Grosbach        GenericValue rv;
14934714a06096f854c76371295d8c20b017fbba50bJim Grosbach        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
15034714a06096f854c76371295d8c20b017fbba50bJim Grosbach                                 (char **)GVTOP(ArgValues[1]),
15134714a06096f854c76371295d8c20b017fbba50bJim Grosbach                                 (const char **)GVTOP(ArgValues[2])));
15234714a06096f854c76371295d8c20b017fbba50bJim Grosbach        return rv;
15334714a06096f854c76371295d8c20b017fbba50bJim Grosbach      }
15434714a06096f854c76371295d8c20b017fbba50bJim Grosbach      break;
15534714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case 2:
15634714a06096f854c76371295d8c20b017fbba50bJim Grosbach      if (FTy->getParamType(0)->isIntegerTy(32) &&
15734714a06096f854c76371295d8c20b017fbba50bJim Grosbach          FTy->getParamType(1)->isPointerTy()) {
15834714a06096f854c76371295d8c20b017fbba50bJim Grosbach        int (*PF)(int, char **) = (int(*)(int, char **))(intptr_t)FPtr;
15934714a06096f854c76371295d8c20b017fbba50bJim Grosbach
16034714a06096f854c76371295d8c20b017fbba50bJim Grosbach        // Call the function.
16134714a06096f854c76371295d8c20b017fbba50bJim Grosbach        GenericValue rv;
16234714a06096f854c76371295d8c20b017fbba50bJim Grosbach        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue(),
16334714a06096f854c76371295d8c20b017fbba50bJim Grosbach                                 (char **)GVTOP(ArgValues[1])));
16434714a06096f854c76371295d8c20b017fbba50bJim Grosbach        return rv;
16534714a06096f854c76371295d8c20b017fbba50bJim Grosbach      }
16634714a06096f854c76371295d8c20b017fbba50bJim Grosbach      break;
16734714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case 1:
16834714a06096f854c76371295d8c20b017fbba50bJim Grosbach      if (FTy->getNumParams() == 1 &&
16934714a06096f854c76371295d8c20b017fbba50bJim Grosbach          FTy->getParamType(0)->isIntegerTy(32)) {
17034714a06096f854c76371295d8c20b017fbba50bJim Grosbach        GenericValue rv;
17134714a06096f854c76371295d8c20b017fbba50bJim Grosbach        int (*PF)(int) = (int(*)(int))(intptr_t)FPtr;
17234714a06096f854c76371295d8c20b017fbba50bJim Grosbach        rv.IntVal = APInt(32, PF(ArgValues[0].IntVal.getZExtValue()));
17334714a06096f854c76371295d8c20b017fbba50bJim Grosbach        return rv;
17434714a06096f854c76371295d8c20b017fbba50bJim Grosbach      }
17534714a06096f854c76371295d8c20b017fbba50bJim Grosbach      break;
17634714a06096f854c76371295d8c20b017fbba50bJim Grosbach    }
17734714a06096f854c76371295d8c20b017fbba50bJim Grosbach  }
17834714a06096f854c76371295d8c20b017fbba50bJim Grosbach
17934714a06096f854c76371295d8c20b017fbba50bJim Grosbach  // Handle cases where no arguments are passed first.
18034714a06096f854c76371295d8c20b017fbba50bJim Grosbach  if (ArgValues.empty()) {
18134714a06096f854c76371295d8c20b017fbba50bJim Grosbach    GenericValue rv;
18234714a06096f854c76371295d8c20b017fbba50bJim Grosbach    switch (RetTy->getTypeID()) {
18334714a06096f854c76371295d8c20b017fbba50bJim Grosbach    default: llvm_unreachable("Unknown return type for function call!");
18434714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case Type::IntegerTyID: {
18534714a06096f854c76371295d8c20b017fbba50bJim Grosbach      unsigned BitWidth = cast<IntegerType>(RetTy)->getBitWidth();
18634714a06096f854c76371295d8c20b017fbba50bJim Grosbach      if (BitWidth == 1)
18734714a06096f854c76371295d8c20b017fbba50bJim Grosbach        rv.IntVal = APInt(BitWidth, ((bool(*)())(intptr_t)FPtr)());
18834714a06096f854c76371295d8c20b017fbba50bJim Grosbach      else if (BitWidth <= 8)
18934714a06096f854c76371295d8c20b017fbba50bJim Grosbach        rv.IntVal = APInt(BitWidth, ((char(*)())(intptr_t)FPtr)());
19034714a06096f854c76371295d8c20b017fbba50bJim Grosbach      else if (BitWidth <= 16)
19134714a06096f854c76371295d8c20b017fbba50bJim Grosbach        rv.IntVal = APInt(BitWidth, ((short(*)())(intptr_t)FPtr)());
19234714a06096f854c76371295d8c20b017fbba50bJim Grosbach      else if (BitWidth <= 32)
19334714a06096f854c76371295d8c20b017fbba50bJim Grosbach        rv.IntVal = APInt(BitWidth, ((int(*)())(intptr_t)FPtr)());
19434714a06096f854c76371295d8c20b017fbba50bJim Grosbach      else if (BitWidth <= 64)
19534714a06096f854c76371295d8c20b017fbba50bJim Grosbach        rv.IntVal = APInt(BitWidth, ((int64_t(*)())(intptr_t)FPtr)());
19634714a06096f854c76371295d8c20b017fbba50bJim Grosbach      else
19734714a06096f854c76371295d8c20b017fbba50bJim Grosbach        llvm_unreachable("Integer types > 64 bits not supported");
19834714a06096f854c76371295d8c20b017fbba50bJim Grosbach      return rv;
19934714a06096f854c76371295d8c20b017fbba50bJim Grosbach    }
20034714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case Type::VoidTyID:
20134714a06096f854c76371295d8c20b017fbba50bJim Grosbach      rv.IntVal = APInt(32, ((int(*)())(intptr_t)FPtr)());
20234714a06096f854c76371295d8c20b017fbba50bJim Grosbach      return rv;
20334714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case Type::FloatTyID:
20434714a06096f854c76371295d8c20b017fbba50bJim Grosbach      rv.FloatVal = ((float(*)())(intptr_t)FPtr)();
20534714a06096f854c76371295d8c20b017fbba50bJim Grosbach      return rv;
20634714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case Type::DoubleTyID:
20734714a06096f854c76371295d8c20b017fbba50bJim Grosbach      rv.DoubleVal = ((double(*)())(intptr_t)FPtr)();
20834714a06096f854c76371295d8c20b017fbba50bJim Grosbach      return rv;
20934714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case Type::X86_FP80TyID:
21034714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case Type::FP128TyID:
21134714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case Type::PPC_FP128TyID:
21234714a06096f854c76371295d8c20b017fbba50bJim Grosbach      llvm_unreachable("long double not supported yet");
21334714a06096f854c76371295d8c20b017fbba50bJim Grosbach      return rv;
21434714a06096f854c76371295d8c20b017fbba50bJim Grosbach    case Type::PointerTyID:
21534714a06096f854c76371295d8c20b017fbba50bJim Grosbach      return PTOGV(((void*(*)())(intptr_t)FPtr)());
21634714a06096f854c76371295d8c20b017fbba50bJim Grosbach    }
21734714a06096f854c76371295d8c20b017fbba50bJim Grosbach  }
21834714a06096f854c76371295d8c20b017fbba50bJim Grosbach
21934714a06096f854c76371295d8c20b017fbba50bJim Grosbach  assert("Full-featured argument passing not supported yet!");
2206aec29848676494867e26307698155bc2c5a4033Daniel Dunbar  return GenericValue();
2216aec29848676494867e26307698155bc2c5a4033Daniel Dunbar}
222