clang-interpreter on windows

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

clang-interpreter on windows

Nathan Ridge via cfe-dev
Hi,

We have been using a JIT clang modelled after clang-interpreter from version 5.0.0.
It has been working on linux, osx and windows (x86 and x64).

Recently I attempted to upgrade llvm and clang to 7 and then 8, currently trying
llvm and cfe 8.0.1.
There are significant changes in using the newer JIT system and I see that there is another iteration coming in the trunk.

The clang-interpreter example works on mac but on windows I can't get it to work.
I have built x86 /MD, x64 /MD and an x86 /MT version, all with Visual Studio 2017, Version 15.8.8.

Initially for me the debug version asserts with the following message and the release version crashes as it fails to resolve the pointer to main.

Assertion failed: Target.isCompatibleDataLayout(getDataLayout()) && "Can't create a MachineFunction using a Module with a " "Target-incompatible DataLayout attached\n", file d:\bl\llvm\llvm-8.0.1.src\lib\codegen\machinefunction.cpp, line 200

I inferred that the JIT container and the compiled module are incompatible.  I think this is because the code explicitly changes the detected Triple from COFF to ELF.
 // Use ELF on Windows-32 and MingW for now.
#ifndef CLANG_INTERPRETER_COFF_FORMAT
  if (T.isOSBinFormatCOFF())
    T.setObjectFormat(llvm::Triple::ELF);
#endif

I wondered if maybe this is no longer necessary so tried commenting it out, which resolved the error assertion but now the debug version also just silently fails to find the symbol.

This is the output from dumping the module, the input C++ I have simplified from the provided example Test.cxx by removing the exception throw and hard coded a printf("hello\n");

=================================================================
; ModuleID = 'D:\llvm\llvm-8.0.1.src\tools\clang\examples\clang-interpreter\Test.cxx'
source_filename = "D:\5Cllvm\5Cllvm-8.0.1.src\5Ctools\5Cclang\5Cexamples\5Cclang-interpreter\5CTest.cxx"
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i686-pc-windows-msvc19.15.26732"

%struct._iobuf = type { i8* }
%struct.__crt_locale_pointers = type { %struct.__crt_locale_data*, %struct.__crt_multibyte_data* }
%struct.__crt_locale_data = type opaque
%struct.__crt_multibyte_data = type opaque

$printf = comdat any

$_vfprintf_l = comdat any

$__local_stdio_printf_options = comdat any

$"??_C@_0O@OAOIOGJB@arg?$FL?$CFd?$FN?$DN?8?$CFs?8?6?$AA@" = comdat any

$"??_C@_06BGKFAKIK@hello?6?$AA@" = comdat any

$"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = comdat any

@"??_C@_0O@OAOIOGJB@arg?$FL?$CFd?$FN?$DN?8?$CFs?8?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [14 x i8] c"arg[%d]='%s'\0A\00", comdat, align 1
@"??_C@_06BGKFAKIK@hello?6?$AA@" = linkonce_odr dso_local unnamed_addr constant [7 x i8] c"hello\0A\00", comdat, align 1
@"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA" = linkonce_odr dso_local global i64 0, comdat, align 8

; Function Attrs: noinline norecurse optnone
define dso_local i32 @main(i32 %argc, i8** %argv) #0 {
entry:
  %retval = alloca i32, align 4
  %argv.addr = alloca i8**, align 4
  %argc.addr = alloca i32, align 4
  %I = alloca i32, align 4
  store i32 0, i32* %retval, align 4
  store i8** %argv, i8*** %argv.addr, align 4
  store i32 %argc, i32* %argc.addr, align 4
  store i32 0, i32* %I, align 4
  br label %for.cond

for.cond:                                         ; preds = %for.inc, %entry
  %0 = load i32, i32* %I, align 4
  %1 = load i32, i32* %argc.addr, align 4
  %cmp = icmp slt i32 %0, %1
  br i1 %cmp, label %for.body, label %for.end

for.body:                                         ; preds = %for.cond
  %2 = load i8**, i8*** %argv.addr, align 4
  %3 = load i32, i32* %I, align 4
  %arrayidx = getelementptr inbounds i8*, i8** %2, i32 %3
  %4 = load i8*, i8** %arrayidx, align 4
  %5 = load i32, i32* %I, align 4
  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([14 x i8], [14 x i8]* @"??_C@_0O@OAOIOGJB@arg?$FL?$CFd?$FN?$DN?8?$CFs?8?6?$AA@", i32 0, i32 0), i32 %5, i8* %4)
  br label %for.inc

for.inc:                                          ; preds = %for.body
  %6 = load i32, i32* %I, align 4
  %inc = add nsw i32 %6, 1
  store i32 %inc, i32* %I, align 4
  br label %for.cond

for.end:                                          ; preds = %for.cond
  %call1 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @"??_C@_06BGKFAKIK@hello?6?$AA@", i32 0, i32 0))
  ret i32 0
}

; Function Attrs: noinline optnone
define linkonce_odr dso_local i32 @printf(i8* %_Format, ...) #1 comdat {
entry:
  %_Format.addr = alloca i8*, align 4
  %_Result = alloca i32, align 4
  %_ArgList = alloca i8*, align 4
  store i8* %_Format, i8** %_Format.addr, align 4
  %_ArgList1 = bitcast i8** %_ArgList to i8*
  call void @llvm.va_start(i8* %_ArgList1)
  %0 = load i8*, i8** %_ArgList, align 4
  %1 = load i8*, i8** %_Format.addr, align 4
  %call = call %struct._iobuf* @__acrt_iob_func(i32 1)
  %call2 = call i32 @_vfprintf_l(%struct._iobuf* %call, i8* %1, %struct.__crt_locale_pointers* null, i8* %0)
  store i32 %call2, i32* %_Result, align 4
  %_ArgList3 = bitcast i8** %_ArgList to i8*
  call void @llvm.va_end(i8* %_ArgList3)
  %2 = load i32, i32* %_Result, align 4
  ret i32 %2
}

; Function Attrs: nounwind
declare void @llvm.va_start(i8*) #2

; Function Attrs: noinline optnone
define linkonce_odr dso_local i32 @_vfprintf_l(%struct._iobuf* %_Stream, i8* %_Format, %struct.__crt_locale_pointers* %_Locale, i8* %_ArgList) #1 comdat {
entry:
  %_ArgList.addr = alloca i8*, align 4
  %_Locale.addr = alloca %struct.__crt_locale_pointers*, align 4
  %_Format.addr = alloca i8*, align 4
  %_Stream.addr = alloca %struct._iobuf*, align 4
  store i8* %_ArgList, i8** %_ArgList.addr, align 4
  store %struct.__crt_locale_pointers* %_Locale, %struct.__crt_locale_pointers** %_Locale.addr, align 4
  store i8* %_Format, i8** %_Format.addr, align 4
  store %struct._iobuf* %_Stream, %struct._iobuf** %_Stream.addr, align 4
  %0 = load i8*, i8** %_ArgList.addr, align 4
  %1 = load %struct.__crt_locale_pointers*, %struct.__crt_locale_pointers** %_Locale.addr, align 4
  %2 = load i8*, i8** %_Format.addr, align 4
  %3 = load %struct._iobuf*, %struct._iobuf** %_Stream.addr, align 4
  %call = call i64* @__local_stdio_printf_options()
  %4 = load i64, i64* %call, align 8
  %call1 = call i32 @__stdio_common_vfprintf(i64 %4, %struct._iobuf* %3, i8* %2, %struct.__crt_locale_pointers* %1, i8* %0)
  ret i32 %call1
}

declare dso_local %struct._iobuf* @__acrt_iob_func(i32) #3

; Function Attrs: nounwind
declare void @llvm.va_end(i8*) #2

declare dso_local i32 @__stdio_common_vfprintf(i64, %struct._iobuf*, i8*, %struct.__crt_locale_pointers*, i8*) #3

; Function Attrs: noinline nounwind optnone
define linkonce_odr dso_local i64* @__local_stdio_printf_options() #4 comdat {
entry:
  ret i64* @"?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA"
}

attributes #0 = { noinline norecurse optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #1 = { noinline optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #2 = { nounwind }
attributes #3 = { "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
attributes #4 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="pentium4" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

!llvm.linker.options = !{!0, !1, !2, !3, !4}
!llvm.module.flags = !{!5, !6}
!llvm.ident = !{!7}

!0 = !{!"/FAILIFMISMATCH:\22_MSC_VER=1900\22"}
!1 = !{!"/FAILIFMISMATCH:\22_ITERATOR_DEBUG_LEVEL=0\22"}
!2 = !{!"/FAILIFMISMATCH:\22RuntimeLibrary=MT_StaticRelease\22"}
!3 = !{!"/DEFAULTLIB:libcpmt.lib"}
!4 = !{!"/FAILIFMISMATCH:\22_CRT_STDIO_ISO_WIDE_SPECIFIERS=0\22"}
!5 = !{i32 1, !"NumRegisterParameters", i32 0}
!6 = !{i32 1, !"wchar_size", i32 2}
!7 = !{!"clang version 8.0.1 (tags/RELEASE_801/final)"}
======================================================

I then considered that the change to the triple may be necessary so I think I figured out how to modify the JIT container code to have a matching container by modifying the constructor for the TargetMachine.
Replacing TM(EngineBuilder().selectTarget()),
with
TM(EngineBuilder().selectTarget(GetTarget(), "", "", MAttrs)),
where GetTarget just reproduces the Triple code that was in the example....
  static llvm::Triple GetTarget() {
    const std::string TripleStr = llvm::sys::getProcessTriple();
    llvm::Triple T(TripleStr);

    // Use ELF on Windows-32 and MingW for now.
#ifndef CLANG_INTERPRETER_COFF_FORMAT
    if (T.isOSBinFormatCOFF())
      T.setObjectFormat(llvm::Triple::ELF);
#endif

    return T;
  }

This version of the code also resolves the debug assertion that I had initially but it fails to link with
LLVM ERROR: invalid llvm.linker.options

I'm not sure what else to try or how to diagnose the problem further.

Thanks in advance for any help that may be provided.

Thanks,
Shane Blackett



"This communication is confidential and may contain privileged and/or copyright material. If you are not the intended recipient you must not use, disclose, copy or retain it. If you have received it in error please immediately notify me by return email, delete the emails and destroy any hard copies. Soul Machines Limited does not guarantee the integrity of this communication, or that it is free from errors, viruses or interference."

Please consider the environment before printing this email.


_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev