digitalmars.D.ldc - blockaddress( function, %block) IR?
- Tove (9/9) Aug 14 2014 Hi,
- Tove (36/36) Aug 15 2014 I'm now convinced it's a bug, I get this error-message:
- Kagamin (1/1) Aug 16 2014 Did you try to compile with -output-ll option?
- Tove (10/11) Aug 16 2014 Yes, it works fine in the normal case, but every time when I get
- Kai Nacke (7/8) Aug 16 2014 Please read http://wiki.dlang.org/LDC_inline_IR.
- Tove (30/38) Aug 16 2014 Hi Kai,
- Tove (10/17) Aug 16 2014 I guess one possible conclusion from this is that ldc invokes
- Tove (11/20) Aug 18 2014 After cloning the source, I found the issue using code-review,
- Tove (50/52) Aug 18 2014 Argh, silly me, since the results didn't make fully sense I
- Kagamin (2/2) Aug 19 2014 Such things should be tested with IR to see if the feature is
- David Nadlinger via digitalmars-d-ldc (13/15) Aug 19 2014 LLVM indeed provides this feature; in fact, that's the entire point of
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
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
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
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
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: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, ToveI'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
On Sunday, 17 August 2014 at 02:30:33 UTC, Tove wrote:====================== use of undefined value ' fun' ====================== %tmp = call i8* fun() ====================== Best Regards, ToveI 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
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
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
Such things should be tested with IR to see if the feature is provided by LLVM at all.
Aug 19 2014
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