www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.ldc - blockaddress( function, %block) IR?

reply "Tove" <Tove fransson.se> writes:
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?
Aug 14 2014
parent reply "Tove" <Tove fransson.se> writes:
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
}
==================================================
Aug 15 2014
next sibling parent reply "Kagamin" <spam here.lot> writes:
Did you try to compile with -output-ll option?
Aug 16 2014
parent "Tove" <Tove fransson.se> writes:
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)
Aug 16 2014
prev sibling parent reply "Kai Nacke" <kai redstar.de> writes:
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
Aug 16 2014
parent reply "Tove" <Tove fransson.se> writes:
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
Aug 16 2014
parent reply "Tove" <Tove fransson.se> writes:
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.
Aug 16 2014
parent reply "Tove" <Tove fransson.se> writes:
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.
Aug 18 2014
parent reply "Tove" <Tove fransson.se> writes:
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'.
Aug 18 2014
parent reply "Kagamin" <spam here.lot> writes:
Such things should be tested with IR to see if the feature is 
provided by LLVM at all.
Aug 19 2014
parent David Nadlinger via digitalmars-d-ldc <digitalmars-d-ldc puremagic.com> writes:
On 19 Aug 2014, at 11:03, Kagamin via digitalmars-d-ldc wrote:
 Such things should be tested with IR to see if the feature is provided 
 by LLVM at all.
LLVM indeed provides this feature; in fact, that's the entire point of the intrinsic in question. The problem is that inline IR support was not written with this sort of dependencies in mind (and I don't see us making any stability guarantees for the generated IR, e.g. that "foo:" is always lowered to %label_foo). It might be possible and reasonable to delay emitting any inline IR wrapper function bodies until after the main function has been completed. In fact, it shouldn't even be too difficult to throw together a quick implementation, but unfortunately, I don't have the time to look into this right now. Cheers, David
Aug 19 2014