private FunctionSymbol VisitFunctionDeclaration(FunctionDeclarationStmt fd, bool hasDefination) { foreach (var arg in fd.Signature.Arguments) { Assert(arg.Type != "void", $"'void' can't be used as a type."); LinkTypeSymbol(arg.Type); } LinkTypeSymbol(fd.Signature.Return); var funcSym = FindSymbol <FunctionSymbol>(fd.Name); if (funcSym != null) { Assert(funcSym.Signature == fd.Signature, $"Function '{fd.Name}' signature mismatch."); if (hasDefination) { funcSym.HasBody = true; } } else { funcSym = new FunctionSymbol { Name = fd.Name, Signature = fd.Signature, HasBody = hasDefination }; Assert(GetNearestSymbolTable().TryAdd(funcSym), $"There's another type of symbol with the same name '{fd.Name}'."); } return(funcSym); }
private void VisitStmt(Statement stmt, out bool terminate) { terminate = false; if (stmt == null) { return; } LoadTypes(stmt.ScopeSymbols); switch (stmt) { case FunctionDeclarationStmt fd: { break; } case FunctionStmt f: { FunctionSymbol funcSym = f.Symbol; TypeSymbol returnSym = funcSym.Signature.Return.Symbol; LLVMTypeRef funcTy = LLVM.FunctionType( ReturnType: m_Types[returnSym], ParamTypes: funcSym.Signature.Arguments.Select(arg => m_Types[arg.Type.Symbol]).ToArray(), IsVarArg: false); m_Function = LLVM.AddFunction(m_Module, f.Declaration.Name, funcTy); m_FunctionPointers.Add(funcSym, m_Function); LLVMBasicBlockRef bb = LLVM.AppendBasicBlock(m_Function, "entry"); LLVM.PositionBuilderAtEnd(m_Builder, bb); int paramIndex = 0; foreach (var param in m_Function.GetParams()) { LLVMValueRef ptrArg = LLVM.BuildAlloca(m_Builder, LLVM.TypeOf(param), "arg"); LLVM.BuildStore(m_Builder, param, ptrArg); m_VariablePointers.Add(funcSym.Signature.Arguments[paramIndex].Symbol, ptrArg); paramIndex++; } VisitStmt(f.Body, out bool term); if (!term) { if (returnSym.IsPrimitive) { CPrimitiveType prim = returnSym.Primitive.Value; if (prim == CPrimitiveType.Void) { LLVM.BuildRetVoid(m_Builder); } else { LLVM.BuildRet(m_Builder, m_PrimitiveLookup[prim].Default.Value); } } else { throw new NotImplementedException(); } } break; } case BlockStmt block: { foreach (var childStmt in block.Statements) { VisitStmt(childStmt, out bool term); if (term) { terminate = true; break; } } break; } case VariableDeclarationStmt vd: { if (vd.Symbol.IsGlobal) { throw new NotImplementedException(); } else { LLVMValueRef ptr = LLVM.BuildAlloca(m_Builder, m_Types[vd.Type.Symbol], vd.Name); m_VariablePointers.Add(vd.Symbol, ptr); if (vd.Assignment != null) { LLVMValueRef value = VisitExpr(vd.Assignment); LLVM.BuildStore(m_Builder, value, ptr); } } break; } case IfStmt ifs: { LLVMValueRef i32 = VisitExpr(ifs.Condition); LLVMValueRef cond = I32ToCond(i32); LLVMBasicBlockRef bbTrue = LLVM.AppendBasicBlock(m_Function, "if_true"); LLVMBasicBlockRef bbFalse = LLVM.AppendBasicBlock(m_Function, "if_false"); LLVMBasicBlockRef bbSucc = LLVM.AppendBasicBlock(m_Function, "if_succ"); LLVM.BuildCondBr(m_Builder, cond, bbTrue, bbFalse); LLVM.PositionBuilderAtEnd(m_Builder, bbTrue); VisitStmt(ifs.True, out bool termTrue); if (!termTrue) { LLVM.BuildBr(m_Builder, bbSucc); } LLVM.PositionBuilderAtEnd(m_Builder, bbFalse); VisitStmt(ifs.False, out bool termFalse); if (!termFalse) { LLVM.BuildBr(m_Builder, bbSucc); } LLVM.PositionBuilderAtEnd(m_Builder, bbSucc); break; } case ReturnStmt ret: { if (ret.Value == null) { LLVM.BuildRetVoid(m_Builder); } else { LLVMValueRef value = VisitExpr(ret.Value); LLVM.BuildRet(m_Builder, value); } terminate = true; break; } case WhileStmt wh: { LLVMBasicBlockRef bbCond = LLVM.AppendBasicBlock(m_Function, "while_cond"); LLVMBasicBlockRef bbBody = LLVM.AppendBasicBlock(m_Function, "while_body"); LLVMBasicBlockRef bbSucc = LLVM.AppendBasicBlock(m_Function, "while_succ"); m_BreakableStatementSuccessor.Add(wh, bbSucc); LLVM.BuildBr(m_Builder, bbCond); LLVM.PositionBuilderAtEnd(m_Builder, bbCond); LLVMValueRef i32 = VisitExpr(wh.Condition); LLVMValueRef cond = I32ToCond(i32); LLVM.BuildCondBr(m_Builder, cond, bbBody, bbSucc); LLVM.PositionBuilderAtEnd(m_Builder, bbBody); VisitStmt(wh.Body, out bool term); if (!term) { LLVM.BuildBr(m_Builder, bbCond); } LLVM.PositionBuilderAtEnd(m_Builder, bbSucc); break; } case BreakStmt brk: { terminate = true; LLVM.BuildBr(m_Builder, m_BreakableStatementSuccessor[brk.Host]); break; } case ExpressionStmt exprStmt: { VisitExpr(exprStmt.Expression); break; } default: { throw new ArgumentException("Unrecognizable statement type."); } } }