#include #include #include #include #include #include #include #include #include #include #include #include #include #include "y.tab.h" #include "ast.h" #include "stack.h" #include "../lib/dropt/dropt.h" extern FILE *yyin; Stack *stack; Node *rootNode; typedef struct LocalVariable { char *name; LLVMValueRef pointer; } LocalVariable; typedef struct FunctionArgument { char *name; LLVMValueRef value; } FunctionArgument; typedef struct ScopeFrame { LocalVariable *localVariables; uint32_t localVariableCount; } ScopeFrame; typedef struct Scope { ScopeFrame *scopeStack; uint32_t scopeStackCount; } Scope; Scope *scope; typedef struct StructTypeField { char *name; uint32_t index; } StructTypeField; typedef struct StructTypeFunction { char *name; LLVMValueRef function; LLVMTypeRef returnType; uint8_t isStatic; } StructTypeFunction; typedef struct StructTypeDeclaration { char *name; LLVMTypeRef structType; LLVMTypeRef structPointerType; StructTypeField *fields; uint32_t fieldCount; StructTypeFunction *functions; uint32_t functionCount; } StructTypeDeclaration; StructTypeDeclaration *structTypeDeclarations; uint32_t structTypeDeclarationCount; static Scope* CreateScope() { Scope *scope = malloc(sizeof(Scope)); scope->scopeStack = malloc(sizeof(ScopeFrame)); scope->scopeStack[0].localVariableCount = 0; scope->scopeStack[0].localVariables = NULL; scope->scopeStackCount = 1; return scope; } static void PushScopeFrame(Scope *scope) { uint32_t index = scope->scopeStackCount; scope->scopeStack = realloc(scope->scopeStack, sizeof(ScopeFrame) * (scope->scopeStackCount + 1)); scope->scopeStack[index].localVariableCount = 0; scope->scopeStack[index].localVariables = NULL; scope->scopeStackCount += 1; } static void PopScopeFrame(Scope *scope) { uint32_t i; uint32_t index = scope->scopeStackCount - 1; if (scope->scopeStack[index].localVariables != NULL) { for (i = 0; i < scope->scopeStack[index].localVariableCount; i += 1) { free(scope->scopeStack[index].localVariables[i].name); } free(scope->scopeStack[index].localVariables); } scope->scopeStackCount -= 1; scope->scopeStack = realloc(scope->scopeStack, sizeof(ScopeFrame) * scope->scopeStackCount); } static void AddLocalVariable(Scope *scope, LLVMValueRef pointer, char *name) { ScopeFrame *scopeFrame = &scope->scopeStack[scope->scopeStackCount - 1]; uint32_t index = scopeFrame->localVariableCount; scopeFrame->localVariables = realloc(scopeFrame->localVariables, sizeof(LocalVariable) * (scopeFrame->localVariableCount + 1)); scopeFrame->localVariables[index].name = strdup(name); scopeFrame->localVariables[index].pointer = pointer; scopeFrame->localVariableCount += 1; } static LLVMTypeRef WraithTypeToLLVMType(PrimitiveType type) { switch (type) { case Int: return LLVMInt64Type(); case UInt: return LLVMInt64Type(); case Bool: return LLVMInt1Type(); case Void: return LLVMVoidType(); } fprintf(stderr, "Unrecognized type!"); return NULL; } static LLVMTypeRef FindStructType(char *name) { uint32_t i; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (strcmp(structTypeDeclarations[i].name, name) == 0) { return structTypeDeclarations[i].structType; } } return NULL; } static LLVMValueRef FindStructFieldPointer(LLVMBuilderRef builder, LLVMValueRef structPointer, char *name) { int32_t i, j; LLVMTypeRef structPointerType = LLVMTypeOf(structPointer); for (i = 0; i < structTypeDeclarationCount; i += 1) { if (structTypeDeclarations[i].structPointerType == structPointerType) { for (j = 0; j < structTypeDeclarations[i].fieldCount; j += 1) { if (strcmp(structTypeDeclarations[i].fields[j].name, name) == 0) { char *ptrName = strdup(name); strcat(ptrName, "_ptr"); return LLVMBuildStructGEP( builder, structPointer, structTypeDeclarations[i].fields[j].index, ptrName ); free(ptrName); } } } } printf("Failed to find struct field pointer!"); return NULL; } static LLVMValueRef FindVariablePointer(char *name) { int32_t i, j; for (i = scope->scopeStackCount - 1; i >= 0; i -= 1) { for (j = 0; j < scope->scopeStack[i].localVariableCount; j += 1) { if (strcmp(scope->scopeStack[i].localVariables[j].name, name) == 0) { return scope->scopeStack[i].localVariables[j].pointer; } } } printf("Failed to find variable pointer!"); return NULL; } static LLVMValueRef FindVariableValue(LLVMBuilderRef builder, char *name) { int32_t i, j; for (i = scope->scopeStackCount - 1; i >= 0; i -= 1) { for (j = 0; j < scope->scopeStack[i].localVariableCount; j += 1) { if (strcmp(scope->scopeStack[i].localVariables[j].name, name) == 0) { return LLVMBuildLoad(builder, scope->scopeStack[i].localVariables[j].pointer, name); } } } printf("Failed to find variable value!"); return NULL; } static void AddStructDeclaration( LLVMTypeRef wStructType, LLVMTypeRef wStructPointerType, char *name, Node **fieldDeclarations, uint32_t fieldDeclarationCount ) { uint32_t i; uint32_t index = structTypeDeclarationCount; structTypeDeclarations = realloc(structTypeDeclarations, sizeof(StructTypeDeclaration) * (structTypeDeclarationCount + 1)); structTypeDeclarations[index].structType = wStructType; structTypeDeclarations[index].structPointerType = wStructPointerType; structTypeDeclarations[index].name = strdup(name); structTypeDeclarations[index].fields = NULL; structTypeDeclarations[index].fieldCount = 0; structTypeDeclarations[index].functions = NULL; structTypeDeclarations[index].functionCount = 0; for (i = 0; i < fieldDeclarationCount; i += 1) { structTypeDeclarations[index].fields = realloc(structTypeDeclarations[index].fields, sizeof(StructTypeField) * (structTypeDeclarations[index].fieldCount + 1)); structTypeDeclarations[index].fields[i].name = strdup(fieldDeclarations[i]->children[1]->value.string); structTypeDeclarations[index].fields[i].index = i; structTypeDeclarations[index].fieldCount += 1; } structTypeDeclarationCount += 1; } static void DeclareStructFunction( LLVMTypeRef wStructPointerType, LLVMValueRef function, LLVMTypeRef returnType, uint8_t isStatic, char *name ) { uint32_t i, index; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (structTypeDeclarations[i].structPointerType == wStructPointerType) { index = structTypeDeclarations[i].functionCount; structTypeDeclarations[i].functions = realloc(structTypeDeclarations[i].functions, sizeof(StructTypeFunction) * (structTypeDeclarations[i].functionCount + 1)); structTypeDeclarations[i].functions[index].name = strdup(name); structTypeDeclarations[i].functions[index].function = function; structTypeDeclarations[i].functions[index].returnType = returnType; structTypeDeclarations[i].functions[index].isStatic = isStatic; structTypeDeclarations[i].functionCount += 1; return; } } fprintf(stderr, "Could not find struct type for function!\n"); } static LLVMTypeRef LookupCustomType(char *name) { uint32_t i; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (strcmp(structTypeDeclarations[i].name, name) == 0) { return structTypeDeclarations[i].structType; } } fprintf(stderr, "Could not find struct type!\n"); return NULL; } static LLVMTypeRef ResolveType(Node* typeNode) { if (IsPrimitiveType(typeNode)) { return WraithTypeToLLVMType(typeNode->children[0]->primitiveType); } else if (typeNode->children[0]->syntaxKind == CustomTypeNode) { char *typeName = typeNode->children[0]->value.string; return LookupCustomType(typeName); } else if (typeNode->children[0]->syntaxKind == ReferenceTypeNode) { return LLVMPointerType(ResolveType(typeNode->children[0]->children[0]), 0); } else { fprintf(stderr, "Unknown type node!\n"); return NULL; } } static LLVMValueRef LookupFunctionByType( LLVMTypeRef structType, char *name, LLVMTypeRef *pReturnType, uint8_t *pStatic ) { uint32_t i, j; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (structTypeDeclarations[i].structType == structType) { for (j = 0; j < structTypeDeclarations[i].functionCount; j += 1) { if (strcmp(structTypeDeclarations[i].functions[j].name, name) == 0) { *pReturnType = structTypeDeclarations[i].functions[j].returnType; *pStatic = structTypeDeclarations[i].functions[j].isStatic; return structTypeDeclarations[i].functions[j].function; } } } } fprintf(stderr, "Could not find struct function!\n"); return NULL; } static LLVMValueRef LookupFunctionByPointerType( LLVMTypeRef structPointerType, char *name, LLVMTypeRef *pReturnType, uint8_t *pStatic ) { uint32_t i, j; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (structTypeDeclarations[i].structPointerType == structPointerType) { for (j = 0; j < structTypeDeclarations[i].functionCount; j += 1) { if (strcmp(structTypeDeclarations[i].functions[j].name, name) == 0) { *pReturnType = structTypeDeclarations[i].functions[j].returnType; *pStatic = structTypeDeclarations[i].functions[j].isStatic; return structTypeDeclarations[i].functions[j].function; } } } } fprintf(stderr, "Could not find struct function!\n"); return NULL; } static LLVMValueRef LookupFunctionByInstance( LLVMValueRef structPointer, char *name, LLVMTypeRef *pReturnType, uint8_t *pStatic ) { return LookupFunctionByPointerType(LLVMTypeOf(structPointer), name, pReturnType, pStatic); } static void AddStructVariablesToScope( LLVMBuilderRef builder, LLVMValueRef structPointer ) { uint32_t i, j; for (i = 0; i < structTypeDeclarationCount; i += 1) { if (structTypeDeclarations[i].structPointerType == LLVMTypeOf(structPointer)) { for (j = 0; j < structTypeDeclarations[i].fieldCount; j += 1) { char *ptrName = strdup(structTypeDeclarations[i].fields[j].name); strcat(ptrName, "_ptr"); LLVMValueRef elementPointer = LLVMBuildStructGEP( builder, structPointer, structTypeDeclarations[i].fields[j].index, ptrName ); free(ptrName); AddLocalVariable( scope, elementPointer, structTypeDeclarations[i].fields[j].name ); } } } } static LLVMValueRef CompileExpression( LLVMBuilderRef builder, Node *binaryExpression ); static LLVMValueRef CompileNumber( Node *numberExpression ) { return LLVMConstInt(LLVMInt64Type(), numberExpression->value.number, 0); } static LLVMValueRef CompileBinaryExpression( LLVMBuilderRef builder, Node *binaryExpression ) { LLVMValueRef left = CompileExpression(builder, binaryExpression->children[0]); LLVMValueRef right = CompileExpression(builder, binaryExpression->children[1]); switch (binaryExpression->operator.binaryOperator) { case Add: return LLVMBuildAdd(builder, left, right, "tmp"); case Subtract: return LLVMBuildSub(builder, left, right, "tmp"); case Multiply: return LLVMBuildMul(builder, left, right, "tmp"); } return NULL; } /* FIXME THIS IS ALL BROKEN */ static LLVMValueRef CompileFunctionCallExpression( LLVMBuilderRef builder, Node *expression ) { uint32_t i; uint32_t argumentCount = 0; LLVMValueRef args[expression->children[1]->childCount + 1]; LLVMValueRef function; uint8_t isStatic; LLVMValueRef structInstance; LLVMTypeRef functionReturnType; char *returnName = ""; /* FIXME: this needs to be recursive on access chains */ if (expression->children[0]->syntaxKind == AccessExpression) { LLVMTypeRef typeReference = FindStructType( expression->children[0]->children[0]->value.string ); if (typeReference != NULL) { function = LookupFunctionByType( typeReference, expression->children[0]->children[1]->value.string, &functionReturnType, &isStatic ); } else { structInstance = FindVariablePointer(expression->children[0]->children[0]->value.string); function = LookupFunctionByInstance(structInstance, expression->children[0]->children[1]->value.string, &functionReturnType, &isStatic); } } else { fprintf(stderr, "Failed to find function!\n"); return NULL; } if (!isStatic) { args[argumentCount] = structInstance; argumentCount += 1; } for (i = 0; i < expression->children[1]->childCount; i += 1) { args[argumentCount] = CompileExpression(builder, expression->children[1]->children[i]); argumentCount += 1; } if (LLVMGetTypeKind(functionReturnType) != LLVMVoidTypeKind) { returnName = "callReturn"; } return LLVMBuildCall(builder, function, args, argumentCount, returnName); } static LLVMValueRef CompileAccessExpressionForStore( LLVMBuilderRef builder, Node *expression ) { Node *accessee = expression->children[0]; Node *accessor = expression->children[1]; LLVMValueRef accesseeValue = FindVariablePointer(accessee->value.string); return FindStructFieldPointer(builder, accesseeValue, accessor->value.string); } static LLVMValueRef CompileAccessExpression( LLVMBuilderRef builder, Node *expression ) { Node *accessee = expression->children[0]; Node *accessor = expression->children[1]; LLVMValueRef accesseeValue = FindVariablePointer(accessee->value.string); LLVMValueRef access = FindStructFieldPointer(builder, accesseeValue, accessor->value.string); return LLVMBuildLoad(builder, access, accessor->value.string); } static LLVMValueRef CompileAllocExpression( LLVMBuilderRef builder, Node *expression ) { LLVMTypeRef type = ResolveType(expression->children[0]); return LLVMBuildMalloc(builder, type, "allocation"); } static LLVMValueRef CompileExpression( LLVMBuilderRef builder, Node *expression ) { switch (expression->syntaxKind) { case AccessExpression: return CompileAccessExpression(builder, expression); case AllocExpression: return CompileAllocExpression(builder, expression); case BinaryExpression: return CompileBinaryExpression(builder, expression); case FunctionCallExpression: return CompileFunctionCallExpression(builder, expression); case Identifier: return FindVariableValue(builder, expression->value.string); case Number: return CompileNumber(expression); } fprintf(stderr, "Unknown expression kind!\n"); return NULL; } static void CompileReturn(LLVMBuilderRef builder, Node *returnStatemement) { LLVMValueRef expression = CompileExpression(builder, returnStatemement->children[0]); LLVMBuildRet(builder, expression); } static void CompileReturnVoid(LLVMBuilderRef builder) { LLVMBuildRetVoid(builder); } static void CompileAssignment(LLVMBuilderRef builder, Node *assignmentStatement) { LLVMValueRef result = CompileExpression(builder, assignmentStatement->children[1]); LLVMValueRef identifier; if (assignmentStatement->children[0]->syntaxKind == AccessExpression) { identifier = CompileAccessExpressionForStore(builder, assignmentStatement->children[0]); } else if (assignmentStatement->children[0]->syntaxKind == Identifier) { identifier = FindVariablePointer(assignmentStatement->children[0]->value.string); } else { printf("Identifier not found!"); return; } LLVMBuildStore(builder, result, identifier); } /* FIXME: path for reference types */ static void CompileFunctionVariableDeclaration(LLVMBuilderRef builder, Node *variableDeclaration) { LLVMValueRef variable; char *variableName = variableDeclaration->children[1]->value.string; char *ptrName = strdup(variableName); strcat(ptrName, "_ptr"); variable = LLVMBuildAlloca(builder, ResolveType(variableDeclaration->children[0]), ptrName); free(ptrName); AddLocalVariable(scope, variable, variableName); } static uint8_t CompileStatement(LLVMBuilderRef builder, LLVMValueRef function, Node *statement) { switch (statement->syntaxKind) { case Assignment: CompileAssignment(builder, statement); return 0; case FunctionCallExpression: CompileFunctionCallExpression(builder, statement); return 0; case Declaration: CompileFunctionVariableDeclaration(builder, statement); return 0; case Return: CompileReturn(builder, statement); return 1; case ReturnVoid: CompileReturnVoid(builder); return 1; } fprintf(stderr, "Unknown statement kind!\n"); return 0; } static void CompileFunction( LLVMModuleRef module, char *parentStructName, LLVMTypeRef wStructPointerType, Node **fieldDeclarations, uint32_t fieldDeclarationCount, Node *functionDeclaration ) { uint32_t i; uint8_t hasReturn = 0; uint8_t isStatic = 0; Node *functionSignature = functionDeclaration->children[0]; Node *functionBody = functionDeclaration->children[1]; uint32_t argumentCount = functionSignature->children[2]->childCount; LLVMTypeRef paramTypes[argumentCount + 1]; uint32_t paramIndex = 0; if (functionSignature->children[3]->childCount > 0) { for (i = 0; i < functionSignature->children[3]->childCount; i += 1) { if (functionSignature->children[3]->children[i]->syntaxKind == StaticModifier) { isStatic = 1; break; } } } if (!isStatic) { paramTypes[paramIndex] = wStructPointerType; paramIndex += 1; } PushScopeFrame(scope); /* FIXME: should work for non-primitive types */ for (i = 0; i < functionSignature->children[2]->childCount; i += 1) { paramTypes[paramIndex] = WraithTypeToLLVMType(functionSignature->children[2]->children[i]->children[0]->children[0]->primitiveType); paramIndex += 1; } LLVMTypeRef returnType = WraithTypeToLLVMType(functionSignature->children[1]->children[0]->primitiveType); LLVMTypeRef functionType = LLVMFunctionType(returnType, paramTypes, paramIndex, 0); char *functionName = strdup(parentStructName); strcat(functionName, "_"); strcat(functionName, functionSignature->children[0]->value.string); LLVMValueRef function = LLVMAddFunction(module, functionName, functionType); free(functionName); DeclareStructFunction(wStructPointerType, function, returnType, isStatic, functionSignature->children[0]->value.string); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(function, "entry"); LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMPositionBuilderAtEnd(builder, entry); if (!isStatic) { LLVMValueRef wStructPointer = LLVMGetParam(function, 0); AddStructVariablesToScope(builder, wStructPointer); } for (i = 0; i < functionSignature->children[2]->childCount; i += 1) { char *ptrName = strdup(functionSignature->children[2]->children[i]->children[1]->value.string); strcat(ptrName, "_ptr"); LLVMValueRef argument = LLVMGetParam(function, i + !isStatic); LLVMValueRef argumentCopy = LLVMBuildAlloca(builder, LLVMTypeOf(argument), ptrName); LLVMBuildStore(builder, argument, argumentCopy); free(ptrName); AddLocalVariable(scope, argumentCopy, functionSignature->children[2]->children[i]->children[1]->value.string); } for (i = 0; i < functionBody->childCount; i += 1) { hasReturn |= CompileStatement(builder, function, functionBody->children[i]); } if (LLVMGetTypeKind(returnType) == LLVMVoidTypeKind && !hasReturn) { LLVMBuildRetVoid(builder); } else if (LLVMGetTypeKind(returnType) != LLVMVoidTypeKind && !hasReturn) { fprintf(stderr, "Return statement not provided!"); } PopScopeFrame(scope); LLVMDisposeBuilder(builder); } static void CompileStruct(LLVMModuleRef module, LLVMContextRef context, Node *node) { uint32_t i; uint32_t fieldCount = 0; uint32_t declarationCount = node->children[1]->childCount; uint8_t packed = 1; LLVMTypeRef types[declarationCount]; Node *currentDeclarationNode; Node *fieldDeclarations[declarationCount]; char *structName = node->children[0]->value.string; PushScopeFrame(scope); LLVMTypeRef wStructType = LLVMStructCreateNamed(context, structName); LLVMTypeRef wStructPointerType = LLVMPointerType(wStructType, 0); /* FIXME: is this address space correct? */ /* first, build the structure definition */ for (i = 0; i < declarationCount; i += 1) { currentDeclarationNode = node->children[1]->children[i]; switch (currentDeclarationNode->syntaxKind) { case Declaration: /* this is badly named */ types[fieldCount] = ResolveType(currentDeclarationNode->children[0]); fieldDeclarations[fieldCount] = currentDeclarationNode; fieldCount += 1; break; } } LLVMStructSetBody(wStructType, types, fieldCount, packed); AddStructDeclaration(wStructType, wStructPointerType, node->children[0]->value.string, fieldDeclarations, fieldCount); /* now we can wire up the functions */ for (i = 0; i < declarationCount; i += 1) { currentDeclarationNode = node->children[1]->children[i]; switch (currentDeclarationNode->syntaxKind) { case FunctionDeclaration: CompileFunction(module, structName, wStructPointerType, fieldDeclarations, fieldCount, currentDeclarationNode); break; } } PopScopeFrame(scope); } static void Compile(LLVMModuleRef module, LLVMContextRef context, Node *node) { uint32_t i; for (i = 0; i < node->childCount; i += 1) { if (node->children[i]->syntaxKind == StructDeclaration) { CompileStruct(module, context, node->children[i]); } else { fprintf(stderr, "top level declarations that are not structs are forbidden!\n"); } } } static int Build(char *inputFilename, uint32_t optimizationLevel) { scope = CreateScope(); structTypeDeclarations = NULL; structTypeDeclarationCount = 0; stack = CreateStack(); FILE *fp = fopen(inputFilename, "r"); yyin = fp; yyparse(fp, stack); fclose(fp); PrintTree(rootNode, 0); LLVMModuleRef module = LLVMModuleCreateWithName("my_module"); LLVMContextRef context = LLVMGetGlobalContext(); Compile(module, context, rootNode); /* add main call */ LLVMBuilderRef builder = LLVMCreateBuilder(); LLVMTypeRef mainFunctionType = LLVMFunctionType(LLVMInt64Type(), NULL, 0, 0); LLVMValueRef mainFunction = LLVMAddFunction(module, "main", mainFunctionType); LLVMBasicBlockRef entry = LLVMAppendBasicBlock(mainFunction, "entry"); LLVMPositionBuilderAtEnd(builder, entry); LLVMValueRef wraithMainFunction = LLVMGetNamedFunction(module, "Program_Main"); LLVMValueRef mainResult = LLVMBuildCall(builder, wraithMainFunction, NULL, 0, "result"); LLVMBuildRet(builder, mainResult); LLVMDisposeBuilder(builder); /* verify */ char *error = NULL; if (LLVMVerifyModule(module, LLVMAbortProcessAction, &error) != 0) { fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); return EXIT_FAILURE; } /* prepare to emit assembly */ LLVMInitializeNativeTarget(); LLVMInitializeAllTargetInfos(); LLVMInitializeAllTargets(); LLVMInitializeAllTargetMCs(); LLVMInitializeAllAsmParsers(); LLVMInitializeAllAsmPrinters(); LLVMSetTarget(module, LLVM_DEFAULT_TARGET_TRIPLE); LLVMTargetRef target; if (LLVMGetTargetFromTriple(LLVM_DEFAULT_TARGET_TRIPLE, &target, &error) != 0) { fprintf(stderr, "Failed to get target!\n"); fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); return EXIT_FAILURE; } LLVMPassManagerRef passManager = LLVMCreatePassManager(); // LLVMAddInstructionCombiningPass(passManager); // LLVMAddCFGSimplificationPass(passManager); // LLVMAddReassociatePass(passManager); // LLVMAddPromoteMemoryToRegisterPass(passManager); LLVMPassManagerBuilderRef passManagerBuilder = LLVMPassManagerBuilderCreate(); LLVMPassManagerBuilderSetOptLevel(passManagerBuilder, optimizationLevel); LLVMPassManagerBuilderPopulateModulePassManager(passManagerBuilder, passManager); LLVMRunPassManager(passManager, module); if (LLVMWriteBitcodeToFile(module, "test.bc") != 0) { fprintf(stderr, "error writing bitcode to file\n"); return EXIT_FAILURE; } char *cpu = "generic"; char *features = ""; LLVMTargetMachineRef targetMachine = LLVMCreateTargetMachine( target, LLVM_DEFAULT_TARGET_TRIPLE, cpu, features, LLVMCodeGenLevelDefault, LLVMRelocDefault, LLVMCodeModelDefault ); if (LLVMTargetMachineEmitToFile(targetMachine, module, "test.o", LLVMObjectFile, &error) != 0) { fprintf(stderr, "Failed to emit machine code!\n"); fprintf(stderr, "%s\n", error); LLVMDisposeMessage(error); return EXIT_FAILURE; } LLVMDisposeMessage(error); LLVMDisposeTargetMachine(targetMachine); LLVMPassManagerBuilderDispose(passManagerBuilder); LLVMDisposePassManager(passManager); LLVMDisposeModule(module); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { dropt_bool showHelp; uint32_t optimizationLevel = 0; char *inputFilename; extern int yydebug; int exitCode = EXIT_SUCCESS; dropt_option options[] = { { 'h', "help", "Shows help.", NULL, dropt_handle_bool, &showHelp, dropt_attr_halt }, { 'O', "optimize", "Sets optimization level of the output IR. Must be a value between 0 and 3.", "number", dropt_handle_uint, &optimizationLevel }, { 0 } /* Required sentinel value. */ }; dropt_context *droptContext = dropt_new_context(options); if (droptContext == NULL) { exitCode = EXIT_FAILURE; } else if (argc == 0) { printf("Must supply an input file."); exitCode = EXIT_FAILURE; } else { char** rest = dropt_parse(droptContext, -1, &argv[1]); if (dropt_get_error(droptContext) != dropt_error_none) { fprintf(stderr, "wraith: %s\n", dropt_get_error_message(droptContext)); exitCode = EXIT_FAILURE; } else if (showHelp) { printf("Usage: wraith [options] [--] [input_file]\n\n" "Options:\n"); dropt_print_help(stdout, droptContext, NULL); } else { yydebug = 1; /* FIXME: make this an option */ inputFilename = *rest; if (inputFilename == NULL) { fprintf(stderr, "ERROR: Must provide an input file.\n"); exitCode = EXIT_FAILURE; } else { exitCode = Build(inputFilename, optimizationLevel); } } } return exitCode; }