Jump to page: 1 2
Thread overview
blockaddress(@function, %block) IR?
Aug 15, 2014
Tove
Aug 15, 2014
Tove
Aug 16, 2014
Kagamin
Aug 17, 2014
Tove
Aug 16, 2014
Kai Nacke
Aug 17, 2014
Tove
Aug 17, 2014
Tove
Aug 18, 2014
Tove
Aug 19, 2014
Tove
Aug 19, 2014
Kagamin
Aug 19, 2014
David Nadlinger
August 15, 2014
Hi,

I was testing 'LDC 0.14.0 alpha1' and started hacking around with the very nice LDC_inline_ir feature, but I don't think my issue is version specific, thus I created a new thread...

Many IR:s work fine, but I simply cannot get blockaddress(@function, %block) to compile(trying to follow the spec from here):
http://llvm.org/docs/LangRef.html

Does anyone have a minimal working example?
August 15, 2014
I'm now convinced it's a bug, I get this error-message:
==================================================
store i8* blockaddress(@fun, %label_lbl1), i8** %0
                       ^
unknown function referenced by blockaddress
==================================================

For this program:
==================================================
pragma(LDC_no_moduleinfo)
pragma(LDC_inline_ir)
R inlineIR(string s, R, P...)(P);

extern(C)
byte* fun()
{
  byte* lbl_addr;

  inlineIR!(`store i8* blockaddress(@fun, %label_lbl1), i8** %0`, void)(&lbl_addr);

lbl1:
  return lbl_addr;
}
==================================================

But it works fine, if I instead hand-edit the *.ll file and compile it.
==================================================
target triple = "i686-pc-mingw32"

define i8* @fun() {
  %lbl_addr = alloca i8*, align 4
  store i8* blockaddress(@fun, %label_lbl1), i8** %lbl_addr
  %tmp = load i8** %lbl_addr
  br label %label_lbl1

label_lbl1:                                       ; preds = %0
  %tmp1 = load i8** %lbl_addr
  %tmp2 = load i8** %lbl_addr
  ret i8* %tmp2
}
==================================================
August 16, 2014
Did you try to compile with -output-ll option?
August 16, 2014
Hi Tove!

On Friday, 15 August 2014 at 18:10:45 UTC, Tove wrote:
> I'm now convinced it's a bug, I get this error-message:

Please read http://wiki.dlang.org/LDC_inline_IR.

A separate LLVM function is generated for the inlineIR template.
The label is outside this function.

Regards,
Kai
August 17, 2014
On Saturday, 16 August 2014 at 18:35:51 UTC, Kagamin wrote:
> Did you try to compile with -output-ll option?

Yes, it works fine in the normal case, but every time when I get
an IR compilation error, I am greeted with the following:
"ldc2.exe has stopped working", which unfortunately means it
fails to write anything to the file.

RtlInitUnicodeString() + 0x164 bytes(s)
RtlAllocateHeap() + 0xAC bytes(s)
RtlImageNtHeader() + 0xB3F bytes(s)
RtlImageNtHeader() + 0xB6A bytes(s)
malloc() + 0x57 bytes(s)
August 17, 2014
On Saturday, 16 August 2014 at 21:25:58 UTC, Kai Nacke wrote:
> Hi Tove!
>
> On Friday, 15 August 2014 at 18:10:45 UTC, Tove wrote:
>> I'm now convinced it's a bug, I get this error-message:
>
> Please read http://wiki.dlang.org/LDC_inline_IR.
>
> A separate LLVM function is generated for the inlineIR template.
> The label is outside this function.
>
> Regards,
> Kai

Hi Kai,

thanks for your help, actually that page was the very reason I
started using the inlineIR.

However the really exciting part of 'blockaddress' in LLVM is
that it supports accessing labels inside different functions,
this is why it takes 2 parameters!(I verified that accessing a
label inside another function works fine when manually writing
the IR)

If it had taken only 1 param I could have gotten it to work by
accessing a local label inside the IR.

But anyway, it is _NOT_ the label-lookup which fails, it is the
function-lookup!

In order to attempt to workaround, I tried to declare a function
prototype both in the IR and in D.
======================
Inserting "extern(C) byte* fun();" on line 1, didn't help.

Also using IR "declare" inside another nested function definition
seems illegal in LLVM, thus it's also not a feasible workaround.
======================

Because it's the function-lookup which fails, I started
suspecting that call would fail as well and actually it does,
although it gives me a different error message.
======================
use of undefined value '@fun'
======================                  ^
%tmp = call i8* @fun()
======================

Best Regards,
Tove
August 17, 2014
On Sunday, 17 August 2014 at 02:30:33 UTC, Tove wrote:
> ======================
> use of undefined value '@fun'
> ======================
> %tmp = call i8* @fun()
> ======================
>
> Best Regards,
> Tove

I guess one possible conclusion from this is that ldc invokes
llvm to translate the inlineIR totally isolated from the rest of
the d-file and thus is unable to access any global symbols which
are not parameters to the template?

If it simply had concatenated the output generated by the
inlineIR to the end of the output generated by the rest of the
translation unit, then it would most likely have worked?

Well, I'm just speculating, I should familiarize myself with the
ldc source one sunny day.
August 18, 2014
On Sunday, 17 August 2014 at 03:35:14 UTC, Tove wrote:
> I guess one possible conclusion from this is that ldc invokes
> llvm to translate the inlineIR totally isolated from the rest of
> the d-file and thus is unable to access any global symbols which
> are not parameters to the template?
>
> If it simply had concatenated the output generated by the
> inlineIR to the end of the output generated by the rest of the
> translation unit, then it would most likely have worked?
>
> Well, I'm just speculating, I should familiarize myself with the
> ldc source one sunny day.

After cloning the source, I found the issue using code-review, the regression was introduced in:
7436d94e09700fc3ead5fc3b1912d172c299dfaa

Since I'm not able to build LDC at the moment, I downloaded a binary ldc-dist before this patch was introduced and indeed it is able to compile my blockaddress example, but instead there's a linking error, the inline function is missing, it's not as simple as reverting this patch.

Looking at the "-output-ll" I see that the inlineIR function is "declared" but not defined.
August 19, 2014
On Monday, 18 August 2014 at 15:45:55 UTC, Tove wrote:
> Looking at the "-output-ll" I see that the inlineIR function is "declared" but not defined.

Argh, silly me, since the results didn't make fully sense I continued to investigate.

Because I used an older compiler without support for pragma(LDC_no_moduleinfo), I deleted it but I accidentally deleted pragma(LDC_inline_ir) as well, no wonder the results were strange. But anyway the rest of the observations were correct.

With the old version it now sort of works!!! :)
=======================================
extern(C)
byte* fun1()
{
  byte* lbl_addr;

lbl1:
  inlineIR!(`
            store i8* blockaddress(@fun1, %label_lbl1), i8** %0
            `, void)(&lbl_addr);
  return lbl_addr;
}
=======================================
define i8* @fun1() {
entry:
  %lbl_addr = alloca i8*, align 4
  store i8* null, i8** %lbl_addr
  %tmp = load i8** %lbl_addr
  br label %label_lbl1

label_lbl1:                                       ; preds = %entry
  store i8* blockaddress(@fun1, %label_lbl1), i8** %lbl_addr
  %tmp1 = load i8** %lbl_addr
  %tmp2 = load i8** %lbl_addr
  ret i8* %tmp2
}
=======================================

However... the label is only accessible if it's located _before_ the inlineIR otherwise it fails, I guess that means the inlineIR is send to llvm::ParseAssemblyString too early, is that complicated to fix?

To be absolutely clear what I mean:
=======================================
extern(C)
byte* fun2()
{
  byte* lbl_addr;

  inlineIR!(`
            store i8* blockaddress(@fun2, %label_lbl2), i8** %0
            `, void)(&lbl_addr);
lbl2:
  return lbl_addr;
}

This fails with 'referenced value is not a basic block'.
August 19, 2014
Such things should be tested with IR to see if the feature is provided by LLVM at all.
« First   ‹ Prev
1 2