[cfe-dev] Calling Extern Function

o.j.sivart at gmail.com o.j.sivart at gmail.com
Wed Aug 18 07:56:01 PDT 2010


What does nm on your application binary give in terms of the name yipee?
You are not by any chance stripping symbols from your binary?

Possibly you need the equivalent of gcc's -rdynamic flag for your compiler.

On 19/08/2010, at 12:14 AM, Paul Griffiths wrote:

> Yes, it is c++;
> ave also tried it with
> 
> extern "C"
> int yipee(int aVar)
> {
>    return 5;
> }
> 
> but still no luck.
> 
> 
> 
> heres my full listing, im stuck.
> 
> 
> 
> 
> 
> 
> // Whistle.cpp : Defines the entry point for the console application.
> //
> 
> #include "stdafx.h"
> #include "clang/CodeGen/CodeGenAction.h"
> #include "clang/Driver/Compilation.h"
> #include "clang/Driver/Driver.h"
> #include "clang/Driver/Tool.h"
> #include "clang/Frontend/CompilerInvocation.h"
> #include "clang/Frontend/CompilerInstance.h"
> #include "clang/Frontend/DiagnosticOptions.h"
> #include "clang/Frontend/FrontendDiagnostic.h"
> #include "clang/Frontend/TextDiagnosticPrinter.h"
> #include "llvm/DerivedTypes.h"
> #include "llvm/Support/TypeBuilder.h"
> #include "llvm/LLVMContext.h"
> #include "llvm/Module.h"
> #include "llvm/Config/config.h"
> #include "llvm/ADT/OwningPtr.h"
> #include "llvm/ADT/SmallString.h"
> #include "llvm/Config/config.h"
> #include "llvm/ExecutionEngine/ExecutionEngine.h"
> #include "llvm/Support/ManagedStatic.h"
> #include "llvm/Support/raw_ostream.h"
> #include "llvm/System/Host.h"
> #include "llvm/System/Path.h"
> #include "llvm/Target/TargetSelect.h"
> using namespace clang;
> using namespace clang::driver;
> 
> extern "C"
> int yipee(int val)
> {
> 	fprintf(stderr, "yipee!");
> 
> 	return 1;
> }
> 
> 
> llvm::sys::Path GetExecutablePath(const char *Argv0) {
> 	// This just needs to be some symbol in the binary; C++ doesn't
> 	// allow taking the address of ::main however.
> 	void *MainAddr = (void*) (intptr_t) GetExecutablePath;
> 	return llvm::sys::Path::GetMainExecutable(Argv0, MainAddr);
> }
> 
> int Execute(llvm::Module *Mod, char * const *envp) {
> 	llvm::InitializeNativeTarget();
> 
> 	std::string Error;
> 	llvm::OwningPtr<llvm::ExecutionEngine> EE(
> 		llvm::ExecutionEngine::createJIT(Mod, &Error));
> 	if (!EE) {
> 		llvm::errs() << "unable to make execution engine: " << Error << "\n";
> 		return 255;
> 	}
> 
> 	// code I have added
> ---------------------------------------------------------------------------------------------
> 	llvm::FunctionType* ft =
> llvm::FunctionType::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()),
> 		std::vector<const llvm::Type*>(1,
> llvm::Type::getInt32Ty(llvm::getGlobalContext())), false);
> 
> 	llvm::Function* F = llvm::Function::Create(ft,
> llvm::Function::ExternalLinkage, "yipee", Mod);
> 	EE->addGlobalMapping(F, (void*)(intptr_t)yipee);
> 	llvm::Function *YipeeFn = Mod->getFunction("yipee");
> 	if (!YipeeFn) {
> 		llvm::errs() << "'yipee' function not found in module.\n";
> 		return 255;
> 	}
> 	// end code I have added
> ---------------------------------------------------------------------------------------------
> 
> 	llvm::Function *EntryFn = Mod->getFunction("main");
> 	if (!EntryFn) {
> 		llvm::errs() << "'main' function not found in module.\n";
> 		return 255;
> 	}
> 
> 	// FIXME: Support passing arguments.
> 	std::vector<std::string> Args;
> 	Args.push_back(Mod->getModuleIdentifier());
> 
> 	return EE->runFunctionAsMain(EntryFn, Args, envp);
> }
> 
> int main(int argc, const char **argv, char * const *envp) {
>  void *MainAddr = (void*) (intptr_t) GetExecutablePath;
>  llvm::sys::Path Path = GetExecutablePath(argv[0]);
>  TextDiagnosticPrinter DiagClient(llvm::errs(), DiagnosticOptions());
> 
>  Diagnostic Diags(&DiagClient);
>  Driver TheDriver(Path.str(), llvm::sys::getHostTriple(),
>                   "a.out", /*IsProduction=*/false, /*CXXIsProduction=*/false,
>                   Diags);
>  TheDriver.setTitle("clang interpreter");
> 
>  // FIXME: This is a hack to try to force the driver to do something we can
>  // recognize. We need to extend the driver library to support this use model
>  // (basically, exactly one input, and the operation mode is hard wired).
>  llvm::SmallVector<const char *, 16> Args(argv, argv + argc);
>  Args.push_back("-fsyntax-only");
>  llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(Args.size(),
>                                                            Args.data()));
>  if (!C)
>    return 0;
> 
>  // FIXME: This is copied from ASTUnit.cpp; simplify and eliminate.
> 
>  // We expect to get back exactly one command job, if we didn't something
>  // failed. Extract that job from the compilation.
>  const driver::JobList &Jobs = C->getJobs();
>  if (Jobs.size() != 1 || !isa<driver::Command>(Jobs.begin())) {
>    llvm::SmallString<256> Msg;
>    llvm::raw_svector_ostream OS(Msg);
>    C->PrintJob(OS, C->getJobs(), "; ", true);
>    Diags.Report(diag::err_fe_expected_compiler_job) << OS.str();
>    return 1;
>  }
> 
>  const driver::Command *Cmd = cast<driver::Command>(*Jobs.begin());
>  if (llvm::StringRef(Cmd->getCreator().getName()) != "clang") {
>    Diags.Report(diag::err_fe_expected_clang_command);
>    return 1;
>  }
> 
>  // Initialize a compiler invocation object from the clang (-cc1) arguments.
>  const driver::ArgStringList &CCArgs = Cmd->getArguments();
>  llvm::OwningPtr<CompilerInvocation> CI(new CompilerInvocation);
>  CompilerInvocation::CreateFromArgs(*CI,
>                                     const_cast<const char **>(CCArgs.data()),
>                                     const_cast<const char **>(CCArgs.data()) +
>                                       CCArgs.size(),
>                                     Diags);
> 
>  // Show the invocation, with -v.
>  if (CI->getHeaderSearchOpts().Verbose) {
>    llvm::errs() << "clang invocation:\n";
>    C->PrintJob(llvm::errs(), C->getJobs(), "\n", true);
>    llvm::errs() << "\n";
>  }
> 
>  // FIXME: This is copied from cc1_main.cpp; simplify and eliminate.
> 
>  // Create a compiler instance to handle the actual work.
>  CompilerInstance Clang;
>  Clang.setLLVMContext(new llvm::LLVMContext);
>  Clang.setInvocation(CI.take());
> 
>  // Create the compilers actual diagnostics engine.
>  Clang.createDiagnostics(int(CCArgs.size()),const_cast<char**>(CCArgs.data()));
>  if (!Clang.hasDiagnostics())
>    return 1;
> 
>  // Infer the builtin include path if unspecified.
>  if (Clang.getHeaderSearchOpts().UseBuiltinIncludes &&
>      Clang.getHeaderSearchOpts().ResourceDir.empty())
>    Clang.getHeaderSearchOpts().ResourceDir =
>      CompilerInvocation::GetResourcesPath(argv[0], MainAddr);
> 
>  // Create and execute the frontend to generate an LLVM bitcode module.
>  llvm::OwningPtr<CodeGenAction> Act(new EmitLLVMOnlyAction());
>  if (!Clang.ExecuteAction(*Act))
>    return 1;
> 
>  int Res = 255;
>  if (llvm::Module *Module = Act->takeModule())
>  {
> 
> 
>    Res = Execute(Module, envp);
>  }
> 
>  // Shutdown.
> 
>  llvm::llvm_shutdown();
> 
>  return Res;
> }
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> 
> On 18 August 2010 14:36,  <o.j.sivart at gmail.com> wrote:
>> I assume you are compiling your program as c++. In this case your problem is that "yipee" will have been name mangled by the c++ compiler.
>> 
>> On 18/08/2010, at 9:08 PM, Paul Griffiths wrote:
>> 
>>> Can someone please tell me what I am doing wrong?
>>> 
>>> Im trying to register an external function with the JIT, so can call
>>> functions in my music application(heres an image :
>>> http://img534.imageshack.us/img534/3995/87647073.jpg).
>>> 
>>> Here my functions
>>> 
>>> int yipee(int aVar)
>>> {
>>>    return 5;
>>> }
>>> 
>>> int Execute(llvm::Module *Mod, char * const *envp) {
>>>       llvm::InitializeNativeTarget();
>>> 
>>>       std::string Error;
>>>       llvm::OwningPtr<llvm::ExecutionEngine> EE(
>>>               llvm::ExecutionEngine::createJIT(Mod, &Error));
>>>       if (!EE) {
>>>               llvm::errs() << "unable to make execution engine: " << Error << "\n";
>>>               return 255;
>>>       }
>>> 
>>>       // code I have added
>>> ---------------------------------------------------------------------------------------------
>>>       llvm::FunctionType* ft =
>>> llvm::FunctionType::get(llvm::Type::getInt32Ty(llvm::getGlobalContext()),
>>>               std::vector<const llvm::Type*>(0,
>>> llvm::Type::getInt32Ty(llvm::getGlobalContext())), false);
>>> 
>>>       llvm::Function* f = llvm::Function::Create(ft,
>>> llvm::Function::ExternalLinkage, "yipee", Mod);
>>>       EE->addGlobalMapping(f, yipee);
>>>       llvm::Function *YipeeFn = Mod->getFunction("yipee");
>>>       if (!YipeeFn) {
>>>               llvm::errs() << "'yipee' function not found in module.\n";
>>>               return 255;
>>>       }
>>>       // end code I have added
>>> ---------------------------------------------------------------------------------------------
>>> 
>>>       llvm::Function *EntryFn = Mod->getFunction("main");
>>>       if (!EntryFn) {
>>>               llvm::errs() << "'main' function not found in module.\n";
>>>               return 255;
>>>       }
>>> 
>>>       // FIXME: Support passing arguments.
>>>       std::vector<std::string> Args;
>>>       Args.push_back(Mod->getModuleIdentifier());
>>> 
>>>       return EE->runFunctionAsMain(EntryFn, Args, envp);
>>> }
>>> 
>>> 
>>> 
>>> // here the C code to be ran with JIT
>>> -------------------------------------------------------------------
>>> 
>>> int main() {
>>>       int dd = yipee(1);
>>>  return 1;
>>> }
>>> _______________________________________________
>>> cfe-dev mailing list
>>> cfe-dev at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>> 
>> 
> 
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev





More information about the cfe-dev mailing list