├── .gitignore ├── Mutang.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── Mutang └── main.m ├── README.md └── laboratory ├── Makefile ├── main.bc ├── main.c ├── main.ll ├── sum.bc ├── sum.c └── sum.ll /.gitignore: -------------------------------------------------------------------------------- 1 | Mutang.xcodeproj/xcuserdata 2 | Mutang.xcodeproj/project.xcworkspace/xcuserdata 3 | -------------------------------------------------------------------------------- /Mutang.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 4642D8DC1CAB072400F1FFF2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 4642D8DB1CAB072400F1FFF2 /* main.m */; }; 11 | /* End PBXBuildFile section */ 12 | 13 | /* Begin PBXCopyFilesBuildPhase section */ 14 | 4642D8D61CAB072400F1FFF2 /* CopyFiles */ = { 15 | isa = PBXCopyFilesBuildPhase; 16 | buildActionMask = 2147483647; 17 | dstPath = /usr/share/man/man1/; 18 | dstSubfolderSpec = 0; 19 | files = ( 20 | ); 21 | runOnlyForDeploymentPostprocessing = 1; 22 | }; 23 | /* End PBXCopyFilesBuildPhase section */ 24 | 25 | /* Begin PBXFileReference section */ 26 | 4642D8D81CAB072400F1FFF2 /* Mutang */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Mutang; sourceTree = BUILT_PRODUCTS_DIR; }; 27 | 4642D8DB1CAB072400F1FFF2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 28 | /* End PBXFileReference section */ 29 | 30 | /* Begin PBXFrameworksBuildPhase section */ 31 | 4642D8D51CAB072400F1FFF2 /* Frameworks */ = { 32 | isa = PBXFrameworksBuildPhase; 33 | buildActionMask = 2147483647; 34 | files = ( 35 | ); 36 | runOnlyForDeploymentPostprocessing = 0; 37 | }; 38 | /* End PBXFrameworksBuildPhase section */ 39 | 40 | /* Begin PBXGroup section */ 41 | 4642D8CF1CAB072400F1FFF2 = { 42 | isa = PBXGroup; 43 | children = ( 44 | 4642D8DA1CAB072400F1FFF2 /* Mutang */, 45 | 4642D8D91CAB072400F1FFF2 /* Products */, 46 | ); 47 | sourceTree = ""; 48 | }; 49 | 4642D8D91CAB072400F1FFF2 /* Products */ = { 50 | isa = PBXGroup; 51 | children = ( 52 | 4642D8D81CAB072400F1FFF2 /* Mutang */, 53 | ); 54 | name = Products; 55 | sourceTree = ""; 56 | }; 57 | 4642D8DA1CAB072400F1FFF2 /* Mutang */ = { 58 | isa = PBXGroup; 59 | children = ( 60 | 4642D8DB1CAB072400F1FFF2 /* main.m */, 61 | ); 62 | path = Mutang; 63 | sourceTree = ""; 64 | }; 65 | /* End PBXGroup section */ 66 | 67 | /* Begin PBXNativeTarget section */ 68 | 4642D8D71CAB072400F1FFF2 /* Mutang */ = { 69 | isa = PBXNativeTarget; 70 | buildConfigurationList = 4642D8DF1CAB072400F1FFF2 /* Build configuration list for PBXNativeTarget "Mutang" */; 71 | buildPhases = ( 72 | 4642D8D41CAB072400F1FFF2 /* Sources */, 73 | 4642D8D51CAB072400F1FFF2 /* Frameworks */, 74 | 4642D8D61CAB072400F1FFF2 /* CopyFiles */, 75 | ); 76 | buildRules = ( 77 | ); 78 | dependencies = ( 79 | ); 80 | name = Mutang; 81 | productName = Mutang; 82 | productReference = 4642D8D81CAB072400F1FFF2 /* Mutang */; 83 | productType = "com.apple.product-type.tool"; 84 | }; 85 | /* End PBXNativeTarget section */ 86 | 87 | /* Begin PBXProject section */ 88 | 4642D8D01CAB072400F1FFF2 /* Project object */ = { 89 | isa = PBXProject; 90 | attributes = { 91 | LastUpgradeCheck = 0730; 92 | ORGANIZATIONNAME = lowlevelbits; 93 | TargetAttributes = { 94 | 4642D8D71CAB072400F1FFF2 = { 95 | CreatedOnToolsVersion = 7.3; 96 | }; 97 | }; 98 | }; 99 | buildConfigurationList = 4642D8D31CAB072400F1FFF2 /* Build configuration list for PBXProject "Mutang" */; 100 | compatibilityVersion = "Xcode 3.2"; 101 | developmentRegion = English; 102 | hasScannedForEncodings = 0; 103 | knownRegions = ( 104 | en, 105 | ); 106 | mainGroup = 4642D8CF1CAB072400F1FFF2; 107 | productRefGroup = 4642D8D91CAB072400F1FFF2 /* Products */; 108 | projectDirPath = ""; 109 | projectRoot = ""; 110 | targets = ( 111 | 4642D8D71CAB072400F1FFF2 /* Mutang */, 112 | ); 113 | }; 114 | /* End PBXProject section */ 115 | 116 | /* Begin PBXSourcesBuildPhase section */ 117 | 4642D8D41CAB072400F1FFF2 /* Sources */ = { 118 | isa = PBXSourcesBuildPhase; 119 | buildActionMask = 2147483647; 120 | files = ( 121 | 4642D8DC1CAB072400F1FFF2 /* main.m in Sources */, 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | /* End PBXSourcesBuildPhase section */ 126 | 127 | /* Begin XCBuildConfiguration section */ 128 | 4642D8DD1CAB072400F1FFF2 /* Debug */ = { 129 | isa = XCBuildConfiguration; 130 | buildSettings = { 131 | ALWAYS_SEARCH_USER_PATHS = NO; 132 | CLANG_ANALYZER_NONNULL = YES; 133 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 134 | CLANG_CXX_LIBRARY = "libc++"; 135 | CLANG_ENABLE_MODULES = YES; 136 | CLANG_ENABLE_OBJC_ARC = YES; 137 | CLANG_WARN_BOOL_CONVERSION = YES; 138 | CLANG_WARN_CONSTANT_CONVERSION = YES; 139 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 140 | CLANG_WARN_EMPTY_BODY = YES; 141 | CLANG_WARN_ENUM_CONVERSION = YES; 142 | CLANG_WARN_INT_CONVERSION = YES; 143 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 144 | CLANG_WARN_UNREACHABLE_CODE = YES; 145 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 146 | CODE_SIGN_IDENTITY = "-"; 147 | COPY_PHASE_STRIP = NO; 148 | DEBUG_INFORMATION_FORMAT = dwarf; 149 | ENABLE_STRICT_OBJC_MSGSEND = YES; 150 | ENABLE_TESTABILITY = YES; 151 | GCC_C_LANGUAGE_STANDARD = gnu99; 152 | GCC_DYNAMIC_NO_PIC = NO; 153 | GCC_NO_COMMON_BLOCKS = YES; 154 | GCC_OPTIMIZATION_LEVEL = 0; 155 | GCC_PREPROCESSOR_DEFINITIONS = ( 156 | "DEBUG=1", 157 | "$(inherited)", 158 | ); 159 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 160 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 161 | GCC_WARN_UNDECLARED_SELECTOR = YES; 162 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 163 | GCC_WARN_UNUSED_FUNCTION = YES; 164 | GCC_WARN_UNUSED_VARIABLE = YES; 165 | LLVM_BUILD_DIR = /Users/alexdenisov/Projects/LLVM/build_static; 166 | LLVM_LIBS = "-lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoCodeView -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMInstrumentation -lLLVMProfileData -lLLVMTransformUtils -lLLVMBitWriter -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMExecutionEngine -lLLVMTarget -lLLVMAnalysis -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMMC -lLLVMCore -lLLVMSupport -lLLVMLinker"; 167 | LLVM_SOURCE_DIR = /Users/alexdenisov/Projects/LLVM/llvm; 168 | MACOSX_DEPLOYMENT_TARGET = 10.11; 169 | MTL_ENABLE_DEBUG_INFO = YES; 170 | ONLY_ACTIVE_ARCH = YES; 171 | SDKROOT = macosx; 172 | }; 173 | name = Debug; 174 | }; 175 | 4642D8DE1CAB072400F1FFF2 /* Release */ = { 176 | isa = XCBuildConfiguration; 177 | buildSettings = { 178 | ALWAYS_SEARCH_USER_PATHS = NO; 179 | CLANG_ANALYZER_NONNULL = YES; 180 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 181 | CLANG_CXX_LIBRARY = "libc++"; 182 | CLANG_ENABLE_MODULES = YES; 183 | CLANG_ENABLE_OBJC_ARC = YES; 184 | CLANG_WARN_BOOL_CONVERSION = YES; 185 | CLANG_WARN_CONSTANT_CONVERSION = YES; 186 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 187 | CLANG_WARN_EMPTY_BODY = YES; 188 | CLANG_WARN_ENUM_CONVERSION = YES; 189 | CLANG_WARN_INT_CONVERSION = YES; 190 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 191 | CLANG_WARN_UNREACHABLE_CODE = YES; 192 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 193 | CODE_SIGN_IDENTITY = "-"; 194 | COPY_PHASE_STRIP = NO; 195 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 196 | ENABLE_NS_ASSERTIONS = NO; 197 | ENABLE_STRICT_OBJC_MSGSEND = YES; 198 | GCC_C_LANGUAGE_STANDARD = gnu99; 199 | GCC_NO_COMMON_BLOCKS = YES; 200 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 201 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 202 | GCC_WARN_UNDECLARED_SELECTOR = YES; 203 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 204 | GCC_WARN_UNUSED_FUNCTION = YES; 205 | GCC_WARN_UNUSED_VARIABLE = YES; 206 | LLVM_BUILD_DIR = /Users/alexdenisov/Projects/LLVM/build_static; 207 | LLVM_LIBS = "-lLLVMX86Disassembler -lLLVMX86AsmParser -lLLVMX86CodeGen -lLLVMSelectionDAG -lLLVMAsmPrinter -lLLVMDebugInfoCodeView -lLLVMCodeGen -lLLVMScalarOpts -lLLVMInstCombine -lLLVMInstrumentation -lLLVMProfileData -lLLVMTransformUtils -lLLVMBitWriter -lLLVMX86Desc -lLLVMMCDisassembler -lLLVMX86Info -lLLVMX86AsmPrinter -lLLVMX86Utils -lLLVMMCJIT -lLLVMExecutionEngine -lLLVMTarget -lLLVMAnalysis -lLLVMRuntimeDyld -lLLVMObject -lLLVMMCParser -lLLVMBitReader -lLLVMMC -lLLVMCore -lLLVMSupport -lLLVMLinker"; 208 | LLVM_SOURCE_DIR = /Users/alexdenisov/Projects/LLVM/llvm; 209 | MACOSX_DEPLOYMENT_TARGET = 10.11; 210 | MTL_ENABLE_DEBUG_INFO = NO; 211 | SDKROOT = macosx; 212 | }; 213 | name = Release; 214 | }; 215 | 4642D8E01CAB072400F1FFF2 /* Debug */ = { 216 | isa = XCBuildConfiguration; 217 | buildSettings = { 218 | GCC_PREPROCESSOR_DEFINITIONS = ( 219 | __STDC_CONSTANT_MACROS, 220 | __STDC_LIMIT_MACROS, 221 | ); 222 | HEADER_SEARCH_PATHS = /usr/local/include; 223 | LIBRARY_SEARCH_PATHS = ( 224 | "$(LLVM_BUILD_DIR)/lib", 225 | /usr/local/lib, 226 | ); 227 | OTHER_LDFLAGS = ( 228 | "$(LLVM_LIBS)", 229 | "-lc++", 230 | "-lz", 231 | "-ltermcap", 232 | "-lgit2", 233 | ); 234 | PRODUCT_NAME = "$(TARGET_NAME)"; 235 | USER_HEADER_SEARCH_PATHS = "$(LLVM_SOURCE_DIR)/include $(LLVM_BUILD_DIR)/include"; 236 | }; 237 | name = Debug; 238 | }; 239 | 4642D8E11CAB072400F1FFF2 /* Release */ = { 240 | isa = XCBuildConfiguration; 241 | buildSettings = { 242 | GCC_PREPROCESSOR_DEFINITIONS = ( 243 | __STDC_CONSTANT_MACROS, 244 | __STDC_LIMIT_MACROS, 245 | ); 246 | HEADER_SEARCH_PATHS = /usr/local/include; 247 | LIBRARY_SEARCH_PATHS = ( 248 | "$(LLVM_BUILD_DIR)/lib", 249 | /usr/local/lib, 250 | ); 251 | OTHER_LDFLAGS = ( 252 | "$(LLVM_LIBS)", 253 | "-lc++", 254 | "-lz", 255 | "-ltermcap", 256 | "-lgit2", 257 | ); 258 | PRODUCT_NAME = "$(TARGET_NAME)"; 259 | USER_HEADER_SEARCH_PATHS = "$(LLVM_SOURCE_DIR)/include $(LLVM_BUILD_DIR)/include"; 260 | }; 261 | name = Release; 262 | }; 263 | /* End XCBuildConfiguration section */ 264 | 265 | /* Begin XCConfigurationList section */ 266 | 4642D8D31CAB072400F1FFF2 /* Build configuration list for PBXProject "Mutang" */ = { 267 | isa = XCConfigurationList; 268 | buildConfigurations = ( 269 | 4642D8DD1CAB072400F1FFF2 /* Debug */, 270 | 4642D8DE1CAB072400F1FFF2 /* Release */, 271 | ); 272 | defaultConfigurationIsVisible = 0; 273 | defaultConfigurationName = Release; 274 | }; 275 | 4642D8DF1CAB072400F1FFF2 /* Build configuration list for PBXNativeTarget "Mutang" */ = { 276 | isa = XCConfigurationList; 277 | buildConfigurations = ( 278 | 4642D8E01CAB072400F1FFF2 /* Debug */, 279 | 4642D8E11CAB072400F1FFF2 /* Release */, 280 | ); 281 | defaultConfigurationIsVisible = 0; 282 | defaultConfigurationName = Release; 283 | }; 284 | /* End XCConfigurationList section */ 285 | }; 286 | rootObject = 4642D8D01CAB072400F1FFF2 /* Project object */; 287 | } 288 | -------------------------------------------------------------------------------- /Mutang.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Mutang/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Mutang 4 | // 5 | // Created by AlexDenisov on 29/03/16. 6 | // Copyright © 2016 lowlevelbits. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include 16 | 17 | @import LLVM_C; 18 | 19 | LLVMModuleRef newModule(const char *path) { 20 | LLVMMemoryBufferRef buffer; 21 | char *message; 22 | if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buffer, &message)) { 23 | printf("Can't create buffer: %s\n", message); 24 | exit(1); 25 | } 26 | 27 | LLVMModuleRef module; 28 | if (LLVMParseBitcode2(buffer, &module)) { 29 | printf("Can't get Bitcode\n"); 30 | exit(1); 31 | } 32 | 33 | LLVMDisposeMemoryBuffer(buffer); 34 | 35 | return module; 36 | } 37 | 38 | LLVMValueRef firstTestFromModule(LLVMModuleRef module) { 39 | LLVMValueRef currentFunction = LLVMGetFirstFunction(module); 40 | 41 | while (currentFunction) { 42 | const char *name = LLVMGetValueName(currentFunction); 43 | if (LLVMIsDeclaration(currentFunction)) { 44 | // skip declarations, since we interested only in functions with body 45 | currentFunction = LLVMGetNextFunction(currentFunction); 46 | continue; 47 | } 48 | 49 | if (strncmp(name, "test", strlen("test")) == 0) { 50 | break; 51 | } 52 | 53 | currentFunction = LLVMGetNextFunction(currentFunction); 54 | } 55 | 56 | return currentFunction; 57 | } 58 | 59 | bool hasSources(const char *functionName) { 60 | if (strncmp(functionName, "llvm", strlen("llvm")) == 0) { 61 | return false; 62 | } 63 | 64 | return true; 65 | } 66 | 67 | const char *firstMutationFunctionNameForTestFunction(LLVMValueRef testFunction) { 68 | assert(LLVMIsAFunction(testFunction)); 69 | assert(LLVMCountBasicBlocks(testFunction)); 70 | 71 | LLVMBasicBlockRef basicBlock = LLVMGetFirstBasicBlock(testFunction); 72 | 73 | while (basicBlock) { 74 | LLVMValueRef instruction = LLVMGetFirstInstruction(basicBlock); 75 | while (instruction) { 76 | if (LLVMIsACallInst(instruction)) { 77 | assert(LLVMGetNumOperands(instruction)); 78 | 79 | int functionOperand = LLVMGetNumOperands(instruction) - 1; 80 | LLVMValueRef functionDeclaration = LLVMGetOperand(instruction, functionOperand); 81 | 82 | const char *functionName = LLVMGetValueName(functionDeclaration); 83 | if (hasSources(functionName)) { 84 | return functionName; 85 | } 86 | } 87 | 88 | instruction = LLVMGetNextInstruction(instruction); 89 | } 90 | 91 | basicBlock = LLVMGetNextBasicBlock(basicBlock); 92 | } 93 | 94 | return ""; 95 | } 96 | 97 | LLVMModuleRef copyOfModuleWithoutFunction(LLVMModuleRef module, const char *name) { 98 | LLVMModuleRef copyOfModule = LLVMCloneModule(module); 99 | LLVMValueRef function = LLVMGetNamedFunction(copyOfModule, name); 100 | 101 | LLVMDeleteFunction(function); 102 | 103 | return copyOfModule; 104 | } 105 | 106 | LLVMModuleRef copyOfModuleWithFunctionOnly(LLVMModuleRef module, const char *functionName) { 107 | LLVMModuleRef copyOfModule = LLVMCloneModule(module); 108 | 109 | LLVMValueRef currentFunction = LLVMGetFirstFunction(copyOfModule); 110 | 111 | while (currentFunction) { 112 | const char *name = LLVMGetValueName(currentFunction); 113 | if (LLVMIsDeclaration(currentFunction)) { 114 | // skip declarations, since we interested only in functions with body 115 | currentFunction = LLVMGetNextFunction(currentFunction); 116 | continue; 117 | } 118 | 119 | if (strcmp(name, functionName)) { 120 | LLVMValueRef functionToDelete = currentFunction; 121 | currentFunction = LLVMGetNextFunction(currentFunction); 122 | LLVMDeleteFunction(functionToDelete); 123 | continue; 124 | } 125 | 126 | currentFunction = LLVMGetNextFunction(currentFunction); 127 | } 128 | 129 | return copyOfModule; 130 | } 131 | 132 | void dumpMetadataRecursively(LLVMValueRef mdNode) { 133 | if (!mdNode) { 134 | return; 135 | } 136 | 137 | // LLVMDumpValue(mdNode); 138 | 139 | if (DILocationKind == LLVMGetMetadataKind(mdNode)) { 140 | printf("%s/%s:%d,%d\n", LLVMGetDILocationDirectory(mdNode), LLVMGetDILocationFilename(mdNode), LLVMGetDILocationLineNumber(mdNode), LLVMGetDILocationColumn(mdNode)); 141 | } 142 | 143 | 144 | if (LLVMIsAMDString(mdNode)) { 145 | // unsigned int size = 0; 146 | // const char *s = LLVMGetMDString(mdNode, &size); 147 | // printf("%d %s\n", LLVMGetMetadataKind(mdNode), s); 148 | return; 149 | } 150 | 151 | unsigned int numDebugOperands = LLVMGetMDNodeNumOperands(mdNode); 152 | if (numDebugOperands) { 153 | LLVMValueRef *debugOperands = calloc(numDebugOperands, sizeof(LLVMValueRef)); 154 | LLVMGetMDNodeOperands(mdNode, debugOperands); 155 | 156 | for (int i = 0; i < numDebugOperands; i++) { 157 | dumpMetadataRecursively(debugOperands[i]); 158 | } 159 | 160 | free(debugOperands); 161 | } 162 | } 163 | 164 | struct MutationPoint { 165 | LLVMValueRef function; 166 | LLVMBasicBlockRef basicBlock; 167 | LLVMValueRef instruction; 168 | }; 169 | 170 | struct MutationPoint mutationPointForMutationFromFunction(LLVMValueRef function) { 171 | LLVMBasicBlockRef basicBlock = LLVMGetFirstBasicBlock(function); 172 | LLVMValueRef instruction = NULL; 173 | 174 | while (basicBlock) { 175 | instruction = LLVMGetFirstInstruction(basicBlock); 176 | while (instruction) { 177 | if (LLVMIsABinaryOperator(instruction)) { 178 | break; 179 | } 180 | 181 | instruction = LLVMGetNextInstruction(instruction); 182 | } 183 | 184 | if (instruction) { 185 | break; 186 | } 187 | 188 | basicBlock = LLVMGetNextBasicBlock(basicBlock); 189 | } 190 | 191 | struct MutationPoint mutationPoint = { .function = function, .basicBlock = basicBlock, .instruction = instruction }; 192 | 193 | return mutationPoint; 194 | } 195 | 196 | struct MutationPoint makeMutationAtMutationPoint(struct MutationPoint mutationPoint) { 197 | LLVMValueRef function = mutationPoint.function; 198 | LLVMBasicBlockRef basicBlock = mutationPoint.basicBlock; 199 | LLVMValueRef instruction = mutationPoint.instruction; 200 | 201 | LLVMBuilderRef builder = LLVMCreateBuilder(); 202 | LLVMPositionBuilder(builder, basicBlock, instruction); 203 | 204 | LLVMValueRef mutant = LLVMBuildNSWSub(builder, LLVMGetOperand(instruction, 0), LLVMGetOperand(instruction, 1), LLVMGetValueName(instruction)); 205 | 206 | LLVMReplaceAllUsesWith(instruction, mutant); 207 | LLVMInstructionEraseFromParent(instruction); 208 | 209 | struct MutationPoint mutatedPoint = { .function = function, .basicBlock = basicBlock, .instruction = mutant }; 210 | 211 | return mutatedPoint; 212 | } 213 | 214 | unsigned long long runFunction(LLVMValueRef function, LLVMModuleRef modules[], int modulesSize, LLVMModuleRef extraModule) { 215 | LLVMModuleRef firstModule = modules[0]; 216 | 217 | char *error = NULL; 218 | LLVMExecutionEngineRef executionEngine; 219 | if (LLVMCreateExecutionEngineForModule(&executionEngine, firstModule, &error) != 0 ) { 220 | printf("Can't initialize engine: %s\n", error); 221 | // TODO: cleanup all allocated memory ;) 222 | exit(1); 223 | } 224 | 225 | for (int i = 1; i < modulesSize; i++) { 226 | LLVMAddModule(executionEngine, modules[i]); 227 | } 228 | 229 | LLVMAddModule(executionEngine, extraModule); 230 | 231 | LLVMGenericValueRef value = LLVMRunFunction(executionEngine, function, 0, NULL); 232 | unsigned long long result = LLVMGenericValueToInt(value, 0); 233 | 234 | LLVMModuleRef _dummy; 235 | 236 | LLVMRemoveModule(executionEngine, extraModule, &_dummy, NULL); 237 | 238 | return result; 239 | } 240 | 241 | char *sourceForModule(LLVMModuleRef module) { 242 | const char *directory = LLVMGetModuleDirectory(module); 243 | const char *filename = LLVMGetModuleFilename(module); 244 | 245 | char fullname[100]; 246 | strcpy(fullname, directory); 247 | strcat(fullname, "/"); 248 | strcat(fullname, filename); 249 | 250 | FILE *sourceFile = fopen(fullname, "rb"); 251 | if (!sourceFile) { 252 | printf("can't open file %s: %s\n", fullname, strerror(errno)); 253 | return NULL; 254 | } 255 | 256 | fseek(sourceFile, 0, SEEK_END); 257 | long size = ftell(sourceFile); 258 | fseek(sourceFile, 0, SEEK_SET); 259 | 260 | char *source = calloc(size, sizeof(char)); 261 | fread(source, sizeof(char), size, sourceFile); 262 | 263 | fclose(sourceFile); 264 | 265 | return source; 266 | } 267 | 268 | char *highlevelMutantRepresentation(const char *originalSource, struct MutationPoint mutationPoint) { 269 | assert(LLVMHasMetadata(mutationPoint.instruction)); 270 | 271 | LLVMValueRef metadata = LLVMGetMetadata(mutationPoint.instruction, 0); 272 | 273 | const unsigned int line = LLVMGetDILocationLineNumber(metadata); 274 | const unsigned int column = LLVMGetDILocationColumn(metadata); 275 | 276 | char *mutationSource = calloc(strlen(originalSource), sizeof(char)); 277 | strcpy(mutationSource, originalSource); 278 | 279 | unsigned int currentLine = 1; 280 | 281 | char *curChar = mutationSource; 282 | while ( (*(curChar++) != '\0') ) { 283 | if (currentLine == line) { 284 | *(curChar + column - 1) = '-'; 285 | break; 286 | } 287 | 288 | if (*curChar == '\n') { 289 | currentLine++; 290 | } 291 | } 292 | 293 | return mutationSource; 294 | } 295 | 296 | int mutang_diff_callback(const git_diff_delta *delta, 297 | const git_diff_hunk *hunk, 298 | const git_diff_line *line, 299 | void *payload) { 300 | FILE *fp = payload ? payload : stdout; 301 | 302 | if (line->origin == GIT_DIFF_LINE_FILE_HDR) { 303 | fwrite("--- ", 1, strlen("--- "), fp); 304 | fwrite("a/", 1, strlen("a/"), fp); 305 | fwrite(delta->old_file.path, 1, strlen(delta->old_file.path), fp); 306 | fwrite("\n", 1, strlen("\n"), fp); 307 | 308 | fwrite("--- ", 1, strlen("--- "), fp); 309 | fwrite("b/", 1, strlen("b/"), fp); 310 | fwrite(delta->new_file.path, 1, strlen(delta->new_file.path), fp); 311 | fwrite("\n", 1, strlen("\n"), fp); 312 | return 0; 313 | } 314 | 315 | if (line->origin == GIT_DIFF_LINE_HUNK_HDR) { 316 | fwrite(line->content, 1, line->content_len, fp); 317 | return 0; 318 | } 319 | 320 | if (line->origin != GIT_DIFF_LINE_CONTEXT && 321 | line->origin != GIT_DIFF_LINE_ADDITION && 322 | line->origin != GIT_DIFF_LINE_DELETION) { 323 | return 0; 324 | } 325 | 326 | fputc(line->origin, fp); 327 | fwrite(line->content, 1, line->content_len, fp); 328 | return 0; 329 | } 330 | 331 | int main(int argc, const char * argv[]) { 332 | assert(argc == 2); 333 | 334 | char moduleWithTestPath[100]; 335 | char moduleWithTesteePath[100]; 336 | 337 | const char *laboratoryPath = argv[1]; 338 | 339 | strcpy(moduleWithTestPath, laboratoryPath); 340 | strcpy(moduleWithTesteePath, laboratoryPath); 341 | 342 | strcat(moduleWithTestPath, "/main.bc"); 343 | strcat(moduleWithTesteePath, "/sum.bc"); 344 | 345 | const LLVMModuleRef moduleWithTest = newModule(moduleWithTestPath); 346 | const LLVMModuleRef moduleWithTestee = newModule(moduleWithTesteePath); 347 | 348 | LLVMValueRef testFunction = firstTestFromModule(moduleWithTest); 349 | const char *mutationFunctionName = firstMutationFunctionNameForTestFunction(testFunction); 350 | 351 | LLVMModuleRef testeeModuleWithoutTestee = copyOfModuleWithoutFunction(moduleWithTestee, mutationFunctionName); 352 | 353 | LLVMModuleRef moduleWithMutation = copyOfModuleWithFunctionOnly(moduleWithTestee, mutationFunctionName); 354 | 355 | LLVMValueRef functionForMutation = LLVMGetNamedFunction(moduleWithMutation, mutationFunctionName); 356 | 357 | struct MutationPoint mutationPoint = mutationPointForMutationFromFunction(functionForMutation); 358 | __unused struct MutationPoint mutatedPoint = makeMutationAtMutationPoint(mutationPoint); 359 | 360 | char *originalSource = sourceForModule(moduleWithMutation); 361 | char *mutantSource = highlevelMutantRepresentation(originalSource, mutationPoint); 362 | 363 | git_libgit2_init(); 364 | 365 | git_patch *patch; 366 | 367 | git_patch_from_buffers(&patch, 368 | originalSource, strlen(originalSource), LLVMGetModuleFilename(moduleWithMutation), 369 | mutantSource, strlen(mutantSource), LLVMGetModuleFilename(moduleWithMutation), 370 | NULL); 371 | 372 | git_patch_print(patch, mutang_diff_callback, NULL); 373 | 374 | git_patch_free(patch); 375 | 376 | git_libgit2_shutdown(); 377 | 378 | free(originalSource); 379 | free(mutantSource); 380 | 381 | LLVMLinkInMCJIT(); 382 | LLVMInitializeNativeTarget(); 383 | LLVMInitializeNativeAsmPrinter(); 384 | 385 | LLVMModuleRef modules[] = { moduleWithTest, testeeModuleWithoutTestee }; 386 | 387 | unsigned long long initialResult = runFunction(testFunction, modules, 2, moduleWithTestee); 388 | unsigned long long mutatedResult = runFunction(testFunction, modules, 2, moduleWithMutation); 389 | 390 | if (initialResult != mutatedResult) { 391 | printf("mutant killed\n"); 392 | } else { 393 | printf("mutant survived\n"); 394 | } 395 | 396 | LLVMDisposeModule(moduleWithTest); 397 | LLVMDisposeModule(moduleWithTestee); 398 | LLVMDisposeModule(moduleWithMutation); 399 | LLVMDisposeModule(testeeModuleWithoutTestee); 400 | 401 | return 0; 402 | } 403 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # LLVM-based Mutation Testing System. Proof of Concept 2 | 3 | This is just a proof of concept. It is not intended to be runnable on your machine since it uses 'slightly forked' LLVM. 4 | 5 | You can find out more here: http://lowlevelbits.org/llvm-based-mutation-testing-system/ 6 | 7 | ### High level input 8 | 9 | ```c 10 | // main.c 11 | extern int sum(int a, int b); 12 | 13 | int test_main() { 14 | int result = sum(3, 5); 15 | int result_matches = result == 8; 16 | 17 | return result_matches; 18 | } 19 | ``` 20 | 21 | ```c 22 | // sum.c 23 | int someUnusedFucntion() { 24 | return 42.f; 25 | } 26 | 27 | int sum(int a, int b) { 28 | return a + b; 29 | } 30 | ``` 31 | 32 | ### Low level input 33 | 34 | ```ll 35 | ; ModuleID = 'main.c' 36 | target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 37 | target triple = "x86_64-apple-macosx10.11.0" 38 | 39 | ; Function Attrs: nounwind ssp uwtable 40 | define i32 @test_main() #0 !dbg !4 { 41 | entry: 42 | %result = alloca i32, align 4 43 | %result_matches = alloca i32, align 4 44 | %call = call i32 @sum(i32 3, i32 5), !dbg !10 45 | store i32 %call, i32* %result, align 4, !dbg !11 46 | %0 = load i32, i32* %result, align 4, !dbg !12 47 | %cmp = icmp eq i32 %0, 8, !dbg !13 48 | %conv = zext i1 %cmp to i32, !dbg !13 49 | store i32 %conv, i32* %result_matches, align 4, !dbg !14 50 | %1 = load i32, i32* %result_matches, align 4, !dbg !15 51 | ret i32 %1, !dbg !16 52 | } 53 | 54 | declare i32 @sum(i32, i32) #1 55 | 56 | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" } 57 | attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" } 58 | 59 | !llvm.dbg.cu = !{!0} 60 | !llvm.module.flags = !{!6, !7, !8} 61 | !llvm.ident = !{!9} 62 | 63 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)", isOptimized: false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3) 64 | !1 = !DIFile(filename: "main.c", directory: "/Users/alexdenisov/Projects/LLVM/Mutang/laboratory") 65 | !2 = !{} 66 | !3 = !{!4} 67 | !4 = distinct !DISubprogram(name: "test_main", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: false, variables: !2) 68 | !5 = !DISubroutineType(types: !2) 69 | !6 = !{i32 2, !"Dwarf Version", i32 2} 70 | !7 = !{i32 2, !"Debug Info Version", i32 3} 71 | !8 = !{i32 1, !"PIC Level", i32 2} 72 | !9 = !{!"clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)"} 73 | !10 = !DILocation(line: 4, column: 16, scope: !4) 74 | !11 = !DILocation(line: 4, column: 7, scope: !4) 75 | !12 = !DILocation(line: 5, column: 24, scope: !4) 76 | !13 = !DILocation(line: 5, column: 31, scope: !4) 77 | !14 = !DILocation(line: 5, column: 7, scope: !4) 78 | ``` 79 | 80 | ```ll 81 | ; ModuleID = 'sum.c' 82 | target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 83 | target triple = "x86_64-apple-macosx10.11.0" 84 | 85 | ; Function Attrs: nounwind ssp uwtable 86 | define i32 @someUnusedFucntion() #0 !dbg !4 { 87 | entry: 88 | ret i32 42, !dbg !11 89 | } 90 | 91 | ; Function Attrs: nounwind ssp uwtable 92 | define i32 @sum(i32 %a, i32 %b) #0 !dbg !6 { 93 | entry: 94 | %a.addr = alloca i32, align 4 95 | %b.addr = alloca i32, align 4 96 | store i32 %a, i32* %a.addr, align 4 97 | store i32 %b, i32* %b.addr, align 4 98 | %0 = load i32, i32* %a.addr, align 4, !dbg !12 99 | %1 = load i32, i32* %b.addr, align 4, !dbg !13 100 | %add = add nsw i32 %0, %1, !dbg !14 101 | ret i32 %add, !dbg !15 102 | } 103 | 104 | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" } 105 | 106 | !llvm.dbg.cu = !{!0} 107 | !llvm.module.flags = !{!7, !8, !9} 108 | !llvm.ident = !{!10} 109 | 110 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)", isOptimized: false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3) 111 | !1 = !DIFile(filename: "sum.c", directory: "/Users/alexdenisov/Projects/LLVM/Mutang/laboratory") 112 | !2 = !{} 113 | !3 = !{!4, !6} 114 | !4 = distinct !DISubprogram(name: "someUnusedFucntion", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2) 115 | !5 = !DISubroutineType(types: !2) 116 | !6 = distinct !DISubprogram(name: "sum", scope: !1, file: !1, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, variables: !2) 117 | !7 = !{i32 2, !"Dwarf Version", i32 2} 118 | !8 = !{i32 2, !"Debug Info Version", i32 3} 119 | !9 = !{i32 1, !"PIC Level", i32 2} 120 | !10 = !{!"clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)"} 121 | !11 = !DILocation(line: 2, column: 3, scope: !4) 122 | !12 = !DILocation(line: 6, column: 10, scope: !6) 123 | !13 = !DILocation(line: 6, column: 14, scope: !6) 124 | !14 = !DILocation(line: 6, column: 12, scope: !6) 125 | !15 = !DILocation(line: 6, column: 3, scope: !6) 126 | ``` 127 | 128 | ### System Output 129 | 130 | ```txt 131 | --- a/sum.c 132 | --- b/sum.c 133 | @@ -3,6 +3,6 @@ int someUnusedFucntion() { 134 | } 135 | 136 | int sum(int a, int b) { 137 | - return a + b; 138 | + return a - b; 139 | } 140 | 141 | mutant killed 142 | ``` 143 | -------------------------------------------------------------------------------- /laboratory/Makefile: -------------------------------------------------------------------------------- 1 | CC=~/Projects/LLVM/build_static/bin/clang 2 | 3 | all: 4 | $(CC) -c -emit-llvm -g main.c sum.c 5 | $(CC) -S -emit-llvm -gline-tables-only main.c sum.c 6 | -------------------------------------------------------------------------------- /laboratory/main.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDenisov/mutation-testing-poc/b596d2742a1485b6fc53f0cdc33d72a0f8336440/laboratory/main.bc -------------------------------------------------------------------------------- /laboratory/main.c: -------------------------------------------------------------------------------- 1 | extern int sum(int a, int b); 2 | 3 | int test_main() { 4 | int result = sum(3, 5); 5 | int result_matches = result == 8; 6 | 7 | return result_matches; 8 | } 9 | 10 | -------------------------------------------------------------------------------- /laboratory/main.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'main.c' 2 | target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 3 | target triple = "x86_64-apple-macosx10.11.0" 4 | 5 | ; Function Attrs: nounwind ssp uwtable 6 | define i32 @test_main() #0 !dbg !4 { 7 | entry: 8 | %result = alloca i32, align 4 9 | %result_matches = alloca i32, align 4 10 | %call = call i32 @sum(i32 3, i32 5), !dbg !10 11 | store i32 %call, i32* %result, align 4, !dbg !11 12 | %0 = load i32, i32* %result, align 4, !dbg !12 13 | %cmp = icmp eq i32 %0, 8, !dbg !13 14 | %conv = zext i1 %cmp to i32, !dbg !13 15 | store i32 %conv, i32* %result_matches, align 4, !dbg !14 16 | %1 = load i32, i32* %result_matches, align 4, !dbg !15 17 | ret i32 %1, !dbg !16 18 | } 19 | 20 | declare i32 @sum(i32, i32) #1 21 | 22 | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" } 23 | attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" } 24 | 25 | !llvm.dbg.cu = !{!0} 26 | !llvm.module.flags = !{!6, !7, !8} 27 | !llvm.ident = !{!9} 28 | 29 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)", isOptimized: false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3) 30 | !1 = !DIFile(filename: "main.c", directory: "/Users/alexdenisov/Projects/LLVM/Mutang/laboratory") 31 | !2 = !{} 32 | !3 = !{!4} 33 | !4 = distinct !DISubprogram(name: "test_main", scope: !1, file: !1, line: 3, type: !5, isLocal: false, isDefinition: true, scopeLine: 3, isOptimized: false, variables: !2) 34 | !5 = !DISubroutineType(types: !2) 35 | !6 = !{i32 2, !"Dwarf Version", i32 2} 36 | !7 = !{i32 2, !"Debug Info Version", i32 3} 37 | !8 = !{i32 1, !"PIC Level", i32 2} 38 | !9 = !{!"clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)"} 39 | !10 = !DILocation(line: 4, column: 16, scope: !4) 40 | !11 = !DILocation(line: 4, column: 7, scope: !4) 41 | !12 = !DILocation(line: 5, column: 24, scope: !4) 42 | !13 = !DILocation(line: 5, column: 31, scope: !4) 43 | !14 = !DILocation(line: 5, column: 7, scope: !4) 44 | !15 = !DILocation(line: 7, column: 10, scope: !4) 45 | !16 = !DILocation(line: 7, column: 3, scope: !4) 46 | -------------------------------------------------------------------------------- /laboratory/sum.bc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AlexDenisov/mutation-testing-poc/b596d2742a1485b6fc53f0cdc33d72a0f8336440/laboratory/sum.bc -------------------------------------------------------------------------------- /laboratory/sum.c: -------------------------------------------------------------------------------- 1 | int someUnusedFucntion() { 2 | return 42.f; 3 | } 4 | 5 | int sum(int a, int b) { 6 | return a + b; 7 | } 8 | 9 | -------------------------------------------------------------------------------- /laboratory/sum.ll: -------------------------------------------------------------------------------- 1 | ; ModuleID = 'sum.c' 2 | target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128" 3 | target triple = "x86_64-apple-macosx10.11.0" 4 | 5 | ; Function Attrs: nounwind ssp uwtable 6 | define i32 @someUnusedFucntion() #0 !dbg !4 { 7 | entry: 8 | ret i32 42, !dbg !11 9 | } 10 | 11 | ; Function Attrs: nounwind ssp uwtable 12 | define i32 @sum(i32 %a, i32 %b) #0 !dbg !6 { 13 | entry: 14 | %a.addr = alloca i32, align 4 15 | %b.addr = alloca i32, align 4 16 | store i32 %a, i32* %a.addr, align 4 17 | store i32 %b, i32* %b.addr, align 4 18 | %0 = load i32, i32* %a.addr, align 4, !dbg !12 19 | %1 = load i32, i32* %b.addr, align 4, !dbg !13 20 | %add = add nsw i32 %0, %1, !dbg !14 21 | ret i32 %add, !dbg !15 22 | } 23 | 24 | attributes #0 = { nounwind ssp uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="core2" "target-features"="+cx16,+fxsr,+mmx,+sse,+sse2,+sse3,+ssse3" "unsafe-fp-math"="false" "use-soft-float"="false" } 25 | 26 | !llvm.dbg.cu = !{!0} 27 | !llvm.module.flags = !{!7, !8, !9} 28 | !llvm.ident = !{!10} 29 | 30 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)", isOptimized: false, runtimeVersion: 0, emissionKind: 2, enums: !2, subprograms: !3) 31 | !1 = !DIFile(filename: "sum.c", directory: "/Users/alexdenisov/Projects/LLVM/Mutang/laboratory") 32 | !2 = !{} 33 | !3 = !{!4, !6} 34 | !4 = distinct !DISubprogram(name: "someUnusedFucntion", scope: !1, file: !1, line: 1, type: !5, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, variables: !2) 35 | !5 = !DISubroutineType(types: !2) 36 | !6 = distinct !DISubprogram(name: "sum", scope: !1, file: !1, line: 5, type: !5, isLocal: false, isDefinition: true, scopeLine: 5, flags: DIFlagPrototyped, isOptimized: false, variables: !2) 37 | !7 = !{i32 2, !"Dwarf Version", i32 2} 38 | !8 = !{i32 2, !"Debug Info Version", i32 3} 39 | !9 = !{i32 1, !"PIC Level", i32 2} 40 | !10 = !{!"clang version 3.9.0 (http://llvm.org/git/clang.git 32fcd42fc53548a16473f398bbb61299b7cd3ffa) (http://llvm.org/git/llvm.git ba0d0e16636b305f26a3b9970eadd409960f7d7a)"} 41 | !11 = !DILocation(line: 2, column: 3, scope: !4) 42 | !12 = !DILocation(line: 6, column: 10, scope: !6) 43 | !13 = !DILocation(line: 6, column: 14, scope: !6) 44 | !14 = !DILocation(line: 6, column: 12, scope: !6) 45 | !15 = !DILocation(line: 6, column: 3, scope: !6) 46 | --------------------------------------------------------------------------------