Index: src/CodeGen/FixMain.cc
===================================================================
--- src/CodeGen/FixMain.cc	(revision 8941b6ba42567534f65c1e322eb782a5984d80f5)
+++ src/CodeGen/FixMain.cc	(revision bef4f1a7c08805c9e325222c0cbf3d9df27ef61e)
@@ -14,5 +14,4 @@
 //
 
-
 #include "FixMain.h"
 
@@ -23,5 +22,7 @@
 
 #include "AST/Decl.hpp"
+#include "AST/Pass.hpp"
 #include "AST/Type.hpp"
+#include "AST/Vector.hpp"
 #include "Common/PassVisitor.h"
 #include "Common/SemanticError.h"  // for SemanticError
@@ -47,4 +48,21 @@
 	}
 };
+
+struct FindMainCore_new {
+	ast::FunctionDecl const * main_declaration = nullptr;
+
+	void previsit( ast::FunctionDecl const * decl ) {
+		if ( FixMain::isMain( decl ) ) {
+			if ( main_declaration ) {
+				SemanticError( decl, "Multiple definition of main routine\n" );
+			}
+			main_declaration = decl;
+		}
+	}
+};
+
+std::string genTypeAt( const ast::vector<ast::Type> & types, size_t at ) {
+	return genType( types[at], "", Options( false, false, false, false ) );
+}
 
 }
@@ -83,38 +101,44 @@
 namespace {
 
-ObjectDecl * signedIntObj() {
-	return new ObjectDecl(
-		"", Type::StorageClasses(), LinkageSpec::Cforall, 0,
-		new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr );
-}
-
-ObjectDecl * makeArgvObj() {
-	return new ObjectDecl(
-		"", Type::StorageClasses(), LinkageSpec::Cforall, 0,
-		new PointerType( Type::Qualifiers(),
-			new PointerType( Type::Qualifiers(),
-				new BasicType( Type::Qualifiers(), BasicType::Char ) ) ),
-		nullptr );
-}
-
-std::string create_mangled_main_function_name( FunctionType * function_type ) {
-	std::unique_ptr<FunctionDecl> decl( new FunctionDecl(
-		"main", Type::StorageClasses(), LinkageSpec::Cforall,
-		function_type, nullptr ) );
-	return SymTab::Mangler::mangle( decl.get() );
-}
-
-std::string mangled_0_argument_main() {
-	FunctionType* main_type = new FunctionType( Type::Qualifiers(), true );
-	main_type->get_returnVals().push_back( signedIntObj() );
-	return create_mangled_main_function_name( main_type );
-}
-
-std::string mangled_2_argument_main() {
-	FunctionType* main_type = new FunctionType( Type::Qualifiers(), false );
-	main_type->get_returnVals().push_back( signedIntObj() );
-	main_type->get_parameters().push_back( signedIntObj() );
-	main_type->get_parameters().push_back( makeArgvObj() );
-	return create_mangled_main_function_name( main_type );
+ast::ObjectDecl * makeIntObj(){
+	return new ast::ObjectDecl( CodeLocation(), "",
+		new ast::BasicType( ast::BasicType::SignedInt ) );
+}
+
+ast::ObjectDecl * makeCharStarStarObj() {
+	return new ast::ObjectDecl( CodeLocation(), "",
+		new ast::PointerType(
+			new ast::PointerType(
+				new ast::BasicType( ast::BasicType::Char ) ) ) );
+}
+
+std::string getMangledNameOfMain(
+		ast::vector<ast::DeclWithType> && params, ast::ArgumentFlag isVarArgs ) {
+	ast::ptr<ast::FunctionDecl> decl = new ast::FunctionDecl(
+		CodeLocation(),
+		"main",
+		ast::vector<ast::TypeDecl>(),
+		ast::vector<ast::DeclWithType>(),
+		std::move( params ),
+		{ makeIntObj() },
+		nullptr,
+		ast::Storage::Classes(),
+		ast::Linkage::Spec(),
+		ast::vector<ast::Attribute>(),
+		ast::Function::Specs(),
+		isVarArgs
+	);
+	return Mangle::mangle( decl.get() );
+}
+
+std::string getMangledNameOf0ParameterMain() {
+	return getMangledNameOfMain( {}, ast::VariableArgs );
+}
+
+std::string getMangledNameOf2ParameterMain() {
+	return getMangledNameOfMain( {
+		makeIntObj(),
+		makeCharStarStarObj(),
+	}, ast::FixedArgs );
 }
 
@@ -122,7 +146,7 @@
 	// This breaks if you move it out of the function.
 	static const std::string mangled_mains[] = {
-		mangled_0_argument_main(),
-		mangled_2_argument_main(),
-		//mangled_3_argument_main(),
+		getMangledNameOf0ParameterMain(),
+		getMangledNameOf2ParameterMain(),
+		//getMangledNameOf3ParameterMain(),
 	};
 
@@ -149,3 +173,31 @@
 }
 
-};
+void FixMain::fix( ast::TranslationUnit & translationUnit,
+		std::ostream &os, const char * bootloader_filename ) {
+
+	ast::Pass<FindMainCore_new> main_finder;
+	ast::accept_all( translationUnit, main_finder );
+	if ( nullptr == main_finder.core.main_declaration ) return;
+
+	ast::FunctionDecl * main_declaration =
+		ast::mutate( main_finder.core.main_declaration );
+
+	main_declaration->mangleName = Mangle::mangle( main_declaration );
+
+	os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return ";
+	os << main_declaration->scopedMangleName() << "(";
+	const auto& params = main_declaration->type->params;
+	switch ( params.size() ) {
+		case 3: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv, (" << genTypeAt(params, 2) << ")envp"; break;
+		case 2: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv"; break;
+		case 0: break;
+		default : assert(false);
+	}
+	os << "); }\n";
+
+	std::ifstream bootloader( bootloader_filename, std::ios::in );
+	assertf( bootloader.is_open(), "cannot open bootloader.c\n" );
+	os << bootloader.rdbuf();
+}
+
+} // namespace CodeGen
Index: src/CodeGen/FixMain.h
===================================================================
--- src/CodeGen/FixMain.h	(revision 8941b6ba42567534f65c1e322eb782a5984d80f5)
+++ src/CodeGen/FixMain.h	(revision bef4f1a7c08805c9e325222c0cbf3d9df27ef61e)
@@ -27,4 +27,5 @@
 namespace ast {
 	class FunctionDecl;
+	class TranslationUnit;
 }
 
@@ -49,4 +50,6 @@
 	static void fix( std::list< Declaration * > & decls,
 			std::ostream &os, const char* bootloader_filename );
+	static void fix( ast::TranslationUnit & translationUnit,
+			std::ostream &os, const char * bootloader_filename );
 
 private:
Index: src/main.cc
===================================================================
--- src/main.cc	(revision 8941b6ba42567534f65c1e322eb782a5984d80f5)
+++ src/main.cc	(revision bef4f1a7c08805c9e325222c0cbf3d9df27ef61e)
@@ -437,7 +437,5 @@
 		PASS( "Code Gen", CodeGen::generate, transUnit, *output, !genproto, prettycodegenp, true, linemarks, false );
 
-		translationUnit = convert( std::move( transUnit ) );
-
-		CodeGen::FixMain::fix( translationUnit, *output,
+		CodeGen::FixMain::fix( transUnit, *output,
 				(PreludeDirector + "/bootloader.c").c_str() );
 		if ( output != &cout ) {
