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 }