Browse Source

mac compatibility with linking

Nicolas Winkler 6 năm trước cách đây
mục cha
commit
d8cb96145f
10 tập tin đã thay đổi với 66 bổ sung75 xóa
  1. 1 1
      src/Builtin.h
  2. 22 3
      src/CMakeLists.txt
  3. 4 5
      src/Driver.cpp
  4. 18 2
      src/Linking.cpp
  5. 1 0
      src/Linking.h
  6. 2 0
      src/ast/Ast.h
  7. 1 1
      src/ast/AstVisitor.cpp
  8. 0 59
      src/makefile
  9. 12 2
      src/sem/CodeGeneration.cpp
  10. 5 2
      src/sem/Semantic.h

+ 1 - 1
src/Builtin.h

@@ -30,7 +30,7 @@ namespace qlow
 struct qlow::sem::NativeMethod : public sem::Method
 {
     inline NativeMethod(NativeScope& scope, TypeId returnType) :
-        Method{ scope, returnType }
+        Method{ scope, returnType, false }
     {
     }
     

+ 22 - 3
src/CMakeLists.txt

@@ -41,13 +41,20 @@ include_directories( ${LLVM_INCLUDE_DIRS} )
 link_directories( ${LLVM_LIBRARY_DIRS} )
 add_definitions( ${LLVM_DEFINITIONS} )
 
-target_compile_definitions(${PROJECT_NAME} PRIVATE LLVM_VERSION=${LLVM_VERSION_MAJOR})
+if (${APPLE})
+    # hack to include libc++fs installed with homebrew
+    set_property(TARGET ${PROJECT_NAME} APPEND_STRING PROPERTY LINK_FLAGS "-L/usr/local/opt/llvm/lib")
+endif()
 
-if ( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_CLANG )
+if ( CMAKE_COMPILER_IS_GNUCC OR CMAKE_CXX_COMPILER MATCHES ".*clang" )
     target_compile_options(${PROJECT_NAME} PRIVATE 
         -Wall -Wextra -Wpedantic -pedantic -Wno-unused-parameter -Wno-unused-function -Wno-unused-variable
     )
-    target_link_libraries(${PROJECT_NAME} stdc++fs)
+    if (${APPLE})
+        target_link_libraries(${PROJECT_NAME} c++fs)
+    else()
+        target_link_libraries(${PROJECT_NAME} stdc++fs)
+    endif()
     set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -DDEBUGGING")
 endif()
 if ( MSVC )
@@ -60,6 +67,18 @@ if(ipo_supported)
 endif()
 
 
+#
+# assuming no cross compiling, target is set to the platform we are compiling on
+#
+
+if (${APPLE})
+    target_compile_definitions(${PROJECT_NAME} PRIVATE QLOW_TARGET_APPLE)
+endif()
+
+if (${WIN32})
+    target_compile_definitions(${PROJECT_NAME} PRIVATE QLOW_TARGET_APPLE)
+endif()
+
 #explicit_llvm_config(${PROJECT_NAME} STATIC_LIBRARY)
 llvm_config(${PROJECT_NAME})
 

+ 4 - 5
src/Driver.cpp

@@ -235,10 +235,6 @@ bool Driver::parseStage(void)
             reportError(errMsg);
             errorOccurred = true;
         }
-        catch (const SyntaxError& se) {
-            se.print(printer);
-            errorOccurred = true;
-        }
         catch (...) {
             reportError("an unknown error occurred.");
             errorOccurred = true;
@@ -286,7 +282,10 @@ bool Driver::linkingStage(void)
 
     std::vector<std::string> ldArgs = {
         tempObject.string(), "-e", "_qlow_start", "-o", options.outfile,
-        "-lc", "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2"
+        "-lc",
+#ifdef __linux__
+        "-dynamic-linker", "/lib64/ld-linux-x86-64.so.2"
+#endif
     };
 
     std::copy(options.libs.begin(), options.libs.end(), std::back_inserter(ldArgs));

+ 18 - 2
src/Linking.cpp

@@ -1,12 +1,26 @@
 #include "Linking.h"
 #include "Printer.h"
 
+#include <vector>
+#include <string>
+
 #include <cstring>
-#ifdef __unix__
+#if defined(__linux__) || defined(__APPLE__) || defined(__unix__)
 #include <unistd.h>
 #include <sys/wait.h>
 #endif
 
+
+std::string qlow::getExternalSymbol(const std::string& name)
+{
+#ifdef QLOW_TARGET_APPLE
+    return "_" + name;
+#else
+    return name;
+#endif
+}
+
+
 std::string qlow::getLinkerExecutable(void)
 {
     return "ld";
@@ -17,7 +31,7 @@ int qlow::invokeProgram(const std::string& path, const std::vector<std::string>&
 {
 #ifdef _WIN32
     throw "unimplemented on windows";
-#elif defined(__unix__)
+#elif defined(__linux__) || defined(__APPLE__) || defined(__unix__)
     pid_t pid = fork();
     
     if (pid == 0) { // we are the child
@@ -62,3 +76,5 @@ int qlow::invokeProgram(const std::string& path, const std::vector<std::string>&
 
 
 
+
+

+ 1 - 0
src/Linking.h

@@ -5,6 +5,7 @@
 
 namespace qlow
 {
+    std::string getExternalSymbol(const std::string& name);
     std::string getLinkerExecutable(void);
     int invokeProgram(const std::string& path, const std::vector<std::string>& args);
 }

+ 2 - 0
src/ast/Ast.h

@@ -291,6 +291,8 @@ struct qlow::ast::MethodDefinition : public FeatureDeclaration
     {
     }
 
+    inline bool isExtern(void) const { return body.get() == nullptr; }
+
     virtual std::unique_ptr<sem::SemanticObject> accept(StructureVisitor& v, sem::Scope&);
 };
 

+ 1 - 1
src/ast/AstVisitor.cpp

@@ -53,7 +53,7 @@ std::unique_ptr<sem::SemanticObject> StructureVisitor::visit(ast::MethodDefiniti
             ast.type->pos
         );
     }
-    auto m = std::make_unique<sem::Method>(scope, returnType);
+    auto m = std::make_unique<sem::Method>(scope, returnType, ast.isExtern());
     m->name = ast.name;
     m->astNode = &ast;
     

+ 0 - 59
src/makefile

@@ -1,59 +0,0 @@
-# building depends on debian packages: "g++" "llvm-dev" "bison" "flex" (and "make", duh)
-# running depends on "llvm" if not statically linked
-
-CXX := clang++
-
-LLVMCONFIG := llvm-config
-
-INCLUDEDIRS := -I$(shell $(LLVMCONFIG) --includedir) -I.. -Isem/ -Iast/ -I.
-CXXFLAGS := -std=c++17 $(INCLUDEDIRS) -w # -Wall -Wextra
-
-ifdef STATIC
-LDFLAGS := $(shell $(LLVMCONFIG) --link-static --ldflags --system-libs --libs all) -static -dead-strip -s
-else
-LDFLAGS := $(shell $(LLVMCONFIG) --ldflags --system-libs --libs all)
-endif
-
-YACC := bison
-YACCFLAGS := -d
-LEX := flex
-LEXFLAGS :=
-
-#OBJECTS := $(patsubst %.cpp, %.o, $(wildcard *.cpp */*.cpp))
-OBJECTS := $(patsubst %.cpp, %.o, $(wildcard *.cpp */*.cpp)) \
-    ast/syntax.o ast/lexer.o
-LIBRARIES := 
-EXECUTABLE := qlow
-
-.PHONY: all
-all: $(EXECUTABLE)
-
-release: CXXFLAGS += -O3 -flto
-release: LDFLAGS += -O3 -flto
-release: all
-
-debug: CXXFLAGS += -DDEBUGGING -g
-debug: all
-
-$(EXECUTABLE): $(OBJECTS)
-	$(CXX) $^ $(LDFLAGS) -o $@
-
-ast/syntax.o: ast/syntax.cpp ast/lexer.cpp
-	$(CXX) -c -o $@ $< $(CXXFLAGS) -fno-strict-aliasing
-
-%.o: %.cpp
-	$(CXX) -c -o $@ $< $(CXXFLAGS)
-
-%.cpp: %.y
-	$(YACC) -o $@ $< $(YACCFLAGS)
-
-%.cpp: %.l ast/syntax.cpp
-	$(LEX) $(LEXFLAGS) -o $@ $<
-
-
-
-.PHONY: clean
-clean:
-	rm -f $(EXECUTABLE) $(OBJECTS) ast/syntax.cpp ast/syntax.hpp ast/lexer.cpp ast/lexer.h
-
-

+ 12 - 2
src/sem/CodeGeneration.cpp

@@ -1,4 +1,5 @@
 #include "CodeGeneration.h"
+#include "Linking.h"
 
 #include <llvm/IR/LLVMContext.h>
 #include <llvm/IR/LegacyPassManager.h>
@@ -175,7 +176,16 @@ llvm::Function* generateFunction(llvm::Module* module, sem::Method* method)
 #endif 
     if (returnType == nullptr)
         throw "invalid return type";
-    Function* func = Function::Create(funcType, Function::ExternalLinkage, method->name, module);
+    std::string symbolName;
+    if (method->isExtern) {
+        Printer::getInstance() << method->name << " is extern" << std::endl;
+        symbolName = qlow::getExternalSymbol(method->name);
+    }
+    else {
+        Printer::getInstance() << method->name << " is not extern" << std::endl;
+        symbolName = method->name;
+    }
+    Function* func = Function::Create(funcType, Function::ExternalLinkage, symbolName, module);
     method->llvmNode = func;
     
     // linking alloca instances for funcs
@@ -219,7 +229,7 @@ llvm::Function* generateStartFunction(llvm::Module* module, llvm::Function* star
     FunctionType* exitFuncType = FunctionType::get(
         Type::getVoidTy(context), { Type::getInt32Ty(context) }, false);
     Function* startFunction = Function::Create(startFuncType, Function::ExternalLinkage, "_qlow_start", module);
-    Function* exitFunction = Function::Create(exitFuncType, Function::ExternalLinkage, "exit", module);
+    Function* exitFunction = Function::Create(exitFuncType, Function::ExternalLinkage, qlow::getExternalSymbol("exit"), module);
 
 
     IRBuilder<> builder(context);

+ 5 - 2
src/sem/Semantic.h

@@ -154,18 +154,20 @@ struct qlow::sem::Method : public SemanticObject
     ast::MethodDefinition* astNode;
     ThisExpression* thisExpression;
     std::unique_ptr<DoEndBlock> body;
+    bool isExtern;
 
     LocalScope scope;
 
     llvm::Function* llvmNode;
 
     inline Method(Scope& parentScope,
-            TypeId returnType) :
+            TypeId returnType, bool isExtern) :
         SemanticObject{ parentScope.getContext() },
         containingClass{ nullptr },
         returnType{ returnType },
         thisExpression{ nullptr },
         body{ nullptr },
+        isExtern{ isExtern },
         scope{ parentScope, this }
     {
     }
@@ -174,11 +176,12 @@ struct qlow::sem::Method : public SemanticObject
     inline Method(ast::MethodDefinition* astNode, Scope& parentScope) :
         SemanticObject{ parentScope.getContext() },
         containingClass{ nullptr },
-        returnType{ parentScope.getReturnableType()},
+        returnType{ parentScope.getReturnableType() },
         name{ astNode->name },
         astNode{ astNode },
         thisExpression{ nullptr },
         body{ nullptr },
+        isExtern{ astNode->isExtern() },
         scope{ parentScope, this }
     {
     }