[cfe-dev] clang-interpreter on windows

Shane Blackett via cfe-dev cfe-dev at lists.llvm.org
Wed Jul 31 15:10:09 PDT 2019


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 at _0O@OAOIOGJB at arg?$FL?$CFd?$FN?$DN?8?$CFs?8?6?$AA@" = comdat any

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

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

@"??_C at _0O@OAOIOGJB at 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 at _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 at 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 at _0O@OAOIOGJB at 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 at _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 at 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.*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20190801/c618fc4e/attachment.html>


More information about the cfe-dev mailing list