1 /** 2 * This module crawl the AST to resolve identifiers and process types. 3 */ 4 module d.semantic.semantic; 5 6 public import util.visitor; 7 8 import d.semantic.scheduler; 9 10 import d.ast.declaration; 11 import d.ast.expression; 12 import d.ast.statement; 13 14 import d.ir.expression; 15 import d.ir.symbol; 16 import d.ir.type; 17 18 import source.name; 19 20 alias AstModule = d.ast.declaration.Module; 21 alias Module = d.ir.symbol.Module; 22 23 alias CallExpression = d.ir.expression.CallExpression; 24 25 final class SemanticPass { 26 import source.context; 27 Context context; 28 29 string[] includePaths; 30 bool enableUnittest; 31 32 Scheduler scheduler; 33 34 static struct State { 35 import d.ir.dscope; 36 Scope currentScope; 37 38 ParamType returnType; 39 ParamType thisType; 40 41 Function ctxSym; 42 43 string manglePrefix; 44 45 // Indicate that what is being worked on is a 46 // template specialization pattern. 47 bool inPattern; 48 } 49 50 State state; 51 alias state this; 52 53 alias Step = d.ir.symbol.Step; 54 55 import d.semantic.evaluator; 56 Evaluator evaluator; 57 58 import d.semantic.datalayout; 59 DataLayout dataLayout; 60 61 import d.semantic.dmodule; 62 ModuleVisitorData moduleVisitorData; 63 64 import d.object; 65 ObjectReference object; 66 67 Name[] versions = getDefaultVersions(); 68 69 alias EvaluatorBuilder = Evaluator delegate(SemanticPass); 70 alias DataLayoutBuilder = DataLayout delegate(ObjectReference); 71 72 this( 73 Context context, 74 string[] includePaths, 75 bool enableUnittest, 76 EvaluatorBuilder evBuilder, 77 DataLayoutBuilder dlBuilder, 78 ) { 79 this.context = context; 80 this.includePaths = includePaths; 81 this.enableUnittest = enableUnittest; 82 83 scheduler = new Scheduler(this); 84 85 import source.name; 86 auto obj = importModule([BuiltinName!"object"]); 87 this.object = new ObjectReference(obj); 88 89 evaluator = evBuilder(this); 90 dataLayout = dlBuilder(this.object); 91 92 scheduler.require(obj, Step.Populated); 93 } 94 95 Module add(string filename) { 96 return ModuleVisitor(this).add(filename); 97 } 98 99 void terminate() { 100 scheduler.terminate(); 101 } 102 103 auto evaluate(Expression e) { 104 return evaluator.evaluate(e); 105 } 106 107 auto evalIntegral(Expression e) { 108 return evaluator.evalIntegral(e); 109 } 110 111 auto evalString(Expression e) { 112 return evaluator.evalString(e); 113 } 114 115 auto importModule(Name[] pkgs) { 116 return ModuleVisitor(this).importModule(pkgs); 117 } 118 119 Function buildMain(Module m) { 120 import std.algorithm, std.array; 121 auto candidates = m.members.map!((s) { 122 if (auto fun = cast(Function) s) { 123 if (fun.name == BuiltinName!"main") { 124 return fun; 125 } 126 } 127 128 return null; 129 }).filter!(s => !!s).array(); 130 131 assert(candidates.length < 2, "Several main functions"); 132 assert(candidates.length == 1, "No main function"); 133 134 auto main = candidates[0]; 135 auto location = main.location; 136 137 auto type = main.type; 138 auto returnType = type.returnType.getType(); 139 auto call = new CallExpression(location, returnType, new FunctionExpression(location, main), []); 140 141 import d.ir.instruction; 142 Body fbody; 143 auto bb = fbody.newBasicBlock(BuiltinName!"entry"); 144 if (returnType.kind == TypeKind.Builtin && returnType.builtin == BuiltinType.Void) { 145 fbody[bb].eval(location, call); 146 fbody[bb].ret(location, new IntegerLiteral(location, 0, BuiltinType.Int)); 147 } else { 148 fbody[bb].ret(location, call); 149 } 150 151 auto bootstrap = new Function( 152 main.location, 153 main.getModule(), 154 FunctionType( 155 Linkage.C, 156 Type.get(BuiltinType.Int).getParamType(ParamKind.Regular), 157 [], 158 false, 159 ), 160 BuiltinName!"_Dmain", 161 [], 162 ); 163 164 bootstrap.fbody = fbody; 165 166 bootstrap.visibility = Visibility.Public; 167 bootstrap.step = Step.Processed; 168 bootstrap.mangle = BuiltinName!"_Dmain"; 169 170 return bootstrap; 171 } 172 } 173 174 private: 175 176 auto getDefaultVersions() { 177 import source.name; 178 auto versions = [BuiltinName!"SDC", BuiltinName!"D_LP64", BuiltinName!"X86_64", BuiltinName!"Posix"]; 179 180 version(linux) { 181 versions ~= BuiltinName!"linux"; 182 } 183 184 version(OSX) { 185 versions ~= BuiltinName!"OSX"; 186 } 187 188 version(FreeBSD) { 189 versions ~= BuiltinName!"FreeBSD"; 190 } 191 192 version(Posix) { 193 versions ~= BuiltinName!"Posix"; 194 } 195 196 return versions; 197 }