1 /** 2 Copyright: Copyright (c) 2017-2019 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 /// IR global. Stores info about global variables, string/array/struct literals. 7 module vox.ir.ir_global; 8 9 import vox.all; 10 11 enum IrGlobalFlags : uint { 12 isMutable = 1 << 0, 13 isAllZero = 1 << 1, 14 needsZeroTermination = 1 << 2, 15 /// Global data is copied into static data buffer (or zeroes are reserved for isAllZero) 16 /// If (and only if) set, then staticBufferOffset must be valid 17 isInBuffer = 1 << 3, 18 isString = 1 << 4, 19 } 20 21 /// 22 @(IrValueKind.global) 23 struct IrGlobal 24 { 25 /// Type of global. Must be a pointer type 26 IrIndex type; 27 uint numUsers; 28 LinkIndex objectSymIndex; 29 //bool isMutable() { return (flags & IrGlobalFlags.isMutable) != 0; } 30 //bool isAllZero() { return (flags & IrGlobalFlags.isAllZero) != 0; } 31 //bool needsZeroTermination() { return (flags & IrGlobalFlags.needsZeroTermination) != 0; } 32 //bool isInBuffer() { return (flags & IrGlobalFlags.isInBuffer) != 0; } 33 //bool isString() { return (flags & IrGlobalFlags.isString) != 0; } 34 35 void addUser(IrIndex user) { ++numUsers; } 36 void removeUser(IrIndex user) { --numUsers; } 37 } 38 39 /// 40 struct IrGlobalStorage 41 { 42 Arena!IrGlobal buffer; 43 Arena!ubyte initializerBuffer; 44 45 private IrIndex f32_sign_bit_constant; 46 private IrIndex f64_sign_bit_constant; 47 48 IrIndex get_or_add_f32_sign_bit_constant(CompilationContext* c) { 49 if (f32_sign_bit_constant.isDefined) return f32_sign_bit_constant; 50 51 IrIndex type = makeIrType(IrBasicType.f32); 52 ubyte[16] buf; 53 (cast(uint[])buf[])[] = 0x80000000; 54 55 f32_sign_bit_constant = add_float_sign_bit_constant(type, buf[], c); 56 57 return f32_sign_bit_constant; 58 } 59 60 IrIndex get_or_add_f64_sign_bit_constant(CompilationContext* c) { 61 if (f64_sign_bit_constant.isDefined) return f64_sign_bit_constant; 62 63 IrIndex type = makeIrType(IrBasicType.f64); 64 ubyte[16] buf; 65 (cast(ulong[])buf[])[] = 0x8000000000000000; 66 67 f64_sign_bit_constant = add_float_sign_bit_constant(type, buf[], c); 68 69 return f64_sign_bit_constant; 70 } 71 72 // Creates a bit pattern constant that is used to flip a bit sign of xmm register 73 private IrIndex add_float_sign_bit_constant(IrIndex type, ubyte[] initializer, CompilationContext* c) { 74 IrIndex globalIndex = add(); 75 IrGlobal* global = get(globalIndex); 76 global.type = c.types.appendPtr(type); 77 78 ObjectSymbol sym = { 79 kind : ObjectSymbolKind.isLocal, 80 sectionIndex : c.builtinSections[ObjectSectionType.ro_data], 81 moduleIndex : c.builtinModuleIndex, 82 flags : ObjectSymbolFlags.isFloat, 83 id : c.idMap.getOrReg(c, ":float"), 84 }; 85 global.objectSymIndex = c.objSymTab.addSymbol(sym); 86 87 ObjectSymbol* globalSym = c.objSymTab.getSymbol(global.objectSymIndex); 88 globalSym.alignmentPower = 4; 89 90 SizeAndAlignment valueSizealign = c.types.typeSizeAndAlignment(type); 91 ubyte[] buffer = c.globals.allocateInitializer(16); 92 buffer[] = initializer; 93 globalSym.setInitializer(buffer); 94 95 return globalIndex; 96 } 97 98 /// 99 IrIndex add() 100 { 101 IrIndex globalIndex = IrIndex(cast(uint)buffer.length, IrValueKind.global); 102 buffer.put(IrGlobal()); 103 return globalIndex; 104 } 105 106 /// Allocate space for compiletime generated initializers (struct initializers for example) 107 /// String literals without escape sequences are sliced directly from source code 108 ubyte[] allocateInitializer(uint length) 109 { 110 return initializerBuffer.voidPut(length); 111 } 112 113 /// 114 IrGlobal* get(IrIndex index) 115 { 116 assert(index.kind == IrValueKind.global); 117 assert(index.storageUintIndex < buffer.length); 118 return &buffer.data[index.storageUintIndex]; 119 } 120 }