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

LLVM converts integer types to floats #194

Open
AnErrupTion opened this issue Aug 9, 2022 · 3 comments
Open

LLVM converts integer types to floats #194

AnErrupTion opened this issue Aug 9, 2022 · 3 comments

Comments

@AnErrupTion
Copy link

AnErrupTion commented Aug 9, 2022

Hey!

I'm making a compiler which will use LLVM as its backend. But while I was doing some tests, I saw that LLVM, for some reason, was transforming any integer types (i8, i16, i32 or i64) to floats (more precisely, ppc_fp128). But some other types like double work and are not converted to floats (since doubles can hold decimals already).

What I don't understand is that I'm not using any decimal values, and it is still converting them into floats, which actually breaks my code.

Here is a sample demo which does this behavior:

unsafe
{
    LLVMModuleRef module = LLVM.ModuleCreateWithName((sbyte*)0);
    LLVMBuilderRef builder = LLVM.CreateBuilder();

    const string targetStr = "x86_64-unknown-none";

    LLVM.InitializeX86TargetInfo();
    LLVM.InitializeX86Target();
    LLVM.InitializeX86TargetMC();
    LLVM.InitializeX86AsmParser();
    LLVM.InitializeX86AsmPrinter();

    module.Target = targetStr;

    var target = LLVMTargetRef.GetTargetFromTriple(targetStr);
    var machine = target.CreateTargetMachine(targetStr, "generic", "", LLVMCodeGenOptLevel.LLVMCodeGenLevelNone,
        LLVMRelocMode.LLVMRelocStatic, LLVMCodeModel.LLVMCodeModelKernel);

    LLVM.SetModuleDataLayout(module, machine.CreateTargetDataLayout());

    var function = module.AddFunction("main", LLVM.FunctionType(LLVM.VoidType(), null, 0, 0));
    var stack = new Stack<LLVMValueRef>();

    LLVM.SetLinkage(function, LLVMLinkage.LLVMExternalLinkage);
    builder.PositionAtEnd(function.AppendBasicBlock("entry"));

    // Simulating what the stack would look like before Add
    stack.Push(LLVM.ConstReal(LLVM.Int32Type(), 8));
    stack.Push(LLVM.ConstReal(LLVM.Int32Type(), 4));

    var value2 = stack.Pop();
    var value1 = stack.Pop();

    stack.Push(builder.BuildAdd(value1, value2));

    fixed (LLVMOpaqueType** ptr = new[] { LLVM.Int32Type() })
    {
        var tmp = module.AddFunction("tmp", LLVM.FunctionType(LLVM.VoidType(), ptr, 1, 0));
        LLVM.SetLinkage(tmp, LLVMLinkage.LLVMExternalLinkage);
        builder.BuildCall(tmp, new[] { stack.Pop() /* This should be the result of the previous Add instruction */ });
    }

    builder.BuildRetVoid();

    LLVM.DumpModule(module);
}

Here is the LLVM IR output:

target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-none"

define void @main() {
entry:
  call void @tmp(ppc_fp128 add (ppc_fp128 0xM40200000000000000000000000000000, ppc_fp128 0xM40100000000000000000000000000000))
  ret void
}

declare void @tmp(i32 %0)

I'm not quite sure if this is a bug, or if I'm using LLVM(Sharp) wrong here. Any help would be greatly appreciated!

@tannergooding
Copy link
Member

Could you clarify which version of LLVMSharp you're using?

For reference, this is incorrect usage and likely and I'm actually surprised its producing IR at all:

LLVMSharp is ultimately fairly simple bindings over LLVM. As such, it is very lowlevel and only really has the safety that libLLVM has built into itself, but should in general work exactly like it does in C.

I'd like to eventually build a higher level safe wrapper on top (much like I did for ClangSharp) and there is some semblance on the start of that with things like: https://github.com/dotnet/LLVMSharp/blob/main/sources/LLVMSharp/LLVMContext.cs, but its not nearly there or close to complete yet.

@AnErrupTion
Copy link
Author

Could you clarify which version of LLVMSharp you're using?

I'm using LLVMSharp 14.0.0-beta1 from NuGet.

For reference, this is incorrect usage and likely and I'm actually surprised its producing IR at all:

I'm fairly new to LLVM in general, so I just guessed how to use it. And documentation doesn't really help in my case, as I'm not actually making an AST or anything, I'm transforming the bytecode to LLVM IR.

So I guess it's not how you create constant values. So yeah, it doesn't generate any error or anything. For reference (which may or may not help), here is what I get when running llc --version, I get this on the first line:

Ubuntu LLVM version 14.0.0

@tannergooding
Copy link
Member

Thanks! That all lines up then. I'm unsure why its not erroring, as it really should be.

I'll leave this issue open to track adding some diagnostics on the LLVMSharp side to help catch some of these issues. The raw LLVM.RealConst wouldn't expose them, but I can expose it via LLVMValueRef.CreateConstReal which is a "safer" (but still lowlevel) wrapper over the raw bindings.

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