On Mon, Jul 25, 2011 at 11:16 PM, Chris Lattner <span dir="ltr"><<a href="mailto:clattner@apple.com">clattner@apple.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">

<div style="word-wrap:break-word"><div class="im"><div><div>On Jul 25, 2011, at 10:58 PM, Talin wrote:</div><blockquote type="cite"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0.8ex;border-left-width:1px;border-left-color:rgb(204, 204, 204);border-left-style:solid;padding-left:1ex">

To handle the fact that types do not (and can not, at least as long as we intend to support obscure languages like "C" :) have linkage, the the linker uses a "best effort" approach.  It attempts to merge types and rewrite IR to use the merged types where it can, but it doesn't make any guarantees.<br>




<font color="#888888"><br></font></blockquote><div>I want to add an additional detail into this mix: That the frontend generating all of this code is making a best effort to insure that the types are in fact compatible -- and it isn't working.</div>



<div><br></div><div>One of the painful things about the old type system was that you were forced to specify every type in excruciating detail - so if I had a type A which had a data member of type B*, I had to include the complete definition of B in my module, even if the module never dereferenced that field - because otherwise my definition of A wouldn't be compatible with another module's definition of A. And if B contained a C* which in turn contained a D*, all of those had to be specified as well, even if the module never used types C or D.</div>



<div><br></div><div>One of the benefits I had hoped to get out of the new system was to be able to "forward declare" a type without giving a definition for it - so if I have my definition of A containing a B*, I only need to declare B as an opaque type instead of giving all the details.</div>



<div><br></div><div>However, it sounds like what you are saying is that if I do this, I can't depend on the linker being able to merge the definition of forward-declared B with fully-specified B, nor A from module 1 (containing forward-declared B*) with A from module 2 (containing fully-specified B*).</div>



<div><br></div><div>If that's true, then it means that we're back to the case where every type has to be fully defined down to the leaf level.</div></div></blockquote><br></div></div><div>I'm not sure what you mean.  LLVM is perfectly fine with opaque structs so long as you don't "deference" them, GEP into them, need their size, etc.</div>

</div></blockquote><div><br></div><div>Let me try with another example: Let's say Module A and Module B both import class Exception. Class Exception has a "message" field which is a pointer to type String. Now, let's say Module A dereferences the Exception.message field by printing the message. The compiler sees this dereference, and automatically loads the String module. Type String is added to Module A as a fully-resolved struct type.</div>

<div><br></div><div>In Module B, on the other hand, there is no dereference of the message field. So the compiler includes the definition of Exception, but the definition of String is opaque, because no code in Module B ever referred to any of the fields of class String. In fact the compiler never even loaded the definition of String because it wasn't needed.</div>

<div><br></div><div>Now we attempt to link together a bunch of modules including A and B. The linker sees that there are two types named "Exception" and renamed one of them. It also sees that there are two types named "String" and renames one of those as well. At this point, the linker fails because of a type mismatch. At least, this is the behavior that I am seeing.</div>

<div><br></div></div>-- <br>-- Talin<br>