Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HelloWorld example implementation #199

Closed
CWKSC opened this issue Oct 3, 2022 · 4 comments
Closed

HelloWorld example implementation #199

CWKSC opened this issue Oct 3, 2022 · 4 comments

Comments

@CWKSC
Copy link

CWKSC commented Oct 3, 2022

I am an LLVM beginner and trying to transform LLVM C++ API to LLVMSharp in my project (suffering from C++ and CMake)

So I am implementing a HelloWorld example with LLVMSharp for learning, but there are some things wrong

I create a console program with .NET 7 by Visual Studio 2022 Preview

I install LLVMSharp and libLLVM by NuGet, and add <RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == ''">$(NETCoreSdkRuntimeIdentifier)</RuntimeIdentifier> into csproj to solve DllNotFoundException (#157 (comment))

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net7.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <RuntimeIdentifier Condition="'$(RuntimeIdentifier)' == ''">$(NETCoreSdkRuntimeIdentifier)</RuntimeIdentifier>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="libLLVM" Version="15.0.0" />
    <PackageReference Include="LLVMSharp" Version="5.0.0" />
  </ItemGroup>

</Project>

With abstruct some utilities function like CreateExtern, DeclarePuts, CreateFunction, CreateMain ...

I create the following program:

using LLVMSharp;

LLVMValueRef CreateExtern(
    LLVMModuleRef module,
    string name,
    LLVMTypeRef returnType,
    LLVMTypeRef[] parameters,
    bool isVarArg = false
)
{
    var functionType = LLVM.FunctionType(returnType, parameters, isVarArg);
    return LLVM.AddFunction(module, name, functionType);
}

LLVMValueRef DeclarePuts(LLVMModuleRef module)
{
    LLVMTypeRef returnType = LLVM.Int32Type();
    LLVMTypeRef[] parameters = { LLVM.PointerType(LLVM.Int8Type(), 0) };
    return CreateExtern(module, "puts", returnType, parameters);
}

(LLVMValueRef, LLVMBuilderRef) CreateFunction(
    LLVMModuleRef module,
    string name,
    LLVMTypeRef returnType,
    LLVMTypeRef[] parameters,
    bool isVarArgs = false
)
{
    var funcType = LLVM.FunctionType(returnType, parameters, isVarArgs);
    var func = LLVM.AddFunction(module, name, funcType);
    var entry = LLVM.AppendBasicBlock(func, "entry");
    var builder = LLVM.CreateBuilder();
    LLVM.PositionBuilderAtEnd(builder, entry);

    return (func, builder);
}

(LLVMValueRef, LLVMBuilderRef) CreateMain(LLVMModuleRef module)
{
    return CreateFunction(module, "main", LLVM.Int32Type(), Array.Empty<LLVMTypeRef>());
}

void RunMain(LLVMModuleRef module)
{
    LLVM.LinkInMCJIT();
    LLVM.InitializeX86TargetMC();
    LLVM.InitializeX86Target();
    LLVM.InitializeX86TargetInfo();
    LLVM.InitializeX86AsmParser();
    LLVM.InitializeX86AsmPrinter();

    LLVM.CreateExecutionEngineForModule(out var engine, module, out var _);
    var main = LLVM.GetNamedFunction(module, "main");
    LLVM.RunFunction(engine, main, Array.Empty<LLVMGenericValueRef>());
}


var context = LLVM.ContextCreate();
var module = LLVM.ModuleCreateWithNameInContext("Hello World", context);

var funcPuts = DeclarePuts(module);
var (_, builder_main) = CreateMain(module);

var constInt0 = LLVM.ConstInt(LLVM.Int32Type(), 0, true);
var constStr = LLVM.BuildGlobalStringPtr(builder_main, "Hello World!", "");
var parameters = new LLVMValueRef[] { constStr };
LLVM.BuildCall(builder_main, funcPuts, parameters, "");
LLVM.BuildRet(builder_main, constInt0);

LLVM.DumpModule(module);

RunMain(module);

Program crashes in LLVM.BuildCall(builder_main, funcPuts, parameters, "");, and the console output:

Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Repeat 2 times:
--------------------------------
   at LLVMSharp.LLVM.BuildCall(LLVMSharp.LLVMBuilderRef, LLVMSharp.LLVMValueRef, LLVMSharp.LLVMValueRef ByRef, UInt32, System.String)
--------------------------------
   at LLVMSharp.LLVM.BuildCall(LLVMSharp.LLVMBuilderRef, LLVMSharp.LLVMValueRef, LLVMSharp.LLVMValueRef[], System.String)
   at LearnLLVMSharp.Program.Main(System.String[])

By LLVM.DumpModule(module);, the halfway result before the crash is as follows:

; ModuleID = 'Hello World'
source_filename = "Hello World"

@0 = private unnamed_addr constant [13 x i8] c"Hello World!\00", align 1

declare i32 @puts(ptr %0)

define i32 @main() {
entry:
}
@CWKSC
Copy link
Author

CWKSC commented Oct 3, 2022

If I remove libLLVM and only install LLVMSharp, the error disappear

@CWKSC CWKSC closed this as completed Oct 3, 2022
@CWKSC
Copy link
Author

CWKSC commented Oct 4, 2022

I fix with removing libLLVM 15.0.0 and only installing LLVMSharp.

The program looks like using libLLVM 5.0.0, It is not normal, so I reopen it.

I guess the problem is related to the creation of a const global string.

@CWKSC CWKSC reopened this Oct 4, 2022
@CWKSC
Copy link
Author

CWKSC commented Oct 4, 2022

I downgrade until libLLVM 14.0.0 and its work

By check out LLVM 15.0.0 ReleaseNotes

Find that LLVM 15.0.0 has some changes of C API, but I don't see anything affecting this, BuildGlobalStringPtr should be still working

@tannergooding
Copy link
Member

LLVM 15 made some changes in how BuildCall and friends work. They are "obsolete" now and you should be using BuildCall2 instead. This requires you to pass in the function type explicitly.

I plan on trying to improve this experience more in the future, but it will require a custom C extension library libLLVMSharp, much as was provided for ClangSharp. Such a library would "fill the gaps" in the official libLLVM C bindings exposed by LLVM.

@CWKSC CWKSC closed this as completed Feb 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants