Goose  Check-in [2a03dd67e5]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:codegen: improved the translation of address computations into llvm GEP instructions
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | cir-stack-language
Files: files | file ages | folders
SHA3-256: 2a03dd67e58879fa73ad80eb1142ae85a28c6e9b8bcb33950b1f7cd82f3def25
User & Date: zlodo 2022-06-28 22:23:50.963
Context
2022-06-28
22:51
Removed an unusued file and a left over debugging profanity check-in: 6c5b747f5c user: zlodo tags: cir-stack-language
22:23
codegen: improved the translation of address computations into llvm GEP instructions check-in: 2a03dd67e5 user: zlodo tags: cir-stack-language
2022-06-27
16:56
  • cir: allow verification specific code and instructions to be interspersed with regular code again and added a function to filter them out before consuming the code in the interpreter and during codegen
  • verification: better handling of non-representable types that don't involve giving up entirely on verifying the function
  • g0 api: updated it to match the CIR changes
  • prelude: adapted reference verification to the new CIR api
check-in: b81d4242e3 user: zlodo tags: cir-stack-language
Changes
Unified Diff Ignore Whitespace Patch
Changes to bs/codegen/address.cpp.
1
2
3
4
5
6














7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include "codegen.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;















bool Module::buildInstruction( State& st, const VarAddr& va )
{
    auto* ppVal = st.temporaries->get( va.varIndex() );

    assert( ppVal );
    if( !ppVal )
        return false;

    st.stack.push( *ppVal );
    return true;
}

bool Module::buildInstruction( State& st, const TempAddr& ta )
{
    auto initVal = st.stack.pop();
    if( !initVal )
        return false;

    auto* ppVal = st.temporaries->get( ta.tempIndex() );

    if( !ppVal )
    {
        st.temporaries->set( ta.tempIndex(), *initVal );
        ppVal = st.temporaries->get( ta.tempIndex() );
    }

    if( llvm::isa< llvm::AllocaInst >( **ppVal ) )
    {
        st.stack.push( *ppVal );
        return true;
    }

    auto* pAlloca = buildAlloca( st, ( *ppVal )->getType() );
    m_llvmBuilder.CreateStore( *ppVal, pAlloca );
    st.temporaries->set( ta.tempIndex(), pAlloca );

    st.stack.push( pAlloca );
    return true;
}

bool Module::buildInstruction( State& st, const Select& s )
{
    llvm::SmallVector< uint32_t, 8 > path;
    path.emplace_back( s.memberIndex() );

    // TODO_STACKBASED: this is a bit shitty since the stack language refactor:
    // if we have a chain of multiple "Select" CIR instrs,
    // we no longer build a single GEP, but rather a chain of
    // GEPs with one index each.
    //
    // Dunno if llvm cares a lot about this.
    // Might want to check if the base addr is already a GEP and
    // append to its index array if so.

    auto baseAddr = st.stack.pop();
    if( !baseAddr )
        return false;

    llvm::SmallVector< llvm::Value*, 2 > idxs;
    idxs.push_back( llvm::ConstantInt::get( llvm::Type::getInt32Ty( GetLLVMContext() ), 0 ) );
    idxs.push_back( llvm::ConstantInt::get( llvm::Type::getInt32Ty( GetLLVMContext() ), s.memberIndex() ) );

    st.stack.push( m_llvmBuilder.CreateGEP( (*baseAddr )->getType()->getScalarType()->getPointerElementType(), *baseAddr, idxs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::GhostCall& gc )
{
    // We should never encounter this during codegen, since it's a construct only
    // intended to be used in verification expressions.






>
>
>
>
>
>
>
>
>
>
>
>
>
>









|





|













|







|





<
<
<
<
<
<
<
<
<
<
<
<




|
<
|
|
|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63












64
65
66
67
68

69
70
71
72
73
74
75
76
77
78
#include "codegen.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;

llvm::Value* codegen::AddressToGEP( llvm::IRBuilder<>& builder, const codegen::Address& addr )
{
    if( addr.path().empty() )
        return addr.originAddr();

    llvm::SmallVector< llvm::Value*, 8 > idxs;
    idxs.push_back( llvm::ConstantInt::get( llvm::Type::getInt32Ty( GetLLVMContext() ), 0 ) );

    for( auto it = addr.path().rbegin(); it != addr.path().rend(); ++it )
        idxs.push_back( llvm::ConstantInt::get( llvm::Type::getInt32Ty( GetLLVMContext() ), *it ) );

    return builder.CreateGEP( addr.originAddr()->getType()->getScalarType()->getPointerElementType(), addr.originAddr(), idxs );
}

bool Module::buildInstruction( State& st, const VarAddr& va )
{
    auto* ppVal = st.temporaries->get( va.varIndex() );

    assert( ppVal );
    if( !ppVal )
        return false;

    st.stack.push( Address( *ppVal ) );
    return true;
}

bool Module::buildInstruction( State& st, const TempAddr& ta )
{
    auto initVal = st.stack.pop( m_llvmBuilder );
    if( !initVal )
        return false;

    auto* ppVal = st.temporaries->get( ta.tempIndex() );

    if( !ppVal )
    {
        st.temporaries->set( ta.tempIndex(), *initVal );
        ppVal = st.temporaries->get( ta.tempIndex() );
    }

    if( llvm::isa< llvm::AllocaInst >( **ppVal ) )
    {
        st.stack.push( Address( *ppVal ) );
        return true;
    }

    auto* pAlloca = buildAlloca( st, ( *ppVal )->getType() );
    m_llvmBuilder.CreateStore( *ppVal, pAlloca );
    st.temporaries->set( ta.tempIndex(), pAlloca );

    st.stack.push( Address( pAlloca ) );
    return true;
}

bool Module::buildInstruction( State& st, const Select& s )
{












    auto baseAddr = st.stack.pop();
    if( !baseAddr )
        return false;

    if( holds_alternative< Address >( *baseAddr ) )

        st.stack.push( Address::Select( move( get< Address >( *baseAddr ) ), s.memberIndex() ) );
    else
        st.stack.push( Address::Select( Address( get< llvm::Value* >( *baseAddr ) ), s.memberIndex() ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::GhostCall& gc )
{
    // We should never encounter this during codegen, since it's a construct only
    // intended to be used in verification expressions.
Added bs/codegen/address.h.




























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#ifndef GOOSE_CODEGEN_ADDRESS_H
#define GOOSE_CODEGEN_ADDRESS_H

namespace goose::codegen
{
    class Address
    {
        public:
            Address( llvm::Value* originAddr ) :
                m_originAddr( originAddr )
            {}

            auto originAddr() const { return m_originAddr; }
            const auto& path() const { return m_path; }

            static Address Select( Address&& baseAddr, uint32_t index )
            {
                baseAddr.m_path.emplace_back( index );
                return baseAddr;
            }

        private:
            SelectPath m_path;
            llvm::Value* m_originAddr = nullptr;
    };

    extern llvm::Value* AddressToGEP( llvm::IRBuilder<>& builder, const codegen::Address& addr );
}

#endif
Changes to bs/codegen/arithops.cpp.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "codegen.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;

bool Module::buildInstruction( State& st, const cir::Add& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateAdd( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Sub& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateSub( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Mul& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateMul( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::UDiv& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateUDiv( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SDiv& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateSDiv( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::URem& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateURem( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SRem& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateSRem( *lhs, *rhs ) );
    return true;
}









|



|









|



|









|



|









|



|









|



|









|



|









|



|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#include "codegen.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;

bool Module::buildInstruction( State& st, const cir::Add& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateAdd( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Sub& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateSub( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Mul& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateMul( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::UDiv& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateUDiv( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SDiv& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateSDiv( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::URem& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateURem( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SRem& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateSRem( *lhs, *rhs ) );
    return true;
}
Changes to bs/codegen/basicblock.cpp.
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
{
    m_llvmBuilder.CreateRetVoid();
    return true;
}

bool Module::buildTerminator( State& st, const cir::Ret& r )
{
    auto retVal = st.stack.pop();
    if( !retVal )
        return false;

    m_llvmBuilder.CreateRet( *retVal );
    return true;
}








|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
{
    m_llvmBuilder.CreateRetVoid();
    return true;
}

bool Module::buildTerminator( State& st, const cir::Ret& r )
{
    auto retVal = st.stack.pop( m_llvmBuilder );
    if( !retVal )
        return false;

    m_llvmBuilder.CreateRet( *retVal );
    return true;
}

91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
        return false;

    return true;
}

bool Module::buildTerminator( State& st, const cir::CondBranch& cb )
{
    auto condVal = st.stack.pop();
    if( !condVal )
        return false;

    auto pTrueLLVMBB = GetOrCreateLLVMBB( st, cb.trueDest().lock() );
    auto pFalseLLVMBB = GetOrCreateLLVMBB( st, cb.falseDest().lock() );
    m_llvmBuilder.CreateCondBr( *condVal, pTrueLLVMBB, pFalseLLVMBB );








|







91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
        return false;

    return true;
}

bool Module::buildTerminator( State& st, const cir::CondBranch& cb )
{
    auto condVal = st.stack.pop( m_llvmBuilder );
    if( !condVal )
        return false;

    auto pTrueLLVMBB = GetOrCreateLLVMBB( st, cb.trueDest().lock() );
    auto pFalseLLVMBB = GetOrCreateLLVMBB( st, cb.falseDest().lock() );
    m_llvmBuilder.CreateCondBr( *condVal, pTrueLLVMBB, pFalseLLVMBB );

Changes to bs/codegen/codegen.h.
23
24
25
26
27
28
29

30
31
32
33
    using namespace cir;
    using namespace sema;

    extern llvm::LLVMContext& GetLLVMContext();
    extern optional< string > Mangle( const Term& identity );
}


#include "stack.h"
#include "module.h"

#endif







>




23
24
25
26
27
28
29
30
31
32
33
34
    using namespace cir;
    using namespace sema;

    extern llvm::LLVMContext& GetLLVMContext();
    extern optional< string > Mangle( const Term& identity );
}

#include "address.h"
#include "stack.h"
#include "module.h"

#endif
Changes to bs/codegen/compareops.cpp.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "codegen.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;

bool Module::buildInstruction( State& st, const cir::Eq& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpEQ( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Neq& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpNE( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::UGT& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpUGT( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::UGE& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpUGE( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::ULT& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpULT( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::ULE& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpULE( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SGT& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpSGT( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SGE& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpSGE( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SLT& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpSLT( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SLE& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpSLE( *lhs, *rhs ) );
    return true;
}









|



|









|



|









|



|









|



|









|



|









|



|









|



|









|



|









|



|









|



|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#include "codegen.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;

bool Module::buildInstruction( State& st, const cir::Eq& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpEQ( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Neq& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpNE( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::UGT& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpUGT( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::UGE& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpUGE( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::ULT& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpULT( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::ULE& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpULE( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SGT& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpSGT( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SGE& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpSGE( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SLT& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpSLT( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::SLE& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateICmpSLE( *lhs, *rhs ) );
    return true;
}
Changes to bs/codegen/instructions.cpp.
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
bool Module::buildInstruction( State& st, const monostate& )
{
    return false;
}

bool Module::buildInstruction( State& st, const cir::Call& call )
{
    auto callee = st.stack.pop< llvm::Function >();
    if( !callee )
        return false;

    llvm::SmallVector< llvm::Value*, 8 > args;
    args.resize( call.numArgs() );

    for( uint32_t i = 0; i < call.numArgs(); ++i )
    {
        auto parg = st.stack.pop();
        if( !parg )
            return false;

        args[call.numArgs() - i - 1] = *parg;
    }

    st.stack.push( m_llvmBuilder.CreateCall( llvm::FunctionCallee( *callee ), args ) );







|








|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
bool Module::buildInstruction( State& st, const monostate& )
{
    return false;
}

bool Module::buildInstruction( State& st, const cir::Call& call )
{
    auto callee = st.stack.pop< llvm::Function* >( m_llvmBuilder );
    if( !callee )
        return false;

    llvm::SmallVector< llvm::Value*, 8 > args;
    args.resize( call.numArgs() );

    for( uint32_t i = 0; i < call.numArgs(); ++i )
    {
        auto parg = st.stack.pop( m_llvmBuilder );
        if( !parg )
            return false;

        args[call.numArgs() - i - 1] = *parg;
    }

    st.stack.push( m_llvmBuilder.CreateCall( llvm::FunctionCallee( *callee ), args ) );
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

    st.stack.push( val );
    return true;
}

bool Module::buildInstruction( State& st, const cir::CreateTemporary& ct )
{
    auto initVal = st.stack.pop();
    if( !initVal )
        return false;

    createTemporary( st, ct.index(), *initVal );
    return true;
}








|







59
60
61
62
63
64
65
66
67
68
69
70
71
72
73

    st.stack.push( val );
    return true;
}

bool Module::buildInstruction( State& st, const cir::CreateTemporary& ct )
{
    auto initVal = st.stack.pop( m_llvmBuilder );
    if( !initVal )
        return false;

    createTemporary( st, ct.index(), *initVal );
    return true;
}

112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    createTemporary( st, av.index(), pAlloca );

    return true;
}

bool Module::buildInstruction( State& st, const cir::Load& load )
{
    auto ptrVal = st.stack.pop();
    if( !ptrVal )
        return false;

    auto type = LowerTypeForRuntime( st.context, *EIRToValue( load.type() ) );
    if( !type )
        return false;

    auto* llvmType = GetLLVMType( *type );
    assert( llvmType );

    st.stack.push( m_llvmBuilder.CreateLoad( llvmType, *ptrVal ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Store& store )
{
    auto val = st.stack.pop();
    if( !val )
        return false;

    auto ptrVal = st.stack.pop();
    if( !ptrVal )
        return false;

    if( llvm::isa< llvm::ConstantAggregate >( *val ) )
    {
        stringstream name;
        name << ".constaggr" << hex << m_nextAggregateID++;







|
















|



|







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
    createTemporary( st, av.index(), pAlloca );

    return true;
}

bool Module::buildInstruction( State& st, const cir::Load& load )
{
    auto ptrVal = st.stack.pop( m_llvmBuilder );
    if( !ptrVal )
        return false;

    auto type = LowerTypeForRuntime( st.context, *EIRToValue( load.type() ) );
    if( !type )
        return false;

    auto* llvmType = GetLLVMType( *type );
    assert( llvmType );

    st.stack.push( m_llvmBuilder.CreateLoad( llvmType, *ptrVal ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Store& store )
{
    auto val = st.stack.pop( m_llvmBuilder );
    if( !val )
        return false;

    auto ptrVal = st.stack.pop( m_llvmBuilder );
    if( !ptrVal )
        return false;

    if( llvm::isa< llvm::ConstantAggregate >( *val ) )
    {
        stringstream name;
        name << ".constaggr" << hex << m_nextAggregateID++;
Changes to bs/codegen/logicops.cpp.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "codegen.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;

bool Module::buildInstruction( State& st, const cir::Not& uo )
{
    auto operand = st.stack.pop();
    if( !operand )
        return false;

    st.stack.push( m_llvmBuilder.CreateXor( *operand, llvm::ConstantInt::getTrue( GetLLVMContext() ) ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::And& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateAnd( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Or& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateOr( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Xor& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateXor( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Shl& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateShl( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::LShr& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateLShr( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::AShr& bo )
{
    auto rhs = st.stack.pop();
    if( !rhs )
        return false;

    auto lhs = st.stack.pop();
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateAShr( *lhs, *rhs ) );
    return true;
}









|









|



|









|



|









|



|









|



|









|



|









|



|






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include "codegen.h"
#include "builtins/builtins.h"

using namespace goose;
using namespace goose::codegen;
using namespace goose::builtins;

bool Module::buildInstruction( State& st, const cir::Not& uo )
{
    auto operand = st.stack.pop( m_llvmBuilder );
    if( !operand )
        return false;

    st.stack.push( m_llvmBuilder.CreateXor( *operand, llvm::ConstantInt::getTrue( GetLLVMContext() ) ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::And& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateAnd( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Or& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateOr( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Xor& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateXor( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::Shl& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateShl( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::LShr& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateLShr( *lhs, *rhs ) );
    return true;
}

bool Module::buildInstruction( State& st, const cir::AShr& bo )
{
    auto rhs = st.stack.pop( m_llvmBuilder );
    if( !rhs )
        return false;

    auto lhs = st.stack.pop( m_llvmBuilder );
    if( !lhs )
        return false;

    st.stack.push( m_llvmBuilder.CreateAShr( *lhs, *rhs ) );
    return true;
}
Changes to bs/codegen/stack.h.
1
2
3
4
5
6
7
8


9
10



























11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#ifndef GOOSE_CODEGEN_STACK_H
#define GOOSE_CODEGEN_STACK_H

namespace goose::codegen
{
    class Stack
    {
        public:


            template< typename T = llvm::Value >
            optional< T* > pop()



























            {
                if( m_stack.empty() )
                    return nullopt;

                auto result = m_stack.top();
                m_stack.pop();

                if constexpr( is_same_v< T, llvm::Value > )
                {
                    return result;
                }
                else
                {
                    return llvm::dyn_cast_or_null< T >( result );
                }
            }

            template< typename T >
            void push( T&& v )
            {
                m_stack.push( forward< T >( v ) );
            }

        private:
            stack< llvm::Value* > m_stack;
    };
}

#endif








>
>
|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>






<
<
<
|
<
<
<
<
<









|




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45



46





47
48
49
50
51
52
53
54
55
56
57
58
59
60
#ifndef GOOSE_CODEGEN_STACK_H
#define GOOSE_CODEGEN_STACK_H

namespace goose::codegen
{
    class Stack
    {
        public:
            using Slot = variant< llvm::Value*, codegen::Address >;

            template< typename T = llvm::Value* >
            optional< T > pop( llvm::IRBuilder<>& builder )
            {
                if( m_stack.empty() )
                    return nullopt;

                auto result = m_stack.top();
                m_stack.pop();

                if constexpr( is_same_v< T, codegen::Address > )
                {
                    if( !holds_alternative< codegen::Address >( result ) )
                        return nullopt;
                    return get< codegen::Address >( result );
                }
                else if constexpr( is_same_v< T, llvm::Value* > )
                {
                    if( holds_alternative< codegen::Address >( result ) )
                        return AddressToGEP( builder, get< codegen::Address >( result ) );
                    else
                        return get< llvm::Value* >( result );
                }
                else if( holds_alternative< llvm::Value* >( result ) )
                    return llvm::dyn_cast_or_null< remove_pointer_t< T > >( get< llvm::Value* >( result ) );

                return nullopt;
            }

            optional< Slot > pop()
            {
                if( m_stack.empty() )
                    return nullopt;

                auto result = m_stack.top();
                m_stack.pop();



                return result;





            }

            template< typename T >
            void push( T&& v )
            {
                m_stack.push( forward< T >( v ) );
            }

        private:
            stack< Slot > m_stack;
    };
}

#endif
Changes to bs/codegen/value.cpp.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

    if( val.isConstant() )
        return buildConstant( st, val );

    if( !buildInstruction( st, *val.cir() ) )
        return nullptr;

    auto result = st.stack.pop();
    if( !result )
        return nullptr;

    return *result;
}

llvm::Constant* Module::buildConstant( State& st, const Value& v )







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

    if( val.isConstant() )
        return buildConstant( st, val );

    if( !buildInstruction( st, *val.cir() ) )
        return nullptr;

    auto result = st.stack.pop( m_llvmBuilder );
    if( !result )
        return nullptr;

    return *result;
}

llvm::Constant* Module::buildConstant( State& st, const Value& v )