github.com/hbdrawn/golang@v0.0.0-20141214014649-6b835209aba2/src/liblink/pass.c (about) 1 // Inferno utils/6l/pass.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/6l/pass.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 // Code and data passes. 32 33 #include <u.h> 34 #include <libc.h> 35 #include <bio.h> 36 #include <link.h> 37 38 Prog* 39 brchain(Link *ctxt, Prog *p) 40 { 41 int i; 42 43 for(i=0; i<20; i++) { 44 if(p == nil || p->as != ctxt->arch->AJMP || p->pcond == nil) 45 return p; 46 p = p->pcond; 47 } 48 return nil; 49 } 50 51 Prog* 52 brloop(Link *ctxt, Prog *p) 53 { 54 int c; 55 Prog *q; 56 57 c = 0; 58 for(q = p; q != nil; q = q->pcond) { 59 if(q->as != ctxt->arch->AJMP || q->pcond == nil) 60 break; 61 c++; 62 if(c >= 5000) 63 return nil; 64 } 65 return q; 66 } 67 68 void 69 linkpatch(Link *ctxt, LSym *sym) 70 { 71 int32 c; 72 Prog *p, *q; 73 74 ctxt->cursym = sym; 75 76 for(p = sym->text; p != nil; p = p->link) { 77 if(ctxt->arch->progedit) 78 ctxt->arch->progedit(ctxt, p); 79 if(p->to.type != ctxt->arch->D_BRANCH) 80 continue; 81 if(p->to.u.branch != nil) { 82 // TODO: Remove to.u.branch in favor of p->pcond. 83 p->pcond = p->to.u.branch; 84 continue; 85 } 86 if(p->to.sym != nil) 87 continue; 88 c = p->to.offset; 89 for(q = sym->text; q != nil;) { 90 if(c == q->pc) 91 break; 92 if(q->forwd != nil && c >= q->forwd->pc) 93 q = q->forwd; 94 else 95 q = q->link; 96 } 97 if(q == nil) { 98 ctxt->diag("branch out of range (%#ux)\n%P [%s]", 99 c, p, p->to.sym ? p->to.sym->name : "<nil>"); 100 p->to.type = ctxt->arch->D_NONE; 101 } 102 p->to.u.branch = q; 103 p->pcond = q; 104 } 105 106 for(p = sym->text; p != nil; p = p->link) { 107 p->mark = 0; /* initialization for follow */ 108 if(p->pcond != nil) { 109 p->pcond = brloop(ctxt, p->pcond); 110 if(p->pcond != nil) 111 if(p->to.type == ctxt->arch->D_BRANCH) 112 p->to.offset = p->pcond->pc; 113 } 114 } 115 }