[llvm-dev] Kaleidoscope tutorial: comments, corrections and Windows support

Moritz Kroll via llvm-dev llvm-dev at lists.llvm.org
Tue Feb 7 14:56:01 PST 2017


Hi Mehdi,

well, some comments are actually questions, but I'll see what I can do.
For Chapter 5, I'm already changing the tutorial directly based on svn 
trunk.

Best regards
Moritz


On 07.02.2017 08:02, Mehdi Amini wrote:
>
>> On Feb 6, 2017, at 5:07 PM, Moritz Kroll via llvm-dev <llvm-dev at lists.llvm.org> wrote:
>>
>> Hi,
>>
>> I'm currently working my way through the tutorial with LLVM 3.9.1 on Windows (finished chapter 4) and stumbled over a few things which could be improved:
>
> Any chance you would submit a patch to fix all this?
>
> http://llvm.org/docs/DeveloperPolicy.html
> http://llvm.org/docs/Phabricator.html
>
> Thanks,
>
>> Mehdi
>
>
>>
>> - "LLVMContext" does not exist as a variable -> "TheContext"
>>   - Chapter 3: 5 times
>>   - Chapter 4: 1 time
>>   - Chapter 5: 4 times
>>   - Chapter 6: 2 times
>>   - Chapter 7: 2 times
>>
>> 3.4. Function Code Generation
>>
>> - Wouldn't it make sense to have a
>>   "Type *DoubleTy = Type::getDoubleTy(TheContext);"?
>> - "Function *TheFunction = TheModule->getFunction(Proto->getName());"
>>   The new getName method is unexpected, the tutorial user has to lookup
>>   and copy the definition from the full listing.
>>
>> 3.5. Driver Changes and Closing Thoughts
>>
>> - "When you quit the current demo"
>>   -> "When you quit the current demo (by sending an EOF
>>   via CTRL+D on Linux or CTRL+Z and ENTER on Windows)"
>>   (Windows users normally don't send EOF characters so they
>>   usually don't know this shortcut)
>>
>> 4.3. LLVM Optimization Passes
>>
>> - Code for InitializeModuleAndPassManager:
>>   - Remove "Context LLVMContext;"
>>   - "TheJIT" comes out of nowhere and thus is not defined in the code
>>     of the tutorial user. Setting the data layout could be added in
>>     4.4, as it is at least not required for showing the improved body
>>     of "test"
>>   - "createBasicAliasAnalysisPass" does not exist anymore (llvm-3.9.1).
>>     Also requires adaption of the text
>>
>> 4.4. Adding a JIT Compiler
>>
>> - Code for main:
>>   - "TheJIT = llvm::make_unique<KaleidoscopeJIT>();" will cause a crash
>>     due to an invalid read in "Datalayout::operator=" as
>>     "EngineBuilder().selectTarget()" returns a nullptr when
>>     "InitializeNativeTarget" has not been called yet.
>>     Other problems occur if the other InitializeNative* functions are
>>     not called. So you should add them here.
>>   - The (silently added) "TheModule->print" call from chapter 3
>>     is missing
>>
>> - "The KaleidoscopeJIT class is a simple JIT built specifically for
>>    these tutorials.":
>>   It would be nice to mention, where to find the include file:
>>   llvm-src/examples/Kaleidoscope/include/KaleidoscopeJIT.h
>>
>> - "auto ExprSymbol = TheJIT->findSymbol("__anon_expr");":
>>   On Windows, this will always fail as this function will search for
>>   "ExportedSymbolsOnly" and the exported flag seems to be implemented
>>   incorrectly for COFF in LLVM (see bug report from Russell Wallace:
>>   http://lists.llvm.org/pipermail/llvm-dev/2016-April/097964.html ).
>>   Applied to the current version of Kaleidoscope, he suggested to use
>>   "CompileLayer.findSymbolIn(H, Name, false)" in
>>   "KaleidoscopeJIT::findMangledSymbol" to also allow non-exported
>>   symbols.
>>   I fixed it by changing "COFFObjectFile::getSymbolFlags" in
>>   llvm-src/lib/Object/COFFObjectFile.cpp
>>   to additionally OR SymbolRef::SF_Exported to Result:
>>
>>> uint32_t COFFObjectFile::getSymbolFlags(DataRefImpl Ref) const {
>>>  COFFSymbolRef Symb = getCOFFSymbol(Ref);
>>>  uint32_t Result = SymbolRef::SF_None;
>>>
>>>  if (Symb.isExternal() || Symb.isWeakExternal())
>>>    Result |= SymbolRef::SF_Global | SymbolRef::SF_Exported;
>>
>>   Works and sounds reasonable to me, but maybe you can prove me wrong.
>>
>> - "ready> sin(1.0);": On Windows, this fails with "LLVM ERROR: Program
>>   used external function '_sin' which could not be resolved!" because
>>   "DynamicLibrary::SearchForAddressOfSymbol" iterates over all loaded
>>   libraries and uses GetProcAddress to try getting the address.
>>   But for the old "msvcrt.dll" as well as the newer "ucrtbased.dll",
>>   the math functions are exported without a leading underscore.
>>   Additionally, LLVM provides some "explicit" symbols which would
>>   otherwise only exist in form of a macro (see comment in
>>   llvm-src/lib/Support/Windows/DynamicLibrary.inc). These are also only
>>   available in unmangled form, for example "sinf".
>>   Thus I propose to add this code at the end of
>>   "KaleidoscopeJIT::findMangledSymbol":
>>
>>> #ifdef LLVM_ON_WIN32
>>>    // For Windows retry without "_" at begining, as RTDyldMemoryManager uses
>>>    // GetProcAddress and standard libraries like msvcrt.dll use names
>>>    // with and without "_" (for example "_itoa" but "sin").
>>>    if (Name.length() > 2 && Name[0] == '_')
>>>      if (auto SymAddr = RTDyldMemoryManager::getSymbolAddressInProcess(
>>>            Name.substr(1)))
>>>        return JITSymbol(SymAddr, JITSymbolFlags::Exported);
>>> #endif
>>>
>>>    return nullptr;
>>>  }
>>
>> - "ready> sin(1.0);
>>    Read top-level expression:
>>    define double @2() {
>>    entry:
>>      ret double 0x3FEAED548F090CEE
>>    }
>>
>>    Evaluated to 0.841471":
>>   Actually "sin" is not called at all, LLVM knew "sin" and just returns
>>   the already const-folded value.
>>   In my case, I do see a
>>   "%calltmp = call double @sin(double 1.000000e+00)",
>>   though, inspite of the same optimizations as in your listing...
>>
>> - "ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
>>    Read function definition:
>>    define double @foo(double %x) {
>>    entry:
>>      %calltmp = call double @sin(double %x)
>>      %multmp = fmul double %calltmp, %calltmp
>>      %calltmp2 = call double @cos(double %x)
>>      %multmp4 = fmul double %calltmp2, %calltmp2
>>      %addtmp = fadd double %multmp, %multmp4
>>      ret double %addtmp
>>    }":
>>   In my case, the CSE does not work, although it does work for the
>>   example in 4.3:
>>    "ready> def foo(x) sin(x)*sin(x) + cos(x)*cos(x);
>>    ready> Read function definition:
>>    define double @foo(double %x) {
>>    entry:
>>      %calltmp = call double @sin(double %x)
>>      %calltmp1 = call double @sin(double %x)
>>      %multmp = fmul double %calltmp, %calltmp1
>>      %calltmp2 = call double @cos(double %x)
>>      %calltmp3 = call double @cos(double %x)
>>      %multmp4 = fmul double %calltmp2, %calltmp3
>>      %addtmp = fadd double %multmp, %multmp4
>>      ret double %addtmp
>>    }"
>>
>> - "extern putchard(x); putchard(120);":
>>   Again, on Windows, this doesn't work. To make it work, you have to
>>   use "extern "C" __declspec(dllexport) double putchard(double X)"
>>   so the function will be found via GetProcAddress for the main module.
>>   This wouldn't hurt for Linux / Mac, would it?
>>
>> Best regards
>> Moritz Kroll
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
>


More information about the llvm-dev mailing list